861 lines
34 KiB
C#
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
|