using UnityEngine;
using UnityEngine.Rendering;
using System;
using System.Collections.Generic;
using UnityEngine.UIElements;
using System.IO;
using UnityEditor;
using UnityEditor.UIElements;
namespace UnityEditor.Rendering.LookDev
{
///
/// Class containing a collection of Environment
///
[HelpURL(Documentation.baseURLHDRP + Documentation.version + Documentation.subURL + "Environment-Library" + Documentation.endURL)]
public class EnvironmentLibrary : ScriptableObject
{
[field: SerializeField]
List environments { get; set; } = new List();
///
/// Number of elements in the collection
///
public int Count => environments.Count;
///
/// Indexer giving access to contained Environment
///
public Environment this[int index] => environments[index];
///
/// Create a new empty Environment at the end of the collection
///
/// The created Environment
public Environment Add()
{
Undo.SetCurrentGroupName("Add Environment");
int group = Undo.GetCurrentGroup();
Environment environment = ScriptableObject.CreateInstance();
environment.name = "New Environment";
Undo.RegisterCreatedObjectUndo(environment, "Add Environment");
Undo.RecordObject(this, "Add Environment");
environments.Add(environment);
// Store this new environment as a subasset so we can reference it safely afterwards.
AssetDatabase.AddObjectToAsset(environment, this);
Undo.CollapseUndoOperations(group);
// Force save / refresh. Important to do this last because SaveAssets can cause effect to become null!
EditorUtility.SetDirty(this);
AssetDatabase.SaveAssets();
return environment;
}
///
/// Remove Environment of the collection at given index
///
/// Index where to remove Environment
public void Remove(int index)
{
Undo.SetCurrentGroupName("Remove Environment");
int group = Undo.GetCurrentGroup();
Environment environment = environments[index];
Undo.RecordObject(this, "Remove Environment");
environments.RemoveAt(index);
Undo.DestroyObjectImmediate(environment);
Undo.CollapseUndoOperations(group);
// Force save / refresh
EditorUtility.SetDirty(this);
AssetDatabase.SaveAssets();
}
///
/// Duplicate the Environment at given index and add it at the end of the Collection
///
/// Index where to take data for duplication
/// The created Environment
public Environment Duplicate(int fromIndex)
{
Undo.SetCurrentGroupName("Duplicate Environment");
int group = Undo.GetCurrentGroup();
Environment environment = ScriptableObject.CreateInstance();
Environment environmentToCopy = environments[fromIndex];
environmentToCopy.CopyTo(environment);
Undo.RegisterCreatedObjectUndo(environment, "Duplicate Environment");
Undo.RecordObject(this, "Duplicate Environment");
environments.Add(environment);
// Store this new environment as a subasset so we can reference it safely afterwards.
AssetDatabase.AddObjectToAsset(environment, this);
Undo.CollapseUndoOperations(group);
// Force save / refresh. Important to do this last because SaveAssets can cause effect to become null!
EditorUtility.SetDirty(this);
AssetDatabase.SaveAssets();
return environment;
}
///
/// Compute position of given Environment in the collection
///
/// Environment to look at
/// Index of the searched environment. If not found, -1.
public int IndexOf(Environment environment)
=> environments.IndexOf(environment);
}
[CustomEditor(typeof(EnvironmentLibrary))]
class EnvironmentLibraryEditor : Editor
{
VisualElement m_Root;
VisualElement m_OpenButton;
public sealed override VisualElement CreateInspectorGUI()
{
var library = target as EnvironmentLibrary;
m_Root = new VisualElement();
m_OpenButton = new Button(() =>
{
if (!LookDev.open)
LookDev.Open();
LookDev.currentContext.UpdateEnvironmentLibrary(library);
LookDev.currentEnvironmentDisplayer.Repaint();
})
{
text = "Open in Look Dev window"
};
m_OpenButton.SetEnabled(LookDev.supported);
m_Root.Add(m_OpenButton);
return m_Root;
}
void OnEnable() => EditorApplication.update += Update;
void OnDisable() => EditorApplication.update -= Update;
void Update()
{
// Current SRP can be changed at any time so we need to do this at every update.
if (m_OpenButton != null)
m_OpenButton.SetEnabled(LookDev.supported);
}
// Don't use ImGUI
public sealed override void OnInspectorGUI() { }
}
class EnvironmentLibraryCreator : ProjectWindowCallback.EndNameEditAction
{
ObjectField m_Field = null;
public void SetField(ObjectField field)
=> m_Field = field;
public override void Cancelled(int instanceId, string pathName, string resourceFile)
=> m_Field = null;
public override void Action(int instanceId, string pathName, string resourceFile)
{
var newAsset = CreateInstance();
newAsset.name = Path.GetFileName(pathName);
AssetDatabase.CreateAsset(newAsset, pathName);
ProjectWindowUtil.ShowCreatedAsset(newAsset);
if (m_Field != null)
m_Field.value = newAsset;
m_Field = null;
}
[MenuItem("Assets/Create/LookDev/Environment Library", priority = 2000)]
static void Create()
{
var icon = EditorGUIUtility.FindTexture("ScriptableObject Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New EnvironmentLibrary.asset", icon, null);
}
public static void CreateAndAssignTo(ObjectField field)
{
var icon = EditorGUIUtility.FindTexture("ScriptableObject Icon");
var assetCreator = ScriptableObject.CreateInstance();
assetCreator.SetField(field);
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(assetCreator.GetInstanceID(), assetCreator, "New EnvironmentLibrary.asset", icon, null);
}
}
static class EnvironmentLibraryLoader
{
static Action LoadCallback(Action onUpdate)
{
return (UnityEngine.Object newLibrary) =>
{
LookDev.currentContext.UpdateEnvironmentLibrary(newLibrary as EnvironmentLibrary);
onUpdate?.Invoke();
};
}
}
}