MaterialReplacements.cs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.Assertions;
  5. namespace SoftMasking {
  6. class MaterialReplacements {
  7. readonly IMaterialReplacer _replacer;
  8. readonly Action<Material> _applyParameters;
  9. readonly List<MaterialOverride> _overrides = new List<MaterialOverride>();
  10. public MaterialReplacements(IMaterialReplacer replacer, Action<Material> applyParameters) {
  11. _replacer = replacer;
  12. _applyParameters = applyParameters;
  13. }
  14. public Material Get(Material original) {
  15. for (int i = 0; i < _overrides.Count; ++i) {
  16. var entry = _overrides[i];
  17. if (ReferenceEquals(entry.original, original)) {
  18. var existing = entry.Get();
  19. if (existing) { // null may be stored in _overrides
  20. existing.CopyPropertiesFromMaterial(original);
  21. _applyParameters(existing);
  22. }
  23. return existing;
  24. }
  25. }
  26. var replacement = _replacer.Replace(original);
  27. if (replacement) {
  28. Assert.AreNotEqual(original, replacement, "IMaterialRepalcer should not return the original material");
  29. replacement.hideFlags = HideFlags.HideAndDontSave;
  30. _applyParameters(replacement);
  31. }
  32. _overrides.Add(new MaterialOverride(original, replacement));
  33. return replacement;
  34. }
  35. public void Release(Material replacement) {
  36. for (int i = 0; i < _overrides.Count; ++i) {
  37. var entry = _overrides[i];
  38. if (entry.replacement == replacement)
  39. if (entry.Release()) {
  40. UnityEngine.Object.DestroyImmediate(replacement);
  41. _overrides.RemoveAt(i);
  42. return;
  43. }
  44. }
  45. }
  46. public void ApplyAll() {
  47. for (int i = 0; i < _overrides.Count; ++i) {
  48. var mat = _overrides[i].replacement;
  49. if (mat)
  50. _applyParameters(mat);
  51. }
  52. }
  53. public void DestroyAllAndClear() {
  54. for (int i = 0; i < _overrides.Count; ++i)
  55. UnityEngine.Object.DestroyImmediate(_overrides[i].replacement);
  56. _overrides.Clear();
  57. }
  58. class MaterialOverride {
  59. int _useCount;
  60. public MaterialOverride(Material original, Material replacement) {
  61. this.original = original;
  62. this.replacement = replacement;
  63. _useCount = 1;
  64. }
  65. public Material original { get; private set; }
  66. public Material replacement { get; private set; }
  67. public Material Get() {
  68. ++_useCount;
  69. return replacement;
  70. }
  71. public bool Release() {
  72. Assert.IsTrue(_useCount > 0);
  73. return --_useCount == 0;
  74. }
  75. }
  76. }
  77. }