Undo.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace Edit{
  5. /******************************************************************************/
  6. _Undo::_Undo(Bool full, Ptr user, Flt time)
  7. {
  8. del();
  9. T._full=full;
  10. T. user=user;
  11. T. time=time;
  12. _max_changes=-1; _max_mem_usage=-1;
  13. }
  14. _Undo& _Undo::del()
  15. {
  16. _changes.del();
  17. _undos=_change_frame=0; _change_time=0; _change_type=null;
  18. return T;
  19. }
  20. _Undo& _Undo::forceCreateNextUndo()
  21. {
  22. _change_type =null;
  23. _change_time =0;
  24. _change_frame=0;
  25. return T;
  26. }
  27. /******************************************************************************/
  28. void _Undo::clean(Bool test_mem_usage)
  29. {
  30. test_mem_usage &=(_max_mem_usage>=0); // only if it's enabled
  31. Bool test_change_limit=(_max_changes >=0);
  32. Long mem_usage; Memt<UInt> mem_usages;
  33. if(test_mem_usage)
  34. {
  35. mem_usage=0; mem_usages.setNum(_changes.elms()); REPA(mem_usages){UInt u=_changes[i].memUsage(); mem_usages[i]=u; mem_usage+=u;}
  36. }
  37. for(; test_mem_usage && mem_usage >_max_mem_usage
  38. || test_change_limit && _changes.elms()>_max_changes; )
  39. {
  40. if(undos()>redos()) // remove first undo
  41. {
  42. _undos--;
  43. _changes.removeValid(0, true);
  44. if(test_mem_usage){mem_usage-=mem_usages[0]; mem_usages.remove(0, true);}
  45. }else // remove last redo
  46. {
  47. _changes.removeLast();
  48. if(test_mem_usage){mem_usage-=mem_usages.last(); mem_usages.removeLast();}
  49. }
  50. }
  51. }
  52. /******************************************************************************/
  53. Long _Undo::memUsage()C
  54. {
  55. Long usage=0; REPA(_changes)usage+=_changes[i].memUsage();
  56. return usage;
  57. }
  58. _Undo& _Undo::maxMemUsage(Long limit)
  59. {
  60. if(limit<-1)limit=-1;
  61. if(_max_mem_usage!=limit)
  62. {
  63. Long old_limit=_max_mem_usage;
  64. _max_mem_usage=limit;
  65. if(_max_mem_usage>=0 && (_max_mem_usage<old_limit || old_limit<0))clean(true); // if new limit is smaller then potentially we need to remove some changes
  66. }
  67. return T;
  68. }
  69. _Undo& _Undo::maxChanges(Int limit)
  70. {
  71. if(limit<-1)limit=-1;
  72. if(_max_changes!=limit)
  73. {
  74. Int old_limit=limit;
  75. _max_changes=limit;
  76. if(_max_changes>=0 && (_max_changes<old_limit || old_limit<0))clean(false); // if new limit is smaller then potentially we need to remove some changes
  77. }
  78. return T;
  79. }
  80. /******************************************************************************/
  81. _Undo::Change* _Undo::getNextUndo() {return _changes.addr(undos()-1);}
  82. _Undo::Change* _Undo::getNextRedo() {return _changes.addr(undos() );}
  83. /******************************************************************************/
  84. _Undo::Change* _Undo::set(CPtr change_type, Bool force_create, Flt extra_time)
  85. {
  86. Change *change=null;
  87. // remove all redos
  88. for(; _changes.elms()>undos(); )_changes.removeLast();
  89. if(!undos() // no undos yet
  90. || force_create // force create
  91. || _change_type!=change_type // new change type
  92. || (Time.frame()!=_change_frame && Time.frame()!=_change_frame+1 && Time.appTime()>_change_time+extra_time+Time.ad()) // enough time has passed (check the frames too in case the frame took a long time)
  93. )
  94. {
  95. // clean if we have to
  96. clean(true);
  97. // add new change
  98. _undos++;
  99. change=&_changes.New(); if(_full)change->create(user); // create only in full mode
  100. }else
  101. if(!_full) // in partial mode we need to re-use the last change
  102. {
  103. // return last one
  104. change=&_changes.last();
  105. }
  106. // adjust settings (do this always to keep up the continuousness)
  107. _change_type =change_type;
  108. _change_frame=Time.frame();
  109. _change_time =Time.appTime()+time;
  110. return change;
  111. }
  112. _Undo::Change* _Undo::set(Int change_type, Bool force_create, Flt extra_time)
  113. {
  114. return set((CPtr)change_type, force_create, extra_time);
  115. }
  116. /******************************************************************************/
  117. Bool _Undo::undo()
  118. {
  119. if(undos()) // if there are any Undo Changes
  120. {
  121. if(_full && undos()==changes())if(set(null, true, 0))_undos--; // in full mode if we're at the end then we need to save current state
  122. if(undos()) // if there are still any Undo Changes after above codes
  123. {
  124. forceCreateNextUndo(); // call this after saving current state with 'set' because that modifies the parameters
  125. Change &change=_changes[--_undos]; // change the counter before calling 'apply' so inside it will be detected with correct info if undos/redos are available
  126. if(_full)change.apply(user);else change.swap(user);
  127. return true;
  128. }
  129. }
  130. return false;
  131. }
  132. Bool _Undo::redo()
  133. {
  134. if(_full && undos()<changes()-1)_undos++; // go forward
  135. if(InRange(undos(), changes())) // if there are still any Redo Changes
  136. {
  137. forceCreateNextUndo();
  138. Change &change=_changes[_undos++]; // change the counter before calling 'apply' so inside it will be detected with correct info if undos/redos are available
  139. if(_full)
  140. {
  141. change.apply(user);
  142. if(undos()==changes())_changes.removeLast(); // if we're at the end, then there's no need to keep this change anymore
  143. _undos--; // revert the ++ counter change
  144. }else change.swap(user);
  145. return true;
  146. }
  147. return false;
  148. }
  149. Bool _Undo::undoAsChange()
  150. {
  151. if(_full && undos()) // if there are any Undo Changes, currently supported only in full mode
  152. {
  153. set(null, true, 0); // always save current state
  154. if(undos()>1) // if there are still any Undo Changes (including the original one and the new created for saving state)
  155. {
  156. forceCreateNextUndo(); // call this after saving current state with 'set' because that modifies the parameters
  157. _changes[undos()-2].apply(user); return true;
  158. }
  159. }
  160. return false;
  161. }
  162. /******************************************************************************/
  163. } // Edit
  164. } // EE
  165. /******************************************************************************/