private void SetState(PuzzleStateNode newState, bool animate)
    {
        PuzzleStateNode lastState = state;

        m_State = newState;

        stateChangeTime = Time.time;
        if (animate)
        {
            itemChangeTime = stateChangeTime + itemDelay;
            doneTime       = stateChangeTime;
        }
        else
        {
            itemChangeTime = stateChangeTime;
            doneTime       = stateChangeTime;
        }

        bool itemChange = false;

        foreach (var element in puzzle.dynamicElements)
        {
            object oldVal = puzzle.GetElementValue(lastState.state, element);
            object newVal = puzzle.GetElementValue(newState.state, element);
            if (!newVal.Equals(oldVal))
            {
                PuzzleContainer container = puzzle.GetElementContainer(element);
                ContainerFront  front     = GetContainer(container);
                StartCoroutine(front.AnimateValue((bool)oldVal, (bool)newVal, animate));
                itemChange = true;
            }
        }
        if (itemChange && animate)
        {
            doneTime += itemAndEffectDuration;
        }

        bool movement = false;

        foreach (var item in puzzle.items)
        {
            PuzzleNode oldNode = puzzle.GetItemNode(lastState.state, item);
            PuzzleNode newNode = puzzle.GetItemNode(newState.state, item);
            if (newNode != oldNode)
            {
                movement = true;
            }
            ItemFront front = GetItem(item);
            // Animate regardless of whether old and new node are the same.
            // Movement of other items may cause static item to change offset.
            StartCoroutine(front.AnimateNode(oldNode, newNode, state, animate));
        }
        if (movement && animate)
        {
            itemChangeTime += moveDuration;
            doneTime       += moveDuration;
        }
    }
    public void AddItem(PuzzleItem item)
    {
        ItemFront itemFront = Instantiate(itemPrefab) as ItemFront;

        itemFront.transform.parent = transform;
        itemFront.gameObject.name  = "Item " + item.GetType().Name.Replace("Puzzle", "");
        itemFront.Set(this, item);
        items.Add(itemFront);
    }
    public void Reset()
    {
        undoStack.Clear();
        m_State = puzzle.startNode;

        foreach (var element in puzzle.dynamicElements)
        {
            PuzzleContainer container = puzzle.GetElementContainer(element);
            ContainerFront  front     = GetContainer(container);
            front.SetElement(element);
        }

        foreach (var item in puzzle.items)
        {
            PuzzleNode newNode = item.defaultNode;
            ItemFront  front   = GetItem(item);
            front.SetNodePos(newNode, state);
        }
    }