/// <summary> /// Adds a twist to our history. /// </summary> public void Update(SingleTwist twist) { if (m_undoMode) { // Remove from twist list. m_twists.RemoveAt(m_twists.Count - 1); // Save in our redo list. SingleTwist temp = twist.Clone(); temp.ReverseTwist(); m_redoTwists.Add(temp); m_undoMode = false; return; } if (m_redoMode) { m_redoTwists.RemoveAt(m_redoTwists.Count - 1); m_redoMode = false; } else { m_redoTwists.Clear(); } // This block should apply to normal twists and redo twists. m_twists.Add(twist); }
/// <summary> /// Checks if we are an undo of another twist. /// </summary> public bool IsUndo(SingleTwist other) { if (other == null) { return(false); } SingleTwist clone = this.Clone(); clone.ReverseTwist(); return(clone.Compare(other)); }
/// <summary> /// Transforms us into a new macro based on a different click location. /// </summary> public Macro Transform(Cell clickedCell, Vector3D clickedPoint, Puzzle puzzle, bool mouseMotionReflected) { Macro m = this.CloneAllButTwists(); m.SetupMobius(clickedCell, clickedPoint, puzzle, mouseMotionReflected); // Did we have an odd number of view reflections? bool viewReflected = this.ViewReflected ^ m.ViewReflected; Isometry iso1 = new Isometry(m.Mobius, null); Isometry iso2 = new Isometry(this.Mobius, null); if (viewReflected) { iso1 = Isometry.ReflectX() * iso1; } Isometry combined = iso1.Inverse() * iso2; foreach (SingleTwist t in this.m_twists) { // Find the transformed twist data. // NOTE: We choose the one which will be closest to the origin after transformation, // which hopefully won't lead to performance problems. // I initially just used the first TwistDataForStateCalcs list item, // but that led to issues because sometimes it would get transformed // to very near the disk boundary. We'd have run out of cells to // find the correct closest, and the transformed macros got all messed up. TwistData tdOriginal = t.IdentifiedTwistData.TwistDataForStateCalcs .OrderBy(td => combined.Apply(td.Center).MagSquared()) .First(); Vector3D newCenter = combined.Apply(tdOriginal.Center); TwistData tdNew = puzzle.ClosestTwistingCircles(newCenter); SingleTwist tClone = t.Clone(); tClone.IdentifiedTwistData = tdNew.IdentifiedTwistData; // If the reverse state of our transformed twist // has changed, we may need to reverse the new twist. bool reverse = tdOriginal.Reverse ^ tdNew.Reverse; if (reverse ^ viewReflected) // NOTE: Very similar to code in Renderer. { tClone.ReverseTwist(); } m.m_twists.Add(tClone); } return(m); }
/// <summary> /// Get undo rotation parameters. /// Calling this will set us in the "undo" state for the next rotation. /// Returns false if there are no more twists to undo. /// </summary> public bool GetUndoTwist(out SingleTwist twist) { twist = null; if (0 == m_twists.Count) { return(false); } twist = m_twists[m_twists.Count - 1].Clone(); twist.ReverseTwist(); m_undoMode = true; return(true); }