Ejemplo n.º 1
0
		/// <summary>
		/// Detects an UndoState change as either an undo or redo operation
		/// A positive return value indicates a redo operation, a negative an undo operation;
		/// If it is 0, then the adressed stack (undo/redo) was empty
		/// The absolute value is the number of records that were adressed, means the size of the group
		/// It is possible that the group size changed due to an anomaly, so count of records added by the anomaly is put into addedRecordsCount
		/// </summary>
		private static int DetectStateChange (UndoState prevState, UndoState nextState, out int addedRecordsCount)
		{
			addedRecordsCount = 0;

			int prevUndoCount = prevState.undoRecords.Count, prevRedoCount = prevState.redoRecords.Count;
			int nextUndoCount = nextState.undoRecords.Count, nextRedoCount = nextState.redoRecords.Count;
			int undoChange = nextUndoCount-prevUndoCount, redoChange = nextRedoCount-prevRedoCount;

			// Check if the action is undo or redo
			bool undoAction = undoChange < 0, redoAction = redoChange < 0;
			if ((!redoAction && prevUndoCount == 0) || (!undoAction && prevRedoCount == 0)) // Tried to undo/redo with an empty record stack
				return 0;
			if (!undoAction && !redoAction)
				throw new Exception ("Detected neither redo nor undo operation!");
			int recordChange = undoAction? Math.Abs (undoChange) : Math.Abs (redoChange);

		#if UNDO_DEBUG
			Debug.Log ("Detected " + (undoAction? "UNDO" : "REDO") + " of " + recordChange + " initial records!");
		#endif

			if (redoChange != -undoChange)
			{ // This anomaly happens only for records that trigger other undo/redo operations
				// -> only known case: Reparent unselected object in hierarchy, each iteration (undo/redo) of the issued record a 'Parenting' record gets added ontop
				addedRecordsCount = undoAction? (Math.Abs (redoChange)-Math.Abs (undoChange)) : (Math.Abs (undoChange)-Math.Abs (redoChange));
		#if UNDO_DEBUG
				Debug.LogWarning ("Due to an anomaly a difference of " + addedRecordsCount + " records was created during " + (undoAction? "undo" : "redo") + 
					" where undo change was " + undoChange + " and redo change " + redoChange);
		#endif
			}

			return (undoAction? -recordChange : recordChange); // Return the count of initially changed records
		}
Ejemplo n.º 2
0
        private static UndoState FetchUndoState()
        {
            UndoState newUndoState = new UndoState();

            getRecordsInternalDelegate.Invoke(newUndoState.undoRecords, newUndoState.redoRecords);
            return(newUndoState);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Callback recognising the type of record, calling the apropriate callback and handling undo pro records
        /// </summary>
        private static void UndoRedoPerformed()
        {
            lastFrameUndoRedoPerformed = true;
            AssureRecords();

            // Get new UndoState
            UndoState prevState = records.undoState;
            UndoState newState  = records.undoState = FetchUndoState();

            // Detect undo/redo
            int addedRecordCount;
            int change = DetectStateChange(prevState, newState, out addedRecordCount);

            if (change == 0)             // Nothing happend; Only possible if Undo/Redo stack was empty
            {
                return;
            }

            List <UndoProRecord> operatedRecords = records.PerformOperationInternal(change, addedRecordCount);

            if (change < 0)
            {             // UNDO operation
                foreach (UndoProRecord undoRecord in operatedRecords)
                {         // Invoke undo operations
                    if (undoRecord.undo != null)
                    {
                        undoRecord.undo.Invoke();
                    }
                }
                // Callback for whole group
                if (OnUndoPerformed != null)
                {
                    OnUndoPerformed.Invoke(operatedRecords.Select((UndoProRecord record) => record.label).ToArray());
                }
            }
            else
            {             // REDO operation
                foreach (UndoProRecord redoRecord in operatedRecords)
                {         // Invoke redo operations
                    if (redoRecord.perform != null)
                    {
                        redoRecord.perform.Invoke();
                    }
                }
                // Callback for whole group
                if (OnRedoPerformed != null)
                {
                    OnRedoPerformed.Invoke(operatedRecords.Select((UndoProRecord record) => record.label).ToArray());
                }
            }
        }
Ejemplo n.º 4
0
		/// <summary>
		/// Check the current undoState for any added undo records and updates the internal records accordingly
		/// </summary>
		private static void UpdateUndoRecords () 
		{
			AssureRecords ();

			// Get new UndoState
			UndoState prevState = records.undoState;
			records.undoState = FetchUndoState ();
			UndoState newState = records.undoState;

			// Detect additions to the record through comparision of the old and the new UndoState
			if (prevState.undoRecords.Count == newState.undoRecords.Count)
				return; // No undo record was added for sure

			// Fetch new undo records
			int addedUndoCount = newState.undoRecords.Count-prevState.undoRecords.Count;
		#if UNDO_DEBUG
			Debug.Log ("Checking for update... change detected! Added Undo's: " + addedUndoCount);
		#endif
			if (addedUndoCount < 0)
			{ // This happens only when the undo was erased, for example after switching the scene
				if (newState.undoRecords.Count != 0)
				{
					records.ClearRedo ();
					Debug.LogWarning ("Cleared Redo because some undos were removed!");
				}
				CreateRecords ();
				return;
			}

			// Update internals
			records.UndoRecordsAdded (addedUndoCount);

			// Callback
			string[] undosAdded = newState.undoRecords.GetRange (newState.undoRecords.Count-addedUndoCount, addedUndoCount).ToArray ();
			if (OnAddUndoRecord != null)
				OnAddUndoRecord.Invoke (undosAdded, newState.redoRecords.Count == 0);

		#if UNDO_DEBUG
			// Debug added undo records
			string undoLog = undosAdded.Length + " undo records added: ";
			for (int undoCnt = 0; undoCnt < undosAdded.Length; undoCnt++)
				undoLog += undosAdded[undoCnt] + "; ";
			Debug.Log (undoLog);
		#endif
		}