Пример #1
0
        public async Task Apply(ActorViewModel actor, SkeletonVisual3d skeleton, Configuration config)
        {
            if (actor == null)
            {
                throw new ArgumentNullException(nameof(actor));
            }

            if (actor.ModelObject == null)
            {
                throw new Exception("Actor has no model");
            }

            if (actor.ModelObject.Skeleton == null)
            {
                throw new Exception("Actor model has no skeleton wrapper");
            }

            if (actor.ModelObject.Skeleton.Skeleton == null)
            {
                throw new Exception("Actor skeleton wrapper has no skeleton");
            }

            SkeletonViewModel skeletonMem = actor.ModelObject.Skeleton.Skeleton;

            skeletonMem.MemoryMode = MemoryModes.None;

            PoseService.Instance.SetEnabled(true);
            PoseService.Instance.CanEdit = false;
            await Task.Delay(100);

            if (this.Bones != null)
            {
                // Apply all transforms a few times to ensure parent-inherited values are caluclated correctly, and to ensure
                // we dont end up with some values read during a ffxiv frame update.
                for (int i = 0; i < 3; i++)
                {
                    foreach ((string name, Bone? savedBone) in this.Bones)
                    {
                        if (savedBone == null)
                        {
                            continue;
                        }

                        BoneVisual3d?bone = skeleton.GetBone(name);

                        if (bone == null)
                        {
                            Log.Warning($"Bone: \"{name}\" not found");
                            continue;
                        }

                        if (config.UseSelection && !skeleton.GetIsBoneSelected(bone))
                        {
                            continue;
                        }

                        TransformPtrViewModel vm = bone.ViewModel;

                        if (PoseService.Instance.FreezePositions && savedBone.Position != null && config.LoadPositions)
                        {
                            vm.Position = (Vector)savedBone.Position;
                        }

                        if (PoseService.Instance.FreezeRotation && savedBone.Rotation != null && config.LoadRotations)
                        {
                            vm.Rotation = (Quaternion)savedBone.Rotation;
                        }

                        if (PoseService.Instance.FreezeScale && savedBone.Scale != null && config.LoadScales)
                        {
                            vm.Scale = (Vector)savedBone.Scale;
                        }

                        bone.ReadTransform();
                        bone.WriteTransform(skeleton, false);
                    }

                    await Task.Delay(1);
                }
            }

            await Task.Delay(100);

            skeletonMem.MemoryMode = MemoryModes.ReadWrite;

            await skeletonMem.ReadFromMemoryAsync();

            PoseService.Instance.CanEdit = true;
        }
Пример #2
0
        public async Task Apply(ActorViewModel actor, SkeletonVisual3d skeleton, Configuration config, bool selectionOnly)
        {
            if (actor == null)
            {
                throw new ArgumentNullException(nameof(actor));
            }

            if (actor.ModelObject == null)
            {
                throw new Exception("Actor has no model");
            }

            if (actor.ModelObject.Skeleton == null)
            {
                throw new Exception("Actor model has no skeleton wrapper");
            }

            if (actor.ModelObject.Skeleton.Skeleton == null)
            {
                throw new Exception("Actor skeleton wrapper has no skeleton");
            }

            SkeletonViewModel skeletonMem = actor.ModelObject.Skeleton.Skeleton;

            skeletonMem.MemoryMode = MemoryModes.None;

            PoseService.Instance.SetEnabled(true);
            PoseService.Instance.CanEdit = false;
            await Task.Delay(100);

            // Facial expressions hack:
            // Since all facial bones are parented to the head, if we load the head rotation from
            // the pose that matches the expression, it wont break.
            // We then just set the head back to where it should be afterwards.
            BoneVisual3d?headBone = skeleton.GetIsHeadSelection() ? skeleton.GetBone("Head") : null;

            headBone?.ReadTransform(true);
            Quaternion?originalHeadRotation = headBone?.ViewModel.Rotation;

            if (this.Bones != null)
            {
                // Apply all transforms a few times to ensure parent-inherited values are caluclated correctly, and to ensure
                // we dont end up with some values read during a ffxiv frame update.
                for (int i = 0; i < 3; i++)
                {
                    foreach ((string name, Bone? savedBone) in this.Bones)
                    {
                        if (savedBone == null)
                        {
                            continue;
                        }

                        BoneVisual3d?bone = skeleton.GetBone(name);

                        if (bone == null)
                        {
                            Log.Warning($"Bone: \"{name}\" not found");
                            continue;
                        }

                        if (selectionOnly && !skeleton.GetIsBoneSelected(bone))
                        {
                            continue;
                        }

                        TransformPtrViewModel vm = bone.ViewModel;

                        if (PoseService.Instance.FreezePositions && savedBone.Position != null && config.LoadPositions)
                        {
                            vm.Position = (Vector)savedBone.Position;
                        }

                        if (PoseService.Instance.FreezeRotation && savedBone.Rotation != null && config.LoadRotations)
                        {
                            vm.Rotation = (Quaternion)savedBone.Rotation;
                        }

                        if (PoseService.Instance.FreezeScale && savedBone.Scale != null && config.LoadScales)
                        {
                            vm.Scale = (Vector)savedBone.Scale;
                        }

                        bone.ReadTransform();
                        bone.WriteTransform(skeleton, false);
                    }

                    await Task.Delay(1);
                }
            }

            // Restore the head bone rotation if we were only loading an expression
            if (headBone != null && originalHeadRotation != null)
            {
                headBone.ViewModel.Rotation = (Quaternion)originalHeadRotation;
                headBone.ReadTransform();
                headBone.WriteTransform(skeleton, true);
            }

            await Task.Delay(100);

            skeletonMem.MemoryMode = MemoryModes.ReadWrite;

            await skeletonMem.ReadFromMemoryAsync();

            PoseService.Instance.CanEdit = true;
        }