Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OscillatorComponent.cs
2022-02-26 02:43:01 +09:00

116 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
namespace Barotrauma.Items.Components
{
class OscillatorComponent : ItemComponent
{
public enum WaveType
{
Pulse,
Sawtooth,
Sine,
Square,
Triangle,
}
private float frequency;
private float phase;
[InGameEditable, Serialize(WaveType.Pulse, IsPropertySaveable.Yes, description: "What kind of a signal the item outputs." +
" Pulse: periodically sends out a signal of 1." +
" Sawtooth: sends out a periodic wave that increases linearly from 0 to 1." +
" Sine: sends out a sine wave oscillating between -1 and 1." +
" Square: sends out a signal that alternates between 0 and 1." +
" Triangle: sends out a wave that alternates between increasing linearly from -1 to 1 and decreasing from 1 to -1.",
alwaysUseInstanceValues: true)]
public WaveType OutputType
{
get;
set;
}
[InGameEditable(DecimalCount = 2), Serialize(1.0f, IsPropertySaveable.Yes, description: "How fast the signal oscillates, or how fast the pulses are sent (in Hz).", alwaysUseInstanceValues: true)]
public float Frequency
{
get { return frequency; }
set
{
//capped to 240 Hz (= 4 signals per frame) to prevent players
//from wrecking the performance by setting the value too high
frequency = MathHelper.Clamp(value, 0.0f, 240.0f);
}
}
public OscillatorComponent(Item item, ContentXElement element) :
base(item, element)
{
IsActive = true;
}
public override void Update(float deltaTime, Camera cam)
{
switch (OutputType)
{
case WaveType.Pulse:
if (frequency <= 0.0f) return;
phase += deltaTime;
float pulseInterval = 1.0f / frequency;
while (phase >= pulseInterval)
{
item.SendSignal("1", "signal_out");
phase -= pulseInterval;
}
break;
case WaveType.Sawtooth:
phase = (phase + deltaTime * frequency) % 1.0f;
item.SendSignal(phase.ToString(CultureInfo.InvariantCulture), "signal_out");
break;
case WaveType.Square:
phase = (phase + deltaTime * frequency) % 1.0f;
item.SendSignal(phase < 0.5f ? "0" : "1", "signal_out");
break;
case WaveType.Sine:
phase = (phase + deltaTime * frequency) % 1.0f;
item.SendSignal(Math.Sin(phase * MathHelper.TwoPi).ToString(CultureInfo.InvariantCulture), "signal_out");
break;
case WaveType.Triangle:
phase = (phase + deltaTime * frequency) % 1.0f;
float output = 4.0f * MathF.Abs(MathUtils.PositiveModulo(phase - 0.25f, 1.0f) - 0.5f) - 1.0f;
item.SendSignal(output.ToString(CultureInfo.InvariantCulture), "signal_out");
break;
}
}
public override void ReceiveSignal(Signal signal, Connection connection)
{
switch (connection.Name)
{
case "set_frequency":
case "frequency_in":
float newFrequency;
if (float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out newFrequency))
{
Frequency = newFrequency;
}
IsActive = true;
break;
case "set_outputtype":
case "set_wavetype":
WaveType newOutputType;
if (Enum.TryParse(signal.value, out newOutputType))
{
OutputType = newOutputType;
}
break;
}
}
}
}