Skip to content

Instantly share code, notes, and snippets.

@alankent
Created July 16, 2021 18:00
Show Gist options
  • Save alankent/cb04c52ba1a5c8f6726b283641dcbbb0 to your computer and use it in GitHub Desktop.
Save alankent/cb04c52ba1a5c8f6726b283641dcbbb0 to your computer and use it in GitHub Desktop.
using UnityEngine;
using UnityEditor;
using UnityEngine.Timeline;
using UnityEngine.Playables;
using System.Collections.Generic;
public class MyAssemblyWindow : EditorWindow
{
[MenuItem("Window/Alan Tools/Assembly")]
public static void ShowWindow()
{
// Find or create window so it appears on the screen.
EditorWindow.GetWindow<MyAssemblyWindow>("Assembly");
}
void OnGUI()
{
AddCategory("Characters");
AddCategory("Props");
AddCategory("Lighting");
}
private void AddCategory(string name)
{
var assets = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/_PROJECT/Assembly Prefabs/" + name });
if (assets.Length == 0)
{
return;
}
var buttonStyle = EditorStyles.miniButton;
GUILayout.Label(name, EditorStyles.boldLabel);
var inHoriz = false;
int i = 0;
foreach (var guid in assets)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
// Get a clean name for the button (removing "Prefab Variant" style endings).
var prefabName = path.Substring(path.LastIndexOf('/') + 1);
prefabName = prefabName.Remove(prefabName.LastIndexOf('.'));
if (prefabName.EndsWith(" Variant"))
{
prefabName = prefabName.Remove(prefabName.LastIndexOf(' '));
}
if (prefabName.EndsWith(" Prefab"))
{
prefabName = prefabName.Remove(prefabName.LastIndexOf(' '));
}
// Putting 4 per line because cannot work out how to flow them nicely to pack as many as will fit per line.
// TODO: try https://docs.unity3d.com/ScriptReference/EditorGUIUtility.GetFlowLayoutedRects.html
if (!inHoriz)
{
GUILayout.BeginHorizontal("box");
inHoriz = true;
}
if (GUILayout.Button(prefabName, buttonStyle))
{
AddPrefabInstance(prefabName, path);
}
if ((i % 4) == 3)
{
GUILayout.EndHorizontal();
inHoriz = false;
}
i++;
}
if (inHoriz)
{
GUILayout.EndHorizontal();
}
}
/*
* Add prefab instance
*/
private void AddPrefabInstance(string name, string path)
{
foreach (GameObject obj in Selection.gameObjects)
{
PlayableDirector director = obj.GetComponent<PlayableDirector>();
if (director != null)
{
var child = obj.transform.Find(name);
if (child == null)
{
// Does not already exist, lets try and add it.
var prefab = (GameObject)AssetDatabase.LoadAssetAtPath(path, typeof(GameObject));
if (prefab == null)
{
Debug.LogError("Could not load '" + name + "' at path '" + path + "'.");
}
else
{
// Add prefab game object as child.
var inst = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
Undo.RecordObject(inst.transform, "Add " + name + " to sequence");
inst.transform.parent = obj.transform;
// If we find the Timeline, add an animation track to the timeline as well.
TimelineAsset timeline = (TimelineAsset) director.playableAsset;
if (timeline != null)
{
AnimationTrack track = timeline.CreateTrack<AnimationTrack>(null, name);
director.SetGenericBinding(track, inst);
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment