Change folder structure, add solution to the root.

This commit is contained in:
2023-06-18 17:19:03 +02:00
parent d5f5fb5614
commit 15747d7e9b
51 changed files with 33 additions and 6 deletions

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ImGui.NET" Version="1.89.4" />
<PackageReference Include="Raylib-cs" Version="4.2.0.1" />
<PackageReference Include="Silk.NET" Version="2.17.0" />
<PackageReference Include="StbImageSharp" Version="2.27.13" />
<PackageReference Include="StbVorbisSharp" Version="1.22.4" />
</ItemGroup>
<ItemGroup>
<Content Include="libs/fmod/bin/linux/*.*"
Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))'">
<Link>%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="libs/fmod/bin/windows/*.*" Condition=" '$(OS)' == 'Windows_NT' ">
<Link>%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,40 @@
namespace DaggerFramework.Audio
{
public abstract class AudioBackend : IDisposable
{
public abstract void Initialize();
public abstract void Update();
public abstract void Shutdown();
// BUS
public abstract void CreateBus(string busName);
public abstract void SetBusVolume(string busName, float volume);
public abstract float GetBusVolume(string busName);
// SOUND
public abstract void PlaySound(Sound sound, string bus = "Master", float pitch = 1.0f, float volume = 1.0f);
public void PlaySound(Sound sound, string bus = "Master") => PlaySound(sound, bus, default, default);
public void PlaySoundVariation(Sound sound, string bus = "Master", float pitchVariation = 0.1f, float volume = 1.0f)
{
var maxPitch = 1.0f + pitchVariation;
var minPitch = 1.0f - pitchVariation;
var pitch = (float)_random.NextDouble() * (maxPitch - minPitch) + minPitch;
PlaySound(sound, bus, pitch, volume);
}
// EFFECTS
public abstract void AddBusEffect<T>(T effect, string bus = "Master") where T : AudioEffect;
public void Dispose()
{
Shutdown();
}
private LehmerRandom _random = new LehmerRandom();
}
public struct SoundInstance
{
}
}

View File

@@ -0,0 +1,7 @@
namespace DaggerFramework
{
public class AudioBus
{
}
}

View File

@@ -0,0 +1,9 @@
namespace DaggerFramework
{
public class AudioEffect { }
public class AudioEffectReverb : AudioEffect
{
}
}

View File

@@ -0,0 +1,45 @@
namespace DaggerFramework.Audio
{
public class DummyAudioBackend : AudioBackend
{
public override void AddBusEffect<T>(T effect, string bus = "Master")
{
return;
}
public override void CreateBus(string busName)
{
return;
}
public override float GetBusVolume(string busName)
{
return 0.0f;
}
public override void Initialize()
{
return;
}
public override void SetBusVolume(string busName, float volume)
{
return;
}
public override void Shutdown()
{
return;
}
public override void Update()
{
return;
}
public override void PlaySound(Sound sound, string bus = "Master", float pitch = 1, float volume = 1)
{
return;
}
}
}

View File

@@ -0,0 +1,136 @@
using FMOD;
using System.Runtime.InteropServices;
namespace DaggerFramework.Audio
{
public class FmodAudioBackend : AudioBackend
{
public override void Initialize()
{
CreateSystem();
_loadedSounds = new Dictionary<string, FMOD.Sound>();
_channelGroups = new Dictionary<string, ChannelGroup>();
CreateBus("Master");
}
public override void Update() => _system.update();
public override void PlaySound(Sound sound, string bus = "Master", float pitch = 1, float volume = 1)
{
int channels = 0;
if (sound.Format == SoundFormat.Mono)
{
channels = 1;
}
else if (sound.Format == SoundFormat.Stereo)
{
channels = 2;
}
var channel = PlaySoundFromBuffer(sound.Path, sound.BufferSize, channels, sound.SampleRate, sound.Buffer, GetChannelGroup(bus));
channel.setVolume(volume);
channel.setPitch(pitch);
}
public override void CreateBus(string busName)
{
ChannelGroup channelGroup;
_system.createChannelGroup(busName, out channelGroup);
_channelGroups.Add(busName, channelGroup);
}
public override void SetBusVolume(string busName, float volume)
{
var channel = GetChannelGroup(busName);
channel.setVolume(volume);
}
public override float GetBusVolume(string busName)
{
float volume;
GetChannelGroup(busName).getVolume(out volume);
return volume;
}
public override void AddBusEffect<T>(T effect, string bus = "Master")
{
var channelGroup = GetChannelGroup(bus);
DSP dsp;
switch (effect)
{
case AudioEffectReverb:
dsp = CreateReverbDsp(effect as AudioEffectReverb);
break;
default:
_system.createDSPByType(DSP_TYPE.UNKNOWN, out dsp);
break;
}
channelGroup.addDSP(0, dsp);
}
private DSP CreateReverbDsp(AudioEffectReverb effectReverb)
{
DSP dsp;
_system.createDSPByType(DSP_TYPE.SFXREVERB, out dsp);
return dsp;
}
private void CreateSystem()
{
var result = FMOD.Factory.System_Create(out _system);
_system.init(128, INITFLAGS.NORMAL, 0);
}
private Channel PlaySoundFromBuffer(string path, int length, int channels, int sampleRate, byte[] buffer, ChannelGroup channelGroup)
{
Channel fmodChannel;
FMOD.Sound fmodSound = IsLoaded(path) ? GetSoundFromLoaded(path) : CreateSound(length, channels, sampleRate, path, buffer);
_system.playSound(fmodSound, channelGroup, false, out fmodChannel);
return fmodChannel;
}
private FMOD.Sound GetSoundFromLoaded(string path) => _loadedSounds[path];
private bool IsLoaded(string path) => _loadedSounds.ContainsKey(path);
private FMOD.Sound CreateSound(int length, int channels, int sampleRate, string path, byte[] buffer)
{
FMOD.Sound sound;
CREATESOUNDEXINFO info = new CREATESOUNDEXINFO()
{
numchannels = channels,
defaultfrequency = sampleRate,
format = SOUND_FORMAT.PCM16,
length = (uint)length,
cbsize = Marshal.SizeOf(typeof(CREATESOUNDEXINFO))
};
var result = _system.createSound(buffer, FMOD.MODE.OPENMEMORY | FMOD.MODE.OPENRAW | FMOD.MODE.CREATESAMPLE, ref info, out sound);
AddToLoaded(path, sound);
return sound;
}
private void AddToLoaded(string path, FMOD.Sound sound) => _loadedSounds.Add(path, sound);
private ChannelGroup GetChannelGroup(string busName)
{
return _channelGroups[busName];
}
public override void Shutdown()
{
throw new NotImplementedException();
}
private FMOD.System _system;
// TODO: use a different key for the dictionary, paths are not good :( (waste of memory lol)
private Dictionary<string, FMOD.Sound> _loadedSounds;
private Dictionary<string, ChannelGroup> _channelGroups;
}
}

View File

