diff --git a/.idea/.idea.VRC_Collar/.idea/indexLayout.xml b/.idea/.idea.VRC_Collar/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.VRC_Collar/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.VRC_Collar/.idea/vcs.xml b/.idea/.idea.VRC_Collar/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.VRC_Collar/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/OSCCollar/OSCCollar.cs b/OSCCollar/OSCCollar.cs new file mode 100644 index 0000000..89e622b --- /dev/null +++ b/OSCCollar/OSCCollar.cs @@ -0,0 +1,78 @@ +using BuildSoft.OscCore; + +namespace VRC_Console; + +public class OSCCollar +{ + private OscServer Server { get; init; } + private OscClient Client { get; init; } + private float _collarAngle, _collarStretch; + private const float StretchDeadzone = 0.1f; + private const float TurnDeadZone = 5f / 180f; //5 degrees + private DateTime _lastMessageSent = DateTime.UnixEpoch; + private bool _sendingMessage = false; + + public OSCCollar() + { + this.Server = new OscServer(9001); + this.Client = new OscClient("127.0.0.1", 9000); + this._collarAngle = 0; + this._collarStretch = 0; + Server.TryAddMethodPair("/avatar/parameters/Collar_Angle", CollarAngleHandle, HandleCollarChange); + Server.TryAddMethodPair("/avatar/parameters/Collar_Stretch", CollarStretchHandle, HandleCollarChange); + + Thread sendNullInputThread = new Thread(SendNullInput); + sendNullInputThread.Start(); + } + + private void CollarAngleHandle(OscMessageValues messageValues) + { + this._collarAngle = messageValues.ReadFloatElement(0); + } + + private void CollarStretchHandle(OscMessageValues messageValues) + { + this._collarStretch = messageValues.ReadFloatElement(0); + } + + private void SendNullInput() + { + while (true) + { + if (!_sendingMessage) + { + this.Client.Send("/input/Vertical", 0f); + this.Client.Send("/input/LookHorizontal", 0f); + this._lastMessageSent = DateTime.Now; + } + Thread.Sleep(400); + } + } + + private static readonly TimeSpan MessageTimeoutSpan = TimeSpan.FromMilliseconds(10); + private void HandleCollarChange() + { + _sendingMessage = true; + TimeSpan messageTimeout = _lastMessageSent.Add(MessageTimeoutSpan).Subtract(DateTime.Now); + if(messageTimeout > TimeSpan.FromMilliseconds(0)) + Thread.Sleep(messageTimeout); + + if (this._collarStretch > StretchDeadzone) + this.Client.Send("/input/Vertical", this._collarStretch); + else + this.Client.Send("/input/Vertical", 0f); + + if (Math.Abs(this._collarAngle) > TurnDeadZone) + this.Client.Send("/input/LookHorizontal", CalculateTurnPower(this._collarAngle)); + else + this.Client.Send("/input/LookHorizontal", 0f); + _sendingMessage = false; + } + + private const float MaxAngle = 180f; + private const float MaxPower = 0.5f; + private static float CalculateTurnPower(float boneAngle) + { + return (boneAngle / MaxAngle) * MaxPower; + } +} \ No newline at end of file diff --git a/OSCCollar/OSCCollar.csproj b/OSCCollar/OSCCollar.csproj new file mode 100644 index 0000000..4c837a3 --- /dev/null +++ b/OSCCollar/OSCCollar.csproj @@ -0,0 +1,15 @@ + + + + Exe + net7.0 + enable + enable + VRC_Console + + + + + + + diff --git a/VRC_Collar.sln b/VRC_Collar.sln index a55ff74..0d630ee 100644 --- a/VRC_Collar.sln +++ b/VRC_Collar.sln @@ -1,8 +1,16 @@  Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSCCollar", "OSCCollar\OSCCollar.csproj", "{1D3DEA0F-4D6A-473D-AD77-834F4BC6FB02}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1D3DEA0F-4D6A-473D-AD77-834F4BC6FB02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D3DEA0F-4D6A-473D-AD77-834F4BC6FB02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D3DEA0F-4D6A-473D-AD77-834F4BC6FB02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D3DEA0F-4D6A-473D-AD77-834F4BC6FB02}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection EndGlobal diff --git a/VRC_Collar.sln.DotSettings b/VRC_Collar.sln.DotSettings new file mode 100644 index 0000000..9d7df3f --- /dev/null +++ b/VRC_Collar.sln.DotSettings @@ -0,0 +1,3 @@ + + OSC + True \ No newline at end of file