Skip to content

Instantly share code, notes, and snippets.

@bengsfort
Created September 26, 2018 08:31
Show Gist options
  • Save bengsfort/f0245fea906c3ec5dc33e93505cf55ac to your computer and use it in GitHub Desktop.
Save bengsfort/f0245fea906c3ec5dc33e93505cf55ac to your computer and use it in GitHub Desktop.
using System;
using UnityEditor;
using UnityEngine;
namespace Pixeland.Tools.Router.Editor
{
public abstract class EditorBase : UnityEditor.Editor
{
protected void ChangeCheck<T>(T val, Action<T> onChanged) where T : class
{
EditorGUI.BeginChangeCheck();
T newVal;
if (val is string)
newVal = EditorGUILayout.TextField(val as string) as T;
else if (val is SceneAsset)
newVal = EditorGUILayout.ObjectField(val as SceneAsset, typeof(SceneAsset), false) as T;
else
throw new Exception("Unsupported ChangeCheck type: " + val.GetType().Name);
if (EditorGUI.EndChangeCheck())
{
onChanged(newVal);
}
}
protected void Vertical(GUIStyle style, Action<Rect> addContent)
{
Rect layout = style != null ? EditorGUILayout.BeginVertical(style) : EditorGUILayout.BeginVertical();
addContent(layout);
EditorGUILayout.EndVertical();
}
protected void Vertical(Action<Rect> addContent)
{
Vertical(null, addContent);
}
protected void Horizontal(Action<Rect> addContent)
{
Rect layout = EditorGUILayout.BeginHorizontal();
addContent(layout);
EditorGUILayout.EndHorizontal();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace Pixeland.Tools.Router.Editor
{
[CustomEditor(typeof(GameRouter))]
public class GameRouterEditor : EditorBase
{
private GameRouter m_Router;
private void OnEnable()
{
m_Router = target as GameRouter;
}
private void DrawRouteItem(int index)
{
RouteDefinition route = m_Router.routes[index];
// Find all routes that have a parent id of this route's id
List<RouteDefinition> children = m_Router.routes
.Where(r => r.parentId == route.id)
.ToList();
Horizontal(_ =>
{
EditorGUILayout.PrefixLabel("Route:",
EditorStyles.label,
EditorStyles.miniBoldLabel);
if (GUILayout.Button("Delete", EditorStyles.miniButton))
{
Undo.RecordObject(m_Router, "Delete subroute");
ArrayUtility.RemoveAt(ref m_Router.routes, index);
// Clear out all the children
for (int i = m_Router.routes.Length - 1; i >= 0; i--)
if (m_Router.routes[i].parentId == route.id)
ArrayUtility.RemoveAt(ref m_Router.routes, i);
EditorUtility.SetDirty(m_Router);
}
});
// Get current scene and update it in the inspector...
var currentScene = AssetDatabase.LoadAssetAtPath<SceneAsset>(route.scenePath);
serializedObject.Update();
// Start drawing our list item
Horizontal(_ =>
{
// Name field
ChangeCheck(route.name, newName =>
{
Undo.RecordObject(m_Router, "Update route name");
m_Router.routes[index].name = newName;
EditorUtility.SetDirty(m_Router);
});
// Scene field
if (!children.Any())
{
ChangeCheck(currentScene, newScene =>
{
Undo.RecordObject(m_Router, "Update route scene");
string newPath = AssetDatabase.GetAssetPath(newScene);
m_Router.routes[index].scenePath = newPath;
EditorUtility.SetDirty(m_Router);
});
}
serializedObject.ApplyModifiedProperties();
});
// Child routes...
if (children.Any())
{
Vertical(new GUIStyle { padding = new RectOffset(16, 0, 16, 0) }, rect =>
{
foreach (RouteDefinition subroute in children)
{
Horizontal(_ =>
{
EditorGUILayout.PrefixLabel("Subroute:", EditorStyles.label, EditorStyles.miniBoldLabel);
if (GUILayout.Button("Delete", EditorStyles.miniButton))
{
Undo.RecordObject(m_Router, "Delete subroute");
ArrayUtility.RemoveAt(ref m_Router.routes, m_Router.routes.ToList().IndexOf(subroute));
EditorUtility.SetDirty(m_Router);
}
});
// Get current scene and update it in the inspector...
var currentChildScene = AssetDatabase.LoadAssetAtPath<SceneAsset>(subroute.scenePath);
serializedObject.Update();
// Start drawing our list item
Horizontal(_ =>
{
// Name field
ChangeCheck(subroute.name, subNewName =>
{
Undo.RecordObject(m_Router, "Update subroute name");
subroute.name = subNewName;
EditorUtility.SetDirty(m_Router);
});
// Scene field
ChangeCheck(currentChildScene, newSubScene =>
{
Undo.RecordObject(m_Router, "Update route scene");
string newPath = AssetDatabase.GetAssetPath(newSubScene);
subroute.scenePath = newPath;
EditorUtility.SetDirty(m_Router);
});
serializedObject.ApplyModifiedProperties();
});
EditorGUILayout.Space();
}
});
}
Horizontal(_r =>
{
if (GUILayout.Button("+ subroute", EditorStyles.miniButton))
{
Undo.RecordObject(m_Router, "Add subroute");
ArrayUtility.Add(ref m_Router.routes, new RouteDefinition
{
id = m_Router.routes.Max(r => r.id) + 1,
name = "subroute",
parentId = route.id
});
EditorUtility.SetDirty(m_Router);
}
});
}
public override void OnInspectorGUI()
{
serializedObject.Update();
Vertical(_ =>
{
for (var i = 0; i < m_Router.routes.Length; i++)
{
// If this is a subroute, don't render it (yet)
if (m_Router.routes[i].parentId >= 0)
continue;
DrawRouteItem(i);
// Draw separator
Vertical(sep =>
{
EditorGUI.DrawRect(new Rect(sep.x, sep.y += EditorGUIUtility.standardVerticalSpacing, sep.width, 1.0f), Color.grey);
EditorGUILayout.Space();
});
}
});
Horizontal(_ =>
{
if (GUILayout.Button("+ route", EditorStyles.miniButton))
{
Undo.RecordObject(m_Router, "Add route");
ArrayUtility.Add(ref m_Router.routes, new RouteDefinition
{
id = m_Router.routes.Any() ? m_Router.routes.Max(r => r.id) + 1 : 0,
name = "my-route"
});
EditorUtility.SetDirty(m_Router);
}
});
serializedObject.ApplyModifiedProperties();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment