/// <summary>
        /// Removes scene item from document and scene.
        /// </summary>
        /// <param name="proxy">Proxy to delete.</param>
        private void RemoveSceneItem(BaseEditorProxy proxy)
        {
            // Cannot delete scene proxy or null proxy
            if (proxy == null || proxy is SceneDocumentProxy)
            {
                return;
            }

            // Handle removing entity
            if (proxy is EntityProxy)
            {
                // Remove all child proxies
                foreach (TreeNode node in proxy.TreeNode.Nodes)
                {
                    (node.Tag as BaseEditorProxy).Remove();
                }
            }
            else
            {
                // Just remove this proxy
                proxy.Remove();
            }

            // Delete tree node
            SceneTreeView.Nodes.Remove(proxy.TreeNode);
        }
        /// <summary>
        /// Called when an object is deleted.
        /// </summary>
        private void DeleteSceneObjectMenu_Click(object sender, EventArgs e)
        {
            // Get editor proxy
            BaseEditorProxy proxy = GetSelectedProxy();

            // Cannot delete scene proxy or null proxy
            if (proxy == null || proxy is SceneDocumentProxy)
            {
                return;
            }

            // Select parent node based on type
            TreeNode parentNode = null;

            if (proxy is EntityProxy)
            {
                parentNode = documentProxy.TreeNode;
            }
            else
            {
                parentNode = proxy.TreeNode.Parent;
            }

            // Change selected item to parent
            SceneTreeView.SelectedNode = parentNode;

            // Delete selected item
            RemoveSceneItem(proxy);
        }
        /// <summary>
        /// Called when context menu is opened.
        /// </summary>
        private void SceneContextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            // Check if user has opened context menu on an entity node
            bool            enableComponentMenus = false;
            BaseEditorProxy proxy  = GetSelectedProxy();
            EntityProxy     entity = GetSelectedEntity();

            if (entity != null)
            {
                enableComponentMenus = true;
            }

            // Disable/Enable component menus
            EnableComponentsMenu(enableComponentMenus);

            // Cannot delete scene document proxy
            if (proxy is SceneDocumentProxy)
            {
                DeleteSceneObjectMenu.Enabled = false;
            }
            else
            {
                DeleteSceneObjectMenu.Enabled = true;
            }
        }
        /// <summary>
        /// A tree view item has been selected.
        /// </summary>
        private void SceneTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            UpdatePropertyGrid();

            // Get selected proxy
            BaseEditorProxy proxy = SceneTreeView.SelectedNode.Tag as BaseEditorProxy;

            // Enable/disable terrain editor
            if (proxy is QuadTerrainProxy)
            {
                TerrainEditorPanel.Visible = true;
                terrainEditMode            = true;
                currentTerrainProxy        = (QuadTerrainProxy)proxy;
                terrainEditor1.SetTerrain(currentTerrainProxy.Component, sceneDocument);
                (proxy as QuadTerrainProxy).Component.EnablePicking = true;
            }
            else
            {
                TerrainEditorPanel.Visible = false;
                terrainEditMode            = false;
                if (currentTerrainProxy != null)
                {
                    currentTerrainProxy.Component.EnablePicking = false;
                    currentTerrainProxy = null;
                    terrainEditor1.ClearTerrain();
                }
            }
        }
        /// <summary>
        /// Pushes property undo information onto the undo stack.
        /// </summary>
        /// <param name="propertyInfo">Property information.</param>
        public void PushUndo(BaseEditorProxy proxy, PropertyInfo propertyInfo)
        {
            // Do nothing if locked
            if (lockUndoRedo)
            {
                return;
            }

            // Making a change invalidates redo.
            // This is to prevent inconsistent redo operations.
            if (redoStack.Count > 0)
            {
                redoStack.Clear();
            }

            // Set undo information
            UndoInfo undoInfo = new UndoInfo
            {
                Type         = UndoTypes.Property,
                Proxy        = proxy,
                PropertyInfo = propertyInfo,
                Value        = propertyInfo.GetValue(proxy, null),
            };

            // Push onto undo stack
            undoStack.Push(undoInfo);

            // Raise event
            if (OnPushUndo != null)
            {
                OnPushUndo(this, null);
            }
        }
        /// <summary>
        /// Gets selected editor proxy in scene view.
        /// </summary>
        /// <returns>Editor proxy.</returns>
        private BaseEditorProxy GetSelectedProxy()
        {
            // Get selected proxy
            BaseEditorProxy proxy = null;

            if (SceneTreeView.SelectedNode != null)
            {
                proxy = SceneTreeView.SelectedNode.Tag as BaseEditorProxy;
            }

            return(proxy);
        }
        /// <summary>
        /// Adds a proxy to the document tree.
        /// </summary>
        /// <param name="parent">Parent tree node.</param>
        /// <param name="proxy">Proxy to resource.</param>
        /// <returns>Tree node added.</returns>
        private TreeNode AddTreeNode(TreeNode parent, BaseEditorProxy proxy)
        {
            // Determine image to use
            string imageKey;

            if (proxy is SceneDocumentProxy)
            {
                imageKey = "Scene";
            }
            else if (proxy is EntityProxy)
            {
                imageKey = "Entity";
            }
            else if (proxy is QuadTerrainProxy)
            {
                imageKey = "QuadTerrain";
            }
            else if (proxy is SphereProxy)
            {
                imageKey = "Geometry";
            }
            else if (proxy is LightProxy)
            {
                imageKey = "Light";
            }
            else
            {
                imageKey = "Unknown";
            }

            // Create new tree node
            TreeNode node = new TreeNode();

            node.Text             = proxy.Name;
            node.ImageKey         = imageKey;
            node.SelectedImageKey = imageKey;
            node.Tag = proxy;

            // Add new tree node
            if (parent == null)
            {
                SceneTreeView.Nodes.Add(node);
            }
            else
            {
                parent.Nodes.Add(node);
            }

            // Set node in proxt
            proxy.TreeNode = node;

            return(node);
        }
        /// <summary>
        /// Gets selected entity in editor, either from directly
        ///  selecting entity or one of its child proxies.
        /// </summary>
        /// <returns></returns>
        private EntityProxy GetSelectedEntity()
        {
            // Get selected proxy
            BaseEditorProxy proxy = GetSelectedProxy();

            // Return entity directly
            if (proxy is EntityProxy)
            {
                return(proxy as EntityProxy);
            }

            // Return entity from component
            if (proxy is BaseComponentProxy)
            {
                return(proxy.EntityProxy);
            }

            return(null);
        }