Files
2026-11-01 23:39:55 +02:00

205 lines
7.1 KiB
C#

using System.IO;
using UnityEditor;
using UnityEngine;
//-----------------------------------------------------------------------
// Author: Colby-O
// File: PSXMaterialFactory.cs
//-----------------------------------------------------------------------
namespace ColbyO.VNTG.PSX.Editor
{
public static class PSXMaterialFactory
{
private const string PSX_SHADER_NAME = "VNTG/PSXMaster_URP";
private const string PSX_TERRIAN_SHADER_NAME = "VNTG/PSXTerrian_URP";
private const string PSX_WATER_SHADER_NAME = "VNTG/PSXWater_URP";
private const string PSX_DECAL_SHADER_NAME = "VNTG/PSXDecal_URP";
private const string PSX_SKYBOX_SHADER_NAME = "VNTG/PSXSkybox_URP";
[MenuItem("Assets/Create/VNTG/PSX Material", false)]
public static void CreatePSXMaterial()
{
CreateMateral(PSX_SHADER_NAME);
}
#if UNITY_6000_3_OR_NEWER
[MenuItem("Assets/Create/VNTG/PSX Terrian Material", false)]
public static void CreateTerrianMaterial()
{
CreateMateral(PSX_TERRIAN_SHADER_NAME);
}
#endif
[MenuItem("Assets/Create/VNTG/PSX Water Material", false)]
public static void CreateWaterMaterial()
{
CreateMateral(PSX_WATER_SHADER_NAME);
}
[MenuItem("Assets/Create/VNTG/PSX Decal Material", false)]
public static void CreateDecalMaterial()
{
CreateMateral(PSX_DECAL_SHADER_NAME);
}
[MenuItem("Assets/Create/VNTG/PSX Skybox Material", false)]
public static void CreateSkyboxMaterial()
{
CreateMateral(PSX_SKYBOX_SHADER_NAME);
}
[MenuItem("Assets/VNTG/Convert to PSX Material", false)]
public static void ConvertToPSXMaterial()
{
Material selectedMaterial = Selection.activeObject as Material;
Shader psxShader = Shader.Find(PSX_SHADER_NAME);
if (psxShader == null)
{
Debug.LogError($"PSXFactory: Could not find shader: '{PSX_SHADER_NAME}'.");
return;
}
string originalShaderName = selectedMaterial.shader.name;
bool isLit = false;
if (originalShaderName.Contains("Lit") && !originalShaderName.Contains("Unlit"))
{
isLit = true;
}
string texturePropertyName = "_MainTex";
Vector2 originalTiling = Vector2.one;
Vector2 originalOffset = Vector2.zero;
if (selectedMaterial.HasProperty(texturePropertyName))
{
originalTiling = selectedMaterial.GetTextureScale(texturePropertyName);
originalOffset = selectedMaterial.GetTextureOffset(texturePropertyName);
}
float originalCutoff = 0.5f;
bool isAlphaClipEnabled = false;
if (selectedMaterial.HasProperty("_Cutoff"))
{
originalCutoff = selectedMaterial.GetFloat("_Cutoff");
}
if (selectedMaterial.IsKeywordEnabled("_ALPHATEST_ON"))
{
isAlphaClipEnabled = true;
}
bool receiveShadows = true;
if (selectedMaterial.IsKeywordEnabled("_RECEIVE_SHADOWS_OFF"))
{
receiveShadows = false;
}
else if (selectedMaterial.HasProperty("_ReceiveShadows"))
{
receiveShadows = selectedMaterial.GetFloat("_ReceiveShadows") == 1.0f;
}
float originalSmoothness = 0.0f;
if (selectedMaterial.HasProperty("_Smoothness"))
{
originalSmoothness = selectedMaterial.GetFloat("_Smoothness");
}
else if (selectedMaterial.HasProperty("_Glossiness"))
{
originalSmoothness = selectedMaterial.GetFloat("_Glossiness");
}
float originalMetallic = 0.0f;
if (selectedMaterial.HasProperty("_Metallic"))
{
originalMetallic = selectedMaterial.GetFloat("_Metallic");
}
Undo.RecordObject(selectedMaterial, "Convert Material to PSX");
selectedMaterial.shader = psxShader;
if (isLit)
{
selectedMaterial.SetLightingMethod(PSXLightingMethod.Lit);
selectedMaterial.SetFloat("_UseSpecular", 1.0f);
selectedMaterial.SetFloat("_Smoothness", originalSmoothness);
selectedMaterial.SetFloat("_Metalness", originalMetallic);
}
else
{
selectedMaterial.SetLightingMethod(PSXLightingMethod.Unlit);
}
selectedMaterial.SetVector("_Tiling", originalTiling);
selectedMaterial.SetVector("_Offset", originalOffset);
selectedMaterial.SetFloat("_AlphaClipThreshold", isAlphaClipEnabled ? originalCutoff : 0.0f);
selectedMaterial.SetFloat("_EnableShadows", receiveShadows ? 1.0f : 0.0f);
EditorUtility.SetDirty(selectedMaterial);
AssetDatabase.SaveAssets();
Debug.Log($"Successfully converted '{selectedMaterial.name}' to PSX shader.", selectedMaterial);
}
[MenuItem("Assets/VNTG/Convert to PSX Material", true)]
public static bool ValidateConvertToPSXMaterial()
{
if (Selection.activeObject is Material mat)
{
return mat.shader.name != PSX_SHADER_NAME;
}
return false;
}
private static string GetDefaultMaterialName(string shaderName)
{
return shaderName switch
{
"VNTG/PSXMaster_URP" => "New PSX Material",
"VNTG/PSXTerrian_URP" => "New PSX Terrain Material",
"VNTG/PSXWater_URP" => "New PSX Water Material",
"VNTG/PSXDecal_URP" => "New PSX Decal Material",
"VNTG/PSXSkybox_URP" => "New PSX Skybox Material",
_ => "New Material"
};
}
private static void CreateMateral(string shaderName)
{
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
if (string.IsNullOrEmpty(path))
{
path = "Assets";
}
else if (!Directory.Exists(path))
{
path = Path.GetDirectoryName(path);
}
string fullPath = Path.Combine(path, $"{GetDefaultMaterialName(shaderName)}.mat");
fullPath = AssetDatabase.GenerateUniqueAssetPath(fullPath);
Shader psxShader = Shader.Find(shaderName);
if (psxShader == null)
{
Debug.LogError($"PSXFactory: Could not find shader: '{shaderName}'. Please check the shader path string in the script.");
return;
}
Material newMat = new Material(psxShader);
AssetDatabase.CreateAsset(newMat, fullPath);
AssetDatabase.SaveAssets();
EditorUtility.FocusProjectWindow();
Selection.activeObject = newMat;
}
}
}