// -----------------------------------------------------------------------
        void DisplayObjectErrorsAndWarnings(List <ErrorWarning> errors, List <ErrorWarning> warnings)
        {
            // -- Determine wich objects have errors or warnings --
            var objectIds = P.append(P.map(e => e.ObjectId, errors), P.map(w => w.ObjectId, warnings));

            objectIds = P.removeDuplicates(objectIds);

            // -- Display the errors/warnings on the objects in the graph --
            foreach (var id in objectIds)
            {
                // -- Determine if node is visible --
                var node = IStorage[id];
                if (!DisplayRoot.IsParentOf(node))
                {
                    continue;
                }
                var pos = node.GlobalPosition;
                if (!VisibleGraphRect.Contains(pos))
                {
                    continue;
                }
                // -- Determine errors/warnings for this particular node --
                var nodeErrors   = P.filter(e => e.ObjectId == id, errors);
                var nodeWarnings = P.filter(w => w.ObjectId == id, warnings);
                // -- Display the appropriate error/warning icon --
                var r = Math3D.BuildRectCenteredAt(pos, 32f, 32f);
                r = myGraphics.TranslateAndScale(r);
                DisplayErrorsAndWarningAt(r, nodeErrors, nodeWarnings);
            }
        }
        // ----------------------------------------------------------------------
        void MouseDownEvent()
        {
            MouseDownPosition = ViewportMousePosition;
            // Update click count.
            myClickCount = Event.current.clickCount;
            // Keep a copy of the scroll position.
            MouseDragStartPosition   = ViewportMousePosition;
            DragStartDisplayPosition = ScrollPosition;
            // Update the selected object.
            SelectedObjectBeforeMouseDown = SelectedObject;
            switch (Event.current.button)
            {
            case 0: {     // Left mouse button
                // -- Update Hot Zones --
                var pickInfo = myGraphics.GetPickInfo(GraphMousePosition, IStorage);
                if (HotZoneMouseClick(WindowMousePosition, pickInfo))
                {
                    break;
                }
                // -- Update Selected Object --
                DetermineSelectedObject();
                if (SelectedObject != null && DisplayRoot.IsParentOf(SelectedObject))
                {
                    if (SelectedObject.IsNode && IsDisplayRootKeyDown && IsDoubleClick &&
                        !(SelectedObject.IsKindOfFunction || SelectedObject.IsInstanceNode))
                    {
                        if (SelectedObject == DisplayRoot)
                        {
                            if (IsShiftKeyDown && IStorage.HasBackwardNavigationHistory)
                            {
                                iCS_UserCommands.ReloadFromBackwardNavigationHistory(IStorage);
                            }
                        }
                        else
                        {
                            iCS_UserCommands.SetAsDisplayRoot(SelectedObject);
                        }
                    }
                    IsDragEnabled = true;
                }
                CloseSubEditor();
                break;
            }

            case 1: {     // Right mouse button
                if (!IsMultiSelectionActive)
                {
                    DetermineSelectedObject();
                }
                myShowDynamicMenu = true;
                break;
            }

            case 2: {     // Middle mouse button
                // Mainly used for panning the viewport.
                break;
            }
            }
        }
        // ----------------------------------------------------------------------
        // Returns the closest visible port at graph position.
        iCS_EditorObject GetClosestVisiblePortAt(Vector2 graphPosition)
        {
            var port = IStorage.GetClosestPortAt(graphPosition);

            if (port != null && DisplayRoot.IsParentOf(port))
            {
                return(port);
            }
            return(null);
        }
        // ----------------------------------------------------------------------
        // Returns the visible node at graph position.
        iCS_EditorObject GetVisibleNodeAt(Vector2 graphPosition, iCS_EditorObject exclude = null)
        {
            var node = IStorage.GetNodeAt(graphPosition, exclude);

            // Anything outside the DisplayRoot will be mapped to the DisplayRoot.
            if (node != null && DisplayRoot.IsParentOf(node))
            {
                return(node);
            }
            return(DisplayRoot);
        }
        // ----------------------------------------------------------------------
        // Returns the closest visible port at graph position.
        iCS_EditorObject GetVisibleNodeWithEdgeAt(Vector2 graphPosition)
        {
            var node = IStorage.GetNodeWithEdgeAt(graphPosition);

            if (node != null)
            {
                if (DisplayRoot.IsParentOf(node))
                {
                    return(node);
                }
                if (node == DisplayRoot && IStorage.ShowDisplayRootNode == true)
                {
                    return(node);
                }
            }
            return(null);
        }
        // ----------------------------------------------------------------------
        public void TakeAnimationSnapshotForAll()
        {
            int len = EditorObjects.Count;

            myWasPresent = new bool[len];
            myWasVisible = new bool[len];
            for (int i = 0; i < EditorObjects.Count; ++i)
            {
                // Update presence & visible flags.
                var obj = EditorObjects[i];
                if (obj == null || !obj.IsValid)
                {
                    myWasPresent[i] = myWasVisible[i] = false;
                    continue;
                }
                myWasPresent[i] = true;
                myWasVisible[i] = IsVisibleInLayout(obj);
                // Get copy of the initial position.
                if (obj == DisplayRoot || DisplayRoot.IsParentOf(obj))
                {
                    obj.ResetAnimationRect(obj.GlobalRect);
                }
            }
        }