예제 #1
0
        public SpawnedAvatar SpawnAvatar(LoadedAvatar avatar, IAvatarInput input, Transform parent = null)
        {
            if (avatar == null)
            {
                throw new ArgumentNullException(nameof(avatar));
            }
            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }

            if (parent)
            {
                _logger.Info($"Spawning avatar '{avatar.descriptor.name}' into '{parent.name}'");
            }
            else
            {
                _logger.Info($"Spawning avatar '{avatar.descriptor.name}'");
            }

            DiContainer subContainer = new DiContainer(_container);

            subContainer.Bind <LoadedAvatar>().FromInstance(avatar);
            subContainer.Bind <IAvatarInput>().FromInstance(input);

            GameObject avatarInstance = subContainer.InstantiatePrefab(avatar.prefab, parent);

            return(subContainer.InstantiateComponent <SpawnedAvatar>(avatarInstance));
        }
예제 #2
0
        public SpawnedAvatar(LoadedAvatar avatar, AvatarInput input)
        {
            customAvatar = avatar ?? throw new ArgumentNullException(nameof(avatar));

            _gameObject            = Object.Instantiate(customAvatar.gameObject);
            _firstPersonExclusions = _gameObject.GetComponentsInChildren <FirstPersonExclusion>();

            eventsPlayer = _gameObject.AddComponent <AvatarEventsPlayer>();
            tracking     = _gameObject.AddComponent <AvatarTracking>();

            tracking.customAvatar = customAvatar;
            tracking.input        = input;

            if (customAvatar.isIKAvatar)
            {
                AvatarIK ik = _gameObject.AddComponent <AvatarIK>();

                ik.input = input;
            }

            if (customAvatar.supportsFingerTracking)
            {
                _gameObject.AddComponent <AvatarFingerTracking>();
            }

            Object.DontDestroyOnLoad(_gameObject);
        }
예제 #3
0
 public void Inject(ILoggerProvider loggerProvider, LoadedAvatar avatar, ScoreController scoreController, BeatmapObjectCallbackController beatmapObjectCallbackController, ILevelEndActions levelEndActions)
 {
     _logger          = loggerProvider.CreateLogger <AvatarGameplayEventsPlayer>(avatar.descriptor.name);
     _scoreController = scoreController;
     _levelEndActions = levelEndActions;
     _beatmapObjectCallbackController = beatmapObjectCallbackController;
 }
예제 #4
0
        public void Inject(ILoggerProvider loggerProvider, LoadedAvatar avatar, ScoreController scoreController, BeatmapObjectCallbackController beatmapObjectCallbackController, ILevelEndActions levelEndActions)
        {
            _logger          = loggerProvider.CreateLogger <AvatarGameplayEventsPlayer>(avatar.descriptor.name);
            _scoreController = scoreController;
            _levelEndActions = levelEndActions;
            _beatmapObjectCallbackController = beatmapObjectCallbackController;

            // unfortunately this is not bound through Zenject
            _sparkleEffectManager = FindObjectOfType <ObstacleSaberSparkleEffectManager>();
        }
예제 #5
0
        private void HandleSuccess(string fullPath, LoadedAvatar loadedAvatar)
        {
            _logger.Info($"Successfully loaded avatar '{loadedAvatar.descriptor.name}' by '{loadedAvatar.descriptor.author}' from '{fullPath}'");

            foreach (LoadHandlers handler in _handlers[fullPath])
            {
                handler.InvokeSuccess(loadedAvatar);
            }

            _handlers.Remove(fullPath);
        }
예제 #6
0
        public AvatarInfo(LoadedAvatar avatar)
        {
            name   = avatar.descriptor.name;
            author = avatar.descriptor.author;
            icon   = avatar.descriptor.cover ? avatar.descriptor.cover.texture : null;

            var fileInfo = new FileInfo(avatar.fullPath);

            fileName     = fileInfo.Name;
            fileSize     = fileInfo.Length;
            created      = fileInfo.CreationTimeUtc;
            lastModified = fileInfo.LastWriteTimeUtc;

            timestamp = DateTime.Now;
        }
