This commit is contained in:
glax 2023-11-29 01:53:40 +01:00
parent 94b4754890
commit 3d6ad97f2b

View File

@ -4,25 +4,65 @@ namespace VRC_Console;
public class OSCCollar
{
public static void Main(string[] args)
{
OSCCollar collar = new 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;
private double _leftOrRight = 1;
private double _verticalMovement = 0;
private double _horizontalMovement = 0;
private bool _allowMoving = false;
private uint _nilSent = 0;
private DateTime _lastNilMessageSent = DateTime.UnixEpoch;
private DateTime _lastConsoleOutput = DateTime.UnixEpoch;
private static readonly TimeSpan ConsoleUpdateInterval = TimeSpan.FromMilliseconds(50);
private static readonly TimeSpan UpdateFieldsTimeout = TimeSpan.FromMilliseconds(1);
private static readonly TimeSpan NilMessageMaxTimeout = TimeSpan.FromMilliseconds(400);
public OSCCollar()
private 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);
Server.TryAddMethod("/avatar/parameters/Collar_Angle", CollarAngleHandle);
Server.TryAddMethod("/avatar/parameters/CollarRight", CollarLeftRightHandle);
Server.TryAddMethod("/avatar/parameters/Collar_Allow_Moving", AllowMovingHandle);
Server.TryAddMethodPair("/avatar/parameters/Collar_Stretch", CollarStretchHandle, CalculateMovement);
this.Server.Start();
Thread sendNullInputThread = new Thread(SendNullInput);
sendNullInputThread.Start();
Thread runningThread = new Thread(RunningThread);
runningThread.Start();
}
private void PrintOutput(double verticalMovement, double horizontalMovement)
{
Console.Clear();
Console.WriteLine($"OSC Collar - Status: {(_allowMoving ? "enabled" : "disabled")}");
Console.WriteLine("===============================================================");
Console.WriteLine($"Angle:...............{_collarAngle:0.000000}");
Console.WriteLine($"Left/Right:..........{(_leftOrRight < 0 ? "left" : "right")}");
Console.WriteLine($"Stretch:.............{_collarStretch:0.000000}");
Console.WriteLine($"Vertical Movement:...{verticalMovement:0.000000}");
Console.WriteLine($"Horizontal Movement:.{horizontalMovement:0.000000}");
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine($"Sending /input nil {_nilSent}");
}
private void AllowMovingHandle(OscMessageValues messageValues)
{
this._allowMoving = messageValues.ReadBooleanElement(0);
}
private void CollarAngleHandle(OscMessageValues messageValues)
@ -30,49 +70,52 @@ public class OSCCollar
this._collarAngle = messageValues.ReadFloatElement(0);
}
private void CollarLeftRightHandle(OscMessageValues messageValues)
{
this._leftOrRight = messageValues.ReadBooleanElement(0) ? 1 : -1;
}
private void CollarStretchHandle(OscMessageValues messageValues)
{
this._collarStretch = messageValues.ReadFloatElement(0);
}
private void SendNullInput()
private const float PowerAdjust = 0.25f;
private void CalculateMovement()
{
float degrees = _collarAngle * 180;
double radians = degrees * Math.PI / 180;
_verticalMovement = Math.Cos(radians) * this._collarStretch * PowerAdjust;
_horizontalMovement = Math.Sin(radians) * this._collarStretch * PowerAdjust * _leftOrRight;
}
private void RunningThread()
{
while (true)
{
if (!_sendingMessage)
this.Server.Update();
if (_lastNilMessageSent.Add(NilMessageMaxTimeout) < DateTime.Now)
{
this.Client.Send("/input/Vertical", 0f);
this.Client.Send("/input/LookHorizontal", 0f);
this._lastMessageSent = DateTime.Now;
}
Thread.Sleep(400);
}
this.Client.Send("/input/Horizontal", 0f);
this._lastNilMessageSent = DateTime.Now;
_nilSent++;
}
private static readonly TimeSpan MessageTimeoutSpan = TimeSpan.FromMilliseconds(10);
private void HandleCollarChange()
if (_allowMoving)
{
_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;
Thread.Sleep(1);
this.Client.Send("/input/Vertical", Convert.ToSingle(_verticalMovement));
this.Client.Send("/input/Horizontal", Convert.ToSingle(_horizontalMovement));
}
private const float MaxAngle = 180f;
private const float MaxPower = 0.5f;
private static float CalculateTurnPower(float boneAngle)
if (_lastConsoleOutput.Add(ConsoleUpdateInterval) < DateTime.Now)
{
return (boneAngle / MaxAngle) * MaxPower;
PrintOutput(_verticalMovement, _horizontalMovement);
_lastConsoleOutput = DateTime.Now;
}
Thread.Sleep(UpdateFieldsTimeout);
}
}
}