/// <summary>
		/// Traverse from the bottom right of the scene graph (top visible node)
		/// up the tree determining which parent nodes are occluded by their children
		/// nodes.
		/// </summary>
		/// <param name="n">The node to find occlusions for.</param>
		/// <param name="pickPath">
		/// A pick path representing the bounds of <c>n</c> in parent coordinates.
		/// </param>
		/// <remarks>
		/// Note that this is only detecting a subset of occlusions (parent, child),
		/// others such as overlapping siblings or cousins are not detected.
		/// </remarks>
		public void DetectOcclusions(PNode n, PPickPath pickPath) {
			if (n.FullIntersects(pickPath.PickBounds)) {
				pickPath.PushMatrix(n.MatrixReference);
		
				int count = n.ChildrenCount;
				for (int i = count - 1; i >= 0; i--) {
					PNode each = n[i];
					if (n.Occluded) {
						// if n has been occluded by a previous decendent then
						// this child must also be occluded
						each.Occluded = true;
					} else {
						// see if child each occludes n
						DetectOcclusions(each, pickPath);
					}
				}

				// see if n occludes it's parents		
				if (!n.Occluded) {
					if (n.Intersects(pickPath.PickBounds)) {
						if (n.IsOpaque(pickPath.PickBounds)) {
							PNode p = n.Parent;
							while (p != null && !p.Occluded) {
								p.Occluded = true;
							}
						}
					}
				}
	
				pickPath.PopMatrix(n.MatrixReference);
			}				
		}
		/// <summary>
		/// Overridden.  Returns true if this node or any pickable descendends are picked.
		/// </summary>
		/// <remarks>
		/// If a pick occurs the pickPath is modified so that this node is always returned as
		/// the picked node, even if it was a decendent node that initialy reported the pick.
		/// </remarks>
		/// <param name="pickPath"></param>
		/// <returns>True if this node or any descendents are picked; false, otherwise.</returns>
		public override bool FullPick(PPickPath pickPath) {
			if (base.FullPick(pickPath)) {
				PNode picked = pickPath.PickedNode;
			
				// this code won't work with internal cameras, because it doesn't pop
				// the cameras view transform.
				while (picked != this) {
					pickPath.PopMatrix(picked.MatrixReference);
					pickPath.PopNode(picked);
					picked = pickPath.PickedNode;
				}
			
				return true;
			}
			return false;
		}
		public virtual PActivity DirectCameraViewToFocus(PCamera aCamera, PNode aFocusNode, PPickPath path, int duration) {
			PMatrix originalViewMatrix = aCamera.ViewMatrix;

			// Scale the canvas to include
			SizeF s = new SizeF(1, 0);
			s = aFocusNode.GlobalToLocal(s);
		
			float scaleFactor = s.Width / aCamera.ViewScale;
			PointF scalePoint = PUtil.CenterOfRectangle(aFocusNode.GlobalFullBounds);
			if (scaleFactor != 1) {
				aCamera.ScaleViewBy(scaleFactor, scalePoint.X, scalePoint.Y);
			}
		
			// Pan the canvas to include the view bounds with minimal canvas
			// movement.
			aCamera.AnimateViewToPanToBounds(aFocusNode.GlobalFullBounds, 0);

			// Get rid of any white space. The canvas may be panned and
			// zoomed in to do this. But make sure not stay constrained by max
			// magnification.
			//FillViewWhiteSpace(aCamera);

			PMatrix resultingMatrix = aCamera.ViewMatrix;
			aCamera.ViewMatrix = originalViewMatrix;

			// Animate the canvas so that it ends up with the given
			// view transform.
			PActivity animateCameraViewActivity = AnimateCameraViewMatrixTo(aCamera, resultingMatrix, duration);

			PControl controlNode = (PControl)aFocusNode;
			aCamera.Root.WaitForActivities();

			controlNode.CurrentCanvas = path.TopCamera.Canvas;
			PointF pf = path.GetPathTransformTo(controlNode).Transform(new PointF(controlNode.X, controlNode.Y));
			controlNode.ControlLocation = new Point((int)pf.X, (int)pf.Y);

			controlNode.Editing = true;

			return animateCameraViewActivity;
		}
