#ifndef UI_H #define UI_H #include "raylib.h" #include "synth.h" #include "midi.h" #include "patch.h" #include "config.h" typedef struct { int id; float *valuePtr; float min; float max; } UIControlEntry; // Sprite indices typedef enum { SPRITE_WAVE_SINE = 0, SPRITE_WAVE_TRIANGLE, SPRITE_WAVE_SAW, SPRITE_WAVE_RAMP, SPRITE_WAVE_PULSE, SPRITE_WAVE_NOISE, SPRITE_BTN_RED, SPRITE_BTN_GREEN, SPRITE_SLIDER, SPRITE_KNOB } SpriteIndex; // UI state that needs to persist between frames typedef struct { Texture2D sprites; Font font; MidiState *midi; Camera2D *camera; // About menu state int aboutMenuOpen; // MIDI menu state int midiMenuOpen; int midiMenuSelected; // -1 if none // Knob drag state int draggingKnob; // -1 if none Vector2 dragStart; float dragStartValue; // Slider drag state int draggingSlider; // -1 if none // MIDI learn state int midiLearnActive; // 0=off 1=click a control 2=wiggle CC int midiLearnTargetId; // id of selected control (-1 if none) float *midiLearnValuePtr; float midiLearnMin; float midiLearnMax; // Patch browser state int patchMenuOpen; int focusedTextInput; // -1 if none int patchConfirmOverwrite; int patchConfirmClear; char patchSaveName[PATCH_NAME_LEN]; char patchCurrentName[PATCH_NAME_LEN]; int patchFileCount; char patchFiles[PATCH_MAX_FILES][PATCH_NAME_LEN]; int patchScrollOffset; int patchShowFavsOnly; char patchFavs[PATCH_MAX_FILES][PATCH_NAME_LEN]; int patchFavCount; char patchCurrentDir[256]; char patchSubDirs[PATCH_MAX_DIRS][PATCH_NAME_LEN]; int patchSubDirCount; // Control registry — built lazily by uiKnob/uiSlider for CC mapping persistence UIControlEntry controlRegistry[128]; int controlRegistryCount; // CC mappings loaded from file but not yet resolved (registry not yet populated) ConfigCcEntry pendingMappings[128]; int pendingCount; } UIState; // Lifecycle void uiInit(UIState *ui, MidiState *midi, Camera2D *camera); void uiClose(UIState *ui); // Primitives float uiKnob(UIState *ui, int id, float x, float y, float *ptr, float min, float max, const char *label); float uiSlider(UIState *ui, int id, float x, float y, float width, float *ptr, float min, float max, const char *label); int uiWaveformSelector(UIState *ui, float x, float y, int currentWaveform); void uiADSRShape(float x, float y, float width, float height, float attack, float decay, float sustain, float release, Color color); void uiVoiceMeter(UIState *ui, float x, float y, Voice *voices, int voiceCount); // Panels void uiOscillatorPanel(UIState *ui, int baseId, float x, float y, float width, float height, Oscillator *osc, const char *title); void uiEnvelopePanel(UIState *ui, int baseId, float x, float y, float width, float height, Envelope *env, const char *title); void uiLfoPanel(UIState *ui, int baseId, float x, float y, float width, float height, LFO *lfo, const char *title); void uiFilterPanel(UIState *ui, float x, float y, float width, float height, Filter *filter, const char *title); void uiMasterPanel(UIState *ui, float x, float y, float width, float height, Synth *s); void uiMidiMenu(UIState *ui, float x, float y, float width, MidiState *midi); void uiPatchMenu(UIState *ui, float x, float y, float width, Synth *s); void uiAboutMenu(UIState *ui, float x, float y, float width); void uiLoadCcMappingsForDevice(UIState *ui, const char *deviceName); // Window helpers void recomputeViewPort(Camera2D* camera, int x_logical_resolution, int y_logical_resolution, int border_width); #endif