using System; using System.IO; using MCPForUnity.Editor.Tools; using MCPForUnity.Editor.Tools.GameObjects; using Newtonsoft.Json.Linq; using NUnit.Framework; using UnityEditor; using UnityEngine; using static MCPForUnityTests.Editor.TestUtilities; namespace MCPForUnityTests.Editor.Tools { public class MaterialParameterToolTests { private const string TempRoot = "Assets/Temp/MaterialParameterToolTests"; private string _matPath; // unique per test run private GameObject _sphere; [SetUp] public void SetUp() { _matPath = $"{TempRoot}/BlueURP_{Guid.NewGuid().ToString("N")}.mat"; if (!AssetDatabase.IsValidFolder("Assets/Temp")) { AssetDatabase.CreateFolder("Assets", "Temp"); } if (!AssetDatabase.IsValidFolder(TempRoot)) { AssetDatabase.CreateFolder("Assets/Temp", "MaterialParameterToolTests"); } // Ensure any leftover material from previous runs is removed if (AssetDatabase.LoadAssetAtPath(_matPath) != null) { AssetDatabase.DeleteAsset(_matPath); AssetDatabase.Refresh(); } // Hard-delete any stray files on disk (in case GUID lookup fails) var abs = Path.Combine(Directory.GetCurrentDirectory(), _matPath); try { if (File.Exists(abs)) File.Delete(abs); if (File.Exists(abs + ".meta")) File.Delete(abs + ".meta"); } catch { /* best-effort cleanup */ } AssetDatabase.Refresh(); } [TearDown] public void TearDown() { if (_sphere != null) { UnityEngine.Object.DestroyImmediate(_sphere); _sphere = null; } if (AssetDatabase.LoadAssetAtPath(_matPath) != null) { AssetDatabase.DeleteAsset(_matPath); } // Clean up temp directory after each test if (AssetDatabase.IsValidFolder(TempRoot)) { AssetDatabase.DeleteAsset(TempRoot); } // Clean up empty parent folders to avoid debris CleanupEmptyParentFolders(TempRoot); AssetDatabase.Refresh(); } [Test] public void CreateMaterial_WithObjectProperties_SucceedsAndSetsColor() { // Ensure a clean state if a previous run left the asset behind (uses _matPath now) if (AssetDatabase.LoadAssetAtPath(_matPath) != null) { AssetDatabase.DeleteAsset(_matPath); AssetDatabase.Refresh(); } var createParams = new JObject { ["action"] = "create", ["path"] = _matPath, ["assetType"] = "Material", ["properties"] = new JObject { ["shader"] = "Universal Render Pipeline/Lit", ["color"] = new JArray(0f, 0f, 1f, 1f) } }; var result = ToJObject(ManageAsset.HandleCommand(createParams)); Assert.IsTrue(result.Value("success"), result.Value("error")); var mat = AssetDatabase.LoadAssetAtPath(_matPath); Assert.IsNotNull(mat, "Material should exist at path."); // Verify color if shader exposes _Color if (mat.HasProperty("_Color")) { Assert.AreEqual(Color.blue, mat.GetColor("_Color")); } } [Test] public void AssignMaterial_ToSphere_UsingManageMaterial_Succeeds() { // Ensure material exists first CreateMaterial_WithObjectProperties_SucceedsAndSetsColor(); // Create a sphere via handler var createGo = new JObject { ["action"] = "create", ["name"] = "ToolTestSphere", ["primitiveType"] = "Sphere" }; var createGoResult = ToJObject(ManageGameObject.HandleCommand(createGo)); Assert.IsTrue(createGoResult.Value("success"), createGoResult.Value("error")); _sphere = GameObject.Find("ToolTestSphere"); Assert.IsNotNull(_sphere, "Sphere should be created."); // Assign material via ManageMaterial tool var assignParams = new JObject { ["action"] = "assign_material_to_renderer", ["target"] = "ToolTestSphere", ["searchMethod"] = "by_name", ["materialPath"] = _matPath, ["slot"] = 0 }; var assignResult = ToJObject(ManageMaterial.HandleCommand(assignParams)); Assert.IsTrue(assignResult.Value("success"), assignResult.ToString()); var renderer = _sphere.GetComponent(); Assert.IsNotNull(renderer, "Sphere should have MeshRenderer."); Assert.IsNotNull(renderer.sharedMaterial, "sharedMaterial should be assigned."); StringAssert.StartsWith("BlueURP_", renderer.sharedMaterial.name); } [Test] public void ReadRendererData_DoesNotInstantiateMaterial_AndIncludesSharedMaterial() { // Prepare object and assignment AssignMaterial_ToSphere_UsingManageMaterial_Succeeds(); var renderer = _sphere.GetComponent(); int beforeId = renderer.sharedMaterial != null ? renderer.sharedMaterial.GetInstanceID() : 0; var data = MCPForUnity.Editor.Helpers.GameObjectSerializer.GetComponentData(renderer) as System.Collections.Generic.Dictionary; Assert.IsNotNull(data, "Serializer should return data."); int afterId = renderer.sharedMaterial != null ? renderer.sharedMaterial.GetInstanceID() : 0; Assert.AreEqual(beforeId, afterId, "sharedMaterial instance must not change (no instantiation in EditMode)."); if (data.TryGetValue("properties", out var propsObj) && propsObj is System.Collections.Generic.Dictionary props) { Assert.IsTrue( props.ContainsKey("sharedMaterial") || props.ContainsKey("material") || props.ContainsKey("sharedMaterials") || props.ContainsKey("materials"), "Serialized data should include material info."); } } } }