@@ -0,0 +1,110 @@
namespace DaggerFramework
{
// Based on https://github.com/ppr-game/PPR/blob/engine/PER.Util/src/Color.cs
/// <summary>
/// A record struct representing a color.
/// </summary>
public record struct Color
{
// TODO: add more HTML colors.
public static Color AliceBlue = new(0xF0F8FF);
public static Color AntiqueWhite = new(0xFAEBD7);
public static Color Aqua = new(0x00FFFF);
public static Color Aquamarine = new(0x7FFFD4);
public static Color Azure = new(0xF0FFFF);
public static Color Beige = new(0xF5F5DC);
public static Color Bisque = new(0xFFE4C4);
public static Color Black = new(0x000000);
public static Color BlanchedAlmond = new(0xFFEBCD);
public static Color Blue = new(0x0000FF);
public static Color BlueViolet = new(0x8A2BE2);
public static Color Brown = new(0xA52A2A);
public static Color BurlyWood = new(0xDEB887);
public static Color CadetBlue = new(0x5F9EA0);
public static Color Chartreuse = new(0x7FFF00);
public static Color Chocolate = new(0xD2691E);
public static Color Coral = new(0xFF7F50);
public static Color CornflowerBlue = new(0x6495ED);
public static Color Cornsilk = new(0xFFF8DC);
public static Color Crimson = new(0xDC143C);
public static Color Cyan = new(0x00FFFF);
public static Color DarkBlue = new(0x00008B);
public static Color DarkCyan = new(0x008B8B);
public static Color White = new(0xFFFFFF);
public static Color Green = new(0x00FF00);
public static Color Red = new(0xFF0000);
public float R { get; set; }
public float G { get; set; }
public float B { get; set; }
public float A { get; set; }
public int Argb
{
get
{
int c = (ushort)Math.Round(A * 255f);
c <<= 8;
c |= (ushort)Math.Round(R * 255f);
c <<= 8;
c |= (ushort)Math.Round(G * 255f);
c <<= 8;
c |= (ushort)Math.Round(B * 255f);
return c;
}
}
public Color(float r, float g, float b, float a)
{
R = r;
G = g;
B = b;
A = a;
}
public Color(byte r, byte g, byte b, byte a)
{
R = r / 255f;
G = g / 255f;
B = b / 255f;
A = a / 255f;
}
public Color(int hex)
{
A = 1.0f;
B = (hex & 0xFF) / 255.0f;
hex >>= 8;
G = (hex & 0xFF) / 255.0f;
hex >>= 8;
R = (hex & 0xFF) / 255.0f;
}
public Color Lightened(float amount)
{
var result = this;
result.R = result.R + (1.0f - result.R) * amount;
result.G = result.G + (1.0f - result.G) * amount;
result.B = result.B + (1.0f - result.B) * amount;
return result;
}
public Color Darkened(float amount)
{
var result = this;
result.R = result.R * (1.0f - amount);
result.G = result.G * (1.0f - amount);
result.B = result.B * (1.0f - amount);
return result;
}
public System.Drawing.Color ToSystemColor()
{
var result = System.Drawing.Color.FromArgb(Argb);
return result;
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Numerics;
namespace DaggerFramework.Extensions
{
public static class Mat4Extensions
{
public static Matrix4x4 Scale(this Matrix4x4 mat, Vector2 scale)
{
return mat;
}
}
}

2506
DaggerFramework/Source/External/FastNoiseLite.cs vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,201 @@
/// <summary>
/// https://github.com/YourRobotOverlord/LehmerRandom/blob/master/Lehmer/Random.cs
/// Alternative to System.Random based on the Lehmer algorithm.
/// </summary>
public class LehmerRandom
{
// Stores the seed for the Next methods.
private uint _seed;
/// <summary>
/// Initializes a new instance of the Random class, using a time-dependent default seed value.
/// </summary>
public LehmerRandom()
{
_seed = (uint)System.Environment.TickCount;
}
/// <summary>
/// Initializes a new instance of the Random class, using the specified seed value.
/// </summary>
/// <param name="seed"></param>
public LehmerRandom(int seed)
{
_seed = (uint)seed;
}
/// <summary>
/// Initializes a new instance of the Random class, using the specified seed value.
/// </summary>
/// <param name="seed"></param>
public LehmerRandom(uint seed)
{
_seed = seed;
}
/// <summary>
/// Returns a non-negative random integer.
/// </summary>
/// <returns>Int32</returns>
public int Next()
{
return GetNextInt(0, int.MaxValue);
}
/// <summary>
/// Returns a non-negative random integer that is less than the specified maximum.
/// </summary>
/// <param name="maxValue">Int32</param>
/// <returns>Int32</returns>
public int Next(int maxValue)
{
return GetNextInt(0, maxValue);
}
/// <summary>
/// Returns a random integer that is within a specified range.
/// </summary>
/// <param name="minValue">Int32</param>
/// <param name="maxValue">Int32</param>
/// <returns>Int32</returns>
public int Next(int minValue, int maxValue)
{
return GetNextInt(minValue, maxValue);
}
/// <summary>
/// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0
/// </summary>
/// <returns></returns>
public double NextDouble()
{
return GetNextDouble(0.0, 1.0);
}
/// <summary>
/// Returns a non-negative random floating-point number that is less than the specified maximum.
/// </summary>
/// <param name="maxValue"></param>
/// <returns></returns>
public double NextDouble(double maxValue)
{
return GetNextDouble(0.0, maxValue);
}
/// <summary>
/// Returns a random floating-point number that is within a specified range.
/// </summary>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
/// <returns></returns>
public double NextDouble(double minValue, double maxValue)
{
return GetNextDouble(minValue, maxValue);
}
/// <summary>
/// Fills the elements of a specified array of bytes with random numbers.
/// </summary>
/// <param name="buffer">The array to be filled with random numbers.</param>
public void NextBytes(byte[] buffer)
{
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)Next();
}
}
// Returns a random int and sets the seed for the next pass.
internal int GetNextInt(int minValue, int maxValue)
{
_seed = Rnd(_seed);
return ConvertToIntRange(_seed, minValue, maxValue);
}
// Returns a random double and sets the seed for the next pass.
internal double GetNextDouble(double minValue, double maxValue)
{
_seed = Rnd(_seed);
return ConvertToDoubleRange(_seed, minValue, maxValue);
}
/// <summary>
/// Returns a random integer that is within a specified range, using the specified seed value.
/// </summary>
/// <param name="seed"></param>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
/// <returns></returns>
public static int RndInt(uint seed, int minValue, int maxValue)
{
return GetInt(seed, minValue, maxValue);
}
/// <summary>
/// Returns a random integer that is within a specified range, using a time-dependent default seed value.
/// </summary>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
/// <returns></returns>
public static int RndInt(int minValue, int maxValue)
{
return GetInt((uint)System.Environment.TickCount, minValue, maxValue);
}
/// <summary>
/// Returns a random double that is within a specified range, using the specified seed value.
/// </summary>
/// <param name="seed"></param>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
/// <returns></returns>
public static double RndDouble(uint seed, double minValue, double maxValue)
{
return GetDouble(seed, minValue, maxValue);
}
/// <summary>
/// Returns a random double that is within a specified range, using a time-dependent default seed value.
/// </summary>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
/// <returns></returns>
public static double RndDouble(double minValue, double maxValue)
{
return GetDouble((uint)System.Environment.TickCount, minValue, maxValue);
}
internal static int GetInt(uint seed, int minValue, int maxValue)
{
return ConvertToIntRange(Rnd(seed), minValue, maxValue);
}
internal static double GetDouble(uint seed, double minValue, double maxValue)
{
return ConvertToDoubleRange(Rnd(seed), minValue, maxValue);
}
// Converts uint to integer within the given range.
internal static int ConvertToIntRange(uint val, int minValue, int maxValue)
{
return (int)(val % (maxValue - minValue) + minValue);
}
// Converts uint to double within the given range.
internal static double ConvertToDoubleRange(uint val, double minValue, double maxValue)
{
return (double)val / uint.MaxValue * (maxValue - minValue) + minValue;
}
// Pseudo-random number generator based on the Lehmer Algorithm
// and javidx9's implementation:
// https://github.com/OneLoneCoder/olcPixelGameEngine/blob/master/Videos/OneLoneCoder_PGE_ProcGen_Universe.cpp
internal static uint Rnd(uint seed)
{
seed += 0xe120fc15;
ulong tmp = (ulong)seed * 0x4a39b70d;
uint m1 = (uint)((tmp >> 32) ^ tmp);
tmp = (ulong)m1 * 0x12fad5c9;
return (uint)((tmp >> 32) ^ tmp);
}
}

40
DaggerFramework/Source/Game.cs Executable file
View File

@@ -0,0 +1,40 @@
namespace DaggerFramework
{
public abstract class Game
{
public abstract string ResourceRoot { get; }
/// <summary>
/// Starts the game application.
/// This involves initializing the required subsystems, loading resources from the disk, and then preparing the subsystems for running in the main loop.
/// </summary>
public void Start()
{
Initialize();
LoadResources();
Ready();
Run();
}
/// <summary>
/// Called when it's time to initialize the subsystems.
/// </summary>
public abstract void Initialize();
/// <summary>
/// Called when it's time to load the application's resources, such as images or sounds.
/// </summary>
protected abstract void LoadResources();
/// <summary>
/// Called when it's safe to manipulate with the resources or/and systems.
/// </summary>
protected abstract void Ready();
/// <summary>
/// Called when everything has been readied to start the main loop.
/// </summary>
protected abstract void Run();
/// <summary>
/// Called when the application quits and it's safe to clean up.
/// </summary>
public abstract void Shutdown();
}
}

View File

@@ -0,0 +1,29 @@
namespace DaggerFramework
{
public abstract class InputAction
{
public abstract bool IsDown(InputHandler inputHandler);
public abstract bool IsPressed(InputHandler inputHandler);
}
public class KeyInputAction : InputAction
{
public KeyboardKey Key => _keyboardKey;
public KeyInputAction(KeyboardKey keyboardKey)
{
_keyboardKey = keyboardKey;
}
public override bool IsDown(InputHandler inputHandler)
{
return inputHandler.IsKeyboardKeyDown(_keyboardKey);
}
public override bool IsPressed(InputHandler inputHandler)
{
return inputHandler.KeyboardKeyJustPressed(_keyboardKey);
}
private KeyboardKey _keyboardKey;
}
}

View File

@@ -0,0 +1,159 @@
using System.Numerics;
namespace DaggerFramework
{
public abstract class InputHandler
{
public InputHandler()
{
inputMappings = new Dictionary<string, IEnumerable<InputAction>>();
}
public Action OnInput;
public bool Handled { get => _handled; set => _handled = value; }
public abstract bool IsKeyboardKeyDown(KeyboardKey key);
public abstract bool KeyboardKeyJustPressed(KeyboardKey key);
public abstract Vector2 GetInputDirection(KeyboardKey leftKey, KeyboardKey rightKey, KeyboardKey upKey, KeyboardKey downKey);
public abstract int GetCharPressed();
public abstract bool IsActionDown(string action);
public abstract bool IsActionJustPressed(string action);
public abstract bool IsMouseButtonDown(MouseButton button);
public abstract float GetMouseWheelMovement();
public abstract void SetMousePosition(Vector2 position);
public abstract Vector2 GetMousePosition();
public abstract void HideCursor();
public abstract void ShowCursor();
public abstract bool IsCursorHidden();
public void SetAsHandled() => _handled = true;
public void AddInputMapping(string actionName, IEnumerable<InputAction> inputActions)
{
inputMappings.Add(actionName, inputActions);
}
private bool _handled;
protected Dictionary<string, IEnumerable<InputAction>> inputMappings;
}
public enum KeyboardKey
{
Null = 0,
Back = 4,
VolumeUp = 24,
VolumeDown = 25,
Spacebar = 32,
Apostrophe = 39,
Comma = 44,
Minus = 45,
Period = 46,
Slash = 47,
Zero = 48,
One = 49,
Two = 50,
Three = 51,
Four = 52,
Five = 53,
Six = 54,
Seven = 55,
Eight = 56,
Nine = 57,
Semicolon = 59,
Equal = 61,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
Menu = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LeftBracket = 91,
Backslash = 92,
RightBracket = 93,
Grave = 96,
Escape = 256,
Enter = 257,
Tab = 258,
Backspace = 259,
Insert = 260,
Delete = 261,
Right = 262,
Left = 263,
Down = 264,
Up = 265,
PageUp = 266,
PageDown = 267,
Home = 268,
End = 269,
CapsLock = 280,
ScrollLock = 281,
NumLock = 282,
PrintScreen = 283,
Pause = 284,
F1 = 290,
F2 = 291,
F3 = 292,
F4 = 293,
F5 = 294,
F6 = 295,
F7 = 296,
F8 = 297,
F9 = 298,
F10 = 299,
F11 = 300,
F12 = 301,
KP0 = 320,
KP1 = 321,
KP2 = 322,
KP3 = 323,
KP4 = 324,
KP5 = 325,
KP6 = 326,
KP7 = 327,
KP8 = 328,
KP9 = 329,
KPDecimal = 330,
KPDivide = 331,
KPMultiply = 332,
KPSubstract = 333,
KPAdd = 334,
KPEnter = 335,
KPEqual = 336,
LeftShift = 340,
LeftControl = 341,
LeftAlt = 342,
LeftSuper = 343,
RightShift = 344,
RightControl = 345,
RightAlt = 346,
RightSuper = 347,
KBMenu = 348
}
public enum MouseButton
{
Left = 0,
Right = 1,
Middle = 2,
}
}

View File

@@ -0,0 +1,87 @@
using System.Numerics;
using Raylib_cs;
namespace DaggerFramework
{
public class RaylibInputHandler : InputHandler
{
public override int GetCharPressed()
{
return Raylib.GetCharPressed();
}
public override Vector2 GetInputDirection(KeyboardKey leftKey, KeyboardKey rightKey, KeyboardKey upKey, KeyboardKey downKey)
{
Vector2 dir = Vector2.Zero;
if (IsKeyboardKeyDown(leftKey))
dir += new Vector2(-1, 0);
if (IsKeyboardKeyDown(rightKey))
dir += new Vector2(1, 0);
if (IsKeyboardKeyDown(upKey))
dir += new Vector2(0, -1);
if (IsKeyboardKeyDown(downKey))
dir += new Vector2(0, 1);
return dir == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(dir);
}
public override Vector2 GetMousePosition()
{
return Raylib.GetMousePosition();
}
public override float GetMouseWheelMovement()
{
return Raylib.GetMouseWheelMove();
}
public override void HideCursor()
{
Raylib.HideCursor();
}
public override bool IsActionDown(string action)
{
// throw new NotImplementedException();
// return inputMappings[action].IsPressed();
foreach (InputAction inputAction in inputMappings[action])
if (inputAction.IsDown(this)) return true;
return false;
}
public override bool IsActionJustPressed(string action)
{
foreach (InputAction inputAction in inputMappings[action])
if (inputAction.IsPressed(this)) return true;
return false;
}
public override bool IsKeyboardKeyDown(DaggerFramework.KeyboardKey key)
{
Raylib_cs.KeyboardKey rayKey = (Raylib_cs.KeyboardKey)key;
OnInput?.Invoke();
return Raylib.IsKeyDown(rayKey);
}
public override bool IsMouseButtonDown(MouseButton button)
{
return Raylib.IsMouseButtonDown((Raylib_cs.MouseButton)button);
}
public override bool KeyboardKeyJustPressed(KeyboardKey key)
{
Raylib_cs.KeyboardKey rayKey = (Raylib_cs.KeyboardKey)key;
return Raylib.IsKeyPressed(rayKey);
}
public override void SetMousePosition(Vector2 position)
{
Raylib.SetMousePosition((int)position.X, (int)position.Y);
}
public override void ShowCursor() => Raylib.ShowCursor();
public override bool IsCursorHidden() => Raylib.IsCursorHidden();
}
}

View File

@@ -0,0 +1,49 @@
namespace DaggerFramework.Rendering
{
public class ColorRectShader : Shader
{
public override string FragmentSource => @"
#version 450
layout(location = 0) out vec4 fsout_Color;
layout (set = 0, binding = 0) uniform Uniforms
{
vec4 color;
};
void main()
{
fsout_Color = color;
}
";
public override string VertexSource => @"
#version 450
layout(location = 0) in vec2 Position;
// uniform MatrixBlock
// {
// // mat4 model = mat4();
// // mat4 view;
// // mat4 proj;
// mat4 transform = mat4(1.0, 1.0, 1.0, 1.0,
// 1.0, 1.0, 1.0, 1.0,
// 1.0, 1.0, 1.0, 1.0,
// 1.0, 1.0, 1.0, 1.0);
// };
// mat4 transform = mat4(1.0, 1.0, 0.0, 1.0,
// 0.0, 1.0, 1.0, 1.0,
// 0.0, 0.0, 1.0, 1.0,
// 0.0, 0.0, 0.0, 1.0);
mat4 transform = mat4(1.0);
void main()
{
// gl_Position = proj * view * model * vec4(Position, 0, 1);
// gl_Position = vec4(Position, 0, 1);
gl_Position = transform * vec4(Position, 0, 1);
}";
}
}

View File

@@ -0,0 +1,164 @@
using System.Drawing;
using System.Numerics;
using Silk.NET.GLFW;
using Silk.NET.OpenGL;
namespace DaggerFramework.Rendering
{
/// <summary>
/// A standard, OpenGL-based renderer.
/// </summary>
public class StandardRenderer : Renderer
{
/// <inheritdoc />
public override Vector2 WindowSize => throw new NotImplementedException();
/// <inheritdoc />
public override bool ShouldRun => throw new NotImplementedException();
/// <inheritdoc />
public override void Initialize(RendererSettings settings)
{
}
/// <inheritdoc />
public override void CreateAndInitialize(WindowSettings windowSettings, RendererSettings renderSettings)
{
CreateWindow(windowSettings);
Initialize(renderSettings);
}
public override void BeginFrame()
{
_glfw.PollEvents();
_gl.Viewport(new Size((int)_windowSize.X, (int)_windowSize.Y));
}
/// <inheritdoc />
public override void EndFrame()
{
// throw new NotImplementedException();
EndFrameUnsafe();
}
/// <inheritdoc />
public override void ClearBackground(Color color)
{
_gl.ClearColor(color.ToSystemColor());
_gl.Clear((uint)ClearBufferMask.ColorBufferBit);
}
/// <inheritdoc />
public override void CreateWindow(string title, Vector2 size) => CreateWindowUnsafe(title, size);
/// <inheritdoc />
public override void Shutdown()
{
CloseWindowUnsafe();
_glfw.Terminate();
}
/// <inheritdoc />
public override void DrawCircle(float radius, Color color)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public override void DrawDebugText(string text, int fontSize, Color color)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public override void DrawRectangle(Vector2 size, Color color)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public override void DrawTexture(int id, Color tint)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public override double GetFrameTime()
{
return 0.0;
}
/// <inheritdoc />
public override int LoadTexture(Texture2d texture)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public override void SetTargetFps(int fps)
{
return;
}
/// <inheritdoc />
public override void SetTransform(Vector2 position, float rotation = 0)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public override void SetTransform(Matrix4x4 transform)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public override void SetWindowTitle(string title)
{
SetWindowTitleUnsafe(title);
}
/// <inheritdoc />
public override void SetWindowVSync(bool value)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public override bool WindowShouldClose() => WindowShouldCloseUnsafe();
private unsafe void CreateWindowUnsafe(string title, Vector2 size)
{
_glfw = GlfwProvider.GLFW.Value;
_glfw.Init();
_glfw.WindowHint(WindowHintInt.ContextVersionMajor, 4);
_glfw.WindowHint(WindowHintInt.ContextVersionMinor, 6);
_windowHandle = _glfw.CreateWindow((int)size.X, (int)size.Y, title, null, null);
_glfw.MakeContextCurrent(_windowHandle);
_gl = GL.GetApi(_glfw.GetProcAddress);
_glfw.SwapInterval(1);
_windowSize = size;
}
private unsafe void CloseWindowUnsafe() => _glfw.DestroyWindow(_windowHandle);
private unsafe bool WindowShouldCloseUnsafe() => _glfw.WindowShouldClose(_windowHandle);
private unsafe void SetWindowTitleUnsafe(string title) => _glfw.SetWindowTitle(_windowHandle, title);
private unsafe void EndFrameUnsafe()
{
_glfw.SwapBuffers(_windowHandle);
}
public override void DrawSdfText(string text, int fontSize, Color color)
{
throw new NotImplementedException();
}
private GL _gl;
private Glfw _glfw;
private unsafe WindowHandle* _windowHandle;
private Vector2 _windowSize;
}
}

View File

@@ -0,0 +1,162 @@
using System.Numerics;
using System.Text;
using Raylib_cs;
namespace DaggerFramework.Rendering
{
public class RaylibRenderer : Renderer
{
public override Vector2 WindowSize => _windowSize;
public override bool ShouldRun => !WindowShouldClose();
public override void CreateWindow(string title, Vector2 size)
{
Raylib.SetTraceLogLevel(TraceLogLevel.LOG_NONE);
_windowSize = size;
Raylib.InitWindow((int)_windowSize.X, (int)_windowSize.Y, title);
}
public override void SetWindowTitle(string title)
{
Raylib.SetWindowTitle(title);
}
public override void SetWindowVSync(bool value)
{
}
public override void SetTargetFps(int fps)
{
Raylib.SetTargetFPS(fps);
}
public override bool WindowShouldClose()
{
return Raylib.WindowShouldClose();
}
public override void Shutdown()
{
Raylib.CloseWindow();
}
public override void BeginFrame()
{
Raylib.BeginDrawing();
}
public override void EndFrame()
{
Raylib.EndDrawing();
}
public override void ClearBackground(Color color)
{
Raylib.ClearBackground(DaggerColorToRaylibColor(color));
}
public override double GetFrameTime()
{
return (double)Raylib.GetFrameTime();
}
public override void DrawCircle(float radius, Color color)
{
Raylib.DrawCircle((int)_position.X, (int)_position.Y, radius, DaggerColorToRaylibColor(color));
}
public override void SetTransform(Vector2 position, float rotation)
{
_position = position;
_rotation = rotation;
}
public override int LoadTexture(Texture2d texture)
{
Image image = new Image();
unsafe
{
fixed (void* dataPtr = texture.Buffer)
{
image.data = dataPtr;
}
}
image.width = texture.Width;
image.height = texture.Height;
image.mipmaps = 1;
image.format = PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
Texture2D rayTexture;
rayTexture = Raylib.LoadTextureFromImage(image);
_texturePool.Add(rayTexture);
return _texturePool.Count - 1;
}
public override void DrawTexture(int id, Color tint)
{
Raylib.DrawTextureV(_texturePool[id], _position, DaggerColorToRaylibColor(tint));
}
public override void DrawRectangle(Vector2 size, Color color)
{
// Raylib.DrawRectangleV(_position, size, SystemColorToRaylibColor(color));
Raylib.DrawRectanglePro(new Rectangle()
{
x = _position.X,
y = _position.Y,
width = size.X,
height = size.Y
}, Vector2.Zero, _rotation, DaggerColorToRaylibColor(color));
}
public override void DrawDebugText(string text, int fontSize, Color color)
{
Raylib.DrawText(text, (int)_position.X, (int)_position.Y, fontSize, DaggerColorToRaylibColor(color));
}
public override void DrawSdfText(string text, int fontSize, Color color)
{
throw new NotImplementedException();
}
public override void Initialize(RendererSettings settings)
{
ConfigFlags flags = 0;
// MSAA
flags |= settings.Msaa == Msaa.Msaa4x ? ConfigFlags.FLAG_MSAA_4X_HINT : 0;
// VSync
flags |= settings.UseVSync ? ConfigFlags.FLAG_VSYNC_HINT : 0;
// Fullscreen
flags |= settings.Fullscreen ? ConfigFlags.FLAG_FULLSCREEN_MODE : 0;
Raylib.SetConfigFlags(flags);
}
// TODO
public override void SetTransform(Matrix4x4 transform) { }
public override void CreateAndInitialize(WindowSettings windowSettings, RendererSettings renderSettings)
{
CreateWindow(windowSettings);
Initialize(renderSettings);
}
private Raylib_cs.Color DaggerColorToRaylibColor(Color color)
{
return new Raylib_cs.Color { r = (byte)Math.Round(color.R * 255f), g = (byte)Math.Round(color.G * 255f), b = (byte)Math.Round(color.B * 255f), a = (byte)Math.Round(color.A * 255f) };
}
private List<Texture2D> _texturePool = new List<Texture2D>();
private Vector2 _position;
private float _rotation;
private Vector2 _windowSize;
}
}

View File

@@ -0,0 +1,150 @@
using System.Numerics;
namespace DaggerFramework.Rendering
{
/// <summary>
/// An abstract class representing the graphics renderer.
/// </summary>
public abstract class Renderer
{
// INIT
/// <summary>
/// Creates the renderer window and initializes internal resources.
/// </summary>
/// <param name="windowSettings">Settings for the rendering window.</param>
/// <param name="renderSettings">Rendering settings.</param>
public abstract void CreateAndInitialize(WindowSettings windowSettings, RendererSettings renderSettings);
/// <summary>
/// Initializes internal resources. Should be called before other methods.
/// </summary>
/// <param name="settings">Rendering settings.</param>
public abstract void Initialize(RendererSettings settings);
// UTIL
/// <summary>
/// Indicates if the renderer will render the next frame.
/// </summary>
public abstract bool ShouldRun { get; }
// WINDOW
/// <summary>
/// The size of the render window.
/// </summary>
public abstract Vector2 WindowSize { get; }
/// <summary>
/// Creates the window with a given title and size.
/// </summary>
/// <param name="title">Title of the window.</param>
/// <param name="size">Vector2 representing size.</param>
public abstract void CreateWindow(string title, Vector2 size);
public void CreateWindow(WindowSettings windowSettings)
{
CreateWindow(windowSettings.Title, windowSettings.Size);
}
// TODO: use properties for these.
public abstract void SetWindowTitle(string title);
public abstract void SetWindowVSync(bool value);
public abstract void SetTargetFps(int fps);
public abstract bool WindowShouldClose();
public abstract void Shutdown();
// DRAWING
/// <summary>
/// Prepares the renderer for drawing the next frame.
/// </summary>
public abstract void BeginFrame();
/// <summary>
/// Ends rendering of the frame.
/// </summary>
public abstract void EndFrame();
/// <summary>
/// Clears the render canvas and sets a background color.
/// </summary>
/// <param name="color">Background color.</param>
public abstract void ClearBackground(Color color);
public abstract double GetFrameTime();
/// <summary>
/// Loads the texture onto the GPU for later use in DrawTexture or other Texture related methods.
/// </summary>
/// <param name="texture">Texture to load.</param>
/// <returns>A texture handler on the GPU.</returns>
public abstract int LoadTexture(Texture2d texture);
/// <summary>
/// Sets transforms for the next draw operation.
/// </summary>
/// <param name="position">Global transform position.</param>
/// <param name="rotation">Rotation.</param>
public abstract void SetTransform(Vector2 position, float rotation = 0.0f);
/// <summary>
/// Sets the transform for the next draw operation.
/// </summary>
/// <param name="transform">Transform matrix.</param>
public abstract void SetTransform(Matrix4x4 transform);
/// <summary>
/// Draws a filled circle.
/// </summary>
/// <param name="radius">Radius of a circle.</param>
/// <param name="color">Fill color.</param>
public abstract void DrawCircle(float radius, Color color);
/// <summary>
/// Draws a filled rectangle.
/// </summary>
/// <param name="size">Rectangle size.</param>
/// <param name="color">Fill color.</param>
public abstract void DrawRectangle(Vector2 size, Color color);
/// <summary>
/// Draws a debug text with a default font.
/// </summary>
/// <param name="position"></param>
/// <param name="text"></param>
/// <param name="fontSize"></param>
/// <param name="color"></param>
public abstract void DrawDebugText(string text, int fontSize, Color color);
/// <summary>
/// Draws text using a signed distance field font atlas.
/// </summary>
/// <param name="text">Text to draw.</param>
/// <param name="fontSize">Size of the font.</param>
/// <param name="color">Color of the text.</param>
public abstract void DrawSdfText(string text, int fontSize, Color color);
/// <summary>
/// Draws the texture.
/// </summary>
/// <param name="id">Texture handle.</param>
/// <param name="tint">Texture tint.</param>
public abstract void DrawTexture(int id, Color tint);
}
public enum Msaa
{
None,
Msaa2x,
Msaa4x,
Msaa8x
}
public struct RendererSettings
{
public Msaa Msaa;
public bool UseVSync;
public bool Fullscreen;
public static RendererSettings Default => new RendererSettings()
{
UseVSync = true,
};
}
public struct WindowSettings
{
public string Title;
public Vector2 Size = new Vector2(640, 480);
public WindowSettings(string title, Vector2 size)
{
Title = title;
Size = size;
}
}
}

View File

@@ -0,0 +1,8 @@
namespace DaggerFramework.Rendering
{
public abstract class Shader
{
public abstract string FragmentSource { get; }
public abstract string VertexSource { get; }
}
}

View File

@@ -0,0 +1,9 @@
namespace DaggerFramework;
public class Font : Resource
{
public int Size = 16;
public Font(string path, byte[] buffer) : base(path, buffer)
{
}
}

View File

@@ -0,0 +1,9 @@
namespace DaggerFramework;
public class FontLoader : ResourceLoader<Font>
{
public override Font Load(string path)
{
return default;
}
}

View File

@@ -0,0 +1,8 @@
namespace DaggerFramework
{
public abstract class ResourceLoader<T> : IDisposable where T : Resource
{
public void Dispose() { }
public abstract T Load(string path);
}
}

View File

@@ -0,0 +1,47 @@
using StbVorbisSharp;
namespace DaggerFramework
{
public class SoundLoader : ResourceLoader<Sound>
{
public override Sound Load(string path)
{
Vorbis vorbis;
Sound result;
var fileBuffer = File.ReadAllBytes(path);
vorbis = Vorbis.FromMemory(fileBuffer);
vorbis.SubmitBuffer();
if (vorbis.Decoded == 0)
{
vorbis.Restart();
vorbis.SubmitBuffer();
}
var audioShort = vorbis.SongBuffer;
int length = vorbis.Decoded * vorbis.Channels;
byte[] audioData = new byte[length * 2];
for (int i = 0; i < length; i++)
{
if (i * 2 >= audioData.Length) break;
var b1 = (byte)(audioShort[i] >> 8);
var b2 = (byte)(audioShort[i] & 256);
audioData[i * 2] = b2;
audioData[i * 2 + 1] = b1;
}
result = new Sound(path, audioData);
result.Format = (SoundFormat)vorbis.Channels - 1;
result.SampleRate = vorbis.SampleRate;
result.BufferSize = length;
vorbis.Dispose();
return result;
}
}
}

View File

@@ -0,0 +1,22 @@
using StbImageSharp;
namespace DaggerFramework
{
public class Texture2dLoader : ResourceLoader<Texture2d>
{
public override Texture2d Load(string path)
{
ImageResult image;
using (var stream = File.OpenRead(path))
{
image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
}
Texture2d result = new Texture2d(path, image.Data);
result.Width = image.Width;
result.Height = image.Height;
return result;
}
}
}

View File

@@ -0,0 +1,23 @@
namespace DaggerFramework
{
public abstract class Resource : IDisposable
{
public string? Path { get => _path; set => _path = value; }
public byte[]? Buffer { get => _buffer; set => _buffer = value; }
public Resource(string path, byte[] buffer)
{
_path = path;
_buffer = buffer;
}
public void Dispose()
{
Buffer = null;
Path = null;
}
private string? _path;
private byte[]? _buffer;
}
}

View File

@@ -0,0 +1,19 @@
namespace DaggerFramework
{
public class Sound : Resource
{
public SoundFormat Format { get; set; }
public int SampleRate { get; set; }
public int BufferSize { get; set; }
public Sound(string path, byte[] buffer) : base(path, buffer)
{
}
}
public enum SoundFormat
{
Mono,
Stereo
}
}

View File

@@ -0,0 +1,11 @@
namespace DaggerFramework
{
public class Texture2d : Resource
{
public int Width { get; set; }
public int Height { get; set; }
public Texture2d(string path, byte[] buffer) : base(path, buffer)
{
}
}
}

View File

@@ -0,0 +1,18 @@
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public class CircleShape2d : Drawable2d
{
public float Radius { get => _radius; set => _radius = value; }
public Color Color { get => _color; set => _color = value; }
public override void OnDraw(Renderer renderer)
{
renderer.DrawCircle(_radius, _color);
}
private float _radius;
private Color _color;
}
}

