/// <summary> /// Sorts the list of Nodes with animations asynchrnously with yields. /// </summary> /// <returns></returns> private IEnumerator AnimatedSortCoroutine() { GameObject runner = null, currentNode = null; int currentNodeValue = int.MaxValue; int comparisonCount = 0; // Execute the sorting algorithm. O(n^2) for (int i = 0; i < theList.Count(); i++) { // Current node = theList[i] currentNode = theList.GetComponent <NodeList>().NodeAtIndex(i); currentNodeValue = currentNode.GetComponent <Node>().nodeValue; // Runner node = theList[i - 1] runner = currentNode.GetComponent <Node>().prevNode; yield return(new WaitForSeconds(timeBetweenComparisons)); currentNode.GetComponent <Renderer>().material = materials[1]; while (runner != null) { yield return(new WaitForSeconds(timeBetweenComparisons)); runner.GetComponent <Renderer>().material = materials[2]; if (currentNodeValue < runner.GetComponent <Node>().nodeValue) { yield return(new WaitForSeconds(timeBetweenComparisons)); runner.GetComponent <Renderer>().material = materials[3]; // If the current node's value is less than the runner;s, then we keep going. // runnerNode = theList[runnerNode.Index - 1] runner = runner.GetComponent <Node>().prevNode; } else { runner.GetComponent <Renderer>().material = materials[4]; yield return(new WaitForSeconds(timeBetweenComparisons)); // If on manual mode, flag so that we wait until the animation is done before we accept input for the next step. canExecuteStep = false; // If we are using manual stepping, wait until we get input to execute before executing swaps. if (isUsingManualStepping && !canExecuteStep) { yield return(new WaitUntil(() => canExecuteStep == true)); canExecuteStep = false; } isReadyForInput = false; // If the current node's value is greater than the runner's, // remove the node and place it at the index after the runner's. if (currentNode.GetComponent <Node>().nodeIndex - 1 != runner.GetComponent <Node>().nodeIndex) { // Only perform the animated removal and insert if the element being inserted needs to be moved. theList.AnimatedRemoveAtIndex(i); theList.AnimatedInsertAtIndex(runner.GetComponent <Node>().nodeIndex + 1, currentNode); } else { theList.RemoveAtIndex(i); theList.InsertAtIndex(runner.GetComponent <Node>().nodeIndex + 1, currentNode); } // Wait for any active animations to finish. yield return(new WaitUntil(() => theList.shiftAnimationHelper.isLerpShifting() == false)); yield return(new WaitUntil(() => theList.insertAnimationHelper.isLerpInserting() == false)); isReadyForInput = true; runner.GetComponent <Renderer>().material = materials[3]; break; } comparisonCount++; } // If we get here, then that means the current value is the smallest in the sorted list. // Insert at the head. if (runner == null) { GameObject tempNode = theList.GetComponent <NodeList>().NodeAtIndex(0); tempNode.GetComponent <Renderer>().material = materials[4]; yield return(new WaitForSeconds(timeBetweenComparisons)); // If on manual mode, flag so that we wait until the animation is done before we accept input for the next step. canExecuteStep = false; // If we are using manual stepping, wait until we get input to execute before executing swaps. if (isUsingManualStepping && !canExecuteStep) { yield return(new WaitUntil(() => canExecuteStep == true)); canExecuteStep = false; } isReadyForInput = false; if (i != 0) { // Only perform the animated removal and insert if the element being inserted isn't the first element being sorted. currentNode = theList.AnimatedRemoveAtIndex(i); theList.AnimatedInsertAtIndex(0, currentNode); } else { currentNode = theList.RemoveAtIndex(i); theList.InsertAtIndex(0, currentNode); } // Wait for any active animations to finish. yield return(new WaitUntil(() => theList.insertAnimationHelper.isLerpInserting() == false)); yield return(new WaitUntil(() => theList.shiftAnimationHelper.isLerpShifting() == false)); isReadyForInput = true; tempNode.GetComponent <Renderer>().material = materials[3]; currentNode.GetComponent <Renderer>().material = materials[3]; } else { currentNode.GetComponent <Renderer>().material = materials[3]; } // Reset temp variables. currentNode = runner = null; currentNodeValue = int.MaxValue; //Debug.Log("Insertion sort: " + theList.ToString()); } // Change the material to indicate sorting has finished. theList.GetComponent <NodeList>().NodeAtIndex(theList.Count() - 1).GetComponent <Renderer>().material = materials[3]; Debug.Log("Insertion sort comparisons: " + comparisonCount); isCoroutineIsActive = false; }