Arrow keys now navigate the full virtual row list (../, subdirs, patches) rather than only patch rows. Landing on a patch auto-loads it as before; landing on .. or a subdir highlights it and Enter confirms navigation. Added patchVCursor to UIState to track keyboard focus independently of the loaded patch. Mouse-click on a patch now also syncs the cursor so subsequent arrow-key movement starts from the right position. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
112 lines
3.8 KiB
C
112 lines
3.8 KiB
C
#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;
|
|
int patchVCursor;
|
|
|
|
// 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
|