View File

@@ -0,0 +1,15 @@
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public abstract class Drawable2d : Entity2d, IDrawable
{
public void Draw(Renderer renderer)
{
renderer.SetTransform(Position);
OnDraw(renderer);
}
public abstract void OnDraw(Renderer renderer);
}
}

View File

@@ -0,0 +1,27 @@
using DaggerFramework.Audio;
namespace DaggerFramework.SceneGraph
{
public class Entity
{
public EntityLayer Layer { get; set; }
public InputHandler Input => Layer.Scene.Input;
public AudioBackend Audio => Layer.Scene.Audio;
public int Id { get; set; }
public void Start() => OnStart();
public void Update(double dt) => OnUpdate(dt);
public void ReceiveInput(InputHandler input) => OnInput(input);
protected virtual void OnStart() { }
protected virtual void OnDestroy() { }
protected virtual void OnUpdate(double dt) { }
protected virtual void OnInput(InputHandler input) { }
public void Destroy()
{
OnDestroy();
Layer?.DestroyEntity(Id);
}
}
}

View File

@@ -0,0 +1,9 @@
using System.Numerics;
namespace DaggerFramework.SceneGraph
{
public class Entity2d : Entity
{
public Vector2 Position { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public interface IDrawable
{
public void Draw(Renderer renderer);
}
}

View File

@@ -0,0 +1,158 @@
using System.Drawing;
using System.Numerics;
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
// TODO: add oneshot parameter.
public class Particles2d : Drawable2d
{
public int MaxParticles => _maxParticles;
public void BeginEmit(ParticleSettings settings)
{
_settings = settings;
_maxParticles = _settings.MaxParticles;
_particleIndex = _maxParticles - 1;
InitializeParticles();
}
public void Restart()
{
CleanupParticles();
InitializeParticles();
}
public override void OnDraw(Renderer renderer)
{
foreach (var particle in _particles)
{
if (!particle.Alive) continue;
var t = particle.LifeTimeRemaining / particle.LifeTime;
var scale = MathUtils.Lerp(_settings.ScaleEnd, _settings.ScaleBegin, t);
var color = MathUtils.LerpColor(_settings.ColorEnd, _settings.ColorBegin, t);
renderer.SetTransform(particle.Position, particle.Rotation);
renderer.DrawRectangle(Vector2.One * scale, color);
}
}
protected override void OnStart()
{
base.OnStart();
// Emit();
}
protected override void OnUpdate(double dt)
{
base.OnUpdate(dt);
var rate = (int)MathUtils.Lerp(1, _maxParticles, _settings.Explosiveness);
for (int i = 0; i < rate; i++)
{
Emit();
}
for (int i = 0; i < _maxParticles; i++)
{
var particle = _particles[i];
if (!particle.Alive) continue;
if (particle.LifeTimeRemaining <= 0.0f)
{
particle.Alive = false;
continue;
}
particle.LifeTimeRemaining -= (float)dt;
particle.Velocity += _settings.Gravity * (float)dt;
particle.Position += particle.Velocity * (float)dt;
particle.Rotation += particle.AngularVelocity * (float)dt;
particle.Velocity -= particle.Velocity * _settings.Damping * (float)dt;
_particles[i] = particle;
}
}
private void InitializeParticles()
{
_particles = new Particle[_maxParticles];
}
private void Emit()
{
Particle particle = _particles[_particleIndex];
if (!(particle.LifeTimeRemaining <= 0)) return;
particle.Alive = true;
particle.Position = GetEmitPosition();
particle.Velocity = _settings.Direction * _settings.LinearVelocity;
particle.Velocity += Vector2.One * _settings.LinearVelocityRandom * ((float)_random.NextDouble() - 0.5f);
particle.AngularVelocity = _settings.AngularVelocity;
particle.AngularVelocity += 1f * _settings.AngularVelocityRandom * ((float)_random.NextDouble() - 0.5f);
particle.LifeTime = _settings.LifeTime;
particle.LifeTimeRemaining = particle.LifeTime;
_particles[_particleIndex] = particle;
_particleIndex = --_particleIndex <= 0 ? _maxParticles - 1 : --_particleIndex;
}
private void CleanupParticles() => Array.Clear(_particles);
private Vector2 GetEmitPosition()
{
// https://gamedev.stackexchange.com/questions/26713/calculate-random-points-pixel-within-a-circle-image
var angle = _random.NextDouble() * Math.PI * 2;
float radius = (float)Math.Sqrt(_random.NextDouble()) * _settings.EmitRadius;
float x = Position.X + radius * (float)Math.Cos(angle);
float y = Position.Y + radius * (float)Math.Sin(angle);
return new Vector2(x, y);
}
private ParticleSettings _settings;
private int _maxParticles;
private Particle[] _particles;
private int _particleIndex;
// TODO: replace a random function for better distribution and performance.
private LehmerRandom _random = new LehmerRandom();
}
public struct ParticleSettings
{
public ParticleSettings()
{
}
public float EmitRadius;
public float LifeTime;
public float Explosiveness;
public int MaxParticles;
public Vector2 Direction;
public float LinearVelocity;
public float AngularVelocity = 0.0f;
public float AngularVelocityRandom;
public float LinearVelocityRandom;
public Vector2 Gravity;
public float ScaleBegin = 16f;
public float ScaleEnd = 0.0f;
public Color ColorBegin = Color.White;
public Color ColorEnd = Color.Black;
public float Damping = 0.0f;
}
public struct Particle
{
public Particle()
{
}
public Vector2 Position;
public Vector2 Velocity;
public float AngularVelocity;
public float LifeTime;
public float LifeTimeRemaining;
public float Scale;
public float Rotation;
public bool Alive = true;
}
}

View File

@@ -0,0 +1,25 @@
using System.Drawing;
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public class Sprite2d : Drawable2d
{
public Texture2d Texture { get => _texture; set => _texture = value; }
protected override void OnStart()
{
var renderer = Layer.Scene.Renderer;
_texId = renderer.LoadTexture(_texture);
}
public override void OnDraw(Renderer renderer)
{
renderer.DrawTexture(_texId, Color.White);
}
private Texture2d _texture;
private int _texId;
}
}

