void Control_MouseMove(object sender, MouseEventArgs e) { if (EnableMouseAction != null && !EnableMouseAction(e)) { return; // Don't do anything } float4x4 CameraMatrixBeforeBaseCall = CameraTransform; // base.OnMouseMove( e ); m_Control.Focus(); // if ( m_ButtonsDown == MouseButtons.None ) // return; // Can't manipulate... float2 MousePos = ComputeNormalizedScreenPosition(e.X, e.Y, (float)m_Control.Width / m_Control.Height); // Check for FIRST PERSON switch if (m_bLastManipulationWasFirstPerson ^ FirstPersonKeyDown) { // There was a switch so we need to copy the current matrix and make it look like the button was just pressed... Control_MouseDown(sender, e); } m_bLastManipulationWasFirstPerson = FirstPersonKeyDown; if (!FirstPersonKeyDown) { ////////////////////////////////////////////////////////////////////////// // MAYA MANIPULATION MODE ////////////////////////////////////////////////////////////////////////// // switch (m_ButtonsDown) { // ROTATE case MouseButtons.Left: { if (!m_bRotationEnabled) { break; // Rotation is disabled! } float fAngleX = (MousePos.y - m_ButtonDownMousePosition.y) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed; float fAngleY = (MousePos.x - m_ButtonDownMousePosition.x) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed; float4 AxisX = m_ButtonDownTransform.r0; float4x4 Rot = float4x4.FromAngleAxis(fAngleX, new float3(-AxisX.x, -AxisX.y, -AxisX.z)) * float4x4.FromAngleAxis(fAngleY, new float3(0f, -1.0f, 0.0f)); float4x4 Rotated = m_ButtonDownTransform * m_InvButtonDownTargetObjectMatrix * Rot * TargetObjectMatrix; CameraTransform = Rotated; break; } // DOLLY => Simply translate along the AT axis case MouseButtons.Right: case MouseButtons.Left | MouseButtons.Middle: { float fTrans = m_ButtonDownMousePosition.x - m_ButtonDownMousePosition.y - MousePos.x + MousePos.y; m_NormalizedTargetDistance = m_ButtonDownNormalizedTargetDistance + 4.0f * m_ManipulationZoomSpeed * fTrans; float fTargetDistance = Math.Sign(m_NormalizedTargetDistance) * DeNormalizeTargetDistance(m_NormalizedTargetDistance); if (fTargetDistance > MIN_TARGET_DISTANCE) { // Okay! We're far enough so we can reduce the distance anyway CameraTargetDistance = fTargetDistance; m_bPushingTarget = false; } else { // Too close! Let's move the camera forward and clamp the target distance... That will push the target along. m_CameraTargetDistance = MIN_TARGET_DISTANCE; m_NormalizedTargetDistance = NormalizeTargetDistance(m_CameraTargetDistance); if (!m_bPushingTarget) { m_ButtonDownNormalizedTargetDistance = m_NormalizedTargetDistance; fTrans = 0.0f; m_bPushingTarget = true; } m_ButtonDownMousePosition = MousePos; float4x4 DollyCam = CameraTransform; DollyCam.r3 = DollyCam.r3 - (2.0f * m_ManipulationZoomSpeed * fTrans) * DollyCam.r2; CameraTransform = DollyCam; } break; } // PAN case MouseButtons.Middle: { float2 Trans = new float2(-(MousePos.x - m_ButtonDownMousePosition.x), MousePos.y - m_ButtonDownMousePosition.y ); float fTransFactor = m_ManipulationPanSpeed * Math.Max(2.0f, m_CameraTargetDistance); // Make the camera pan float4x4 PanCam = m_ButtonDownTransform; PanCam.r3 = m_ButtonDownTransform.r3 - fTransFactor * Trans.x * m_ButtonDownTransform.r0 - fTransFactor * Trans.y * m_ButtonDownTransform.r1; CameraTransform = PanCam; break; } } } else { ////////////////////////////////////////////////////////////////////////// // UNREAL MANIPULATION MODE ////////////////////////////////////////////////////////////////////////// // switch (m_ButtonsDown) { // TRANSLATE IN THE ZX PLANE (WORLD SPACE) case MouseButtons.Left: { float fTransFactor = m_ManipulationPanSpeed * System.Math.Max(4.0f, CameraTargetDistance); // Compute translation in the view direction float4 Trans = CameraMatrixBeforeBaseCall.r2; Trans.y = 0.0f; if (Trans.Dot(Trans) < 1e-4f) { // Better use Y instead... Trans = CameraMatrixBeforeBaseCall.r1; Trans.y = 0.0f; } Trans = Trans.Normalized; float4 NewPosition = CameraMatrixBeforeBaseCall.r3 + fTransFactor * (MousePos.y - m_ButtonDownMousePosition.y) * Trans; m_ButtonDownMousePosition.y = MousePos.y; // The translation is a cumulative operation... // Compute rotation about the the Y WORLD axis float fAngleY = (m_ButtonDownMousePosition.x - MousePos.x) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed * 0.2f; // [PATAPATCH] Multiplied by 0.2 as it's REALLY too sensitive otherwise! if (m_ButtonDownTransform.r1.y < 0.0f) { fAngleY = -fAngleY; // Special "head down" case... } float4x4 RotY = float4x4.RotationY(fAngleY); float4x4 FinalMatrix = m_ButtonDownTransform; FinalMatrix.r3 = new float4(0, 0, 0, 0); // Clear translation... FinalMatrix = FinalMatrix * RotY; FinalMatrix.r3 = NewPosition; CameraTransform = FinalMatrix; break; } // ROTATE ABOUT CAMERA case MouseButtons.Right: { float fAngleY = (m_ButtonDownMousePosition.x - MousePos.x) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed; float fAngleX = (m_ButtonDownMousePosition.y - MousePos.y) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed; float3 Euler = GetEuler(m_ButtonDownTransform); float4x4 CamRotYMatrix = float4x4.RotationY(fAngleY + Euler.y); float4x4 CamRotXMatrix = float4x4.RotationX(fAngleX + Euler.x); float4x4 CamRotZMatrix = float4x4.RotationZ(Euler.z); float4x4 RotateMatrix = CamRotXMatrix * CamRotYMatrix * CamRotZMatrix; RotateMatrix.r3 = CameraTransform.r3; CameraTransform = RotateMatrix; break; } // Translate in the ( Z-world Y-camera ) plane case MouseButtons.Middle: case MouseButtons.Left | MouseButtons.Right: { float fTransFactor = m_ManipulationPanSpeed * System.Math.Max(4.0f, CameraTargetDistance); float4 NewPosition = m_ButtonDownTransform.r3 + fTransFactor * ((MousePos.y - m_ButtonDownMousePosition.y) * new float4(0, 1, 0, 0) + (m_ButtonDownMousePosition.x - MousePos.x) * m_ButtonDownTransform.r0); float4x4 NewMatrix = m_ButtonDownTransform; NewMatrix.r3 = NewPosition; CameraTransform = NewMatrix; break; } } } }