/// <summary>
 /// Invalidates all cached information.
 /// </summary>
 public void Invalidate()
 {
   _isDirty = true;
   _isBonePoseRelativeDirty.SetAll(true);
   _isBonePoseAbsoluteDirty.SetAll(true);
   _isSkinningMatrixDirty.SetAll(true);
 }
    private void Initialize(SkeletonPose skeletonPose)
    {
      _skeletonPose = skeletonPose;

      if (_bonePoseRelative == null)
      {
        // The SkeletonPoseAccessor is initialized for the first time.
        int numberOfBones = skeletonPose.Skeleton.NumberOfBones;

        // Create arrays. (Note: SkinningMatrices are created on demand.)
        _bonePoseRelative = new SrtTransform[numberOfBones];
        _bonePoseAbsolute = new SrtTransform[numberOfBones];

        // Set all dirty flags.
        _isDirty = true;
        _isBonePoseRelativeDirty = new FastBitArray(numberOfBones);
        _isBonePoseRelativeDirty.SetAll(true);
        _isBonePoseAbsoluteDirty = new FastBitArray(numberOfBones);
        _isBonePoseAbsoluteDirty.SetAll(true);
        _isSkinningMatrixDirty = new FastBitArray(numberOfBones);
        _isSkinningMatrixDirty.SetAll(true);
      }
      else
      {
        Debug.Assert(_bonePoseRelative != null, "SkeletonBoneAccessor is not properly initialized. Array _bonePoseRelative is not set.");
        Debug.Assert(_bonePoseAbsolute != null, "SkeletonBoneAccessor is not properly initialized. Array _bonePoseAbsolute is not set.");
        Debug.Assert(_isBonePoseRelativeDirty != null, "SkeletonBoneAccessor is not properly initialized. BitArray _isBonePoseRelativeDirty is not set.");
        Debug.Assert(_isBonePoseAbsoluteDirty != null, "SkeletonBoneAccessor is not properly initialized. BitArray _isBonePoseAbsoluteDirty is not set.");
        Debug.Assert(_isSkinningMatrixDirty != null, "SkeletonBoneAccessor is not properly initialized. BitArray _isSkinningMatrixDirty is not set.");
        Debug.Assert(_bonePoseRelative.Length != skeletonPose.Skeleton.NumberOfBones, "SkeletonBoneAccessor is incompatible. Array _bonePoseRelative has wrong length.");
        Debug.Assert(_bonePoseAbsolute.Length != skeletonPose.Skeleton.NumberOfBones, "SkeletonBoneAccessor is incompatible. Array _bonePoseAbsolute has wrong length.");
        Debug.Assert(_isBonePoseRelativeDirty.Length != skeletonPose.Skeleton.NumberOfBones, "SkeletonBoneAccessor is incompatible. BitArray _isBonePoseRelativeDirty has wrong length.");
        Debug.Assert(_isBonePoseAbsoluteDirty.Length != skeletonPose.Skeleton.NumberOfBones, "SkeletonBoneAccessor is incompatible. BitArray _isBonePoseAbsoluteDirty has wrong length.");
        Debug.Assert(_isSkinningMatrixDirty.Length != skeletonPose.Skeleton.NumberOfBones, "SkeletonBoneAccessor is incompatible. BitArray _isSkinningMatrixDirty has wrong length.");

        // Set all dirty flags.
        Invalidate();
      }
    }
        /// <summary>Analyzes the state of the puzzle to determine whether it is a solution or not.</summary>
        /// <returns>The status of the puzzle.</returns>
        private PuzzleStatus AnalyzeSolutionStatus()
        {
            // Need a way of keeping track of what numbers have been used (in each row, column, box, etc.)
            // A bit array is a great way to do this, where each bit corresponds to a true/false value
            // as to whether a number was already used in a particular scenario.
            FastBitArray numbersUsed = new FastBitArray(_gridSize);

            // Make sure every column contains the right numbers.  It's ok if a column has holes
            // as long as those cells have possibilities, in which case it's a puzzle in progress.
            // However, two numbers can't be used in the same column, even if there are holes.
            for (int i = 0; i < _gridSize; i++)
            {
                numbersUsed.SetAll(false);
                for (int j = 0; j < _gridSize; j++)
                {
                    if (_grid[i, j].HasValue)
                    {
                        int value = _grid[i, j].Value;
                        if (numbersUsed[value])
                        {
                            return(PuzzleStatus.CannotBeSolved);
                        }
                        numbersUsed[value] = true;
                    }
                }
            }

            // Same for rows
            for (int j = 0; j < _gridSize; j++)
            {
                numbersUsed.SetAll(false);
                for (int i = 0; i < _gridSize; i++)
                {
                    if (_grid[i, j].HasValue)
                    {
                        int value = _grid[i, j].Value;
                        if (numbersUsed[value])
                        {
                            return(PuzzleStatus.CannotBeSolved);
                        }
                        numbersUsed[value] = true;
                    }
                }
            }

            // Same for boxes
            for (int boxNumber = 0; boxNumber < _gridSize; boxNumber++)
            {
                numbersUsed.SetAll(false);
                int boxStartX = (boxNumber / _boxSize) * _boxSize;
                for (int x = boxStartX; x < boxStartX + _boxSize; x++)
                {
                    int boxStartY = (boxNumber % _boxSize) * _boxSize;
                    for (int y = boxStartY; y < boxStartY + _boxSize; y++)
                    {
                        if (_grid[x, y].HasValue)
                        {
                            int value = _grid[x, y].Value;
                            if (numbersUsed[value])
                            {
                                return(PuzzleStatus.CannotBeSolved);
                            }
                            numbersUsed[value] = true;
                        }
                    }
                }
            }

            // Now figure out whether this is a solved puzzle or a work in progress
            // based on whether there are any holes
            for (int i = 0; i < _gridSize; i++)
            {
                for (int j = 0; j < _gridSize; j++)
                {
                    if (!_grid[i, j].HasValue)
                    {
                        return(PuzzleStatus.InProgress);
                    }
                }
            }

            // If we made it this far, this state is a valid solution!  Woo hoo!
            return(PuzzleStatus.Solved);
        }