View File

@@ -0,0 +1,21 @@
using DaggerFramework.Rendering;
using System.Drawing;
namespace DaggerFramework.SceneGraph
{
public class Text2d : Drawable2d
{
public string Contents { get => _contents; set => _contents = value; }
public int FontSize { get => _fontSize; set => _fontSize = value; }
public Color FontColor { get => _fontColor; set => _fontColor = value; }
public override void OnDraw(Renderer renderer)
{
renderer.DrawDebugText(_contents, _fontSize, _fontColor);
}
private string _contents = string.Empty;
private int _fontSize = 16;
private Color _fontColor = Color.White;
}
}

View File

@@ -0,0 +1,58 @@
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public class EntityLayer : Layer
{
public List<Entity> Entities { get => _entities; }
public EntityLayer(List<Entity> entities)
{
_entities = entities;
}
public EntityLayer()
{
_entities = new List<Entity>();
}
public bool AddEntity(Entity entity)
{
entity.Id = Entities.Count;
entity.Layer = this;
Entities.Add(entity);
return true;
}
public void DestroyEntity(int at)
{
_entities.RemoveAt(at);
}
protected override void OnStart()
{
foreach (var entity in _entities)
{
entity.Layer = this;
entity.Start();
}
}
protected override void OnUpdate(double dt)
{
foreach (var entity in _entities)
{
entity.Update(dt);
}
}
protected override void OnDraw(Renderer renderer)
{
foreach (IDrawable drawable in _entities)
{
drawable.Draw(renderer);
}
}
private List<Entity> _entities;
}
}

View File

@@ -0,0 +1,11 @@
namespace DaggerFramework.SceneGraph
{
public interface IMainLoop
{
public void Init();
public void Start();
public bool ShouldStop();
public void Update();
public double DeltaTime { get; }
}
}

View File

@@ -0,0 +1,21 @@
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public abstract class Layer : IDrawable
{
public Scene Scene { get; set; }
public InputHandler Input { get; set; }
public void Draw(Renderer renderer) => OnDraw(renderer);
public void Start() => OnStart();
public void Update(double dt) => OnUpdate(dt);
public void ReceiveInput(InputHandler input) => OnInput(input);
protected virtual void OnStart() { }
protected virtual void OnUpdate(double dt) { }
protected virtual void OnInput(InputHandler input) { }
protected abstract void OnDraw(Renderer renderer);
}
}

View File

