// SPDX-License-Identifier: Unlicense

#ifndef TYPE_H
#define TYPE_H

#include "typedefs.h"

#include <string>
#include <vector>

enum struct FullscreenMode : u8
{
  windowed,
  borderless,
  //fullscreen // not supported. vst plugin ui does not show.
};

enum struct ScalingMode : i8
{
  HorPlus = 0,
  Strech = 1
};

#if !defined(PLATFORM_EMSCRIPTEN) && !defined(PLATFORM_QUEST_3)
enum struct VSyncMode : i8
{
  noVSync = 0,
  VSync = 1,
#ifdef SHR3D_WINDOW_SDL
  AdaptiveVSync = -1
#endif // SHR3D_WINDOW_SDL
};
#endif // !PLATFORM_EMSCRIPTEN && !PLATFORM_QUEST_3

enum struct AudioSystem : u8
{
#ifdef SHR3D_AUDIO_AAUDIO
  AAudio,
#endif // SHR3D_AUDIO_AAUDIO
#ifdef SHR3D_AUDIO_ASIO
  ASIO,
#endif // SHR3D_AUDIO_ASIO
#ifdef SHR3D_AUDIO_JACK
  JACK,
#endif // SHR3D_AUDIO_JACK
#ifdef SHR3D_AUDIO_PIPEWIRE
  PipeWire,
#endif // SHR3D_AUDIO_PIPEWIRE
#ifdef SHR3D_AUDIO_SDL
  SDL,
#endif // SHR3D_AUDIO_SDL
#ifdef SHR3D_AUDIO_SUPERPOWERED
  Superpowered,
#endif // SHR3D_AUDIO_SUPERPOWERED
#ifdef SHR3D_AUDIO_WASAPI
  WASAPI,
#endif // SHR3D_AUDIO_WASAPI
#ifdef SHR3D_AUDIO_WEBAUDIO
  WebAudio,
#endif // SHR3D_AUDIO_WEBAUDIO  
  COUNT
};

#ifdef SHR3D_AUDIO_AAUDIO
enum struct AAudioPerformanceMode
{
  None,
  PowerSaving,
  LowLatency
};
#endif // SHR3D_AUDIO_AAUDIO

enum struct BackupMode : u8
{
  off,
  onceOnStart
};

enum struct InstallMode : u8
{
  showInstaller,
  continueWithoutSaving,
  installed
};

enum struct Instrument : u8
{
  LeadGuitar,
  RhythmGuitar,
  BassGuitar
};

enum struct EndOfSong : u8
{
  doNothing,
  openMenu,
  loopSong
};

enum struct NoteDetectionSource : u8
{
  pickup,
#ifdef SHR3D_MIDI
  midiDevice,
#endif // SHR3D_MIDI
  midiPlugin
};

enum struct NoteShape : u8
{
  hex,
  rect
};

enum struct NoteSymbols : u8
{
  none,
  fretMute,
  hammerOn,
  harmonic,
  palmMute,
  pinchHarmonic,
  pop,
  pullOff,
  slap,
  tap,
  slimX,
  slimEye,
  triangleDown,
  triangleUp,
  wideX,
  wideV,
  wideUpsideV,
  wideOffsetV,
  wideEye,
  sineRight,
  sineLeft,
  COUNT
};

enum struct SongFormat : u8
{
  sng,
  xml,
};

enum struct SongSortMode : u8
{
  unsorted,
  tuning,
  songName,
  artistName,
  albumName,
  year,
};

enum struct CameraMode : u8
{
  fixed,
  parallax,
#ifdef SHR3D_OPENXR_PCVR
  pcVrParallax,
#endif // SHR3D_OPENXR_PCVR
};

#if defined(SHR3D_HUD_DEVELOPMENT) || defined(SHR3D_RENDERER_DEVELOPMENT)
enum struct Renderer : i8
{
  production,
  development
};
#endif // SHR3D_HUD_DEVELOPMENT || defined(SHR3D_RENDERER_DEVELOPMENT

