Skip to content

Commit

Permalink
Merge pull request #1068 from AsgardXIV/voice
Browse files Browse the repository at this point in the history
Voice Support
  • Loading branch information
Yuki-Codes authored May 17, 2022
2 parents ac98aaf + a929937 commit a04b37f
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 80 deletions.
2 changes: 0 additions & 2 deletions Anamnesis/Actor/Pages/ActionPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@
Style="{StaticResource Label}" />

<ComboBox Grid.Row="2" Grid.Column="1" ItemsSource="{Binding LipSyncTypes, Mode=OneTime}" SelectedValue="{Binding Actor.Animation.LipsOverride, Mode=TwoWay}" SelectedValuePath="AnimationId" DisplayMemberPath="DisplayName" />


</Grid>
</GroupBox>
</StackPanel>
Expand Down
11 changes: 9 additions & 2 deletions Anamnesis/Actor/Pages/ActionPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public ActionPage()

this.ContentArea.DataContext = this;

// Grab "no animation" and all "speak/" animations, which are the only ones valid in this slot
this.LipSyncTypes = GameDataService.ActionTimelines.Where(x => x.AnimationId == 0 || (x.Key?.StartsWith("speak/") ?? false));
this.LipSyncTypes = this.GenerateLipList();
}

public GposeService GposeService => GposeService.Instance;
public AnimationService AnimationService => AnimationService.Instance;
public PoseService PoseService => PoseService.Instance;
public ActorMemory? Actor { get; private set; }
public IEnumerable<ActionTimeline> LipSyncTypes { get; private set; }

public UserAnimationOverride AnimationOverride { get; private set; } = new();

public ConditionalWeakTable<ActorMemory, UserAnimationOverride> UserAnimationOverrides { get; private set; } = new();
Expand Down Expand Up @@ -78,6 +78,13 @@ private void OnActorChanged(ActorMemory? actor)
}
}

private IEnumerable<ActionTimeline> GenerateLipList()
{
// Grab "no animation" and all "speak/" animations, which are the only ones valid in this slot
IEnumerable<ActionTimeline> lips = GameDataService.ActionTimelines.Where(x => x.AnimationId == 0 || (x.Key?.StartsWith("speak/") ?? false));
return lips;
}

private void OnBaseAnimationSearchClicked(object sender, RoutedEventArgs e)
{
if (this.Actor == null)
Expand Down
79 changes: 36 additions & 43 deletions Anamnesis/Actor/Pages/CharacterPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

<Button Click="OnRaceGearClicked"
Style="{StaticResource TransparentIconButton}"
Visibility="{Binding Actor.IsPlayer, Converter={StaticResource B2V}}">
Visibility="{Binding Actor.IsHuman, Converter={StaticResource B2V}}">

<Button.ToolTip>
<XivToolsWpf:TextBlock Key="Character_Equipment_RaceGear" />
Expand All @@ -69,7 +69,7 @@

<Button Click="OnNpcSmallclothesClicked"
Style="{StaticResource TransparentIconButton}"
Visibility="{Binding Actor.IsPlayer, Converter={StaticResource B2V}}">
Visibility="{Binding Actor.IsHuman, Converter={StaticResource B2V}}">

<Button.ToolTip>
<XivToolsWpf:TextBlock Key="Character_Equipment_NpcSmallclothes" />
Expand Down Expand Up @@ -138,6 +138,7 @@
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<XivToolsWpf:TextBlock Key="Character_Actor_Nickname"
Expand All @@ -151,44 +152,6 @@
Style="{StaticResource MaterialDesignTextBox}"
Text="{Binding Actor.Nickname, UpdateSourceTrigger=PropertyChanged}"/>

<!--<XivToolsWpf:TextBlock Key="Character_Actor_EntityType"
Grid.Row="2"
Grid.Column="0"
Style="{StaticResource Label}" />
<Grid Grid.Row="2"
Grid.Column="1"
Margin="0,2,0,0">
<ComboBox ItemsSource="{Binding Source={x:Static anaMem:ActorType.AllActorTypes}}" SelectedIndex="{Binding Actor.ObjectKindInt}">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="IsEnabled" Value="{Binding IsSupportedType}"/>
</Style>
</ComboBox.ItemContainerStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
<XivToolsWpf:TextBlock Key="Character_Actor_Model"
Grid.Row="3"
Grid.Column="0"
Style="{StaticResource Label}" />
<Grid Grid.Row="3"
Grid.Column="1"
Margin="0,2,0,0"
IsEnabled="{Binding Actor.IsOverworldActor}">
<XivToolsWpf:NumberBox Value="{Binding Actor.ModelType}"
Minimum="0"
Maximum="10000"
Buttons="True" />
</Grid>-->

<XivToolsWpf:TextBlock Key="Character_Actor_Alpha"
Grid.Row="4"
Grid.Column="0"
Expand All @@ -201,13 +164,43 @@
TickFrequency="0.1"
Value="{Binding Actor.Transparency}" />


<XivToolsWpf:TextBlock Key="SubActor_Title"
<XivToolsWpf:TextBlock Key="Character_Actor_Voice"
Grid.Row="5"
Grid.Column="0"
Style="{StaticResource Label}" />
<ComboBox Grid.Row="5" Grid.Column="1" ItemsSource="{Binding VoiceEntries, Mode=OneTime}" SelectedValue="{Binding Actor.Voice, Mode=TwoWay}" IsEnabled="{Binding Actor.IsPlayer}" SelectedValuePath="VoiceId">
<ComboBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<XivToolsWpf:TextBlock
Style="{StaticResource Label}"
HorizontalAlignment="Left"
FontStyle="Italic"
FontWeight="Bold"
FontSize="13"
Padding="10,5"
Text="{Binding Name}"
/>

</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ComboBox.GroupStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding VoiceName}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>