@@ -0,0 +1,82 @@
using System.Drawing;
using System.Numerics;
using DaggerFramework.Audio;
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public class Scene : IMainLoop
{
public Renderer Renderer { get => _renderer; set => _renderer = value; }
public InputHandler Input { get => _input; set => _input = value; }
public AudioBackend Audio => _audioBackend;
public double DeltaTime => Renderer.GetFrameTime();
public Scene(Renderer renderer, InputHandler input, AudioBackend audioBackend)
{
_renderer = renderer;
_input = input;
_audioBackend = audioBackend;
_layers = new Dictionary<string, Layer>();
}
public Scene(Renderer renderer)
{
_renderer = renderer;
}
public void Init() => SetupRenderer();
public void Start()
{
foreach (var layer in _layers.Values)
{
layer.Input = _input;
layer.Start();
}
}
public void Update()
{
foreach (var layer in _layers)
{
layer.Value.Update(DeltaTime);
}
Draw();
}
public void AddLayer(string name, Layer layer)
{
layer.Scene = this;
_layers.Add(name, layer);
}
public bool ShouldStop() => Renderer.WindowShouldClose();
private void Draw()
{
Renderer.BeginFrame();
Renderer.ClearBackground(Color.Black);
foreach (var layer in _layers.Values)
{
layer.Draw(_renderer);
}
Renderer.EndFrame();
Audio.Update();
}
private void SetupRenderer()
{
Renderer.CreateWindow("Game", new Vector2(1280, 720));
Renderer.Initialize(new RendererSettings { Msaa = Msaa.Msaa4x, UseVSync = true });
Renderer.SetTargetFps(60);
}
private Dictionary<string, Layer> _layers;
private Renderer _renderer;
private AudioBackend _audioBackend;
private InputHandler _input;
}
}

View File

@@ -0,0 +1,320 @@
using System.Numerics;
using ImGuiNET;
using Raylib_cs;
using DaggerFramework.Rendering;
namespace DaggerFramework.SceneGraph
{
public class ImGuiRenderLayer : Layer
{
protected override void OnDraw(Renderer renderer)
{
Layout();
_controller.Draw(renderer);
}
protected virtual void Layout() { }
protected override void OnStart()
{
_controller = new ImGuiController();
_controller.Load(Scene.Renderer.WindowSize);
}
protected override void OnUpdate(double dt)
{
_controller.Update(dt, Input);
}
private ImGuiController _controller;
}
public class ImGuiController : IDisposable, IDrawable
{
public ImGuiController()
{
_context = ImGui.CreateContext();
ImGui.SetCurrentContext(_context);
}
public void Dispose()
{
ImGui.DestroyContext();
}
public void Load(Vector2 size)
{
ImGuiIOPtr io = ImGui.GetIO();
io.Fonts.AddFontDefault();
Resize(size);
LoadFontTexture();
SetupInput();
ImGui.NewFrame();
}
unsafe void LoadFontTexture()
{
ImGuiIOPtr io = ImGui.GetIO();
io.Fonts.GetTexDataAsRGBA32(out byte* pixels, out int width, out int height);
// TODO: use engine API instead of Raylib.
Image image = new Image
{
data = pixels,
width = width,
height = height,
mipmaps = 1,
format = PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
};
_fontTexture = Raylib.LoadTextureFromImage(image);
io.Fonts.SetTexID(new IntPtr(_fontTexture.id));
io.Fonts.ClearTexData();
}
private void SetupInput()
{
ImGuiIOPtr io = ImGui.GetIO();
// Setup config flags
io.ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard;
// Setup back-end capabilities flags
io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors;
io.BackendFlags |= ImGuiBackendFlags.HasSetMousePos;
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[(int)ImGuiKey.Tab] = (int)KeyboardKey.Tab;
io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)KeyboardKey.Left;
io.KeyMap[(int)ImGuiKey.RightArrow] = (int)KeyboardKey.Right;
io.KeyMap[(int)ImGuiKey.UpArrow] = (int)KeyboardKey.Up;
io.KeyMap[(int)ImGuiKey.DownArrow] = (int)KeyboardKey.Down;
io.KeyMap[(int)ImGuiKey.PageUp] = (int)KeyboardKey.PageUp;
io.KeyMap[(int)ImGuiKey.PageDown] = (int)KeyboardKey.PageDown;
io.KeyMap[(int)ImGuiKey.Home] = (int)KeyboardKey.Home;
io.KeyMap[(int)ImGuiKey.End] = (int)KeyboardKey.End;
io.KeyMap[(int)ImGuiKey.Insert] = (int)KeyboardKey.Insert;
io.KeyMap[(int)ImGuiKey.Delete] = (int)KeyboardKey.Delete;
io.KeyMap[(int)ImGuiKey.Backspace] = (int)KeyboardKey.Backspace;
io.KeyMap[(int)ImGuiKey.Space] = (int)KeyboardKey.Spacebar;
io.KeyMap[(int)ImGuiKey.Enter] = (int)KeyboardKey.Enter;
io.KeyMap[(int)ImGuiKey.Escape] = (int)KeyboardKey.Escape;
io.KeyMap[(int)ImGuiKey.A] = (int)KeyboardKey.A;
io.KeyMap[(int)ImGuiKey.C] = (int)KeyboardKey.C;
io.KeyMap[(int)ImGuiKey.V] = (int)KeyboardKey.V;
io.KeyMap[(int)ImGuiKey.X] = (int)KeyboardKey.X;
io.KeyMap[(int)ImGuiKey.Y] = (int)KeyboardKey.Y;
io.KeyMap[(int)ImGuiKey.Z] = (int)KeyboardKey.Z;
}
public void Resize(Vector2 size)
{
ImGuiIOPtr io = ImGui.GetIO();
io.DisplaySize = size / _scaleFactor;
}
public void Update(double dt, InputHandler input)
{
ImGuiIOPtr io = ImGui.GetIO();
io.DisplayFramebufferScale = Vector2.One;
io.DeltaTime = (float)dt;
UpdateKeyboard(input);
UpdateMouse(input);
ImGui.NewFrame();
}
private void UpdateKeyboard(InputHandler input)
{
ImGuiIOPtr io = ImGui.GetIO();
// Modifiers are not reliable across systems
io.KeyCtrl = io.KeysDown[(int)KeyboardKey.LeftControl] || io.KeysDown[(int)KeyboardKey.RightControl];
io.KeyShift = io.KeysDown[(int)KeyboardKey.LeftShift] || io.KeysDown[(int)KeyboardKey.RightShift];
io.KeyAlt = io.KeysDown[(int)KeyboardKey.LeftAlt] || io.KeysDown[(int)KeyboardKey.RightAlt];
io.KeySuper = io.KeysDown[(int)KeyboardKey.LeftSuper] || io.KeysDown[(int)KeyboardKey.RightSuper];
// Key states
for (int i = (int)KeyboardKey.Spacebar; i < (int)KeyboardKey.KBMenu + 1; i++)
{
io.KeysDown[i] = input.IsKeyboardKeyDown((KeyboardKey)i);
}
// Key input
int keyPressed = input.GetCharPressed();
if (keyPressed != 0)
{
io.AddInputCharacter((uint)keyPressed);
}
}
private void UpdateMouse(InputHandler input)
{
ImGuiIOPtr io = ImGui.GetIO();
// Store button states
for (int i = 0; i < io.MouseDown.Count; i++)
{
io.MouseDown[i] = input.IsMouseButtonDown((MouseButton)i);
}
// Mouse scroll
io.MouseWheel += input.GetMouseWheelMovement();
// Mouse position
Vector2 mousePosition = io.MousePos;
// TODO:
// bool focused = Raylib.IsWindowFocused();
if (io.WantSetMousePos)
{
input.SetMousePosition(mousePosition);
}
else
{
io.MousePos = input.GetMousePosition();
}
// Mouse cursor state
if ((io.ConfigFlags & ImGuiConfigFlags.NoMouseCursorChange) == 0 || input.IsCursorHidden())
{
ImGuiMouseCursor cursor = ImGui.GetMouseCursor();
if (cursor == ImGuiMouseCursor.None || io.MouseDrawCursor)
{
input.HideCursor();
}
else
{
input.ShowCursor();
}
}
}
private void Render()
{
ImGui.Render();
}
private void RenderCommandLists(ImDrawDataPtr data)
{
// Scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fbWidth = (int)(data.DisplaySize.X * data.FramebufferScale.X);
int fbHeight = (int)(data.DisplaySize.Y * data.FramebufferScale.Y);
// Avoid rendering if display is minimized or if the command list is empty
if (fbWidth <= 0 || fbHeight <= 0 || data.CmdListsCount == 0)
{
return;
}
Rlgl.rlDrawRenderBatchActive();
Rlgl.rlDisableBackfaceCulling();
Rlgl.rlEnableScissorTest();
data.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale);
for (int n = 0; n < data.CmdListsCount; n++)
{
int idxOffset = 0;
ImDrawListPtr cmdList = data.CmdListsRange[n];
// Vertex buffer and index buffer generated by DearImGui
ImPtrVector<ImDrawVertPtr> vtxBuffer = cmdList.VtxBuffer;
ImVector<ushort> idxBuffer = cmdList.IdxBuffer;
for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++)
{
ImDrawCmdPtr pcmd = cmdList.CmdBuffer[cmdi];
// Scissor rect
Vector2 pos = data.DisplayPos;
int rectX = (int)((pcmd.ClipRect.X - pos.X) * data.FramebufferScale.X);
int rectY = (int)((pcmd.ClipRect.Y - pos.Y) * data.FramebufferScale.Y);
int rectW = (int)((pcmd.ClipRect.Z - rectX) * data.FramebufferScale.Y);
int rectH = (int)((pcmd.ClipRect.W - rectY) * data.FramebufferScale.Y);
Rlgl.rlScissor(rectX, Raylib.GetScreenHeight() - (rectY + rectH), rectW, rectH);
if (pcmd.UserCallback != IntPtr.Zero)
{
// pcmd.UserCallback(cmdList, pcmd);
idxOffset += (int)pcmd.ElemCount;
}
else
{
DrawTriangles(pcmd.ElemCount, idxOffset, (int)pcmd.VtxOffset, idxBuffer, vtxBuffer, pcmd.TextureId);
idxOffset += (int)pcmd.ElemCount;
Rlgl.rlDrawRenderBatchActive();
}
}
}
Rlgl.rlSetTexture(0);
Rlgl.rlDisableScissorTest();
Rlgl.rlEnableBackfaceCulling();
}
private Color GetColor(uint hexValue)
{
Color color = new Color();
color.R = (byte)(hexValue & 0xFF) / 255f;
color.G = (byte)((hexValue >> 8) & 0xFF) / 255f;
color.B = (byte)((hexValue >> 16) & 0xFF) / 255f;
color.A = (byte)((hexValue >> 24) & 0xFF) / 255f;
return color;
}
void DrawTriangleVertex(ImDrawVertPtr idxVert)
{
Color c = GetColor(idxVert.col);
Rlgl.rlColor4ub((byte)Math.Round(c.R * 255f), (byte)Math.Round(c.G * 255f), (byte)Math.Round(c.B * 255f), (byte)Math.Round(c.A * 255f));
Rlgl.rlTexCoord2f(idxVert.uv.X, idxVert.uv.Y);
Rlgl.rlVertex2f(idxVert.pos.X, idxVert.pos.Y);
}
// Draw the imgui triangle data
private void DrawTriangles(uint count, int idxOffset, int vtxOffset, ImVector<ushort> idxBuffer, ImPtrVector<ImDrawVertPtr> idxVert, IntPtr textureId)
{
ushort index = 0;
ImDrawVertPtr vertex;
if (Rlgl.rlCheckRenderBatchLimit((int)count * 3))
{
Rlgl.rlDrawRenderBatchActive();
}
Rlgl.rlBegin(DrawMode.TRIANGLES);
Rlgl.rlSetTexture((uint)textureId);
for (int i = 0; i <= (count - 3); i += 3)
{
index = idxBuffer[idxOffset + i];
vertex = idxVert[vtxOffset + index];
DrawTriangleVertex(vertex);
index = idxBuffer[idxOffset + i + 1];
vertex = idxVert[vtxOffset + index];
DrawTriangleVertex(vertex);
index = idxBuffer[idxOffset + i + 2];
vertex = idxVert[vtxOffset + index];
DrawTriangleVertex(vertex);
}
Rlgl.rlEnd();
}
public void Draw(Renderer renderer)
{
ImGui.Render();
RenderCommandLists(ImGui.GetDrawData());
}
private IntPtr _context;
private Texture2D _fontTexture;
private Vector2 _scaleFactor = Vector2.One;
}
}

View File

