public static void SaveRecord(GameObject forObject, ObjectRecord record, bool isUndo)
        {
            UndoRedoOps operations = new UndoRedoOps();
            int         key        = forObject.GetHashCode();

            bool containsEntry = dataContainer.objectsHistory.TryGetValue(key, out operations);


            if (containsEntry)
            {
                if (isUndo)
                {
                    if (operations.undoOperations.Count == undoLimit)
                    {
                        operations.undoOperations[0].Destruct();
                        operations.undoOperations.RemoveAt(0);
                    }

                    operations.undoOperations.Add(record);
                }

                else
                {
                    if (operations.redoOperations.Count == undoLimit)
                    {
                        operations.redoOperations[0].Destruct();
                        operations.redoOperations.RemoveAt(0);
                    }

                    operations.redoOperations.Add(record);
                }
            }

            else
            {
                if (dataContainer.objectsHistory.Count == objectRecordLimit)
                {
                    dataContainer.objectsHistory[0].Destruct();
                    dataContainer.objectsHistory.Remove(0);
                }


                operations                = new UndoRedoOps();
                operations.gameObject     = forObject;
                operations.undoOperations = new List <ObjectRecord>();
                operations.redoOperations = new List <ObjectRecord>();

                if (isUndo)
                {
                    operations.undoOperations.Add(record);
                }
                else
                {
                    operations.redoOperations.Add(record);
                }

                dataContainer.objectsHistory.Add(key, operations);
            }
        }
        public static bool DoUndoRedoOperation(GameObject forObject, bool doUndo)
        {
            UndoRedoOps   operations = new UndoRedoOps();
            int           key        = forObject.GetHashCode();
            Quaternion    collRot    = Quaternion.identity;
            Vector3       collPos    = Vector3.zero;
            CollRecognize collRecog  = forObject.GetComponentInChildren <CollRecognize>();

            //ColliderState colliderState = SaveColliderState(forObject);
            //ChildStateTuple[] childrenStates = SaveChildrenStates(forObject);


            if (collRecog)
            {
                collRot = collRecog.gameObject.transform.rotation;
                collPos = collRecog.gameObject.transform.position;
            }



            bool containsEntry = dataContainer.objectsHistory.TryGetValue(key, out operations);

            if (containsEntry)
            {
                int          lastIndex = -1;
                ObjectRecord operation;


                if (doUndo)
                {
                    lastIndex = operations.undoOperations.Count - 1;
                    operation = operations.undoOperations[lastIndex];
                    operations.undoOperations.RemoveAt(lastIndex);
                }

                else
                {
                    lastIndex = operations.redoOperations.Count - 1;
                    operation = operations.redoOperations[lastIndex];
                    operations.redoOperations.RemoveAt(lastIndex);
                }


                if (!operation.isMeshless)
                {
                    if (operation.currPos != forObject.transform.position)
                    {
                        PivotManager.MovePivot(forObject, forObject.transform.position + operation.changeInPos, true);
                    }

                    if (!operation.currRot.Equals(forObject.transform.rotation))
                    {
                        PivotManager.RotatePivot(forObject, operation.currRot, true);
                    }
                }

                else
                {
                    if (!operation.currPos.Equals(forObject.transform.position))
                    {
                        PivotManager.MovePivotForMeshless(forObject, forObject.transform.position + operation.changeInPos, true);
                    }

                    if (!operation.currRot.Equals(forObject.transform.rotation))
                    {
                        PivotManager.RotatePivotForMeshless(forObject, operation.currRot, true);
                    }
                }


                //RestoreColliderState(forObject, operation.colliderState);
                //RestoreChildrenStates(operation.childrenStates);

                //RestoreColliderState(forObject, colliderState);
                //RestoreChildrenStates(childrenStates);


                if (collRecog)
                {
                    collRecog.gameObject.transform.rotation = collRot;
                    collRecog.gameObject.transform.position = collPos;
                }


                return(true);
            }


            else
            {
                return(false);
            }
        }
 /// <summary>
 /// Shifts all visual nodes to the right by the specified amount.
 /// </summary>
 /// <param name="nodeId">The id of the node that is not affected by the shift.</param>
 /// <param name="rightShift">The amount by which to shift to the right.</param>
 /// <param name="moveCall">A value that indicates whether this call belongs to a node
 /// move operation.</param>
 public void RightShift(String nodeId, double rightShift, UndoRedoOps callType)
 {
     for (int i = 0; i < ElementProvider.NodesCount; i++)
     {
         IVisualNode node = ElementProvider.GetNode(i);
         if (node.Id.Equals(nodeId))
             continue;
         node.XPos += rightShift;
         Model.ChangePosition(node.Id, (int)node.XPos, (int)node.YPos);
     }
     for (int i = 0; i < ElementProvider.NameFieldsCount; i++)
     {
         INameField nField = ElementProvider.GetNameField(i);
         if (nField.Id.Equals(nodeId))
             continue;
         nField.XPos += rightShift;
     }
     ViewSizeChanged(this, new ViewSizeChangedEventArgs(ViewWidth + rightShift, ViewHeight));
     switch (callType)
     {
         case UndoRedoOps.Move:
             UndoManager.MoveRightShift += rightShift;
             break;
         case UndoRedoOps.Create:
             UndoManager.CreateRightShift += rightShift;
             break;
         case UndoRedoOps.ChangeSize:
             UndoManager.SizeChangeRightShift += rightShift;
             break;
         default:
             break;
     }
 }
 /// <summary>
 /// Adjusts the size of the visual presentation of the petrinet to fit the positioning of all
 /// nodes. To be called after the visual presentation of a node has been repositioned.
 /// </summary>
 /// <param name="id">The id of the node that requested the adjustment.</param>
 /// <param name="callType">A value that indicates what kind of operation is responsible for this 
 /// call.</param>
 public void AdjustViewSize(String id, UndoRedoOps callType)
 {
     IVisualNode node = ElementProvider.GetNode(id);
     INameField nField = ElementProvider.GetNameField(id);
     double xNameOverhang = (nField.Width > node.DrawSize ? (nField.Width - node.DrawSize) / 2 : 0);
     double yNameOverhang = nField.Height;
     double spanToRight = node.XPos + node.DrawSize / 2 + xNameOverhang;
     double spanToBottom = node.YPos + node.DrawSize / 2;
     double spanPastLeft = -(node.XPos - node.DrawSize / 2) + xNameOverhang;
     double spanPastTop = -(node.YPos - node.DrawSize / 2) + yNameOverhang;
     // if the node is located past the right edge of the presentation, add width
     if (spanToRight > ViewWidth)
         ViewSizeChanged(this, new ViewSizeChangedEventArgs(spanToRight, ViewHeight));
     // if the node is located past the bottom edge of the presentation, add height
     if (spanToBottom > ViewHeight)
         ViewSizeChanged(this, new ViewSizeChangedEventArgs(ViewWidth, spanToBottom));
     // if the node is located past the left edge of the presentation, put node on left edge,
     // reposition all other nodes and add width
     if (spanPastLeft > 0)
     {
         node.XPos = node.DrawSize / 2 + xNameOverhang;
         nField.XPos = 0;
         Model.ChangePosition(node.Id, (int)node.XPos, (int)node.YPos);
         RightShift(node.Id, spanPastLeft, callType);
     }
     // if the node is located past the top edge of the presentation, put node on top edge,
     // reposition all other nodes and add height
     if (spanPastTop > 0)
     {
         node.YPos = node.DrawSize / 2 + yNameOverhang;
         nField.YPos = 0;
         Model.ChangePosition(node.Id, (int)node.XPos, (int)node.YPos);
         DownShift(node.Id, spanPastTop, callType);
     }
     ScrollIntoView(id);
 }