Skip to content

Instantly share code, notes, and snippets.

@tvhees
Created February 18, 2018 01:35
Show Gist options
  • Save tvhees/b7819263df2e1eb564a16b3ece10aca1 to your computer and use it in GitHub Desktop.
Save tvhees/b7819263df2e1eb564a16b3ece10aca1 to your computer and use it in GitHub Desktop.
Helper class for creating new ColorPresetLibrary assets in the Unity Editor
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.Reflection;
public static class ColorPresetLibraryCreator {
/*
Unity creates new preset librarys internally through typed singleton instances of the PresetLibraryManager class.
The two key methods we need to access through reflection are:
public T CreateLibrary<T>(ScriptableObjectSaveLoadHelper<T> helper, string presetLibraryPathWithoutExtension) where T : ScriptableObject
public void SaveLibrary<T>(ScriptableObjectSaveLoadHelper<T> helper, T library, string presetLibraryPathWithoutExtension) where T : ScriptableObject
CreateLibrary does some file path checking before creating the library through the helper object
and registering it with the library cache. SaveLibrary does what it says through the helper object.
In between the two calls is when we can actually add presets to the library.
We could use the helper object directly to save the library but it's probably safer to let the Manager class do it.
*/
private const string assemblyDef = "UnityEditor.{0},UnityEditor";
public static void CreateNewLibraryThroughPresetLibraryManager(string name, List<Color> colors)
{
// The ScriptableSingleton class is public, but because PresetLibraryManager isn't
// we still need to make a generic type and then use reflection to get the static instance property.
// This is assuming that we need the singleton instance for library registration purposes -
// it might not be necessary.
Type managerType = Type.GetType(string.Format(assemblyDef, "PresetLibraryManager"));
Type singletonType = typeof(ScriptableSingleton<>).MakeGenericType(managerType);
PropertyInfo instancePropertyInfo = singletonType.GetProperty("instance", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
var managerInstance = instancePropertyInfo.GetValue(null, null);
// We create an instance of the save/load helper and then pass it and the path to the CreateLibrary method.
// "colors" is the file extension we want for the library asset without the '.'
Type libraryType = Type.GetType(string.Format(assemblyDef, "ColorPresetLibrary"));
Type helperType = Type.GetType(string.Format(assemblyDef, "ScriptableObjectSaveLoadHelper`1"))
.MakeGenericType(libraryType);
MethodInfo createMethod = managerType.GetMethod("CreateLibrary", BindingFlags.Instance | BindingFlags.Public)
.MakeGenericMethod(libraryType);
var helper = Activator.CreateInstance(helperType, new object[] { "colors", SaveType.Text });
var library = createMethod.Invoke(managerInstance, new object[] {helper, Path.Combine("Assets/Editor", name) });
// We can't cast library to the desired type so we get the Add method through reflection
// and add the desired colours as presets through that.
// After that the library can be saved!
if ((UnityEngine.Object) library != (UnityEngine.Object) null)
{
MethodInfo addPresetMethod = libraryType.GetMethod("Add");
foreach(var color in colors)
{
addPresetMethod.Invoke(library, new object[] {color, color.ToString()});
}
MethodInfo saveMethod = managerType.GetMethod("SaveLibrary", BindingFlags.Instance | BindingFlags.Public)
.MakeGenericMethod(libraryType);
saveMethod.Invoke(managerInstance, new object[] { helper, library, Path.Combine("Assets/Editor", name) });
}
// The library could be returned as an Object or ScriptableObject reference if that was useful
// I don't know of a way to cast it to the actual ColorPresetLibrary type.
}
// Extension function because why not
public static void CreateNewPresetLibrary(this List<Color> colors, string name) {
CreateNewLibraryThroughPresetLibraryManager(name, colors);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment