Skip to content

Commit f0b1d59

Browse files
authored
Merge pull request lonelyicer#9 from lonelyicer/dev
feat: rich module info
2 parents 33d9558 + 24f3d87 commit f0b1d59

7 files changed

Lines changed: 124 additions & 28 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"start-init": "Starting Initialization...",
3+
"initializing-udp-clients": "Initializing UDP Clients on ports: {0}",
4+
"using-port": "Using port: {0}",
5+
"eye-tracking-disabled": "Eye tracking is disabled",
6+
"expression-tracking-disabled": "Expression tracking is disabled",
7+
"legacy-protocol": "Legacy Protocol",
8+
"full-face-tracking": "Full FaceTracking",
9+
"eye-tracking": "Eye Tracking",
10+
"expression-tracking": "Expression Tracking",
11+
"init-failed": "Initialization failed, exception: {0}",
12+
"update-timeout": "Receive data timed out",
13+
"update-failed": "Update failed with exception: {0}"
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"start-init": "正在开始初始化...",
3+
"initializing-udp-clients": "正在端口 {0} 上初始化 UDP 客户端",
4+
"using-port": "使用端口:{0}",
5+
"eye-tracking-disabled": "眼部追踪已停用",
6+
"expression-tracking-disabled": "表情追踪已停用",
7+
"legacy-protocol": "旧版协议",
8+
"full-face-tracking": "完整面部追踪",
9+
"eye-tracking": "眼部追踪",
10+
"expression-tracking": "表情追踪",
11+
"init-failed": "初始化失败,原因:{0}",
12+
"update-timeout": "接收数据超时",
13+
"update-failed": "更新数据失败,原因:{0}"
14+
}