@@ -0,0 +1,47 @@
using System.Drawing;
using System.Numerics;
namespace DaggerFramework
{
public static class MathUtils
{
public static float Lerp(float a, float b, double t) => a + (b - a) * (float)t;
public static Color LerpColor(Color colorA, Color colorB, double t)
{
var r = (byte)Lerp(colorA.R, colorB.R, t);
var g = (byte)Lerp(colorA.G, colorB.G, t);
var b = (byte)Lerp(colorA.B, colorB.B, t);
var a = (byte)Lerp(colorA.A, colorB.A, t);
return new Color(r, g, b, a);
}
public static Vector2 LerpVector2(Vector2 v1, Vector2 v2, double t)
{
var x = Lerp(v1.X, v2.X, t);
var y = Lerp(v1.X, v2.Y, t);
return new Vector2(x, y);
}
public static float EaseOutBack(float x)
{
var c1 = 1.70158f;
var c3 = c1 + 1f;
return 1f + c3 * (float)Math.Pow(x - 1f, 3f) + c1 * (float)Math.Pow(x - 1, 2);
}
public static float EaseOutElastic(float x)
{
var c4 = (2f * (float)Math.PI) / 3f;
return x == 0
? 0
: x == 1
? 1
: (float)Math.Pow(2, -10 * x) * (float)Math.Sin((x * 10 - 0.75f) * c4) + 1;
}
}
}

28
DaggerFramework/TODO.md Executable file
View File

