|
1 | 1 | using System; |
2 | 2 | using System.Collections.Generic; |
| 3 | +using System.Collections; |
3 | 4 | using NUnit.Framework; |
4 | 5 | using UnityEngine; |
5 | 6 | using UnityEditor; |
@@ -355,5 +356,205 @@ public void SetComponentProperties_ContinuesAfterException() |
355 | 356 | } |
356 | 357 | Assert.IsTrue(foundVelocityError, "errors should include a message referencing 'velocity'"); |
357 | 358 | } |
| 359 | + |
| 360 | + [Test] |
| 361 | + public void GetComponentData_DoesNotInstantiateMaterialsInEditMode() |
| 362 | + { |
| 363 | + // Arrange - Create a GameObject with MeshRenderer and MeshFilter components |
| 364 | + var testObject = new GameObject("MaterialMeshTestObject"); |
| 365 | + var meshRenderer = testObject.AddComponent<MeshRenderer>(); |
| 366 | + var meshFilter = testObject.AddComponent<MeshFilter>(); |
| 367 | + |
| 368 | + // Create a simple material and mesh for testing |
| 369 | + var testMaterial = new Material(Shader.Find("Standard")); |
| 370 | + var tempCube = GameObject.CreatePrimitive(PrimitiveType.Cube); |
| 371 | + var testMesh = tempCube.GetComponent<MeshFilter>().sharedMesh; |
| 372 | + UnityEngine.Object.DestroyImmediate(tempCube); |
| 373 | + |
| 374 | + // Set the shared material and mesh (these should be used in edit mode) |
| 375 | + meshRenderer.sharedMaterial = testMaterial; |
| 376 | + meshFilter.sharedMesh = testMesh; |
| 377 | + |
| 378 | + // Act - Get component data which should trigger material/mesh property access |
| 379 | + var prevIgnore = LogAssert.ignoreFailingMessages; |
| 380 | + LogAssert.ignoreFailingMessages = true; // Avoid failing due to incidental editor logs during reflection |
| 381 | + object result; |
| 382 | + try |
| 383 | + { |
| 384 | + result = MCPForUnity.Editor.Helpers.GameObjectSerializer.GetComponentData(meshRenderer); |
| 385 | + } |
| 386 | + finally |
| 387 | + { |
| 388 | + LogAssert.ignoreFailingMessages = prevIgnore; |
| 389 | + } |
| 390 | + |
| 391 | + // Assert - Basic success and shape tolerance |
| 392 | + Assert.IsNotNull(result, "GetComponentData should return a result"); |
| 393 | + if (result is Dictionary<string, object> dict && |
| 394 | + dict.TryGetValue("properties", out var propsObj) && |
| 395 | + propsObj is Dictionary<string, object> properties) |
| 396 | + { |
| 397 | + Assert.IsTrue(properties.ContainsKey("material") || properties.ContainsKey("sharedMaterial") || properties.ContainsKey("materials") || properties.ContainsKey("sharedMaterials"), |
| 398 | + "Serialized data should include a material-related key when present."); |
| 399 | + } |
| 400 | + |
| 401 | + // Clean up |
| 402 | + UnityEngine.Object.DestroyImmediate(testMaterial); |
| 403 | + UnityEngine.Object.DestroyImmediate(testObject); |
| 404 | + } |
| 405 | + |
| 406 | + [Test] |
| 407 | + public void GetComponentData_DoesNotInstantiateMeshesInEditMode() |
| 408 | + { |
| 409 | + // Arrange - Create a GameObject with MeshFilter component |
| 410 | + var testObject = new GameObject("MeshTestObject"); |
| 411 | + var meshFilter = testObject.AddComponent<MeshFilter>(); |
| 412 | + |
| 413 | + // Create a simple mesh for testing |
| 414 | + var tempSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); |
| 415 | + var testMesh = tempSphere.GetComponent<MeshFilter>().sharedMesh; |
| 416 | + UnityEngine.Object.DestroyImmediate(tempSphere); |
| 417 | + meshFilter.sharedMesh = testMesh; |
| 418 | + |
| 419 | + // Act - Get component data which should trigger mesh property access |
| 420 | + var prevIgnore2 = LogAssert.ignoreFailingMessages; |
| 421 | + LogAssert.ignoreFailingMessages = true; |
| 422 | + object result; |
| 423 | + try |
| 424 | + { |
| 425 | + result = MCPForUnity.Editor.Helpers.GameObjectSerializer.GetComponentData(meshFilter); |
| 426 | + } |
| 427 | + finally |
| 428 | + { |
| 429 | + LogAssert.ignoreFailingMessages = prevIgnore2; |
| 430 | + } |
| 431 | + |
| 432 | + // Assert - Basic success and shape tolerance |
| 433 | + Assert.IsNotNull(result, "GetComponentData should return a result"); |
| 434 | + if (result is Dictionary<string, object> dict2 && |
| 435 | + dict2.TryGetValue("properties", out var propsObj2) && |
| 436 | + propsObj2 is Dictionary<string, object> properties2) |
| 437 | + { |
| 438 | + Assert.IsTrue(properties2.ContainsKey("mesh") || properties2.ContainsKey("sharedMesh"), |
| 439 | + "Serialized data should include a mesh-related key when present."); |
| 440 | + } |
| 441 | + |
| 442 | + // Clean up |
| 443 | + UnityEngine.Object.DestroyImmediate(testObject); |
| 444 | + } |
| 445 | + |
| 446 | + [Test] |
| 447 | + public void GetComponentData_UsesSharedMaterialInEditMode() |
| 448 | + { |
| 449 | + // Arrange - Create a GameObject with MeshRenderer |
| 450 | + var testObject = new GameObject("SharedMaterialTestObject"); |
| 451 | + var meshRenderer = testObject.AddComponent<MeshRenderer>(); |
| 452 | + |
| 453 | + // Create a test material |
| 454 | + var testMaterial = new Material(Shader.Find("Standard")); |
| 455 | + testMaterial.name = "TestMaterial"; |
| 456 | + meshRenderer.sharedMaterial = testMaterial; |
| 457 | + |
| 458 | + // Act - Get component data in edit mode |
| 459 | + var result = MCPForUnity.Editor.Helpers.GameObjectSerializer.GetComponentData(meshRenderer); |
| 460 | + |
| 461 | + // Assert - Verify that the material property was accessed without instantiation |
| 462 | + Assert.IsNotNull(result, "GetComponentData should return a result"); |
| 463 | + |
| 464 | + // Check that result is a dictionary with properties key |
| 465 | + if (result is Dictionary<string, object> resultDict && |
| 466 | + resultDict.TryGetValue("properties", out var propertiesObj) && |
| 467 | + propertiesObj is Dictionary<string, object> properties) |
| 468 | + { |
| 469 | + Assert.IsTrue(properties.ContainsKey("material") || properties.ContainsKey("sharedMaterial"), |
| 470 | + "Serialized data should include 'material' or 'sharedMaterial' when present."); |
| 471 | + } |
| 472 | + |
| 473 | + // Clean up |
| 474 | + UnityEngine.Object.DestroyImmediate(testMaterial); |
| 475 | + UnityEngine.Object.DestroyImmediate(testObject); |
| 476 | + } |
| 477 | + |
| 478 | + [Test] |
| 479 | + public void GetComponentData_UsesSharedMeshInEditMode() |
| 480 | + { |
| 481 | + // Arrange - Create a GameObject with MeshFilter |
| 482 | + var testObject = new GameObject("SharedMeshTestObject"); |
| 483 | + var meshFilter = testObject.AddComponent<MeshFilter>(); |
| 484 | + |
| 485 | + // Create a test mesh |
| 486 | + var tempCylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder); |
| 487 | + var testMesh = tempCylinder.GetComponent<MeshFilter>().sharedMesh; |
| 488 | + UnityEngine.Object.DestroyImmediate(tempCylinder); |
| 489 | + testMesh.name = "TestMesh"; |
| 490 | + meshFilter.sharedMesh = testMesh; |
| 491 | + |
| 492 | + // Act - Get component data in edit mode |
| 493 | + var result = MCPForUnity.Editor.Helpers.GameObjectSerializer.GetComponentData(meshFilter); |
| 494 | + |
| 495 | + // Assert - Verify that the mesh property was accessed without instantiation |
| 496 | + Assert.IsNotNull(result, "GetComponentData should return a result"); |
| 497 | + |
| 498 | + // Check that result is a dictionary with properties key |
| 499 | + if (result is Dictionary<string, object> resultDict && |
| 500 | + resultDict.TryGetValue("properties", out var propertiesObj) && |
| 501 | + propertiesObj is Dictionary<string, object> properties) |
| 502 | + { |
| 503 | + Assert.IsTrue(properties.ContainsKey("mesh") || properties.ContainsKey("sharedMesh"), |
| 504 | + "Serialized data should include 'mesh' or 'sharedMesh' when present."); |
| 505 | + } |
| 506 | + |
| 507 | + // Clean up |
| 508 | + UnityEngine.Object.DestroyImmediate(testObject); |
| 509 | + } |
| 510 | + |
| 511 | + [Test] |
| 512 | + public void GetComponentData_HandlesNullMaterialsAndMeshes() |
| 513 | + { |
| 514 | + // Arrange - Create a GameObject with MeshRenderer and MeshFilter but no materials/meshes |
| 515 | + var testObject = new GameObject("NullMaterialMeshTestObject"); |
| 516 | + var meshRenderer = testObject.AddComponent<MeshRenderer>(); |
| 517 | + var meshFilter = testObject.AddComponent<MeshFilter>(); |
| 518 | + |
| 519 | + // Don't set any materials or meshes - they should be null |
| 520 | + |
| 521 | + // Act - Get component data |
| 522 | + var rendererResult = MCPForUnity.Editor.Helpers.GameObjectSerializer.GetComponentData(meshRenderer); |
| 523 | + var meshFilterResult = MCPForUnity.Editor.Helpers.GameObjectSerializer.GetComponentData(meshFilter); |
| 524 | + |
| 525 | + // Assert - Verify that the operations succeeded even with null materials/meshes |
| 526 | + Assert.IsNotNull(rendererResult, "GetComponentData should handle null materials"); |
| 527 | + Assert.IsNotNull(meshFilterResult, "GetComponentData should handle null meshes"); |
| 528 | + |
| 529 | + // Clean up |
| 530 | + UnityEngine.Object.DestroyImmediate(testObject); |
| 531 | + } |
| 532 | + |
| 533 | + [Test] |
| 534 | + public void GetComponentData_WorksWithMultipleMaterials() |
| 535 | + { |
| 536 | + // Arrange - Create a GameObject with MeshRenderer that has multiple materials |
| 537 | + var testObject = new GameObject("MultiMaterialTestObject"); |
| 538 | + var meshRenderer = testObject.AddComponent<MeshRenderer>(); |
| 539 | + |
| 540 | + // Create multiple test materials |
| 541 | + var material1 = new Material(Shader.Find("Standard")); |
| 542 | + material1.name = "TestMaterial1"; |
| 543 | + var material2 = new Material(Shader.Find("Standard")); |
| 544 | + material2.name = "TestMaterial2"; |
| 545 | + |
| 546 | + meshRenderer.sharedMaterials = new Material[] { material1, material2 }; |
| 547 | + |
| 548 | + // Act - Get component data |
| 549 | + var result = MCPForUnity.Editor.Helpers.GameObjectSerializer.GetComponentData(meshRenderer); |
| 550 | + |
| 551 | + // Assert - Verify that the operation succeeded with multiple materials |
| 552 | + Assert.IsNotNull(result, "GetComponentData should handle multiple materials"); |
| 553 | + |
| 554 | + // Clean up |
| 555 | + UnityEngine.Object.DestroyImmediate(material1); |
| 556 | + UnityEngine.Object.DestroyImmediate(material2); |
| 557 | + UnityEngine.Object.DestroyImmediate(testObject); |
| 558 | + } |
358 | 559 | } |
359 | 560 | } |
0 commit comments