enum struct MidiNote : u8
{
  C_0 = 12,        //    16.352Hz
  C_sharp_0 = 13,  //    17.324Hz
  D_0 = 14,        //    18.354Hz
  D_sharp_0 = 15,  //    19.445Hz
  E_0 = 16,        //    20.602Hz
  F_0 = 17,        //    21.827Hz
  F_sharp_0 = 18,  //    23.125Hz
  G_0 = 19,        //    24.500Hz
  G_sharp_0 = 20,  //    25.957Hz
  A_0 = 21,        //    27.500Hz
  A_sharp_0 = 22,  //    29.135Hz
  B_0 = 23,        //    30.868Hz
  C_1 = 24,        //    32.703Hz
  C_sharp_1 = 25,  //    34.648Hz
  D_1 = 26,        //    36.708Hz
  D_sharp_1 = 27,  //    38.891Hz
  E_1 = 28,        //    41.203Hz
  F_1 = 29,        //    43.654Hz
  F_sharp_1 = 30,  //    46.249Hz
  G_1 = 31,        //    48.999Hz
  G_sharp_1 = 32,  //    51.913Hz
  A_1 = 33,        //    55.000Hz
  A_sharp_1 = 34,  //    58.270Hz
  B_1 = 35,        //    61.735Hz
  C_2 = 36,        //    65.406Hz
  C_sharp_2 = 37,  //    69.296Hz
  D_2 = 38,        //    73.416Hz
  D_sharp_2 = 39,  //    77.782Hz
  E_2 = 40,        //    82.407Hz
  F_2 = 41,        //    87.307Hz
  F_sharp_2 = 42,  //    92.499Hz
  G_2 = 43,        //    97.999Hz
  G_sharp_2 = 44,  //   103.826Hz
  A_2 = 45,        //   110.000Hz
  A_sharp_2 = 46,  //   116.541Hz
  B_2 = 47,        //   123.471Hz
  C_3 = 48,        //   130.813Hz
  C_sharp_3 = 49,  //   138.591Hz
  D_3 = 50,        //   146.832Hz
  D_sharp_3 = 51,  //   155.563Hz
  E_3 = 52,        //   164.814Hz
  F_3 = 53,        //   174.614Hz
  F_sharp_3 = 54,  //   184.997Hz
  G_3 = 55,        //   195.998Hz
  G_sharp_3 = 56,  //   207.652Hz
  A_3 = 57,        //   220.000Hz
  A_sharp_3 = 58,  //   233.082Hz
  B_3 = 59,        //   246.942Hz
  C_4 = 60,        //   261.626Hz
  C_sharp_4 = 61,  //   277.183Hz
  D_4 = 62,        //   293.665Hz
  D_sharp_4 = 63,  //   311.127Hz
  E_4 = 64,        //   329.628Hz
  F_4 = 65,        //   349.228Hz
  F_sharp_4 = 66,  //   369.994Hz
  G_4 = 67,        //   391.995Hz
  G_sharp_4 = 68,  //   415.305Hz
  A_4 = 69,        //   440.000Hz
  A_sharp_4 = 70,  //   466.164Hz
  B_4 = 71,        //   493.883Hz
  C_5 = 72,        //   523.251Hz
  C_sharp_5 = 73,  //   554.365Hz
  D_5 = 74,        //   587.330Hz
  D_sharp_5 = 75,  //   622.254Hz
  E_5 = 76,        //   659.255Hz
  F_5 = 77,        //   698.456Hz
  F_sharp_5 = 78,  //   739.989Hz
  G_5 = 79,        //   783.991Hz
  G_sharp_5 = 80,  //   830.609Hz
  A_5 = 81,        //   880.000Hz
  A_sharp_5 = 82,  //   932.328Hz
  B_5 = 83,        //   987.767Hz
  C_6 = 84,        //  1046.502Hz
  C_sharp_6 = 85,  //  1108.731Hz
  D_6 = 86,        //  1174.659Hz
  D_sharp_6 = 87,  //  1244.508Hz
  E_6 = 88,        //  1318.510Hz
  F_6 = 89,        //  1396.913Hz
  F_sharp_6 = 90,  //  1479.978Hz
  G_6 = 91,        //  1567.982Hz
  G_sharp_6 = 92,  //  1661.219Hz
  A_6 = 93,        //  1760.000Hz
  A_sharp_6 = 94,  //  1864.655Hz
  B_6 = 95,        //  1975.533Hz
  C_7 = 96,        //  2093.005Hz
  C_sharp_7 = 97,  //  2217.461Hz
  D_7 = 98,        //  2349.318Hz
  D_sharp_7 = 99,  //  2489.016Hz
  E_7 = 100,       //  2637.020Hz
  F_7 = 101,       //  2793.826Hz
  F_sharp_7 = 102, //  2959.955Hz
  G_7 = 103,       //  3135.963Hz
  G_sharp_7 = 104, //  3322.438Hz
  A_7 = 105,       //  3520.000Hz
  A_sharp_7 = 106, //  3729.310Hz
  B_7 = 107,       //  3951.066Hz
  C_8 = 108,       //  4186.009Hz
  C_sharp_8 = 109, //  4434.922Hz
  D_8 = 110,       //  4698.636Hz
  D_sharp_8 = 111, //  4978.032Hz
  E_8 = 112,       //  5274.041Hz
  F_8 = 113,       //  5587.652Hz
  F_sharp_8 = 114, //  5919.911Hz
  G_8 = 115,       //  6271.927Hz
  G_sharp_8 = 116, //  6644.875Hz
  A_8 = 117,       //  7040.000Hz
  A_sharp_8 = 118, //  7458.620Hz
  B_8 = 119,       //  7902.133Hz
  C_9 = 120,       //  8372.018Hz
  C_sharp_9 = 121, //  8869.844Hz
  D_9 = 122,       //  9397.273Hz
  D_sharp_9 = 123, //  9956.063Hz
  E_9 = 124,       // 10548.080Hz
  F_9 = 125,       // 11175.300Hz
  F_sharp_9 = 126, // 11839.820Hz
  G_9 = 127,       // 12543.850Hz
  COUNT = 128
};

