Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_2DOpticsDisplay.c
Go to the documentation of this file.
3
6
7class SCR_2DOpticsDisplay : SCR_InfoDisplayExtended
8{
9 protected bool m_bActivated;
11
15
16 // Optics data
17 protected float m_fOpticBaseFov;
18 protected float m_fOpticCurrentFov;
19 protected float m_fReticleSize;
20 protected float m_fReticleAngularSize;
21 protected float m_fReticlePortion;
22 protected float m_fReticleBaseZoom;
23 protected float m_fReticleOffsetX;
24 protected float m_fReticleOffsetY;
25 protected float m_fVignetteScale;
26 protected float m_fVignetteSize;
27 protected float m_fVignetteMoveSpeed;
28 protected float m_fObjectiveFov;
29 protected float m_fObjectiveScale;
30 protected float m_fObjectiveSize;
31 protected float m_fMisalignmentScale;
33 protected float m_fRotationScale;
34 protected float m_fRotationDampingSpeed;
35 protected float m_fMovementScale;
36 protected float m_fMovementDampingSpeed;
37 protected float m_fRollScale;
38 protected float m_fRollDampingSpeed;
39 protected float m_fRollOffset;
40
42 protected vector m_vObjectiveOffset; // Objective and reticle offset
43 protected vector m_vVignetteOffset; // Vignette SetReticleOffset
50
51 protected bool m_bInitialBlurOver;
52
53 // Default widget names
54 const string WIDGET_LAYOUT_REAR = "HRearEyePiece";
55 const string WIDGET_LAYOUT_FRONT = "HFrontObjective";
56 const string WIDGET_IMAGE_COVER = "ImgCover";
57
58 const string WIDGET_SIZE_REAR = "SizeRear";
59 const string WIDGET_SIZE_OBJECTIVE = "SizeFrontObjective";
60
61 const string WIDGET_IMAGE_PADDING_LEFT = "ImgPaddingLeft";
62 const string WIDGET_IMAGE_PADDING_RIGHT = "ImgPaddingRight";
63 const string WIDGET_IMAGE_PADDING_TOP = "ImgPaddingTop";
64 const string WIDGET_IMAGE_PADDING_BOTTOM = "ImgPaddingBottom";
65
66 const string WIDGET_OVERLAY_RETICLES = "OverlayReticles";
67 const string WIDGET_IMAGE_RETICLE = "ImgReticle";
68 const string WIDGET_IMAGE_RETICLE_GLOW = "ImgReticleGlow";
69 const string WIDGET_IMAGE_VIGNETTE = "ImgVignette";
70 const string WIDGET_IMAGE_SCRATCHES = "ImgScratches";
71 const string WIDGET_BLUR = "Blur";
72 const string WIDGET_IMAGE_FILTER = "ImgFilter";
73
74 const string WIDGET_SIZE_LEFT = "SizePaddingLeft";
75 const string WIDGET_SIZE_TOP = "SizePaddingTop";
76
77 const float OPACITY_INITIAL = 0.75;
78
83
89
94
97
98 //------------------------------------------------------------------------------------------------
99 protected void OnLayoutChanged(SCR_HUDLayout newLayout, SCR_HUDLayout oldLayout, SCR_HUDManagerComponent hudManager)
100 {
101 if (!m_bActivated)
103 }
104
105 //------------------------------------------------------------------------------------------------
106 protected override void DisplayStartDraw(IEntity owner)
107 {
108 if (!m_wRoot)
109 return;
110
111 m_wRoot.SetVisible(false);
112
113 FindWidgets();
114
116
118 if (layoutHandler)
119 layoutHandler.GetOnLayoutChange().Insert(OnLayoutChanged);
120
121#ifdef ENABLE_DIAG
122 if (!s_bOpticDiagRegistered)
123 {
124 DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_WEAPONS_OPTICS_USE_2D, "", "Toggle 2D optics", "Weapons");
125 DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_WEAPONS_OPTICS, "", "Show optics diag", "Weapons");
126 s_bOpticDiagRegistered = true;
127 }
128#endif
129 }
130
131 //------------------------------------------------------------------------------------------------
132 protected override void DisplayStopDraw(IEntity owner)
133 {
135
136 if (!m_Optic)
137 return;
138
139 m_Optic.OnSetupOpticImage().Remove(SetupOpticImage);
140 m_Optic.OnIlluminationChange().Remove(ChangeReticleTint);
141 }
142
143 //------------------------------------------------------------------------------------------------
144 protected override void DisplayUpdate(IEntity owner, float timeSlice)
145 {
146#ifdef ENABLE_DIAG
147 if (s_bToggle2DOptics != DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_WEAPONS_OPTICS_USE_2D))
148 {
149 s_bToggle2DOptics = !s_bToggle2DOptics;
150 SetScope2DEnabled(!SCR_Global.IsScope2DEnabled());
151 }
152
153 if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_WEAPONS_OPTICS))
154 DebugOptics();
155#endif
156
157 if (!m_Optic)
158 return;
159
160 if (!m_bInADS && SCR_PlayerController.s_pLocalPlayerController && !SCR_PlayerController.s_pLocalPlayerController.GetIsBinocularsZoomed() && !m_Optic.IsSightADSActive())
161 return;
162
163 // Widget check
165 return;
166
168
169 MoveScopeWidgets(timeSlice);
170 LowerBlurIntensity(timeSlice, m_Optic.GetAnimationSpeedBlur());
171
172 m_fReticleOffsetX = m_Optic.GetReticleOffsetX();
173 m_fReticleOffsetY = m_Optic.GetCurrentReticleOffsetY();
175 }
176
177 //------------------------------------------------------------------------------------------------
179 protected void FindWidgets()
180 {
181 // Parts
184 m_wImgCover = ImageWidget.Cast(m_wRoot.FindAnyWidget(WIDGET_IMAGE_COVER));
186
188 {
189 Print("Scope vignette movement is not possible due to missing widget references!", LogLevel.WARNING);
190 return;
191 }
192
193 // Rear part - eye piece
197
198 // Front part - objective
202
206 m_wBlur = BlurWidget.Cast(m_wRoot.FindAnyWidget(WIDGET_BLUR));
208 }
209
210 //------------------------------------------------------------------------------------------------
213 {
214 // Setup reticle
215 if (!m_sReticleTexture.IsEmpty())
216 m_wImgReticle.LoadImageTexture(0, m_sReticleTexture);
217
218 m_wImgReticleGlow.SetVisible(!m_sReticleTexture.IsEmpty());
219
220 if (!m_sReticleGlowTexture.IsEmpty())
221 m_wImgReticleGlow.LoadImageTexture(0, m_sReticleGlowTexture);
222
223 m_wImgReticleGlow.SetVisible(!m_sReticleGlowTexture.IsEmpty());
224
225 // Setup lens filter
226 if (!m_sFilterTexture.IsEmpty())
227 m_wImgFilter.LoadImageTexture(0, m_sFilterTexture);
228
229 m_wImgFilter.SetVisible(!m_sFilterTexture.IsEmpty());
230
231 UpdateCurrentFov(true);
232 }
233
234 //------------------------------------------------------------------------------------------------
235 void UpdateCurrentFov(bool forceUpdate = false)
236 {
237 float fov;
238 if (m_Optic)
239 {
240 // for binoculars getFOV is wrong
241 SCR_FixedFOVInfo fixedFOVInfo = SCR_FixedFOVInfo.Cast(m_Optic.GetFOVInfo());
242 if (fixedFOVInfo)
243 fov = m_Optic.GetFovZoomed();
244 else
245 fov = m_Optic.GetFOV();
246 }
247 else
248 {
249 CameraBase camera = GetGame().GetCameraManager().CurrentCamera();
250 if (camera)
251 fov = camera.GetVerticalFOV();
252 }
253
254 if (!float.AlmostEqual(m_fOpticCurrentFov, fov))
255 m_fOpticCurrentFov = fov;
256 else if (!forceUpdate)
257 return;
258
260 }
261
262 //------------------------------------------------------------------------------------------------
265 {
266 // Compute reticle base FOV once
267 if (m_fReticleBaseZoom > 0)
268 m_fReticleBaseZoom = -m_Optic.CalculateZoomFOV(m_fReticleBaseZoom);
269
270 float fovReticle;
271 if (m_fReticleBaseZoom == 0)
272 fovReticle = m_fOpticCurrentFov;
273 else
274 fovReticle = -m_fReticleBaseZoom;
275
276 // Account for part that represents the measurable reticle
277 float reticleAngularSize;
278 if (m_fReticlePortion > 0)
279 reticleAngularSize = m_fReticleAngularSize / m_fReticlePortion;
280
281 if (fovReticle > 0)
282 m_fReticleSize = reticleAngularSize / fovReticle;
283 else if (m_fOpticBaseFov > 0)
284 m_fReticleSize = reticleAngularSize / m_fOpticBaseFov;
285
286 UpdateScale(1, 1, 1);
287 }
288
289 //------------------------------------------------------------------------------------------------
290 protected void OnADSChange(notnull SCR_2DOpticsComponent comp, bool inADS)
291 {
292 if (m_Optic != comp)
293 {
294 // Clear previous optic invokers as well
295 if (m_Optic)
296 {
297 m_Optic.OnSetupOpticImage().Remove(SetupOpticImage);
298 m_Optic.OnIlluminationChange().Remove(ChangeReticleTint);
299 }
300
301 m_Optic = comp;
302
303 GetOpticData();
304 }
305
306 if (inADS)
307 {
308 m_Optic.OnSetupOpticImage().Insert(SetupOpticImage);
309 m_Optic.OnIlluminationChange().Insert(ChangeReticleTint);
310 }
311 else
312 {
313 m_Optic.OnSetupOpticImage().Remove(SetupOpticImage);
314 m_Optic.OnIlluminationChange().Remove(ChangeReticleTint);
315 Deactivate();
316 return;
317 }
318
319 m_wRoot.SetZOrder(-1);
320 m_wRoot.SetVisible(false);
321
322 m_bInitialBlurOver = false;
323
325
326 m_Optic.GetRotation(m_vRotation, 1);
329
330 m_Optic.GetMovement(m_vMovement, 1);
331
334
336
337 Activate();
338 }
339
340 //------------------------------------------------------------------------------------------------
341 protected void Activate()
342 {
343 // Prevent calnceling animation
345 GetGame().GetCallqueue().Remove(DeactivateWidget);
346
347 // Activate and setup hud
348 m_wRoot.SetVisible(true);
349 m_wImgCover.SetVisible(false);
350 m_wRoot.SetOpacity(0);
351
352 // Blur
353 m_wBlur.SetIntensity(OPACITY_INITIAL);
354 m_wBlur.SetOpacity(1);
355
356 m_bActivated = true;
357
358 int activationDelay;
359 int enterTime;
360 SCR_2DOpticsComponentClass data = SCR_2DOpticsComponentClass.Cast(m_Optic.GetComponentData(m_Optic.GetOwner()));
361 if (data)
362 {
363 activationDelay = data.GetAnimationActivationDelay();
364 enterTime = data.GetAnimationEnterTime();
365 }
366
367 //Play fadeIn animation after given delay
368 GetGame().GetCallqueue().CallLater(PlayEntryAnimation, activationDelay, false, enterTime);
369 }
370
371 //------------------------------------------------------------------------------------------------
373 protected void Deactivate()
374 {
375 m_bActivated = false;
376
377 // Prevent entering animation
379 GetGame().GetCallqueue().Remove(PlayEntryAnimation);
380
381 if (!m_Optic)
382 return;
383
384 int deactivationDelay;
385 SCR_2DOpticsComponentClass data = SCR_2DOpticsComponentClass.Cast(m_Optic.GetComponentData(m_Optic.GetOwner()));
386 if (data)
387 deactivationDelay = data.GetAnimationDeactivationDelay();
388
389 //Deactivate the HUD after set delay
390 GetGame().GetCallqueue().CallLater(DeactivateWidget, deactivationDelay, false);
391 }
392
393 //------------------------------------------------------------------------------------------------
396 protected void PlayEntryAnimation(float animationSpeed)
397 {
398 if (animationSpeed > 0)
399 AnimateWidget.Opacity(m_wRoot, 1, animationSpeed);
400 else
401 m_wRoot.SetOpacity(1);
402 }
403
404 //------------------------------------------------------------------------------------------------
406 protected void DeactivateWidget()
407 {
408 if (m_wImgCover)
409 m_wImgCover.SetOpacity(0);
410
411 if (m_wRoot)
412 m_wRoot.SetVisible(false);
413 }
414
415 //------------------------------------------------------------------------------------------------
418 {
419 SCR_2DOpticsComponentClass data = SCR_2DOpticsComponentClass.Cast(m_Optic.GetComponentData(m_Optic.GetOwner()));
420 if (!data)
421 return;
422
425 m_fOpticBaseFov = m_Optic.GetFovZoomed();
426 m_fObjectiveFov = m_Optic.GetObjectiveFov();
427 m_fObjectiveScale = m_Optic.GetObjectiveScale();
428 m_fVignetteScale = data.GetVignetteScale();
429 m_fVignetteMoveSpeed = data.GetVignetteMoveSpeed();
430 m_fMisalignmentScale = data.GetMisalignmentScale();
431 m_fMisalignmentDampingSpeed = data.GetMisalignmentDampingSpeed();
432 m_fRotationScale = data.GetRotationScale();
433 m_fRotationDampingSpeed = data.GetRotationDampingSpeed();
434 m_fMovementScale = data.GetMovementScale();
435 m_fMovementDampingSpeed = data.GetMovementDampingSpeed();
436 m_fRollScale = data.GetRollScale();
437 m_fRollDampingSpeed = data.GetRollDampingSpeed();
438
439#ifdef ENABLE_DIAG
440 s_bDebugOpticsReset = true;
441#endif
442 }
443
444 //------------------------------------------------------------------------------------------------
446 void UpdateScale(float reticleScale, float vignetteScale, float objectiveScale)
447 {
448 float uiScale = 1;
449 WorkspaceWidget workspace = GetGame().GetWorkspace();
450 if (workspace)
451 uiScale = workspace.DPIUnscale(workspace.GetHeight());
452
453 // Reticle size setup
455 {
456 float reticleSize = m_fReticleSize * uiScale * reticleScale;
457 FrameSlot.SetSize(m_wOverlayReticles, reticleSize, reticleSize);
458 }
459
460 // Vignette size setup
462 {
463 m_fVignetteSize = m_fObjectiveFov * m_fVignetteScale * uiScale * vignetteScale / m_fOpticBaseFov;
464
465 m_wSizeLayoutRear.SetWidthOverride(m_fVignetteSize);
466 m_wSizeLayoutRear.SetHeightOverride(m_fVignetteSize);
467 }
468
469 // Ocular size setup
471 {
472 m_fObjectiveSize = m_fObjectiveFov * m_fObjectiveScale * uiScale * objectiveScale / m_fOpticBaseFov;
473
475 m_wSizeLayoutObjective.SetHeightOverride(m_fObjectiveSize);
476 }
477 }
478
479 //------------------------------------------------------------------------------------------------
483 void SetReticleOffset(float x, float y)
484 {
486 return;
487
488 WorkspaceWidget workspace = GetGame().GetWorkspace();
489 if (!workspace)
490 return;
491
492 float fov = m_fOpticBaseFov;
493 CameraManager cameraManager = GetGame().GetCameraManager();
494 if (cameraManager)
495 {
496 CameraBase camera = cameraManager.CurrentCamera();
497 if (camera)
498 fov = camera.GetVerticalFOV();
499 }
500
501 float uiHeight = workspace.DPIUnscale(workspace.GetHeight());
502 float offsetX = x * uiHeight / fov;
503 float offsetY = y * uiHeight / fov;
504
505 FrameSlot.SetPos(m_wOverlayReticles, offsetX, offsetY);
506
508 if (m_wImgReticle)
509 {
510 float pivotX = 0.5 - (offsetX / size[0]);
511 float pivotY = 0.5 - (offsetY / size[1]);
512 m_wImgReticle.SetPivot(pivotX, pivotY);
513 }
514
516 {
517 float pivotX = 0.5 - (offsetX / size[0]);
518 float pivotY = 0.5 - (offsetY / size[1]);
519 m_wImgReticleGlow.SetPivot(pivotX, pivotY);
520 }
521 }
522
523 //------------------------------------------------------------------------------------------------
527 protected void LowerBlurIntensity(float timeSlice, float speed)
528 {
529 if (!m_wBlur)
530 return;
531
532 float intensity = m_wBlur.GetIntensity();
533 intensity = Math.Lerp(intensity, 0, timeSlice * speed);
534
535 // Clear initial bluer
536 if (intensity < 0.1 && !m_bInitialBlurOver)
537 {
538 m_bInitialBlurOver = true;
539 intensity = 0;
540 }
541
542 m_wBlur.SetIntensity(intensity);
543 }
544
545 //------------------------------------------------------------------------------------------------
549 protected void ChangeReticleTint(Color color, Color colorGlow)
550 {
552 m_wImgReticleGlow.SetColor(colorGlow);
553
554 if (m_wImgReticle)
555 m_wImgReticle.SetColor(color);
556 }
557
558 //------------------------------------------------------------------------------------------------
560 protected void MoveScopeWidgets(float timeSlice)
561 {
562 // Only valid if there is main camera
563 CameraManager cameraManager = GetGame().GetCameraManager();
564 if (!cameraManager)
565 return;
566
567 CameraBase camera = cameraManager.CurrentCamera();
568 if (!camera)
569 return;
570
571 // Only positive FOV allowed
572 float fov = camera.GetVerticalFOV();
573 if (fov <= 0)
574 return;
575
576 // Update vignette and reticle direction and roll
577 vector misalignment = m_Optic.GetMisalignmentAngles(camera);
578
579 // Stabilize roll
580 float roll = misalignment[2] * m_fRollScale;
581 if (m_fRollDampingSpeed > 0)
582 {
583 float rollSmooth = Math.Min(1, timeSlice * m_fRollDampingSpeed);
584 m_fRollOffset = Math.Lerp(m_fRollOffset, roll, rollSmooth);
585 roll -= m_fRollOffset;
586 }
587
588 // Stabilize binocular reticle over time
590 {
591 float offsetDamping = Math.Min(timeSlice * m_fMisalignmentDampingSpeed, 1);
592 m_vMisalignmentOffset = vector.Lerp(m_vMisalignmentOffset, misalignment, offsetDamping);
593 misalignment = misalignment - m_vMisalignmentOffset;
594 }
595
596 // Stabilize rotation speed over time
597 vector rotation = m_Optic.GetRotation(m_vRotation, timeSlice);
599 {
600 float rotationDamping = Math.Min(timeSlice * m_fRotationDampingSpeed, 1);
601 m_vRotationOffset = vector.Lerp(m_vRotationOffset, rotation, rotationDamping);
603 }
604
605 // Movement is also stabilizable
606 vector movement = m_Optic.GetMovement(m_vMovement, timeSlice);
608 {
609 float movementDamping = Math.Min(timeSlice * m_fMovementDampingSpeed, 1);
610 m_vMovementOffset = vector.Lerp(m_vMovementOffset, movement, movementDamping);
611 movement = movement - m_vMovementOffset;
612 }
613
614 // Objective must be set instantly
616
617 // Make sure lerp doesn't go out of bounds
618 float vignetteMove = Math.Min(timeSlice * m_fVignetteMoveSpeed, 1);
619
621
622 if (m_fRotationScale != 0)
624
625 if (m_fMovementScale != 0)
627
628 // Clamp vignette distance from objective center down to objective size
629 vector vignetteObjectiveOffset = m_vVignetteOffset - m_vObjectiveOffset;
630 float vignetteDistance = vignetteObjectiveOffset.Length();
631 if (vignetteDistance > 0 && vignetteDistance > m_fObjectiveFov * m_fObjectiveScale)
632 {
633 vignetteObjectiveOffset *= m_fObjectiveFov * m_fObjectiveScale / vignetteDistance;
634 m_vVignetteOffset = m_vObjectiveOffset + vignetteObjectiveOffset;
635 }
636
637 WorkspaceWidget workspace = GetGame().GetWorkspace();
638
639 float screenW, screenH;
640 workspace.GetScreenSize(screenW, screenH);
641 screenW = workspace.DPIUnscale(screenW);
642 screenH = workspace.DPIUnscale(screenH);
643
644 float pixelsPerDegree = screenH / fov;
645
646 // Objective horizontal movement
647 float defaultFrontLeft = LayerDefaultPosition(screenW, m_fObjectiveSize);
648 float objectiveX = m_vObjectiveOffset[0] * pixelsPerDegree;
649 float frontPaddingLeft = defaultFrontLeft + objectiveX;
650 float frontEdgeRight = screenW - m_fObjectiveSize;
651
652 // If objective is passing right edge of the screen, horizontal movement is halved
653 if (frontPaddingLeft > frontEdgeRight)
654 frontPaddingLeft = frontEdgeRight + (frontPaddingLeft - frontEdgeRight) * 2;
655
656 m_wFrontFillLeft.SetWidthOverride(frontPaddingLeft);
657
658 // Objective vertical movement
659 float defaultFrontTop = LayerDefaultPosition(screenH, m_fObjectiveSize);
660 float objectiveY = m_vObjectiveOffset[1] * pixelsPerDegree;
661 float frontPaddingTop = defaultFrontTop - objectiveY;
662 float frontEdgeBottom = screenH - m_fObjectiveSize;
663
664 // If objective is passing bottom edge of the screen, vertical movement is halved
665 if (frontPaddingTop > frontEdgeBottom)
666 frontPaddingTop = frontEdgeBottom + (frontPaddingTop - frontEdgeBottom) * 2;
667
668 m_wFrontFillTop.SetHeightOverride(frontPaddingTop);
669
670 // Vignette horizontal movement
671 float defaultRearLeft = LayerDefaultPosition(screenW, m_fVignetteSize);
672 float vignetteX = 2 * objectiveX - m_vVignetteOffset[0] * pixelsPerDegree;
673 float rearPaddingLeft = defaultRearLeft + vignetteX;
674 float rearEdgeLeft = screenW - m_fVignetteSize;
675
676 // If vignette is passing right edge of the screen, horizontal movement is halved
677 if (rearPaddingLeft > rearEdgeLeft)
678 rearPaddingLeft = rearEdgeLeft + (rearPaddingLeft - rearEdgeLeft) * 2;
679
680 m_wRearFillLeft.SetWidthOverride(rearPaddingLeft);
681
682 // Vignette vertical movement
683 float defaultRearTop = LayerDefaultPosition(screenH, m_fVignetteSize);
684 float vignetteY = 2 * objectiveY - m_vVignetteOffset[1] * pixelsPerDegree;
685 float rearPaddingTop = defaultRearTop - vignetteY;
686 float rearEdgeBottom = screenH - m_fVignetteSize;
687
688 // If vignette is passing bottom edge of the screen, vertical movement is halved
689 if (rearPaddingTop > rearEdgeBottom)
690 rearPaddingTop = rearEdgeBottom + (rearPaddingTop - rearEdgeBottom) * 2;
691
692 m_wRearFillTop.SetHeightOverride(rearPaddingTop);
693
694 // Reticle rotation
695 if (m_wImgReticle)
696 m_wImgReticle.SetRotation(roll);
697
699 m_wImgReticleGlow.SetRotation(roll);
700
701 if (m_wImgFilter)
702 m_wImgFilter.SetRotation(roll);
703
704 if (m_wImgCover)
705 m_wImgCover.SetRotation(roll);
706
707 if (m_wImgScratches)
708 m_wImgScratches.SetRotation(roll + m_Optic.GetScratchesRoll());
709
710 // Motion offset blur
713 }
714
715 //------------------------------------------------------------------------------------------------
716 protected void MotionBlur(float posX, float posY)
717 {
718 if (!m_wBlur)
719 return;
720
721 // Check movement
722 if (!m_Optic.GetIsMoving() || !m_Optic.GetIsRotating())
723 return;
724
725 SCR_2DOpticsComponentClass data = SCR_2DOpticsComponentClass.Cast(m_Optic.GetComponentData(m_Optic.GetOwner()));
726 if (!data)
727 return;
728
729 // Pick axis
730 float intensity = Math.AbsFloat(posX);
731 if (intensity > Math.AbsFloat(posY))
732 intensity = Math.AbsFloat(posY);
733
734 // Scale and limit
735 intensity = intensity * data.GetMotionBlurScale();
736 if (intensity > data.GetMotionBlurMax())
737 intensity = data.GetMotionBlurMax();
738
739 m_wBlur.SetIntensity(intensity);
740 }
741
742 //------------------------------------------------------------------------------------------------
743 static float LayerDefaultPosition(float screenSize, float layerSize)
744 {
745 return (screenSize - layerSize) * 0.5;
746 }
747
748#ifdef ENABLE_DIAG
749 protected static bool s_bOpticDiagRegistered;
750 protected static bool s_bToggle2DOptics;
751 protected static bool s_bDebugOptics;
752 protected static bool s_bDebugOpticsReset;
753 protected static bool s_bDebug2DOptics;
754 protected static bool s_bDebug2DOpticsReset;
755 protected static bool s_bDebugDrawReset;
756 protected static bool s_bDebugDrawCross = true;
757 protected static bool s_bDebugDrawNotches = true;
758 protected static bool s_bDebugDrawFieldOfView = true;
759 protected static bool s_bDebugDrawRandomColors;
760
761 protected static SCR_EOpticsAngleUnits s_eCrossUnit = SCR_EOpticsAngleUnits.RETICLE;
762 protected static float s_fCrossUnit = 0.05625;
763 protected static float s_fCrossRadius = 100;
764
765 protected static SCR_EOpticsAngleUnits s_eNotchesUnit = SCR_EOpticsAngleUnits.RETICLE;
766 protected static float s_fNotchesUnit = 0.05625;
767 protected static float s_fNotchesSize = 100;
768 protected static float s_fNotchesSmallLength = 5;
769 protected static float s_fNotchesSmallSpacing = 5;
770 protected static float s_fNotchesLargeLength = 10;
771 protected static float s_fNotchesLargeSpacing = 10;
772
773 protected static SCR_EOpticsAngleUnits s_eFieldOfViewUnit = SCR_EOpticsAngleUnits.OBJECTIVE;
774 protected static float s_fFieldOfViewUnit = 0.05625;
775 protected static float s_fFieldOfViewAngle = 100;
776
777 protected static ref array<int> s_aRandomColors = {COLOR_BLUE, COLOR_RED, COLOR_GREEN, COLOR_YELLOW};
778 protected static int s_iLineColor;
779
780 //------------------------------------------------------------------------------------------------
781 protected void InputFloatClamped(inout float value, string label, float min, float max, int pxWidth = 100)
782 {
783 DbgUI.InputFloat(label, value, pxWidth);
784 value = Math.Clamp(value, min, max);
785 }
786
787 //------------------------------------------------------------------------------------------------
788 void DebugOptics()
789 {
790 if (s_bDebugOpticsReset)
791 {
792 s_bDebugOpticsReset = false;
793
794 if (!SCR_Global.IsScope2DEnabled())
795 {
796 SetScope2DEnabled(true);
797 s_bToggle2DOptics = !DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_WEAPONS_OPTICS_USE_2D);
798 }
799
800 return;
801 }
802
803 if (s_bDebugDrawReset)
804 {
805 s_bDebugDrawReset = false;
806 s_bDebugDrawCross = true;
807 s_bDebugDrawNotches = true;
808 s_bDebugDrawFieldOfView = true;
809 s_bDebugDrawRandomColors = false;
810
811 s_eCrossUnit = SCR_EOpticsAngleUnits.RETICLE;
812 s_fCrossUnit = 0.05625;
813 s_fCrossRadius = 100;
814
815 s_eNotchesUnit = SCR_EOpticsAngleUnits.RETICLE;
816 s_fNotchesUnit = 0.05625;
817 s_fNotchesSize = 100;
818 s_fNotchesSmallLength = 5;
819 s_fNotchesSmallSpacing = 5;
820 s_fNotchesLargeLength = 10;
821 s_fNotchesLargeSpacing = 10;
822
823 s_eFieldOfViewUnit = SCR_EOpticsAngleUnits.OBJECTIVE;
824 s_fFieldOfViewUnit = 0.05625;
825 s_fFieldOfViewAngle = 100;
826
827 return;
828 }
829
830 vector sightMat[4];
831
832 if (m_Optic)
833 {
834 m_Optic.GetSightsTransform(sightMat, true);
835 sightMat[3] = m_Optic.GetSightsFrontPosition(true);
836 vector ownerMat[4];
837 m_Optic.GetOwner().GetWorldTransform(ownerMat);
838 Math3D.MatrixMultiply4(ownerMat, sightMat, sightMat);
839 }
840
841 // In case of binoculars, side and up vector is expected to match camera
842 CameraBase camera = GetGame().GetCameraManager().CurrentCamera();
843 if (camera && m_fRollDampingSpeed != 0)
844 {
845 vector cameraMat[4];
846 camera.GetTransform(cameraMat);
847 sightMat[0] = cameraMat[0];
848 sightMat[1] = cameraMat[1];
849 }
850
851 DbgUI.Begin("Optics", 100, 300);
852
853 array<string> units = {};
854 SCR_Enum.GetEnumNames(SCR_EOpticsAngleUnits, units);
855
857 {
858 DbgUI.Text("________________________________________");
859 DbgUI.Check("OPTICS ", s_bDebugOptics);
860 }
861
862 // Basic reticle and objective FOV settings
863 if (s_bDebugOptics)
864 {
865 {
866 InputFloatClamped(m_fObjectiveFov, "m_fObjectiveFov deg", 0, 100);
867 InputFloatClamped(m_fObjectiveScale, "m_fObjectiveScale %", 0, 100);
868 InputFloatClamped(m_fReticleBaseZoom, "m_fReticleBaseZoom x", -60, 200);
869 InputFloatClamped(m_fReticleAngularSize, "m_fReticleAngularSize deg", 0, 100);
870 InputFloatClamped(m_fReticlePortion, "m_fReticlePortion %", 0, 100);
871 InputFloatClamped(m_fReticleOffsetX, "m_fReticleOffsetX deg", -90, 90);
872 InputFloatClamped(m_fReticleOffsetY, "m_fReticleOffsetY deg", -90, 90);
873 }
874
875 if (m_Optic && DbgUI.Button("LOAD OPTICS ATTRIBUTES"))
876 GetOpticData();
877
878 if (m_Optic && DbgUI.Button("SAVE OPTICS ATTRIBUTES"))
879 {
880 m_Optic.SetObjectiveFov(m_fObjectiveFov);
881 m_Optic.SetObjectiveScale(m_fObjectiveScale);
882 m_Optic.SetReticleBaseZoom(m_fReticleBaseZoom);
883 m_Optic.SetReticleAngularSize(m_fReticleAngularSize);
884 m_Optic.SetReticlePortion(m_fReticlePortion);
885 m_Optic.SetReticleOffsetX(m_fReticleOffsetX);
886 m_Optic.SetReticleOffsetY(m_fReticleOffsetY);
887 }
888 }
889
891 {
892 DbgUI.Text("________________________________________");
893 DbgUI.Check("2D OPTICS ", s_bDebug2DOptics);
894 }
895
896 // 2D optics features attributes
897 if (s_bDebug2DOptics)
898 {
899 {
900 InputFloatClamped(m_fVignetteScale, "m_fVignetteScale ", 0, 100);
901 InputFloatClamped(m_fVignetteMoveSpeed, "m_fVignetteMoveSpeed ", -100, 100);
902 InputFloatClamped(m_fMisalignmentScale, "m_fMisalignmentScale ", -100, 100);
903 InputFloatClamped(m_fMisalignmentDampingSpeed, "m_fMisalignmentDampingSpeed ", -100, 100);
904 InputFloatClamped(m_fRotationScale, "m_fRotationScale ", -100, 100);
905 InputFloatClamped(m_fRotationDampingSpeed, "m_fRotationDampingSpeed ", -100, 100);
906 InputFloatClamped(m_fMovementScale, "m_fMovementScale ", -100, 100);
907 InputFloatClamped(m_fMovementDampingSpeed, "m_fMovementDampingSpeed ", -100, 100);
908 InputFloatClamped(m_fRollScale, "m_fRollScale ", -100, 100);
909 InputFloatClamped(m_fRollDampingSpeed, "m_fRollDampingSpeed ", -100, 100);
910 }
911 }
912
913 // Debug settings
914 {
915 DbgUI.Text("________________________________________");
916
917 if (DbgUI.Button("RESET DEBUG ATTRIBUTES"))
918 s_bDebugDrawReset = true;
919
920 DbgUI.Check("RANDOM LINE COLORS ", s_bDebugDrawRandomColors);
921
922 if (s_bDebugDrawRandomColors)
923 s_iLineColor = s_aRandomColors.GetRandomElement();
924 else
925 s_iLineColor = COLOR_RED;
926
927 DbgUI.Text(" ");
928 }
929
931 {
932 DbgUI.Text("________________________________________");
933 DbgUI.Check("CROSS ", s_bDebugDrawCross);
934 }
935
936 // Draw basic crosshair matching reticle size
937 if (s_bDebugDrawCross)
938 {
939 {
940 DbgUI.Combo("Cross units ", s_eCrossUnit, units);
941 if (s_eCrossUnit == SCR_EOpticsAngleUnits.CUSTOM)
942 InputFloatClamped(s_fCrossUnit, "Custom cross unit deg", 0, 180);
943
944 InputFloatClamped(s_fCrossRadius, "Cross radius ", 0, 1000);
945 }
946
947 float unit = DebugAngleUnitsToDegrees(s_eCrossUnit, s_fCrossUnit);
948
949 DebugDrawCross(sightMat, s_fCrossRadius * unit);
950 }
951
953 {
954 DbgUI.Text("________________________________________");
955 DbgUI.Check("NOTCHES ", s_bDebugDrawNotches);
956 }
957
958 // Draw notches for the angle measurement across reticle
959 if (s_bDebugDrawNotches)
960 {
961 {
962 DbgUI.Combo("Notches units ", s_eNotchesUnit, units);
963 if (s_eNotchesUnit == SCR_EOpticsAngleUnits.CUSTOM)
964 InputFloatClamped(s_fNotchesUnit, "Custom notches unit deg", 0, 180);
965
966 InputFloatClamped(s_fNotchesSize, "Size ", 0, 100);
967 InputFloatClamped(s_fNotchesSmallLength, "Small length ", 0, 100);
968 InputFloatClamped(s_fNotchesSmallSpacing, "Small spacing ", 0, 100);
969 InputFloatClamped(s_fNotchesLargeLength, "Large length ", 0, 100);
970 InputFloatClamped(s_fNotchesLargeSpacing, "Large spacing ", 0, 100);
971 }
972
973 float unit = DebugAngleUnitsToDegrees(s_eNotchesUnit, s_fNotchesUnit);
974 DebugDrawNotches(sightMat, s_fNotchesSmallLength * unit, s_fNotchesSmallSpacing * unit, s_fNotchesSize * unit * 0.5);
975 DebugDrawNotches(sightMat, s_fNotchesLargeLength * unit, s_fNotchesLargeSpacing * unit, s_fNotchesSize * unit * 0.5);
976 }
977
979 {
980 DbgUI.Text("________________________________________");
981 DbgUI.Check("FIELD OF VIEW ", s_bDebugDrawFieldOfView);
982 }
983
984 // Draw basic circle and frame
985 if (s_bDebugDrawFieldOfView)
986 {
987 {
988 DbgUI.Combo("Field of view units ", s_eFieldOfViewUnit, units);
989 if (s_eFieldOfViewUnit == SCR_EOpticsAngleUnits.CUSTOM)
990 InputFloatClamped(s_fFieldOfViewUnit, "Custom field of view unit deg", 0, 180);
991
992 InputFloatClamped(s_fFieldOfViewAngle, "Field of view angle ", 0, 1000);
993 }
994
995 float unit = DebugAngleUnitsToDegrees(s_eFieldOfViewUnit, s_fFieldOfViewUnit);
996
997 DebugDrawFieldOfView(sightMat, s_fFieldOfViewAngle * unit);
998 }
999
1000 DbgUI.End();
1001
1002 if (m_Optic && s_bDebugOptics)
1003 UpdateCurrentFov(true);
1004
1005 if (m_Optic && s_bDebug2DOptics)
1006 UpdateScale(1, 1, 1);
1007 }
1008
1009 //------------------------------------------------------------------------------------------------
1010 protected float DebugAngleUnitsToDegrees(SCR_EOpticsAngleUnits unit, float custom = 0)
1011 {
1012 if (unit == SCR_EOpticsAngleUnits.DEGREES)
1013 return 1;
1014
1015 if (unit == SCR_EOpticsAngleUnits.RETICLE)
1016 {
1017 float reticleAngularSize = m_fReticleAngularSize * 0.01;
1018
1019 if (m_fReticleBaseZoom < 0)
1020 reticleAngularSize *= m_fOpticCurrentFov / -m_fReticleBaseZoom;
1021 else if (m_fReticleBaseZoom > 0)
1022 reticleAngularSize *= m_fOpticCurrentFov / m_Optic.CalculateZoomFOV(m_fReticleBaseZoom);
1023
1024 return reticleAngularSize;
1025 }
1026
1027 if (unit == SCR_EOpticsAngleUnits.OBJECTIVE)
1028 {
1029 float objectiveSize = m_fObjectiveFov * m_fObjectiveScale * 0.01;
1030
1031 if (m_fOpticBaseFov > 0)
1032 objectiveSize *= m_fOpticCurrentFov / m_fOpticBaseFov;
1033
1034 return objectiveSize;
1035 }
1036
1037 if (unit == SCR_EOpticsAngleUnits.MILS_WP)
1038 return 360 / 6000;
1039
1040 if (unit == SCR_EOpticsAngleUnits.MILS_NATO)
1041 return 360 / 6400;
1042
1043 if (unit == SCR_EOpticsAngleUnits.MILS_STRECK)
1044 return 360 / 6300;
1045
1046 if (unit == SCR_EOpticsAngleUnits.MILLIRADIANS)
1047 return Math.RAD2DEG * 0.001;
1048
1049 return custom;
1050 }
1051
1052 //------------------------------------------------------------------------------------------------
1053 static void DebugDrawFieldOfView(vector sightMat[4], float angle)
1054 {
1055 if (float.AlmostEqual(angle, 0))
1056 return;
1057
1058 // References
1059 float targetSize = Math.Tan(Math.DEG2RAD * angle * 0.5);
1060 float range = 1000;
1061 CameraBase currentCamera = GetGame().GetCameraManager().CurrentCamera();
1062 if (currentCamera)
1063 range = currentCamera.GetFarPlane() * 0.5;
1064
1065 vector fovMat[4];
1066 fovMat[0] = sightMat[0];
1067 fovMat[1] = sightMat[2];
1068 fovMat[2] = sightMat[1];
1069 fovMat[3] = sightMat[3] + sightMat[2] * range;
1070
1071 SCR_Shape.DrawCircle(fovMat, targetSize * range, s_iLineColor, COLOR_YELLOW_A, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER | ShapeFlags.TRANSP | ShapeFlags.NOOUTLINE | ShapeFlags.NOZWRITE);
1072 }
1073
1074 //------------------------------------------------------------------------------------------------
1075 protected void DebugDrawNotches(vector sightMat[4], float length, float spacing, float size)
1076 {
1077 if (float.AlmostEqual(length, 0))
1078 return;
1079
1080 if (float.AlmostEqual(spacing, 0))
1081 return;
1082
1083 vector opticSide = sightMat[0];
1084 vector opticUp = sightMat[1];
1085 vector opticDir = sightMat[2];
1086 vector opticPos = sightMat[3];
1087
1088 // References
1089 int count = Math.Floor(size / spacing);
1090 float notchSpacing = Math.DEG2RAD * spacing;
1091 float notchHalf = Math.Tan(Math.DEG2RAD * length * 0.5);
1092 float range = 1000;
1093 CameraBase currentCamera = GetGame().GetCameraManager().CurrentCamera();
1094 if (currentCamera)
1095 range = currentCamera.GetFarPlane() * 0.5;
1096
1097 vector zeroMat[4] = sightMat;
1098 zeroMat[3] = opticPos + opticDir * range;
1099
1100 vector notchMat[4] = zeroMat;
1101 vector notchSide = opticSide * notchHalf * range;
1102 vector notchUp = opticUp * notchHalf * range;
1103 vector notch[2];
1104
1105 // Horizontal markings - left
1106 notchMat = zeroMat;
1107 for (int i; i < count; i++)
1108 {
1109 SCR_Math3D.RotateAround(notchMat, opticPos, opticUp, -notchSpacing, notchMat);
1110 notch[0] = notchMat[3] + notchUp;
1111 notch[1] = notchMat[3] - notchUp;
1112 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, notch, 2);
1113 }
1114
1115 // Horizontal markings - right
1116 notchMat = zeroMat;
1117 for (int i; i < count; i++)
1118 {
1119 SCR_Math3D.RotateAround(notchMat, opticPos, opticUp, notchSpacing, notchMat);
1120 notch[0] = notchMat[3] + notchUp;
1121 notch[1] = notchMat[3] - notchUp;
1122 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, notch, 2);
1123 }
1124
1125 // Vertical markings - up
1126 notchMat = zeroMat;
1127 for (int i; i < count; i++)
1128 {
1129 SCR_Math3D.RotateAround(notchMat, opticPos, opticSide, -notchSpacing, notchMat);
1130 notch[0] = notchMat[3] + notchSide;
1131 notch[1] = notchMat[3] - notchSide;
1132 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, notch, 2);
1133 }
1134
1135 // Vertical markings - down
1136 notchMat = zeroMat;
1137 for (int i; i < count; i++)
1138 {
1139 SCR_Math3D.RotateAround(notchMat, opticPos, opticSide, notchSpacing, notchMat);
1140 notch[0] = notchMat[3] + notchSide;
1141 notch[1] = notchMat[3] - notchSide;
1142 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, notch, 2);
1143 }
1144 }
1145
1146 //------------------------------------------------------------------------------------------------
1147 protected void DebugDrawCross(vector sightMat[4], float radius)
1148 {
1149 if (float.AlmostEqual(radius, 0))
1150 return;
1151
1152 vector opticSide = sightMat[0];
1153 vector opticUp = sightMat[1];
1154 vector opticDir = sightMat[2];
1155 vector opticPos = sightMat[3];
1156
1157 // References
1158 float crossRadius = Math.Tan(Math.DEG2RAD * radius * 0.5);
1159 float range = 1000;
1160 CameraBase currentCamera = GetGame().GetCameraManager().CurrentCamera();
1161 if (currentCamera)
1162 range = currentCamera.GetFarPlane() * 0.5;
1163
1164 vector crossPos = opticPos + opticDir * range;
1165 vector cross[2];
1166
1167 // Line of sight
1168 cross[0] = opticPos;
1169 cross[1] = crossPos;
1170 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, cross, 2);
1171
1172 // Horizontal
1173 vector crossSide = opticSide * crossRadius * range;
1174 cross[0] = crossPos + crossSide;
1175 cross[1] = crossPos - crossSide;
1176 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, cross, 2);
1177
1178 // Vertical
1179 vector crossUp = opticUp * crossRadius * range;
1180 cross[0] = crossPos + crossUp;
1181 cross[1] = crossPos - crossUp;
1182 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, cross, 2);
1183
1184 // Diagonal #1
1185 cross[0] = crossPos - crossUp - crossSide;
1186 cross[1] = crossPos + crossUp + crossSide;
1187 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, cross, 2);
1188
1189 // Diagonal #2
1190 cross[0] = crossPos + crossUp - crossSide;
1191 cross[1] = crossPos - crossUp + crossSide;
1192 Shape.CreateLines(s_iLineColor, ShapeFlags.ONCE | ShapeFlags.NOZBUFFER, cross, 2);
1193 }
1194
1195 //------------------------------------------------------------------------------------------------
1196 static void SetScope2DEnabled(bool enabled)
1197 {
1198 BaseContainer gameplaySettings = GetGame().GetGameUserSettings().GetModule("SCR_GameplaySettings");
1199 if (gameplaySettings)
1200 gameplaySettings.Set("m_b2DScopes", enabled);
1201 }
1202#endif
1203}
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
ArmaReforgerScripted GetGame()
Definition game.c:1398
SCR_HUDManagerComponent m_HUDManager
Definition game.c:39
int size
func On2DOpticsADSChange
func On2DOpticsIlluminationChange
SCR_EOpticsAngleUnits
Get all prefabs that have the spawner data
Widget m_wRoot
SCR_HelicopterControllerComponentClass gameplaySettings
bool m_bInADS
static bool StopAnimation(Widget w, typename typeName)
static WidgetAnimationOpacity Opacity(Widget widget, float targetValue, float speed, bool toggleVisibility=false)
Definition Color.c:13
Diagnostic and developer menu system.
Definition DiagMenu.c:18
Definition Math.c:13
static ref ScriptInvokerBase< On2DOpticsADSChange > s_On2DOpticADSChanged
void SetReticleOffset(float x, float y)
ResourceName m_sReticleGlowTexture
SizeLayoutWidget m_wSizeLayoutRear
const string WIDGET_IMAGE_COVER
void MoveScopeWidgets(float timeSlice)
Apply result movement to scope widgets.
const string WIDGET_IMAGE_VIGNETTE
const string WIDGET_IMAGE_PADDING_TOP
void Deactivate()
Stop any running animation for entering Scope and disable the layout after some delay.
const string WIDGET_IMAGE_RETICLE
const string WIDGET_OVERLAY_RETICLES
static float LayerDefaultPosition(float screenSize, float layerSize)
void UpdateCurrentFov(bool forceUpdate=false)
void SetupOpticImage()
Setup images and right texture sizing.
SCR_2DOpticsComponent m_Optic
const string WIDGET_IMAGE_PADDING_RIGHT
void GetOpticData()
Get optic data for quick retrieval later.
const string WIDGET_IMAGE_RETICLE_GLOW
void DeactivateWidget()
Open optics hud with animation delay.
void LowerBlurIntensity(float timeSlice, float speed)
void ChangeReticleTint(Color color, Color colorGlow)
SizeLayoutWidget m_wRearFillLeft
const string WIDGET_IMAGE_PADDING_LEFT
const string WIDGET_LAYOUT_REAR
override void DisplayStopDraw(IEntity owner)
SizeLayoutWidget m_wSizeLayoutObjective
void UpdateReticleSize()
Setup images and right texture sizing.
void OnADSChange(notnull SCR_2DOpticsComponent comp, bool inADS)
const string WIDGET_IMAGE_SCRATCHES
void MotionBlur(float posX, float posY)
const string WIDGET_IMAGE_PADDING_BOTTOM
void OnLayoutChanged(SCR_HUDLayout newLayout, SCR_HUDLayout oldLayout, SCR_HUDManagerComponent hudManager)
SizeLayoutWidget m_wFrontFillLeft
override void DisplayUpdate(IEntity owner, float timeSlice)
SizeLayoutWidget m_wFrontFillTop
void FindWidgets()
Find widget refences.
SizeLayoutWidget m_wRearFillTop
override void DisplayStartDraw(IEntity owner)
const string WIDGET_SIZE_OBJECTIVE
const string WIDGET_LAYOUT_FRONT
const string WIDGET_IMAGE_FILTER
void PlayEntryAnimation(float animationSpeed)
void UpdateScale(float reticleScale, float vignetteScale, float objectiveScale)
Update widget sizes according to the screen height and DPI scale.
const int COLOR_BLUE
Definition constants.c:23
const int COLOR_RED
Definition constants.c:21
const int COLOR_GREEN
Definition constants.c:22
const int COLOR_YELLOW_A
Definition constants.c:29
const int COLOR_YELLOW
Definition constants.c:24
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
ShapeFlags
Definition ShapeFlags.c:13
RespawnSystemComponentClass GameComponentClass vector vector rotation