MeshCreatorUndoManager.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Created by Daniele Giardini - 2011 - Holoville - http://www.holoville.com
  2. // Mesh Creator team found this at http://wiki.unity3d.com/index.php?title=EditorUndoManager
  3. // we stripped out many of the comments and changed names of things
  4. using UnityEditor;
  5. using UnityEngine;
  6. public class MeshCreatorUndoManager
  7. {
  8. // VARS ///////////////////////////////////////////////////
  9. private Object defTarget;
  10. private string defName;
  11. private bool autoSetDirty;
  12. private bool listeningForGuiChanges;
  13. private bool isMouseDown;
  14. private Object waitingToRecordPrefab; // If different than NULL indicates the prefab instance that will need to record its state as soon as the mouse is released.
  15. // ***********************************************************************************
  16. // CONSTRUCTOR
  17. // ***********************************************************************************
  18. /// Creates a new MeshCreatorUndoManager,
  19. /// setting it so that the target is marked as dirty each time a new undo is stored.
  20. /// params:
  21. /// The default Object you want to save undo info for.
  22. /// The default name of the thing to undo (displayed as "Undo [name]" in the main menu).
  23. public MeshCreatorUndoManager(Object p_target, string p_name) : this(p_target, p_name, true) { }
  24. /// Creates a new MeshCreatorUndoManager.
  25. /// params:
  26. /// The default Object you want to save undo info for.
  27. /// The default name of the thing to undo (displayed as "Undo [name]" in the main menu).
  28. /// If TRUE, marks the target as dirty each time a new undo is stored.
  29. public MeshCreatorUndoManager(Object p_target, string p_name, bool p_autoSetDirty)
  30. {
  31. defTarget = p_target;
  32. defName = p_name;
  33. autoSetDirty = p_autoSetDirty;
  34. }
  35. // ===================================================================================
  36. // METHODS ---------------------------------------------------------------------------
  37. /// Call this method BEFORE any undoable UnityGUI call.
  38. /// Manages undo for the default target, with the default name.
  39. public void CheckUndo() { CheckUndo(defTarget, defName); }
  40. /// Call this method BEFORE any undoable UnityGUI call.
  41. /// Manages undo for the given target, with the default name.
  42. /// params:
  43. /// The object you want to save undo info for.
  44. public void CheckUndo(Object p_target) { CheckUndo(p_target, defName); }
  45. /// Call this method BEFORE any undoable UnityGUI call.
  46. /// Manages undo for the given target, with the given name.
  47. /// params:
  48. /// The object you want to save undo info for.
  49. /// The name of the thing to undo (displayed as "Undo [name]" in the main menu).
  50. public void CheckUndo(Object p_target, string p_name)
  51. {
  52. Event e = Event.current;
  53. if (waitingToRecordPrefab != null)
  54. {
  55. // Record eventual prefab instance modification.
  56. // TODO Avoid recording if nothing changed (no harm in doing so, but it would be nicer).
  57. switch (e.type)
  58. {
  59. case EventType.MouseDown:
  60. case EventType.MouseUp:
  61. case EventType.KeyDown:
  62. case EventType.KeyUp:
  63. PrefabUtility.RecordPrefabInstancePropertyModifications(waitingToRecordPrefab);
  64. break;
  65. }
  66. }
  67. if ((e.type == EventType.MouseDown && e.button == 0) || (e.type == EventType.KeyUp && e.keyCode == KeyCode.Tab))
  68. {
  69. // When the LMB is pressed or the TAB key is released,
  70. // store a snapshot, but don't register it as an undo
  71. // (so that if nothing changes we avoid storing a useless undo).
  72. Undo.SetSnapshotTarget(p_target, p_name);
  73. Undo.CreateSnapshot();
  74. Undo.ClearSnapshotTarget(); // Not sure if this is necessary.
  75. listeningForGuiChanges = true;
  76. }
  77. }
  78. /// Call this method AFTER any undoable UnityGUI call.
  79. /// Manages undo for the default target, with the default name,
  80. /// and returns a value of TRUE if the target is marked as dirty.
  81. public bool CheckDirty() { return CheckDirty(defTarget, defName); }
  82. /// Call this method AFTER any undoable UnityGUI call.
  83. /// Manages undo for the given target, with the default name,
  84. /// and returns a value of TRUE if the target is marked as dirty.
  85. /// params:
  86. /// The object you want to save undo info for.
  87. public bool CheckDirty(Object p_target) { return CheckDirty(p_target, defName); }
  88. /// Call this method AFTER any undoable UnityGUI call.
  89. /// Manages undo for the given target, with the given name,
  90. /// and returns a value of TRUE if the target is marked as dirty.
  91. /// params:
  92. /// The object you want to save undo info for.
  93. /// The name of the thing to undo (displayed as "Undo [name]" in the main menu).
  94. public bool CheckDirty(Object p_target, string p_name)
  95. {
  96. if (listeningForGuiChanges && GUI.changed)
  97. {
  98. // Some GUI value changed after pressing the mouse
  99. // or releasing the TAB key.
  100. // Register the previous snapshot as a valid undo.
  101. SetDirty(p_target, p_name);
  102. return true;
  103. }
  104. return false;
  105. }
  106. /// Call this method AFTER any undoable UnityGUI call.
  107. /// Forces undo for the default target, with the default name.
  108. /// Used to undo operations that are performed by pressing a button,
  109. /// which doesn't set the GUI to a changed state.
  110. public void ForceDirty() { ForceDirty(defTarget, defName); }
  111. /// Call this method AFTER any undoable UnityGUI call.
  112. /// Forces undo for the given target, with the default name.
  113. /// Used to undo operations that are performed by pressing a button,
  114. /// which doesn't set the GUI to a changed state.
  115. /// params:
  116. /// The object you want to save undo info for.
  117. public void ForceDirty(Object p_target) { ForceDirty(p_target, defName); }
  118. /// Call this method AFTER any undoable UnityGUI call.
  119. /// Forces undo for the given target, with the given name.
  120. /// Used to undo operations that are performed by pressing a button,
  121. /// which doesn't set the GUI to a changed state.
  122. /// params:
  123. /// The object you want to save undo info for.
  124. /// The name of the thing to undo (displayed as "Undo [name]" in the main menu).
  125. public void ForceDirty(Object p_target, string p_name)
  126. {
  127. if (!listeningForGuiChanges)
  128. {
  129. // Create a new snapshot.
  130. Undo.SetSnapshotTarget(p_target, p_name);
  131. Undo.CreateSnapshot();
  132. Undo.ClearSnapshotTarget();
  133. }
  134. SetDirty(p_target, p_name);
  135. }
  136. // ===================================================================================
  137. // PRIVATE METHODS -------------------------------------------------------------------
  138. private void SetDirty(Object p_target, string p_name)
  139. {
  140. Undo.SetSnapshotTarget(p_target, p_name);
  141. Undo.RegisterSnapshot();
  142. Undo.ClearSnapshotTarget(); // Not sure if this is necessary.
  143. if (autoSetDirty) EditorUtility.SetDirty(p_target);
  144. listeningForGuiChanges = false;
  145. if (CheckTargetIsPrefabInstance(p_target))
  146. {
  147. // Prefab instance: record immediately and also wait for value to be changed and than re-record it
  148. // (otherwise prefab instances are not updated correctly when using Custom Inspectors).
  149. PrefabUtility.RecordPrefabInstancePropertyModifications(p_target);
  150. waitingToRecordPrefab = p_target;
  151. }
  152. else
  153. {
  154. waitingToRecordPrefab = null;
  155. }
  156. }
  157. private bool CheckTargetIsPrefabInstance(Object p_target)
  158. {
  159. return (PrefabUtility.GetPrefabType(p_target) == PrefabType.PrefabInstance);
  160. }
  161. }