Files
soundThing/include/ui.h
Anachronaut 75e0894ff8 v0.9.5 beta — full feature build ready for distribution
Core additions since initial commit:
- Platform-split MIDI (midi_linux.c / midi_windows.c)
- Patch system: save/load/scan, subdirectory navigation, favourites
- Config system: last MIDI device and CC mappings persisted to disk
- Custom embedded pixel font and sprite sheet (no loose asset files at runtime)
- Window icon embedded at runtime (SetWindowIcon) and in Windows .exe (windres)
- chdirToExeDir() in platform.c so double-click launch finds patches/ correctly
- About screen accessible from Master panel

UI polish:
- TITLE_BAR_H constant (20 px) — sprite buttons now fit inside title bars
- All title bar text, button overlay text, and close/active labels vertically centred
- Full-screen dim overlay computed from camera transform (no more partial coverage)
- Patch browser: folder navigation, breadcrumb title, 256-slot limit lifted

Build:
- Makefile auto-discovers sources; embeds sprites/font/icon via xxd rules
- Windows cross-compile: make PLATFORM=windows (mingw-w64 + windres)
- windows.h isolated in platform.c to avoid Rectangle/CloseWindow conflicts with raylib.h
- WIN_RES uses lazy = assignment so OBJ_DIR expands correctly for windres output path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 19:18:34 -04:00

111 lines
3.7 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;
// 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