Added GenerateMask to AssetsHelpers;

This commit is contained in:
Misaki
2024-12-26 00:44:11 +09:00
parent 509357011c
commit 2a455513bc
47 changed files with 974 additions and 297 deletions

View File

@@ -1,47 +0,0 @@
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
namespace Misaki.ArtToolEditor
{
public class CreateDecal
{
[MenuItem("Assets/Art Tools/Material Helpers/Create Decal", true)]
public static bool CreateDecalMenuValidator()
{
foreach (var selectedObject in Selection.objects)
{
if (selectedObject is not Material)
{
return false;
}
}
return true;
}
[MenuItem("Assets/Art Tools/Material Helpers/Create Decal")]
public static void CreateDecalMenu()
{
OutputOptionsWindow.ShowWindow("Decal Output Options", Selection.objects, CreateDecalInternal);
}
private static string CreateDecalInternal(Object inputObject, string outputDirectory)
{
if (inputObject is not Material mat)
{
return null;
}
var outputPath = Path.Combine(outputDirectory, mat.name + ".prefab");
var decal = AssetCreationHelpers.CreateDecal(outputPath);
mat.shader = Shader.Find(Constants.Shader.DECAL_SHADER_PATH);
decal.transform.rotation = Quaternion.Euler(90, 0, 0);
decal.GetComponent<DecalProjector>().material = mat;
return outputPath;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6b4c8332e8ca2c540bc3b8c49b91e750
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using UnityEditor;
using UnityEngine;
namespace Misaki.ArtToolEditor
{
internal class CreateDecalMenu
{
[MenuItem("Assets/Art Tools/Material Helpers/Create Decal", true)]
public static bool CreateDecalValidator()
{
foreach (var selectedObject in Selection.objects)
{
if (selectedObject is not Material)
{
return false;
}
}
return true;
}
[MenuItem("Assets/Art Tools/Material Helpers/Create Decal")]
public static void CreateDecal()
{
var createDecal = new CreateDecalMenu();
var window = EditorWindow.GetWindow<OutputOptionsWindow>(true, "Decal Output Options");
window.WithItemSource(Selection.objects);
window.RegisterProcessor<CreateDecalProcessor>();
window.InitializeAndShow();
}
}
}

View File

@@ -0,0 +1,32 @@
using System.IO;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
namespace Misaki.ArtToolEditor
{
internal class CreateDecalProcessor : IAssetsProcessor
{
public void OnPreProcess(AssetsProcessContext context)
{
}
public void OnProcess(UnityEngine.Object source, string outputDirectory, AssetsProcessContext context)
{
if (source is not Material mat)
{
return;
}
var outputPath = Path.Combine(outputDirectory, mat.name + ".prefab");
var decal = AssetCreationHelpers.CreateDecal(outputPath);
mat.shader = Shader.Find(Constants.Shader.DECAL_SHADER_PATH);
decal.transform.rotation = Quaternion.Euler(90, 0, 0);
decal.GetComponent<DecalProjector>().material = mat;
}
public void OnPostProcess(AssetsProcessContext context)
{
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 94792199a8319cd46b91c5b746992046

View File

@@ -1,52 +0,0 @@
using System.IO;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Misaki.ArtToolEditor
{
public class CreateTerrainLayer
{
private const string Terrain_Layer_Extension = ".terrainlayer";
[MenuItem("Assets/Art Tools/Material Helpers/Create Terrain Layer", true)]
public static bool CreateDecalMenuValidator()
{
foreach (var selectedObject in Selection.objects)
{
if (selectedObject is not Material)
{
return false;
}
}
return true;
}
[MenuItem("Assets/Art Tools/Material Helpers/Create Terrain Layer")]
public static void CreateDecalMenu()
{
OutputOptionsWindow.ShowWindow("Terrain Layer Output Options", Selection.objects, CreateTerrainLayerInternal);
}
private static string CreateTerrainLayerInternal(Object inputObject, string outputDirectory)
{
if (inputObject is not Material mat)
{
return null;
}
var terrainLayer = new TerrainLayer()
{
diffuseTexture = mat.GetTexture("_BaseColorMap") as Texture2D,
normalMapTexture = mat.GetTexture("_NormalMap") as Texture2D,
maskMapTexture = mat.GetTexture("_MaskMap") as Texture2D,
};
var outputPath = Path.Combine(outputDirectory, mat.name + Terrain_Layer_Extension);
AssetDatabase.CreateAsset(terrainLayer, outputPath);
return outputPath;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0210915e427912e4fad7c31d47370949
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using UnityEditor;
using UnityEngine;
namespace Misaki.ArtToolEditor
{
public class CreateTerrainLayerMenu
{
private const string Terrain_Layer_Extension = ".terrainlayer";
[MenuItem("Assets/Art Tools/Material Helpers/Create Terrain Layer", true)]
public static bool CreateTerrainLayerValidator()
{
foreach (var selectedObject in Selection.objects)
{
if (selectedObject is not Material)
{
return false;
}
}
return true;
}
[MenuItem("Assets/Art Tools/Material Helpers/Create Terrain Layer")]
public static void CreateTerrainLayer()
{
var window = EditorWindow.GetWindow<OutputOptionsWindow>(true, "Extract Materials Output Options");
window.WithItemSource(Selection.objects);
window.RegisterProcessor<CreateTerrainLayerProcessor>();
window.InitializeAndShow();
}
}
}

View File

@@ -0,0 +1,37 @@
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Misaki.ArtToolEditor
{
internal class CreateTerrainLayerProcessor : IAssetsProcessor
{
private const string Terrain_Layer_Extension = ".terrainlayer";
public void OnPreProcess(AssetsProcessContext context)
{
}
public void OnProcess(UnityEngine.Object source, string outputDirectory, AssetsProcessContext context)
{
if (source is not Material mat)
{
return;
}
var terrainLayer = new TerrainLayer()
{
diffuseTexture = mat.GetTexture("_BaseColorMap") as Texture2D,
normalMapTexture = mat.GetTexture("_NormalMap") as Texture2D,
maskMapTexture = mat.GetTexture("_MaskMap") as Texture2D,
};
var outputPath = Path.Combine(outputDirectory, mat.name + Terrain_Layer_Extension);
AssetDatabase.CreateAsset(terrainLayer, outputPath);
}
public void OnPostProcess(AssetsProcessContext context)
{
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c0d5979c585023248ba3c56e7936097f

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c61caf20baa490d44a8d447822f5225d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
using UnityEditor;
namespace Misaki.ArtToolEditor
{
public class ExtractMaterialsMenu
{
private const string Material_Extension = ".mat";
[MenuItem("Assets/Art Tools/Mesh Helpers/Extract Materials", true)]
public static bool ExtractMaterialsValidator()
{
foreach (var selectedObject in Selection.objects)
{
var assetImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(selectedObject));
if (assetImporter is not ModelImporter)
{
return false;
}
}
return true;
}
[MenuItem("Assets/Art Tools/Mesh Helpers/Extract Materials")]
public static void ExtractMaterials()
{
var window = EditorWindow.GetWindow<OutputOptionsWindow>(true, "Extract Materials Output Options");
window.WithItemSource(Selection.objects);
window.RegisterVisualProvider<ExtractMaterialsVisualProvider>();
window.RegisterProcessor<ExtractMaterialsProcessor>();
window.InitializeAndShow();
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c21cf688d17737c4d91cec961bfce976

View File

@@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Misaki.ArtToolEditor
{
internal class ExtractMaterialsProcessor : IAssetsProcessor
{
private const string Material_Extension = ".mat";
public bool useMaterialRemap = false;
public ModelImporterMaterialLocation materialLocation = ModelImporterMaterialLocation.InPrefab;
public ModelImporterMaterialName materialRemapNamingOption = ModelImporterMaterialName.BasedOnMaterialName;
public ModelImporterMaterialSearch materialRemapSearchOption = ModelImporterMaterialSearch.RecursiveUp;
public void OnPreProcess(AssetsProcessContext context)
{
context.userData = new HashSet<string>();
}
public void OnProcess(Object source, string outputDirectory, AssetsProcessContext context)
{
var assetsToReload = (HashSet<string>)context.userData;
var assetImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(source));
if (assetImporter is not ModelImporter modelImporter)
{
return;
}
if (useMaterialRemap)
{
modelImporter.materialLocation = materialLocation;
modelImporter.SearchAndRemapMaterials(materialRemapNamingOption, materialRemapSearchOption);
modelImporter.SaveAndReimport();
return;
}
else
{
var materials = AssetDatabase.LoadAllAssetsAtPath(modelImporter.assetPath).Where(x => x.GetType() == typeof(Material));
foreach (var material in materials)
{
var newAssetPath = Path.Combine(outputDirectory, material.name) + Material_Extension;
newAssetPath = AssetDatabase.GenerateUniqueAssetPath(newAssetPath);
var error = AssetDatabase.ExtractAsset(material, newAssetPath);
if (string.IsNullOrEmpty(error))
{
assetsToReload.Add(modelImporter.assetPath);
}
}
}
}
public void OnPostProcess(AssetsProcessContext context)
{
var assetsToReload = (HashSet<string>)context.userData;
foreach (var assetPath in assetsToReload)
{
if (string.IsNullOrEmpty(assetPath))
{
return;
}
AssetDatabase.WriteImportSettingsIfDirty(assetPath);
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ae6fdf97993458e47add233725aecaa4

View File

@@ -0,0 +1,66 @@
using System.Collections.Generic;
using Unity.Properties;
using UnityEditor;
using UnityEngine.UIElements;
namespace Misaki.ArtToolEditor
{
internal class ExtractMaterialsVisualProvider : OptionsVisualProvider
{
internal override VisualElement ContentAfterList()
{
var root = new VisualElement();
var materialRemapOptionContainer = new VisualElement()
{
style =
{
display = DisplayStyle.None,
}
};
var useMaterialRemapField = new DropdownField("Use Material Remap", new List<string> { "False", "True" }, "False");
useMaterialRemapField.SetBinding(
nameof(DropdownField.index),
new DataBinding()
{
dataSourcePath = PropertyPath.FromName(nameof(ExtractMaterialsProcessor.useMaterialRemap))
});
useMaterialRemapField.RegisterValueChangedCallback(evt =>
{
materialRemapOptionContainer.style.display = evt.newValue == "True" ? DisplayStyle.Flex : DisplayStyle.None;
});
var materialLocationField = new EnumField("Location", ModelImporterMaterialLocation.External);
materialLocationField.SetBinding(
nameof(EnumField.value),
new DataBinding()
{
dataSourcePath = PropertyPath.FromName(nameof(ExtractMaterialsProcessor.materialLocation))
});
var materialRemapNamingOptionField = new EnumField("Naming Option", ModelImporterMaterialName.BasedOnTextureName);
materialRemapNamingOptionField.SetBinding(
nameof(EnumField.value),
new DataBinding()
{
dataSourcePath = PropertyPath.FromName(nameof(ExtractMaterialsProcessor.materialRemapNamingOption))
});
var materialRemapSearchOptionField = new EnumField("Search Option", ModelImporterMaterialSearch.Local);
materialRemapSearchOptionField.SetBinding(
nameof(EnumField.value),
new DataBinding()
{
dataSourcePath = PropertyPath.FromName(nameof(ExtractMaterialsProcessor.materialRemapSearchOption))
});
materialRemapOptionContainer.Add(materialLocationField);
materialRemapOptionContainer.Add(materialRemapNamingOptionField);
materialRemapOptionContainer.Add(materialRemapSearchOptionField);
root.Add(useMaterialRemapField);
root.Add(materialRemapOptionContainer);
return root;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 74347edff42a5cd47a6a5d4989210334

View File

@@ -1,123 +0,0 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace Misaki.ArtToolEditor
{
public class RemapMaterials
{
private const string Material_Extension = ".mat";
private static bool _useMaterialRemap = false;
private static ModelImporterMaterialLocation _materialLocation = ModelImporterMaterialLocation.InPrefab;
private static ModelImporterMaterialName _materialRemapNamingOption = ModelImporterMaterialName.BasedOnMaterialName;
private static ModelImporterMaterialSearch _materialRemapSearchOption = ModelImporterMaterialSearch.RecursiveUp;
[MenuItem("Assets/Art Tools/Mesh Helpers/Extract Materials", true)]
public static bool CreateDecalMenuValidator()
{
foreach (var selectedObject in Selection.objects)
{
var assetImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(selectedObject));
if (assetImporter is not ModelImporter)
{
return false;
}
}
return true;
}
[MenuItem("Assets/Art Tools/Mesh Helpers/Extract Materials")]
public static void CreateDecalMenu()
{
var window = EditorWindow.GetWindow<OutputOptionsWindow>(true, "Extract Materials Output Options");
window.WithSource(Selection.objects);
window.WithContentBeforeButton(() =>
{
var root = new VisualElement();
var materialRemapOptionContainer = new VisualElement()
{
style =
{
display = DisplayStyle.None,
}
};
var useMaterialRemap = new DropdownField("Use Material Remap", new List<string> { "False", "True" }, "False");
useMaterialRemap.RegisterValueChangedCallback(evt =>
{
_useMaterialRemap = evt.newValue == "True";
materialRemapOptionContainer.style.display = _useMaterialRemap ? DisplayStyle.Flex : DisplayStyle.None;
});
var materialLocation = new EnumField("Material Location", _materialLocation);
materialLocation.RegisterValueChangedCallback(evt => _materialLocation = (ModelImporterMaterialLocation)evt.newValue);
var materialRemapNamingOption = new EnumField("Material Naming Option", _materialRemapNamingOption);
materialRemapNamingOption.RegisterValueChangedCallback(evt => _materialRemapNamingOption = (ModelImporterMaterialName)evt.newValue);
var materialRemapSearchOption = new EnumField("Material Search Option", _materialRemapSearchOption);
materialRemapSearchOption.RegisterValueChangedCallback(evt => _materialRemapSearchOption = (ModelImporterMaterialSearch)evt.newValue);
materialRemapOptionContainer.Add(materialLocation);
materialRemapOptionContainer.Add(materialRemapNamingOption);
materialRemapOptionContainer.Add(materialRemapSearchOption);
root.Add(useMaterialRemap);
root.Add(materialRemapOptionContainer);
return root;
});
window.WithOutput(ExtractMaterialsInternal);
window.WithPostOutput(ExtractMaterialsPostInternal);
window.ShowUtility();
}
private static string ExtractMaterialsInternal(Object inputObject, string outputDirectory)
{
var assetImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(inputObject));
if (assetImporter is not ModelImporter modelImporter)
{
return null;
}
if (_useMaterialRemap)
{
modelImporter.materialLocation = _materialLocation;
modelImporter.SearchAndRemapMaterials(_materialRemapNamingOption, _materialRemapSearchOption);
modelImporter.SaveAndReimport();
return null;
}
else
{
var materials = AssetDatabase.LoadAllAssetsAtPath(modelImporter.assetPath).Where(x => x.GetType() == typeof(Material));
foreach (var material in materials)
{
var newAssetPath = Path.Combine(outputDirectory, material.name) + Material_Extension;
newAssetPath = AssetDatabase.GenerateUniqueAssetPath(newAssetPath);
AssetDatabase.ExtractAsset(material, newAssetPath);
}
return modelImporter.assetPath;
}
}
private static void ExtractMaterialsPostInternal(string assetPath)
{
if (string.IsNullOrEmpty(assetPath))
{
return;
}
AssetDatabase.WriteImportSettingsIfDirty(assetPath);
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 9cc9f1a0be83aa444884c32f825c5303

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c45ddbe7c1e4d6246ac1957c1e88d2ea
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 819df015e3521a3479dfefbf5bed26b2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using UnityEditor;
using UnityEngine;
namespace Misaki.ArtToolEditor
{
internal class GenerateMaskMenu
{
[MenuItem("Assets/Art Tools/Texture Helpers/Generate Mask", true)]
public static bool GenerateMaskValidator()
{
foreach (var selectedObject in Selection.objects)
{
if (selectedObject is not Texture2D)
{
return false;
}
}
return true;
}
[MenuItem("Assets/Art Tools/Texture Helpers/Generate Mask")]
public static void GenerateMask()
{
var window = EditorWindow.GetWindow<OutputOptionsWindow>(true, "Generate Mask Output Options");
window.WithItemSource(Selection.objects);
window.RegisterVisualProvider<GenerateMaskVisualProvider>();
window.RegisterProcessor<GenerateMaskProcessor>();
window.InitializeAndShow();
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 353f02bb002aafd419d5472f331069a9

View File

@@ -0,0 +1,227 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using Unity.Collections;
using UnityEditor;
using UnityEngine;
namespace Misaki.ArtToolEditor
{
internal class GenerateMaskProcessor : IAssetsProcessor
{
private struct PackingConfig : IDisposable
{
public string outputDirectory;
public NativeList<FixedString64Bytes> texturePaths;
public void Dispose()
{
texturePaths.Dispose();
}
}
private class Constants
{
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 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 Png_Extension = ".png";
}
public string metallicTextureRegex = ".*_metallic";
public string aoTextureRegex = ".*_ao|.*_ambientocclusion";
public string detailMaskTextureRegex = ".*_detailmask";
public string smoothnessTextureRegex = ".*_smoothness";
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 TextureNamingSourceType namingSource;
public string replaceBy = "Mask";
public void OnPreProcess(AssetsProcessContext context)
{
context.userData = new Dictionary<string, PackingConfig>();
}
public void OnProcess(UnityEngine.Object source, string outputDirectory, AssetsProcessContext context)
{
if (source is not Texture2D texture)
{
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));
}
public void OnPostProcess(AssetsProcessContext context)
{
var groupConfigs = (Dictionary<string, PackingConfig>)context.userData;
try
{
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);
GetTextureSizeAndName(metallicTexture, aoTexture, detailMaskTexture, out var textureSize, out var textureName);
SetupAndBlitTexture(metallicTexture, aoTexture, detailMaskTexture, smoothnessTexture, textureSize, out var tempRT, out var material);
ExportTextureToPNG(group, textureName, tempRT);
UnityEngine.Object.DestroyImmediate(material);
tempRT.Release();
}
}
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)
{
foreach (var texturePath in texturePaths)
{
if (Regex.IsMatch(texturePath.ToString(), metallicTextureRegex, RegexOptions.IgnoreCase | RegexOptions.Compiled))
{
return AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath.ToString());
}
}
return null;
}
private void GetTextureSizeAndName(Texture2D metallicTexture, Texture2D aoTexture, Texture2D detailMaskTexture, out Vector2Int textureSize, out string textureName)
{
textureSize = new Vector2Int(2048, 2048);
textureName = string.Empty;
switch (namingSource)
{
case TextureNamingSourceType.R:
textureSize = new Vector2Int(metallicTexture.width, metallicTexture.height);
textureName = Regex.Replace(metallicTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
break;
case TextureNamingSourceType.G:
textureSize = new Vector2Int(aoTexture.width, aoTexture.height);
textureName = Regex.Replace(aoTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
break;
case TextureNamingSourceType.B:
textureSize = new Vector2Int(detailMaskTexture.width, detailMaskTexture.height);
textureName = Regex.Replace(detailMaskTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
break;
case TextureNamingSourceType.A:
textureSize = new Vector2Int(detailMaskTexture.width, detailMaskTexture.height);
textureName = Regex.Replace(detailMaskTexture.name, namingRegex, replaceBy, RegexOptions.IgnoreCase | RegexOptions.Compiled);
break;
}
}
private void SetupAndBlitTexture(Texture2D textureR, Texture2D textureG, Texture2D textureB, Texture2D textureA, Vector2Int textureSize, out RenderTexture tempRT, out Material material)
{
tempRT = RenderTexture.GetTemporary(textureSize.x, textureSize.y, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
tempRT.Create();
material = new Material(Shader.Find(Constants.Generate_Mask_Shader_Path));
if (textureR != null)
{
material.SetTexture(Constants.Texture_R_Property, textureR);
material.EnableKeyword(Constants.Has_Texture_R_Keyword);
}
if (textureG != null)
{
material.SetTexture(Constants.Texture_G_Property, textureG);
material.EnableKeyword(Constants.Has_Texture_G_Keyword);
}
if (textureB != null)
{
material.SetTexture(Constants.Texture_B_Property, textureB);
material.EnableKeyword(Constants.Has_Texture_B_Keyword);
}
if (textureA != null)
{
material.SetTexture(Constants.Texture_A_Property, textureA);
material.EnableKeyword(Constants.Has_Texture_A_Keyword);
}
var fallback = new Vector4(
GetFallbackValue(metallicFallbackType),
GetFallbackValue(aoFallbackType),
GetFallbackValue(detailMaskFallbackType),
GetFallbackValue(smoothnessFallbackType)
);
material.SetVector("_Fallback", fallback);
Graphics.Blit(null, tempRT, material);
}
private static void ExportTextureToPNG(KeyValuePair<string, PackingConfig> group, string textureName, RenderTexture tempRT)
{
var exportTexture = new Texture2D(tempRT.width, tempRT.height, TextureFormat.RGBA32, false);
exportTexture.ReadPixels(new Rect(0, 0, tempRT.width, tempRT.height), 0, 0);
exportTexture.Apply();
var bytes = exportTexture.EncodeToPNG();
var path = Path.Combine(group.Value.outputDirectory, textureName + Constants.Png_Extension);
File.WriteAllBytes(path, bytes);
UnityEngine.Object.DestroyImmediate(exportTexture);
AssetDatabase.ImportAsset(path);
}
private float GetFallbackValue(TextureFallbackType type)
{
return type switch
{
TextureFallbackType.White => 1.0f,
TextureFallbackType.LinearGray => 0.73f,
TextureFallbackType.Gray => 0.5f,
TextureFallbackType.Black => 0.0f,
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 94ec75a6994a6db41b574c5bebf56670

View File

@@ -0,0 +1,86 @@
using System;
using Unity.Properties;
using UnityEngine.UIElements;
namespace Misaki.ArtToolEditor
{
internal class GenerateMaskVisualProvider : OptionsVisualProvider
{
internal override VisualElement ContentAfterList()
{
var root = new VisualElement();
root.Add(new HelpBox("All regex are case insensitive", HelpBoxMessageType.Info));
root.Add(CreateTextInputWithEnumField("Metallic Regex",
nameof(GenerateMaskProcessor.metallicTextureRegex),
nameof(GenerateMaskProcessor.metallicFallbackType),
TextureFallbackType.Black));
root.Add(CreateTextInputWithEnumField("AO Regex",
nameof(GenerateMaskProcessor.aoTextureRegex),
nameof(GenerateMaskProcessor.aoFallbackType),
TextureFallbackType.White));
root.Add(CreateTextInputWithEnumField("Detail Mask Regex",
nameof(GenerateMaskProcessor.detailMaskTextureRegex),
nameof(GenerateMaskProcessor.detailMaskFallbackType),
TextureFallbackType.White));
root.Add(CreateTextInputWithEnumField("Smoothness Regex",
nameof(GenerateMaskProcessor.smoothnessTextureRegex),
nameof(GenerateMaskProcessor.smoothnessFallbackType),
TextureFallbackType.LinearGray));
root.Add(CreateTextInputField("Grouping Regex",
nameof(GenerateMaskProcessor.textureGroupingRegex)));
root.Add(CreateTextInputWithEnumField("Naming Regex",
nameof(GenerateMaskProcessor.namingRegex),
nameof(GenerateMaskProcessor.namingSource),
TextureNamingSourceType.R));
root.Add(CreateTextInputField("Replace By",
nameof(GenerateMaskProcessor.replaceBy)));
return root;
}
private VisualElement CreateTextInputField(string label, string binding)
{
var textField = new TextField(label);
textField.SetBinding(nameof(TextField.value), new DataBinding() { dataSourcePath = PropertyPath.FromName(binding) });
return textField;
}
private VisualElement CreateTextInputWithEnumField(string label, string textInputBinding, string enumBinding, Enum defaultEnumValue)
{
var root = new VisualElement()
{
style =
{
flexDirection = FlexDirection.Row,
}
};
var textField = new TextField(label)
{
style =
{
flexGrow = 1,
}
};
textField.SetBinding(nameof(TextField.value), new DataBinding() { dataSourcePath = PropertyPath.FromName(textInputBinding) });
var enumField = new EnumField(defaultEnumValue)
{
style =
{
width = 100,
}
};
enumField.SetBinding(nameof(EnumField.value), new DataBinding() { dataSourcePath = PropertyPath.FromName(enumBinding) });
root.Add(textField);
root.Add(enumField);
return root;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 591e3f52dbd05794395f0918f2b19557

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7d55aad869a0f394abc5a531318a7b7d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,85 @@
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"
}
SubShader
{
Cull Off
ZWrite Off
ZTest Always
Pass
{
CGPROGRAM
#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
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _TexR;
sampler2D _TexG;
sampler2D _TexB;
sampler2D _TexA;
float4 _Fallback;
float4 frag (v2f i) : SV_Target
{
#ifdef _HAS_TEX_R
float r = tex2D(_TexR, i.uv).r;
#else
float r = _Fallback.r;
#endif
#ifdef _HAS_TEX_G
float g = tex2D(_TexG, i.uv).r;
#else
float g = _Fallback.g;
#endif
#ifdef _HAS_TEX_B
float b = tex2D(_TexB, i.uv).r;
#else
float b = _Fallback.b;
#endif
#ifdef _HAS_TEX_A
float a = tex2D(_TexA, i.uv).r;
#else
float a = _Fallback.a;
#endif
return float4(r, g, b, a);
}
ENDCG
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 132046c0498c1ab49aa91453b6ae2766
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant: