6 class SCR_CharacterCameraHandlerComponent : CameraHandlerComponent
14 protected ref ScriptInvoker m_OnThirdPersonSwitch =
new ScriptInvoker();
15 protected static float s_fOverlayCameraFOV;
17 protected int m_iHipsBoneIndex = 0;
19 protected bool m_bCameraActive;
26 void SCR_CharacterCameraHandlerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
29 DiagMenu.RegisterRange(
SCR_DebugMenuID.DEBUGUI_CHARACTER_DEBUG_VIEW,
"",
"Cycle Debug View",
"Character",
"0, 8, 0, 1");
30 DiagMenu.RegisterBool(
SCR_DebugMenuID.DEBUGUI_DRAW_CAMERA_COLLISION_SOLVER,
"",
"Draw Camera Collision Solver",
"Character");
53 m_bCameraActive =
true;
63 if (playerController.m_bRetain3PV)
65 playerController.m_bRetain3PV =
false;
105 m_bCameraActive =
false;
137 CompartmentAccessComponent compartmentAccess =
m_OwnerCharacter.GetCompartmentAccessComponent();
139 if (compartmentAccess && compartmentAccess.IsInCompartment() && !compartmentAccess.IsGettingOut())
141 BaseCompartmentSlot compartment = compartmentAccess.GetCompartment();
144 BaseControllerComponent controller = compartment.GetController();
148 if(turretController && turretController.GetTurretComponent())
150 isInAds = turretController.IsWeaponADS();
195 if (SCR_BinocularsComponent.IsZoomedView())
205 CompartmentAccessComponent compartmentAccess =
m_OwnerCharacter.GetCompartmentAccessComponent();
210 bool isRolling =
false;
215 if (moveCmd && !moveCmd.IsBlendingOutRoll())
221 if(
m_OwnerCharacter.IsInVehicle() && compartmentAccess && !compartmentAccess.IsGettingOut() )
223 bool isTurretAds =
false;
239 if (compartmentAccess && (compartmentAccess.IsGettingOut() || compartmentAccess.IsGettingIn()))
247 SCR_CharacterCommandHandlerComponent scrCmdHandler = SCR_CharacterCommandHandlerComponent.Cast(
m_CmdHandler);
248 if (scrCmdHandler && scrCmdHandler.IsLoitering())
277 else if (compartmentAccess && (compartmentAccess.IsGettingIn() || compartmentAccess.IsGettingOut()))
283 bool isTurretAds =
false;
327 float transTime = 0.4;
356 CompartmentAccessComponent compAcc =
m_OwnerCharacter.GetCompartmentAccessComponent();
357 if (compAcc && compAcc.IsInCompartment())
359 BaseCompartmentSlot compartment = compAcc.GetCompartment();
362 BaseControllerComponent controller = compartment.GetController();
366 if (turretController)
392 transTime =
GetCameraSet().GetTransitionTime(pFrom, pTo);
409 m_OnThirdPersonSwitch.Invoke();
416 return m_OnThirdPersonSwitch;
424 [
Attribute(
"0.5", UIWidgets.Slider,
"Focus interpolation time",
"0 10 0.05")]
427 [
Attribute(
"0.9", UIWidgets.Slider,
"Focus interpolation deceleration",
"0 1 0.05")]
442 if (currDiff <= sm_fDistanceEpsilon)
454 if (!isWeaponADS && playerController)
455 isWeaponADS = playerController.GetGadgetFocus();
462 float adsChange = pDt / adsTime;
525 if (
float.AlmostEqual(absDelta, 0))
535 override void OnAfterCameraUpdate(
float pDt,
bool pIsKeyframe, inout vector transformMS[4], inout vector transformWS[4])
556 vector headBoneMat[4];
560 Math3D.MatrixMultiply4(charMat, headBoneMat, headBoneMat);
563 OnAlphatestChange(255 - Math.Clamp((vector.Distance(cameraPositionWS, headBoneMat[3]) - 0.2) / 0.15, 0.0, 1.0)*255);
570 if (m_pRecoilShake && !m_pRecoilShake.IsFinished())
580 bool applyRecoilShake =
true;
582 applyRecoilShake = !DiagMenu.GetBool(
SCR_DebugMenuID.DEBUGUI_CHARACTER_RECOIL_CAMERASHAKE_DISABLE);
586 if (applyRecoilShake && m_pRecoilShake)
587 m_pRecoilShake.Apply(transform, fieldOfView);
590 SCR_CameraShakeManagerComponent.ApplyCameraShake(transform, fieldOfView);
601 override void CollisionSolver(
float pDt, inout ScriptedCameraItemResult pOutResult, inout vector resCamTM[4],
bool isKeyframe)
610 if (pOutResult.m_fDistance == 0.0)
616 IEntity owner = pOutResult.m_pOwner;
617 vector ownerTransformWS[4];
619 owner.GetWorldTransform(ownerTransformWS);
621 Math3D.MatrixIdentity4(ownerTransformWS);
623 vector resultWorldTransform[4];
624 if (pOutResult.m_pWSAttachmentReference)
625 pOutResult.m_pWSAttachmentReference.GetOwner().GetWorldTransform(resultWorldTransform);
627 owner.GetWorldTransform(resultWorldTransform);
629 Math3D.MatrixIdentity4(resultWorldTransform);
633 Math3D.MatrixMultiply4(resultWorldTransform, hipBoneWS, hipBoneWS);
635 #ifdef ENABLE_DIAG // These things are only useful for showing the debug spheres.
636 vector camPos = pOutResult.m_CameraTM[3];
637 vector inputCameraPosWS = camPos.Multiply4(resultWorldTransform);
640 vector camTransformLS[4];
641 Math3D.MatrixCopy(pOutResult.m_CameraTM, camTransformLS);
643 if (pOutResult.m_pWSAttachmentReference)
647 owner = pOutResult.m_pWSAttachmentReference.GetOwner();
648 vector wsAttachmentWorldTransform[4];
649 pOutResult.m_pWSAttachmentReference.GetModelTransform(wsAttachmentWorldTransform);
650 Math3D.MatrixMultiply4(wsAttachmentWorldTransform, camTransformLS, camTransformLS);
653 vector basePos = camTransformLS[3];
656 Math3D.MatrixIdentity4(charRot);
658 if (pOutResult.m_fPositionModelSpace == 2.0)
660 camTransformLS[3] = camTransformLS[3] - resultWorldTransform[3];
664 if (pOutResult.m_fUseHeading > 0.0)
666 vector headingMat[4];
667 Math3D.AnglesToMatrix(Vector( Math.RAD2DEG * -pOutResult.m_fHeading, 0.0, 0.0), headingMat);
669 if (pOutResult.m_pOwner)
670 pOutResult.m_pOwner.GetLocalTransform(charRot);
672 charRot[3] = vector.Zero;
674 Math3D.MatrixInvMultiply4(charRot, headingMat, charRot);
676 Math3D.MatrixToQuat(charRot, charRotQ);
677 float quatF[4] = {0.0, 0.0, 0.0, 1.0};
678 Math3D.QuatLerp(charRotQ, quatF, charRotQ, pOutResult.m_fUseHeading);
679 vector charRotQAngles = Math3D.QuatToAngles(charRotQ);
680 Math3D.AnglesToMatrix(charRotQAngles, charRot);
682 Math3D.MatrixMultiply4(charRot, camTransformLS, camTransformLS);
684 if (pOutResult.m_fDistance == 0.0)
685 camTransformLS[3] = basePos;
688 if (pOutResult.m_fPositionModelSpace > 0.0)
691 vector msPos = camTransformLS[3];
692 vector lsPos = basePos;
693 camTransformLS[3] = vector.Lerp(lsPos, msPos, pOutResult.m_fPositionModelSpace);
698 vector camTransformWS[4];
699 if (pOutResult.m_fPositionModelSpace == 2.0)
700 Math3D.MatrixCopy(camTransformLS, camTransformWS);
702 Math3D.MatrixMultiply4(resultWorldTransform, camTransformLS, camTransformWS);
704 if (pOutResult.m_bAllowCollisionSolver && !isKeyframe && pOutResult.m_fDistance > 0.0)
708 float SIDE_TRACE_MARGIN_MULTIPLIER = 2.0;
709 float BACK_TRACE_MARGIN_MULTIPLIER = 1.25;
715 while (parent !=
null)
717 excludeArray.Insert(parent);
718 while (sibling !=
null)
720 excludeArray.Insert(sibling);
721 sibling = sibling.GetSibling();
723 sibling = parent.GetSibling();
724 parent = parent.GetParent();
727 const float TRACE_RADIUS = 0.06;
730 TraceSphere param =
new TraceSphere();
731 param.Radius = TRACE_RADIUS;
732 param.ExcludeArray = excludeArray;
733 param.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
737 vector sideTraceStart = Vector(hipBoneWS[3][0], camTransformWS[3][1], hipBoneWS[3][2]);
738 vector sideTraceEnd = camTransformWS[3];
740 vector sideTraceDiff = sideTraceEnd - sideTraceStart;
744 param.Start = sideTraceStart;
745 param.End = sideTraceStart + SIDE_TRACE_MARGIN_MULTIPLIER * sideTraceDiff;
746 param.End[1] = sideTraceStart[1] + sideTraceDiff[1];
748 float rightTrace = world.TraceMove(param,
null);
753 ApplySmoothedSlide(pDt, rightTrace, sideTraceStart, sideTraceDiff, SIDE_TRACE_MARGIN_MULTIPLIER, pOutResult.m_fShoulderDist, camTransformWS);
755 sideTraceEnd = vector.Lerp(param.Start, param.End, rightTrace);
760 Math3D.MatrixInvMultiply4(resultWorldTransform, camTransformWS, camTransformLS);
763 vector backtraceDir = pOutResult.m_vBacktraceDir.Multiply3(charRot).Multiply3(resultWorldTransform);
764 backtraceDir = vector.Lerp(camTransformWS[2], backtraceDir, pOutResult.m_fUseBacktraceDir);
767 vector backTraceStart = camTransformWS[3];
768 vector backTraceEnd = camTransformWS[3] - BACK_TRACE_MARGIN_MULTIPLIER * pOutResult.m_fDistance * backtraceDir;
772 float rayBackTrace[N];
773 SCR_Math3D.LookAt(backTraceStart, backTraceEnd, {0, 1, 0}, traceMat);
774 vector traceOffset[N] = {
775 TRACE_RADIUS * traceMat[0],
776 TRACE_RADIUS * traceMat[1],
777 TRACE_RADIUS * -traceMat[0],
778 TRACE_RADIUS * -traceMat[1]
781 if (pOutResult.m_fPositionModelSpace <= 2.0 && pOutResult.m_fDistance > 0.001)
783 TraceParam rayParam();
784 rayParam.ExcludeArray = excludeArray;
785 rayParam.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
789 for (
int i = 0; i < N; ++i)
791 rayParam.Start = backTraceStart + traceOffset[i];
792 rayParam.End = backTraceEnd + traceOffset[i];
793 rayBackTrace[i] = world.TraceMove(rayParam,
null);
794 backTrace = Math.Min(backTrace, rayBackTrace[i]);
797 Math.Max(0, backTrace - TRACE_RADIUS);
801 backTrace = BACK_TRACE_MARGIN_MULTIPLIER * backTrace;
803 float newDistance = pOutResult.m_fDistance * Math.Min(1.0, backTrace);
805 if (newDistance < sm_fDistanceEpsilon)
820 if (DiagMenu.GetValue(
SCR_DebugMenuID.DEBUGUI_DRAW_CAMERA_COLLISION_SOLVER))
822 int baseColor = ARGB(255, 0, 110, 255);
823 ShapeFlags shFlags = ShapeFlags.WIREFRAME|ShapeFlags.ONCE;
825 Shape.CreateSphere(ARGB(255, 255, 255, 255), shFlags, inputCameraPosWS, param.Radius);
827 Shape.CreateSphere(ARGB(255, 0, 255, 0), shFlags, sideTraceStart, param.Radius);
828 Shape.CreateSphere(ARGB(255, 255, 255 * rightTrace, 0), shFlags, sideTraceEnd, param.Radius);
830 for (
int i = 0; i < N; ++i)
832 vector rayStart = backTraceStart + traceOffset[i];
833 vector rayEnd = backTraceEnd + traceOffset[i];
835 Shape.CreateSphere(ARGB(255, 150, 0, 255), shFlags, rayStart, param.Radius * 0.2);
836 Shape.CreateSphere(ARGB(255, 0, 255, 255), shFlags, vector.Lerp(rayStart, rayEnd, Math.Lerp(0.05, 0.4, backTrace) * rayBackTrace[i]), param.Radius * 0.1);
841 Shape.CreateSphere(ARGB(255, 255, 255 * backTrace, 0), shFlags, backTraceStart + (backTraceEnd - backTraceStart).Normalized() * (
m_fCameraDistanceFilter - param.Radius), param.Radius * (1 - backTrace));
847 Math3D.MatrixCopy(camTransformLS, resCamTM);
849 if (pOutResult.m_fPositionModelSpace < 2.0 && pOutResult.m_fDistance > 0.0)
851 vector camBoomDir = pOutResult.m_vBacktraceDir.Multiply3(charRot);
852 camBoomDir = vector.Lerp(resCamTM[2], camBoomDir, pOutResult.m_fUseBacktraceDir);
854 resCamTM[3] = resCamTM[3] - pOutResult.m_fDistance * camBoomDir;
864 float freeLookOffsetScale = 0;
866 freeLookOffsetScale = 1;
884 float stanceBobScale = 0.5;
886 stanceBobScale = 0.25;
888 stanceBobScale = 0.55;
910 if( pAllowTranslation )
914 float bobUp = Math.Sin(
m_fBob_Up * 360 * Math.DEG2RAD) * 0.02 * bobMoveScale;
915 float bobRt = Math.Sin(
m_fBob_Right * 360 * Math.DEG2RAD) * 0.015 * bobMoveScale;
917 vector bobTranslation = pOutTransform[0] * bobRt + pOutTransform[3];
918 bobTranslation = pOutTransform[1] * bobUp + bobTranslation;
919 pOutTransform[3] = pOutTransform[2] * bobFw + bobTranslation;
922 vector angBob = vector.Zero;
923 angBob[0] = Math.Sin(
m_fBob_Up * 360 * Math.DEG2RAD) * 0.3 * bobMoveScale;
924 angBob[1] = Math.Sin(
m_fBob_Right * 360 * Math.DEG2RAD) * 0.3 * bobMoveScale;
926 vector angBobMat[3], endBobmat[3];
927 Math3D.AnglesToMatrix(angBob * pBobScale, angBobMat);
928 Math3D.MatrixMultiply3(angBobMat, pOutTransform, endBobmat);
929 pOutTransform[0] = endBobmat[0];
930 pOutTransform[1] = endBobmat[1];
931 pOutTransform[2] = endBobmat[2];
992 static private float sm_fDistanceEpsilon = 0.0001;
1026 private bool ApplySmoothedSlide(
float pDt,
float slide, vector sideTraceStart, vector sideTraceDiff,
float sideTraceMarginMultiplier,
float shoulderDist, inout vector inoutMat[4])
1071 float slideT = sideTraceMarginMultiplier * ((
m_fCameraSlideFilter)/Math.Max(0.01, slide * sideTraceMarginMultiplier) - (1/sideTraceMarginMultiplier));
1072 slideTime = Math.Lerp(0.1,
m_fSlideTimeout, Math.Clamp(slideT, 0, 1));
1118 return m_pRecoilShakeParams;
1123 static void SetOverlayCameraFOV(
float fov)
1125 s_fOverlayCameraFOV = fov;
1129 protected override event float CalculateFovScalar(notnull CameraBase mainCamera, CameraBase overlayCamera)
1131 float fov = mainCamera.GetVerticalFOV();
1132 if (overlayCamera && s_fOverlayCameraFOV > 0)
1142 return m_bCameraActive;