void Awake() { foreach (SpritePair pair in sprites) { if (spriteObjects.ContainsKey(pair.boneName)) { throw new ArgumentException("There were duplicate keys in the sprite array. (Game object " + gameObject.name + ")"); } spriteObjects.Add(pair.boneName, pair.spriteHolder); } List <string> skeletonNames; switch (skeletonType) { case SkeletonType.Humanoid: skeletonNames = HumanoidSkeleton.getBoneNames(); break; default: skeletonNames = null; break; } List <string> keyNames = new List <string>(spriteObjects.Keys); //Debug.Log(skeletonNames); //Debug.Log(keyNames); if (!keyNames.Equals(skeletonNames)) { //throw new ArgumentException("Sprite bone names do not match provided skeleton type."); } }
private static async UniTask Build(StateObject state, Model3D model, Model3DLoadMeshDelegate load) { //var (resourceLoader, name, token) = obj; var(file, token) = state; var screen = model.GetValidScreen(); var timingPoints = screen.TimingPoints; token.ThrowIfCancellationRequested(); await UniTask.SwitchToThreadPool(); // ↓ thread pool -------------------------------------- token.ThrowIfCancellationRequested(); // Parse fbx file using var fbx = FbxSemanticParser <SkinnedVertex> .ParseUnsafe(file.GetStream(), false, token); await timingPoints.Update.Next(token); // ↓ main thread -------------------------------------- await CreateTexture(file, fbx, model); // Create a skeleton component if (fbx.Skeletons.IsEmpty == false) { var skeletonIndex = 0; var skeleton = new HumanoidSkeleton(); model.AddComponent(skeleton); using var bones = new ValueTypeRentMemory <Bone>(fbx.Skeletons[skeletonIndex].BoneCount, false); fbx.Skeletons[skeletonIndex].CreateBones(bones.AsSpan()); await skeleton.LoadAsync(bones, timingPoints, cancellationToken : token); } load.Invoke(fbx.Vertices, fbx.Indices); await UniTask.SwitchToThreadPool(); // ↓ thread pool -------------------------------------- // 'using' scope ends here. Dispose resources on a thread pool. // Nobody knows the thread if exceptions are thrown in this method, // but I don't care about that. }
private static async UniTask LoadToModel(PMXObject pmx, Model3D model, Model3DLoadMeshDelegate load, ModelState obj) { // ------------------------------ // ↓ thread pool Debug.Assert(Engine.IsThreadMain == false); var screen = model.GetValidScreen(); // Don't make the followings parallel like UniTask.WhenAll. // ModelData will be disposed when an exception is throw, but another parallel code could not know that. using var vertices = GetVertices(pmx); using var bones = GetBones(pmx); await BuildTexture(pmx, obj.File, model, vertices, obj.CancellationToken); await UniTask.SwitchToThreadPool(); var skeleton = new HumanoidSkeleton(); model.AddComponent(skeleton); await skeleton.LoadAsync(bones.AsSpanLike(), screen.TimingPoints, obj.CancellationToken); // ↑ thread pool // ------------------------------ await screen.TimingPoints.Update.NextOrNow(obj.CancellationToken); // ------------------------------ // ↓ main thread Debug.Assert(Engine.CurrentContext == screen); Debug.Assert(model.LifeState == LifeState.Activating); model.Shader ??= new PmxModelShader(); // load vertices and indices load.Invoke(vertices.AsSpan().AsReadOnly(), pmx.SurfaceList.AsSpan().MarshalCast <Surface, int>()); // ↑ main thread // ------------------------------ }