Example #4
0
		/// <summary>
		/// Try to pick this node and all of its descendents.
		/// </summary>
		/// <param name="pickPath">The pick path to add the node to if its picked.</param>
		/// <returns>True if this node or one of its descendents was picked; else false.</returns>
		/// <remarks>
		/// <b>Notes to Inheritors:</b>  Most subclasses should not need to override this
		/// method. Instead they should override <c>Pick</c> or <c>PickAfterChildren</c>.
		///	</remarks>
		public virtual bool FullPick(PPickPath pickPath) {
			if ((Pickable || ChildrenPickable) && FullIntersects(pickPath.PickBounds)) {
				pickPath.PushNode(this);
				pickPath.PushMatrix(matrix);
			
				bool thisPickable = Pickable && pickPath.AcceptsNode(this);

				if (thisPickable && Pick(pickPath)) {
					return true;
				}

				if (ChildrenPickable) {
					int count = ChildrenCount;
					for (int i = count - 1; i >= 0; i--) {
						if (children[i].FullPick(pickPath)) {
							return true;
						}
					}				
				}

				if (thisPickable && PickAfterChildren(pickPath)) {
					return true;
				}

				pickPath.PopMatrix(matrix);
				pickPath.PopNode(this);
			}

			return false;
		}
Example #5
0
		/// <summary>
		/// Try to pick this node before its children have had a chance to be picked.
		/// </summary>
		/// <param name="pickPath">The pick path used for the pick operation.</param>
		/// <returns>True if this node was picked; else false.</returns>
		/// <remarks>
		/// Nodes that paint on top of their children may want to override this method to see
		/// if the pick path intersects that paint.
		/// </remarks>
		protected virtual bool Pick(PPickPath pickPath) {
			return false;
		}
Example #6
0
		/// <summary>
		/// Dispatch the given PInputEvent to the given pick path.
		/// </summary>
		/// <param name="e">A PInputEventArgs that contains the event data.</param>
		/// <param name="type">The type of PInputEvent being dispatched.</param>
		/// <param name="path">The pick path to which the PInputEvent will be dispatched.</param>
		public virtual void DispatchToPath(PInputEventArgs e, PInputType type, PPickPath path) {
			if (path != null) {
				//set the type and clear the handled bit since the same event object is
				//used to send multiple events such as mouseEntered/mouseExited and mouseMove.
				e.Type = type;
				e.Handled = false;

				path.ProcessEvent(e);
			}
		}
Example #7
0
		/// <summary>
		/// Check if the mouse has entered or exited a node during a drag and drop
		/// operation and, if so, dispatch the appropriate event.
		/// </summary>
		/// <param name="e">A PInputEventArgs that contains the event data.</param>
		public virtual void CheckForMouseDragEnteredAndExited(PInputEventArgs e) {
			PNode c = (mouseOver != null) ? mouseOver.PickedNode : null; 
			PNode p = (previousMouseOver != null) ? previousMouseOver.PickedNode : null;

			if (c != p) {
				DispatchToPath(e, PInputType.DragLeave, previousMouseOver);
				DispatchToPath(e, PInputType.DragEnter, mouseOver);
				previousMouseOver = mouseOver;
			}
		}
