|
| 1 | +using System; |
| 2 | +using System.IO; |
| 3 | +using Newtonsoft.Json.Linq; |
| 4 | +using NUnit.Framework; |
| 5 | +using UnityEditor; |
| 6 | +using UnityEngine; |
| 7 | +using MCPForUnity.Editor.Tools; |
| 8 | + |
| 9 | +namespace MCPForUnityTests.Editor.Tools |
| 10 | +{ |
| 11 | + public class MaterialDirectPropertiesTests |
| 12 | + { |
| 13 | + private const string TempRoot = "Assets/Temp/MaterialDirectPropertiesTests"; |
| 14 | + private string _matPath; |
| 15 | + private string _baseMapPath; |
| 16 | + private string _normalMapPath; |
| 17 | + private string _occlusionMapPath; |
| 18 | + |
| 19 | + [SetUp] |
| 20 | + public void SetUp() |
| 21 | + { |
| 22 | + if (!AssetDatabase.IsValidFolder("Assets/Temp")) |
| 23 | + { |
| 24 | + AssetDatabase.CreateFolder("Assets", "Temp"); |
| 25 | + } |
| 26 | + if (!AssetDatabase.IsValidFolder(TempRoot)) |
| 27 | + { |
| 28 | + AssetDatabase.CreateFolder("Assets/Temp", "MaterialDirectPropertiesTests"); |
| 29 | + } |
| 30 | + |
| 31 | + string guid = Guid.NewGuid().ToString("N"); |
| 32 | + _matPath = $"{TempRoot}/DirectProps_{guid}.mat"; |
| 33 | + _baseMapPath = $"{TempRoot}/TexBase_{guid}.asset"; |
| 34 | + _normalMapPath = $"{TempRoot}/TexNormal_{guid}.asset"; |
| 35 | + _occlusionMapPath = $"{TempRoot}/TexOcc_{guid}.asset"; |
| 36 | + |
| 37 | + // Clean any leftovers just in case |
| 38 | + TryDeleteAsset(_matPath); |
| 39 | + TryDeleteAsset(_baseMapPath); |
| 40 | + TryDeleteAsset(_normalMapPath); |
| 41 | + TryDeleteAsset(_occlusionMapPath); |
| 42 | + |
| 43 | + AssetDatabase.Refresh(); |
| 44 | + } |
| 45 | + |
| 46 | + [TearDown] |
| 47 | + public void TearDown() |
| 48 | + { |
| 49 | + TryDeleteAsset(_matPath); |
| 50 | + TryDeleteAsset(_baseMapPath); |
| 51 | + TryDeleteAsset(_normalMapPath); |
| 52 | + TryDeleteAsset(_occlusionMapPath); |
| 53 | + AssetDatabase.Refresh(); |
| 54 | + } |
| 55 | + |
| 56 | + private static void TryDeleteAsset(string path) |
| 57 | + { |
| 58 | + if (string.IsNullOrEmpty(path)) return; |
| 59 | + if (AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path) != null) |
| 60 | + { |
| 61 | + AssetDatabase.DeleteAsset(path); |
| 62 | + } |
| 63 | + var abs = Path.Combine(Directory.GetCurrentDirectory(), path); |
| 64 | + try |
| 65 | + { |
| 66 | + if (File.Exists(abs)) File.Delete(abs); |
| 67 | + if (File.Exists(abs + ".meta")) File.Delete(abs + ".meta"); |
| 68 | + } |
| 69 | + catch { } |
| 70 | + } |
| 71 | + |
| 72 | + private static Texture2D CreateSolidTextureAsset(string path, Color color) |
| 73 | + { |
| 74 | + var tex = new Texture2D(4, 4, TextureFormat.RGBA32, false); |
| 75 | + var pixels = new Color[16]; |
| 76 | + for (int i = 0; i < pixels.Length; i++) pixels[i] = color; |
| 77 | + tex.SetPixels(pixels); |
| 78 | + tex.Apply(); |
| 79 | + AssetDatabase.CreateAsset(tex, path); |
| 80 | + AssetDatabase.SaveAssets(); |
| 81 | + return tex; |
| 82 | + } |
| 83 | + |
| 84 | + private static JObject ToJObject(object result) |
| 85 | + { |
| 86 | + return result as JObject ?? JObject.FromObject(result); |
| 87 | + } |
| 88 | + |
| 89 | + [Test] |
| 90 | + public void CreateAndModifyMaterial_WithDirectPropertyKeys_Works() |
| 91 | + { |
| 92 | + // Arrange: create textures as assets |
| 93 | + CreateSolidTextureAsset(_baseMapPath, Color.white); |
| 94 | + CreateSolidTextureAsset(_normalMapPath, new Color(0.5f, 0.5f, 1f)); |
| 95 | + CreateSolidTextureAsset(_occlusionMapPath, Color.gray); |
| 96 | + |
| 97 | + // Create material using direct keys via JSON string |
| 98 | + var createParams = new JObject |
| 99 | + { |
| 100 | + ["action"] = "create", |
| 101 | + ["path"] = _matPath, |
| 102 | + ["assetType"] = "Material", |
| 103 | + ["properties"] = new JObject |
| 104 | + { |
| 105 | + ["shader"] = "Universal Render Pipeline/Lit", |
| 106 | + ["_Color"] = new JArray(0f, 1f, 0f, 1f), |
| 107 | + ["_Glossiness"] = 0.25f |
| 108 | + } |
| 109 | + }; |
| 110 | + var createRes = ToJObject(ManageAsset.HandleCommand(createParams)); |
| 111 | + Assert.IsTrue(createRes.Value<bool>("success"), createRes.ToString()); |
| 112 | + |
| 113 | + // Modify with aliases and textures |
| 114 | + var modifyParams = new JObject |
| 115 | + { |
| 116 | + ["action"] = "modify", |
| 117 | + ["path"] = _matPath, |
| 118 | + ["properties"] = new JObject |
| 119 | + { |
| 120 | + ["_BaseColor"] = new JArray(0f, 0f, 1f, 1f), |
| 121 | + ["_Smoothness"] = 0.5f, |
| 122 | + ["_BaseMap"] = _baseMapPath, |
| 123 | + ["_BumpMap"] = _normalMapPath, |
| 124 | + ["_OcclusionMap"] = _occlusionMapPath |
| 125 | + } |
| 126 | + }; |
| 127 | + var modifyRes = ToJObject(ManageAsset.HandleCommand(modifyParams)); |
| 128 | + Assert.IsTrue(modifyRes.Value<bool>("success"), modifyRes.ToString()); |
| 129 | + |
| 130 | + var mat = AssetDatabase.LoadAssetAtPath<Material>(_matPath); |
| 131 | + Assert.IsNotNull(mat, "Material should exist at path."); |
| 132 | + |
| 133 | + // Verify color alias applied |
| 134 | + if (mat.HasProperty("_BaseColor")) |
| 135 | + { |
| 136 | + Assert.AreEqual(Color.blue, mat.GetColor("_BaseColor")); |
| 137 | + } |
| 138 | + else if (mat.HasProperty("_Color")) |
| 139 | + { |
| 140 | + Assert.AreEqual(Color.blue, mat.GetColor("_Color")); |
| 141 | + } |
| 142 | + |
| 143 | + // Verify float |
| 144 | + string smoothProp = mat.HasProperty("_Smoothness") ? "_Smoothness" : (mat.HasProperty("_Glossiness") ? "_Glossiness" : null); |
| 145 | + Assert.IsNotNull(smoothProp, "Material should expose Smoothness/Glossiness."); |
| 146 | + Assert.That(Mathf.Abs(mat.GetFloat(smoothProp) - 0.5f) < 1e-4f); |
| 147 | + |
| 148 | + // Verify textures |
| 149 | + string baseMapProp = mat.HasProperty("_BaseMap") ? "_BaseMap" : (mat.HasProperty("_MainTex") ? "_MainTex" : null); |
| 150 | + Assert.IsNotNull(baseMapProp, "Material should expose BaseMap/MainTex."); |
| 151 | + Assert.IsNotNull(mat.GetTexture(baseMapProp), "BaseMap/MainTex should be assigned."); |
| 152 | + if (mat.HasProperty("_BumpMap")) Assert.IsNotNull(mat.GetTexture("_BumpMap")); |
| 153 | + if (mat.HasProperty("_OcclusionMap")) Assert.IsNotNull(mat.GetTexture("_OcclusionMap")); |
| 154 | + } |
| 155 | + } |
| 156 | +} |
| 157 | + |
| 158 | + |
0 commit comments