@@ -0,0 +1,28 @@
# RogueMine
## Engine
### Rendering
- ~~API for drawing textured quads~~
- Switch to custom rendering (Veldrid?)
### Audio
- 2D audio abstraction
- Integrate FMOD
### Misc
- Asset manager
- ~~Separate engine and game into separate projects~~
- Create a custom math library
- ~~Particle system~~
### Entity system
- ~~Layers (sorting mechanism)~~
## Input
- ~~Action system~~
### UI
- Basic containers
- MarginContainer
- XML layout file
- Interaction
- Callbacks

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,897 @@
/* ======================================================================================== */
/* FMOD Core API - DSP header file. */
/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2022. */
/* */
/* Use this header if you are wanting to develop your own DSP plugin to use with FMODs */
/* dsp system. With this header you can make your own DSP plugin that FMOD can */
/* register and use. See the documentation and examples on how to make a working plugin. */
/* */
/* For more detail visit: */
/* https://fmod.com/docs/2.02/api/plugin-api-dsp.html */
/* =========================================================================================*/
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace FMOD
{
[StructLayout(LayoutKind.Sequential)]
public struct DSP_BUFFER_ARRAY
{
public int numbuffers;
public int[] buffernumchannels;
public CHANNELMASK[] bufferchannelmask;
public IntPtr[] buffers;
public SPEAKERMODE speakermode;
}
public enum DSP_PROCESS_OPERATION
{
PROCESS_PERFORM = 0,
PROCESS_QUERY
}
[StructLayout(LayoutKind.Sequential)]
public struct COMPLEX
{
public float real;
public float imag;
}
public enum DSP_PAN_SURROUND_FLAGS
{
DEFAULT = 0,
ROTATION_NOT_BIASED = 1,
}
/*
DSP callbacks
*/
public delegate RESULT DSP_CREATE_CALLBACK (ref DSP_STATE dsp_state);
public delegate RESULT DSP_RELEASE_CALLBACK (ref DSP_STATE dsp_state);
public delegate RESULT DSP_RESET_CALLBACK (ref DSP_STATE dsp_state);
public delegate RESULT DSP_SETPOSITION_CALLBACK (ref DSP_STATE dsp_state, uint pos);
public delegate RESULT DSP_READ_CALLBACK (ref DSP_STATE dsp_state, IntPtr inbuffer, IntPtr outbuffer, uint length, int inchannels, ref int outchannels);
public delegate RESULT DSP_SHOULDIPROCESS_CALLBACK (ref DSP_STATE dsp_state, bool inputsidle, uint length, CHANNELMASK inmask, int inchannels, SPEAKERMODE speakermode);
public delegate RESULT DSP_PROCESS_CALLBACK (ref DSP_STATE dsp_state, uint length, ref DSP_BUFFER_ARRAY inbufferarray, ref DSP_BUFFER_ARRAY outbufferarray, bool inputsidle, DSP_PROCESS_OPERATION op);
public delegate RESULT DSP_SETPARAM_FLOAT_CALLBACK (ref DSP_STATE dsp_state, int index, float value);
public delegate RESULT DSP_SETPARAM_INT_CALLBACK (ref DSP_STATE dsp_state, int index, int value);
public delegate RESULT DSP_SETPARAM_BOOL_CALLBACK (ref DSP_STATE dsp_state, int index, bool value);
public delegate RESULT DSP_SETPARAM_DATA_CALLBACK (ref DSP_STATE dsp_state, int index, IntPtr data, uint length);
public delegate RESULT DSP_GETPARAM_FLOAT_CALLBACK (ref DSP_STATE dsp_state, int index, ref float value, IntPtr valuestr);
public delegate RESULT DSP_GETPARAM_INT_CALLBACK (ref DSP_STATE dsp_state, int index, ref int value, IntPtr valuestr);
public delegate RESULT DSP_GETPARAM_BOOL_CALLBACK (ref DSP_STATE dsp_state, int index, ref bool value, IntPtr valuestr);
public delegate RESULT DSP_GETPARAM_DATA_CALLBACK (ref DSP_STATE dsp_state, int index, ref IntPtr data, ref uint length, IntPtr valuestr);
public delegate RESULT DSP_SYSTEM_REGISTER_CALLBACK (ref DSP_STATE dsp_state);
public delegate RESULT DSP_SYSTEM_DEREGISTER_CALLBACK (ref DSP_STATE dsp_state);
public delegate RESULT DSP_SYSTEM_MIX_CALLBACK (ref DSP_STATE dsp_state, int stage);
/*
DSP functions
*/
public delegate IntPtr DSP_ALLOC_FUNC (uint size, MEMORY_TYPE type, IntPtr sourcestr);
public delegate IntPtr DSP_REALLOC_FUNC (IntPtr ptr, uint size, MEMORY_TYPE type, IntPtr sourcestr);
public delegate void DSP_FREE_FUNC (IntPtr ptr, MEMORY_TYPE type, IntPtr sourcestr);
public delegate void DSP_LOG_FUNC (DEBUG_FLAGS level, IntPtr file, int line, IntPtr function, IntPtr str);
public delegate RESULT DSP_GETSAMPLERATE_FUNC (ref DSP_STATE dsp_state, ref int rate);
public delegate RESULT DSP_GETBLOCKSIZE_FUNC (ref DSP_STATE dsp_state, ref uint blocksize);
public delegate RESULT DSP_GETSPEAKERMODE_FUNC (ref DSP_STATE dsp_state, ref int speakermode_mixer, ref int speakermode_output);
public delegate RESULT DSP_GETCLOCK_FUNC (ref DSP_STATE dsp_state, out ulong clock, out uint offset, out uint length);
public delegate RESULT DSP_GETLISTENERATTRIBUTES_FUNC (ref DSP_STATE dsp_state, ref int numlisteners, IntPtr attributes);
public delegate RESULT DSP_GETUSERDATA_FUNC (ref DSP_STATE dsp_state, out IntPtr userdata);
public delegate RESULT DSP_DFT_FFTREAL_FUNC (ref DSP_STATE dsp_state, int size, IntPtr signal, IntPtr dft, IntPtr window, int signalhop);
public delegate RESULT DSP_DFT_IFFTREAL_FUNC (ref DSP_STATE dsp_state, int size, IntPtr dft, IntPtr signal, IntPtr window, int signalhop);
public delegate RESULT DSP_PAN_SUMMONOMATRIX_FUNC (ref DSP_STATE dsp_state, int sourceSpeakerMode, float lowFrequencyGain, float overallGain, IntPtr matrix);
public delegate RESULT DSP_PAN_SUMSTEREOMATRIX_FUNC (ref DSP_STATE dsp_state, int sourceSpeakerMode, float pan, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
public delegate RESULT DSP_PAN_SUMSURROUNDMATRIX_FUNC (ref DSP_STATE dsp_state, int sourceSpeakerMode, int targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix, DSP_PAN_SURROUND_FLAGS flags);
public delegate RESULT DSP_PAN_SUMMONOTOSURROUNDMATRIX_FUNC (ref DSP_STATE dsp_state, int targetSpeakerMode, float direction, float extent, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
public delegate RESULT DSP_PAN_SUMSTEREOTOSURROUNDMATRIX_FUNC (ref DSP_STATE dsp_state, int targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
public delegate RESULT DSP_PAN_GETROLLOFFGAIN_FUNC (ref DSP_STATE dsp_state, DSP_PAN_3D_ROLLOFF_TYPE rolloff, float distance, float mindistance, float maxdistance, out float gain);
public enum DSP_TYPE : int
{
UNKNOWN,
MIXER,
OSCILLATOR,
LOWPASS,
ITLOWPASS,
HIGHPASS,
ECHO,
FADER,
FLANGE,
DISTORTION,
NORMALIZE,
LIMITER,
PARAMEQ,
PITCHSHIFT,
CHORUS,
VSTPLUGIN,
WINAMPPLUGIN,
ITECHO,
COMPRESSOR,
SFXREVERB,
LOWPASS_SIMPLE,
DELAY,
TREMOLO,
LADSPAPLUGIN,
SEND,
RETURN,
HIGHPASS_SIMPLE,
PAN,
THREE_EQ,
FFT,
LOUDNESS_METER,
ENVELOPEFOLLOWER,
CONVOLUTIONREVERB,
CHANNELMIX,
TRANSCEIVER,
OBJECTPAN,
MULTIBAND_EQ,
MAX
}
public enum DSP_PARAMETER_TYPE
{
FLOAT = 0,
INT,
BOOL,
DATA,
MAX
}
public enum DSP_PARAMETER_FLOAT_MAPPING_TYPE
{
DSP_PARAMETER_FLOAT_MAPPING_TYPE_LINEAR = 0,
DSP_PARAMETER_FLOAT_MAPPING_TYPE_AUTO,
DSP_PARAMETER_FLOAT_MAPPING_TYPE_PIECEWISE_LINEAR,
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR
{
public int numpoints;
public IntPtr pointparamvalues;
public IntPtr pointpositions;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_FLOAT_MAPPING
{
public DSP_PARAMETER_FLOAT_MAPPING_TYPE type;
public DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR piecewiselinearmapping;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_DESC_FLOAT
{
public float min;
public float max;
public float defaultval;
public DSP_PARAMETER_FLOAT_MAPPING mapping;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_DESC_INT
{
public int min;
public int max;
public int defaultval;
public bool goestoinf;
public IntPtr valuenames;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_DESC_BOOL
{
public bool defaultval;
public IntPtr valuenames;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_DESC_DATA
{
public int datatype;
}
[StructLayout(LayoutKind.Explicit)]
public struct DSP_PARAMETER_DESC_UNION
{
[FieldOffset(0)]
public DSP_PARAMETER_DESC_FLOAT floatdesc;
[FieldOffset(0)]
public DSP_PARAMETER_DESC_INT intdesc;
[FieldOffset(0)]
public DSP_PARAMETER_DESC_BOOL booldesc;
[FieldOffset(0)]
public DSP_PARAMETER_DESC_DATA datadesc;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_DESC
{
public DSP_PARAMETER_TYPE type;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] label;
public string description;
public DSP_PARAMETER_DESC_UNION desc;
}
public enum DSP_PARAMETER_DATA_TYPE
{
DSP_PARAMETER_DATA_TYPE_USER = 0,
DSP_PARAMETER_DATA_TYPE_OVERALLGAIN = -1,
DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES = -2,
DSP_PARAMETER_DATA_TYPE_SIDECHAIN = -3,
DSP_PARAMETER_DATA_TYPE_FFT = -4,
DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES_MULTI = -5,
DSP_PARAMETER_DATA_TYPE_ATTENUATION_RANGE = -6
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_OVERALLGAIN
{
public float linear_gain;
public float linear_gain_additive;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_3DATTRIBUTES
{
public ATTRIBUTES_3D relative;
public ATTRIBUTES_3D absolute;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_3DATTRIBUTES_MULTI
{
public int numlisteners;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public ATTRIBUTES_3D[] relative;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public float[] weight;
public ATTRIBUTES_3D absolute;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_SIDECHAIN
{
public int sidechainenable;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_FFT
{
public int length;
public int numchannels;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=32)]
private IntPtr[] spectrum_internal;
public float[][] spectrum
{
get
{
var buffer = new float[numchannels][];
for (int i = 0; i < numchannels; ++i)
{
buffer[i] = new float[length];
Marshal.Copy(spectrum_internal[i], buffer[i], 0, length);
}
return buffer;
}
}
public void getSpectrum(ref float[][] buffer)
{
int bufferLength = Math.Min(buffer.Length, numchannels);
for (int i = 0; i < bufferLength; ++i)
{
getSpectrum(i, ref buffer[i]);
}
}
public void getSpectrum(int channel, ref float[] buffer)
{
int bufferLength = Math.Min(buffer.Length, length);
Marshal.Copy(spectrum_internal[channel], buffer, 0, bufferLength);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_LOUDNESS_METER_INFO_TYPE
{
public float momentaryloudness;
public float shorttermloudness;
public float integratedloudness;
public float loudness10thpercentile;
public float loudness95thpercentile;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 66)]
public float[] loudnesshistogram;
public float maxtruepeak;
public float maxmomentaryloudness;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_LOUDNESS_METER_WEIGHTING_TYPE
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public float[] channelweight;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_PARAMETER_ATTENUATION_RANGE
{
public float min;
public float max;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_DESCRIPTION
{
public uint pluginsdkversion;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] name;
public uint version;
public int numinputbuffers;
public int numoutputbuffers;
public DSP_CREATE_CALLBACK create;
public DSP_RELEASE_CALLBACK release;
public DSP_RESET_CALLBACK reset;
public DSP_READ_CALLBACK read;
public DSP_PROCESS_CALLBACK process;
public DSP_SETPOSITION_CALLBACK setposition;
public int numparameters;
public IntPtr paramdesc;
public DSP_SETPARAM_FLOAT_CALLBACK setparameterfloat;
public DSP_SETPARAM_INT_CALLBACK setparameterint;
public DSP_SETPARAM_BOOL_CALLBACK setparameterbool;
public DSP_SETPARAM_DATA_CALLBACK setparameterdata;
public DSP_GETPARAM_FLOAT_CALLBACK getparameterfloat;
public DSP_GETPARAM_INT_CALLBACK getparameterint;
public DSP_GETPARAM_BOOL_CALLBACK getparameterbool;
public DSP_GETPARAM_DATA_CALLBACK getparameterdata;
public DSP_SHOULDIPROCESS_CALLBACK shouldiprocess;
public IntPtr userdata;
public DSP_SYSTEM_REGISTER_CALLBACK sys_register;
public DSP_SYSTEM_DEREGISTER_CALLBACK sys_deregister;
public DSP_SYSTEM_MIX_CALLBACK sys_mix;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_STATE_DFT_FUNCTIONS
{
public DSP_DFT_FFTREAL_FUNC fftreal;
public DSP_DFT_IFFTREAL_FUNC inversefftreal;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_STATE_PAN_FUNCTIONS
{
public DSP_PAN_SUMMONOMATRIX_FUNC summonomatrix;
public DSP_PAN_SUMSTEREOMATRIX_FUNC sumstereomatrix;
public DSP_PAN_SUMSURROUNDMATRIX_FUNC sumsurroundmatrix;
public DSP_PAN_SUMMONOTOSURROUNDMATRIX_FUNC summonotosurroundmatrix;
public DSP_PAN_SUMSTEREOTOSURROUNDMATRIX_FUNC sumstereotosurroundmatrix;
public DSP_PAN_GETROLLOFFGAIN_FUNC getrolloffgain;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_STATE_FUNCTIONS
{
public DSP_ALLOC_FUNC alloc;
public DSP_REALLOC_FUNC realloc;
public DSP_FREE_FUNC free;
public DSP_GETSAMPLERATE_FUNC getsamplerate;
public DSP_GETBLOCKSIZE_FUNC getblocksize;
public IntPtr dft;
public IntPtr pan;
public DSP_GETSPEAKERMODE_FUNC getspeakermode;
public DSP_GETCLOCK_FUNC getclock;
public DSP_GETLISTENERATTRIBUTES_FUNC getlistenerattributes;
public DSP_LOG_FUNC log;
public DSP_GETUSERDATA_FUNC getuserdata;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_STATE
{
public IntPtr instance;
public IntPtr plugindata;
public uint channelmask;
public int source_speakermode;
public IntPtr sidechaindata;
public int sidechainchannels;
public IntPtr functions;
public int systemobject;
}
[StructLayout(LayoutKind.Sequential)]
public struct DSP_METERING_INFO
{
public int numsamples;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public float[] peaklevel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public float[] rmslevel;
public short numchannels;
}
/*
==============================================================================================================
FMOD built in effect parameters.
Use DSP::setParameter with these enums for the 'index' parameter.
==============================================================================================================
*/
public enum DSP_OSCILLATOR : int
{
TYPE,
RATE
}
public enum DSP_LOWPASS : int
{
CUTOFF,
RESONANCE
}
public enum DSP_ITLOWPASS : int
{
CUTOFF,
RESONANCE
}
public enum DSP_HIGHPASS : int
{
CUTOFF,
RESONANCE
}
public enum DSP_ECHO : int
{
DELAY,
FEEDBACK,
DRYLEVEL,
WETLEVEL
}
public enum DSP_FADER : int
{
GAIN,
OVERALL_GAIN,
}
public enum DSP_DELAY : int
{
CH0,
CH1,
CH2,
CH3,
CH4,
CH5,
CH6,
CH7,
CH8,
CH9,
CH10,
CH11,
CH12,
CH13,
CH14,
CH15,
MAXDELAY,
}
public enum DSP_FLANGE : int
{
MIX,
DEPTH,
RATE
}
public enum DSP_TREMOLO : int
{
FREQUENCY,
DEPTH,
SHAPE,
SKEW,
DUTY,
SQUARE,
PHASE,
SPREAD
}
public enum DSP_DISTORTION : int
{
LEVEL
}
public enum DSP_NORMALIZE : int
{
FADETIME,
THRESHOLD,
MAXAMP
}
public enum DSP_LIMITER : int
{
RELEASETIME,
CEILING,
MAXIMIZERGAIN,
MODE,
}
public enum DSP_PARAMEQ : int
{
CENTER,
BANDWIDTH,
GAIN
}
public enum DSP_MULTIBAND_EQ : int
{
A_FILTER,
A_FREQUENCY,
A_Q,
A_GAIN,
B_FILTER,
B_FREQUENCY,
B_Q,
B_GAIN,
C_FILTER,
C_FREQUENCY,
C_Q,
C_GAIN,
D_FILTER,
D_FREQUENCY,
D_Q,
D_GAIN,
E_FILTER,
E_FREQUENCY,
E_Q,
E_GAIN,
}
public enum DSP_MULTIBAND_EQ_FILTER_TYPE : int
{
DISABLED,
LOWPASS_12DB,
LOWPASS_24DB,
LOWPASS_48DB,
HIGHPASS_12DB,
HIGHPASS_24DB,
HIGHPASS_48DB,
LOWSHELF,
HIGHSHELF,
PEAKING,
BANDPASS,
NOTCH,
ALLPASS,
}
public enum DSP_PITCHSHIFT : int
{
PITCH,
FFTSIZE,
OVERLAP,
MAXCHANNELS
}
public enum DSP_CHORUS : int
{
MIX,
RATE,
DEPTH,
}
public enum DSP_ITECHO : int
{
WETDRYMIX,
FEEDBACK,
LEFTDELAY,
RIGHTDELAY,
PANDELAY
}
public enum DSP_COMPRESSOR : int
{
THRESHOLD,
RATIO,
ATTACK,
RELEASE,
GAINMAKEUP,
USESIDECHAIN,
LINKED
}
public enum DSP_SFXREVERB : int
{
DECAYTIME,
EARLYDELAY,
LATEDELAY,
HFREFERENCE,
HFDECAYRATIO,
DIFFUSION,
DENSITY,
LOWSHELFFREQUENCY,
LOWSHELFGAIN,
HIGHCUT,
EARLYLATEMIX,
WETLEVEL,
DRYLEVEL
}
public enum DSP_LOWPASS_SIMPLE : int
{
CUTOFF
}
public enum DSP_SEND : int
{
RETURNID,
LEVEL,
}
public enum DSP_RETURN : int
{
ID,
INPUT_SPEAKER_MODE
}
public enum DSP_HIGHPASS_SIMPLE : int
{
CUTOFF
}
public enum DSP_PAN_2D_STEREO_MODE_TYPE : int
{
DISTRIBUTED,
DISCRETE
}
public enum DSP_PAN_MODE_TYPE : int
{
MONO,
STEREO,
SURROUND
}
public enum DSP_PAN_3D_ROLLOFF_TYPE : int
{
LINEARSQUARED,
LINEAR,
INVERSE,
INVERSETAPERED,
CUSTOM
}
public enum DSP_PAN_3D_EXTENT_MODE_TYPE : int
{
AUTO,
USER,
OFF
}
public enum DSP_PAN : int
{
MODE,
_2D_STEREO_POSITION,
_2D_DIRECTION,
_2D_EXTENT,
_2D_ROTATION,
_2D_LFE_LEVEL,
_2D_STEREO_MODE,
_2D_STEREO_SEPARATION,
_2D_STEREO_AXIS,
ENABLED_SPEAKERS,
_3D_POSITION,
_3D_ROLLOFF,
_3D_MIN_DISTANCE,
_3D_MAX_DISTANCE,
_3D_EXTENT_MODE,
_3D_SOUND_SIZE,
_3D_MIN_EXTENT,
_3D_PAN_BLEND,
LFE_UPMIX_ENABLED,
OVERALL_GAIN,
SURROUND_SPEAKER_MODE,
_2D_HEIGHT_BLEND,
ATTENUATION_RANGE,
OVERRIDE_RANGE
}
public enum DSP_THREE_EQ_CROSSOVERSLOPE_TYPE : int
{
_12DB,
_24DB,
_48DB
}
public enum DSP_THREE_EQ : int
{
LOWGAIN,
MIDGAIN,
HIGHGAIN,
LOWCROSSOVER,
HIGHCROSSOVER,
CROSSOVERSLOPE
}
public enum DSP_FFT_WINDOW : int
{
RECT,
TRIANGLE,
HAMMING,
HANNING,
BLACKMAN,
BLACKMANHARRIS
}
public enum DSP_FFT : int
{
WINDOWSIZE,
WINDOWTYPE,
SPECTRUMDATA,
DOMINANT_FREQ
}
public enum DSP_LOUDNESS_METER : int
{
STATE,
WEIGHTING,
INFO
}
public enum DSP_LOUDNESS_METER_STATE_TYPE : int
{
RESET_INTEGRATED = -3,
RESET_MAXPEAK = -2,
RESET_ALL = -1,
PAUSED = 0,
ANALYZING = 1
}
public enum DSP_ENVELOPEFOLLOWER : int
{
ATTACK,
RELEASE,
ENVELOPE,
USESIDECHAIN
}
public enum DSP_CONVOLUTION_REVERB : int
{
IR,
WET,
DRY,
LINKED
}
public enum DSP_CHANNELMIX_OUTPUT : int
{
DEFAULT,
ALLMONO,
ALLSTEREO,
ALLQUAD,
ALL5POINT1,
ALL7POINT1,
ALLLFE,
ALL7POINT1POINT4
}
public enum DSP_CHANNELMIX : int
{
OUTPUTGROUPING,
GAIN_CH0,
GAIN_CH1,
GAIN_CH2,
GAIN_CH3,
GAIN_CH4,
GAIN_CH5,
GAIN_CH6,
GAIN_CH7,
GAIN_CH8,
GAIN_CH9,
GAIN_CH10,
GAIN_CH11,
GAIN_CH12,
GAIN_CH13,
GAIN_CH14,
GAIN_CH15,
GAIN_CH16,
GAIN_CH17,
GAIN_CH18,
GAIN_CH19,
GAIN_CH20,
GAIN_CH21,
GAIN_CH22,
GAIN_CH23,
GAIN_CH24,
GAIN_CH25,
GAIN_CH26,
GAIN_CH27,
GAIN_CH28,
GAIN_CH29,
GAIN_CH30,
GAIN_CH31,
OUTPUT_CH0,
OUTPUT_CH1,
OUTPUT_CH2,
OUTPUT_CH3,
OUTPUT_CH4,
OUTPUT_CH5,
OUTPUT_CH6,
OUTPUT_CH7,
OUTPUT_CH8,
OUTPUT_CH9,
OUTPUT_CH10,
OUTPUT_CH11,
OUTPUT_CH12,
OUTPUT_CH13,
OUTPUT_CH14,
OUTPUT_CH15,
OUTPUT_CH16,
OUTPUT_CH17,
OUTPUT_CH18,
OUTPUT_CH19,
OUTPUT_CH20,
OUTPUT_CH21,
OUTPUT_CH22,
OUTPUT_CH23,
OUTPUT_CH24,
OUTPUT_CH25,
OUTPUT_CH26,
OUTPUT_CH27,
OUTPUT_CH28,
OUTPUT_CH29,
OUTPUT_CH30,
OUTPUT_CH31,
}
public enum DSP_TRANSCEIVER_SPEAKERMODE : int
{
AUTO = -1,
MONO = 0,
STEREO,
SURROUND,
}
public enum DSP_TRANSCEIVER : int
{
TRANSMIT,
GAIN,
CHANNEL,
TRANSMITSPEAKERMODE
}
public enum DSP_OBJECTPAN : int
{
_3D_POSITION,
_3D_ROLLOFF,
_3D_MIN_DISTANCE,
_3D_MAX_DISTANCE,
_3D_EXTENT_MODE,
_3D_SOUND_SIZE,
_3D_MIN_EXTENT,
OVERALL_GAIN,
OUTPUTGAIN,
ATTENUATION_RANGE,
OVERRIDE_RANGE
}
}

View File

@@ -0,0 +1,106 @@
/* ============================================================================================== */
/* FMOD Core / Studio API - Error string header file. */
/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2022. */
/* */
/* Use this header if you want to store or display a string version / english explanation */
/* of the FMOD error codes. */
/* */
/* For more detail visit: */
/* https://fmod.com/docs/2.02/api/core-api-common.html#fmod_result */
/* =============================================================================================== */
namespace FMOD
{
public class Error
{
public static string String(FMOD.RESULT errcode)
{
switch (errcode)
{
case FMOD.RESULT.OK: return "No errors.";
case FMOD.RESULT.ERR_BADCOMMAND: return "Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound).";
case FMOD.RESULT.ERR_CHANNEL_ALLOC: return "Error trying to allocate a channel.";
case FMOD.RESULT.ERR_CHANNEL_STOLEN: return "The specified channel has been reused to play another sound.";
case FMOD.RESULT.ERR_DMA: return "DMA Failure. See debug output for more information.";
case FMOD.RESULT.ERR_DSP_CONNECTION: return "DSP connection error. Connection possibly caused a cyclic dependency or connected dsps with incompatible buffer counts.";
case FMOD.RESULT.ERR_DSP_DONTPROCESS: return "DSP return code from a DSP process query callback. Tells mixer not to call the process callback and therefore not consume CPU. Use this to optimize the DSP graph.";
case FMOD.RESULT.ERR_DSP_FORMAT: return "DSP Format error. A DSP unit may have attempted to connect to this network with the wrong format, or a matrix may have been set with the wrong size if the target unit has a specified channel map.";
case FMOD.RESULT.ERR_DSP_INUSE: return "DSP is already in the mixer's DSP network. It must be removed before being reinserted or released.";
case FMOD.RESULT.ERR_DSP_NOTFOUND: return "DSP connection error. Couldn't find the DSP unit specified.";
case FMOD.RESULT.ERR_DSP_RESERVED: return "DSP operation error. Cannot perform operation on this DSP as it is reserved by the system.";
case FMOD.RESULT.ERR_DSP_SILENCE: return "DSP return code from a DSP process query callback. Tells mixer silence would be produced from read, so go idle and not consume CPU. Use this to optimize the DSP graph.";
case FMOD.RESULT.ERR_DSP_TYPE: return "DSP operation cannot be performed on a DSP of this type.";
case FMOD.RESULT.ERR_FILE_BAD: return "Error loading file.";
case FMOD.RESULT.ERR_FILE_COULDNOTSEEK: return "Couldn't perform seek operation. This is a limitation of the medium (ie netstreams) or the file format.";
case FMOD.RESULT.ERR_FILE_DISKEJECTED: return "Media was ejected while reading.";
case FMOD.RESULT.ERR_FILE_EOF: return "End of file unexpectedly reached while trying to read essential data (truncated?).";
case FMOD.RESULT.ERR_FILE_ENDOFDATA: return "End of current chunk reached while trying to read data.";
case FMOD.RESULT.ERR_FILE_NOTFOUND: return "File not found.";
case FMOD.RESULT.ERR_FORMAT: return "Unsupported file or audio format.";
case FMOD.RESULT.ERR_HEADER_MISMATCH: return "There is a version mismatch between the FMOD header and either the FMOD Studio library or the FMOD Low Level library.";
case FMOD.RESULT.ERR_HTTP: return "A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere.";
case FMOD.RESULT.ERR_HTTP_ACCESS: return "The specified resource requires authentication or is forbidden.";
case FMOD.RESULT.ERR_HTTP_PROXY_AUTH: return "Proxy authentication is required to access the specified resource.";
case FMOD.RESULT.ERR_HTTP_SERVER_ERROR: return "A HTTP server error occurred.";
case FMOD.RESULT.ERR_HTTP_TIMEOUT: return "The HTTP request timed out.";
case FMOD.RESULT.ERR_INITIALIZATION: return "FMOD was not initialized correctly to support this function.";
case FMOD.RESULT.ERR_INITIALIZED: return "Cannot call this command after System::init.";
case FMOD.RESULT.ERR_INTERNAL: return "An error occurred that wasn't supposed to. Contact support.";
case FMOD.RESULT.ERR_INVALID_FLOAT: return "Value passed in was a NaN, Inf or denormalized float.";
case FMOD.RESULT.ERR_INVALID_HANDLE: return "An invalid object handle was used.";
case FMOD.RESULT.ERR_INVALID_PARAM: return "An invalid parameter was passed to this function.";
case FMOD.RESULT.ERR_INVALID_POSITION: return "An invalid seek position was passed to this function.";
case FMOD.RESULT.ERR_INVALID_SPEAKER: return "An invalid speaker was passed to this function based on the current speaker mode.";
case FMOD.RESULT.ERR_INVALID_SYNCPOINT: return "The syncpoint did not come from this sound handle.";
case FMOD.RESULT.ERR_INVALID_THREAD: return "Tried to call a function on a thread that is not supported.";
case FMOD.RESULT.ERR_INVALID_VECTOR: return "The vectors passed in are not unit length, or perpendicular.";
case FMOD.RESULT.ERR_MAXAUDIBLE: return "Reached maximum audible playback count for this sound's soundgroup.";
case FMOD.RESULT.ERR_MEMORY: return "Not enough memory or resources.";
case FMOD.RESULT.ERR_MEMORY_CANTPOINT: return "Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used.";
case FMOD.RESULT.ERR_NEEDS3D: return "Tried to call a command on a 2d sound when the command was meant for 3d sound.";
case FMOD.RESULT.ERR_NEEDSHARDWARE: return "Tried to use a feature that requires hardware support.";
case FMOD.RESULT.ERR_NET_CONNECT: return "Couldn't connect to the specified host.";
case FMOD.RESULT.ERR_NET_SOCKET_ERROR: return "A socket error occurred. This is a catch-all for socket-related errors not listed elsewhere.";
case FMOD.RESULT.ERR_NET_URL: return "The specified URL couldn't be resolved.";
case FMOD.RESULT.ERR_NET_WOULD_BLOCK: return "Operation on a non-blocking socket could not complete immediately.";
case FMOD.RESULT.ERR_NOTREADY: return "Operation could not be performed because specified sound/DSP connection is not ready.";
case FMOD.RESULT.ERR_OUTPUT_ALLOCATED: return "Error initializing output device, but more specifically, the output device is already in use and cannot be reused.";
case FMOD.RESULT.ERR_OUTPUT_CREATEBUFFER: return "Error creating hardware sound buffer.";
case FMOD.RESULT.ERR_OUTPUT_DRIVERCALL: return "A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted.";
case FMOD.RESULT.ERR_OUTPUT_FORMAT: return "Soundcard does not support the specified format.";
case FMOD.RESULT.ERR_OUTPUT_INIT: return "Error initializing output device.";
case FMOD.RESULT.ERR_OUTPUT_NODRIVERS: return "The output device has no drivers installed. If pre-init, FMOD_OUTPUT_NOSOUND is selected as the output mode. If post-init, the function just fails.";
case FMOD.RESULT.ERR_PLUGIN: return "An unspecified error has been returned from a plugin.";
case FMOD.RESULT.ERR_PLUGIN_MISSING: return "A requested output, dsp unit type or codec was not available.";
case FMOD.RESULT.ERR_PLUGIN_RESOURCE: return "A resource that the plugin requires cannot be allocated or found. (ie the DLS file for MIDI playback)";
case FMOD.RESULT.ERR_PLUGIN_VERSION: return "A plugin was built with an unsupported SDK version.";
case FMOD.RESULT.ERR_RECORD: return "An error occurred trying to initialize the recording device.";
case FMOD.RESULT.ERR_REVERB_CHANNELGROUP: return "Reverb properties cannot be set on this channel because a parent channelgroup owns the reverb connection.";
case FMOD.RESULT.ERR_REVERB_INSTANCE: return "Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesn't exist.";
case FMOD.RESULT.ERR_SUBSOUNDS: return "The error occurred because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have. The operation may also not be able to be performed on a parent sound.";
case FMOD.RESULT.ERR_SUBSOUND_ALLOCATED: return "This subsound is already being used by another sound, you cannot have more than one parent to a sound. Null out the other parent's entry first.";
case FMOD.RESULT.ERR_SUBSOUND_CANTMOVE: return "Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file.";
case FMOD.RESULT.ERR_TAGNOTFOUND: return "The specified tag could not be found or there are no tags.";
case FMOD.RESULT.ERR_TOOMANYCHANNELS: return "The sound created exceeds the allowable input channel count. This can be increased using the 'maxinputchannels' parameter in System::setSoftwareFormat.";
case FMOD.RESULT.ERR_TRUNCATED: return "The retrieved string is too long to fit in the supplied buffer and has been truncated.";
case FMOD.RESULT.ERR_UNIMPLEMENTED: return "Something in FMOD hasn't been implemented when it should be! contact support!";
case FMOD.RESULT.ERR_UNINITIALIZED: return "This command failed because System::init or System::setDriver was not called.";
case FMOD.RESULT.ERR_UNSUPPORTED: return "A command issued was not supported by this object. Possibly a plugin without certain callbacks specified.";
case FMOD.RESULT.ERR_VERSION: return "The version number of this file format is not supported.";
case FMOD.RESULT.ERR_EVENT_ALREADY_LOADED: return "The specified bank has already been loaded.";
case FMOD.RESULT.ERR_EVENT_LIVEUPDATE_BUSY: return "The live update connection failed due to the game already being connected.";
case FMOD.RESULT.ERR_EVENT_LIVEUPDATE_MISMATCH: return "The live update connection failed due to the game data being out of sync with the tool.";
case FMOD.RESULT.ERR_EVENT_LIVEUPDATE_TIMEOUT: return "The live update connection timed out.";
case FMOD.RESULT.ERR_EVENT_NOTFOUND: return "The requested event, bus or vca could not be found.";
case FMOD.RESULT.ERR_STUDIO_UNINITIALIZED: return "The Studio::System object is not yet initialized.";
case FMOD.RESULT.ERR_STUDIO_NOT_LOADED: return "The specified resource is not loaded, so it can't be unloaded.";
case FMOD.RESULT.ERR_INVALID_STRING: return "An invalid string was passed to this function.";
case FMOD.RESULT.ERR_ALREADY_LOCKED: return "The specified resource is already locked.";
case FMOD.RESULT.ERR_NOT_LOCKED: return "The specified resource is not locked, so it can't be unlocked.";
case FMOD.RESULT.ERR_RECORD_DISCONNECTED: return "The specified recording driver has been disconnected.";
case FMOD.RESULT.ERR_TOOMANYSAMPLES: return "The length provided exceed the allowable limit.";
default: return "Unknown error.";
}
}
}
}

File diff suppressed because it is too large Load Diff