Files
YachtDice/Assets/Plugins/AllIn13DShader/Editor/Windows/OverrideMaterialsTabDrawer.cs
T
2026-02-23 22:01:07 +07:00

489 lines
13 KiB
C#

using System.Collections.Generic;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
namespace AllIn13DShader
{
public class OverrideMaterialsTabDrawer : AssetWindowTabDrawer
{
private const string TAB_NAME = "Override Materials";
private enum State
{
NONE = 0,
PREVIEW = 1,
}
private PropertySelectorAuxWindow propertySelectorWindow;
private State state;
private static MaterialOverrideData overrideData;
private SerializedObject dataSO;
private SerializedProperty spFolders;
private GUIStyle propertiesStyle;
public OverrideMaterialsTabDrawer(CommonStyles commonStyles, AllIn13DShaderWindow parentWindow) : base(commonStyles, parentWindow)
{
Initialize();
}
private void Initialize()
{
overrideData = ScriptableObject.CreateInstance<MaterialOverrideData>();
overrideData.Initialize();
state = State.NONE;
dataSO = new SerializedObject(overrideData);
spFolders = dataSO.FindProperty("folders");
}
private void SubscribeEvents()
{
EditorApplication.wantsToQuit += OnWantsToQuit;
EditorSceneManager.sceneClosing += OnSceneClosing;
EditorSceneManager.sceneSaving += OnSceneSaving;
EditorSceneManager.sceneSaved += OnSceneSaved;
EditorSceneManager.sceneDirtied += OnSceneDirtied;
EditorApplication.hierarchyChanged += OnHierarchyChanged;
AssemblyReloadEvents.beforeAssemblyReload += BeforeAssemblyReload;
}
private void UnsubscribeEvents()
{
EditorApplication.wantsToQuit -= OnWantsToQuit;
EditorSceneManager.sceneClosing -= OnSceneClosing;
EditorSceneManager.sceneSaving -= OnSceneSaving;
EditorSceneManager.sceneSaved -= OnSceneSaved;
EditorSceneManager.sceneDirtied -= OnSceneDirtied;
EditorApplication.hierarchyChanged -= OnHierarchyChanged;
AssemblyReloadEvents.beforeAssemblyReload -= BeforeAssemblyReload;
}
public override void OnEnable()
{
SubscribeEvents();
}
public override void OnDisable()
{
UnsubscribeEvents();
}
public override void Show()
{
Initialize();
SubscribeEvents();
}
public override void Hide()
{
UnsubscribeEvents();
Close();
}
//public void Setup(CommonStyles commonStyles, AllIn13DShaderWindow parentWindow)
//{
// this.commonStyles = commonStyles;
// this.parentWindow = parentWindow;
//}
public override void EnteredPlayMode()
{
}
public override void ExitingEditMode()
{
EndOverrideProcess(false);
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
AssetDatabase.SaveAssets();
UnsubscribeEvents();
}
public override void Draw()
{
if(propertiesStyle == null)
{
propertiesStyle = new GUIStyle(EditorStyles.helpBox);
propertiesStyle.margin = new RectOffset(0, 0, 0, 0);
}
dataSO.Update();
GUILayout.Space(10f);
if (state == State.NONE)
{
DrawStateNone();
}
else
{
DrawStatePreview();
}
dataSO.ApplyModifiedProperties();
}
private void StartOverrideProcess()
{
overrideData.ResetData();
overrideData.CreateRendererOverride();
overrideData.ShowPreviewChanges();
state = State.PREVIEW;
}
private void EndOverrideProcess(bool applyChanges)
{
if (applyChanges)
{
List<Material> affectedMaterials = overrideData.CollectAffectedMaterials();
string title = "Overriding AllIn13D materials";
string message = $"You are about to override {affectedMaterials.Count} materials";
string okButton = "Override";
string cancelButton = "Cancel";
bool isOk = EditorUtility.DisplayDialog(title, message, okButton, cancelButton);
if (isOk)
{
overrideData.ApplyChangesToMaterials(affectedMaterials);
overrideData.EndOverrideProcess();
if(overrideData.applyTarget == MaterialOverrideData.ApplyTarget.CURRENT_SCENE)
{
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
AssetDatabase.SaveAssets();
}
state = State.NONE;
}
}
else
{
overrideData.EndOverrideProcess();
state = State.NONE;
}
}
private void DrawStateNone()
{
if (GUILayout.Button("Start"))
{
StartOverrideProcess();
}
}
private void DrawStatePreview()
{
overrideData.applyTarget = (MaterialOverrideData.ApplyTarget)EditorGUILayout.EnumPopup("Apply Target", overrideData.applyTarget);
if(overrideData.applyTarget == MaterialOverrideData.ApplyTarget.SELECTED_FOLDERS)
{
EditorGUILayout.PropertyField(spFolders);
}
GUILayout.Space(20f);
if (GUILayout.Button("+"))
{
propertySelectorWindow = PropertySelectorAuxWindow.GetWindow<PropertySelectorAuxWindow>(title: "Select Property", utility: true);
propertySelectorWindow.Setup(PropertyAddedCallback);
}
GUILayout.Space(20f);
EditorGUI.BeginChangeCheck();
for(int i = 0; i < overrideData.generalPropertiesOverrides.Count; i++)
{
DrawOverriddenEffectProperty(overrideData.generalPropertiesOverrides[i]);
}
if (!overrideData.IsEmpty())
{
GUILayout.Space(10f);
}
for (int i = 0; i < overrideData.effectOverrides.Count; i++)
{
DrawEffectOverride(overrideData.effectOverrides[i]);
}
if (EditorGUI.EndChangeCheck())
{
overrideData.ShowPreviewChanges();
}
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(!overrideData.IsApplyEnabled() || overrideData.IsEmpty());
if (GUILayout.Button("Apply"))
{
EndOverrideProcess(applyChanges: true);
}
EditorGUI.EndDisabledGroup();
if (GUILayout.Button("Cancel"))
{
EndOverrideProcess(applyChanges: false);
}
EditorGUILayout.EndHorizontal();
}
private void DrawEffectOverride(AbstractEffectOverride effectOverride)
{
EditorGUILayout.BeginHorizontal();
float lastLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 150f;
EditorGUI.BeginChangeCheck();
effectOverride.overrideEnabled = EditorGUILayout.Toggle($"{effectOverride.displayName} Override", effectOverride.overrideEnabled);
if (EditorGUI.EndChangeCheck())
{
overrideData.RebuildPreviewMaterial();
}
EditorGUIUtility.labelWidth = lastLabelWidth;
EditorGUI.BeginDisabledGroup(!effectOverride.overrideEnabled);
if (effectOverride is EffectToggleOverride)
{
EffectToggleOverride effectToggleOverride = (EffectToggleOverride)effectOverride;
effectToggleOverride.boolValue = EditorGUILayout.Toggle("On/Off", effectToggleOverride.boolValue);
}
else if(effectOverride is EffectEnumOverride)
{
EffectEnumOverride effectEnumOverride = (EffectEnumOverride)effectOverride;
effectEnumOverride.index = EditorGUILayout.Popup("Value", effectEnumOverride.index, effectEnumOverride.enumOptions);
}
EditorGUI.EndDisabledGroup();
if (GUILayout.Button("-", GUILayout.Width(50f)))
{
overrideData.RemoveEffectOverride(effectOverride);
}
EditorGUILayout.EndHorizontal();
DrawEffectOverrideProperties(effectOverride);
}
private void DrawEffectOverrideProperties(AbstractEffectOverride effectOverride)
{
EditorGUILayout.BeginVertical(propertiesStyle);
for (int i = 0; i < effectOverride.propertyOverrides.Count; i++)
{
DrawOverriddenEffectProperty(effectOverride.propertyOverrides[i]);
}
EditorGUILayout.EndVertical();
}
private void DrawOverriddenEffectProperty(PropertyOverride propertyOverride)
{
EditorGUILayout.BeginHorizontal();
if (propertyOverride.propertyOverrideType == PropertyOverrideType.ENUM)
{
propertyOverride.floatValue = EditorGUILayout.Popup(propertyOverride.displayName, (int)propertyOverride.floatValue, propertyOverride.keywords);
}
else if (propertyOverride.propertyOverrideType == PropertyOverrideType.TOGGLE)
{
bool toggleBool = ((int)propertyOverride.floatValue) == 1f;
toggleBool = EditorGUILayout.Toggle(propertyOverride.displayName, toggleBool);
float toggleFloat = toggleBool ? 1f : 0f;
propertyOverride.floatValue = toggleFloat;
}
else
{
switch (propertyOverride.shaderPropertyType)
{
case ShaderPropertyType.Float:
propertyOverride.floatValue = EditorGUILayout.FloatField(propertyOverride.displayName, propertyOverride.floatValue);
break;
case ShaderPropertyType.Range:
propertyOverride.floatValue = EditorGUILayout.Slider(propertyOverride.displayName, propertyOverride.floatValue, propertyOverride.rangeLimits.x, propertyOverride.rangeLimits.y);
break;
case ShaderPropertyType.Int:
propertyOverride.intValue = EditorGUILayout.IntField(propertyOverride.displayName, propertyOverride.intValue);
break;
case ShaderPropertyType.Color:
GUIContent guiContent = new GUIContent(propertyOverride.displayName);
propertyOverride.colorValue = EditorGUILayout.ColorField(guiContent, propertyOverride.colorValue, true, true, propertyOverride.isHDR);
break;
case ShaderPropertyType.Texture:
EditorGUILayout.BeginVertical();
propertyOverride.texValue = (Texture)EditorGUILayout.ObjectField(propertyOverride.displayName, propertyOverride.texValue, typeof(Texture), false);
float lastLabelWidth = EditorGUIUtility.labelWidth;
if (propertyOverride.hasTilingAndOffset)
{
EditorGUILayout.BeginHorizontal();
Vector2 tiling = new Vector2(propertyOverride.tilingAndOffset.x, propertyOverride.tilingAndOffset.y);
EditorGUILayout.LabelField("Tiling", GUILayout.Width(50));
tiling = EditorGUILayout.Vector2Field(string.Empty, tiling, GUILayout.Width(400));
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
Vector2 offset = new Vector2(propertyOverride.tilingAndOffset.z, propertyOverride.tilingAndOffset.w);
EditorGUILayout.LabelField("Offset", GUILayout.Width(50));
offset = EditorGUILayout.Vector2Field(string.Empty, offset, GUILayout.Width(400));
EditorGUILayout.EndHorizontal();
propertyOverride.tilingAndOffset = new Vector4(tiling.x, tiling.y, offset.x, offset.y);
}
EditorGUIUtility.labelWidth = lastLabelWidth;
EditorGUILayout.EndVertical();
break;
case ShaderPropertyType.Vector:
propertyOverride.vectorValue = EditorGUILayout.Vector4Field(propertyOverride.displayName, propertyOverride.vectorValue);
break;
}
}
if (GUILayout.Button("-", GUILayout.Width(50f)))
{
overrideData.RemovePropertyOverride(propertyOverride);
overrideData.RebuildPreviewMaterial();
}
EditorGUILayout.EndHorizontal();
}
private void PropertyAddedCallback(AllIn13DEffectConfig effectConfig, int propertyIndex, Shader shader,
PropertySelectorAuxWindow.TypeOfPropertyAdded typeOfPropertyAdded)
{
if(typeOfPropertyAdded == PropertySelectorAuxWindow.TypeOfPropertyAdded.EFFECT_MAIN)
{
overrideData.AddCopmleteEffectOverride(effectConfig, shader);
}
else if(typeOfPropertyAdded == PropertySelectorAuxWindow.TypeOfPropertyAdded.GLOBAL_PROPERTY || typeOfPropertyAdded == PropertySelectorAuxWindow.TypeOfPropertyAdded.ADVANCED_PROPERTY)
{
overrideData.AddGeneralPropertyOverride(propertyIndex, shader);
}
//else if(typeOfPropertyAdded == PropertySelectorAuxWindow.TypeOfPropertyAdded.EFFECT_MAIN)
//{
// overrideData.AddEffectOverride(effectConfig);
//}
overrideData.ShowPreviewChanges();
parentWindow.Repaint();
}
public void Close()
{
EndOverrideProcess(applyChanges: false);
//EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
//AssetDatabase.SaveAssets();
if (propertySelectorWindow != null)
{
propertySelectorWindow.Close();
}
}
private void OnSceneClosing(Scene scene, bool removingScene)
{
Close();
EditorSceneManager.MarkSceneDirty(scene);
AssetDatabase.SaveAssets();
Initialize();
}
private void OnSceneSaving(Scene scene, string path)
{
overrideData.UseMaterialSource();
EditorSceneManager.MarkSceneDirty(scene);
}
private void OnSceneSaved(Scene scene)
{
if(state == State.PREVIEW)
{
overrideData.UsePreviewMaterials();
}
}
private void OnSceneDirtied(Scene scene)
{
if(state == State.PREVIEW && Event.current != null)
{
bool deletingObject = false;
if(Event.current.commandName == "Delete" || Event.current.commandName == "SoftDelete")
{
deletingObject = true;
}
if (deletingObject)
{
Transform[] transformsSelected = Selection.transforms;
for (int i = 0; i < transformsSelected.Length; i++)
{
Renderer[] renderers = transformsSelected[i].GetComponentsInChildren<Renderer>();
bool changesDiscarded = overrideData.DiscardChanges(renderers);
if (changesDiscarded)
{
EditorSceneManager.MarkSceneDirty(scene);
AssetDatabase.SaveAssets();
}
}
}
}
}
private bool OnWantsToQuit()
{
bool res = true;
if(state == State.PREVIEW)
{
bool dialog = EditorUtility.DisplayDialog("Overriding in process", "You are using preview materials. Finish override process before closing Unity", "End override process", "Cancel");
if (dialog)
{
Close();
}
res = false;
}
return res;
}
private static void OnHierarchyChanged()
{
}
private static void BeforeAssemblyReload()
{
if(overrideData != null)
{
overrideData.EndOverrideProcess();
}
}
public override string GetTabName()
{
return TAB_NAME;
}
}
}