Example #8
0
		/// <summary>
		/// Dispatch the given event to the appropriate focus node.
		/// </summary>
		/// <param name="e">An PInputEventArgs that contains the event data.</param>
		public virtual void Dispatch(PInputEventArgs e) {
			switch (e.Type) {
				case PInputType.KeyDown:
					DispatchToPath(e, PInputType.KeyDown, KeyboardFocus);
					break;

				case PInputType.KeyPress:
					DispatchToPath(e, PInputType.KeyPress, KeyboardFocus);
					break;

				case PInputType.KeyUp:
					DispatchToPath(e, PInputType.KeyUp, KeyboardFocus);
					break;

				case PInputType.Click:
					//The click event occurs before the MouseRelease so we can
					//dispatch to the current focused node as opposed to the
					//previously focused node
					if (MouseFocus.PickedNode == MouseOver.PickedNode) {
						DispatchToPath(e, PInputType.Click, MouseFocus);
					}
					break;

				case PInputType.DoubleClick:
					//The double click event occurs before the MouseRelease so we can
					//dispatch to the current focused node as opposed to the
					//previously focused node
					if (MouseFocus.PickedNode == MouseOver.PickedNode) {
						DispatchToPath(e, PInputType.DoubleClick, MouseFocus);
					}
					break;

				case PInputType.MouseDown:
					MouseFocus = MouseOver;
					DispatchToPath(e, PInputType.MouseDown, MouseFocus);
					break;

				case PInputType.MouseUp:
					CheckForMouseEnteredAndExited(e);
					DispatchToPath(e, PInputType.MouseUp, MouseFocus);
					mouseFocus = null;
					break;

				case PInputType.MouseDrag:
					CheckForMouseEnteredAndExited(e);
					DispatchToPath(e, PInputType.MouseDrag, MouseFocus);
					break;

				case PInputType.MouseMove:
					CheckForMouseEnteredAndExited(e);
					DispatchToPath(e, PInputType.MouseMove, MouseOver);
					break;

				case PInputType.MouseWheel:
					MouseFocus = MouseOver;
					DispatchToPath(e, PInputType.MouseWheel, MouseOver);
					break;
				case PInputType.DragOver:
					CheckForMouseDragEnteredAndExited(e);
					DispatchToPath(e, PInputType.DragOver, MouseOver); 
					break;
				case PInputType.DragDrop:
					CheckForMouseDragEnteredAndExited(e);
					DispatchToPath(e, PInputType.DragDrop, MouseOver);
					break;
			}
		}
		/// <summary>
		/// Overridden.  Return false since this node should never be picked.
		/// </summary>
		/// <param name="pickPath">The pick path used for the pick operation.</param>
		/// <returns>False since this node should never be picked.</returns>
		protected override bool PickAfterChildren(PPickPath pickPath) {
			return false;
		}
Example #10
0
		//****************************************************************
		// Picking - Methods for picking the camera and it's view.
		//****************************************************************

		/// <summary>
		/// Generate and return a PPickPath for the point x,y specified in the local
		/// coordinate system of this camera.
		/// </summary>
		/// <param name="x">The x coordinate of the pick point.</param>
		/// <param name="y">The y coordinate of the pick point.</param>
		/// <param name="halo">
		/// The value to use for the width and height of the rectangle used for picking.
		/// </param>
		/// <returns>A PPickPath for the given point.</returns>
		/// <remarks>
		/// Picking is done with a rectangle, halo specifies how large that rectangle
		/// will be.
		/// </remarks>
		public virtual PPickPath Pick(float x, float y, float halo) {
			RectangleF b = PUtil.InflatedRectangle(new PointF(x, y), halo, halo);
			PPickPath result = new PPickPath(this, b);

			FullPick(result);
			
			// make sure this camera is pushed.
			if (result.NodeStackReference.Count == 0) {
				result.PushNode(this);
				result.PushMatrix(MatrixReference);
			}

			return result;
		}
Example #11
0
		/// <summary>
		/// Constructs a new PPickPath.
		/// </summary>
		/// <param name="aCamera">The camera that originated the pick action.</param>
		/// <param name="aScreenPickBounds">The bounds being picked.</param>
		public PPickPath(PCamera aCamera, RectangleF aScreenPickBounds) {
			pickBoundsStack = new Stack();
			bottomCamera = null;
			topCamera = aCamera;
			nodeStack = new Stack();
			matrixStack = new Stack();
			pickBoundsStack.Push(aScreenPickBounds);

			CURRENT_PICK_PATH = this;
		}
Example #12
0
		/// <summary>
		/// Overridden.  Only picks this node's children if the pick bounds intersects the
		/// clip.
		/// </summary>
		/// <param name="pickPath">The pick path to add the node to if its picked.</param>
		/// <returns>
		/// True if this node or one of its descendents was picked; else false.
		/// </returns>
		public override bool FullPick(PPickPath pickPath) {
			if (Pickable && FullIntersects(pickPath.PickBounds)) {
				pickPath.PushNode(this);
				pickPath.PushMatrix(MatrixReference);
			
				if (Pick(pickPath)) {
					return true;
				}

				if (ChildrenPickable && PUtil.PathIntersectsRect(PathReference, pickPath.PickBounds)) { 		
					int count = ChildrenCount;
					for (int i = count - 1; i >= 0; i--) {
						PNode each = this.GetChild(i);
						if (each.FullPick(pickPath))
							return true;
					}				
				}

				if (PickAfterChildren(pickPath)) {
					return true;
				}

				pickPath.PopMatrix(MatrixReference);
				pickPath.PopNode(this);
			}

			return false;
		}
