Exemplo n.º 1
0
        private static PosRot GetTrackerWorldPosRot(XRNodeState tracker)
        {
            Vector3    pos = new Vector3();
            Quaternion rot = new Quaternion();

            try
            {
                var notes = new List <XRNodeState>();
                InputTracking.GetNodeStates(notes);
                foreach (XRNodeState note in notes)
                {
                    if (note.uniqueID != tracker.uniqueID)
                    {
                        continue;
                    }
                    if (note.TryGetPosition(out pos) && note.TryGetRotation(out rot))
                    {
                        var roomCenter   = BeatSaberUtil.GetRoomCenter();
                        var roomRotation = BeatSaberUtil.GetRoomRotation();
                        pos  = roomRotation * pos;
                        pos += roomCenter;
                        rot  = roomRotation * rot;
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Log(e.Message + "\n" + e.StackTrace, Logger.LogLevel.Error);
            }
            return(new PosRot(pos, rot));
        }
Exemplo n.º 2
0
        private void SetCameraCullingMask(Camera camera)
        {
            Logger.Log("Adding third person culling mask to " + camera.name);

            camera.cullingMask &= ~(1 << AvatarLayers.OnlyInThirdPerson);
            camera.cullingMask |= 1 << AvatarLayers.OnlyInFirstPerson;
        }
Exemplo n.º 3
0
        public static SpawnedAvatar SpawnAvatar(CustomAvatar customAvatar, IAvatarInput avatarInput)
        {
            if (customAvatar.GameObject == null)
            {
                Logger.Log("Can't spawn " + customAvatar.FullPath + " because it hasn't been loaded!");
                return(null);
            }

            var avatarGameObject = Object.Instantiate(customAvatar.GameObject);

            var behaviour = avatarGameObject.AddComponent <AvatarBehaviour>();

            behaviour.Init(avatarInput);

            avatarGameObject.AddComponent <AvatarEventsPlayer>();

            /* Don't have the patience to make this work rn
             *
             * var mainCamera = Camera.main;
             *
             * foreach (Camera cam in avatarGameObject.GetComponentsInChildren<Camera>())
             * {
             *      if(mainCamera)
             *      {
             *              var newCamObj = Object.Instantiate(mainCamera, cam.transform);
             *              newCamObj.tag = "Untagged";
             *              while (newCamObj.transform.childCount > 0) Object.DestroyImmediate(newCamObj.transform.GetChild(0).gameObject);
             *              Object.DestroyImmediate(newCamObj.GetComponent("CameraRenderCallbacksManager"));
             *              Object.DestroyImmediate(newCamObj.GetComponent("AudioListener"));
             *              Object.DestroyImmediate(newCamObj.GetComponent("MeshCollider"));
             *
             *              var newCam = newCamObj.GetComponent<Camera>();
             *              newCam.stereoTargetEye = StereoTargetEyeMask.None;
             *              newCam.cullingMask = cam.cullingMask;
             *
             *              var _liv = newCam.GetComponent<LIV.SDK.Unity.LIV>();
             *              if (_liv)
             *                      Object.Destroy(_liv);
             *
             *              var _screenCamera = new GameObject("Screen Camera").AddComponent<ScreenCameraBehaviour>();
             *
             *              if (_previewMaterial == null)
             *                      _previewMaterial = new Material(Shader.Find("Hidden/BlitCopyWithDepth"));
             *
             *
             *              cam.enabled = false;
             *      }
             * }
             */

            Object.DontDestroyOnLoad(avatarGameObject);

            var spawnedAvatar = new SpawnedAvatar(customAvatar, avatarGameObject);

            return(spawnedAvatar);
        }
 public void OnSceneTransitioned(Scene newScene)
 {
     Logger.Log("OnSceneTransitioned - " + newScene.name);
     if (newScene.name.Equals("GameCore"))
     {
         _currentSpawnedPlayerAvatar?.GameObject.GetComponentInChildren <AvatarEventsPlayer>()?.LevelStartedEvent();
     }
     else if (newScene.name.Equals("MenuCore"))
     {
         _currentSpawnedPlayerAvatar?.GameObject.GetComponentInChildren <AvatarEventsPlayer>()?.MenuEnteredEvent();
     }
 }
        TableCell TableView.IDataSource.CellForIdx(int row)
        {
            LevelListTableCell tableCell = _tableView.DequeueReusableCellForIdentifier("AvatarListCell") as LevelListTableCell;

            if (tableCell == null)
            {
                tableCell = Instantiate(_tableCellTemplate);

                // remove level type icons
                tableCell.transform.Find("LevelTypeIcon0").gameObject.SetActive(false);
                tableCell.transform.Find("LevelTypeIcon1").gameObject.SetActive(false);
                tableCell.transform.Find("LevelTypeIcon2").gameObject.SetActive(false);

                tableCell.reuseIdentifier = "AvatarListCell";
            }

            var cellInfo = new AvatarCellInfo();

            if (__AvatarLoadResults[row] != AvatarLoadResult.Completed)
            {
                cellInfo.name            = System.IO.Path.GetFileName(AvatarList[row].FullPath) + " failed to load";
                cellInfo.authorName      = "Make sure it's not a duplicate avatar.";
                cellInfo.rawImageTexture = null;
            }
            else
            {
                try
                {
                    cellInfo.name            = __AvatarNames[row];
                    cellInfo.authorName      = __AvatarAuthors[row];
                    cellInfo.rawImageTexture = __AvatarCovers[row] ? __AvatarCovers[row].texture : Texture2D.blackTexture;
                }
                catch (Exception e)
                {
                    cellInfo.name            = "If you see this yell at Assistant";
                    cellInfo.authorName      = "because she f****d up";
                    cellInfo.rawImageTexture = Texture2D.blackTexture;
                    Logger.Log(e.StackTrace, Logger.LogLevel.Error);
                }
            }

            tableCell.SetPrivateField("_beatmapCharacteristicAlphas", new float[0]);
            tableCell.SetPrivateField("_beatmapCharacteristicImages", new UnityEngine.UI.Image[0]);

            tableCell.GetPrivateField <TextMeshProUGUI>("_songNameText").text             = cellInfo.name;
            tableCell.GetPrivateField <TextMeshProUGUI>("_authorText").text               = cellInfo?.authorName;
            tableCell.GetPrivateField <UnityEngine.UI.RawImage>("_coverRawImage").texture = cellInfo.rawImageTexture;

            return(tableCell);
        }
Exemplo n.º 6
0
 private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
 {
     if (scene.name == "MenuCore")
     {
         if (Plugin.Instance.AvatarLoader.Avatars.Count == 0)
         {
             Logger.Log("[CustomAvatarsPlugin] No avatars found. Button not created.");
         }
         else
         {
             AddMainButton();
             Logger.Log("[CustomAvatarsPlugin] Creating Avatars Button.");
         }
     }
 }
Exemplo n.º 7
0
 public void OnUpdate()
 {
     if (Input.GetKeyDown(KeyCode.PageDown))
     {
         PlayerAvatarManager?.SwitchToNextAvatar();
     }
     else if (Input.GetKeyDown(KeyCode.PageUp))
     {
         PlayerAvatarManager?.SwitchToPreviousAvatar();
     }
     else if (Input.GetKeyDown(KeyCode.Home))
     {
         FirstPersonEnabled = !FirstPersonEnabled;
     }
     else if (Input.GetKeyDown(KeyCode.F6))
     {
         IsTrackerAsHand = !IsTrackerAsHand;
     }
     else if (Input.GetKeyDown(KeyCode.F5))
     {
         IsFullBodyTracking = !IsFullBodyTracking;
     }
     else if (Input.GetKeyDown(KeyCode.End))
     {
         int policy = (int)Plugin.Instance.AvatarTailor.ResizePolicy + 1;
         if (policy > 2)
         {
             policy = 0;
         }
         Plugin.Instance.AvatarTailor.ResizePolicy = (AvatarTailor.ResizePolicyType)policy;
         Logger.Log($"Set Resize Policy to {Plugin.Instance.AvatarTailor.ResizePolicy}");
         Plugin.Instance.PlayerAvatarManager.ResizePlayerAvatar();
     }
     else if (Input.GetKeyDown(KeyCode.Insert))
     {
         if (Plugin.Instance.AvatarTailor.FloorMovePolicy == AvatarTailor.FloorMovePolicyType.AllowMove)
         {
             Plugin.Instance.AvatarTailor.FloorMovePolicy = AvatarTailor.FloorMovePolicyType.NeverMove;
         }
         else
         {
             Plugin.Instance.AvatarTailor.FloorMovePolicy = AvatarTailor.FloorMovePolicyType.AllowMove;
         }
         Logger.Log($"Set Floor Move Policy to {Plugin.Instance.AvatarTailor.FloorMovePolicy}");
         Plugin.Instance.PlayerAvatarManager.ResizePlayerAvatar();
     }
 }
        public void SetVRTargets(Transform body, Transform head, Transform leftHand, Transform rightHand)
        {
            if (!(body && head && leftHand && rightHand))
            {
                Logger.Log("Something went wrong - IK Targets not found for player");
                Logger.Log("Body: " + body.name);
                Logger.Log("HeadTarget: " + head.name);
                Logger.Log("LeftHandTarget: " + leftHand.name);
                Logger.Log("RightHandTarget: " + rightHand.name);
                isValid = false;
                return;
            }

            _playerBody      = body;
            _playerHead      = head;
            _playerLeftHand  = leftHand;
            _playerRightHand = rightHand;
        }
 public void OnFirstPersonEnabledChanged(bool firstPersonEnabled)
 {
     try
     {
         Logger.Log("OnFirstPersonEnabledChanged - " + firstPersonEnabled);
         if (_deadSwitch)
         {
             return;
         }
         for (var i = 0; i < Exclude.Length; i++)
         {
             var excludeObject = Exclude[i];
             excludeObject.layer = AvatarLayers.OnlyInThirdPerson;
         }
     }
     catch (System.Exception e)
     {
         Logger.Log(e.StackTrace);
     }
 }
Exemplo n.º 10
0
        private void AvatarsLoaded(IReadOnlyList <CustomAvatar> loadedAvatars)
        {
            if (loadedAvatars.Count == 0)
            {
                Logger.Log("No custom avatars found in path " + Path.GetFullPath(CustomAvatarsPath));
                return;
            }

            var previousAvatarPath = PlayerPrefs.GetString(PreviousAvatarKey, null);

            if (!File.Exists(previousAvatarPath))
            {
                previousAvatarPath = AvatarLoader.Avatars[0].FullPath;
            }

            var previousAvatar = AvatarLoader.Avatars.FirstOrDefault(x => x.FullPath == previousAvatarPath);

            PlayerAvatarManager = new PlayerAvatarManager(AvatarLoader, AvatarTailor, previousAvatar);
            PlayerAvatarManager.AvatarChanged += PlayerAvatarManagerOnAvatarChanged;
            IsFullBodyTracking = true;
        }
        public void Init(GameObject avatarMirror)
        {
            Logger.Log("Begin Mirror Init");
            _avatarMirror = avatarMirror;
            var _VRIK = _avatarMirror.GetComponentsInChildren <AvatarScriptPack.VRIK>().FirstOrDefault();

            Logger.Log("Obtaining IK Targets for Mirror");
            _head      = _avatarMirror.transform.Find("Head/HeadTarget").transform;
            _leftHand  = _avatarMirror.transform.Find("LeftHand/LeftHandTarget").transform;
            _rightHand = _avatarMirror.transform.Find("RightHand/RightHandTarget").transform;

            if (!(_head && _leftHand && _rightHand))
            {
                Logger.Log("Something went wrong - IK Targets not found for mirror");
                isValid = false;
            }

            Logger.Log("Setting IK Targets for mirror");
            _VRIK.solver.spine.headTarget = _head.transform;
            _VRIK.solver.leftArm.target   = _leftHand.transform;
            _VRIK.solver.rightArm.target  = _rightHand.transform;
        }
        private void CustomAvatarLoaded(CustomAvatar loadedAvatar, AvatarLoadResult result)
        {
            if (result != AvatarLoadResult.Completed)
            {
                Logger.Log("Avatar " + loadedAvatar.FullPath + " failed to load");
                return;
            }

            Logger.Log("Loaded avatar " + loadedAvatar.Name + " by " + loadedAvatar.AuthorName);

            if (_currentSpawnedPlayerAvatar?.GameObject != null)
            {
                Object.Destroy(_currentSpawnedPlayerAvatar.GameObject);
            }

            _currentSpawnedPlayerAvatar = AvatarSpawner.SpawnAvatar(loadedAvatar, _playerAvatarInput);

            AvatarChanged?.Invoke(loadedAvatar);

            _avatarTailor.OnAvatarLoaded(_currentSpawnedPlayerAvatar);
            ResizePlayerAvatar();
            OnFirstPersonEnabledChanged(Plugin.Instance.FirstPersonEnabled);
        }
        private void LateUpdate()
        {
            try
            {
                var headPosRot  = _avatarInput.HeadPosRot;
                var leftPosRot  = _avatarInput.LeftPosRot;
                var rightPosRot = _avatarInput.RightPosRot;

                _head.position = headPosRot.Position;
                _head.rotation = headPosRot.Rotation;

                _leftHand.position = leftPosRot.Position;
                _leftHand.rotation = leftPosRot.Rotation;

                _rightHand.position = rightPosRot.Position;
                _rightHand.rotation = rightPosRot.Rotation;

                if (_leftLeg != null && _rightLeg != null && _avatarInput is IAvatarFullBodyInput)
                {
                    var _fbinput       = _avatarInput as IAvatarFullBodyInput;
                    var leftLegPosRot  = _fbinput.LeftLegPosRot;
                    var rightLegPosRot = _fbinput.RightLegPosRot;
                    _prevLeftLegPos   = Vector3.Lerp(_prevLeftLegPos, leftLegPosRot.Position, 15 * Time.deltaTime);
                    _prevLeftLegRot   = Quaternion.Slerp(_prevLeftLegRot, leftLegPosRot.Rotation, 10 * Time.deltaTime);
                    _leftLeg.position = _prevLeftLegPos;
                    _leftLeg.rotation = _prevLeftLegRot;

                    _prevRightLegPos   = Vector3.Lerp(_prevRightLegPos, rightLegPosRot.Position, 15 * Time.deltaTime);
                    _prevRightLegRot   = Quaternion.Slerp(_prevRightLegRot, rightLegPosRot.Rotation, 10 * Time.deltaTime);
                    _rightLeg.position = _prevRightLegPos;
                    _rightLeg.rotation = _prevRightLegRot;
                }

                if (_pelvis != null && _avatarInput is IAvatarFullBodyInput)
                {
                    var _fbinput     = _avatarInput as IAvatarFullBodyInput;
                    var pelvisPosRot = _fbinput.PelvisPosRot;

                    _prevPelvisPos   = Vector3.Lerp(_prevPelvisPos, pelvisPosRot.Position, 17 * Time.deltaTime);
                    _prevPelvisRot   = Quaternion.Slerp(_prevPelvisRot, pelvisPosRot.Rotation, 13 * Time.deltaTime);
                    _pelvis.position = _prevPelvisPos;
                    _pelvis.rotation = _prevPelvisRot;
                }

                var vrPlatformHelper = PersistentSingleton <VRPlatformHelper> .instance;

                vrPlatformHelper.AdjustPlatformSpecificControllerTransform(_leftHand);
                vrPlatformHelper.AdjustPlatformSpecificControllerTransform(_rightHand);

                if (_body == null)
                {
                    return;
                }
                _body.position = _head.position - (_head.transform.up * 0.1f);

                var vel = new Vector3(_body.transform.localPosition.x - _prevBodyPos.x, 0.0f,
                                      _body.localPosition.z - _prevBodyPos.z);

                var rot      = Quaternion.Euler(0.0f, _head.localEulerAngles.y, 0.0f);
                var tiltAxis = Vector3.Cross(gameObject.transform.up, vel);
                _body.localRotation = Quaternion.Lerp(_body.localRotation,
                                                      Quaternion.AngleAxis(vel.magnitude * 1250.0f, tiltAxis) * rot,
                                                      Time.deltaTime * 10.0f);

                _prevBodyPos = _body.transform.localPosition;
            } catch (Exception e)
            {
                Logger.Log($"{e.Message}\n{e.StackTrace}", Logger.LogLevel.Error);
            }
        }
        public void LoadAllAvatars()
        {
            int _AvatarIndex = 0;

            __AvatarPrefabs     = new GameObject[AvatarList.Count()];
            __AvatarNames       = new string[AvatarList.Count()];
            __AvatarAuthors     = new string[AvatarList.Count()];
            __AvatarPaths       = new string[AvatarList.Count()];
            __AvatarCovers      = new Sprite[AvatarList.Count()];
            __AvatarLoadResults = new AvatarLoadResult[AvatarList.Count()];

            for (int i = 0; i < AvatarList.Count(); i++)
            {
                _AvatarIndex = i;
                var avatar = AvatarList[_AvatarIndex];
                try
                {
#if DEBUG
                    Logger.Log("AddToArray -> " + _AvatarIndex);
#endif
                    avatar.Load(AddToArray);
#if DEBUG
                    Logger.Log("AddToArray => " + _AvatarIndex + " (" + Plugin.Instance.AvatarLoader.IndexOf(avatar) + ") | " + avatar.FullPath);
#endif
                }
                catch (Exception e)
                {
#if DEBUG
                    Logger.Log(_AvatarIndex + " | " + e);
#endif
                }
            }

            void AddToArray(CustomAvatar avatar, AvatarLoadResult _loadResult)
            {
#if DEBUG
                Logger.Log("AddToArray == " + AvatarLoadResult.Completed);
#endif
                if (_loadResult != AvatarLoadResult.Completed)
                {
                    Logger.Log("Avatar " + avatar.FullPath + " failed to load");
                    return;
                }
                AvatarIndex = Plugin.Instance.AvatarLoader.IndexOf(avatar);

                __AvatarNames[AvatarIndex]       = avatar.Name;
                __AvatarAuthors[AvatarIndex]     = avatar.AuthorName;
                __AvatarCovers[AvatarIndex]      = avatar.CoverImage;
                __AvatarPaths[AvatarIndex]       = avatar.FullPath;
                __AvatarPrefabs[AvatarIndex]     = avatar.GameObject;
                __AvatarLoadResults[AvatarIndex] = _loadResult;

                _loadedCount++;
#if DEBUG
                Logger.Log("(" + _loadedCount + "/" + ((int)AvatarList.Count()) + ") #" + AvatarIndex);
#endif
                //if (_loadedCount == (AvatarList.Count()))
                if (true)
                {
                    _tableView.ReloadData();
                    PreviewCurrent();
                }
            }
        }
        private void FirstActivation()
        {
            RectTransform containerRect = new GameObject("AvatarSettingsContainer", typeof(RectTransform)).transform as RectTransform;

            containerRect.SetParent(rectTransform, false);
            containerRect.anchorMin = new Vector2(0.05f, 0.0f);
            containerRect.anchorMax = new Vector2(0.95f, 1.0f);
            containerRect.sizeDelta = new Vector2(0, 0);

            SubMenu container = new SubMenu(containerRect);
            List <ListViewController> loadedSettings = new List <ListViewController>();

            System.Action <RectTransform, float, float, float, float, float, float> relative_layout =
                (RectTransform rt, float x, float y, float w, float h, float pivotx, float pivoty) =>
            {
                rt.anchorMin        = new Vector2(x, y);
                rt.anchorMax        = new Vector2(x + w, y + h);
                rt.pivot            = new Vector2(pivotx, pivoty);
                rt.sizeDelta        = Vector2.zero;
                rt.anchoredPosition = Vector2.zero;
            };

            gameObject.SetActive(false);

            TextMeshProUGUI text = BeatSaberUI.CreateText(containerRect, "AVATAR SETTINGS (Klouder is cute)", Vector2.zero);

            text.fontSize  = 6.0f;
            text.alignment = TextAlignmentOptions.Center;
            relative_layout(text.rectTransform, 0f, 0.85f, 1f, 0.166f, 0.5f, 1f);

            var boolFirstPerson = container.AddList("Visible In First Person View", new float[] { 0, 1 });

            boolFirstPerson.applyImmediately = true;
            relative_layout(boolFirstPerson.transform as RectTransform, 0, 0.66f, 1, 0.166f, 0, 1f);
            BeatSaberUI.AddHintText(boolFirstPerson.transform as RectTransform, "Allows you to see the avatar inside of VR");

            var listResizePolicy = container.AddList("Resize Avatars To Player's", new float[] { 0, 1, 2 });

            listResizePolicy.applyImmediately = true;
            relative_layout(listResizePolicy.transform as RectTransform, 0, 0.55f, 1, 0.166f, 0, 1f);
            BeatSaberUI.AddHintText(listResizePolicy.transform as RectTransform, "Use 'Arms Length' to resize the avatar based on your proportions, 'Height' to resize based on your height, and 'Never' to not resize");

            var boolFloorMovePolicy = container.AddList("Floor Height Adjust", new float[] { 0, 1 });

            boolFloorMovePolicy.applyImmediately = true;
            relative_layout(boolFloorMovePolicy.transform as RectTransform, 0, 0.44f, 1, 0.166f, 0, 1f);
            BeatSaberUI.AddHintText(boolFloorMovePolicy.transform as RectTransform, "Move the floor to compensate for height when using 'Arms Length' resize, requires CustomPlatforms");

            var labelMeasure = BeatSaberUI.CreateText(containerRect, $"Hand To Hand Length = {Mathf.Ceil(Plugin.Instance.AvatarTailor.PlayerArmLength * 100.0f) / 100.0f}", Vector2.zero);

            relative_layout(labelMeasure.transform as RectTransform, 0f, 0.18f, 0.5f, 0.11f, 0, .5f);
            BeatSaberUI.AddHintText(labelMeasure.transform as RectTransform, "Value used for 'Arms Length' resize, press on the 'MEASURE!' button and T-Pose");
            labelMeasure.fontSize  = 5f;
            labelMeasure.alignment = TextAlignmentOptions.MidlineLeft;

            gameObject.SetActive(true);

            var buttonMeasure = BeatSaberUI.CreateUIButton(containerRect, "QuitButton", () =>
            {
                labelMeasure.text = "Measuring ...";
                Plugin.Instance.AvatarTailor.MeasurePlayerArmLength((value) =>
                {
                    labelMeasure.text = $"Measuring ... {Mathf.Ceil(value * 100.0f) / 100.0f}";
                },
                                                                    (result) =>
                {
                    labelMeasure.text = $"Hand To Hand Length = {Mathf.Ceil(result * 100.0f) / 100.0f}";
                    if (Plugin.Instance.AvatarTailor.ResizePolicy == AvatarTailor.ResizePolicyType.AlignArmLength)
                    {
                        Plugin.Instance.PlayerAvatarManager.ResizePlayerAvatar();
                    }
                });
            }, "Measure!");

            relative_layout(buttonMeasure.transform as RectTransform, 0.65f, 0.18f, 0.35f, 0.11f, .5f, .5f);
            BeatSaberUI.AddHintText(buttonMeasure.transform as RectTransform, "Press this and T-Pose to measure your arms, needed to use 'Arms Length' resize");

            boolFirstPerson.GetTextForValue = (value) => (value != 0f) ? "ON" : "OFF";
            boolFirstPerson.GetValue        = () => Plugin.Instance.FirstPersonEnabled ? 1f : 0f;
            boolFirstPerson.SetValue        = (value) => Plugin.Instance.FirstPersonEnabled = value != 0f;
            boolFirstPerson.Init();
            loadedSettings.Add(boolFirstPerson);

            listResizePolicy.GetTextForValue = (value) => new string[] { "Arms Length", "Height", "Never" }[(int)value];
            listResizePolicy.GetValue        = () => (int)Plugin.Instance.AvatarTailor.ResizePolicy;
            listResizePolicy.SetValue        = (value) =>
            {
                Plugin.Instance.AvatarTailor.ResizePolicy = (AvatarTailor.ResizePolicyType)(int) value;
                Plugin.Instance.PlayerAvatarManager.ResizePlayerAvatar();
            };
            listResizePolicy.Init();
            loadedSettings.Add(listResizePolicy);

            boolFloorMovePolicy.GetTextForValue = (value) => (value != 0f) ? "ON" : "OFF";
            boolFloorMovePolicy.GetValue        = () => Plugin.Instance.AvatarTailor.FloorMovePolicy == AvatarTailor.FloorMovePolicyType.AllowMove ? 1f : 0f;
            boolFloorMovePolicy.SetValue        = (value) =>
            {
                Plugin.Instance.AvatarTailor.FloorMovePolicy = (value != 0f) ? AvatarTailor.FloorMovePolicyType.AllowMove : AvatarTailor.FloorMovePolicyType.NeverMove;
                Plugin.Instance.PlayerAvatarManager.ResizePlayerAvatar();
            };
            boolFloorMovePolicy.Init();
            loadedSettings.Add(boolFloorMovePolicy);

            foreach (ListViewController list in loadedSettings)
            {
                list.InvokePrivateMethod("OnDisable", new object[] { });
                list.InvokePrivateMethod("OnEnable", new object[] { });
                Logger.Log("Reset " + list.name);
            }
        }
        IEnumerator SpawnMirror()
        {
            yield return(new WaitUntil(() => Camera.main));

            mirrorCamObj = Instantiate(Camera.main.gameObject);

            mirrorCamObj.SetActive(false);
            mirrorCamObj.name             = "mirrorCamObj";
            mirrorCamObj.tag              = "Untagged";
            mirrorCamObj.transform.parent = null;

            while (mirrorCamObj.transform.childCount > 0)
            {
                DestroyImmediate(mirrorCamObj.transform.GetChild(0).gameObject);
            }
            DestroyImmediate(mirrorCamObj.GetComponent("CameraRenderCallbacksManager"));
            DestroyImmediate(mirrorCamObj.GetComponent("AudioListener"));
            DestroyImmediate(mirrorCamObj.GetComponent("MeshCollider"));

            _cam = mirrorCamObj.GetComponent <Camera>();
            _cam.stereoTargetEye  = StereoTargetEyeMask.None;
            _cam.enabled          = true;
            _cam.orthographic     = true;
            _cam.aspect           = 1.4f;
            _cam.orthographicSize = 1.25f;
            _cam.clearFlags       = CameraClearFlags.SolidColor;
            _cam.backgroundColor  = new Color(0, 0, 0, 5 / 255f);
            _cam.farClipPlane     = 10;

            int layer1     = 3;
            int layer2     = 4;
            int layer3     = 0;
            int layerMask1 = 1 << layer1;
            int layerMask2 = 1 << layer2;
            int layerMask3 = 1 << layer3;
            int finalMask  = layerMask1 | layerMask2 | layerMask3;


            _cam.cullingMask = finalMask;


            var _liv = _cam.GetComponent <LIV.SDK.Unity.LIV>();

            if (_liv)
            {
                Destroy(_liv);
            }

            mirrorCamObj.SetActive(true);

            mirrorCamObj.transform.position = new Vector3(0, 1.25f, 1.45f);
            mirrorCamObj.transform.rotation = Quaternion.Euler(0, 180, 0);


            _camRenderTexture                 = new RenderTexture(1, 1, 24);
            _camRenderTexture.width           = _cam.pixelWidth;
            _camRenderTexture.height          = _cam.pixelHeight;
            _camRenderTexture.useDynamicScale = false;
            _camRenderTexture.Create();

            _cam.targetTexture = _camRenderTexture;



            _mirrorMaterial = new Material(CutoutShader);
            _mirrorMaterial.SetTexture("_Tex", _camRenderTexture);
            _mirrorMaterial.SetFloat("_Cutout", .01f);

            _quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
            DontDestroyOnLoad(_quad);
            DestroyImmediate(_quad.GetComponent <Collider>());
            _quad.GetComponent <MeshRenderer>().material = _mirrorMaterial;
            _quad.transform.parent           = mirrorCamObj.transform;
            _quad.transform.localPosition    = new Vector3(0, 0, -.05f);
            _quad.transform.localEulerAngles = new Vector3(0, 0, 0);
            _quad.transform.localScale       = new Vector3(2.5f * _cam.aspect, 2.5f, 2.5f);
            Logger.Log($"Mirror Resolution: {_cam.pixelWidth}x{_cam.pixelHeight}");
        }