VRCFTPicoModule/Utils/DataPacketHelpers.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ public static class DataPacketHelpers
66
{
77
public static T ByteArrayToStructure<T>(byte[] bytes, int offset = 0) where T : struct
88
{
9-
int size = Marshal.SizeOf(typeof(T));
10-
IntPtr ptr = Marshal.AllocHGlobal(size);
9+
var size = Marshal.SizeOf(typeof(T));
10+
var ptr = Marshal.AllocHGlobal(size);
1111

1212
try
1313
{
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using VRCFaceTracking.Core.Helpers;
2+
3+
namespace VRCFTPicoModule.Utils;
4+
5+
public class Localization
6+
{
7+
private Dictionary<string, string>? _translations;
8+
9+
private Localization() { }
10+
11+
private static Localization LocInstance { get; } = new();
12+
13+
public static void Initialize(string languageCode)
14+
{
15+
LocInstance.LoadLanguageAsync(languageCode).GetAwaiter().GetResult();
16+
}
17+
18+
private async Task LoadLanguageAsync(string languageCode)
19+
{
20+
var jsonContent = await LoadResourceAsync($"VRCFTPicoModule.Assets.Locales.{languageCode}.json")
21+
?? await LoadResourceAsync("VRCFTPicoModule.Assets.Locales.en-US.json");
22+
23+
if (jsonContent != null)
24+
{
25+
_translations = await Json.ToObjectAsync<Dictionary<string, string>>(jsonContent);
26+
}
27+
else
28+
{
29+
_translations = new Dictionary<string, string>();
30+
}
31+
}
32+
33+
private async Task<string?> LoadResourceAsync(string resourceName)
34+
{
35+
await using var stream = GetType().Assembly.GetManifestResourceStream(resourceName);
36+
if (stream == null) return null;
37+
using var reader = new StreamReader(stream);
38+
return await reader.ReadToEndAsync();
39+
}
40+
41+
private string GetTranslation(string key)
42+
{
43+
if (_translations != null && _translations.TryGetValue(key, out var translation))
44+
{
45+
return translation;
46+
}
47+
return key;
48+
}
49+
50+
public static string T(string key)
51+
{
52+
return LocInstance.GetTranslation(key);
53+
}
54+
}

VRCFTPicoModule/Utils/Updater.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using VRCFaceTracking.Core.Library;
77
using VRCFaceTracking.Core.Params.Expressions;
88
using VRCFTPicoModule.Data;
9+
using static VRCFTPicoModule.Utils.Localization;
910

1011
namespace VRCFTPicoModule.Utils
1112
{
@@ -59,13 +60,13 @@ public void Update(ModuleState state)
5960
{
6061
if (++_timeOut > 600)
6162
{
62-
_logger.LogWarning("Receive data timed out.");
63+
_logger.LogWarning(T("update-timeout"));
6364
_timeOut = 0;
6465
}
6566
}
6667
catch (Exception ex)
6768
{
68-
_logger.LogWarning("Update failed with exception: {0}", ex);
69+
_logger.LogWarning(T("update-failed"), ex);
6970
}
7071
}
7172

@@ -74,13 +75,10 @@ private static float[] ParseData(byte[] data, bool isLegacy)
7475
if (isLegacy && data.Length >= Marshal.SizeOf<LegacyDataPacket.DataPackBody>())
7576
return DataPacketHelpers.ByteArrayToStructure<LegacyDataPacket.DataPackBody>(data).blendShapeWeight;
7677

77-
if (data.Length >= Marshal.SizeOf<DataPacket.DataPackHeader>() + Marshal.SizeOf<DataPacket.DataPackBody>())
78-
{
79-
var header = DataPacketHelpers.ByteArrayToStructure<DataPacket.DataPackHeader>(data);
80-
if (header.trackingType == 2)
81-
return DataPacketHelpers.ByteArrayToStructure<DataPacket.DataPackBody>(data, Marshal.SizeOf<DataPacket.DataPackHeader>()).blendShapeWeight;
82-
}
83-
return [];
78+
if (data.Length <
79+
Marshal.SizeOf<DataPacket.DataPackHeader>() + Marshal.SizeOf<DataPacket.DataPackBody>()) return [];
80+
var header = DataPacketHelpers.ByteArrayToStructure<DataPacket.DataPackHeader>(data);
81+
return header.trackingType == 2 ? DataPacketHelpers.ByteArrayToStructure<DataPacket.DataPackBody>(data, Marshal.SizeOf<DataPacket.DataPackHeader>()).blendShapeWeight : [];
8482
}
8583

8684
private static void UpdateEye(float[] pShape)
@@ -209,7 +207,7 @@ private void UpdateExpression(float[] pShape)
209207
#endregion
210208

211209
#region Tongue
212-
SetParam(pShape[(int)BlendShape.Index.TongueOut] > 0f ? 1f : 0f, UnifiedExpressions.TongueOut);
210+
SetParam(pShape, BlendShape.Index.TongueOut, UnifiedExpressions.TongueOut);
213211
#endregion
214212
}
215213

VRCFTPicoModule/VRCFTPicoModule.cs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
using Microsoft.Extensions.Logging;
1+
using System.Globalization;
2+
using Microsoft.Extensions.Logging;
23
using System.Net.Sockets;
34
using VRCFaceTracking;
45
using VRCFTPicoModule.Utils;
6+
using static VRCFTPicoModule.Utils.Localization;
57

68
namespace VRCFTPicoModule;
79

@@ -18,40 +20,47 @@ public class VRCFTPicoModule : ExtTrackingModule
1820

1921
public override (bool eyeSuccess, bool expressionSuccess) Initialize(bool eyeAvailable, bool expressionAvailable)
2022
{
21-
Logger.LogInformation("Starting initialization");
23+
Localization.Initialize(CultureInfo.CurrentUICulture.Name);
24+
Logger.LogInformation(T("start-init"));
2225
_trackingAvailable = (eyeAvailable, expressionAvailable);
2326
var initializationResult = InitializeAsync().GetAwaiter().GetResult();
24-
25-
if (!initializationResult.Item1 || !initializationResult.Item2)
26-
UpdateModuleInfo();
27+
UpdateModuleInfo(initializationResult);
2728

2829
return initializationResult;
2930
}
3031

3132
private async Task<(bool eyeSuccess, bool expressionSuccess)> InitializeAsync()
3233
{
33-
Logger.LogDebug("Initializing UDP Clients on ports: {0}", string.Join(", ", Ports));
34+
Logger.LogDebug(T("initializing-udp-clients"), string.Join(", ", Ports));
3435

3536
var portIndex = await ListenOnPorts();
3637
if (portIndex == -1) return (false, false);
3738

3839
_port = Ports[portIndex];
3940
_udpClient = new UdpClient(_port);
40-
Logger.LogInformation("Using port: {0}", _port);
41+
Logger.LogInformation(T("using-port"), _port);
4142

4243
if (!_trackingAvailable.Item1)
43-
Logger.LogInformation("Eye tracking is disabled");
44+
Logger.LogInformation(T("eye-tracking-disabled"));
4445
if (!_trackingAvailable.Item2)
45-
Logger.LogInformation("Expression tracking is disabled");
46+
Logger.LogInformation(T("expression-tracking-disabled"));
4647

4748
_updater = new Updater(_udpClient, Logger, _port == Ports[1], _trackingAvailable);
4849

4950
return _trackingAvailable;
5051
}
5152

52-
private void UpdateModuleInfo()
53+
private void UpdateModuleInfo((bool, bool) initializationResult)
5354
{
54-
ModuleInformation.Name = "PICO Connect";
55+
var moduleProtocol = _port == Ports[1] ? $" [{T("legacy-protocol")}]" : "";
56+
var moduleTrackingStatus = initializationResult switch
57+
{
58+
{ Item1: true, Item2: true } => T("full-face-tracking"),
59+
{ Item1: true, Item2: false } => T("eye-tracking"),
60+
{ Item1: false, Item2: true } => T("expression-tracking"),
61+
_ => ""
62+
};
63+
ModuleInformation.Name = "PICO / " + moduleTrackingStatus + moduleProtocol;
5564
var stream = GetType().Assembly.GetManifestResourceStream("VRCFTPicoModule.Assets.pico.png");
5665
ModuleInformation.StaticImages = stream != null ? [stream] : ModuleInformation.StaticImages;
5766
}
@@ -75,18 +84,15 @@ private async Task<int> ListenOnPorts()
7584
}
7685
catch (Exception ex)
7786
{
78-
Logger.LogError("Initialization failed, exception: {0}", ex);
87+
Logger.LogError(T("init-failed"), ex);
7988
}
8089