#ifdef SHR3D_MIDI
enum struct MidiNoteMode : u8
{
  press,
  toggle,
  analog
};
#endif // SHR3D_MIDI

enum struct MetronomeSide : u8
{
  left,
  right,
  stereo
};

enum struct MusicDoubleBufferStatus : u8
{
  inital = 0b0,
  DataInNonStreched0 = 0b10,
  DataInNonStreched1 = 0b11,
  DataInNonStreched0Delete1 = 0b100,
  DataInNonStreched1Delete0 = 0b101,
};

enum struct StrumDirection : bool
{
  downStroke = false,
  upStroke = true
};

#ifdef SHR3D_SFX
enum struct SfxSystem : u8
{
  empty,

#ifdef SHR3D_SFX_CORE
  core,
#endif // SHR3D_SFX_CORE

#ifdef SHR3D_SFX_CORE_RAKARRACK
  coreRakarrack,
#endif // SHR3D_SFX_CORE_RAKARRACK

#ifdef SHR3D_SFX_CORE_AIRWINDOWS
  coreAirWindows,
#endif // SHR3D_SFX_CORE_AIRWINDOWS

#ifdef SHR3D_SFX_CORE_EXTENSION_V2
  coreExtensionV2,
#endif // SHR3D_SFX_CORE_EXTENSION_V2

#ifdef SHR3D_SFX_PLUGIN_CLAP
  clap,
#endif // SHR3D_SFX_PLUGIN_CLAP

#ifdef SHR3D_SFX_PLUGIN_LV2
  lv2,
#endif // SHR3D_SFX_PLUGIN_LV2

#ifdef SHR3D_SFX_PLUGIN_VST
  vst,
#endif // SHR3D_SFX_PLUGIN_VST

#ifdef SHR3D_SFX_PLUGIN_VST3
  vst3,
#endif // SHR3D_SFX_PLUGIN_VST3

  COUNT
};

struct SfxId
{
  SfxSystem system;
  SfxIndex sfxIndex;
};

enum SfxEffectState : char8_t
{
  active = u8'-',
  muted = u8'M'
};

struct SfxChainEffect
{
  SfxId id;
  SfxEffectState state;
};

#endif // SHR3D_SFX

#ifdef SHR3D_SFX_CORE
enum struct SfxCore
{
  //EMPTY,

#ifdef SHR3D_SFX_CORE_NEURALAMPMODELER
  NeuralAmpModeler,
#endif // SHR3D_SFX_CORE_NEURALAMPMODELER

#ifdef SHR3D_SFX_CORE_HEXFIN
  Hexfin,
#endif // SHR3D_SFX_CORE_HEXFIN

  COUNT
};

