138 lines
5.3 KiB
C#
138 lines
5.3 KiB
C#
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Xml.Linq;
|
|
|
|
namespace Barotrauma.Items.Components
|
|
{
|
|
class TrigonometricFunctionComponent : ItemComponent
|
|
{
|
|
public enum FunctionType
|
|
{
|
|
Sin,
|
|
Cos,
|
|
Tan,
|
|
Asin,
|
|
Acos,
|
|
Atan,
|
|
}
|
|
|
|
private readonly float[] receivedSignal = new float[2];
|
|
private readonly float[] timeSinceReceived = new float[2];
|
|
|
|
protected Character signalSender;
|
|
|
|
[Serialize(FunctionType.Sin, IsPropertySaveable.No, description: "Which kind of function to run the input through.", alwaysUseInstanceValues: true)]
|
|
public FunctionType Function
|
|
{
|
|
get; set;
|
|
}
|
|
|
|
|
|
[InGameEditable, Serialize(false, IsPropertySaveable.Yes, description: "If set to true, the trigonometric function uses radians instead of degrees.", alwaysUseInstanceValues: true)]
|
|
public bool UseRadians
|
|
{
|
|
get; set;
|
|
}
|
|
|
|
|
|
public TrigonometricFunctionComponent(Item item, ContentXElement element)
|
|
: base(item, element)
|
|
{
|
|
IsActive = true;
|
|
}
|
|
|
|
public override void Update(float deltaTime, Camera cam)
|
|
{
|
|
if (Function == FunctionType.Atan)
|
|
{
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
timeSinceReceived[i] += deltaTime;
|
|
if (timeSinceReceived[i] > 0.1f)
|
|
{
|
|
receivedSignal[i] = float.NaN;
|
|
}
|
|
}
|
|
if (!float.IsNaN(receivedSignal[0]) && !float.IsNaN(receivedSignal[1]))
|
|
{
|
|
float angle = (float)Math.Atan2(receivedSignal[1], receivedSignal[0]);
|
|
if (!UseRadians) { angle = MathHelper.ToDegrees(angle); }
|
|
item.SendSignal(new Signal(angle.ToString("G", CultureInfo.InvariantCulture), sender: signalSender), "signal_out");
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void ReceiveSignal(Signal signal, Connection connection)
|
|
{
|
|
float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float value);
|
|
bool sendOutputImmediately = true;
|
|
signalSender = signal.sender;
|
|
switch (Function)
|
|
{
|
|
case FunctionType.Sin:
|
|
if (!UseRadians) { value = MathHelper.ToRadians(value); }
|
|
value = MathF.Sin(value);
|
|
break;
|
|
case FunctionType.Cos:
|
|
if (!UseRadians) { value = MathHelper.ToRadians(value); }
|
|
value = MathF.Cos(value);
|
|
break;
|
|
case FunctionType.Tan:
|
|
if (!UseRadians) { value = MathHelper.ToRadians(value); }
|
|
//tan is undefined if the value is (π / 2) + πk, where k is any integer
|
|
if (!MathUtils.NearlyEqual(value % MathHelper.Pi, MathHelper.PiOver2))
|
|
{
|
|
value = MathF.Tan(value);
|
|
}
|
|
break;
|
|
case FunctionType.Asin:
|
|
//asin is only defined in the range [-1,1]
|
|
if (value >= -1.0f && value <= 1.0f)
|
|
{
|
|
float angle = MathF.Asin(value);
|
|
if (!UseRadians) { angle = MathHelper.ToDegrees(angle); }
|
|
value = angle;
|
|
}
|
|
break;
|
|
case FunctionType.Acos:
|
|
//acos is only defined in the range [-1,1]
|
|
if (value >= -1.0f && value <= 1.0f)
|
|
{
|
|
float angle = MathF.Acos(value);
|
|
if (!UseRadians) { angle = MathHelper.ToDegrees(angle); }
|
|
value = angle;
|
|
}
|
|
break;
|
|
case FunctionType.Atan:
|
|
if (connection.Name == "signal_in_x")
|
|
{
|
|
timeSinceReceived[0] = 0.0f;
|
|
float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]);
|
|
sendOutputImmediately = false;
|
|
}
|
|
else if (connection.Name == "signal_in_y")
|
|
{
|
|
timeSinceReceived[1] = 0.0f;
|
|
float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]);
|
|
sendOutputImmediately = false;
|
|
}
|
|
else
|
|
{
|
|
float angle = MathF.Atan(value);
|
|
if (!UseRadians) { angle = MathHelper.ToDegrees(angle); }
|
|
value = angle;
|
|
}
|
|
break;
|
|
default:
|
|
throw new NotImplementedException($"Function {Function} has not been implemented.");
|
|
}
|
|
if (sendOutputImmediately)
|
|
{
|
|
signal.value = value.ToString("G", CultureInfo.InvariantCulture);
|
|
item.SendSignal(signal, "signal_out");
|
|
}
|
|
}
|
|
}
|
|
}
|