Skip to content

Commit ebaf2ed

Browse files
committed
lookdev: Add material-from-texture generator.
1 parent 2343a28 commit ebaf2ed

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// MaterialFromTextures.cs
2+
// Place this script inside an "Editor" folder in a Unity project running **HDRP**.
3+
// Adds **Assets ▸ Create ▸ Generate HDRP Materials From Selection** to the Project View
4+
// whenever one or more **Texture2D** assets are selected. It converts those textures
5+
// into HDRP/Lit materials based on suffixes:
6+
// <BaseName>_BaseMap.<ext> (required)
7+
// <BaseName>_MaskMap.<ext> (optional)
8+
// <BaseName>_Normal.<ext> (optional)
9+
// The resulting material **<BaseName>.mat** is written next to its BaseMap texture.
10+
11+
using UnityEditor;
12+
using UnityEngine;
13+
using System.IO;
14+
using System.Collections.Generic;
15+
16+
namespace EditorTools
17+
{
18+
public static class MaterialFromTextures
19+
{
20+
private const string BaseSuffix = "BaseMap";
21+
private const string MaskSuffix = "MaskMap";
22+
private const string NormalSuffix = "Normal";
23+
24+
//------------------------------------------------------------------
25+
// Menu item
26+
//------------------------------------------------------------------
27+
[MenuItem("Assets/Create/Generate HDRP Materials From Selection", priority = 2050)]
28+
private static void Generate()
29+
{
30+
var selectedTextures = Selection.GetFiltered<Texture2D>(SelectionMode.Assets);
31+
if (selectedTextures.Length == 0) {
32+
EditorUtility.DisplayDialog("Generate HDRP Materials", "Select one or more texture assets first.", "OK");
33+
return;
34+
}
35+
36+
// Build groups keyed by base name (local dictionary)
37+
var groups = new Dictionary<string, MaterialTextures>();
38+
39+
foreach (var tex in selectedTextures) {
40+
var path = AssetDatabase.GetAssetPath(tex);
41+
var fileName = Path.GetFileNameWithoutExtension(path);
42+
43+
AddTextureToGroup(fileName, tex, path, BaseSuffix, groups, (g, t) => g.baseMap = t, (g, p) => g.baseFolder = Path.GetDirectoryName(p));
44+
AddTextureToGroup(fileName, tex, path, MaskSuffix, groups, (g, t) => g.maskMap = t);
45+
AddTextureToGroup(fileName, tex, path, NormalSuffix, groups, (g, t) => g.normalMap = t);
46+
}
47+
48+
var hdrpShader = Shader.Find("HDRP/Lit");
49+
if (hdrpShader == null) {
50+
EditorUtility.DisplayDialog("Generate HDRP Materials", "Shader 'HDRP/Lit' not found. Is HDRP installed?", "OK");
51+
return;
52+
}
53+
54+
var created = 0;
55+
foreach (var kvp in groups) {
56+
57+
var baseName = kvp.Key;
58+
var maps = kvp.Value;
59+
if (maps.baseMap == null || string.IsNullOrEmpty(maps.baseFolder)) {
60+
continue; // Need at least a BaseMap and its location
61+
}
62+
63+
var matPath = Path.Combine(maps.baseFolder, baseName + ".mat").Replace("\\", "/");
64+
var mat = AssetDatabase.LoadAssetAtPath<Material>(matPath);
65+
var isNew = mat == null;
66+
67+
if (isNew) {
68+
mat = new Material(hdrpShader);
69+
AssetDatabase.CreateAsset(mat, matPath);
70+
created++;
71+
}
72+
73+
AssignHDRPTextures(mat, maps);
74+
EditorUtility.SetDirty(mat);
75+
}
76+
77+
AssetDatabase.SaveAssets();
78+
AssetDatabase.Refresh();
79+
EditorUtility.DisplayDialog("Generate HDRP Materials", $"Created/updated {created} material(s).", "OK");
80+
}
81+
82+
//------------------------------------------------------------------
83+
// Validation – show the menu item only when textures are selected
84+
//------------------------------------------------------------------
85+
[MenuItem("Assets/Create/Generate HDRP Materials From Selection", validate = true)]
86+
private static bool ValidateGenerate() => Selection.GetFiltered<Texture2D>(SelectionMode.Assets).Length > 0;
87+
88+
//------------------------------------------------------------------
89+
// Helpers
90+
//------------------------------------------------------------------
91+
private static void AddTextureToGroup(string fileName,
92+
Texture2D tex,
93+
string path,
94+
string suffix,
95+
Dictionary<string, MaterialTextures> groups,
96+
System.Action<MaterialTextures, Texture2D> texSetter,
97+
System.Action<MaterialTextures, string> folderSetter = null)
98+
{
99+
if (!fileName.EndsWith(suffix)) return;
100+
101+
var baseName = TrimSuffix(fileName, suffix);
102+
var group = GetOrCreateGroup(groups, baseName);
103+
104+
texSetter(group, tex);
105+
folderSetter?.Invoke(group, path);
106+
}
107+
108+
private static string TrimSuffix(string name, string suffix) => name[..^suffix.Length].TrimEnd('_', ' ', '-');
109+
110+
private class MaterialTextures
111+
{
112+
public Texture2D baseMap;
113+
public Texture2D maskMap;
114+
public Texture2D normalMap;
115+
public string baseFolder;
116+
}
117+
118+
private static MaterialTextures GetOrCreateGroup(Dictionary<string, MaterialTextures> dict, string baseName)
119+
{
120+
if (!dict.TryGetValue(baseName, out var g)) {
121+
g = new MaterialTextures();
122+
dict[baseName] = g;
123+
}
124+
125+
return g;
126+
}
127+
128+
// Assign maps to an HDRP/Lit material
129+
private static void AssignHDRPTextures(Material mat, MaterialTextures m)
130+
{
131+
if (m.baseMap && mat.HasProperty("_BaseColorMap")) mat.SetTexture("_BaseColorMap", m.baseMap);
132+
if (m.maskMap && mat.HasProperty("_MaskMap")) mat.SetTexture("_MaskMap", m.maskMap);
133+
if (m.normalMap && mat.HasProperty("_NormalMap")) mat.SetTexture("_NormalMap", m.normalMap);
134+
}
135+
}
136+
}

LookDev~/Assets/Editor/MaterialFromTextures.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)