#ifdef SHR3D_SFX_CORE_AIRWINDOWS
enum struct SfxCoreAirWindows_
{
  Acceleration,
  Acceleration2,
  ADClip7,
  ADClip8,
  ADT,
  Air,
  Air2,
  Air3,
  Apicolypse,
  AQuickVoiceClip,
  AtmosphereBuss,
  AtmosphereChannel,
  Aura,
  AutoPan,
  Average,
  AverMatrix,
  Balanced,
  BassAmp,
  BassDrive,
  BassKit,
  Baxandall,
  Baxandall2,
  Beam,
  BigAmp,
  Biquad,
  Biquad2,
  BiquadDouble,
  BiquadHiLo,
  BiquadNonLin,
  BiquadOneHalf,
  BiquadPlus,
  BiquadStack,
  BiquadTriple,
  Bite,
  BitGlitter,
  BitShiftGain,
  BitShiftPan,
  BlockParty,
  BrassRider,
  BrightAmbience,
  BrightAmbience2,
  BrightAmbience3,
  BuildATPDF,
  BussColors4,
  ButterComp,
  ButterComp2,
  C5RawBuss,
  C5RawChannel,
  Cabs,
  Calibre,
  Capacitor,
  Capacitor2,
  Chamber,
  Chamber2,
  Channel4,
  Channel5,
  Channel6,
  Channel7,
  Channel8,
  Channel9,
  Chorus,
  ChorusEnsemble,
  ChromeOxide,
  Cider,
  ClearCoat,
  ClipOnly2,
  ClipSoftly,
  CloudCoat,
  Coils,
  Coils2,
  Cojones,
  Compresaturator,
  Console0Buss,
  Console0Channel,
  Console4Buss,
  Console4Channel,
  Console5Buss,
  Console5Channel,
  Console5DarkCh,
  Console6Buss,
  Console6Channel,
  Console7Buss,
  Console7Cascade,
  Console7Channel,
  Console7Crunch,
  Console8BussHype,
  Console8BussIn,
  Console8BussOut,
  Console8ChannelHype,
  Console8ChannelIn,
  Console8ChannelOut,
  Console8LiteBuss,
  Console8LiteChannel,
  Console8SubHype,
  Console8SubIn,
  Console8SubOut,
  Console9Buss,
  Console9Channel,
  ConsoleLABuss,
  ConsoleLAChannel,
  ConsoleMCBuss,
  ConsoleMCChannel,
  ConsoleMDBuss,
  ConsoleMDChannel,
  ConsoleXBuss,
  ConsoleXChannel,
  ContentHideD,
  CreamCoat,
  Creature,
  CrickBass,
  CrunchCoat,
  CrunchyGrooveWear,
  Crystal,
  CStrip,
  CStrip2,
  curve,
  Dark,
  DarkNoise,
  DCVoltage,
  DeBess,
  Deckwrecka,
  DeEss,
  DeHiss,
  Density,
  Density2,
  DeRez,
  DeRez2,
  DeRez3,
  Desk,
  Desk4,
  DigitalBlack,
  Dirt,
  Discontinuity,
  Distance,
  Distance2,
  Distance3,
  Distortion,
  Ditherbox,
  DitherFloat,
  DitherMeDiskers,
  DitherMeTimbers,
  Doublelay,
  DoublePaul,
  Drive,
  DrumSlam,
  DubCenter,
  Dubly,
  DubSub,
  DustBunny,
  Dynamics,
  Dyno,
  Edge,
  EdIsDim,
  Elation,
  ElectroHat,
  Energy,
  Energy2,
  Ensemble,
  EQ,
  EveryConsole,
  EverySlew,
  EveryTrim,
  Exciter,
  Facet,
  FathomFive,
  FinalClip,
  FireAmp,
  Flipity,
  Floor,
  Flutter,
  Focus,
  Fracture,
  Fracture2,
  FromTape,
  Galactic,
  Galactic2,
  GalacticVibe,
  Gatelope,
  GlitchShifter,
  GoldenSlew,
  Golem,
  GrindAmp,
  Gringer,
  GrooveWear,
  GuitarConditioner,
  HardVacuum,
  Hermepass,
  HermeTrim,
  HighGlossDither,
  HighImpact,
  Highpass,
  Highpass2,
  Holt,
  Holt2,
  Hombre,
  Huge,
  Hull,
  Hull2,
  Hype,
  Hypersonic,
  HypersonX,
  Infinity,
  Infinity2,
  Inflamer,
  Infrasonic,
  Interstage,
  IronOxide5,
  IronOxideClassic,
  IronOxideClassic2,
  Isolator,
  Isolator2,
  Kalman,
  kCathedral,
  kCathedral2,
  kCathedral3,
  kChamberAR,
  kGuitarHall,
  kPlate140,
  kPlate240,
  kPlateA,
  kPlateB,
  kPlateC,
  kPlateD,
  LeadAmp,
  LeftoMono,
  LilAmp,
  Logical4,
  Loud,
  Lowpass,
  Lowpass2,
  LRFlipTimer,
  Luxor,
  MackEQ,
  Mackity,
  MatrixVerb,
  Melt,
  MidAmp,
  MidSide,
  Mojo,
  Monitoring,
  Monitoring2,
  Monitoring3,
  MoNoam,
  MSFlipTimer,
  MultiBandDistortion,
  MV,
  MV2,
  NaturalizeDither,
  NCSeventeen,
  Neverland,
  Nikola,
  NodeDither,
  Noise,
  NonlinearSpace,
  NotJustAnotherCD,
  NotJustAnotherDither,
  OneCornerClip,
  OrbitKick,
  Overheads,
  Pafnuty,
  Pafnuty2,
  Parametric,
  PaulDither,
  PaulWide,
  PDBuss,
  PDChannel,
  PeaksOnly,
  Pear,
  Pear2,
  PhaseNudge,
  PitchDelay,
  PitchNasty,
  PlatinumSlew,
  PocketVerbs,
  Pockey,
  Pockey2,
  Podcast,
  PodcastDeluxe,
  Point,
  Pop,
  Pop2,
  Pop3,
  PowerSag,
  PowerSag2,
  Precious,
  Preponderant,
  Pressure4,
  Pressure5,
  PurestAir,
  PurestConsole2Buss,
  PurestConsole2Channel,
  PurestConsole3Buss,
  PurestConsole3Channel,
  PurestConsoleBuss,
  PurestConsoleChannel,
  PurestDrive,
  PurestEcho,
  PurestFade,
  PurestGain,
  PurestSquish,
  PurestWarm,
  PurestWarm2,
  Pyewacket,
  RawGlitters,
  RawTimbers,
  Recurve,
  Remap,
  ResEQ,
  ResEQ2,
  Reverb,
  Righteous4,
  RightoMono,
  SampleDelay,
  Shape,
  ShortBuss,
  SideDull,
  Sidepass,
  Silhouette,
  Sinew,
  SingleEndedTriode,
  Slew,
  Slew2,
  Slew3,
  SlewOnly,
  SlewSonic,
  Smooth,
  SoftGate,
  SpatializeDither,
  Spiral,
  Spiral2,
  Srsly,
  Srsly2,
  Srsly3,
  StarChild,
  StarChild2,
  StereoChorus,
  StereoDoubler,
  StereoEnsemble,
  StereoFX,
  Stonefire,
  StoneFireComp,
  StudioTan,
  SubsOnly,
  SubTight,
  Surge,
  SurgeTide,
  Sweeten,
  Swell,
  Tape,
  TapeDelay,
  TapeDelay2,
  TapeDither,
  TapeDust,
  TapeFat,
  Texturize,
  TexturizeMS,
  Thunder,
  ToneSlant,
  ToTape5,
  ToTape6,
  ToVinyl4,
  TPDFDither,
  TPDFWide,
  TransDesk,
  Tremolo,
  TremoSquare,
  Trianglizer,
  TripleSpread,
  Tube,
  Tube2,
  TubeDesk,
  uLawDecode,
  uLawEncode,
  Ultrasonic,
  UltrasonicLite,
  UltrasonicMed,
  UltrasonX,
  UnBox,
  VariMu,
  Verbity,
  Verbity2,
  Vibrato,
  VinylDither,
  VoiceOfTheStarship,
  VoiceTrick,
  Weight,
  Wider,
  Wolfbot,
  XBandpass,
  XHighpass,
  XLowpass,
  XNotch,
  XRegion,
  YBandpass,
  YHighpass,
  YLowpass,
  YNotBandpass,
  YNotch,
  YNotHighpass,
  YNotLowpass,
  YNotNotch,
  ZBandpass,
  ZBandpass2,
  ZHighpass,
  ZHighpass2,
  ZLowpass,
  ZLowpass2,
  ZNotch,
  ZNotch2,
  ZOutputStage,
  ZRegion,
  ZRegion2,
  COUNT
};
#endif // SHR3D_SFX_CORE_AIRWINDOWS

