Updated GenerateMask helper
This commit is contained in:
@@ -2,10 +2,10 @@ Shader "Hidden/GenerateMask"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_TexR ("Red Channel Texture", 2D) = "white"
|
||||
_TexG ("Green Channel Texture", 2D) = "white"
|
||||
_TexB ("Blue Channel Texture", 2D) = "white"
|
||||
_TexA ("Alpha Channel Texture", 2D) = "white"
|
||||
_MetallicMap ("MetallicMap", 2D) = "white"
|
||||
_AoMap ("AoMap", 2D) = "white"
|
||||
_DetailMap ("DetailMap", 2D) = "white"
|
||||
_SmoothnessMap ("SmoothnessMap", 2D) = "white"
|
||||
}
|
||||
SubShader
|
||||
{
|
||||
@@ -20,10 +20,11 @@ Shader "Hidden/GenerateMask"
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#pragma shader_feature_local _HAS_TEX_R
|
||||
#pragma shader_feature_local _HAS_TEX_G
|
||||
#pragma shader_feature_local _HAS_TEX_B
|
||||
#pragma shader_feature_local _HAS_TEX_A
|
||||
#pragma shader_feature_local _HAS_METALLIC
|
||||
#pragma shader_feature_local _HAS_AO
|
||||
#pragma shader_feature_local _HAS_DETAIL
|
||||
#pragma shader_feature_local _HAS_SMOOTHNESS
|
||||
#pragma shader_feature_local _HAS_ROUGHNESS
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
@@ -44,35 +45,37 @@ Shader "Hidden/GenerateMask"
|
||||
return o;
|
||||
}
|
||||
|
||||
sampler2D _TexR;
|
||||
sampler2D _TexG;
|
||||
sampler2D _TexB;
|
||||
sampler2D _TexA;
|
||||
sampler2D _MetallicMap;
|
||||
sampler2D _AoMap;
|
||||
sampler2D _DetailMap;
|
||||
sampler2D _SmoothnessMap;
|
||||
|
||||
float4 _Fallback;
|
||||
|
||||
float4 frag (v2f i) : SV_Target
|
||||
{
|
||||
#ifdef _HAS_TEX_R
|
||||
float r = tex2D(_TexR, i.uv).r;
|
||||
#ifdef _HAS_METALLIC
|
||||
float r = tex2D(_MetallicMap, i.uv).r;
|
||||
#else
|
||||
float r = _Fallback.r;
|
||||
#endif
|
||||
|
||||
#ifdef _HAS_TEX_G
|
||||
float g = tex2D(_TexG, i.uv).r;
|
||||
#ifdef _HAS_AO
|
||||
float g = tex2D(_AoMap, i.uv).r;
|
||||
#else
|
||||
float g = _Fallback.g;
|
||||
#endif
|
||||
|
||||
#ifdef _HAS_TEX_B
|
||||
float b = tex2D(_TexB, i.uv).r;
|
||||
#ifdef _HAS_DETAIL
|
||||
float b = tex2D(_DetailMap, i.uv).r;
|
||||
#else
|
||||
float b = _Fallback.b;
|
||||
#endif
|
||||
|
||||
#ifdef _HAS_TEX_A
|
||||
float a = tex2D(_TexA, i.uv).r;
|
||||
#ifdef _HAS_SMOOTHNESS
|
||||
float a = tex2D(_SmoothnessMap, i.uv).r;
|
||||
#elif _HAS_ROUGHNESS
|
||||
float a = 1.0f - tex2D(_SmoothnessMap, i.uv).r;
|
||||
#else
|
||||
float a = _Fallback.a;
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Unity.Collections;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -10,184 +10,267 @@ namespace Misaki.ArtToolEditor
|
||||
{
|
||||
internal class GenerateMaskProcessor : IAssetsProcessor
|
||||
{
|
||||
private struct PackingConfig : IDisposable
|
||||
public struct TextureSource
|
||||
{
|
||||
public Texture2D texture;
|
||||
public bool isRoughness;
|
||||
public TextureChannel channel;
|
||||
}
|
||||
|
||||
public struct GroupingConfig
|
||||
{
|
||||
public string outputDirectory;
|
||||
public NativeList<FixedString64Bytes> texturePaths;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
texturePaths.Dispose();
|
||||
}
|
||||
public List<TextureSource> textureSources;
|
||||
}
|
||||
|
||||
private class ShaderConstants
|
||||
{
|
||||
internal const string Generate_Mask_Shader_Path = "Hidden/GenerateMask";
|
||||
|
||||
internal const string Texture_R_Property = "_TexR";
|
||||
internal const string Texture_G_Property = "_TexG";
|
||||
internal const string Texture_B_Property = "_TexB";
|
||||
internal const string Texture_A_Property = "_TexA";
|
||||
internal const string Metallic_Property = "_MetallicMap";
|
||||
internal const string Ao_Property = "_AoMap";
|
||||
internal const string Detail_Property = "_DetailMap";
|
||||
internal const string Smoothness_Property = "_SmoothnessMap";
|
||||
internal const string Fallback_Property = "_Fallback";
|
||||
|
||||
internal const string Has_Texture_R_Keyword = "_HAS_TEX_R";
|
||||
internal const string Has_Texture_G_Keyword = "_HAS_TEX_G";
|
||||
internal const string Has_Texture_B_Keyword = "_HAS_TEX_B";
|
||||
internal const string Has_Texture_A_Keyword = "_HAS_TEX_A";
|
||||
internal const string Has_Metallic_Keyword = "_HAS_METALLIC";
|
||||
internal const string Has_Ao_Keyword = "_HAS_AO";
|
||||
internal const string Has_Detail_Keyword = "_HAS_DETAIL";
|
||||
internal const string Has_Smoothness_Keyword = "_HAS_SMOOTHNESS";
|
||||
internal const string Has_Roughness_Keyword = "_HAS_ROUGHNESS";
|
||||
}
|
||||
|
||||
internal const string IGNORED_GROUP_NAME = "Ignored Items";
|
||||
|
||||
private static readonly RegexOptions _regexOptions = RegexOptions.IgnoreCase | RegexOptions.Compiled;
|
||||
|
||||
public string metallicTextureRegex = ".*_metallic";
|
||||
public string aoTextureRegex = ".*_ao|.*_ambientocclusion";
|
||||
public string detailMaskTextureRegex = ".*_detailmask";
|
||||
public string smoothnessTextureRegex = ".*_smoothness";
|
||||
|
||||
public bool isFallbackToRoughness = true;
|
||||
public string roughnessTextureRegex = ".*_roughness";
|
||||
|
||||
public TextureFallbackType metallicFallbackType = TextureFallbackType.Black;
|
||||
public TextureFallbackType aoFallbackType = TextureFallbackType.White;
|
||||
public TextureFallbackType detailMaskFallbackType = TextureFallbackType.White;
|
||||
public TextureFallbackType smoothnessFallbackType = TextureFallbackType.LinearGray;
|
||||
|
||||
public string textureGroupingRegex = "^([^_]+)_";
|
||||
public string namingRegex;
|
||||
public TextureChannel namingSource;
|
||||
public string textureGroupingRegex = "^(.*)_[^_]*$";
|
||||
public string namingRegex = "(?!.*_).*";
|
||||
public TextureChannel namingSource = TextureChannel.R;
|
||||
public string replaceBy = "Mask";
|
||||
|
||||
private void GroupInputTexture(in Dictionary<string, GroupingConfig> group, Texture2D inputTexture, string outputDirectory)
|
||||
{
|
||||
string groupName;
|
||||
|
||||
var match = Regex.Match(inputTexture.name, textureGroupingRegex, _regexOptions);
|
||||
|
||||
var targetChannel = GetTextureTargetChannel(inputTexture);
|
||||
var isRoughness = false;
|
||||
if (targetChannel == TextureChannel.None && isFallbackToRoughness)
|
||||
{
|
||||
if (Regex.IsMatch(inputTexture.name, roughnessTextureRegex, _regexOptions))
|
||||
{
|
||||
targetChannel = TextureChannel.A;
|
||||
isRoughness = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match.Success || targetChannel == TextureChannel.None)
|
||||
{
|
||||
groupName = IGNORED_GROUP_NAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
groupName = match.Groups[1].Value;
|
||||
}
|
||||
|
||||
if (!group.ContainsKey(groupName))
|
||||
{
|
||||
group[groupName] = new GroupingConfig
|
||||
{
|
||||
outputDirectory = outputDirectory,
|
||||
textureSources = new List<TextureSource>(4)
|
||||
};
|
||||
}
|
||||
|
||||
var textureSource = new TextureSource()
|
||||
{
|
||||
texture = inputTexture,
|
||||
isRoughness = isRoughness,
|
||||
channel = targetChannel,
|
||||
};
|
||||
|
||||
group[groupName].textureSources.Add(textureSource);
|
||||
}
|
||||
|
||||
internal Dictionary<string, GroupingConfig> CreatePreviewGroupingResult(IEnumerable<UnityEngine.Object> sourceObjects)
|
||||
{
|
||||
var groupingResult = new Dictionary<string, GroupingConfig>(CaseInsensitiveEqualityComparer.Default);
|
||||
foreach (var sourceObject in sourceObjects)
|
||||
{
|
||||
if (sourceObject is not Texture2D texture)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GroupInputTexture(groupingResult, texture, null);
|
||||
}
|
||||
|
||||
return groupingResult;
|
||||
}
|
||||
|
||||
public void OnPreProcess(AssetsProcessContext context)
|
||||
{
|
||||
context.userData = new Dictionary<string, PackingConfig>();
|
||||
context.userData = new Dictionary<string, GroupingConfig>(CaseInsensitiveEqualityComparer.Default);
|
||||
}
|
||||
|
||||
public void OnProcess(UnityEngine.Object source, string outputDirectory, AssetsProcessContext context)
|
||||
{
|
||||
if (source is not Texture2D texture)
|
||||
if (source is not Texture2D texture ||
|
||||
context.userData is not Dictionary<string, GroupingConfig> groupConfigs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var groupConfigs = (Dictionary<string, PackingConfig>)context.userData;
|
||||
var match = Regex.Match(texture.name, textureGroupingRegex, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
if (!match.Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var groupName = match.Groups[1].Value;
|
||||
if (!groupConfigs.ContainsKey(groupName))
|
||||
{
|
||||
groupConfigs[groupName] = new PackingConfig
|
||||
{
|
||||
outputDirectory = outputDirectory,
|
||||
texturePaths = new NativeList<FixedString64Bytes>(4, Allocator.TempJob)
|
||||
};
|
||||
}
|
||||
|
||||
var config = groupConfigs[groupName];
|
||||
config.texturePaths.AddNoResize(AssetDatabase.GetAssetPath(texture));
|
||||
GroupInputTexture(groupConfigs, texture, outputDirectory);
|
||||
}
|
||||
|
||||
public void OnPostProcess(AssetsProcessContext context)
|
||||
{
|
||||
var groupConfigs = (Dictionary<string, PackingConfig>)context.userData;
|
||||
|
||||
try
|
||||
if (context.userData is not Dictionary<string, GroupingConfig> groupConfigs)
|
||||
{
|
||||
foreach (var group in groupConfigs)
|
||||
{
|
||||
var metallicTexture = FindTexture(group.Value.texturePaths, metallicTextureRegex);
|
||||
var aoTexture = FindTexture(group.Value.texturePaths, aoTextureRegex);
|
||||
var detailMaskTexture = FindTexture(group.Value.texturePaths, detailMaskTextureRegex);
|
||||
var smoothnessTexture = FindTexture(group.Value.texturePaths, smoothnessTextureRegex);
|
||||
return;
|
||||
}
|
||||
|
||||
GetTextureSizeAndName(metallicTexture, aoTexture, detailMaskTexture, out var textureSize, out var textureName);
|
||||
SetupAndBlitTexture(metallicTexture, aoTexture, detailMaskTexture, smoothnessTexture, textureSize, out var tempRT, out var material);
|
||||
foreach (var group in groupConfigs)
|
||||
{
|
||||
if (group.Key == IGNORED_GROUP_NAME)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var metallicTexture = group.Value.textureSources.FirstOrDefault(s => s.channel == TextureChannel.R);
|
||||
var aoTexture = group.Value.textureSources.FirstOrDefault(s => s.channel == TextureChannel.G);
|
||||
var detailMaskTexture = group.Value.textureSources.FirstOrDefault(s => s.channel == TextureChannel.B);
|
||||
var smoothnessTexture = group.Value.textureSources.FirstOrDefault(s => s.channel == TextureChannel.A);
|
||||
|
||||
if (!TryGetTextureSizeAndName(metallicTexture.texture, aoTexture.texture, detailMaskTexture.texture, smoothnessTexture.texture, out var textureSize, out var textureName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var tempMaterial = new Material(Shader.Find(ShaderConstants.Generate_Mask_Shader_Path));
|
||||
var tempRT = RenderTexture.GetTemporary(textureSize.x, textureSize.y, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
||||
tempRT.Create();
|
||||
|
||||
try
|
||||
{
|
||||
SetupAndBlitTexture(metallicTexture, aoTexture, detailMaskTexture, smoothnessTexture, tempRT, tempMaterial);
|
||||
|
||||
var texturePath = Path.Combine(group.Value.outputDirectory, textureName + Constants.Extensions.PNG);
|
||||
TextureHelpers.ExportRenderTextureToPNG(tempRT, texturePath);
|
||||
AssetDatabase.ImportAsset(texturePath);
|
||||
|
||||
UnityEngine.Object.DestroyImmediate(material);
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(tempMaterial);
|
||||
RenderTexture.ReleaseTemporary(tempRT);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var group in groupConfigs)
|
||||
{
|
||||
group.Value.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Texture2D FindTexture(NativeList<FixedString64Bytes> texturePaths, string metallicTextureRegex)
|
||||
private TextureChannel GetTextureTargetChannel(Texture2D texture)
|
||||
{
|
||||
foreach (var texturePath in texturePaths)
|
||||
var textureMapping = new Dictionary<Regex, TextureChannel>
|
||||
{
|
||||
if (Regex.IsMatch(texturePath.ToString(), metallicTextureRegex, RegexOptions.IgnoreCase | RegexOptions.Compiled))
|
||||
{ new Regex(metallicTextureRegex, _regexOptions), TextureChannel.R },
|
||||
{ new Regex(aoTextureRegex, _regexOptions), TextureChannel.G },
|
||||
{ new Regex(detailMaskTextureRegex, _regexOptions), TextureChannel.B },
|
||||
{ new Regex(smoothnessTextureRegex, _regexOptions), TextureChannel.A }
|
||||
};
|
||||
|
||||
foreach (var entry in textureMapping)
|
||||
{
|
||||
if (entry.Key.IsMatch(texture.name))
|
||||
{
|
||||
return AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath.ToString());
|
||||
return entry.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return TextureChannel.None;
|
||||
}
|
||||
|
||||
private void GetTextureSizeAndName(Texture2D metallicTexture, Texture2D aoTexture, Texture2D detailMaskTexture, out Vector2Int textureSize, out string textureName)
|
||||
private bool TryGetTextureSizeAndName(Texture2D textureR, Texture2D textureG, Texture2D textureB, Texture2D textureA, out Vector2Int textureSize, out string textureName)
|
||||
{
|
||||
textureSize = new Vector2Int(2048, 2048);
|
||||
textureName = string.Empty;
|
||||
switch (namingSource)
|
||||
{
|
||||
case TextureChannel.R:
|
||||
textureSize = new Vector2Int(metallicTexture.width, metallicTexture.height);
|
||||
textureName = Regex.Replace(metallicTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
break;
|
||||
return TryGetTextureDetails(textureR, out textureSize, out textureName);
|
||||
case TextureChannel.G:
|
||||
textureSize = new Vector2Int(aoTexture.width, aoTexture.height);
|
||||
textureName = Regex.Replace(aoTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
break;
|
||||
return TryGetTextureDetails(textureG, out textureSize, out textureName);
|
||||
case TextureChannel.B:
|
||||
textureSize = new Vector2Int(detailMaskTexture.width, detailMaskTexture.height);
|
||||
textureName = Regex.Replace(detailMaskTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
break;
|
||||
return TryGetTextureDetails(textureB, out textureSize, out textureName);
|
||||
case TextureChannel.A:
|
||||
textureSize = new Vector2Int(detailMaskTexture.width, detailMaskTexture.height);
|
||||
textureName = Regex.Replace(detailMaskTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
break;
|
||||
return TryGetTextureDetails(textureA, out textureSize, out textureName);
|
||||
}
|
||||
|
||||
textureSize = Vector2Int.one;
|
||||
textureName = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetupAndBlitTexture(Texture2D textureR, Texture2D textureG, Texture2D textureB, Texture2D textureA, Vector2Int textureSize, out RenderTexture tempRT, out Material material)
|
||||
private bool TryGetTextureDetails(Texture2D textureR, out Vector2Int textureSize, out string textureName)
|
||||
{
|
||||
tempRT = RenderTexture.GetTemporary(textureSize.x, textureSize.y, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
||||
tempRT.Create();
|
||||
textureSize = Vector2Int.one;
|
||||
textureName = string.Empty;
|
||||
|
||||
material = new Material(Shader.Find(ShaderConstants.Generate_Mask_Shader_Path));
|
||||
if (textureR != null)
|
||||
if (textureR == null)
|
||||
{
|
||||
material.SetTexture(ShaderConstants.Texture_R_Property, textureR);
|
||||
material.EnableKeyword(ShaderConstants.Has_Texture_R_Keyword);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (textureG != null)
|
||||
textureSize = new Vector2Int(textureR.width, textureR.height);
|
||||
textureName = Regex.Replace(textureR.name, namingRegex, replaceBy, _regexOptions);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SetupAndBlitTexture(TextureSource textureSourceR, TextureSource textureSourceG, TextureSource textureSourceB, TextureSource textureSourceA, RenderTexture tempRT, Material material)
|
||||
{
|
||||
if (textureSourceR.texture != null)
|
||||
{
|
||||
material.SetTexture(ShaderConstants.Texture_G_Property, textureG);
|
||||
material.EnableKeyword(ShaderConstants.Has_Texture_G_Keyword);
|
||||
material.SetTexture(ShaderConstants.Metallic_Property, textureSourceR.texture);
|
||||
material.EnableKeyword(ShaderConstants.Has_Metallic_Keyword);
|
||||
}
|
||||
|
||||
if (textureB != null)
|
||||
if (textureSourceG.texture != null)
|
||||
{
|
||||
material.SetTexture(ShaderConstants.Texture_B_Property, textureB);
|
||||
material.EnableKeyword(ShaderConstants.Has_Texture_B_Keyword);
|
||||
material.SetTexture(ShaderConstants.Ao_Property, textureSourceG.texture);
|
||||
material.EnableKeyword(ShaderConstants.Has_Ao_Keyword);
|
||||
}
|
||||
|
||||
if (textureA != null)
|
||||
if (textureSourceB.texture != null)
|
||||
{
|
||||
material.SetTexture(ShaderConstants.Texture_A_Property, textureA);
|
||||
material.EnableKeyword(ShaderConstants.Has_Texture_A_Keyword);
|
||||
material.SetTexture(ShaderConstants.Detail_Property, textureSourceB.texture);
|
||||
material.EnableKeyword(ShaderConstants.Has_Detail_Keyword);
|
||||
}
|
||||
|
||||
if (textureSourceA.texture != null)
|
||||
{
|
||||
material.SetTexture(ShaderConstants.Smoothness_Property, textureSourceA.texture);
|
||||
|
||||
if (textureSourceA.isRoughness)
|
||||
{
|
||||
material.EnableKeyword(ShaderConstants.Has_Roughness_Keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
material.EnableKeyword(ShaderConstants.Has_Smoothness_Keyword);
|
||||
}
|
||||
}
|
||||
|
||||
var fallback = new Vector4(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Properties;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
@@ -6,41 +7,133 @@ namespace Misaki.ArtToolEditor
|
||||
{
|
||||
internal class GenerateMaskVisualProvider : OptionsVisualProvider
|
||||
{
|
||||
public override VisualElement ContentAfterList()
|
||||
private const string Disable_String = "Disable";
|
||||
private const string Enable_String = "Enable";
|
||||
|
||||
public override void ContentAfterList(VisualElement rootVisualElement)
|
||||
{
|
||||
var root = new VisualElement();
|
||||
rootVisualElement.dataSource = processor;
|
||||
|
||||
root.Add(new HelpBox("All regex are case insensitive", HelpBoxMessageType.Info));
|
||||
rootVisualElement.Add(new HelpBox("All regex are case insensitive", HelpBoxMessageType.Info));
|
||||
|
||||
root.Add(CreateTextInputWithEnumField("Metallic Regex",
|
||||
rootVisualElement.Add(CreateTextInputWithEnumField("Metallic Regex",
|
||||
nameof(GenerateMaskProcessor.metallicTextureRegex),
|
||||
nameof(GenerateMaskProcessor.metallicFallbackType),
|
||||
TextureFallbackType.Black));
|
||||
root.Add(CreateTextInputWithEnumField("AO Regex",
|
||||
rootVisualElement.Add(CreateTextInputWithEnumField("AO Regex",
|
||||
nameof(GenerateMaskProcessor.aoTextureRegex),
|
||||
nameof(GenerateMaskProcessor.aoFallbackType),
|
||||
TextureFallbackType.White));
|
||||
root.Add(CreateTextInputWithEnumField("Detail Mask Regex",
|
||||
rootVisualElement.Add(CreateTextInputWithEnumField("Detail Mask Regex",
|
||||
nameof(GenerateMaskProcessor.detailMaskTextureRegex),
|
||||
nameof(GenerateMaskProcessor.detailMaskFallbackType),
|
||||
TextureFallbackType.White));
|
||||
root.Add(CreateTextInputWithEnumField("Smoothness Regex",
|
||||
rootVisualElement.Add(CreateTextInputWithEnumField("Smoothness Regex",
|
||||
nameof(GenerateMaskProcessor.smoothnessTextureRegex),
|
||||
nameof(GenerateMaskProcessor.smoothnessFallbackType),
|
||||
TextureFallbackType.LinearGray));
|
||||
|
||||
root.Add(CreateTextInputField("Grouping Regex",
|
||||
var roughnessFallbackDropdown = new DropdownField("Roughness Fallback", new List<string> { Disable_String, Enable_String }, Disable_String);
|
||||
roughnessFallbackDropdown.SetBinding(nameof(DropdownField.index), new DataBinding() { dataSourcePath = PropertyPath.FromName(nameof(GenerateMaskProcessor.isFallbackToRoughness)) });
|
||||
|
||||
var roughnessRegexInput = CreateTextInputField("Roughness Regex",
|
||||
nameof(GenerateMaskProcessor.roughnessTextureRegex));
|
||||
roughnessFallbackDropdown.RegisterValueChangedCallback((evt) =>
|
||||
{
|
||||
roughnessRegexInput.style.display = evt.newValue == Disable_String ? DisplayStyle.None : DisplayStyle.Flex;
|
||||
});
|
||||
|
||||
rootVisualElement.Add(roughnessFallbackDropdown);
|
||||
rootVisualElement.Add(roughnessRegexInput);
|
||||
|
||||
rootVisualElement.Add(CreateTextInputField("Grouping Regex",
|
||||
nameof(GenerateMaskProcessor.textureGroupingRegex)));
|
||||
|
||||
root.Add(CreateTextInputWithEnumField("Naming Regex",
|
||||
rootVisualElement.Add(CreateTextInputWithEnumField("Naming Regex",
|
||||
nameof(GenerateMaskProcessor.namingRegex),
|
||||
nameof(GenerateMaskProcessor.namingSource),
|
||||
TextureChannel.R));
|
||||
|
||||
root.Add(CreateTextInputField("Replace By",
|
||||
rootVisualElement.Add(CreateTextInputField("Replace By",
|
||||
nameof(GenerateMaskProcessor.replaceBy)));
|
||||
}
|
||||
|
||||
return root;
|
||||
public override void ContentOnRight(VisualElement rootVisualElement)
|
||||
{
|
||||
rootVisualElement.dataSource = processor;
|
||||
rootVisualElement.style.width = 300;
|
||||
|
||||
var container = new VisualElement();
|
||||
container.StretchToParentSize();
|
||||
|
||||
var title = new Label("Grouping Preview")
|
||||
{
|
||||
style =
|
||||
{
|
||||
marginTop = 4,
|
||||
marginBottom = 2
|
||||
}
|
||||
};
|
||||
|
||||
var groupTreeView = new TreeView()
|
||||
{
|
||||
selectionType = SelectionType.None,
|
||||
reorderable = false,
|
||||
horizontalScrollingEnabled = true,
|
||||
style =
|
||||
{
|
||||
flexGrow = 1,
|
||||
}
|
||||
};
|
||||
|
||||
var previewButton = new Button()
|
||||
{
|
||||
text = "Preview Grouping Result"
|
||||
};
|
||||
previewButton.clicked += () =>
|
||||
{
|
||||
if (processor is not GenerateMaskProcessor generateMaskProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var result = generateMaskProcessor.CreatePreviewGroupingResult(sourceObjects);
|
||||
var previewTreeRoot = new List<TreeViewItemData<string>>();
|
||||
var ignoredGroup = default(TreeViewItemData<string>);
|
||||
|
||||
var index = 0;
|
||||
foreach (var item in result)
|
||||
{
|
||||
var children = new List<TreeViewItemData<string>>(4);
|
||||
foreach (var textureSource in item.Value.textureSources)
|
||||
{
|
||||
var roughnessString = textureSource.isRoughness ? " as roughness" : string.Empty;
|
||||
children.Add(new TreeViewItemData<string>(index++, $"{textureSource.texture.name} to channel {textureSource.channel}" + roughnessString));
|
||||
}
|
||||
|
||||
var groupItem = new TreeViewItemData<string>(index++, item.Key, children);
|
||||
if (item.Key == GenerateMaskProcessor.IGNORED_GROUP_NAME)
|
||||
{
|
||||
ignoredGroup = groupItem;
|
||||
continue;
|
||||
}
|
||||
|
||||
previewTreeRoot.Add(new TreeViewItemData<string>(index++, item.Key, children));
|
||||
}
|
||||
|
||||
if (ignoredGroup.children != null)
|
||||
{
|
||||
previewTreeRoot.Add(ignoredGroup);
|
||||
}
|
||||
|
||||
groupTreeView.SetRootItems(previewTreeRoot);
|
||||
groupTreeView.Rebuild();
|
||||
};
|
||||
|
||||
container.Add(title);
|
||||
container.Add(groupTreeView);
|
||||
container.Add(previewButton);
|
||||
rootVisualElement.Add(container);
|
||||
}
|
||||
|
||||
private static VisualElement CreateTextInputField(string label, string binding)
|
||||
|
||||
Reference in New Issue
Block a user