예제 #7
0
        private void SwitchToAvatar(LoadedAvatar avatar)
        {
            if (currentlySpawnedAvatar && currentlySpawnedAvatar.avatar == avatar)
            {
                return;
            }
            if (avatar?.fullPath != _switchingToPath)
            {
                return;
            }

            if (avatar == null)
            {
                _logger.Info("No avatar selected");
                avatarChanged?.Invoke(null);
                _settings.previousAvatarPath = null;
                return;
            }

            var avatarInfo = new AvatarInfo(avatar);

            _settings.previousAvatarPath = avatarInfo.fileName;

            // cache avatar info since loading asset bundles is expensive
            if (_avatarInfos.ContainsKey(avatarInfo.fileName))
            {
                _avatarInfos[avatarInfo.fileName] = avatarInfo;
            }
            else
            {
                _avatarInfos.Add(avatarInfo.fileName, avatarInfo);
            }

            currentlySpawnedAvatar = _spawner.SpawnAvatar(avatar, _container.Instantiate <VRPlayerInput>(new object[] { avatar }));
            _currentAvatarSettings = _settings.GetAvatarSettings(avatar.fileName);

            ResizeCurrentAvatar();
            UpdateFirstPersonVisibility();
            UpdateLocomotionEnabled();

            avatarChanged?.Invoke(currentlySpawnedAvatar);
        }
예제 #8
0
 public void InvokeSuccess(LoadedAvatar value)
 {
     success?.Invoke(value);
     complete?.Invoke();
 }
        internal void Construct(string fullPath, ILogger <AvatarPrefab> logger, IKHelper ikHelper, DiContainer container)
        {
            this.fullPath = fullPath ?? throw new ArgumentNullException(nameof(fullPath));
            descriptor    = GetComponent <AvatarDescriptor>() ?? throw new AvatarLoadException($"Avatar at '{fullPath}' does not have an AvatarDescriptor");

            fileName = Path.GetFileName(fullPath);

            _logger      = logger;
            _logger.name = descriptor.name;

#pragma warning disable CS0618
            VRIKManager vrikManager = GetComponentInChildren <VRIKManager>();
            IKManager   ikManager   = GetComponentInChildren <IKManager>();
#pragma warning restore CS0618

            // migrate IKManager/IKManagerAdvanced to VRIKManager
            if (ikManager)
            {
                if (!vrikManager)
                {
                    vrikManager = container.InstantiateComponent <VRIKManager>(gameObject);
                }

                _logger.Warning("IKManager and IKManagerAdvanced are deprecated; please migrate to VRIKManager");

                ApplyIKManagerFields(vrikManager, ikManager);
                Destroy(ikManager);
            }

            if (vrikManager)
            {
                if (!vrikManager.areReferencesFilled)
                {
                    _logger.Warning($"References are not filled on '{vrikManager.name}'; detecting references automatically");
                    vrikManager.AutoDetectReferences();
                }
            }

            // remove any existing VRIK instances
            foreach (VRIK existingVrik in GetComponentsInChildren <VRIK>())
            {
                _logger.Warning($"Found VRIK on '{existingVrik.name}'; manually adding VRIK to an avatar is no longer needed, please remove it");

                if (existingVrik && vrikManager && existingVrik.references.isFilled && !vrikManager.areReferencesFilled)
                {
                    _logger.Warning($"Copying references from VRIK on '{existingVrik.name}'; this is deprecated behaviour and will be removed in a future release");
                    CopyReferencesFromExistingVrik(vrikManager, existingVrik.references);
                }

                Destroy(existingVrik);
            }

            if (vrikManager)
            {
                ikHelper.CreateOffsetTargetsIfMissing(vrikManager, transform);
            }

            head      = transform.Find("Head");
            leftHand  = transform.Find("LeftHand");
            rightHand = transform.Find("RightHand");
            pelvis    = transform.Find("Pelvis");
            leftLeg   = transform.Find("LeftLeg");
            rightLeg  = transform.Find("RightLeg");

            if (vrikManager)
            {
                if (vrikManager.references_root != vrikManager.transform)
                {
                    _logger.Warning("VRIKManager is not on the root reference transform; this may cause unexpected issues");
                }

                CheckTargetWeight("Left Arm", leftHand, vrikManager.solver_leftArm_positionWeight, vrikManager.solver_leftArm_rotationWeight);
                CheckTargetWeight("Right Arm", rightHand, vrikManager.solver_rightArm_positionWeight, vrikManager.solver_rightArm_rotationWeight);
                CheckTargetWeight("Pelvis", pelvis, vrikManager.solver_spine_pelvisPositionWeight, vrikManager.solver_spine_pelvisRotationWeight);
                CheckTargetWeight("Left Leg", leftLeg, vrikManager.solver_leftLeg_positionWeight, vrikManager.solver_leftLeg_rotationWeight);
                CheckTargetWeight("Right Leg", rightLeg, vrikManager.solver_rightLeg_positionWeight, vrikManager.solver_rightLeg_rotationWeight);

                FixTrackingReferences(vrikManager);
            }

            if (transform.localPosition.sqrMagnitude > 0)
            {
                _logger.Warning("Avatar root position is not at origin; this may cause unexpected issues");
            }

            var poseManager = GetComponentInChildren <PoseManager>();

            isIKAvatar             = vrikManager;
            supportsFingerTracking = poseManager && poseManager.isValid;

            eyeHeight = GetEyeHeight();
            armSpan   = GetArmSpan(vrikManager);

#pragma warning disable CS0612, CS0618
            loadedAvatar = new LoadedAvatar(this);
#pragma warning restore CS0612, CS0618
        }