#ifdef SHR3D_SFX_CORE_RAKARRACK
enum struct SfxCoreRakarrack
{
  Reverb,
  Echo,
  Chorus,
  Flanger,
  Phaser,
#ifdef SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  Overdrive,
  Distorsion,
#endif // SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  EQ,
  ParametricEQ,
  Cabinet,
  Compressor,
  WahWah,
  AlienWah,
  Pan,
#ifdef SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
#if 0
  Harmonizer,
#endif
#endif // SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  MusicalDelay,
  NoiseGate,
#ifdef SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  Derelict,
#endif // SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  AnalogPhaser,
  Valve,
  DualFlange,
  Ring,
  Exciter,
#ifdef SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  DistBand,
#endif // SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  Arpie,
  Expander,
  Shuffle,
  Synthfilter,
  VaryBand,
#ifdef SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON
  Convolotron,
#endif // SHR3D_SFX_CORE_RAKARRACK_CONVOLOTRON
  MuTroMojo,
  Echoverse,
  CoilCrafter,
  ShelfBoost,
#ifdef SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  Vocoder,
#endif // SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  Sustainer,
#ifdef SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  Sequence,
  Shifter,
  StompBox,
  Reverbtron,
#endif // SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  Echotron,
#ifdef SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  StereoHarm,
#endif // SHR3D_SFX_CORE_RAKARRACK_LIBSAMPLERATE
  CompBand,
  OpticalTrem,
  Vibe,
  COUNT
};
#endif // SHR3D_SFX_CORE_RAKARRACK

