//public MouseEventArgs(MouseButtons button, int clicks, int x, int y, int wheelDelta)
		//: this

		public MouseEventArgs(MouseEventArgs original, double newX, double newY)
			: this(original.Button, original.Clicks, newX, newY, original.WheelDelta)
		{
			positions[0] = new Vector2(newX, newY);
			for (int i = 1; i < original.NumPositions; i++)
			{
				positions.Add(original.GetPosition(i));
			}
		}
		public override void OnMouseMove(MouseEventArgs mouseEvent)
		{
			base.OnMouseMove(mouseEvent);
			Vector2 mousePos = new Vector2();
			if (mouseEvent.NumPositions == 1)
			{
				mousePos = new Vector2(mouseEvent.X, mouseEvent.Y);
			}
			else
			{
				Vector2 centerPosition = (mouseEvent.GetPosition(1) + mouseEvent.GetPosition(0)) / 2;
				mousePos = centerPosition;
			}
			if (MouseCaptured)
			{
				Vector2 mouseDelta = mousePos - lastMousePosition;
				switch (TransformState)
				{
					case ETransformState.Move:
						ScalingTransform.inverse_transform(ref mouseDelta);

						unscaledRenderOffset += mouseDelta;
						break;

					case ETransformState.Scale:
						double zoomDelta = 1;
						if (mouseDelta.y < 0)
						{
							zoomDelta = 1 - (-1 * mouseDelta.y / 100);
						}
						else if (mouseDelta.y > 0)
						{
							zoomDelta = 1 + (1 * mouseDelta.y / 100);
						}

						Vector2 mousePreScale = mouseDownPosition;
						TotalTransform.inverse_transform(ref mousePreScale);

						layerScale *= zoomDelta;

						Vector2 mousePostScale = mouseDownPosition;
						TotalTransform.inverse_transform(ref mousePostScale);

						unscaledRenderOffset += (mousePostScale - mousePreScale);
						break;

					default:
						throw new NotImplementedException();
				}

				Invalidate();
			}
			lastMousePosition = mousePos;

			// check if we should do some scaling
			if (TransformState == ETransformState.Move
				&& mouseEvent.NumPositions > 1
				&& startDistanceBetweenPoints > 0)
			{
				double curDistanceBetweenPoints = (mouseEvent.GetPosition(1) - mouseEvent.GetPosition(0)).Length;

				double scaleAmount = pinchStartScale * curDistanceBetweenPoints / startDistanceBetweenPoints;
				ScalePartAndFixPosition(mouseEvent, scaleAmount);
			}
		}
		public override void OnMouseDown(MouseEventArgs mouseEvent)
		{
			base.OnMouseDown(mouseEvent);
			if (MouseCaptured)
			{
				if (mouseEvent.NumPositions == 1)
				{
					mouseDownPosition.x = mouseEvent.X;
					mouseDownPosition.y = mouseEvent.Y;
				}
				else
				{
					Vector2 centerPosition = (mouseEvent.GetPosition(1) + mouseEvent.GetPosition(0)) / 2;
					mouseDownPosition = centerPosition;
				}

				lastMousePosition = mouseDownPosition;

				if (mouseEvent.NumPositions > 1)
				{
					startDistanceBetweenPoints = (mouseEvent.GetPosition(1) - mouseEvent.GetPosition(0)).Length;
                    pinchStartScale = layerScale;
                }
			}
		}
		public override void OnMouseMove(MouseEventArgs mouseEvent)
		{
			base.OnMouseMove(mouseEvent);

			Vector2 currentMousePosition;
			if (mouseEvent.NumPositions == 1)
			{
				currentMousePosition.x = mouseEvent.X;
				currentMousePosition.y = mouseEvent.Y;
				if (MouseCaptured
					&& TransformState == TrackBallController.MouseDownType.Rotation)
				{
					DrawRotationHelperCircle = true;
				}
				else
				{
					DrawRotationHelperCircle = false;
				}
			}
			else
			{
				Vector2 centerPosition = (mouseEvent.GetPosition(1) + mouseEvent.GetPosition(0)) / 2;
				currentMousePosition = centerPosition;
				DrawRotationHelperCircle = false;
			}

			motionQueue.AddMoveToMotionQueue(currentMousePosition, UiThread.CurrentTimerMs);

			if (!LockTrackBall && TrackBallController.CurrentTrackingType != TrackBallController.MouseDownType.None)
			{
				TrackBallController.OnMouseMove(currentMousePosition);
				Invalidate();
			}

			// check if we should do some scaling or rotation
			if (TransformState != TrackBallController.MouseDownType.None
				&& mouseEvent.NumPositions > 1
				&& startDistanceBetweenPoints > 0)
			{
				Vector2 position0 = mouseEvent.GetPosition(0);
				Vector2 position1 = mouseEvent.GetPosition(1);
				double curDistanceBetweenPoints = (position1 - position0).Length;

				double scaleAmount = pinchStartScale * curDistanceBetweenPoints / startDistanceBetweenPoints;
				TrackBallController.Scale = scaleAmount;

				double angle = Math.Atan2(position1.y - position0.y, position1.x - position0.x);
			}
		}
		public override void OnMouseDown(MouseEventArgs mouseEvent)
		{
			base.OnMouseDown(mouseEvent);

			if (!LockTrackBall && MouseCaptured)
			{
				Vector2 currentMousePosition;
				if (mouseEvent.NumPositions == 1)
				{
					currentMousePosition.x = mouseEvent.X;
					currentMousePosition.y = mouseEvent.Y;
				}
				else
				{
					Vector2 centerPosition = (mouseEvent.GetPosition(1) + mouseEvent.GetPosition(0)) / 2;
					currentMousePosition = centerPosition;
				}

				currentVelocityPerMs = Vector2.Zero;
				motionQueue.Clear();
				motionQueue.AddMoveToMotionQueue(currentMousePosition, UiThread.CurrentTimerMs);

				if (mouseEvent.NumPositions > 1)
				{
					Vector2 position0 = mouseEvent.GetPosition(0);
					Vector2 position1 = mouseEvent.GetPosition(1);
					startDistanceBetweenPoints = (position1 - position0).Length;
					pinchStartScale = TrackBallController.Scale;

					startAngle = Math.Atan2(position1.y - position0.y, position1.x - position0.x);

					if (TransformState != TrackBallController.MouseDownType.None)
					{
						if (!LockTrackBall && TrackBallController.CurrentTrackingType != TrackBallController.MouseDownType.None)
						{
							TrackBallController.OnMouseUp();
						}
						TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Translation);
					}
				}

				if (mouseEvent.Button == MouseButtons.Left)
				{
					if (TrackBallController.CurrentTrackingType == TrackBallController.MouseDownType.None)
					{
						Keys modifierKeys = ModifierKeys;
						if (modifierKeys == Keys.Shift)
						{
							TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Translation);
						}
						else if (modifierKeys == Keys.Control)
						{
							TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Scale);
						}
						else if (modifierKeys == Keys.Alt)
						{
							TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Rotation);
						}
						else
						{
							switch (TransformState)
							{
								case TrackBallController.MouseDownType.Rotation:
									TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Rotation);
									break;

								case TrackBallController.MouseDownType.Translation:
									TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Translation);
									break;

								case TrackBallController.MouseDownType.Scale:
									TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Scale);
									break;
							}
						}
					}
				}
				else if (mouseEvent.Button == MouseButtons.Middle)
				{
					if (TrackBallController.CurrentTrackingType == TrackBallController.MouseDownType.None)
					{
						TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Translation);
					}
				}
				else if (mouseEvent.Button == MouseButtons.Right)
				{
					if (TrackBallController.CurrentTrackingType == TrackBallController.MouseDownType.None)
					{
						TrackBallController.OnMouseDown(currentMousePosition, Matrix4X4.Identity, TrackBallController.MouseDownType.Rotation);
					}
				}
			}
		}