<XivToolsWpf:TextBlock Key="SubActor_Title"
Grid.Row="6"
Grid.Column="0"
Style="{StaticResource Label}" />

<StackPanel Orientation="Horizontal" Grid.Row="5" Grid.Column="1" Margin="0, 6, 0, 0">
<StackPanel Orientation="Horizontal" Grid.Row="6" Grid.Column="1" Margin="0, 6, 0, 0">
<views:SubActorEditor Actor="{Binding Actor}" SubActor="{Binding Actor.Mount}" SubActorType="Mount" Margin="3,0"/>
<views:SubActorEditor Actor="{Binding Actor}" SubActor="{Binding Actor.Companion}" SubActorType="Companion" Margin="3,0"/>
<views:SubActorEditor Actor="{Binding Actor}" SubActor="{Binding Actor.Ornament}" SubActorType="Ornament" Margin="3,0"/>
Expand Down
96 changes: 71 additions & 25 deletions Anamnesis/Actor/Pages/CharacterPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
namespace Anamnesis.Actor.Pages;

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Anamnesis.Actor.Utilities;
using Anamnesis.Actor.Views;
using Anamnesis.Files;
using Anamnesis.GameData;
using Anamnesis.GameData.Excel;
using Anamnesis.Keyboard;
using Anamnesis.Memory;
using Anamnesis.Services;
Expand All @@ -36,9 +39,12 @@ public CharacterPage()
this.ContentArea.DataContext = this;

HotkeyService.RegisterHotkeyHandler("CharacterPage.ClearEquipment", () => this.OnClearClicked());

this.VoiceEntries = this.GenerateVoiceList();
}

public ActorMemory? Actor { get; private set; }
public ListCollectionView VoiceEntries { get; private set; }

private void OnLoaded(object sender, RoutedEventArgs e)
{
Expand All @@ -50,23 +56,56 @@ private void OnDataContextChanged(object sender, DependencyPropertyChangedEventA
this.OnActorChanged(this.DataContext as ActorMemory);
}

private ListCollectionView GenerateVoiceList()
{
List<VoiceEntry> entries = new();
foreach (var makeType in GameDataService.CharacterMakeTypes)
{
if (makeType == null)
continue;

if (makeType.Tribe == 0)
continue;

Tribe? tribe = GameDataService.Tribes.GetRow((uint)makeType.Tribe);

if (tribe == null)
continue;

int voiceCount = makeType.Voices!.Count;
for (int i = 0; i < voiceCount; i++)
{
byte voiceId = makeType.Voices[i]!;
VoiceEntry entry = new();
entry.VoiceName = $"Voice #{i + 1} ({voiceId})";
entry.VoiceCategory = $"{makeType.Race}, {tribe.Masculine} ({makeType.Gender})";
entry.VoiceId = voiceId;
entries.Add(entry);
}
}

ListCollectionView voices = new ListCollectionView(entries);
voices.GroupDescriptions.Add(new PropertyGroupDescription("VoiceCategory"));
return voices;
}

private void OnClearClicked(object? sender = null, RoutedEventArgs? e = null)
{
if (this.Actor == null)
return;

this.Actor.MainHand?.Clear(this.Actor.IsPlayer);
this.Actor.OffHand?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Arms?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Chest?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Ear?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Feet?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Head?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Legs?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.LFinger?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Neck?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.RFinger?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Wrist?.Clear(this.Actor.IsPlayer);
this.Actor.MainHand?.Clear(this.Actor.IsHuman);
this.Actor.OffHand?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Arms?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Chest?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Ear?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Feet?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Head?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Legs?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.LFinger?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Neck?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.RFinger?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Wrist?.Clear(this.Actor.IsHuman);

this.Actor?.ModelObject?.Weapons?.Hide();
this.Actor?.ModelObject?.Weapons?.SubModel?.Hide();
Expand All @@ -77,18 +116,18 @@ private void OnNpcSmallclothesClicked(object sender, RoutedEventArgs e)
if (this.Actor == null)
return;

if (!this.Actor.IsPlayer)
if (!this.Actor.IsHuman)
{
this.OnClearClicked(sender, e);
return;
}

this.Actor.Equipment?.Ear?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Head?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.LFinger?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Neck?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.RFinger?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Wrist?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Ear?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Head?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.LFinger?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Neck?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.RFinger?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Wrist?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Arms?.Equip(ItemUtility.NpcBodyItem);
this.Actor.Equipment?.Chest?.Equip(ItemUtility.NpcBodyItem);
this.Actor.Equipment?.Legs?.Equip(ItemUtility.NpcBodyItem);
Expand Down Expand Up @@ -133,12 +172,12 @@ private void OnRaceGearClicked(object sender, RoutedEventArgs e)
this.Actor.Equipment?.Feet?.Equip(feet);
}

this.Actor.Equipment?.Ear?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Head?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.LFinger?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Neck?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.RFinger?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Wrist?.Clear(this.Actor.IsPlayer);
this.Actor.Equipment?.Ear?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Head?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.LFinger?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Neck?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.RFinger?.Clear(this.Actor.IsHuman);
this.Actor.Equipment?.Wrist?.Clear(this.Actor.IsHuman);
}

