Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweaks for Importing Poses and Expressions #1370

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions Anamnesis/Actor/Pages/PosePage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,33 +250,32 @@ private async Task Refresh()

private async void OnImportClicked(object sender, RoutedEventArgs e)
{
await this.ImportPose(false, PoseFile.Mode.Rotation);
await this.ImportPose(false, PoseFile.Mode.Rotation, true);
}

private async void OnImportScaleClicked(object sender, RoutedEventArgs e)
{
await this.ImportPose(false, PoseFile.Mode.Scale);
await this.ImportPose(false, PoseFile.Mode.Scale, true);
}

private async void OnImportSelectedClicked(object sender, RoutedEventArgs e)
{
await this.ImportPose(true, PoseFile.Mode.Rotation);
await this.ImportPose(true, PoseFile.Mode.Rotation, false);
}

private async void OnImportAllClicked(object sender, RoutedEventArgs e)
{
await this.ImportPose(false, PoseFile.Mode.All);
await this.ImportPose(false, PoseFile.Mode.All, true);
}

private async void OnImportBodyClicked(object sender, RoutedEventArgs e)
{
if (this.Skeleton == null)
return;

this.Skeleton.SelectHead();
this.Skeleton.InvertSelection();
this.Skeleton.SelectBody();

await this.ImportPose(true, PoseFile.Mode.Rotation);
await this.ImportPose(true, PoseFile.Mode.Rotation, false);
this.Skeleton.ClearSelection();
}

Expand All @@ -296,11 +295,14 @@ private async void OnImportExpressionClicked(object sender, RoutedEventArgs e)
}

this.Skeleton.SelectHead();
await this.ImportPose(true, PoseFile.Mode.Rotation | PoseFile.Mode.Scale);
await this.ImportPose(true, PoseFile.Mode.Rotation | PoseFile.Mode.Scale | PoseFile.Mode.Position, true);
this.Skeleton.ClearSelection();
}

private async Task ImportPose(bool selectionOnly, PoseFile.Mode mode)
// We want to skip doing the "Facial Expression Hack" if we're posing by selected bones or by body.
// Otherwise, the head won't pose as intended and will return to its original position.
// Not quite !selectedOnly, due to posing by expression actually needing the hack.
private async Task ImportPose(bool selectionOnly, PoseFile.Mode mode, bool doFacialExpressionHack)
{
try
{
Expand Down Expand Up @@ -351,7 +353,7 @@ private async Task ImportPose(bool selectionOnly, PoseFile.Mode mode)
}
}

await poseFile.Apply(this.Actor, this.Skeleton, bones, mode);
await poseFile.Apply(this.Actor, this.Skeleton, bones, mode, doFacialExpressionHack);
}
}
catch (Exception ex)
Expand Down
12 changes: 12 additions & 0 deletions Anamnesis/Actor/Posing/Visuals/SkeletonVisual3d.cs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,18 @@ public bool GetIsBoneParentsHovered(BoneVisual3d? bone)
return bone;
}

public void SelectBody()
{
this.SelectHead();
this.InvertSelection();

List<BoneVisual3d> additionalBones = new List<BoneVisual3d>();
BoneVisual3d? headBone = this.GetBone("j_kao");
if (headBone != null)
additionalBones.Add(headBone);
this.Select(additionalBones, SkeletonVisual3d.SelectMode.Add);
}

public void SelectHead()
{
this.ClearSelection();
Expand Down
2 changes: 1 addition & 1 deletion Anamnesis/Actor/Refresh/BrioActorRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public async Task RefreshActor(ActorMemory actor)
// Restore current pose
skeletonVisual3D = new SkeletonVisual3d();
await skeletonVisual3D.SetActor(actor);
await poseFile.Apply(actor, skeletonVisual3D, null, PoseFile.Mode.All);
await poseFile.Apply(actor, skeletonVisual3D, null, PoseFile.Mode.All, true);
}).Start();
}
}
Expand Down
11 changes: 8 additions & 3 deletions Anamnesis/Files/PoseFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public void WriteToFile(ActorMemory actor, SkeletonVisual3d skeleton, HashSet<st
}
}

public async Task Apply(ActorMemory actor, SkeletonVisual3d skeleton, HashSet<string>? bones, Mode mode)
public async Task Apply(ActorMemory actor, SkeletonVisual3d skeleton, HashSet<string>? bones, Mode mode, bool doFacialExpressionHack)
{
if (actor == null)
throw new ArgumentNullException(nameof(actor));
Expand Down Expand Up @@ -154,15 +154,19 @@ public async Task Apply(ActorMemory actor, SkeletonVisual3d skeleton, HashSet<st
// 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.
// We can skip this if we actually intend to pose the head
// in the case of posing by selected bones or by body.
BoneVisual3d? headBone = skeleton.GetBone("j_kao");
Quaternion? originalHeadRotation = null;
if (bones != null && bones.Contains("j_kao"))
Vector? originalHeadPosition = null;
if (doFacialExpressionHack && bones != null && bones.Contains("j_kao"))
{
if (headBone == null)
throw new Exception("Unable to find head (j_kao) bone.");

headBone.Tick();
originalHeadRotation = headBone?.Rotation;
originalHeadPosition = headBone?.Position;
}

// Apply all transforms a few times to ensure parent-inherited values are caluclated correctly, and to ensure
Expand Down Expand Up @@ -223,9 +227,10 @@ public async Task Apply(ActorMemory actor, SkeletonVisual3d skeleton, HashSet<st
}

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

Expand Down
2 changes: 1 addition & 1 deletion Anamnesis/Files/SceneFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public async Task Apply(Mode mode)

if (mode.HasFlag(Mode.Pose))
{
await entry.Pose!.Apply(actor, skeleton, null, PoseFile.Mode.Rotation);
await entry.Pose!.Apply(actor, skeleton, null, PoseFile.Mode.Rotation, true);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Anamnesis/Views/TargetSelectorView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ private async void OnCreateActorClicked(object sender, RoutedEventArgs e)
fullActor.SetAddress(newActor.Address);
fullActor.Tick();
await skeletonVisual3D.SetActor(fullActor);
await poseFile.Apply(fullActor, skeletonVisual3D, null, PoseFile.Mode.Rotation);
await poseFile.Apply(fullActor, skeletonVisual3D, null, PoseFile.Mode.Rotation, true);
}
}

Expand Down