avatar/Assets/Unlit_WF_ShaderSuite/Editor/WF_ShaderToolWindow.cs

861 lines
34 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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