#endif // SHR3D_SFX_CORE

struct vec2
{
  union
  {
    f32 x, r = 0.0_f32;
  };
  union
  {
    f32 y, g = 0.0_f32;
  };
};

struct vec3
{
  union
  {
    f32 x, r = 0.0_f32;
  };
  union
  {
    f32 y, g = 0.0_f32;
  };
  union
  {
    f32 z, b = 0.0_f32;
  };
};

struct vec4
{
  union
  {
    f32 x, r = 0.0_f32;
  };
  union
  {
    f32 y, g = 0.0_f32;
  };
  union
  {
    f32 z, b = 0.0_f32;
  };
  union
  {
    f32 w, a = 0.0_f32;
  };
};

struct mat4
{
  /* 4x4 matrix that looks like this:
   / m00 m01 m02 m03 \
  |  m10 m11 m21 m13  |
  |  m20 m21 m22 m23  |
   \ m30 m31 m32 m33 /
  mat4 is column major, just like what vulkan or opengl expects:*/
  f32 m00 = 1.0_f32, m10 = 0.0_f32, m20 = 0.0_f32, m30 = 0.0_f32;
  f32 m01 = 0.0_f32, m11 = 1.0_f32, m21 = 0.0_f32, m31 = 0.0_f32;
  f32 m02 = 0.0_f32, m12 = 0.0_f32, m22 = 1.0_f32, m32 = 0.0_f32;
  f32 m03 = 0.0_f32, m13 = 0.0_f32, m23 = 0.0_f32, m33 = 1.0_f32;
};

struct BoundingBox
{
  f32 bottom;
  f32 left;
  f32 right;
  f32 top;
};

struct Size
{
  u32 width;
  u32 height;
};

struct Rect
{
  i16 top;
  i16 left;
  i16 bottom;
  i16 right;
};

//struct RectF
//{
//  f32 top;
//  f32 left;
//  f32 bottom;
//  f32 right;
//};

enum struct MidiStatus : u8
{
  chan1NoteOff = 0x80,
  chan1NoteOn = 0x90,
  chan1PitchBendChange = 0xE0
  // there are more.
};

struct MidiMessage
{
  MidiStatus status;
  MidiNote note;
  u8 velocity;
};

struct SongStats
{
  u64 lastPlayed = 0;
  f32 score = 0.0f;
  i32 timesPlayed = 0;
  SfxBankIndex sfxBankIndex = -1;
};

