< Summary

Class:CharacterPreviewController
Assembly:AvatarEditorHUD
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/CharacterPreviewController.cs
Covered lines:37
Uncovered lines:38
Coverable lines:75
Total lines:198
Line coverage:49.3% (37 of 75)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
CharacterPreviewController()0%110100%
Awake()0%110100%
UpdateModel(...)0%330100%
OnDestroy()0%440100%
UpdateModelRoutine()0%660100%
TakeSnapshots(...)0%12300%
TakeSnapshots_Routine()0%30500%
Snapshot(...)0%2100%
SetFocus(...)0%110100%
SetFocus(...)0%4.543044.44%
CameraTransition()0%4.134080%
Rotate(...)0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/HUD/AvatarEditorHUD/Scripts/CharacterPreviewController.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Linq;
 5using System.Threading;
 6using AvatarSystem;
 7using Cysharp.Threading.Tasks;
 8using DCL;
 9using GPUSkinning;
 10using UnityEngine;
 11
 12public class CharacterPreviewController : MonoBehaviour
 13{
 14    private const int SNAPSHOT_BODY_WIDTH_RES = 256;
 15    private const int SNAPSHOT_BODY_HEIGHT_RES = 512;
 16
 17    private const int SNAPSHOT_FACE_256_WIDTH_RES = 256;
 18    private const int SNAPSHOT_FACE_256_HEIGHT_RES = 256;
 19
 20    private const int SUPERSAMPLING = 1;
 21    private const float CAMERA_TRANSITION_TIME = 0.5f;
 22
 23    public delegate void OnSnapshotsReady(Texture2D face256, Texture2D body);
 24
 25    public enum CameraFocus
 26    {
 27        DefaultEditing,
 28        FaceEditing,
 29        FaceSnapshot,
 30        BodySnapshot
 31    }
 32
 33    private System.Collections.Generic.Dictionary<CameraFocus, Transform> cameraFocusLookUp;
 34
 35    public new Camera camera;
 36
 37    public Transform defaultEditingTemplate;
 38    public Transform faceEditingTemplate;
 39
 40    public Transform faceSnapshotTemplate;
 41    public Transform bodySnapshotTemplate;
 42
 43    [SerializeField] private GameObject avatarContainer;
 44    private IAvatar avatar;
 4745    private readonly AvatarModel currentAvatarModel = new AvatarModel { wearables = new List<string>() };
 4746    private CancellationTokenSource loadingCts = new CancellationTokenSource();
 47
 48    private void Awake()
 49    {
 4650        cameraFocusLookUp = new Dictionary<CameraFocus, Transform>()
 51        {
 52            { CameraFocus.DefaultEditing, defaultEditingTemplate },
 53            { CameraFocus.FaceEditing, faceEditingTemplate },
 54            { CameraFocus.FaceSnapshot, faceSnapshotTemplate },
 55            { CameraFocus.BodySnapshot, bodySnapshotTemplate },
 56        };
 4657        avatar = new AvatarSystem.Avatar(
 58            new AvatarCurator(new WearableItemResolver()),
 59            new Loader(new WearableLoaderFactory(), avatarContainer, new AvatarMeshCombinerHelper()),
 60            avatarContainer.gameObject.GetComponentInChildren<IAnimator>(),
 61            new Visibility(),
 62            new NoLODs(),
 63            new SimpleGPUSkinning(),
 64            new GPUSkinningThrottler()
 65        );
 4666    }
 67
 68    public void UpdateModel(AvatarModel newModel, Action onDone)
 69    {
 12170        loadingCts?.Cancel();
 12171        loadingCts?.Dispose();
 12172        loadingCts = new CancellationTokenSource();
 12173        UpdateModelRoutine(newModel, onDone, loadingCts.Token);
 12174    }
 75
 76    private void OnDestroy()
 77    {
 4678        loadingCts?.Cancel();
 4679        loadingCts?.Dispose();
 4680        loadingCts = null;
 4681        avatar?.Dispose();
 4682    }
 83
 84    private async UniTaskVoid UpdateModelRoutine(AvatarModel newModel, Action onDone, CancellationToken ct)
 85    {
 12186        if (newModel.HaveSameWearablesAndColors(currentAvatarModel))
 87        {
 4588            onDone?.Invoke();
 4589            return;
 90        }
 91
 7692        currentAvatarModel.CopyFrom(newModel);
 7693        List<string> wearables = new List<string>(newModel.wearables);
 7694        wearables.Add(newModel.bodyShape);
 22895        await avatar.Load(wearables, new AvatarSettings
 96        {
 97            bodyshapeId = newModel.bodyShape,
 98            eyesColor = newModel.eyeColor,
 99            hairColor = newModel.hairColor,
 100            skinColor = newModel.skinColor
 101
 102        }, ct);
 103
 76104        onDone?.Invoke();
 121105    }
 106
 107    public void TakeSnapshots(OnSnapshotsReady onSuccess, Action onFailed)
 108    {
 0109        if (avatar.status != IAvatar.Status.Loaded)
 110        {
 0111            onFailed?.Invoke();
 0112            return;
 113        }
 114
 0115        StartCoroutine(TakeSnapshots_Routine(onSuccess));
 0116    }
 117
 118    private IEnumerator TakeSnapshots_Routine(OnSnapshotsReady callback)
 119    {
 0120        DCL.Environment.i.platform.cullingController.Stop();
 121
 0122        var current = camera.targetTexture;
 0123        camera.targetTexture = null;
 0124        var avatarAnimator = avatarContainer.gameObject.GetComponentInChildren<AvatarAnimatorLegacy>();
 125
 0126        SetFocus(CameraFocus.FaceSnapshot, false);
 0127        avatarAnimator.Reset();
 0128        yield return null;
 0129        Texture2D face256 = Snapshot(SNAPSHOT_FACE_256_WIDTH_RES, SNAPSHOT_FACE_256_HEIGHT_RES);
 130
 0131        SetFocus(CameraFocus.BodySnapshot, false);
 0132        avatarAnimator.Reset();
 0133        yield return null;
 0134        Texture2D body = Snapshot(SNAPSHOT_BODY_WIDTH_RES, SNAPSHOT_BODY_HEIGHT_RES);
 135
 0136        SetFocus(CameraFocus.DefaultEditing, false);
 137
 0138        camera.targetTexture = current;
 139
 0140        DCL.Environment.i.platform.cullingController.Start();
 0141        callback?.Invoke(face256, body);
 0142    }
 143
 144    private Texture2D Snapshot(int width, int height)
 145    {
 0146        RenderTexture rt = new RenderTexture(width * SUPERSAMPLING, height * SUPERSAMPLING, 32);
 0147        camera.targetTexture = rt;
 0148        Texture2D screenShot = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false);
 0149        camera.Render();
 0150        RenderTexture.active = rt;
 0151        screenShot.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
 0152        screenShot.Apply();
 153
 0154        return screenShot;
 155    }
 156
 157    private Coroutine cameraTransitionCoroutine;
 158
 90159    public void SetFocus(CameraFocus focus, bool useTransition = true) { SetFocus(cameraFocusLookUp[focus], useTransitio
 160
 161    private void SetFocus(Transform transform, bool useTransition = true)
 162    {
 45163        if (cameraTransitionCoroutine != null)
 164        {
 0165            StopCoroutine(cameraTransitionCoroutine);
 166        }
 167
 45168        if (useTransition)
 169        {
 45170            cameraTransitionCoroutine = StartCoroutine(CameraTransition(camera.transform.position, transform.position, c
 45171        }
 172        else
 173        {
 0174            var cameraTransform = camera.transform;
 0175            cameraTransform.position = transform.position;
 0176            cameraTransform.rotation = transform.rotation;
 177        }
 0178    }
 179
 180    private IEnumerator CameraTransition(Vector3 initPos, Vector3 endPos, Quaternion initRotation, Quaternion endRotatio
 181    {
 45182        var cameraTransform = camera.transform;
 45183        float currentTime = 0;
 184
 45185        float inverseTime = 1 / time;
 45186        while (currentTime < time)
 187        {
 45188            currentTime = Mathf.Clamp(currentTime + Time.deltaTime, 0, time);
 45189            cameraTransform.position = Vector3.Lerp(initPos, endPos, currentTime * inverseTime);
 45190            cameraTransform.rotation = Quaternion.Lerp(initRotation, endRotation, currentTime * inverseTime);
 45191            yield return null;
 192        }
 193
 0194        cameraTransitionCoroutine = null;
 0195    }
 196
 0197    public void Rotate(float rotationVelocity) { avatarContainer.transform.Rotate(Time.deltaTime * rotationVelocity * Ve
 198}