< Summary

Class:DCLFeatures.ScreencaptureCamera.CameraObject.ScreenRecorder
Assembly:ScreencaptureCamera
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLServices/ScreencaptureCamera/CameraObject/Scripts/ScreenRecorder.cs
Covered lines:0
Uncovered lines:56
Coverable lines:56
Total lines:141
Line coverage:0% (0 of 56)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:9
Method coverage:0% (0 of 9)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ScreenRecorder(...)0%2100%
CaptureScreenshot()0%42600%
CropTexture2D(...)0%2100%
ResizeTexture2D(...)0%2100%
CalculateCurrentScreenFrame()0%6200%
CalculateTargetScreenFrame(...)0%2100%
CalculateRoundRescaledScreenFrame(...)0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLServices/ScreencaptureCamera/CameraObject/Scripts/ScreenRecorder.cs

#LineLine coverage
 1using DCL;
 2using System;
 3using System.Collections;
 4using UnityEngine;
 5using Object = UnityEngine.Object;
 6
 7namespace DCLFeatures.ScreencaptureCamera.CameraObject
 8{
 9    public class ScreenRecorder
 10    {
 11        private const int TARGET_FRAME_WIDTH = 1920;
 12        private const int TARGET_FRAME_HEIGHT = 1080;
 13        private const float FRAME_SCALE = 0.87f; // Defines the scale of the frame in relation to the screen
 14
 15        private readonly float targetAspectRatio;
 16        private readonly RectTransform canvasRectTransform;
 17
 018        private readonly Texture2D screenshot = new (TARGET_FRAME_WIDTH, TARGET_FRAME_HEIGHT, TextureFormat.RGB24, false
 19
 20        private RenderTexture originalBaseTargetTexture;
 21
 22        private ScreenFrameData debugTargetScreenFrame;
 23
 024        public bool IsCapturing { get; private set; }
 25
 026        public ScreenRecorder(RectTransform canvasRectTransform)
 27        {
 028            targetAspectRatio = (float)TARGET_FRAME_WIDTH / TARGET_FRAME_HEIGHT;
 029            Debug.Assert(targetAspectRatio != 0, "Target aspect ratio cannot be null");
 30
 031            this.canvasRectTransform = canvasRectTransform;
 032        }
 33
 34        public virtual IEnumerator CaptureScreenshot(Action<Texture2D> onComplete)
 35        {
 036            IsCapturing = true;
 37
 038            yield return new WaitForEndOfFrame(); // for UI to appear on screenshot. Converting to UniTask didn't work :
 39
 040            ScreenFrameData currentScreenFrame = CalculateCurrentScreenFrame();
 041            (_, float targetRescale) = CalculateTargetScreenFrame(currentScreenFrame);
 042            int roundedUpscale = Mathf.CeilToInt(targetRescale);
 43
 44            // Hotfix for MacOS Desktop crashing on taking screenshot when Explore panel is open
 045            if (DataStore.i.exploreV2.isOpen.Get() && Application.platform == RuntimePlatform.OSXPlayer)
 046                roundedUpscale = 1;
 47
 048            ScreenFrameData rescaledScreenFrame = CalculateRoundRescaledScreenFrame(currentScreenFrame, roundedUpscale);
 49
 050            Texture2D screenshotTexture = ScreenCapture.CaptureScreenshotAsTexture(roundedUpscale); // upscaled Screen F
 051            Texture2D upscaledFrameTexture = CropTexture2D(screenshotTexture, rescaledScreenFrame.CalculateFrameCorners(
 052            ResizeTexture2D(upscaledFrameTexture);
 53
 054            onComplete?.Invoke(screenshot);
 55
 056            Object.Destroy(screenshotTexture);
 057            Object.Destroy(upscaledFrameTexture);
 58
 059            IsCapturing = false;
 060        }
 61
 62        private static Texture2D CropTexture2D(Texture2D texture, Vector2Int startCorner, int width, int height)
 63        {
 064            Color[] pixels = texture.GetPixels(startCorner.x, startCorner.y, width, height);
 65
 066            var result = new Texture2D(width, height, TextureFormat.RGB24, false);
 067            result.SetPixels(pixels);
 068            result.Apply();
 69
 070            return result;
 71        }
 72
 73        private void ResizeTexture2D(Texture originalTexture)
 74        {
 075            var renderTexture = RenderTexture.GetTemporary(TARGET_FRAME_WIDTH, TARGET_FRAME_HEIGHT, 0);
 076            RenderTexture.active = renderTexture;
 77
 78            // Copy and scale the original texture into the RenderTexture
 079            Graphics.Blit(originalTexture, renderTexture);
 80
 81            // Read the pixel data from the RenderTexture into the Texture2D
 082            screenshot.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
 083            screenshot.Apply();
 84
 085            RenderTexture.active = null;
 086            RenderTexture.ReleaseTemporary(renderTexture);
 087        }
 88
 89        private ScreenFrameData CalculateCurrentScreenFrame()
 90        {
 091            var screenFrameData = new ScreenFrameData
 92            {
 93                ScreenWidth = canvasRectTransform.rect.width * canvasRectTransform.lossyScale.x,
 94                ScreenHeight = canvasRectTransform.rect.height * canvasRectTransform.lossyScale.y,
 95            };
 96
 97            // Adjust current by smallest side
 098            if (screenFrameData.ScreenAspectRatio > targetAspectRatio) // Height is the limiting dimension, so scaling w
 99            {
 0100                screenFrameData.FrameHeight = screenFrameData.ScreenHeight * FRAME_SCALE;
 0101                screenFrameData.FrameWidth = screenFrameData.FrameHeight * targetAspectRatio;
 102            }
 103            else // Width is the limiting dimension, so scaling height based on it
 104            {
 0105                screenFrameData.FrameWidth = screenFrameData.ScreenWidth * FRAME_SCALE;
 0106                screenFrameData.FrameHeight = screenFrameData.FrameWidth / targetAspectRatio;
 107            }
 108
 0109            return screenFrameData;
 110        }
 111
 112        private static (ScreenFrameData data, float targetRescale) CalculateTargetScreenFrame(ScreenFrameData currentScr
 113        {
 0114            var screenFrameData = new ScreenFrameData();
 115
 0116            float upscaleFrameWidth = TARGET_FRAME_WIDTH / currentScreenFrameData.FrameWidth;
 0117            float upscaleFrameHeight = TARGET_FRAME_HEIGHT / currentScreenFrameData.FrameHeight;
 0118            Debug.Assert(Math.Abs(upscaleFrameWidth - upscaleFrameHeight) < 0.01f, "Screenshot upscale factors should be
 119
 0120            float targetRescale = upscaleFrameWidth;
 121
 0122            screenFrameData.ScreenWidth = currentScreenFrameData.ScreenWidth * upscaleFrameWidth;
 0123            screenFrameData.ScreenHeight = currentScreenFrameData.ScreenHeight * upscaleFrameWidth;
 0124            screenFrameData.FrameWidth = currentScreenFrameData.FrameWidth * upscaleFrameWidth;
 0125            screenFrameData.FrameHeight = currentScreenFrameData.FrameHeight * upscaleFrameWidth;
 0126            Debug.Assert(Math.Abs(screenFrameData.FrameWidth - TARGET_FRAME_WIDTH) < 0.1f, "Calculated screenshot width 
 0127            Debug.Assert(Math.Abs(screenFrameData.FrameHeight - TARGET_FRAME_HEIGHT) < 0.1f, "Calculated screenshot heig
 128
 0129            return (screenFrameData, targetRescale);
 130        }
 131
 132        private static ScreenFrameData CalculateRoundRescaledScreenFrame(ScreenFrameData rescalingScreenFrame, int round
 0133            new ()
 134            {
 135                FrameWidth = rescalingScreenFrame.FrameWidth * roundedRescaleFactor,
 136                FrameHeight = rescalingScreenFrame.FrameHeight * roundedRescaleFactor,
 137                ScreenWidth = rescalingScreenFrame.ScreenWidth * roundedRescaleFactor,
 138                ScreenHeight = rescalingScreenFrame.ScreenHeight * roundedRescaleFactor,
 139            };
 140    }
 141}