Example #13
0
        /// <summary>
        /// Show the interface if it isn't already being shown
        /// 
        /// If it is being shown, and the user presses escape, remove it
        /// </summary>
        public override void OnKeyDown(object sender, PInputEventArgs e)
        {
            base.OnKeyDown(sender, e);
            //If the interface isn't shown, and should be
            if (IsPressed == false && Interface.Accepts(e))
            {
                //Clear the text from the last time it was used, and show it to the user
                Interface.Entry.Text = "";
                Camera.AddChild(Interface);

                //Fetch the current keyboard focus to save for later, then shift the keyboard focus to the interface
                if (Page.LastPage != null) { KeyFocus = Page.LastPage.ToPickPath(); }
                else { KeyFocus = Camera.ToPickPath(); }
                e.InputManager.KeyboardFocus = Interface.Entry.ToPickPath(e.Camera, Interface.Entry.Bounds);

                //Activate the interface
                IsPressed = true;
                Interface.Activate(sender, e);
            }

            //If the user pressed ecape, remove the interface
            else if (e.KeyCode == Keys.Escape) { RemoveInterface(e); }

            //Register the Activate button press, if appropriate
            if (Interface.Accepts(e)) { Interface.RegisterActivateButtonPress(sender, e); }
        }
Example #14
0
		/// <summary>
		/// Pick all the layers that the camera is looking at.
		/// </summary>
		/// <param name="pickPath">The pick path to use for the pick operation.</param>
		/// <returns>
		/// True if an object viewed by the camera was picked; else false.
		/// </returns>
		/// <remarks>
		/// This method is only called when the camera's view matrix and clip are
		/// applied to the pickPath.
		/// </remarks>
		protected virtual bool PickCameraView(PPickPath pickPath) {
			int count = LayerCount;
			for (int i = count - 1; i >= 0; i--) {
				PLayer each = layers[i];
				if (each.FullPick(pickPath))
					return true;
			}
			return false;
		}
Example #15
0
		/// <summary>
		/// Overridden.  After the direct children of the camera have been given a chance
		/// to be picked objects viewed by the camera are given a chance to be picked.
		/// </summary>
		/// <param name="pickPath">The pick path used for the pick operation.</param>
		/// <returns>
		/// True if an object viewed by the camera was picked; else false.
		/// </returns>
		protected override bool PickAfterChildren(PPickPath pickPath) {
			if (Intersects(pickPath.PickBounds)) {
				pickPath.PushMatrix(viewMatrix);

				if (PickCameraView(pickPath)) {
					return true;
				}

				pickPath.PopMatrix(viewMatrix);
				return true;
			}
			return false;
		}
Example #16
0
		/// <summary>
		/// Try to pick this node after its children have had a chance to be picked.
		/// </summary>
		/// <param name="pickPath">The pick path used for the pick operation.</param>
		/// <returns>True if this node was picked; else false.</returns>
		/// <remarks>
		/// <b>Notes to Inheritors:</b>  Most subclasses that define a different geometry will
		/// need to override this method.
		/// </remarks>
		protected virtual bool PickAfterChildren(PPickPath pickPath) {
			if (Intersects(pickPath.PickBounds)) {
				return true;
			}
			return false;
		}
Example #17
0
		/// <summary>
		/// Creates a pick path with the given Camera and pickbounds and adds this node.
		/// </summary>
		/// <param name="aCamera">The camera to use when creating the pick path.</param>
		/// <param name="pickBounds">The pick bounds to use when creating the pick path.</param>
		/// <returns>
		/// A pick path with the given camera and pickbounds that contains this node
		/// </returns>
		public virtual PPickPath ToPickPath(PCamera aCamera, RectangleF pickBounds) {
			PPickPath pickPath = new PPickPath(aCamera, pickBounds);
			pickPath.PushNode(this);
			return pickPath;
		}
Example #18
0
		/// <summary>
		/// Overridden.  Performs picking in canvas coordinates if <see cref="PickMode">PickMode</see>
		/// is false.
		/// </summary>
		/// <remarks>
		/// Due to the implementation of the GraphicsPath object, picking in canvas coordinates
		/// is more accurate, but will introduce a significant performance hit.
		/// </remarks>
		protected override bool PickAfterChildren(PPickPath pickPath) {
			if (pickMode == PathPickMode.Fast) {
				return base.PickAfterChildren(pickPath);
			} else {
				return Intersects(pickPath.PickBounds,  pickPath.GetPathTransformTo(this));
			}
		}