8190
return -1;
8291
}
8392

8493
public override void Update()
8594
{
86-
if (_updater == null)
87-
return;
88-
89-
_updater.Update(Status);
95+
_updater?.Update(Status);
9096
}
9197

9298
public override void Teardown()

VRCFTPicoModule/VRCFTPicoModule.csproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@
1515
<EmbeddedResource Include="Assets\pico.png">
1616
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
1717
</EmbeddedResource>
18+
<None Remove="Assets\Locales\en-US.json" />
19+
<EmbeddedResource Include="Assets\Locales\en-US.json">
20+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
21+
</EmbeddedResource>
22+
</ItemGroup>
23+
<ItemGroup>
24+
<None Remove="Assets\Locales\zh-CN.json" />
25+
<EmbeddedResource Include="Assets\Locales\zh-CN.json">
26+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
27+
</EmbeddedResource>
1828
</ItemGroup>
1929
<Target Name="PostBuild" AfterTargets="Build" Condition="'$(ContinuousIntegrationBuild)' != 'true'">
2030
<Copy SourceFiles="$(TargetPath)" DestinationFiles="$(APPDATA)\VRCFaceTracking\CustomLibs\$(TargetFileName)" OverwriteReadOnlyFiles="True" SkipUnchangedFiles="True" />

0 commit comments

Comments
 (0)