struct SfxParameterProperties
{
  char name[256];
  char label[64];
  char display[64];
};

struct KeyState
{
  bool pressed : 1 = false; // pressed this frame
  bool released : 1 = false; // released this frame
  bool toggled : 1 = false; // state can be on or off. key press switches state
  bool heldDown : 1 = false; // held down
  bool heldDownLastFrame : 1 = false; // was held down last frame
  bool clickedInUiOrMidi : 1 = false; // the Input::tick() runs before the UI::tick(). This means keypresses update the UI in the same frame, but clicks in the UI are handled one frame later.
};

struct Level
{
  f32 overallLevel;
  std::vector<i32> sectionLevels;
};

#ifdef SHR3D_OPENXR
enum struct ControllerEventBit : u32
{
  none = 0,                   // 0x00000000
  value_trigger = 1 << 0,     // 0x00000001
  value_squeeze = 1 << 1,     // 0x00000002
  value_thumbstick = 1 << 2,  // 0x00000004
  click_trigger = 1 << 4,     // 0x00000010
  click_thumbstick = 1 << 5,  // 0x00000020
  click_squeeze = 1 << 6,     // 0x00000040
  click_a = 1 << 7,           // 0x00000080
  click_b = 1 << 8,           // 0x00000100
  click_x = 1 << 9,           // 0x00000200
  click_y = 1 << 10,          // 0x00000400
  click_menu = 1 << 11,       // 0x00000800
  touch_trigger = 1 << 12,    // 0x00001000
  touch_thumbstick = 1 << 13, // 0x00002000
  touch_a = 1 << 14,          // 0x00004000
  touch_b = 1 << 15,          // 0x00008000
  touch_x = 1 << 16,          // 0x00010000
  touch_y = 1 << 17           // 0x00020000
} BIT_FLAGS(ControllerEventBit);

struct XrControllerEvent
{
  ControllerEventBit controllerEventBit;
  f32 trigger;         // 0.0f - 1.0f
  f32 squeeze;         // 0.0f - 1.0f
  f32 thumbstick_x;    //-1.0f - 1.0f
  f32 thumbstick_y;    //-1.0f - 1.0f
  bool click_trigger;    //true:down false:up
  bool click_thumbstick; //true:down false:up  Surprise, the thumbstick can be pressed
  bool click_squeeze;    //true:down false:up
  bool click_a;          //true:down false:up
  bool click_b;          //true:down false:up
  bool click_x;          //true:down false:up
  bool click_y;          //true:down false:up
  bool click_menu;       //true:down false:up
  // seldom use
  bool touch_trigger;    //true:touch false:none touch
  bool touch_thumbstick; //true:touch false:none touch
  bool touch_a;          //true:touch false:none touch
  bool touch_b;          //true:touch false:none touch
  bool touch_x;          //true:touch false:none touch
  bool touch_y;          //true:touch false:none touch
};

enum struct XrActiveController : u8 {
  left,
  right,
  mouseKeyboard
};

#ifdef SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
enum struct XrController : u8 {
  pico4,
  quest3,
  quest3Neon,
};
#endif // SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
#endif // SHR3D_OPENXR


#ifdef SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE
enum struct SkyboxTextureType : u8 {
  skysphere360degree,
  cubemap
};
#endif // SHR3D_ENVIRONMENT_SKYBOX_CUBE_TEXTURE

#ifdef SHR3D_PARTICLE
struct Particle_
{
  TimeNS particleBornTime;
  vec3 bornPosition;
  vec3 velocity;
  vec3 acceleration;
  f32 rotation;
  vec4 color;
  f32 scale;
};
#endif // SHR3D_PARTICLE

#ifdef SHR3D_SFX_PLUGIN_BENCHMARK
struct SfxBenchmarkResult
{
  TimeNS duration;
  u64 memoryUsageInBytes;
};
#endif // SHR3D_SFX_PLUGIN_BENCHMARK

#ifdef SHR3D_ENVIRONMENT_STAGE
struct StageModel
{
  vec3 translation;
  vec4 rotation;
  vec3 scale;

  u32 indexCount;
  u32 startIndex;
};
#endif // SHR3D_ENVIRONMENT_STAGE

#endif // TYPE_H