예제 #10
0
        // TODO from stream/memory
        /// <summary>
        /// Load an avatar from a file.
        /// </summary>
        /// <param name="path">Path to the .avatar file</param>
        /// <param name="success">Action to call if the avatar is loaded successfully</param>
        /// <param name="error">Action to call if the avatar isn't loaded successfully</param>
        /// <returns><see cref="IEnumerator{AsyncOperation}"/></returns>
        public IEnumerator <AsyncOperation> FromFileCoroutine(string path, Action <LoadedAvatar> success = null, Action <Exception> error = null)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            string fullPath = Path.GetFullPath(path);

            if (!File.Exists(fullPath))
            {
                throw new IOException($"File '{fullPath}' does not exist");
            }

            // already loading, just add handlers
            if (_handlers.ContainsKey(fullPath))
            {
                _handlers[fullPath].Add(new LoadHandlers(success, error));

                yield break;
            }

            _handlers.Add(fullPath, new List <LoadHandlers> {
                new LoadHandlers(success, error)
            });

            _logger.Info($"Loading avatar from '{fullPath}'");

            AssetBundleCreateRequest assetBundleCreateRequest = AssetBundle.LoadFromFileAsync(fullPath);

            yield return(assetBundleCreateRequest);

            if (!assetBundleCreateRequest.isDone || !assetBundleCreateRequest.assetBundle)
            {
                var exception = new AvatarLoadException("Could not load asset bundle");

                _logger.Error($"Failed to load avatar at '{fullPath}'");
                _logger.Error(exception);

                foreach (LoadHandlers handler in _handlers[fullPath])
                {
                    handler.error?.Invoke(exception);
                }

                _handlers.Remove(fullPath);

                yield break;
            }

            AssetBundleRequest assetBundleRequest = assetBundleCreateRequest.assetBundle.LoadAssetWithSubAssetsAsync <GameObject>(kGameObjectName);

            yield return(assetBundleRequest);

            if (!assetBundleRequest.isDone || assetBundleRequest.asset == null)
            {
                assetBundleCreateRequest.assetBundle.Unload(true);

                var exception = new AvatarLoadException("Could not load asset from asset bundle");

                _logger.Error($"Failed to load avatar at '{fullPath}'");
                _logger.Error(exception);

                foreach (LoadHandlers handler in _handlers[fullPath])
                {
                    handler.error?.Invoke(exception);
                }

                _handlers.Remove(fullPath);

                yield break;
            }

            assetBundleCreateRequest.assetBundle.Unload(false);

            try
            {
                var loadedAvatar = new LoadedAvatar(fullPath, (GameObject)assetBundleRequest.asset, _container.Resolve <ILoggerProvider>());

                _logger.Info($"Successfully loaded avatar '{loadedAvatar.descriptor.name}' from '{fullPath}'");

                foreach (LoadHandlers handler in _handlers[fullPath])
                {
                    handler.success?.Invoke(loadedAvatar);
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"Failed to load avatar at '{fullPath}'");
                _logger.Error(ex);

                foreach (LoadHandlers handler in _handlers[fullPath])
                {
                    handler.error?.Invoke(new AvatarLoadException("Failed to load avatar", ex));
                }
            }

            _handlers.Remove(fullPath);
        }