private async UniTask <AnimationGroup> LoadClipsAsync(CameraControlMode cameraControlMode) { if (_asyncLoadInfo != null) { return(await ReturnExistingAsync()); } AsyncLoadInfo <AnimationGroup> info = null; lock (this) { if (_asyncLoadInfo == null) { info = new AsyncLoadInfo <AnimationGroup>(); _asyncLoadInfo = info; } } if (info == null) { return(await ReturnExistingAsync()); } var songResourceName = commonResourceProperties.cameraResourceName; if (string.IsNullOrWhiteSpace(songResourceName)) { info.Fail(); throw new FormatException("Song resource name is empty."); } var camAssetName = $"cam_{songResourceName}"; var camBundle = await bundleLoader.LoadFromRelativePathAsync($"{camAssetName}.imo.unity3d"); AnimationClip mainCamera; { var camAssetPath = $"assets/imas/resources/exclude/imo/camera/{songResourceName}/{camAssetName}_cam.imo.asset"; var mainCamData = camBundle.LoadAsset <CharacterImasMotionAsset>(camAssetPath); switch (cameraControlMode) { case CameraControlMode.Direct: mainCamera = CameraAnimation.CreateClipForCamera(mainCamData, camAssetName); break; case CameraControlMode.Indirect: mainCamera = CameraAnimation.CreateIndirectClip(mainCamData, camAssetName); break; default: throw new ArgumentOutOfRangeException(nameof(cameraControlMode), cameraControlMode, null); } } AnimationClip LoadAppealMotion(string postfix) { // For portrait variations: ".../{camAssetName}_tate_{postfix}.imo.asset" var assetPath = $"assets/imas/resources/exclude/imo/camera/{songResourceName}/{camAssetName}_{postfix}.imo.asset"; if (!camBundle.Contains(assetPath)) { return(null); } var motionData = camBundle.LoadAsset <CharacterImasMotionAsset>(assetPath); AnimationClip result; switch (cameraControlMode) { case CameraControlMode.Direct: result = CameraAnimation.CreateClipForCamera(motionData, $"{camAssetName}_{postfix}"); break; case CameraControlMode.Indirect: result = CameraAnimation.CreateIndirectClip(motionData, $"{camAssetName}_{postfix}"); break; default: throw new ArgumentOutOfRangeException(nameof(cameraControlMode), cameraControlMode, null); } return(result); } var specialAppeal = LoadAppealMotion("apg"); var anotherAppeal = LoadAppealMotion("apa"); var gorgeousAppeal = LoadAppealMotion("bpg"); var group = new AnimationGroup(mainCamera, specialAppeal, anotherAppeal, gorgeousAppeal); info.Success(group); return(group); }
private async UniTask <AnimationGroup> LoadClipsAsync() { if (_asyncLoadInfo != null) { return(await ReturnExistingAsync()); } AsyncLoadInfo <AnimationGroup> info = null; lock (this) { if (_asyncLoadInfo == null) { info = new AsyncLoadInfo <AnimationGroup>(); _asyncLoadInfo = info; } } if (info == null) { return(await ReturnExistingAsync()); } var songResourceName = commonResourceProperties.danceResourceName; if (string.IsNullOrWhiteSpace(songResourceName)) { info.Fail(); throw new FormatException("Song resource name is empty."); } if (placement.motionNumber < MltdSimulationConstants.MinDanceMotion || placement.motionNumber > MltdSimulationConstants.MaxDanceMotion) { info.Fail(); throw new FormatException($"Invalid motion number: {placement.motionNumber}, should be {MltdSimulationConstants.MinDanceMotion} to {MltdSimulationConstants.MaxDanceMotion}."); } if (placement.formationNumber < MltdSimulationConstants.MinDanceFormation || placement.motionNumber > MltdSimulationConstants.MaxDanceFormation) { info.Fail(); throw new FormatException($"Invalid formation number: {placement.motionNumber}, should be {MltdSimulationConstants.MinDanceFormation} to {MltdSimulationConstants.MaxDanceFormation}."); } var danceAssetName = $"dan_{songResourceName}_{placement.motionNumber:00}"; if (!DanceAssetNameRegex.IsMatch(danceAssetName)) { info.Fail(); throw new FormatException($"\"{danceAssetName}\" is not a valid dance asset name."); } var mainDanceBundle = await bundleLoader.LoadFromRelativePathAsync($"{danceAssetName}.imo.unity3d"); AssetBundle appealBundle = null; bool? appealBundleFound = null; AnimationClip mainDance; { var assetPath = $"assets/imas/resources/exclude/imo/dance/{songResourceName}/{danceAssetName}_dan.imo.asset"; var motionData = mainDanceBundle.LoadAsset <CharacterImasMotionAsset>(assetPath); mainDance = await DanceAnimation.CreateAsync(motionData, danceAssetName); } async UniTask <AnimationClip> LoadAppealMotionAsync(string postfix) { var appealAssetName = $"dan_{songResourceName}_{placement.formationNumber:00}"; AnimationClip result; var assetPath = $"assets/imas/resources/exclude/imo/dance/{songResourceName}/{appealAssetName}_{postfix}.imo.asset"; if (mainDanceBundle.Contains(assetPath)) { var motionData = mainDanceBundle.LoadAsset <CharacterImasMotionAsset>(assetPath); result = await DanceAnimation.CreateAsync(motionData, $"{appealAssetName}_{postfix}"); } else { if (appealBundleFound.HasValue) { if (!appealBundleFound.Value) { return(null); } } else { bool found; (appealBundle, found) = await TryLoadExternalAppealBundleAsync(); appealBundleFound = found; } if (appealBundle != null && appealBundle.Contains(assetPath)) { var motionData = appealBundle.LoadAsset <CharacterImasMotionAsset>(assetPath); result = await DanceAnimation.CreateAsync(motionData, $"{appealAssetName}_{postfix}"); } else { result = null; } } return(result); } var specialAppeal = await LoadAppealMotionAsync("apg"); var anotherAppeal = await LoadAppealMotionAsync("apa"); var gorgeousAppeal = await LoadAppealMotionAsync("bpg"); var animationGroup = new AnimationGroup(mainDance, specialAppeal, anotherAppeal, gorgeousAppeal); info.Success(animationGroup); return(animationGroup); }