Skip to content

Instantly share code, notes, and snippets.

@CoffeeVampir3
Last active July 31, 2020 22:52
Show Gist options
  • Save CoffeeVampir3/bf49c9c519b09788d252f693d39f2f11 to your computer and use it in GitHub Desktop.
Save CoffeeVampir3/bf49c9c519b09788d252f693d39f2f11 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using UnityEngine;
namespace BW {
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
public class ExpandSO : PropertyAttribute {
public Type cachedType;
public ExpandSO(Type cachedType) {
this.cachedType = cachedType;
}
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
namespace BW {
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
public class TypeCachedAttribute : PropertyAttribute {
public Type typeCachedType;
public TypeCachedAttribute(Type cachedType) {
typeCachedType = cachedType;
}
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Reflection;
namespace BW {
[CustomPropertyDrawer(typeof(ExpandSO)), CanEditMultipleObjects]
public class ExpandSOPropDrawer : PropertyDrawer {
static Dictionary<int, Type> referenceTypes = new Dictionary<int, Type>();
private static string saveFolderName = "ScriptableEffects";
void BindTypeFromProperty(SerializedProperty property) {
System.Type parentType = EditorHelpers.GetSerialziedParentType(property);
int hashCode = EditorHelpers.GetSerializedParentHash(property);
if (referenceTypes.ContainsKey(hashCode))
{
return;
}
var attribs = fieldInfo.GetCustomAttributes(typeof(ExpandSO), true);
if(attribs.Length != 1)
{
Debug.Log("Not designed to support this many/few ExpandSO requests yet.");
}
foreach(ExpandSO att in attribs)
{
referenceTypes.Add(hashCode, att.cachedType);
}
}
bool folded = false;
bool renameFolded = false;
string name = "";
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.PropertyField(position, property, label);
if (property.objectReferenceValue != null)
{
if(!folded)
{
renameFolded = EditorGUILayout.Foldout(renameFolded, "Rename: ");
if(renameFolded)
{
name = GUILayout.TextField(name);
if (GUILayout.Button("Rename"))
{
EditorHelpers.RenameAssetForPropertyParent(property, name);
}
}
}
folded = EditorGUILayout.Foldout(folded, "Expand Contents: ");
if (folded)
{
Editor myEditor = Editor.CreateEditor(property.objectReferenceValue);
myEditor.RequiresConstantRepaint();
myEditor.DrawDefaultInspector();
myEditor.OnInspectorGUI();
myEditor.serializedObject.ApplyModifiedProperties();
}
} else
{
if(GUILayout.Button("Create New"))
{
BindTypeFromProperty(property);
var stat = ScriptableObject.CreateInstance(
referenceTypes[EditorHelpers.GetSerializedParentHash(property)]);
EditorHelpers.CreateAssetForPropertyParent(property, stat, saveFolderName);
property.objectReferenceValue = stat;
}
}
}
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace BW {
static class EditorHelpers {
private static string _assetSavePath = "Assets/DataAssets/";
private static string _assetExtension = ".asset";
public static int GetSerializedParentHash(SerializedProperty property) {
return property.serializedObject.targetObject.GetHashCode();
}
public static Type GetSerialziedParentType(SerializedProperty property) {
return property.serializedObject.targetObject.GetType();
}
public static string GenerateAssetName(string prefix, ScriptableObject asset) {
string[] typeNamePartial = asset.GetType().ToString().Split('.');
string typeName = typeNamePartial[typeNamePartial.Length - 1];
return prefix + "." + typeName + asset.GetInstanceID();
}
public static string GetBaseParentName(string propertyName) {
string[] typeNamePartial = propertyName.ToString().Split('.');
string typeName = typeNamePartial[0];
return typeName;
}
public static void CreateAssetForPropertyParent(SerializedProperty property, ScriptableObject asset, string folderName) {
var parent = property.serializedObject.targetObject;
string propertyTargetName = GetBaseParentName(parent.name);
string savePath = _assetSavePath + folderName + "/" + propertyTargetName + _assetExtension;
string finalPath = AssetDatabase.GenerateUniqueAssetPath(savePath);
AssetDatabase.CreateAsset(asset, finalPath);
AssetDatabase.SaveAssets();
}
public static void RenameAssetForPropertyParent(SerializedProperty property, string newName) {
AssetDatabase.RenameAsset(AssetDatabase.GetAssetPath(property.objectReferenceValue), newName);
AssetDatabase.SaveAssets();
}
public static void WriteAssetToPropertyParent(SerializedProperty property, ScriptableObject asset, string folderName) {
var parent = property.serializedObject.targetObject;
string propertyTargetName = GetBaseParentName(parent.name);
string savePath = _assetSavePath + folderName + "/" + propertyTargetName + _assetExtension;
ScriptableObject containerObj = AssetDatabase.LoadAssetAtPath<ScriptableObject>(savePath);
if (containerObj == null)
{
Debug.LogError("Attempted to write asset without creating an asset for property.");
return;
}
asset.name = GenerateAssetName(propertyTargetName, asset);
AssetDatabase.AddObjectToAsset(asset, containerObj);
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(asset));
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
}
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.Linq;
using System.Reflection;
namespace BW {
[CustomPropertyDrawer(typeof(TypeCachedAttribute)), CanEditMultipleObjects]
public class TypeCachedPropDrawer : PropertyDrawer {
private static Dictionary<int, List<Type>> cachedTypes = new Dictionary<int, List<Type>>();
private static Dictionary<int, Type> referenceTypes = new Dictionary<int, Type>();
private static string saveFolderName = "ScriptableEffects";
private void BindTypeFromProperty(SerializedProperty property) {
int hashCode = EditorHelpers.GetSerializedParentHash(property);
if (cachedTypes.ContainsKey(hashCode))
{
return;
}
var attribs = fieldInfo.GetCustomAttributes(typeof(TypeCachedAttribute), true);
if (attribs.Length != 1)
{
Debug.Log("Too many typed cached attributes on this field.");
}
foreach (TypeCachedAttribute att in attribs)
{
List<Type> derivedList = TypeCache.GetTypesDerivedFrom(att.typeCachedType).ToList();
cachedTypes.Add(hashCode, derivedList);
referenceTypes.Add(hashCode, att.typeCachedType);
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();
BindTypeFromProperty(property);
if (!cachedTypes.TryGetValue(EditorHelpers.GetSerializedParentHash(property), out var typeList))
{
Debug.LogError("Failed to find type list for type " + EditorHelpers.GetSerialziedParentType(property));
return;
}
var displayedOptions = typeList.Select(t => t.Name).ToArray();
var popup = EditorGUILayout.Popup("Search for Item: ", -1, displayedOptions, GUILayout.ExpandWidth(true));
if (EditorGUI.EndChangeCheck())
{
var stat = ScriptableObject.CreateInstance(typeList[popup]);
Debug.Log(stat);
EditorHelpers.WriteAssetToPropertyParent(property, stat, saveFolderName);
Undo.RecordObject(property.serializedObject.targetObject, "Changed command");
property.objectReferenceValue = stat;
}
property.objectReferenceValue = EditorGUI.ObjectField(position, property.objectReferenceValue,
referenceTypes[EditorHelpers.GetSerializedParentHash(property)], false);
if (property.objectReferenceValue != null)
{
Editor myEditor = Editor.CreateEditor(property.objectReferenceValue);
myEditor.OnInspectorGUI();
myEditor.serializedObject.ApplyModifiedProperties();
}
property.serializedObject.ApplyModifiedProperties();
EditorGUI.EndProperty();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment