public void SetDamping(bool enable) { Sandbox.Game.Entities.IMyControllableEntity control = Block.Controller as Sandbox.Game.Entities.IMyControllableEntity; if (control.EnabledDamping != enable) { Log.TraceLog("setting damp, EnabledDamping: " + control.EnabledDamping + ", enable: " + enable); MyAPIGateway.Utilities.TryInvokeOnGameThread(() => { if (control.EnabledDamping != enable) { control.SwitchDamping(); } }); } }
/// <summary> /// Reset the third person camera "head" angles. /// </summary> /// <param name="headAngle">new head angle</param> public bool ResetViewerAngle(Vector2?headAngle) { if (!headAngle.HasValue) { return(false); } Sandbox.Game.Entities.IMyControllableEntity controlledEntity = MySession.Static.ControlledEntity as Sandbox.Game.Entities.IMyControllableEntity; if (controlledEntity == null) { return(false); } controlledEntity.HeadLocalXAngle = headAngle.Value.X; controlledEntity.HeadLocalYAngle = headAngle.Value.Y; return(true); }
public void ResetPosition(double distance, Vector2?headAngle) { if (headAngle.HasValue) { Sandbox.Game.Entities.IMyControllableEntity controlledEntity = MySession.Static.ControlledEntity as Sandbox.Game.Entities.IMyControllableEntity; if (controlledEntity == null) { return; } controlledEntity.HeadLocalXAngle = headAngle.Value.X; controlledEntity.HeadLocalYAngle = headAngle.Value.Y; ResetDistance(distance); m_positionSafe.AssertIsValid(); } }
public void RecalibrateCameraPosition(bool isCharacter = false) { // if (m_lookAt != Vector3D.Zero) // return; IMyCameraController cameraController = MySession.Static.CameraController; if (cameraController == null || !(cameraController is MyEntity)) { return; } Sandbox.Game.Entities.IMyControllableEntity controlledEntity = MySession.Static.ControlledEntity as Sandbox.Game.Entities.IMyControllableEntity; if (controlledEntity == null) { return; } // get latest head matrix if (!isCharacter) { var headMatrix = controlledEntity.GetHeadMatrix(true); m_targetOrientation = (Matrix)headMatrix.GetOrientation(); m_target = headMatrix.Translation; } // parent of hierarchy MyEntity topControlledEntity = ((MyEntity)cameraController).GetTopMostParent(); if (topControlledEntity.Closed) { return; } // calculate controlled object coordinates in parent space var worldToLocal = topControlledEntity.PositionComp.WorldMatrixNormalizedInv; Vector3D targetInLocal = Vector3D.Transform(m_target, worldToLocal); MatrixD orientationInLocal = m_targetOrientation * worldToLocal; var localAABBHr = topControlledEntity.PositionComp.LocalAABBHr; Vector3D centerToTarget = targetInLocal - localAABBHr.Center; Vector3D backVec = Vector3D.Normalize(orientationInLocal.Backward); // calculate offset for the double projectedCenterToTarget = Vector3D.Dot(centerToTarget, backVec); double projectedHalfExtent = Math.Abs(Vector3D.Dot(localAABBHr.HalfExtents, backVec)); double finalLength = projectedHalfExtent - projectedCenterToTarget; Vector3D targetWithOffset = centerToTarget + (finalLength * backVec); double width = LOOK_AT_DEFAULT_LENGTH; // some default value if (Math.Abs(backVec.Z) > 0.0001) { width = localAABBHr.HalfExtents.X * 1.5f; } else if (Math.Abs(backVec.X) > 0.0001) { width = localAABBHr.HalfExtents.Z * 1.5f; } // calculate complete offset for controlled object double halfFovTan = Math.Tan(MySector.MainCamera.FieldOfView * 0.5); double offset = width / (2 * halfFovTan); offset += finalLength; double clampDist = MathHelper.Clamp(offset, GetMinDistance(), MAX_DISTANCE); Vector3D lookAt = LOOK_AT_DIRECTION * clampDist; SetPositionAndLookAt(lookAt); }
// Updates spectator position (spring connected to desired position) public override void UpdateAfterSimulation() { Sandbox.Game.Entities.IMyControllableEntity controlledEntity = MySession.Static.ControlledEntity as Sandbox.Game.Entities.IMyControllableEntity; if (controlledEntity == null) { return; } var headMatrix = controlledEntity.GetHeadMatrix(true); if (controlledEntity is MyCharacter) { var character = controlledEntity as MyCharacter; headMatrix = character.Get3rdBoneMatrix(true, true); } m_targetOrientation = (Matrix)headMatrix.GetOrientation(); m_target = headMatrix.Translation; //VRageRender.MyRenderProxy.DebugDrawAxis(headMatrix, 1, false); UpdateCurrentSpring(); m_transformedLookAt = Vector3D.Transform(m_lookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; //m_position = m_desiredPosition; //m_velocity = Vector3.Zero; // Calculate spring force Vector3D stretch = m_position - m_desiredPosition; Vector3D force = -m_currentSpring.Stiffness * stretch - m_currentSpring.Damping * m_velocity; force.AssertIsValid(); // Apply acceleration Vector3 acceleration = (Vector3)force / m_currentSpring.Mass; m_velocity += acceleration * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_velocity.AssertIsValid(); // Apply velocity if (!Sandbox.Game.Multiplayer.Sync.IsServer) { //We are not able to interpolate camera correctly if position is updated through server m_position = m_desiredPosition; } else { m_position += m_velocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; } m_position.AssertIsValid(); // Limit backward distance from target double backward = Vector3D.Dot((Vector3D)m_targetOrientation.Backward, (m_target - m_position)); if (backward > -BACKWARD_CUTOFF) { m_position += (Vector3D)m_targetOrientation.Backward * (backward + BACKWARD_CUTOFF); } // Roll spring Quaternion targetOrientation = Quaternion.CreateFromRotationMatrix(m_targetOrientation); // Computes angle difference between current and target orientation var angleDifference = (float)Math.Acos(MathHelper.Clamp(Quaternion.Dot(m_orientation, targetOrientation), -1, 1)); // Normalize angle angleDifference = angleDifference > MathHelper.PiOver2 ? MathHelper.Pi - angleDifference : angleDifference; // Compute spring physics float angleForce = -AngleSpring.Stiffness * angleDifference - AngleSpring.Damping * m_angleVelocity; m_angleVelocity += angleForce / AngleSpring.Mass * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; if (angleDifference > 0) { float factor = Math.Abs(m_angleVelocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS / angleDifference); if (angleDifference > MathHelper.PiOver4) { factor = Math.Max(factor, 1.0f - MathHelper.PiOver4 / angleDifference); } factor = MathHelper.Clamp(factor, 0, 1); m_orientation = Quaternion.Slerp(m_orientation, targetOrientation, factor); m_orientationMatrix = Matrix.CreateFromQuaternion(m_orientation); } if ((m_position - m_desiredPosition).LengthSquared() > MAX_DISTANCE * MAX_DISTANCE) { RecalibrateCameraPosition(); } if (m_saveSettings) { MySession.Static.SaveControlledEntityCameraSettings(false); m_saveSettings = false; } ++m_updateCount; }
// Updates spectator position (spring connected to desired position) public override void UpdateAfterSimulation() { IMyControllableEntity genericControlledEntity = MySession.Static.ControlledEntity; if (genericControlledEntity == null) { return; } if (genericControlledEntity != m_lastControllerEntity) { m_disableSpringThisFrame = true; m_lastControllerEntity = genericControlledEntity; } // ----------- gather viewer position and target ------------------ var remotelyControlledEntity = genericControlledEntity as MyRemoteControl; var controlledEntity = remotelyControlledEntity != null ? remotelyControlledEntity.Pilot : genericControlledEntity.Entity; while (controlledEntity.Parent is MyCockpit) { controlledEntity = controlledEntity.Parent; } if (controlledEntity != null && controlledEntity.PositionComp != null) { var positionComp = controlledEntity.PositionComp; float localY = positionComp.LocalAABB.Max.Y - positionComp.LocalAABB.Min.Y; Vector3D lastTarget = m_target; var headMatrix = remotelyControlledEntity == null?genericControlledEntity.GetHeadMatrix(true) : remotelyControlledEntity.Pilot.GetHeadMatrix(true); m_target = controlledEntity is MyCharacter ? ((positionComp.GetPosition() + (localY + m_lookAtOffsetY) * 1.2f * positionComp.WorldMatrix.Up)) : headMatrix.Translation; m_targetOrientation = headMatrix.GetOrientation(); m_targetUpVec = m_positionCurrentIsSafe ? (Vector3D)m_targetOrientation.Up : positionComp.WorldMatrix.Up; // this is right and prevents z-rotation if in invalid position (during timeout before switching to 1st person) m_transformedLookAt = Vector3D.Transform(m_clampedlookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; m_position += m_target - lastTarget; // compensate character movement } else { var headMatrix = genericControlledEntity.GetHeadMatrix(true); m_target = headMatrix.Translation; m_targetOrientation = headMatrix.GetOrientation(); m_targetUpVec = m_targetOrientation.Up; m_transformedLookAt = Vector3D.Transform(m_clampedlookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; m_position = m_desiredPosition; } // --------- camera spring ------------------------ Vector3D backup_mPosition = m_position; if (m_disableSpringThisFrame) { m_position = m_desiredPosition; m_velocity = Vector3.Zero; } else { ProcessSpringCalculation(); } // -------- raycast, prevent camera being inside things ------ if (controlledEntity != null) { if (!controlledEntity.Closed) { HandleIntersection(controlledEntity); } else { m_positionCurrentIsSafe = false; } } // ------- save current settings ------- if (m_saveSettings) { MySession.Static.SaveControlledEntityCameraSettings(false); m_saveSettings = false; } // ------- in case spring is disabled - quickly lerp in new desired position ---------------- if (m_disableSpringThisFrame) { double smoothCoeff = 0.8; m_position = Vector3D.Lerp(backup_mPosition, m_desiredPosition, smoothCoeff); m_velocity = Vector3.Zero; m_disableSpringThisFrame = Vector3D.DistanceSquared(m_position, m_desiredPosition) > CAMERA_RADIUS * CAMERA_RADIUS; } // ------- draw trail if debug draw is enabled -------------------------------------- DebugDrawTrail(); }
// Updates spectator position (spring connected to desired position) public override void UpdateAfterSimulation() { IMyControllableEntity genericControlledEntity = MySession.Static.ControlledEntity; if (genericControlledEntity == null) return; if (genericControlledEntity != m_lastControllerEntity) { m_disableSpringThisFrame = true; m_lastControllerEntity = genericControlledEntity; } // ----------- gather viewer position and target ------------------ var remotelyControlledEntity = genericControlledEntity as MyRemoteControl; var controlledEntity = remotelyControlledEntity != null ? remotelyControlledEntity.Pilot : genericControlledEntity.Entity; while (controlledEntity.Parent is MyCockpit) { controlledEntity = controlledEntity.Parent; } if (controlledEntity != null && controlledEntity.PositionComp != null) { var positionComp = controlledEntity.PositionComp; float localY = positionComp.LocalAABB.Max.Y - positionComp.LocalAABB.Min.Y; Vector3D lastTarget = m_target; var headMatrix = remotelyControlledEntity == null ? genericControlledEntity.GetHeadMatrix(true) : remotelyControlledEntity.Pilot.GetHeadMatrix(true); m_target = controlledEntity is MyCharacter ? ((positionComp.GetPosition() + (localY + m_lookAtOffsetY) * 1.2f * positionComp.WorldMatrix.Up)) : headMatrix.Translation; m_targetOrientation = headMatrix.GetOrientation(); m_targetUpVec = m_positionCurrentIsSafe ? (Vector3D)m_targetOrientation.Up : positionComp.WorldMatrix.Up; // this is right and prevents z-rotation if in invalid position (during timeout before switching to 1st person) m_transformedLookAt = Vector3D.Transform(m_clampedlookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; m_position += m_target - lastTarget; // compensate character movement } else { var headMatrix = genericControlledEntity.GetHeadMatrix(true); m_target = headMatrix.Translation; m_targetOrientation = headMatrix.GetOrientation(); m_targetUpVec = m_targetOrientation.Up; m_transformedLookAt = Vector3D.Transform(m_clampedlookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; m_position = m_desiredPosition; } // --------- camera spring ------------------------ Vector3D backup_mPosition = m_position; if (m_disableSpringThisFrame) { m_position = m_desiredPosition; m_velocity = Vector3.Zero; } else { ProcessSpringCalculation(); } // -------- raycast, prevent camera being inside things ------ if (controlledEntity != null) { if (!controlledEntity.Closed) { HandleIntersection(controlledEntity); } else { m_positionCurrentIsSafe = false; } } // ------- save current settings ------- if (m_saveSettings) { MySession.Static.SaveControlledEntityCameraSettings(false); m_saveSettings = false; } // ------- in case spring is disabled - quickly lerp in new desired position ---------------- if (m_disableSpringThisFrame) { double smoothCoeff = 0.8; m_position = Vector3D.Lerp(backup_mPosition, m_desiredPosition, smoothCoeff); m_velocity = Vector3.Zero; m_disableSpringThisFrame = Vector3D.DistanceSquared(m_position, m_desiredPosition) > CAMERA_RADIUS * CAMERA_RADIUS; } // ------- draw trail if debug draw is enabled -------------------------------------- DebugDrawTrail(); }
/* * public override void HandleInput() * { * try * { * if (MyAPIGateway.Utilities.IsDedicated || MyAPIGateway.Gui.IsCursorVisible || MyAPIGateway.Gui.ChatEntryVisible) * return; * * CamAlignHandler(); * } * catch (Exception e) * { * //... hm? * } * } */ public void CamAlignHandler() { try { if (MyAPIGateway.Input.IsGameControlPressed(MyControlsSpace.LOOKAROUND)) { if (MyAPIGateway.Input.IsGameControlReleased(MyControlsSpace.CAMERA_MODE)) { CameraAutoAlignEnabled = !CameraAutoAlignEnabled; if (CameraAutoAlignEnabled) { MyAPIGateway.Utilities.ShowNotification("Camera auto-align enabled."); } else { MyAPIGateway.Utilities.ShowNotification("Camera auto-align disabled."); } } } if (!CameraAutoAlignEnabled) { alignTick = 60; return; } var camCtrl = MyAPIGateway.Session.CameraController; var controller = MyAPIGateway.Session.ControlledObject as Sandbox.Game.Entities.IMyControllableEntity; // Avoiding ambiguity. if (camCtrl == null || controller == null) { return; } if (isInFirstPersonView != camCtrl.IsInFirstPersonView) { isInFirstPersonView = camCtrl.IsInFirstPersonView; alignTick = 60; } if (ControlledObject != controller) { ControlledObject = controller; alignTick = 60; } if (MyAPIGateway.Input.IsNewGameControlPressed(MyControlsSpace.LOOKAROUND)) { alignTick = -1; } else if (MyAPIGateway.Input.IsGameControlReleased(MyControlsSpace.LOOKAROUND)) { alignTick = 0; } if (alignTick != -1) { alignTick++; if (alignTick > alignAfter) { alignTick = -1; // Slight change, only allow auto-align on cockpits and characters thrid person. if (controller is IMyRemoteControl) { /* * if (RefController == null) * return; * * var shipController = controller as IMyShipController; * if (shipController.GetShipSpeed() < 0.1) * { * alignTick = 0; * return; * } * * MyAPIGateway.Utilities.ShowNotification("LULZ"); * // HACK this is how MyCockpit.Rotate() does things so I kinda have to use these magic numbers. * var num = MyAPIGateway.Input.GetMouseSensitivity() * 0.13f; * * if (camCtrl.IsInFirstPersonView) * camCtrl.Rotate(new Vector2(RefController.HeadLocalXAngle / num, RefController.HeadLocalYAngle / num), 0); * else * camCtrl.Rotate(new Vector2((RefController.HeadLocalXAngle + shipCamHeightOffset) / num, (RefController.HeadLocalYAngle) / num), 0); */ } else if (controller is IMyShipController) { //RefController = controller; var shipController = controller as IMyShipController; if (!shipController.CanControlShip) { alignTick = -1; return; } if (shipController.GetShipSpeed() < 0.1) { alignTick = 0; return; } // HACK this is how MyCockpit.Rotate() does things so I kinda have to use these magic numbers. var num = MyAPIGateway.Input.GetMouseSensitivity() * 0.13f; if (camCtrl.IsInFirstPersonView) { camCtrl.Rotate(new Vector2(controller.HeadLocalXAngle / num, controller.HeadLocalYAngle / num), 0); } else { camCtrl.Rotate(new Vector2((controller.HeadLocalXAngle + shipCamHeightOffset) / num, (controller.HeadLocalYAngle) / num), 0); } } else if (controller is IMyCharacter) { var playerChar = controller as IMyCharacter; if (playerChar.Physics.Speed < 0.1) { alignTick = 0; return; } // HACK this is how MyCharacter.RotateHead() does things so I kinda have to use these magic numbers. if (!camCtrl.IsInFirstPersonView) { camCtrl.Rotate(new Vector2(controller.HeadLocalXAngle * 2, controller.HeadLocalYAngle * 2), 0); } } else { /* * // HACK this is how MyCharacter.RotateHead() does things so I kinda have to use these magic numbers. * if (!camCtrl.IsInFirstPersonView) * camCtrl.Rotate(new Vector2(controller.HeadLocalXAngle * 2, controller.HeadLocalYAngle * 2), 0); */ } } } } catch (Exception e) { //MyAPIGateway.Utilities.ShowNotification("NOPE\n" + e.ToString(), 16); // I should log. A proper log. Oh well... } }
// Updates spectator position (spring connected to desired position) public override void UpdateAfterSimulation() { Sandbox.Game.Entities.IMyControllableEntity genericControlledEntity = MySession.Static.ControlledEntity as Sandbox.Game.Entities.IMyControllableEntity; if (genericControlledEntity == null) { return; } var remotelyControlledEntity = genericControlledEntity as MyRemoteControl; var controlledEntity = remotelyControlledEntity != null ? remotelyControlledEntity.Pilot : genericControlledEntity.Entity; if (controlledEntity != null && controlledEntity.PositionComp != null) { var positionComp = controlledEntity.PositionComp; float localY = positionComp.LocalAABB.Max.Y - positionComp.LocalAABB.Min.Y; Vector3D lastTarget = m_target; var headMatrix = remotelyControlledEntity == null?genericControlledEntity.GetHeadMatrix(true) : remotelyControlledEntity.Pilot.GetHeadMatrix(true); m_target = controlledEntity is MyCharacter ? ((positionComp.GetPosition() + (localY + LOOK_AT_OFFSET_Y) * positionComp.WorldMatrix.Up)) : headMatrix.Translation; m_targetOrientation = headMatrix.GetOrientation(); m_targetUpVec = m_positionCurrentIsSafe ? (Vector3D)m_targetOrientation.Up : positionComp.WorldMatrix.Up; m_transformedLookAt = Vector3D.Transform(m_lookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; m_position += m_target - lastTarget; // compensate character movement //m_position = m_desiredPosition; } else { var headMatrix = genericControlledEntity.GetHeadMatrix(true); m_target = headMatrix.Translation; m_targetOrientation = headMatrix.GetOrientation(); m_targetUpVec = m_targetOrientation.Up; m_transformedLookAt = Vector3D.Transform(m_lookAt, m_targetOrientation); m_desiredPosition = m_target + m_transformedLookAt; m_position = m_desiredPosition; } Vector3D stretch = m_position - m_desiredPosition; Vector3D force = -m_currentSpring.Stiffness * stretch - m_currentSpring.Dampening * m_velocity; force.AssertIsValid(); // Apply acceleration Vector3 acceleration = (Vector3)force / m_currentSpring.Mass; m_velocity += acceleration * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_velocity.AssertIsValid(); // Apply velocity m_position += m_velocity * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_position.AssertIsValid(); // Limit backward distance from target double backward = Vector3D.Dot((Vector3D)m_targetOrientation.Backward, (m_target - m_position)); if (backward > -BACKWARD_CUTOFF) { m_position += (Vector3D)m_targetOrientation.Backward * (backward + BACKWARD_CUTOFF); } // -------- raycast, prevent camera being inside things ------ if (controlledEntity != null) { if (!controlledEntity.Closed) { HandleIntersection(controlledEntity); } else { m_positionCurrentIsSafe = false; } } // ------- save current settings ------- if (m_saveSettings) { MySession.Static.SaveControlledEntityCameraSettings(false); m_saveSettings = false; } ++m_updateCount; }
public override UseActionResult CanUse(UseActionEnum actionEnum, Sandbox.Game.Entities.IMyControllableEntity user) => (base.IsFunctional ? (base.IsWorking ? ((base.m_pilot == null) ? base.CanUse(actionEnum, user) : UseActionResult.UsedBySomeoneElse) : UseActionResult.Unpowered) : UseActionResult.CockpitDamaged);