Files
avatar/Assets/Unlit_WF_ShaderSuite/Editor/WF_ShaderToolWindow.cs
2022-09-27 20:47:45 -07:00

861 lines
34 KiB
C#

/*
* The MIT License
*
* Copyright 2018-2021 whiteflare.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using System.Text.RegularExpressions;
using UnityEngine;
namespace UnlitWF
{
internal static class MenuPathString
{
public const string PATH_TOOLS = "Tools/UnlitWF/";
public const string PATH_ASSETS = "Assets/UnlitWF Material Tools/";
public const string TOOLS_CREANUP = PATH_TOOLS + "CleanUp material property";
public const string ASSETS_CREANUP = PATH_ASSETS + "CleanUp material property";
public const string TOOLS_RESET = PATH_TOOLS + "Reset material property";
public const string ASSETS_RESET = PATH_ASSETS + "Reset material property";
public const string TOOLS_COPY = PATH_TOOLS + "Copy material property";
public const string ASSETS_COPY = PATH_ASSETS + "Copy material property";
public const string TOOLS_MIGRATION = PATH_TOOLS + "Migration material";
public const string ASSETS_MIGRATION = PATH_ASSETS + "Migration material";
public const string TOOLS_DEBUGVIEW = PATH_TOOLS + "Switch DebugView shader";
public const string ASSETS_DEBUGVIEW = PATH_ASSETS + "Switch DebugView shader";
public const string MATERIAL_DEBUGVIEW = "CONTEXT/Material/Switch WF_DebugView shader";
}
internal static class ToolCommon
{
public static bool IsUnlitWFMaterial(Material mm) {
if (mm != null && mm.shader != null) {
return mm.shader.name.Contains("UnlitWF") && !mm.shader.name.Contains("Debug");
}
return false;
}
public static bool IsNotUnlitWFMaterial(Material mm) {
if (mm != null && mm.shader != null) {
return !IsUnlitWFMaterial(mm);
}
return false;
}
}
#region
public class CleanUpParameter : ScriptableObject
{
public Material[] materials = { null };
public bool resetUnused = false;
public bool resetKeywords = false;
}
public class ToolCreanUpWindow : EditorWindow
{
[MenuItem(MenuPathString.TOOLS_CREANUP)]
[MenuItem(MenuPathString.ASSETS_CREANUP)]
private static void OpenWindowFromMenu() {
arguments.Clear();
arguments.AddRange(Selection.GetFiltered<Material>(SelectionMode.Assets));
GetWindow<ToolCreanUpWindow>("UnlitWF/CleanUp material property");
}
[MenuItem(MenuPathString.ASSETS_CREANUP, validate = true)]
private static bool OpenWindowFromMenuValidation() {
return Selection.GetFiltered<Material>(SelectionMode.Assets).Length != 0;
}
internal static void OpenWindowFromShaderGUI(Material[] mats) {
arguments.Clear();
arguments.AddRange(mats);
GetWindow<ToolCreanUpWindow>("UnlitWF/CleanUp material property");
}
private static readonly List<Material> arguments = new List<Material>();
private GUIStyle styleTitle;
private GUIStyle styleBigText;
Vector2 scroll = Vector2.zero;
private CleanUpParameter param;
private void OnEnable() {
minSize = new Vector2(480, 640);
param = ScriptableObject.CreateInstance<CleanUpParameter>();
if (0 < arguments.Count) {
param.materials = arguments.ToArray();
}
styleTitle = new GUIStyle(EditorStyles.boldLabel) {
fontSize = 18,
fontStyle = FontStyle.Bold,
fixedHeight = 32,
};
styleBigText = new GUIStyle(EditorStyles.boldLabel) {
fontSize = 16,
fontStyle = FontStyle.Bold,
fixedHeight = 32,
};
}
private void OnGUI() {
var so = new SerializedObject(param);
so.Update();
SerializedProperty prop;
// タイトル
EditorGUILayout.Space();
EditorGUILayout.LabelField("UnlitWF / CleanUp material property", styleTitle);
EditorGUILayout.Space();
EditorGUILayout.Space();
// メイン
EditorGUILayout.LabelField("CleanUp disabled values", styleBigText);
EditorGUILayout.HelpBox("materialsから無効化されている機能の設定値をクリアします。", MessageType.Info);
EditorGUILayout.Space();
// スクロール開始
scroll = EditorGUILayout.BeginScrollView(scroll);
// マテリアルリスト
EditorGUILayout.LabelField("materials", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(so.FindProperty("materials"), new GUIContent("list"), true);
EditorGUILayout.Space();
// マテリアルに UnlitWF 以外のシェーダが紛れている場合には警告
bool removeOther = false;
foreach (Material mm in param.materials) {
if (ToolCommon.IsNotUnlitWFMaterial(mm)) {
EditorGUILayout.HelpBox("Found Not-UnlitWF materials. Continue?\n(UnlitWF以外のマテリアルが紛れていますが大丈夫ですか?)", MessageType.Warning);
if (GUILayout.Button("Remove other materials")) {
removeOther = true;
}
break;
}
}
EditorGUILayout.Space();
// オプション
EditorGUILayout.LabelField("options", EditorStyles.boldLabel);
prop = so.FindProperty("resetUnused");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "UnUsed Properties (未使用の値) も一緒にクリアする");
prop = so.FindProperty("resetKeywords");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "ShaderKeywords (Shaderキーワード) も一緒にクリアする");
EditorGUILayout.Space();
so.ApplyModifiedPropertiesWithoutUndo();
so.SetIsDifferentCacheDirty();
// UnlitWF 以外のマテリアルを除去
if (removeOther) {
var newlist = new List<Material>();
newlist.AddRange(param.materials);
newlist.RemoveAll(mm => !ToolCommon.IsUnlitWFMaterial(mm));
param.materials = newlist.ToArray();
}
if (GUILayout.Button("CleanUp")) {
new WFMaterialEditUtility().CleanUpProperties(param);
}
EditorGUILayout.Space();
// スクロール終了
EditorGUILayout.EndScrollView();
}
}
#endregion
#region
internal class ResetParameter : ScriptableObject
{
public Material[] materials = { null };
public bool resetColor = false;
public bool resetFloat = false;
public bool resetTexture = false;
public bool resetColorAlpha = false;
public bool resetLit = false;
public bool resetUnused = false;
public bool resetKeywords = false;
}
public class ToolResetWindow : EditorWindow
{
[MenuItem(MenuPathString.TOOLS_RESET)]
[MenuItem(MenuPathString.ASSETS_RESET)]
private static void OpenWindowFromMenu() {
arguments.Clear();
arguments.AddRange(Selection.GetFiltered<Material>(SelectionMode.Assets));
GetWindow<ToolResetWindow>("UnlitWF/Reset material property");
}
[MenuItem(MenuPathString.ASSETS_RESET, validate = true)]
private static bool OpenWindowFromMenuValidation() {
return Selection.GetFiltered<Material>(SelectionMode.Assets).Length != 0;
}
private static readonly List<Material> arguments = new List<Material>();
private GUIStyle styleTitle;
private GUIStyle styleBigText;
Vector2 scroll = Vector2.zero;
private ResetParameter param;
private void OnEnable() {
minSize = new Vector2(480, 640);
param = ScriptableObject.CreateInstance<ResetParameter>();
if (0 < arguments.Count) {
param.materials = arguments.ToArray();
}
styleTitle = new GUIStyle(EditorStyles.boldLabel) {
fontSize = 18,
fontStyle = FontStyle.Bold,
fixedHeight = 32,
};
styleBigText = new GUIStyle(EditorStyles.boldLabel) {
fontSize = 16,
fontStyle = FontStyle.Bold,
fixedHeight = 32,
};
}
private void OnGUI() {
var so = new SerializedObject(param);
so.Update();
SerializedProperty prop;
// タイトル
EditorGUILayout.Space();
EditorGUILayout.LabelField("UnlitWF / Reset material property", styleTitle);
EditorGUILayout.Space();
EditorGUILayout.Space();
// メイン
EditorGUILayout.LabelField("Reset properties", styleBigText);
EditorGUILayout.HelpBox("materialsの設定値を初期化します。", MessageType.Info);
EditorGUILayout.Space();
// スクロール開始
scroll = EditorGUILayout.BeginScrollView(scroll);
// マテリアルリスト
EditorGUILayout.LabelField("materials", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(so.FindProperty("materials"), new GUIContent("list"), true);
EditorGUILayout.Space();
// マテリアルに UnlitWF 以外のシェーダが紛れている場合には警告
bool removeOther = false;
foreach (Material mm in param.materials) {
if (ToolCommon.IsNotUnlitWFMaterial(mm)) {
EditorGUILayout.HelpBox("Found Not-UnlitWF materials. Continue?\n(UnlitWF以外のマテリアルが紛れていますが大丈夫ですか?)", MessageType.Warning);
if (GUILayout.Button("Remove other materials")) {
removeOther = true;
}
break;
}
}
EditorGUILayout.Space();
// 対象(種類から)
EditorGUILayout.LabelField("Reset by Type", EditorStyles.boldLabel);
prop = so.FindProperty("resetColor");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "Color (色) をデフォルトに戻す");
prop = so.FindProperty("resetTexture");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "Texture (テクスチャ) をデフォルトに戻す");
prop = so.FindProperty("resetFloat");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "Float (数値) をデフォルトに戻す");
EditorGUILayout.Space();
// 対象(機能から)
EditorGUILayout.LabelField("Reset by Function", EditorStyles.boldLabel);
prop = so.FindProperty("resetColorAlpha");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "Color (色) の Alpha を 1.0 にする");
prop = so.FindProperty("resetLit");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "Lit & Lit Advance の設定をデフォルトに戻す");
EditorGUILayout.Space();
// オプション
EditorGUILayout.LabelField("options", EditorStyles.boldLabel);
prop = so.FindProperty("resetUnused");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "UnUsed Properties (未使用の値) も一緒にクリアする");
prop = so.FindProperty("resetKeywords");
prop.boolValue = GUILayout.Toggle(prop.boolValue, "ShaderKeywords (Shaderキーワード) も一緒にクリアする");
EditorGUILayout.Space();
so.ApplyModifiedPropertiesWithoutUndo();
so.SetIsDifferentCacheDirty();
// UnlitWF 以外のマテリアルを除去
if (removeOther) {
var newlist = new List<Material>();
newlist.AddRange(param.materials);
newlist.RemoveAll(mm => !ToolCommon.IsUnlitWFMaterial(mm));
param.materials = newlist.ToArray();
}
if (GUILayout.Button("Reset Values")) {
new WFMaterialEditUtility().ResetProperties(param);
}
EditorGUILayout.Space();
// スクロール終了
EditorGUILayout.EndScrollView();
}
}
#endregion
#region
internal class CopyPropParameter : ScriptableObject
{
public Material materialSource = null;
public Material[] materialDestination = { null };
public string[] functions = { };
}
public class ToolCopyWindow : EditorWindow
{
[MenuItem(MenuPathString.TOOLS_COPY)]
[MenuItem(MenuPathString.ASSETS_COPY)]
private static void OpenWindowFromMenu() {
arguments.Clear();
arguments.AddRange(Selection.GetFiltered<Material>(SelectionMode.Assets));
GetWindow<ToolCopyWindow>("UnlitWF/Copy material property");
}
[MenuItem(MenuPathString.ASSETS_COPY, validate = true)]
private static bool OpenWindowFromMenuValidation() {
return Selection.GetFiltered<Material>(SelectionMode.Assets).Length != 0;
}
private static readonly List<Material> arguments = new List<Material>();
private GUIStyle styleTitle;
private GUIStyle styleBigText;
Vector2 scroll = Vector2.zero;
private CopyPropParameter param;
private void OnEnable() {
minSize = new Vector2(480, 640);
param = ScriptableObject.CreateInstance<CopyPropParameter>();
if (0 < arguments.Count) {
param.materialDestination = arguments.ToArray();
}
styleTitle = new GUIStyle(EditorStyles.boldLabel) {
fontSize = 18,
fontStyle = FontStyle.Bold,
fixedHeight = 32,
};
styleBigText = new GUIStyle(EditorStyles.boldLabel) {
fontSize = 16,
fontStyle = FontStyle.Bold,
fixedHeight = 32,
};
}
private void OnGUI() {
var so = new SerializedObject(param);
so.Update();
// タイトル
EditorGUILayout.Space();
EditorGUILayout.LabelField("UnlitWF / Copy material property", styleTitle);
EditorGUILayout.Space();
EditorGUILayout.Space();
// メイン
EditorGUILayout.LabelField("Copy properties", styleBigText);
EditorGUILayout.HelpBox("source material の設定値を destination materials にコピーします。", MessageType.Info);
EditorGUILayout.Space();
// スクロール開始
scroll = EditorGUILayout.BeginScrollView(scroll);
// マテリアルリスト
EditorGUILayout.LabelField("destination materials", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(so.FindProperty("materialDestination"), new GUIContent("list"), true);
EditorGUILayout.Space();
// マテリアルに UnlitWF 以外のシェーダが紛れている場合には警告
bool removeOther = false;
foreach (Material mm in param.materialDestination) {
if (ToolCommon.IsNotUnlitWFMaterial(mm)) {
EditorGUILayout.HelpBox("Found Not-UnlitWF materials. Continue?\n(UnlitWF以外のマテリアルが紛れていますが大丈夫ですか?)", MessageType.Warning);
if (GUILayout.Button("Remove other materials")) {
removeOther = true;
}
break;
}
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("source materials", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(so.FindProperty("materialSource"), new GUIContent("material"), true);
EditorGUILayout.Space();
if (ToolCommon.IsNotUnlitWFMaterial(param.materialSource)) {
EditorGUILayout.HelpBox("Found Not-UnlitWF materials. Continue?\n(UnlitWF以外のマテリアルが紛れていますが大丈夫ですか?)", MessageType.Warning);
EditorGUILayout.Space();
}
so.ApplyModifiedPropertiesWithoutUndo();
so.SetIsDifferentCacheDirty();
// 対象
EditorGUILayout.LabelField("copy target functions", EditorStyles.boldLabel);
var updatedFunctions = new List<string>();
foreach (var func in WFShaderDictionary.ShaderFuncList) {
if (func.Contains(param.materialSource)) {
bool value = param.functions.Contains(func.Label);
if (GUILayout.Toggle(value, string.Format("[{0}] {1}", func.Label, func.Name))) {
updatedFunctions.Add(func.Label);
}
}
}
if (!updatedFunctions.SequenceEqual(param.functions)) {
param.functions = updatedFunctions.ToArray();
}
EditorGUILayout.Space();
// UnlitWF 以外のマテリアルを除去
if (removeOther) {
var newlist = new List<Material>();
newlist.AddRange(param.materialDestination);
newlist.RemoveAll(mm => !ToolCommon.IsUnlitWFMaterial(mm));
param.materialDestination = newlist.ToArray();
}
using (new EditorGUI.DisabledGroupScope(param.functions.Length == 0)) {
if (GUILayout.Button("Copy Values")) {
new WFMaterialEditUtility().CopyProperties(param);
}
}
EditorGUILayout.Space();
// スクロール終了
EditorGUILayout.EndScrollView();
}
}
#endregion
#region
internal class MigrationParameter : ScriptableObject
{
public Material[] materials = { null };
}
public class ToolMigrationWindow : EditorWindow
{
[MenuItem(MenuPathString.TOOLS_MIGRATION)]
[MenuItem(MenuPathString.ASSETS_MIGRATION)]
private static void OpenWindowFromMenu() {
arguments.Clear();
arguments.AddRange(Selection.GetFiltered<Material>(SelectionMode.Assets));
GetWindow<ToolMigrationWindow>("UnlitWF/Migration material");
}
[MenuItem(MenuPathString.ASSETS_MIGRATION, validate = true)]
private static bool OpenWindowFromMenuValidation() {
return Selection.GetFiltered<Material>(SelectionMode.Assets).Length != 0;
}
private static readonly List<Material> arguments = new List<Material>();
private GUIStyle styleTitle;
private GUIStyle styleBigText;
Vector2 scroll = Vector2.zero;
private MigrationParameter param;
private void OnEnable() {
minSize = new Vector2(480, 640);
param = ScriptableObject.CreateInstance<MigrationParameter>();
if (0 < arguments.Count) {
param.materials = arguments.ToArray();
}
styleTitle = new GUIStyle(EditorStyles.boldLabel) {
fontSize = 18,
fontStyle = FontStyle.Bold,
fixedHeight = 32,
};
styleBigText = new GUIStyle(EditorStyles.boldLabel) {
fontSize = 16,
fontStyle = FontStyle.Bold,
fixedHeight = 32,
};
}
private void OnGUI() {
var so = new SerializedObject(param);
so.Update();
// タイトル
EditorGUILayout.Space();
EditorGUILayout.LabelField("UnlitWF / Migration material", styleTitle);
EditorGUILayout.Space();
EditorGUILayout.Space();
// メイン
EditorGUILayout.LabelField("Migration materials", styleBigText);
EditorGUILayout.HelpBox("古いバージョンのUnlitWFで設定されたmaterialsを最新版に変換します。", MessageType.Info);
EditorGUILayout.Space();
// スクロール開始
scroll = EditorGUILayout.BeginScrollView(scroll);
// マテリアルリスト
EditorGUILayout.LabelField("materials", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(so.FindProperty("materials"), new GUIContent("list"), true);
EditorGUILayout.Space();
// マテリアルに UnlitWF 以外のシェーダが紛れている場合には警告
bool removeOther = false;
foreach (Material mm in param.materials) {
if (ToolCommon.IsNotUnlitWFMaterial(mm)) {
EditorGUILayout.HelpBox("Found Not-UnlitWF materials. Continue?\n(UnlitWF以外のマテリアルが紛れていますが大丈夫ですか?)", MessageType.Warning);
if (GUILayout.Button("Remove other materials")) {
removeOther = true;
}
break;
}
}
EditorGUILayout.Space();
so.ApplyModifiedPropertiesWithoutUndo();
so.SetIsDifferentCacheDirty();
// UnlitWF 以外のマテリアルを除去
if (removeOther) {
var newlist = new List<Material>();
newlist.AddRange(param.materials);
newlist.RemoveAll(mm => !ToolCommon.IsUnlitWFMaterial(mm));
param.materials = newlist.ToArray();
}
if (GUILayout.Button("Convert")) {
if (new WFMaterialEditUtility().RenameOldNameProperties(param)) {
// ShaderGUI側のマテリアルキャッシュをリセット
ShaderCustomEditor.ResetOldMaterialTable();
// 変更したマテリアルを保存
AssetDatabase.SaveAssets();
}
}
EditorGUILayout.Space();
// スクロール終了
EditorGUILayout.EndScrollView();
}
}
#endregion
internal class WFMaterialEditUtility
{
#region
public bool ExistsOldNameProperty(params Material[] mats) {
return 0 < CreateOldNamePropertyList(mats).Count;
}
public bool RenameOldNameProperties(MigrationParameter param) {
return RenameOldNameProperties(param.materials);
}
public bool RenameOldNameProperties(Material[] mats) {
Undo.RecordObjects(mats, "WF Migration materials");
var oldPropList = CreateOldNamePropertyList(mats);
// 名称を全て変更
foreach (var propPair in oldPropList) {
if (propPair.after != null) {
propPair.before.CopyTo(propPair.after);
propPair.onAfterCopy(propPair.after);
}
}
// 保存
ShaderSerializedProperty.AllApplyPropertyChange(oldPropList.Select(p => p.after));
// 旧プロパティは全て削除
foreach (var prop in oldPropList.Select(p => p.before)) {
prop.Remove();
}
// 保存
ShaderSerializedProperty.AllApplyPropertyChange(oldPropList.Select(p => p.before));
// シェーダキーワードを整理
WFCommonUtility.SetupShaderKeyword(mats);
return 0 < oldPropList.Count;
}
private List<OldNameProperty> CreateOldNamePropertyList(Material[] mats) {
var result = new List<OldNameProperty>();
foreach (var mat in mats) {
if (mat.shader.name.Contains("MatcapShadows")) {
// MatcapShadowsは古いので対象にしない
continue;
}
var props = ShaderSerializedProperty.AsDict(mat);
foreach (var pair in WFShaderDictionary.OldPropNameToNewPropNameList) {
var before = props.GetValueOrNull(pair.beforeName);
if (before != null) {
result.Add(new OldNameProperty(before, props.GetValueOrNull(pair.afterName), pair.onAfterCopy));
}
}
}
return result;
}
public struct OldNameProperty
{
public readonly ShaderSerializedProperty before;
public readonly ShaderSerializedProperty after;
public readonly Action<ShaderSerializedProperty> onAfterCopy;
public OldNameProperty(ShaderSerializedProperty before, ShaderSerializedProperty after, Action<ShaderSerializedProperty> onAfterCopy) {
this.before = before;
this.after = after;
this.onAfterCopy = onAfterCopy ?? (p => { });
}
public OldNameProperty(ShaderSerializedProperty before, ShaderSerializedProperty after) : this(before, after, null) {
}
}
#endregion
#region
public void CopyProperties(CopyPropParameter param) {
if (param.materialSource == null) {
return;
}
var src_props = new List<ShaderMaterialProperty>();
var copy_target = WFShaderFunction.LabelToPrefix(param.functions.ToList());
foreach (var src_prop in ShaderMaterialProperty.AsList(param.materialSource)) {
string label = WFCommonUtility.GetPrefixFromPropName(src_prop.Name);
if (label == null) {
continue;
}
// ラベルの一致判定
if (copy_target.Any(label.Contains)) {
src_props.Add(src_prop);
}
}
if (src_props.Count == 0) {
return;
}
Undo.RecordObjects(param.materialDestination, "WF copy materials");
for (int i = 0; i < param.materialDestination.Length; i++) {
var dst = param.materialDestination[i];
if (dst == null || dst == param.materialSource) { // コピー先とコピー元が同じ時もコピーしない
continue;
}
var dst_props = ShaderMaterialProperty.AsDict(dst);
// コピー
if (CopyProperties(src_props, dst_props)) {
// キーワードを整理する
WFCommonUtility.SetupShaderKeyword(dst);
// ダーティフラグを付ける
EditorUtility.SetDirty(dst);
}
}
AssetDatabase.SaveAssets();
}
private bool CopyProperties(List<ShaderMaterialProperty> src, Dictionary<string, ShaderMaterialProperty> dst) {
var changed = false;
foreach (var src_prop in src) {
ShaderMaterialProperty dst_prop;
if (dst.TryGetValue(src_prop.Name, out dst_prop)) {
changed |= src_prop.CopyTo(dst_prop);
}
}
return changed;
}
#endregion
#region
public void CleanUpProperties(CleanUpParameter param) {
Undo.RecordObjects(param.materials, "WF cleanup materials");
foreach (Material material in param.materials) {
if (material == null) {
continue;
}
var props = ShaderSerializedProperty.AsList(material);
// 無効になってる機能のプレフィックスを集める
var delPrefix = new List<string>();
foreach (var p in props) {
string label, name;
WFCommonUtility.FormatPropName(p.name, out label, out name);
if (label != null && name.ToLower() == "enable" && p.FloatValue == 0) {
delPrefix.Add(label);
}
}
var del_props = new HashSet<ShaderSerializedProperty>();
// プレフィックスに合致する設定値を消去
Predicate<ShaderSerializedProperty> predPrefix = p => {
string label = WFCommonUtility.GetPrefixFromPropName(p.name);
return label != null && delPrefix.Contains(label);
};
props.FindAll(predPrefix)
// ただしEnableToggle自体は初期化しない
.Where(p => !WFCommonUtility.IsEnableToggleFromPropName(p.name)).ToList().ForEach(p => del_props.Add(p));
// 未使用の値を削除
Predicate<ShaderSerializedProperty> predUnused = p => param.resetUnused && !p.HasPropertyInShader;
props.FindAll(predUnused).ForEach(p => del_props.Add(p));
// 削除実行
DeleteProperties(del_props);
// キーワードクリア
if (param.resetKeywords) {
foreach (var so in ShaderSerializedProperty.GetUniqueSerialObject(props)) {
DeleteShaderKeyword(so);
}
}
// キーワードを整理する
WFCommonUtility.SetupShaderKeyword(material);
// 反映
EditorUtility.SetDirty(material);
}
}
public void ResetProperties(ResetParameter param) {
Undo.RecordObjects(param.materials, "WF reset materials");
foreach (Material material in param.materials) {
if (material == null) {
continue;
}
var props = ShaderSerializedProperty.AsList(material);
var del_props = new HashSet<ShaderSerializedProperty>();
// ColorのAlphaチャンネルのみ変更
foreach (var p in props) {
if (p.HasPropertyInShader && p.Type == ShaderUtil.ShaderPropertyType.Color) {
var c = p.ColorValue;
c.a = 1;
p.ColorValue = c;
}
}
ShaderSerializedProperty.AllApplyPropertyChange(props);
// 条件に合致するプロパティを削除
foreach (var p in props) {
if (param.resetColor && p.ParentName == "m_Colors") {
del_props.Add(p);
}
else if (param.resetFloat && p.ParentName == "m_Floats") {
del_props.Add(p);
}
else if (param.resetTexture && p.ParentName == "m_TexEnvs") {
del_props.Add(p);
}
else if (param.resetUnused && !p.HasPropertyInShader) {
del_props.Add(p);
}
else if (param.resetLit && p.name.StartsWith("_GL_")) {
del_props.Add(p);
}
}
// 削除実行
DeleteProperties(del_props);
// キーワードクリア
if (param.resetKeywords) {
foreach (var so in ShaderSerializedProperty.GetUniqueSerialObject(props)) {
DeleteShaderKeyword(so);
}
}
// キーワードを整理する
WFCommonUtility.SetupShaderKeyword(material);
// 反映
EditorUtility.SetDirty(material);
}
}
private void DeleteProperties(IEnumerable<ShaderSerializedProperty> props) {
var del_names = new HashSet<string>();
foreach (var p in props) {
del_names.Add(p.name);
p.Remove();
}
if (0 < del_names.Count) {
var names = new List<string>(del_names);
names.Sort();
UnityEngine.Debug.Log("[WF][Tool] Deleted Property: " + string.Join(", ", names.ToArray()));
}
ShaderSerializedProperty.AllApplyPropertyChange(props);
}
public void DeleteShaderKeyword(SerializedObject so) {
var prop = so.FindProperty("m_ShaderKeywords");
if (prop == null || string.IsNullOrEmpty(prop.stringValue)) {
return;
}
UnityEngine.Debug.Log("[WF][Tool] Deleted Shaderkeyword: " + prop.stringValue);
prop.stringValue = "";
so.ApplyModifiedProperties();
}
#endregion
}
}
#endif