private async void OnLoadClicked(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -321,4 +360,11 @@ private void OnActorChanged(ActorMemory? actor)
this.IsEnabled = hasValidSelection;
});
}

public class VoiceEntry
{
public byte VoiceId { get; set; }
public string VoiceName { get; set; } = string.Empty;
public string VoiceCategory { get; set; } = string.Empty;
}
}
4 changes: 2 additions & 2 deletions Anamnesis/Actor/Views/CharacterModelEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
DataHead="{Binding ModelObject.DataHead}"
DataPath="{Binding ModelObject.DataPath}"
Tribe="{Binding Customize.Tribe}"
IsEnabled="{Binding ModelObject.IsPlayer}"/>-->
IsEnabled="{Binding ModelObject.IsHuman}"/>-->

<!-- Height -->
<xtw:TextBlock Grid.Row="1" Key="Character_Model_Height" Style="{StaticResource Label}"/>
Expand Down Expand Up @@ -91,7 +91,7 @@
<ana:VectorEditor Grid.Row="4"
Grid.Column="1"
Value="{Binding ModelObject.Bust.Scale}" Expanded="False" CanLink="True" Minimum="0" Maximum="10"
IsEnabled="{Binding ModelObject.IsPlayer}"/>
IsEnabled="{Binding ModelObject.IsHuman}"/>

</Grid>
</UserControl>
2 changes: 1 addition & 1 deletion Anamnesis/Actor/Views/ItemView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private void OnSlotMouseUp(object sender, MouseButtonEventArgs e)

if (e.ChangedButton == MouseButton.Middle && e.ButtonState == MouseButtonState.Released)
{
this.ItemModel?.Clear(this.Actor.IsPlayer);
this.ItemModel?.Clear(this.Actor.IsHuman);
}
}

Expand Down
9 changes: 9 additions & 0 deletions Anamnesis/GameData/Excel/CharaMakeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class CharaMakeType : ExcelRow

public int[]? FacialFeatureOptions { get; private set; }
public List<ImageReference>? FacialFeatures { get; private set; }
public List<byte>? Voices { get; private set; }

public override void PopulateData(RowParser parser, LuminaData lumina, Language language)
{
Expand All @@ -41,5 +42,13 @@ public override void PopulateData(RowParser parser, LuminaData lumina, Language
this.FacialFeatureOptions[i] = parser.ReadColumn<int>(3291 + i);
this.FacialFeatures.Add(new ImageReference(this.FacialFeatureOptions[i]));
}

this.Voices = new List<byte>();

for (int i = 0; i < 12; i++)
{
byte voice = parser.ReadColumn<byte>(3279 + i);
this.Voices.Add(voice);
}
}
}
1 change: 1 addition & 0 deletions Anamnesis/Languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@
"Character_Actor_EntityType": "Type",
"Character_Actor_Nickname": "Nickname",
"Character_Actor_DataPath": "Data Path",
"Character_Actor_Voice": "Voice",

"Character_Model_Header": "Model",
"Character_Model_Height": "Height",
Expand Down
4 changes: 4 additions & 0 deletions Anamnesis/Memory/ActorBasicMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,16 @@ public string Name
}
}

[DependsOn(nameof(ObjectKind))]
public int ObjectKindInt
{
get => (int)this.ObjectKind;
set => this.ObjectKind = (ActorTypes)value;
}

[DependsOn(nameof(ObjectKind))]
public bool IsPlayer => this.ObjectKind == ActorTypes.Player;

[DependsOn(nameof(ObjectIndex), nameof(Address))]
public bool IsValid
{
Expand Down
Loading

0 comments on commit a04b37f

Please sign in to comment.