From fb358e3c4b72a7a83e1d62e59f53d17aaa94e4b5 Mon Sep 17 00:00:00 2001 From: Max Amundsen Date: Wed, 4 Mar 2026 16:26:17 -0500 Subject: [PATCH] type alias refactor --- src/audio/audio.h | 15 ++- src/audio/audio_asio.cpp | 74 +++++------ src/audio/audio_coreaudio.cpp | 56 ++++----- src/base/base_core.h | 2 + src/base/base_strings.cpp | 2 +- src/main.cpp | 184 +++++++++++++-------------- src/midi/midi.h | 27 ++-- src/midi/midi_coremidi.cpp | 82 ++++++------ src/midi/midi_win32.cpp | 40 +++--- src/platform/platform.h | 30 +++-- src/platform/platform_macos.mm | 50 ++++---- src/platform/platform_win32.cpp | 36 +++--- src/renderer/renderer.h | 21 ++-- src/renderer/renderer_dx12.cpp | 210 +++++++++++++++---------------- src/renderer/renderer_metal.mm | 214 +++++++++++++++++--------------- src/ui/ui_core.cpp | 6 +- src/ui/ui_core.h | 12 +- src/ui/ui_widgets.cpp | 124 +++++++++--------- src/ui/ui_widgets.h | 32 ++--- 19 files changed, 614 insertions(+), 603 deletions(-) diff --git a/src/audio/audio.h b/src/audio/audio.h index 5fd4694..7a49b8c 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -1,24 +1,23 @@ #pragma once -#include -#include +#include "base/base_core.h" struct AudioEngine; struct AudioDeviceInfo { char name[128]; - int32_t id; // index into engine's device list + S32 id; // index into engine's device list }; AudioEngine *audio_create(void *hwnd); void audio_destroy(AudioEngine *engine); void audio_refresh_devices(AudioEngine *engine); -int32_t audio_get_device_count(AudioEngine *engine); -AudioDeviceInfo*audio_get_device(AudioEngine *engine, int32_t index); +S32 audio_get_device_count(AudioEngine *engine); +AudioDeviceInfo*audio_get_device(AudioEngine *engine, S32 index); -bool audio_open_device(AudioEngine *engine, int32_t index); +B32 audio_open_device(AudioEngine *engine, S32 index); void audio_close_device(AudioEngine *engine); void audio_play_test_tone(AudioEngine *engine); -bool audio_is_test_tone_playing(AudioEngine *engine); -void audio_update(AudioEngine *engine, float dt); +B32 audio_is_test_tone_playing(AudioEngine *engine); +void audio_update(AudioEngine *engine, F32 dt); diff --git a/src/audio/audio_asio.cpp b/src/audio/audio_asio.cpp index ff28c8e..b02dd45 100644 --- a/src/audio/audio_asio.cpp +++ b/src/audio/audio_asio.cpp @@ -74,21 +74,21 @@ struct ASIOChannelInfo { struct ASIOBufferInfo { ASIOBool isInput; long channelNum; - void *buffers[2]; // double buffer + void *buffers[2]; // F64 buffer }; struct ASIOTimeCode { - double speed; + F64 speed; ASIOSamples timeCodeSamples; unsigned long flags; char future[64]; }; struct AsioTimeInfo { - double speed; + F64 speed; ASIOTimeStamp systemTime; ASIOSamples samplePosition; - double sampleRate; + F64 sampleRate; unsigned long flags; char reserved[12]; }; @@ -101,8 +101,8 @@ struct ASIOTime { struct ASIOCallbacks { void (*bufferSwitch)(long doubleBufferIndex, ASIOBool directProcess); - void (*sampleRateDidChange)(double sRate); - long (*asioMessage)(long selector, long value, void *message, double *opt); + void (*sampleRateDidChange)(F64 sRate); + long (*asioMessage)(long selector, long value, void *message, F64 *opt); ASIOTime *(*bufferSwitchTimeInfo)(ASIOTime *params, long doubleBufferIndex, ASIOBool directProcess); }; @@ -134,9 +134,9 @@ public: virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0; virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0; virtual ASIOError getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity) = 0; - virtual ASIOError canSampleRate(double sampleRate) = 0; - virtual ASIOError getSampleRate(double *sampleRate) = 0; - virtual ASIOError setSampleRate(double sampleRate) = 0; + virtual ASIOError canSampleRate(F64 sampleRate) = 0; + virtual ASIOError getSampleRate(F64 *sampleRate) = 0; + virtual ASIOError setSampleRate(F64 sampleRate) = 0; virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0; virtual ASIOError setClockSource(long reference) = 0; virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0; @@ -162,25 +162,25 @@ struct AudioEngine { // Device enumeration AudioDeviceInfo devices[AUDIO_MAX_DEVICES]; AsioDriverInfo drivers[AUDIO_MAX_DEVICES]; - int32_t device_count; + S32 device_count; // Active driver IASIO *driver; - int32_t active_device_index; // -1 = none + S32 active_device_index; // -1 = none // Buffer state ASIOBufferInfo buffer_infos[AUDIO_MAX_CHANNELS]; long num_output_channels; long num_input_channels; long buffer_size; - double sample_rate; + F64 sample_rate; ASIOSampleType output_sample_type; ASIOCallbacks callbacks; // Test tone state (accessed from callback thread) volatile LONG test_tone_active; volatile LONG test_tone_samples_remaining; - double test_tone_phase; // written only from callback thread + F64 test_tone_phase; // written only from callback thread }; //////////////////////////////// @@ -191,29 +191,29 @@ static AudioEngine *g_audio_engine = nullptr; //////////////////////////////// // Sample writing helper -static void write_sample(void *dest, ASIOSampleType type, double value) { +static void write_sample(void *dest, ASIOSampleType type, F64 value) { // Clamp to [-1, 1] if (value > 1.0) value = 1.0; if (value < -1.0) value = -1.0; switch (type) { case ASIOSTInt16LSB: { - int16_t s = (int16_t)(value * 32767.0); + S16 s = (S16)(value * 32767.0); memcpy(dest, &s, 2); } break; case ASIOSTInt24LSB: { - int32_t s = (int32_t)(value * 8388607.0); - uint8_t *d = (uint8_t *)dest; - d[0] = (uint8_t)(s & 0xFF); - d[1] = (uint8_t)((s >> 8) & 0xFF); - d[2] = (uint8_t)((s >> 16) & 0xFF); + S32 s = (S32)(value * 8388607.0); + U8 *d = (U8 *)dest; + d[0] = (U8)(s & 0xFF); + d[1] = (U8)((s >> 8) & 0xFF); + d[2] = (U8)((s >> 16) & 0xFF); } break; case ASIOSTInt32LSB: { - int32_t s = (int32_t)(value * 2147483647.0); + S32 s = (S32)(value * 2147483647.0); memcpy(dest, &s, 4); } break; case ASIOSTFloat32LSB: { - float f = (float)value; + F32 f = (F32)value; memcpy(dest, &f, 4); } break; case ASIOSTFloat64LSB: { @@ -221,7 +221,7 @@ static void write_sample(void *dest, ASIOSampleType type, double value) { } break; default: { // Unsupported type — write silence (4 bytes of zero) - uint32_t z = 0; + U32 z = 0; memcpy(dest, &z, 4); } break; } @@ -249,7 +249,7 @@ static void asio_buffer_switch(long doubleBufferIndex, ASIOBool directProcess) { long buf_size = engine->buffer_size; ASIOSampleType type = engine->output_sample_type; - int bytes_per_sample = sample_type_size(type); + S32 bytes_per_sample = sample_type_size(type); LONG tone_active = InterlockedCompareExchange(&engine->test_tone_active, 0, 0); @@ -266,13 +266,13 @@ static void asio_buffer_switch(long doubleBufferIndex, ASIOBool directProcess) { } if (tone_active) { - double phase = engine->test_tone_phase; - double phase_inc = 2.0 * AUDIO_PI * AUDIO_TEST_TONE_HZ / engine->sample_rate; + F64 phase = engine->test_tone_phase; + F64 phase_inc = 2.0 * AUDIO_PI * AUDIO_TEST_TONE_HZ / engine->sample_rate; LONG remaining = InterlockedCompareExchange(&engine->test_tone_samples_remaining, 0, 0); long samples_to_gen = (remaining < buf_size) ? (long)remaining : buf_size; for (long s = 0; s < buf_size; s++) { - double sample_val = 0.0; + F64 sample_val = 0.0; if (s < samples_to_gen) { sample_val = sin(phase) * 0.5; // -6dB to avoid clipping phase += phase_inc; @@ -283,7 +283,7 @@ static void asio_buffer_switch(long doubleBufferIndex, ASIOBool directProcess) { for (long ch = 0; ch < engine->num_output_channels; ch++) { void *buf = engine->buffer_infos[ch].buffers[doubleBufferIndex]; if (!buf) continue; - uint8_t *dest = (uint8_t *)buf + (size_t)(s * bytes_per_sample); + U8 *dest = (U8 *)buf + (size_t)(s * bytes_per_sample); write_sample(dest, type, sample_val); } } @@ -298,14 +298,14 @@ static void asio_buffer_switch(long doubleBufferIndex, ASIOBool directProcess) { } } -static void asio_sample_rate_changed(double sRate) { +static void asio_sample_rate_changed(F64 sRate) { AudioEngine *engine = g_audio_engine; if (engine) { engine->sample_rate = sRate; } } -static long asio_message(long selector, long value, void *message, double *opt) { +static long asio_message(long selector, long value, void *message, F64 *opt) { (void)value; (void)message; (void)opt; @@ -377,7 +377,7 @@ static void enumerate_asio_drivers(AudioEngine *engine) { continue; } - int32_t idx = engine->device_count++; + S32 idx = engine->device_count++; strncpy_s(engine->devices[idx].name, sizeof(engine->devices[idx].name), subkey_name, _TRUNCATE); engine->devices[idx].id = idx; engine->drivers[idx].clsid = clsid; @@ -415,17 +415,17 @@ void audio_refresh_devices(AudioEngine *engine) { enumerate_asio_drivers(engine); } -int32_t audio_get_device_count(AudioEngine *engine) { +S32 audio_get_device_count(AudioEngine *engine) { return engine->device_count; } -AudioDeviceInfo *audio_get_device(AudioEngine *engine, int32_t index) { +AudioDeviceInfo *audio_get_device(AudioEngine *engine, S32 index) { if (index < 0 || index >= engine->device_count) return nullptr; return &engine->devices[index]; } -bool audio_open_device(AudioEngine *engine, int32_t index) { +B32 audio_open_device(AudioEngine *engine, S32 index) { // Close any existing device first audio_close_device(engine); @@ -462,7 +462,7 @@ bool audio_open_device(AudioEngine *engine, int32_t index) { } // Query sample rate - double sample_rate = 0; + F64 sample_rate = 0; if (driver->getSampleRate(&sample_rate) != ASE_OK || sample_rate <= 0) { // Try setting a common rate if (driver->setSampleRate(44100.0) == ASE_OK) { @@ -556,11 +556,11 @@ void audio_play_test_tone(AudioEngine *engine) { InterlockedExchange(&engine->test_tone_active, 1); } -bool audio_is_test_tone_playing(AudioEngine *engine) { +B32 audio_is_test_tone_playing(AudioEngine *engine) { return InterlockedCompareExchange(&engine->test_tone_active, 0, 0) != 0; } -void audio_update(AudioEngine *engine, float dt) { +void audio_update(AudioEngine *engine, F32 dt) { (void)engine; (void)dt; // Currently no per-frame work needed on the main thread. diff --git a/src/audio/audio_coreaudio.cpp b/src/audio/audio_coreaudio.cpp index c0efada..215bcc3 100644 --- a/src/audio/audio_coreaudio.cpp +++ b/src/audio/audio_coreaudio.cpp @@ -20,18 +20,18 @@ struct CoreAudioDeviceInfo { struct AudioEngine { AudioDeviceInfo devices[AUDIO_MAX_DEVICES]; CoreAudioDeviceInfo ca_devices[AUDIO_MAX_DEVICES]; - int32_t device_count; + S32 device_count; AUGraph graph; AudioUnit output_unit; - int32_t active_device_index; - double sample_rate; - int32_t num_channels; + S32 active_device_index; + F64 sample_rate; + S32 num_channels; // Test tone state (accessed from audio render thread) - _Atomic int32_t test_tone_active; - _Atomic int32_t test_tone_samples_remaining; - double test_tone_phase; + _Atomic S32 test_tone_active; + _Atomic S32 test_tone_samples_remaining; + F64 test_tone_phase; }; //////////////////////////////// @@ -55,7 +55,7 @@ static OSStatus audio_render_callback(void *inRefCon, return noErr; } - int32_t tone_active = atomic_load(&engine->test_tone_active); + S32 tone_active = atomic_load(&engine->test_tone_active); if (!tone_active) { for (UInt32 buf = 0; buf < ioData->mNumberBuffers; buf++) @@ -63,18 +63,18 @@ static OSStatus audio_render_callback(void *inRefCon, return noErr; } - double phase = engine->test_tone_phase; - double phase_inc = 2.0 * AUDIO_PI * AUDIO_TEST_TONE_HZ / engine->sample_rate; - int32_t remaining = atomic_load(&engine->test_tone_samples_remaining); - int32_t samples_to_gen = (remaining < (int32_t)inNumberFrames) ? remaining : (int32_t)inNumberFrames; + F64 phase = engine->test_tone_phase; + F64 phase_inc = 2.0 * AUDIO_PI * AUDIO_TEST_TONE_HZ / engine->sample_rate; + S32 remaining = atomic_load(&engine->test_tone_samples_remaining); + S32 samples_to_gen = (remaining < (S32)inNumberFrames) ? remaining : (S32)inNumberFrames; // CoreAudio with kAudioFormatFlagIsNonInterleaved: each buffer = one channel for (UInt32 buf = 0; buf < ioData->mNumberBuffers; buf++) { - float *out = (float *)ioData->mBuffers[buf].mData; - double p = phase; + F32 *out = (F32 *)ioData->mBuffers[buf].mData; + F64 p = phase; for (UInt32 s = 0; s < inNumberFrames; s++) { - if ((int32_t)s < samples_to_gen) { - out[s] = (float)(sin(p) * 0.5); // -6dB + if ((S32)s < samples_to_gen) { + out[s] = (F32)(sin(p) * 0.5); // -6dB p += phase_inc; if (p >= 2.0 * AUDIO_PI) p -= 2.0 * AUDIO_PI; } else { @@ -88,7 +88,7 @@ static OSStatus audio_render_callback(void *inRefCon, while (phase >= 2.0 * AUDIO_PI) phase -= 2.0 * AUDIO_PI; engine->test_tone_phase = phase; - int32_t new_remaining = atomic_fetch_sub(&engine->test_tone_samples_remaining, samples_to_gen); + S32 new_remaining = atomic_fetch_sub(&engine->test_tone_samples_remaining, samples_to_gen); if (new_remaining <= samples_to_gen) { atomic_store(&engine->test_tone_active, 0); atomic_store(&engine->test_tone_samples_remaining, 0); @@ -113,7 +113,7 @@ static void enumerate_output_devices(AudioEngine *engine) { if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, nullptr, &data_size) != noErr) return; - int device_count = (int)(data_size / sizeof(AudioDeviceID)); + S32 device_count = (S32)(data_size / sizeof(AudioDeviceID)); if (device_count <= 0) return; AudioDeviceID *device_ids = (AudioDeviceID *)malloc(data_size); @@ -122,7 +122,7 @@ static void enumerate_output_devices(AudioEngine *engine) { return; } - for (int i = 0; i < device_count && engine->device_count < AUDIO_MAX_DEVICES; i++) { + for (S32 i = 0; i < device_count && engine->device_count < AUDIO_MAX_DEVICES; i++) { // Check if device has output channels AudioObjectPropertyAddress stream_prop = { kAudioDevicePropertyStreamConfiguration, @@ -140,9 +140,9 @@ static void enumerate_output_devices(AudioEngine *engine) { continue; } - int output_channels = 0; + S32 output_channels = 0; for (UInt32 b = 0; b < buf_list->mNumberBuffers; b++) - output_channels += (int)buf_list->mBuffers[b].mNumberChannels; + output_channels += (S32)buf_list->mBuffers[b].mNumberChannels; free(buf_list); if (output_channels == 0) continue; @@ -159,7 +159,7 @@ static void enumerate_output_devices(AudioEngine *engine) { if (AudioObjectGetPropertyData(device_ids[i], &name_prop, 0, nullptr, &name_size, &name_ref) != noErr) continue; - int32_t idx = engine->device_count++; + S32 idx = engine->device_count++; CFStringGetCString(name_ref, engine->devices[idx].name, sizeof(engine->devices[idx].name), kCFStringEncodingUTF8); CFRelease(name_ref); @@ -198,16 +198,16 @@ void audio_refresh_devices(AudioEngine *engine) { enumerate_output_devices(engine); } -int32_t audio_get_device_count(AudioEngine *engine) { +S32 audio_get_device_count(AudioEngine *engine) { return engine->device_count; } -AudioDeviceInfo *audio_get_device(AudioEngine *engine, int32_t index) { +AudioDeviceInfo *audio_get_device(AudioEngine *engine, S32 index) { if (index < 0 || index >= engine->device_count) return nullptr; return &engine->devices[index]; } -bool audio_open_device(AudioEngine *engine, int32_t index) { +B32 audio_open_device(AudioEngine *engine, S32 index) { audio_close_device(engine); if (index < 0 || index >= engine->device_count) return false; @@ -328,16 +328,16 @@ void audio_play_test_tone(AudioEngine *engine) { if (!engine->graph) return; engine->test_tone_phase = 0.0; - int32_t total_samples = (int32_t)(engine->sample_rate * AUDIO_TEST_TONE_SEC); + S32 total_samples = (S32)(engine->sample_rate * AUDIO_TEST_TONE_SEC); atomic_store(&engine->test_tone_samples_remaining, total_samples); atomic_store(&engine->test_tone_active, 1); } -bool audio_is_test_tone_playing(AudioEngine *engine) { +B32 audio_is_test_tone_playing(AudioEngine *engine) { return atomic_load(&engine->test_tone_active) != 0; } -void audio_update(AudioEngine *engine, float dt) { +void audio_update(AudioEngine *engine, F32 dt) { (void)engine; (void)dt; } diff --git a/src/base/base_core.h b/src/base/base_core.h index 4851e8b..50b5553 100644 --- a/src/base/base_core.h +++ b/src/base/base_core.h @@ -17,6 +17,8 @@ #endif #define local_persist static +#define trvke true + //////////////////////////////// // Base types diff --git a/src/base/base_strings.cpp b/src/base/base_strings.cpp index 7f17306..87eebcb 100644 --- a/src/base/base_strings.cpp +++ b/src/base/base_strings.cpp @@ -5,7 +5,7 @@ Str8 str8_pushf(Arena *arena, const char *fmt, ...) { va_list args, args2; va_start(args, fmt); va_copy(args2, args); - int len = vsnprintf(nullptr, 0, fmt, args); + S32 len = vsnprintf(nullptr, 0, fmt, args); va_end(args); char *buf = push_array(arena, char, len + 1); diff --git a/src/main.cpp b/src/main.cpp index 119d75b..0bc06d7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,9 +70,9 @@ struct AppState { B32 show_log; B32 show_midi_devices; #ifdef __APPLE__ - uint64_t freq_numer; - uint64_t freq_denom; - uint64_t last_time; + U64 freq_numer; + U64 freq_denom; + U64 last_time; #else LARGE_INTEGER freq; LARGE_INTEGER last_time; @@ -88,11 +88,11 @@ struct AppState { // Demo widget state B32 demo_checkbox_a; B32 demo_checkbox_b; - int32_t demo_radio_sel; - int32_t demo_dropdown_sel; + S32 demo_radio_sel; + S32 demo_dropdown_sel; char demo_text_a[128]; char demo_text_b[128]; - int32_t demo_button_count; + S32 demo_button_count; // Modal / window demo state B32 show_settings_window; @@ -163,22 +163,22 @@ struct AppState { #define PIANO_BLACK_W 11.0f #define PIANO_BLACK_H_PCT 0.6f -static bool piano_is_black_key(int note) { - int n = note % 12; +static B32 piano_is_black_key(S32 note) { + S32 n = note % 12; return n == 1 || n == 3 || n == 6 || n == 8 || n == 10; } // Velocity-based color: blue (vel 0) → green (mid) → red (vel 127) -static Clay_Color velocity_color(int32_t velocity) { - float t = (float)velocity / 127.0f; - float r, g, b; +static Clay_Color velocity_color(S32 velocity) { + F32 t = (F32)velocity / 127.0f; + F32 r, g, b; if (t < 0.5f) { - float s = t * 2.0f; + F32 s = t * 2.0f; r = 40.0f + s * (76.0f - 40.0f); g = 120.0f + s * (175.0f - 120.0f); b = 220.0f + s * (80.0f - 220.0f); } else { - float s = (t - 0.5f) * 2.0f; + F32 s = (t - 0.5f) * 2.0f; r = 76.0f + s * (220.0f - 76.0f); g = 175.0f + s * (50.0f - 175.0f); b = 80.0f + s * (40.0f - 80.0f); @@ -198,14 +198,14 @@ static void update_piano_input(AppState *app) { // Find hovered piano key — check black keys first (they're on top) S32 hovered_note = -1; - for (int note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) { + for (S32 note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) { if (piano_is_black_key(note) && Clay_PointerOver(CLAY_IDI("PKey", note))) { hovered_note = note; break; } } if (hovered_note == -1) { - for (int note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) { + for (S32 note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) { if (!piano_is_black_key(note) && Clay_PointerOver(CLAY_IDI("PKey", note))) { hovered_note = note; break; @@ -225,7 +225,7 @@ static void build_browser_panel(AppState *app) { if (!app->show_browser) return; Clay_Color bp_top = g_theme.bg_medium; - Clay_Color bp_bot = {(float)Max((int)bp_top.r-8,0), (float)Max((int)bp_top.g-8,0), (float)Max((int)bp_top.b-8,0), 255}; + Clay_Color bp_bot = {(F32)Max((S32)bp_top.r-8,0), (F32)Max((S32)bp_top.g-8,0), (F32)Max((S32)bp_top.b-8,0), 255}; CustomGradientData *bp_grad = alloc_gradient(bp_top, bp_bot); CLAY(CLAY_ID("BrowserPanel"), @@ -262,7 +262,7 @@ static void build_browser_panel(AppState *app) { static void build_main_panel(AppState *app) { Clay_Color mp_top = g_theme.bg_light; - Clay_Color mp_bot = {(float)Max((int)mp_top.r-8,0), (float)Max((int)mp_top.g-8,0), (float)Max((int)mp_top.b-8,0), 255}; + Clay_Color mp_bot = {(F32)Max((S32)mp_top.r-8,0), (F32)Max((S32)mp_top.g-8,0), (F32)Max((S32)mp_top.b-8,0), 255}; CustomGradientData *mp_grad = alloc_gradient(mp_top, mp_bot); CLAY(CLAY_ID("MainPanel"), @@ -469,14 +469,14 @@ static void build_main_panel(AppState *app) { { Clay_ScrollContainerData scroll_data = Clay_GetScrollContainerData(CLAY_ID("MainContent")); if (scroll_data.found && scroll_data.contentDimensions.height > scroll_data.scrollContainerDimensions.height) { - float track_h = scroll_data.scrollContainerDimensions.height; - float content_h = scroll_data.contentDimensions.height; - float visible_ratio = track_h / content_h; - float thumb_h = Max(visible_ratio * track_h, uis(24)); - float scroll_range = content_h - track_h; - float scroll_pct = scroll_range > 0 ? -scroll_data.scrollPosition->y / scroll_range : 0; - float thumb_y = scroll_pct * (track_h - thumb_h); - float bar_w = uis(8); + F32 track_h = scroll_data.scrollContainerDimensions.height; + F32 content_h = scroll_data.contentDimensions.height; + F32 visible_ratio = track_h / content_h; + F32 thumb_h = Max(visible_ratio * track_h, uis(24)); + F32 scroll_range = content_h - track_h; + F32 scroll_pct = scroll_range > 0 ? -scroll_data.scrollPosition->y / scroll_range : 0; + F32 thumb_y = scroll_pct * (track_h - thumb_h); + F32 bar_w = uis(8); // Handle scrollbar drag Clay_ElementId thumb_id = CLAY_ID("MainScrollThumb"); @@ -493,8 +493,8 @@ static void build_main_panel(AppState *app) { } else if (mouse_clicked && track_hovered && !thumb_hovered) { // Click on track: jump scroll position so thumb centers on click Clay_BoundingBox track_bb = Clay_GetElementData(track_id).boundingBox; - float click_rel = input.mouse_pos.y - track_bb.y; - float target_pct = (click_rel - thumb_h / 2) / (track_h - thumb_h); + F32 click_rel = input.mouse_pos.y - track_bb.y; + F32 target_pct = (click_rel - thumb_h / 2) / (track_h - thumb_h); if (target_pct < 0) target_pct = 0; if (target_pct > 1) target_pct = 1; scroll_data.scrollPosition->y = -target_pct * scroll_range; @@ -509,9 +509,9 @@ static void build_main_panel(AppState *app) { } if (app->scrollbar_dragging) { - float dy = input.mouse_pos.y - app->scrollbar_drag_start_y; - float scroll_per_px = scroll_range / (track_h - thumb_h); - float new_scroll = app->scrollbar_drag_start_scroll - dy * scroll_per_px; + F32 dy = input.mouse_pos.y - app->scrollbar_drag_start_y; + F32 scroll_per_px = scroll_range / (track_h - thumb_h); + F32 new_scroll = app->scrollbar_drag_start_scroll - dy * scroll_per_px; if (new_scroll > 0) new_scroll = 0; if (new_scroll < -scroll_range) new_scroll = -scroll_range; scroll_data.scrollPosition->y = new_scroll; @@ -521,9 +521,9 @@ static void build_main_panel(AppState *app) { Clay_Color thumb_color = g_theme.scrollbar_grab; if (app->scrollbar_dragging || thumb_hovered) { thumb_color = Clay_Color{ - (float)Min((int)thumb_color.r + 30, 255), - (float)Min((int)thumb_color.g + 30, 255), - (float)Min((int)thumb_color.b + 30, 255), + (F32)Min((S32)thumb_color.r + 30, 255), + (F32)Min((S32)thumb_color.g + 30, 255), + (F32)Min((S32)thumb_color.b + 30, 255), thumb_color.a }; } @@ -562,7 +562,7 @@ static void build_right_panel(AppState *app) { static const char *right_tabs[] = { "Properties", "MIDI Devices" }; Clay_Color rp_top = g_theme.bg_medium; - Clay_Color rp_bot = {(float)Max((int)rp_top.r-8,0), (float)Max((int)rp_top.g-8,0), (float)Max((int)rp_top.b-8,0), 255}; + Clay_Color rp_bot = {(F32)Max((S32)rp_top.r-8,0), (F32)Max((S32)rp_top.g-8,0), (F32)Max((S32)rp_top.b-8,0), 255}; CustomGradientData *rp_grad = alloc_gradient(rp_top, rp_bot); CLAY(CLAY_ID("RightPanel"), @@ -627,7 +627,7 @@ static void build_right_panel(AppState *app) { } static char device_bufs[64][128]; - int32_t device_count = midi_get_device_count(midi); + S32 device_count = midi_get_device_count(midi); // --- Inputs section --- CLAY_TEXT(CLAY_STRING("Inputs"), &g_text_config_dim); @@ -642,12 +642,12 @@ static void build_right_panel(AppState *app) { box_text_config.wrapMode = CLAY_TEXT_WRAP_NONE; B32 has_inputs = 0; - for (int32_t i = 0; i < device_count && i < 64; i++) { + for (S32 i = 0; i < device_count && i < 64; i++) { MidiDeviceInfo *dev = midi_get_device(midi, i); if (!dev->is_input) continue; has_inputs = 1; - int len = snprintf(device_bufs[i], sizeof(device_bufs[i]), "%s", dev->name); + S32 len = snprintf(device_bufs[i], sizeof(device_bufs[i]), "%s", dev->name); Clay_String device_str = { .isStaticallyAllocated = false, .length = len, .chars = device_bufs[i] }; // Velocity-based color: blue (vel 0) → green (mid) → red (vel 127) @@ -662,10 +662,10 @@ static void build_right_panel(AppState *app) { } // Box text: note name when held, "OFF" when releasing, "---" when idle - int nlen; + S32 nlen; if (dev->active) { - int pitch = dev->note % 12; - int octave = (dev->note / 12) - 1; + S32 pitch = dev->note % 12; + S32 octave = (dev->note / 12) - 1; nlen = snprintf(note_bufs[i], sizeof(note_bufs[i]), "%s%d", note_names[pitch], octave); } else if (dev->releasing) { nlen = snprintf(note_bufs[i], sizeof(note_bufs[i]), "OFF"); @@ -682,7 +682,7 @@ static void build_right_panel(AppState *app) { if (dev->releasing) box_txt = &box_text_dark; // Velocity text - int vlen; + S32 vlen; if (dev->active) vlen = snprintf(vel_bufs[i], sizeof(vel_bufs[i]), "%d", dev->velocity); else @@ -723,12 +723,12 @@ static void build_right_panel(AppState *app) { CLAY_TEXT(CLAY_STRING("Outputs"), &g_text_config_dim); B32 has_outputs = 0; - for (int32_t i = 0; i < device_count && i < 64; i++) { + for (S32 i = 0; i < device_count && i < 64; i++) { MidiDeviceInfo *dev = midi_get_device(midi, i); if (dev->is_input) continue; has_outputs = 1; - int len = snprintf(device_bufs[i], sizeof(device_bufs[i]), "%s", dev->name); + S32 len = snprintf(device_bufs[i], sizeof(device_bufs[i]), "%s", dev->name); Clay_String device_str = { .isStaticallyAllocated = false, .length = len, .chars = device_bufs[i] }; CLAY(CLAY_IDI("MidiOut", i), @@ -752,7 +752,7 @@ static void build_log_panel(AppState *app) { if (!app->show_log) return; Clay_Color lp_top = g_theme.bg_medium; - Clay_Color lp_bot = {(float)Max((int)lp_top.r-8,0), (float)Max((int)lp_top.g-8,0), (float)Max((int)lp_top.b-8,0), 255}; + Clay_Color lp_bot = {(F32)Max((S32)lp_top.r-8,0), (F32)Max((S32)lp_top.g-8,0), (F32)Max((S32)lp_top.b-8,0), 255}; CustomGradientData *lp_grad = alloc_gradient(lp_top, lp_bot); CLAY(CLAY_ID("LogPanel"), @@ -808,7 +808,7 @@ static void build_log_panel(AppState *app) { if (black_key_w < uis(8)) black_key_w = uis(8); // White keys (grow to fill width and height) - for (int note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) { + for (S32 note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) { if (piano_is_black_key(note)) continue; B32 midi_held = midi_is_note_held(app->midi, note); @@ -832,7 +832,7 @@ static void build_log_panel(AppState *app) { } // Black keys (floating, attached to left white key) - for (int note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) { + for (S32 note = PIANO_FIRST_NOTE; note <= PIANO_LAST_NOTE; note++) { if (!piano_is_black_key(note)) continue; Clay_ElementId parent_wkey = CLAY_IDI("PKey", note - 1); @@ -923,9 +923,9 @@ static void settings_window_content(void *user_data) { ui_label("SettingsLblAudio", "Audio Device"); static const char *audio_options[AUDIO_MAX_DEVICES + 1]; - int32_t audio_count = audio_get_device_count(app->audio); + S32 audio_count = audio_get_device_count(app->audio); audio_options[0] = "None"; - for (int32_t i = 0; i < audio_count && i < AUDIO_MAX_DEVICES; i++) { + for (S32 i = 0; i < audio_count && i < AUDIO_MAX_DEVICES; i++) { AudioDeviceInfo *dev = audio_get_device(app->audio, i); audio_options[i + 1] = dev ? dev->name : "???"; } @@ -954,8 +954,8 @@ static void settings_window_content(void *user_data) { .layoutDirection = CLAY_LEFT_TO_RIGHT, } ) { - bool device_open = (app->audio_device_sel > 0); - bool tone_playing = audio_is_test_tone_playing(app->audio); + B32 device_open = (app->audio_device_sel > 0); + B32 tone_playing = audio_is_test_tone_playing(app->audio); if (device_open && !tone_playing) { if (ui_button("BtnTestTone", "Play Test Tone")) { @@ -1062,7 +1062,7 @@ static void update_panel_splitters(AppState *app) { static void build_header_bar(AppState *app) { Clay_Color bar_bg = g_theme.bg_dark; - Clay_Color border_bot = {(float)Max((int)bar_bg.r - 12, 0), (float)Max((int)bar_bg.g - 12, 0), (float)Max((int)bar_bg.b - 12, 0), 255}; + Clay_Color border_bot = {(F32)Max((S32)bar_bg.r - 12, 0), (F32)Max((S32)bar_bg.g - 12, 0), (F32)Max((S32)bar_bg.b - 12, 0), 255}; static Clay_TextElementConfig header_btn_active_text = {}; header_btn_active_text.textColor = Clay_Color{255, 255, 255, 255}; @@ -1084,7 +1084,7 @@ static void build_header_bar(AppState *app) { header_indicator_label.fontSize = FONT_SIZE_SMALL; header_indicator_label.wrapMode = CLAY_TEXT_WRAP_NONE; - Clay_Color inset_bg = {(float)Max((int)bar_bg.r - 8, 0), (float)Max((int)bar_bg.g - 8, 0), (float)Max((int)bar_bg.b - 8, 0), 255}; + Clay_Color inset_bg = {(F32)Max((S32)bar_bg.r - 8, 0), (F32)Max((S32)bar_bg.g - 8, 0), (F32)Max((S32)bar_bg.b - 8, 0), 255}; CLAY(CLAY_ID("HeaderBar"), .layout = { @@ -1297,7 +1297,7 @@ static void build_header_bar(AppState *app) { static void build_mix_view(AppState *app) { Clay_Color mv_top = g_theme.bg_medium; - Clay_Color mv_bot = {(float)Max((int)mv_top.r - 8, 0), (float)Max((int)mv_top.g - 8, 0), (float)Max((int)mv_top.b - 8, 0), 255}; + Clay_Color mv_bot = {(F32)Max((S32)mv_top.r - 8, 0), (F32)Max((S32)mv_top.g - 8, 0), (F32)Max((S32)mv_top.b - 8, 0), 255}; CustomGradientData *mv_grad = alloc_gradient(mv_top, mv_bot); CLAY(CLAY_ID("MixView"), @@ -1314,7 +1314,7 @@ static void build_mix_view(AppState *app) { static char fader_id_bufs[8][16]; static char pan_id_bufs[8][16]; - for (int i = 0; i < 8; i++) { + for (S32 i = 0; i < 8; i++) { snprintf(ch_label_bufs[i], sizeof(ch_label_bufs[i]), "Ch %d", i + 1); snprintf(fader_id_bufs[i], sizeof(fader_id_bufs[i]), "MixFader%d", i); snprintf(pan_id_bufs[i], sizeof(pan_id_bufs[i]), "MixPan%d", i); @@ -1333,7 +1333,7 @@ static void build_mix_view(AppState *app) { .border = { .color = g_theme.border, .width = { .right = 1 } }, ) { // Channel label - int llen = snprintf(ch_label_bufs[i], sizeof(ch_label_bufs[i]), "Ch %d", i + 1); + S32 llen = snprintf(ch_label_bufs[i], sizeof(ch_label_bufs[i]), "Ch %d", i + 1); Clay_String ch_str = { .isStaticallyAllocated = false, .length = llen, .chars = ch_label_bufs[i] }; CLAY_TEXT(ch_str, &g_text_config_dim); @@ -1367,9 +1367,9 @@ static void build_mix_view(AppState *app) { // Master strip (slightly wider, accent-tinted) { Clay_Color master_bg = { - (float)Min((int)g_theme.bg_medium.r + 6, 255), - (float)Min((int)g_theme.bg_medium.g + 6, 255), - (float)Min((int)g_theme.bg_medium.b + 6, 255), + (F32)Min((S32)g_theme.bg_medium.r + 6, 255), + (F32)Min((S32)g_theme.bg_medium.g + 6, 255), + (F32)Min((S32)g_theme.bg_medium.b + 6, 255), 255 }; static F32 master_fader = 0.0f; @@ -1420,7 +1420,7 @@ static void build_mix_view(AppState *app) { static void build_patch_view(AppState *app) { Clay_Color pv_top = g_theme.bg_medium; - Clay_Color pv_bot = {(float)Max((int)pv_top.r - 8, 0), (float)Max((int)pv_top.g - 8, 0), (float)Max((int)pv_top.b - 8, 0), 255}; + Clay_Color pv_bot = {(F32)Max((S32)pv_top.r - 8, 0), (F32)Max((S32)pv_top.g - 8, 0), (F32)Max((S32)pv_top.b - 8, 0), 255}; CustomGradientData *pv_grad = alloc_gradient(pv_top, pv_bot); CLAY(CLAY_ID("PatchView"), @@ -1495,7 +1495,7 @@ static void build_patch_view(AppState *app) { CLAY(CLAY_ID("IntOutputLabel"), .layout = { .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() }, - .padding = { (uint16_t)label_w, 0, 0, 0 }, + .padding = { (U16)label_w, 0, 0, 0 }, } ) { CLAY_TEXT(CLAY_STRING("OUTPUT >"), &matrix_axis_text); @@ -1526,8 +1526,8 @@ static void build_patch_view(AppState *app) { } static char int_dst_bufs[MATRIX_OUTPUTS][8]; - for (int d = 0; d < MATRIX_OUTPUTS; d++) { - int dlen; + for (S32 d = 0; d < MATRIX_OUTPUTS; d++) { + S32 dlen; if (d == 0) dlen = snprintf(int_dst_bufs[d], sizeof(int_dst_bufs[d]), "Mst"); else @@ -1547,8 +1547,8 @@ static void build_patch_view(AppState *app) { // Rows static char int_src_bufs[MATRIX_INPUTS][8]; - for (int s = 0; s < MATRIX_INPUTS; s++) { - int slen = snprintf(int_src_bufs[s], sizeof(int_src_bufs[s]), "Ch %d", s + 1); + for (S32 s = 0; s < MATRIX_INPUTS; s++) { + S32 slen = snprintf(int_src_bufs[s], sizeof(int_src_bufs[s]), "Ch %d", s + 1); Clay_String src_str = { .isStaticallyAllocated = false, .length = slen, .chars = int_src_bufs[s] }; CLAY(CLAY_IDI("IntRow", s), @@ -1567,8 +1567,8 @@ static void build_patch_view(AppState *app) { CLAY_TEXT(src_str, &matrix_hdr_text); } - for (int d = 0; d < MATRIX_OUTPUTS; d++) { - int cell_idx = s * MATRIX_OUTPUTS + d; + for (S32 d = 0; d < MATRIX_OUTPUTS; d++) { + S32 cell_idx = s * MATRIX_OUTPUTS + d; Clay_ElementId cell_eid = CLAY_IDI("IntCell", cell_idx); B32 cell_hovered = Clay_PointerOver(cell_eid); @@ -1580,9 +1580,9 @@ static void build_patch_view(AppState *app) { Clay_Color cell_bg; if (is_feedback) { cell_bg = Clay_Color{ - (float)Max((int)g_theme.bg_dark.r - 10, 0), - (float)Max((int)g_theme.bg_dark.g - 10, 0), - (float)Max((int)g_theme.bg_dark.b - 10, 0), 255 + (F32)Max((S32)g_theme.bg_dark.r - 10, 0), + (F32)Max((S32)g_theme.bg_dark.g - 10, 0), + (F32)Max((S32)g_theme.bg_dark.b - 10, 0), 255 }; } else if (active) { cell_bg = g_theme.accent; @@ -1592,17 +1592,17 @@ static void build_patch_view(AppState *app) { cell_bg = g_theme.bg_dark; } else { cell_bg = Clay_Color{ - (float)Min((int)g_theme.bg_dark.r + 6, 255), - (float)Min((int)g_theme.bg_dark.g + 6, 255), - (float)Min((int)g_theme.bg_dark.b + 6, 255), 255 + (F32)Min((S32)g_theme.bg_dark.r + 6, 255), + (F32)Min((S32)g_theme.bg_dark.g + 6, 255), + (F32)Min((S32)g_theme.bg_dark.b + 6, 255), 255 }; } if (d == 0 && !active && !cell_hovered && !is_feedback) { cell_bg = Clay_Color{ - (float)Min((int)cell_bg.r + 10, 255), - (float)Min((int)cell_bg.g + 10, 255), - (float)Min((int)cell_bg.b + 12, 255), 255 + (F32)Min((S32)cell_bg.r + 10, 255), + (F32)Min((S32)cell_bg.g + 10, 255), + (F32)Min((S32)cell_bg.b + 12, 255), 255 }; } @@ -1647,7 +1647,7 @@ static void build_patch_view(AppState *app) { CLAY(CLAY_ID("HwOutputLabel"), .layout = { .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() }, - .padding = { (uint16_t)label_w, 0, 0, 0 }, + .padding = { (U16)label_w, 0, 0, 0 }, } ) { CLAY_TEXT(CLAY_STRING("HW OUTPUT >"), &matrix_axis_text); @@ -1678,8 +1678,8 @@ static void build_patch_view(AppState *app) { } static char hw_dst_bufs[HW_OUTPUTS][8]; - for (int d = 0; d < HW_OUTPUTS; d++) { - int dlen = snprintf(hw_dst_bufs[d], sizeof(hw_dst_bufs[d]), "%d", d + 1); + for (S32 d = 0; d < HW_OUTPUTS; d++) { + S32 dlen = snprintf(hw_dst_bufs[d], sizeof(hw_dst_bufs[d]), "%d", d + 1); Clay_String dst_str = { .isStaticallyAllocated = false, .length = dlen, .chars = hw_dst_bufs[d] }; CLAY(CLAY_IDI("HwDstHdr", d), @@ -1695,8 +1695,8 @@ static void build_patch_view(AppState *app) { // Rows static char hw_src_bufs[HW_OUTPUTS][8]; - for (int s = 0; s < HW_OUTPUTS; s++) { - int slen = snprintf(hw_src_bufs[s], sizeof(hw_src_bufs[s]), "Out %d", s + 1); + for (S32 s = 0; s < HW_OUTPUTS; s++) { + S32 slen = snprintf(hw_src_bufs[s], sizeof(hw_src_bufs[s]), "Out %d", s + 1); Clay_String src_str = { .isStaticallyAllocated = false, .length = slen, .chars = hw_src_bufs[s] }; CLAY(CLAY_IDI("HwRow", s), @@ -1715,8 +1715,8 @@ static void build_patch_view(AppState *app) { CLAY_TEXT(src_str, &matrix_hdr_text); } - for (int d = 0; d < HW_OUTPUTS; d++) { - int cell_idx = s * HW_OUTPUTS + d; + for (S32 d = 0; d < HW_OUTPUTS; d++) { + S32 cell_idx = s * HW_OUTPUTS + d; Clay_ElementId cell_eid = CLAY_IDI("HwCell", cell_idx); B32 cell_hovered = Clay_PointerOver(cell_eid); B32 active = app->hw_matrix[s][d]; @@ -1730,9 +1730,9 @@ static void build_patch_view(AppState *app) { cell_bg = g_theme.bg_dark; } else { cell_bg = Clay_Color{ - (float)Min((int)g_theme.bg_dark.r + 6, 255), - (float)Min((int)g_theme.bg_dark.g + 6, 255), - (float)Min((int)g_theme.bg_dark.b + 6, 255), 255 + (F32)Min((S32)g_theme.bg_dark.r + 6, 255), + (F32)Min((S32)g_theme.bg_dark.g + 6, 255), + (F32)Min((S32)g_theme.bg_dark.b + 6, 255), 255 }; } @@ -1870,7 +1870,7 @@ static void build_ui(AppState *app) { static void do_frame(AppState *app) { // Timing #ifdef __APPLE__ - uint64_t now = mach_absolute_time(); + U64 now = mach_absolute_time(); F32 dt = (F32)(now - app->last_time) * (F32)app->freq_numer / ((F32)app->freq_denom * 1e9f); app->last_time = now; #else @@ -2043,7 +2043,7 @@ int main(int argc, char **argv) { app.log_height = 180.0f; app.panel_drag = 0; app.master_layout = 0; - for (int i = 0; i < 8; i++) { app.mix_faders[i] = 0.0f; app.mix_pans[i] = 0.0f; } + for (S32 i = 0; i < 8; i++) { app.mix_faders[i] = 0.0f; app.mix_pans[i] = 0.0f; } app.mix_master_pan = 0.0f; app.patch_tab = 0; memset(app.patch_matrix, 0, sizeof(app.patch_matrix)); @@ -2061,11 +2061,12 @@ int main(int argc, char **argv) { platform_set_frame_callback(window, frame_callback, &app); - while (platform_poll_events(window)) { + B32 running = 1; + while (running && platform_poll_events(window)) { // Menu commands - int32_t menu_cmd = platform_poll_menu_command(window); + S32 menu_cmd = platform_poll_menu_command(window); switch (menu_cmd) { - case MENU_FILE_EXIT: goto exit_app; + case MENU_FILE_EXIT: running = 0; break; case MENU_VIEW_BROWSER: app.show_browser = !app.show_browser; break; case MENU_VIEW_PROPERTIES:app.show_props = !app.show_props; break; case MENU_VIEW_LOG: app.show_log = !app.show_log; break; @@ -2073,10 +2074,9 @@ int main(int argc, char **argv) { default: break; } - do_frame(&app); + if (running) do_frame(&app); } -exit_app: audio_destroy(audio); midi_destroy(midi); ui_destroy(ui); diff --git a/src/midi/midi.h b/src/midi/midi.h index bae3367..515a121 100644 --- a/src/midi/midi.h +++ b/src/midi/midi.h @@ -1,32 +1,31 @@ #pragma once -#include -#include +#include "base/base_core.h" struct MidiEngine; struct MidiDeviceInfo { char name[64]; - int32_t id; - bool is_input; - bool active; // true when note(s) currently held - bool releasing; // true during release flash - int32_t velocity; // last note-on velocity (0-127) - int32_t note; // last MIDI note number (0-127) + S32 id; + B32 is_input; + B32 active; // true when note(s) currently held + B32 releasing; // true during release flash + S32 velocity; // last note-on velocity (0-127) + S32 note; // last MIDI note number (0-127) }; MidiEngine *midi_create(); void midi_destroy(MidiEngine *engine); void midi_refresh_devices(MidiEngine *engine); -int32_t midi_get_device_count(MidiEngine *engine); -MidiDeviceInfo *midi_get_device(MidiEngine *engine, int32_t index); +S32 midi_get_device_count(MidiEngine *engine); +MidiDeviceInfo *midi_get_device(MidiEngine *engine, S32 index); void midi_open_all_inputs(MidiEngine *engine); void midi_close_all_inputs(MidiEngine *engine); -void midi_update(MidiEngine *engine, float dt); -bool midi_is_input_active(MidiEngine *engine, int32_t device_index); +void midi_update(MidiEngine *engine, F32 dt); +B32 midi_is_input_active(MidiEngine *engine, S32 device_index); // Per-note state: returns true if note (0-127) is currently held on any input device -bool midi_is_note_held(MidiEngine *engine, int32_t note); +B32 midi_is_note_held(MidiEngine *engine, S32 note); // Returns the last note-on velocity (0-127) for a given note, or 0 if not held -int32_t midi_get_note_velocity(MidiEngine *engine, int32_t note); +S32 midi_get_note_velocity(MidiEngine *engine, S32 note); diff --git a/src/midi/midi_coremidi.cpp b/src/midi/midi_coremidi.cpp index 05dd45d..4e840a4 100644 --- a/src/midi/midi_coremidi.cpp +++ b/src/midi/midi_coremidi.cpp @@ -9,28 +9,28 @@ struct MidiEngine { MidiDeviceInfo devices[MIDI_MAX_DEVICES]; - int32_t device_count; + S32 device_count; MIDIClientRef client; MIDIPortRef input_port; // Map: source endpoint index -> our device array index - int32_t source_to_device[MIDI_MAX_DEVICES]; + S32 source_to_device[MIDI_MAX_DEVICES]; // Set atomically from callback thread - _Atomic int32_t pending_note_on_vel[MIDI_MAX_DEVICES]; - _Atomic int32_t pending_note_num[MIDI_MAX_DEVICES]; - _Atomic int32_t pending_note_off[MIDI_MAX_DEVICES]; - _Atomic int32_t held_note_count[MIDI_MAX_DEVICES]; + _Atomic S32 pending_note_on_vel[MIDI_MAX_DEVICES]; + _Atomic S32 pending_note_num[MIDI_MAX_DEVICES]; + _Atomic S32 pending_note_off[MIDI_MAX_DEVICES]; + _Atomic S32 held_note_count[MIDI_MAX_DEVICES]; // Per-note state (across all devices), set atomically from callback - _Atomic int32_t note_states[128]; // held count - _Atomic int32_t note_velocities[128]; // last note-on velocity + _Atomic S32 note_states[128]; // held count + _Atomic S32 note_velocities[128]; // last note-on velocity // Main thread only - int32_t display_velocity[MIDI_MAX_DEVICES]; - int32_t display_note[MIDI_MAX_DEVICES]; - float release_timers[MIDI_MAX_DEVICES]; + S32 display_velocity[MIDI_MAX_DEVICES]; + S32 display_note[MIDI_MAX_DEVICES]; + F32 release_timers[MIDI_MAX_DEVICES]; }; //////////////////////////////// @@ -40,51 +40,51 @@ static void midi_read_callback(const MIDIPacketList *pktlist, void *readProcRefC (void)readProcRefCon; MidiEngine *engine = (MidiEngine *)readProcRefCon; - int32_t device_idx = (int32_t)(intptr_t)srcConnRefCon; + S32 device_idx = (S32)(intptr_t)srcConnRefCon; if (!engine || device_idx < 0 || device_idx >= MIDI_MAX_DEVICES) return; const MIDIPacket *packet = &pktlist->packet[0]; for (UInt32 i = 0; i < pktlist->numPackets; i++) { // Parse MIDI bytes for (UInt16 j = 0; j < packet->length; ) { - uint8_t status = packet->data[j]; + U8 status = packet->data[j]; // Skip non-status bytes (running status not handled for simplicity) if (status < 0x80) { j++; continue; } - uint8_t kind = status & 0xF0; + U8 kind = status & 0xF0; if (kind == 0x90 && j + 2 < packet->length) { - uint8_t note = packet->data[j + 1]; - uint8_t velocity = packet->data[j + 2]; + U8 note = packet->data[j + 1]; + U8 velocity = packet->data[j + 2]; j += 3; if (velocity > 0) { - atomic_store(&engine->pending_note_on_vel[device_idx], (int32_t)velocity); - atomic_store(&engine->pending_note_num[device_idx], (int32_t)(note + 1)); + atomic_store(&engine->pending_note_on_vel[device_idx], (S32)velocity); + atomic_store(&engine->pending_note_num[device_idx], (S32)(note + 1)); atomic_fetch_add(&engine->held_note_count[device_idx], 1); if (note < 128) { atomic_fetch_add(&engine->note_states[note], 1); - atomic_store(&engine->note_velocities[note], (int32_t)velocity); + atomic_store(&engine->note_velocities[note], (S32)velocity); } } else { // Note-on with velocity 0 = note-off atomic_store(&engine->pending_note_off[device_idx], 1); - int32_t count = atomic_fetch_sub(&engine->held_note_count[device_idx], 1); + S32 count = atomic_fetch_sub(&engine->held_note_count[device_idx], 1); if (count <= 1) atomic_store(&engine->held_note_count[device_idx], 0); if (note < 128) { - int32_t c = atomic_fetch_sub(&engine->note_states[note], 1); + S32 c = atomic_fetch_sub(&engine->note_states[note], 1); if (c <= 1) atomic_store(&engine->note_states[note], 0); } } } else if (kind == 0x80 && j + 2 < packet->length) { - uint8_t note_off = packet->data[j + 1]; + U8 note_off = packet->data[j + 1]; j += 3; atomic_store(&engine->pending_note_off[device_idx], 1); - int32_t count = atomic_fetch_sub(&engine->held_note_count[device_idx], 1); + S32 count = atomic_fetch_sub(&engine->held_note_count[device_idx], 1); if (count <= 1) atomic_store(&engine->held_note_count[device_idx], 0); if (note_off < 128) { - int32_t c = atomic_fetch_sub(&engine->note_states[note_off], 1); + S32 c = atomic_fetch_sub(&engine->note_states[note_off], 1); if (c <= 1) atomic_store(&engine->note_states[note_off], 0); } } else if (kind == 0xC0 || kind == 0xD0) { @@ -123,7 +123,7 @@ static void enumerate_midi_devices(MidiEngine *engine) { CFStringGetCString(name_ref, dev->name, sizeof(dev->name), kCFStringEncodingUTF8); CFRelease(name_ref); } else { - snprintf(dev->name, sizeof(dev->name), "MIDI Source %d", (int)i); + snprintf(dev->name, sizeof(dev->name), "MIDI Source %d", (S32)i); } dev->id = engine->device_count; @@ -149,7 +149,7 @@ static void enumerate_midi_devices(MidiEngine *engine) { CFStringGetCString(name_ref, dev->name, sizeof(dev->name), kCFStringEncodingUTF8); CFRelease(name_ref); } else { - snprintf(dev->name, sizeof(dev->name), "MIDI Dest %d", (int)i); + snprintf(dev->name, sizeof(dev->name), "MIDI Dest %d", (S32)i); } dev->id = engine->device_count; @@ -183,9 +183,9 @@ void midi_destroy(MidiEngine *engine) { void midi_open_all_inputs(MidiEngine *engine) { ItemCount num_sources = MIDIGetNumberOfSources(); - for (ItemCount i = 0; i < num_sources && (int32_t)i < MIDI_MAX_DEVICES; i++) { + for (ItemCount i = 0; i < num_sources && (S32)i < MIDI_MAX_DEVICES; i++) { MIDIEndpointRef endpoint = MIDIGetSource(i); - int32_t dev_idx = engine->source_to_device[i]; + S32 dev_idx = engine->source_to_device[i]; MIDIPortConnectSource(engine->input_port, endpoint, (void *)(intptr_t)dev_idx); } } @@ -197,7 +197,7 @@ void midi_close_all_inputs(MidiEngine *engine) { MIDIPortDisconnectSource(engine->input_port, endpoint); } - for (int32_t i = 0; i < MIDI_MAX_DEVICES; i++) { + for (S32 i = 0; i < MIDI_MAX_DEVICES; i++) { atomic_store(&engine->pending_note_on_vel[i], 0); atomic_store(&engine->pending_note_num[i], 0); atomic_store(&engine->pending_note_off[i], 0); @@ -206,23 +206,23 @@ void midi_close_all_inputs(MidiEngine *engine) { engine->display_note[i] = 0; engine->release_timers[i] = 0.0f; } - for (int32_t i = 0; i < 128; i++) { + for (S32 i = 0; i < 128; i++) { atomic_store(&engine->note_states[i], 0); atomic_store(&engine->note_velocities[i], 0); } } -void midi_update(MidiEngine *engine, float dt) { - for (int32_t i = 0; i < engine->device_count; i++) { +void midi_update(MidiEngine *engine, F32 dt) { + for (S32 i = 0; i < engine->device_count; i++) { if (!engine->devices[i].is_input) continue; - int32_t vel = atomic_exchange(&engine->pending_note_on_vel[i], 0); - int32_t note_p1 = atomic_exchange(&engine->pending_note_num[i], 0); + S32 vel = atomic_exchange(&engine->pending_note_on_vel[i], 0); + S32 note_p1 = atomic_exchange(&engine->pending_note_num[i], 0); if (vel > 0) engine->display_velocity[i] = vel; if (note_p1 > 0) engine->display_note[i] = note_p1 - 1; - int32_t off = atomic_exchange(&engine->pending_note_off[i], 0); - int32_t held = atomic_load(&engine->held_note_count[i]); + S32 off = atomic_exchange(&engine->pending_note_off[i], 0); + S32 held = atomic_load(&engine->held_note_count[i]); if (held > 0) { engine->devices[i].active = true; @@ -249,17 +249,17 @@ void midi_update(MidiEngine *engine, float dt) { } } -bool midi_is_input_active(MidiEngine *engine, int32_t device_index) { +B32 midi_is_input_active(MidiEngine *engine, S32 device_index) { if (device_index < 0 || device_index >= engine->device_count) return false; return engine->devices[device_index].active; } -bool midi_is_note_held(MidiEngine *engine, int32_t note) { +B32 midi_is_note_held(MidiEngine *engine, S32 note) { if (note < 0 || note > 127) return false; return atomic_load(&engine->note_states[note]) > 0; } -int32_t midi_get_note_velocity(MidiEngine *engine, int32_t note) { +S32 midi_get_note_velocity(MidiEngine *engine, S32 note) { if (note < 0 || note > 127) return 0; if (atomic_load(&engine->note_states[note]) <= 0) return 0; return atomic_load(&engine->note_velocities[note]); @@ -271,11 +271,11 @@ void midi_refresh_devices(MidiEngine *engine) { midi_open_all_inputs(engine); } -int32_t midi_get_device_count(MidiEngine *engine) { +S32 midi_get_device_count(MidiEngine *engine) { return engine->device_count; } -MidiDeviceInfo *midi_get_device(MidiEngine *engine, int32_t index) { +MidiDeviceInfo *midi_get_device(MidiEngine *engine, S32 index) { if (index < 0 || index >= engine->device_count) return nullptr; return &engine->devices[index]; } diff --git a/src/midi/midi_win32.cpp b/src/midi/midi_win32.cpp index f157fff..4e20f85 100644 --- a/src/midi/midi_win32.cpp +++ b/src/midi/midi_win32.cpp @@ -8,7 +8,7 @@ struct MidiEngine { MidiDeviceInfo devices[MIDI_MAX_DEVICES]; - int32_t device_count; + S32 device_count; HMIDIIN input_handles[MIDI_MAX_DEVICES]; @@ -23,9 +23,9 @@ struct MidiEngine { volatile LONG note_velocities[128]; // last note-on velocity // Main thread only - int32_t display_velocity[MIDI_MAX_DEVICES]; - int32_t display_note[MIDI_MAX_DEVICES]; - float release_timers[MIDI_MAX_DEVICES]; + S32 display_velocity[MIDI_MAX_DEVICES]; + S32 display_note[MIDI_MAX_DEVICES]; + F32 release_timers[MIDI_MAX_DEVICES]; }; //////////////////////////////// @@ -41,7 +41,7 @@ static void CALLBACK midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwIn if (wMsg != MIM_DATA) return; if (!g_midi_engine) return; - int32_t idx = (int32_t)dwInstance; + S32 idx = (S32)dwInstance; if (idx < 0 || idx >= MIDI_MAX_DEVICES) return; BYTE status = (BYTE)(dwParam1 & 0xFF); @@ -86,7 +86,7 @@ void midi_destroy(MidiEngine *engine) { } void midi_open_all_inputs(MidiEngine *engine) { - for (int32_t i = 0; i < engine->device_count; i++) { + for (S32 i = 0; i < engine->device_count; i++) { MidiDeviceInfo *dev = &engine->devices[i]; if (!dev->is_input) continue; if (engine->input_handles[i]) continue; // already open @@ -103,7 +103,7 @@ void midi_open_all_inputs(MidiEngine *engine) { } void midi_close_all_inputs(MidiEngine *engine) { - for (int32_t i = 0; i < MIDI_MAX_DEVICES; i++) { + for (S32 i = 0; i < MIDI_MAX_DEVICES; i++) { if (engine->input_handles[i]) { midiInStop(engine->input_handles[i]); midiInClose(engine->input_handles[i]); @@ -117,24 +117,24 @@ void midi_close_all_inputs(MidiEngine *engine) { engine->display_note[i] = 0; engine->release_timers[i] = 0.0f; } - for (int32_t i = 0; i < 128; i++) { + for (S32 i = 0; i < 128; i++) { engine->note_states[i] = 0; engine->note_velocities[i] = 0; } } -void midi_update(MidiEngine *engine, float dt) { - for (int32_t i = 0; i < engine->device_count; i++) { +void midi_update(MidiEngine *engine, F32 dt) { + for (S32 i = 0; i < engine->device_count; i++) { if (!engine->devices[i].is_input) continue; // Consume pending note-on velocity and note number LONG vel = InterlockedExchange(&engine->pending_note_on_vel[i], 0); LONG note_p1 = InterlockedExchange(&engine->pending_note_num[i], 0); if (vel > 0) { - engine->display_velocity[i] = (int32_t)vel; + engine->display_velocity[i] = (S32)vel; } if (note_p1 > 0) { - engine->display_note[i] = (int32_t)(note_p1 - 1); + engine->display_note[i] = (S32)(note_p1 - 1); } // Consume pending note-off @@ -170,21 +170,21 @@ void midi_update(MidiEngine *engine, float dt) { } } -bool midi_is_input_active(MidiEngine *engine, int32_t device_index) { +B32 midi_is_input_active(MidiEngine *engine, S32 device_index) { if (device_index < 0 || device_index >= engine->device_count) return false; return engine->devices[device_index].active; } -bool midi_is_note_held(MidiEngine *engine, int32_t note) { +B32 midi_is_note_held(MidiEngine *engine, S32 note) { if (note < 0 || note > 127) return false; return engine->note_states[note] > 0; } -int32_t midi_get_note_velocity(MidiEngine *engine, int32_t note) { +S32 midi_get_note_velocity(MidiEngine *engine, S32 note) { if (note < 0 || note > 127) return 0; if (engine->note_states[note] <= 0) return 0; - return (int32_t)engine->note_velocities[note]; + return (S32)engine->note_velocities[note]; } void midi_refresh_devices(MidiEngine *engine) { @@ -197,7 +197,7 @@ void midi_refresh_devices(MidiEngine *engine) { if (midiInGetDevCapsA(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) { MidiDeviceInfo *dev = &engine->devices[engine->device_count++]; strncpy_s(dev->name, sizeof(dev->name), caps.szPname, _TRUNCATE); - dev->id = (int32_t)i; + dev->id = (S32)i; dev->is_input = true; dev->active = false; } @@ -209,7 +209,7 @@ void midi_refresh_devices(MidiEngine *engine) { if (midiOutGetDevCapsA(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) { MidiDeviceInfo *dev = &engine->devices[engine->device_count++]; strncpy_s(dev->name, sizeof(dev->name), caps.szPname, _TRUNCATE); - dev->id = (int32_t)i; + dev->id = (S32)i; dev->is_input = false; dev->active = false; } @@ -218,11 +218,11 @@ void midi_refresh_devices(MidiEngine *engine) { midi_open_all_inputs(engine); } -int32_t midi_get_device_count(MidiEngine *engine) { +S32 midi_get_device_count(MidiEngine *engine) { return engine->device_count; } -MidiDeviceInfo *midi_get_device(MidiEngine *engine, int32_t index) { +MidiDeviceInfo *midi_get_device(MidiEngine *engine, S32 index) { if (index < 0 || index >= engine->device_count) return nullptr; return &engine->devices[index]; diff --git a/src/platform/platform.h b/src/platform/platform.h index 88d3ad4..61dc393 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -1,7 +1,5 @@ #pragma once -#include -#include #include "base/base_core.h" #include "base/base_math.h" @@ -35,16 +33,16 @@ enum { struct PlatformInput { // Typed characters (UTF-16 code units, printable only) - uint16_t chars[PLATFORM_MAX_CHARS_PER_FRAME]; - int32_t char_count; + U16 chars[PLATFORM_MAX_CHARS_PER_FRAME]; + S32 char_count; // Key-down events (virtual key codes) - uint8_t keys[PLATFORM_MAX_KEYS_PER_FRAME]; - int32_t key_count; + U8 keys[PLATFORM_MAX_KEYS_PER_FRAME]; + S32 key_count; // Modifier state at time of last key event - bool ctrl_held; - bool shift_held; + B32 ctrl_held; + B32 shift_held; // Mouse state (polled per frame) Vec2F32 mouse_pos; @@ -57,19 +55,19 @@ struct PlatformWindow; struct PlatformWindowDesc { const char *title = "autosample"; - int32_t width = 1280; - int32_t height = 720; + S32 width = 1280; + S32 height = 720; }; struct PlatformMenuItem { const char *label; // nullptr = separator - int32_t id; // command ID (ignored for separators) + S32 id; // command ID (ignored for separators) }; struct PlatformMenu { const char *label; PlatformMenuItem *items; - int32_t item_count; + S32 item_count; }; // Called by the platform layer when the window needs a frame rendered @@ -79,13 +77,13 @@ typedef void (*PlatformFrameCallback)(void *user_data); PlatformWindow *platform_create_window(PlatformWindowDesc *desc); void platform_destroy_window(PlatformWindow *window); -bool platform_poll_events(PlatformWindow *window); -void platform_get_size(PlatformWindow *window, int32_t *w, int32_t *h); +B32 platform_poll_events(PlatformWindow *window); +void platform_get_size(PlatformWindow *window, S32 *w, S32 *h); void *platform_get_native_handle(PlatformWindow *window); void platform_set_frame_callback(PlatformWindow *window, PlatformFrameCallback cb, void *user_data); -void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count); -int32_t platform_poll_menu_command(PlatformWindow *window); +void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, S32 menu_count); +S32 platform_poll_menu_command(PlatformWindow *window); // Returns accumulated input since last call (keyboard events + polled mouse state), then clears the buffer. PlatformInput platform_get_input(PlatformWindow *window); diff --git a/src/platform/platform_macos.mm b/src/platform/platform_macos.mm index 21eb6c5..823a170 100644 --- a/src/platform/platform_macos.mm +++ b/src/platform/platform_macos.mm @@ -18,7 +18,7 @@ enum { kVK_ANSI_KeypadEnter = 0x4C, }; -static uint8_t macos_keycode_to_pkey(uint16_t keycode) { +static U8 macos_keycode_to_pkey(U16 keycode) { switch (keycode) { case kVK_ANSI_A: return PKEY_A; case kVK_ANSI_C: return PKEY_C; @@ -114,7 +114,7 @@ static PlatformWindow *g_current_window = nullptr; } - (void)keyDown:(NSEvent *)event { - extern void platform_macos_key_down(uint16_t keycode, NSEventModifierFlags mods); + extern void platform_macos_key_down(U16 keycode, NSEventModifierFlags mods); platform_macos_key_down([event keyCode], [event modifierFlags]); // Feed into text input system for character generation @@ -142,8 +142,8 @@ static PlatformWindow *g_current_window = nullptr; - (void)mouseDragged:(NSEvent *)event { (void)event; } - (void)scrollWheel:(NSEvent *)event { - extern void platform_macos_scroll(float dx, float dy); - float dy = (float)[event scrollingDeltaY]; + extern void platform_macos_scroll(F32 dx, F32 dy); + F32 dy = (F32)[event scrollingDeltaY]; if ([event hasPreciseScrollingDeltas]) dy /= 40.0f; // Normalize trackpad deltas to match discrete wheel steps platform_macos_scroll(0, dy); @@ -160,10 +160,10 @@ struct PlatformWindow { NSWindow *ns_window; ASmplView *view; ASmplWindowDelegate *delegate; - bool should_close; - int32_t width; - int32_t height; - int32_t pending_menu_cmd; + B32 should_close; + S32 width; + S32 height; + S32 pending_menu_cmd; PlatformFrameCallback frame_callback; void *frame_callback_user_data; PlatformInput input; @@ -183,8 +183,8 @@ void platform_macos_handle_resize() { if (!g_current_window) return; NSRect frame = [g_current_window->view bounds]; F32 scale = g_current_window->backing_scale; - g_current_window->width = (int32_t)(frame.size.width * scale); - g_current_window->height = (int32_t)(frame.size.height * scale); + g_current_window->width = (S32)(frame.size.width * scale); + g_current_window->height = (S32)(frame.size.height * scale); if (g_current_window->frame_callback) g_current_window->frame_callback(g_current_window->frame_callback_user_data); } @@ -193,11 +193,11 @@ void platform_macos_insert_text(const char *utf8) { if (!g_current_window || !utf8) return; PlatformInput *ev = &g_current_window->input; while (*utf8 && ev->char_count < PLATFORM_MAX_CHARS_PER_FRAME) { - uint8_t c = (uint8_t)*utf8; + U8 c = (U8)*utf8; if (c < 32) { utf8++; continue; } // Handle ASCII printable range (single-byte UTF-8) if (c < 0x80) { - ev->chars[ev->char_count++] = (uint16_t)c; + ev->chars[ev->char_count++] = (U16)c; utf8++; } else { // Skip multi-byte UTF-8 sequences for now (UI only handles ASCII) @@ -208,11 +208,11 @@ void platform_macos_insert_text(const char *utf8) { } } -void platform_macos_key_down(uint16_t keycode, NSEventModifierFlags mods) { +void platform_macos_key_down(U16 keycode, NSEventModifierFlags mods) { if (!g_current_window) return; PlatformInput *ev = &g_current_window->input; - uint8_t pkey = macos_keycode_to_pkey(keycode); + U8 pkey = macos_keycode_to_pkey(keycode); if (pkey && ev->key_count < PLATFORM_MAX_KEYS_PER_FRAME) ev->keys[ev->key_count++] = pkey; @@ -229,7 +229,7 @@ void platform_macos_mouse_up() { if (g_current_window) g_current_window->mouse_down_state = 0; } -void platform_macos_scroll(float dx, float dy) { +void platform_macos_scroll(F32 dx, F32 dy) { (void)dx; if (g_current_window) g_current_window->input.scroll_delta.y += dy; } @@ -245,7 +245,7 @@ void platform_macos_scroll(float dx, float dy) { - (void)menuAction:(id)sender { if (!g_current_window) return; NSMenuItem *item = (NSMenuItem *)sender; - g_current_window->pending_menu_cmd = (int32_t)[item tag]; + g_current_window->pending_menu_cmd = (S32)[item tag]; } @end @@ -288,8 +288,8 @@ PlatformWindow *platform_create_window(PlatformWindowDesc *desc) { window->delegate = delegate; window->should_close = false; window->backing_scale = (F32)[ns_window backingScaleFactor]; - window->width = (int32_t)(desc->width * window->backing_scale); - window->height = (int32_t)(desc->height * window->backing_scale); + window->width = (S32)(desc->width * window->backing_scale); + window->height = (S32)(desc->height * window->backing_scale); g_current_window = window; @@ -308,7 +308,7 @@ void platform_destroy_window(PlatformWindow *window) { delete window; } -bool platform_poll_events(PlatformWindow *window) { +B32 platform_poll_events(PlatformWindow *window) { @autoreleasepool { NSEvent *event; while ((event = [NSApp nextEventMatchingMask:NSEventMaskAny @@ -321,7 +321,7 @@ bool platform_poll_events(PlatformWindow *window) { return !window->should_close; } -void platform_get_size(PlatformWindow *window, int32_t *w, int32_t *h) { +void platform_get_size(PlatformWindow *window, S32 *w, S32 *h) { if (w) *w = window->width; if (h) *h = window->height; } @@ -335,7 +335,7 @@ void platform_set_frame_callback(PlatformWindow *window, PlatformFrameCallback c window->frame_callback_user_data = user_data; } -void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count) { +void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, S32 menu_count) { (void)window; if (!g_menu_target) @@ -352,12 +352,12 @@ void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu [app_menu_item setSubmenu:app_menu]; [menu_bar addItem:app_menu_item]; - for (int32_t i = 0; i < menu_count; i++) { + for (S32 i = 0; i < menu_count; i++) { NSMenuItem *top_item = [[NSMenuItem alloc] init]; NSMenu *submenu = [[NSMenu alloc] initWithTitle: [NSString stringWithUTF8String:menus[i].label]]; - for (int32_t j = 0; j < menus[i].item_count; j++) { + for (S32 j = 0; j < menus[i].item_count; j++) { PlatformMenuItem *item = &menus[i].items[j]; if (!item->label) { [submenu addItem:[NSMenuItem separatorItem]]; @@ -379,8 +379,8 @@ void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu [NSApp setMainMenu:menu_bar]; } -int32_t platform_poll_menu_command(PlatformWindow *window) { - int32_t cmd = window->pending_menu_cmd; +S32 platform_poll_menu_command(PlatformWindow *window) { + S32 cmd = window->pending_menu_cmd; window->pending_menu_cmd = 0; return cmd; } diff --git a/src/platform/platform_win32.cpp b/src/platform/platform_win32.cpp index ed59a1c..c80b86d 100644 --- a/src/platform/platform_win32.cpp +++ b/src/platform/platform_win32.cpp @@ -8,10 +8,10 @@ struct PlatformWindow { HWND hwnd; - bool should_close; - int32_t width; - int32_t height; - int32_t pending_menu_cmd; + B32 should_close; + S32 width; + S32 height; + S32 pending_menu_cmd; PlatformFrameCallback frame_callback; void *frame_callback_user_data; PlatformInput input; @@ -25,8 +25,8 @@ static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM switch (msg) { case WM_SIZE: if (g_current_window && wparam != SIZE_MINIMIZED) { - g_current_window->width = (int32_t)LOWORD(lparam); - g_current_window->height = (int32_t)HIWORD(lparam); + g_current_window->width = (S32)LOWORD(lparam); + g_current_window->height = (S32)HIWORD(lparam); // Render a frame during the modal resize loop so the UI // stays responsive instead of showing a stretched image. if (g_current_window->frame_callback) { @@ -38,7 +38,7 @@ static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM if (g_current_window && wparam >= 32 && wparam < 0xFFFF) { PlatformInput *ev = &g_current_window->input; if (ev->char_count < PLATFORM_MAX_CHARS_PER_FRAME) - ev->chars[ev->char_count++] = (uint16_t)wparam; + ev->chars[ev->char_count++] = (U16)wparam; } return 0; case WM_KEYDOWN: @@ -46,20 +46,20 @@ static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM if (g_current_window) { PlatformInput *ev = &g_current_window->input; if (ev->key_count < PLATFORM_MAX_KEYS_PER_FRAME) - ev->keys[ev->key_count++] = (uint8_t)wparam; + ev->keys[ev->key_count++] = (U8)wparam; ev->ctrl_held = (GetKeyState(VK_CONTROL) & 0x8000) != 0; ev->shift_held = (GetKeyState(VK_SHIFT) & 0x8000) != 0; } break; // fall through to DefWindowProc for system keys case WM_MOUSEWHEEL: if (g_current_window) { - int16_t wheel_delta = (int16_t)HIWORD(wparam); + S16 wheel_delta = (S16)HIWORD(wparam); g_current_window->input.scroll_delta.y += (F32)wheel_delta / (F32)WHEEL_DELTA * 6.0f; } return 0; case WM_COMMAND: if (g_current_window && HIWORD(wparam) == 0) - g_current_window->pending_menu_cmd = (int32_t)LOWORD(wparam); + g_current_window->pending_menu_cmd = (S32)LOWORD(wparam); return 0; case WM_SETCURSOR: // When the cursor is in our client area, use the app-set cursor. @@ -146,7 +146,7 @@ void platform_destroy_window(PlatformWindow *window) { delete window; } -bool platform_poll_events(PlatformWindow *window) { +B32 platform_poll_events(PlatformWindow *window) { MSG msg; while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); @@ -158,7 +158,7 @@ bool platform_poll_events(PlatformWindow *window) { return !window->should_close; } -void platform_get_size(PlatformWindow *window, int32_t *w, int32_t *h) { +void platform_get_size(PlatformWindow *window, S32 *w, S32 *h) { if (w) *w = window->width; if (h) *h = window->height; } @@ -172,13 +172,13 @@ void platform_set_frame_callback(PlatformWindow *window, PlatformFrameCallback c window->frame_callback_user_data = user_data; } -void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count) { +void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, S32 menu_count) { HMENU menu_bar = CreateMenu(); - for (int32_t i = 0; i < menu_count; i++) { + for (S32 i = 0; i < menu_count; i++) { HMENU submenu = CreatePopupMenu(); - for (int32_t j = 0; j < menus[i].item_count; j++) { + for (S32 j = 0; j < menus[i].item_count; j++) { PlatformMenuItem *item = &menus[i].items[j]; if (!item->label) { AppendMenuW(submenu, MF_SEPARATOR, 0, nullptr); @@ -201,8 +201,8 @@ void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu SetMenu(window->hwnd, menu_bar); } -int32_t platform_poll_menu_command(PlatformWindow *window) { - int32_t cmd = window->pending_menu_cmd; +S32 platform_poll_menu_command(PlatformWindow *window) { + S32 cmd = window->pending_menu_cmd; window->pending_menu_cmd = 0; return cmd; } @@ -236,7 +236,7 @@ void platform_set_cursor(PlatformCursor cursor) { void platform_clipboard_set(const char *text) { if (!text) return; - int len = (int)strlen(text); + int len = (S32)strlen(text); if (len == 0) return; // Convert UTF-8 to wide string for Windows clipboard diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index 50bfc52..bb35fcf 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -1,31 +1,30 @@ #pragma once -#include -#include +#include "base/base_core.h" struct Renderer; struct Clay_RenderCommandArray; struct RendererDesc { void *window_handle = nullptr; - int32_t width = 1280; - int32_t height = 720; - int32_t frame_count = 2; + S32 width = 1280; + S32 height = 720; + S32 frame_count = 2; }; Renderer *renderer_create(RendererDesc *desc); void renderer_destroy(Renderer *renderer); -bool renderer_begin_frame(Renderer *renderer); +B32 renderer_begin_frame(Renderer *renderer); void renderer_end_frame(Renderer *renderer, Clay_RenderCommandArray render_commands); -void renderer_resize(Renderer *renderer, int32_t width, int32_t height); -void renderer_set_font_scale(Renderer *renderer, float scale); -void renderer_set_clear_color(Renderer *renderer, float r, float g, float b); +void renderer_resize(Renderer *renderer, S32 width, S32 height); +void renderer_set_font_scale(Renderer *renderer, F32 scale); +void renderer_set_clear_color(Renderer *renderer, F32 r, F32 g, F32 b); // Text measurement callback compatible with UI_MeasureTextFn // Measures text of given length (NOT necessarily null-terminated) at font_size pixels. // user_data should be the Renderer pointer. struct Vec2F32; -Vec2F32 renderer_measure_text(const char *text, int32_t length, float font_size, void *user_data); +Vec2F32 renderer_measure_text(const char *text, S32 length, F32 font_size, void *user_data); // Upload an RGBA8 icon atlas texture for icon rendering (4 bytes per pixel) -void renderer_create_icon_atlas(Renderer *renderer, const uint8_t *data, int32_t w, int32_t h); +void renderer_create_icon_atlas(Renderer *renderer, const U8 *data, S32 w, S32 h); diff --git a/src/renderer/renderer_dx12.cpp b/src/renderer/renderer_dx12.cpp index 9f2086b..b02236d 100644 --- a/src/renderer/renderer_dx12.cpp +++ b/src/renderer/renderer_dx12.cpp @@ -170,17 +170,17 @@ struct FrameContext { struct Renderer { HWND hwnd; - int32_t width; - int32_t height; - int32_t frame_count; + S32 width; + S32 height; + S32 frame_count; UINT frame_index; ID3D12Device *device; ID3D12CommandQueue *command_queue; IDXGISwapChain3 *swap_chain; HANDLE swap_chain_waitable; - bool swap_chain_occluded; - bool tearing_support; + B32 swap_chain_occluded; + B32 tearing_support; ID3D12DescriptorHeap *rtv_heap; ID3D12DescriptorHeap *srv_heap; @@ -198,7 +198,7 @@ struct Renderer { ID3D12RootSignature *root_signature; ID3D12PipelineState *pipeline_state; - // Per-frame vertex/index buffers (double-buffered) + // Per-frame vertex/index buffers (F64-buffered) ID3D12Resource *vertex_buffers[NUM_BACK_BUFFERS]; ID3D12Resource *index_buffers[NUM_BACK_BUFFERS]; void *vb_mapped[NUM_BACK_BUFFERS]; @@ -220,15 +220,15 @@ struct Renderer { F32 measure_font_size; // Clear color - float clear_r = 0.12f; - float clear_g = 0.12f; - float clear_b = 0.13f; + F32 clear_r = 0.12f; + F32 clear_g = 0.12f; + F32 clear_b = 0.13f; }; //////////////////////////////// // DX12 infrastructure -static bool create_device(Renderer *r) { +static B32 create_device(Renderer *r) { #ifdef DX12_ENABLE_DEBUG_LAYER ID3D12Debug *debug = nullptr; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) { @@ -254,7 +254,7 @@ static bool create_device(Renderer *r) { return true; } -static bool create_command_queue(Renderer *r) { +static B32 create_command_queue(Renderer *r) { D3D12_COMMAND_QUEUE_DESC desc = {}; desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; @@ -262,7 +262,7 @@ static bool create_command_queue(Renderer *r) { return r->device->CreateCommandQueue(&desc, IID_PPV_ARGS(&r->command_queue)) == S_OK; } -static bool create_descriptor_heaps(Renderer *r) { +static B32 create_descriptor_heaps(Renderer *r) { // RTV heap { D3D12_DESCRIPTOR_HEAP_DESC desc = {}; @@ -275,7 +275,7 @@ static bool create_descriptor_heaps(Renderer *r) { SIZE_T rtv_size = r->device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); D3D12_CPU_DESCRIPTOR_HANDLE handle = r->rtv_heap->GetCPUDescriptorHandleForHeapStart(); - for (int i = 0; i < NUM_BACK_BUFFERS; i++) { + for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) { r->rtv_descriptors[i] = handle; handle.ptr += rtv_size; } @@ -294,8 +294,8 @@ static bool create_descriptor_heaps(Renderer *r) { return true; } -static bool create_frame_resources(Renderer *r) { - for (int i = 0; i < r->frame_count; i++) { +static B32 create_frame_resources(Renderer *r) { + for (S32 i = 0; i < r->frame_count; i++) { if (r->device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&r->frames[i].command_allocator)) != S_OK) return false; @@ -315,7 +315,7 @@ static bool create_frame_resources(Renderer *r) { return r->fence_event != nullptr; } -static bool create_swap_chain(Renderer *r) { +static B32 create_swap_chain(Renderer *r) { DXGI_SWAP_CHAIN_DESC1 sd = {}; sd.BufferCount = NUM_BACK_BUFFERS; sd.Width = 0; @@ -413,7 +413,7 @@ static void ensure_measure_font(Renderer *r, F32 font_size) { if (r->measure_font) DeleteObject(r->measure_font); r->measure_font = CreateFontW( - -(int)(font_size + 0.5f), 0, 0, 0, + -(S32)(font_size + 0.5f), 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_DONTCARE, @@ -423,18 +423,18 @@ static void ensure_measure_font(Renderer *r, F32 font_size) { SelectObject(r->measure_dc, r->measure_font); } -static bool create_font_atlas(Renderer *r, F32 font_size) { - const int SS = 2; // supersample factor +static B32 create_font_atlas(Renderer *r, F32 font_size) { + const S32 SS = 2; // supersample factor F32 render_size = font_size * SS; - int render_w = FONT_ATLAS_W * SS; - int render_h = FONT_ATLAS_H * SS; + S32 render_w = FONT_ATLAS_W * SS; + S32 render_h = FONT_ATLAS_H * SS; r->font_atlas_size = font_size; // Create a GDI bitmap to render glyphs at supersampled resolution HDC dc = CreateCompatibleDC(nullptr); HFONT font = CreateFontW( - -(int)(render_size + 0.5f), 0, 0, 0, + -(S32)(render_size + 0.5f), 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, @@ -468,16 +468,16 @@ static bool create_font_atlas(Renderer *r, F32 font_size) { SetBkMode(dc, TRANSPARENT); // Render each glyph at supersampled resolution - int pen_x = SS, pen_y = SS; - int row_height = 0; + S32 pen_x = SS, pen_y = SS; + S32 row_height = 0; - for (int i = 0; i < GLYPH_COUNT; i++) { + for (S32 i = 0; i < GLYPH_COUNT; i++) { char ch = (char)(GLYPH_FIRST + i); SIZE ch_size = {}; GetTextExtentPoint32A(dc, &ch, 1, &ch_size); - int gw = ch_size.cx + 2 * SS; // padding scaled by SS - int gh = ch_size.cy + 2 * SS; + S32 gw = ch_size.cx + 2 * SS; // padding scaled by SS + S32 gh = ch_size.cy + 2 * SS; if (pen_x + gw >= render_w) { pen_x = SS; @@ -507,16 +507,16 @@ static bool create_font_atlas(Renderer *r, F32 font_size) { // Box-filter downsample from supersampled resolution to atlas resolution U8 *atlas_data = (U8 *)malloc(FONT_ATLAS_W * FONT_ATLAS_H); U8 *src = (U8 *)dib_bits; - for (int y = 0; y < FONT_ATLAS_H; y++) { - for (int x = 0; x < FONT_ATLAS_W; x++) { - int sum = 0; - for (int sy = 0; sy < SS; sy++) { - for (int sx = 0; sx < SS; sx++) { - int src_idx = ((y * SS + sy) * render_w + (x * SS + sx)) * 4; + for (S32 y = 0; y < FONT_ATLAS_H; y++) { + for (S32 x = 0; x < FONT_ATLAS_W; x++) { + S32 sum = 0; + for (S32 sy = 0; sy < SS; sy++) { + for (S32 sx = 0; sx < SS; sx++) { + S32 src_idx = ((y * SS + sy) * render_w + (x * SS + sx)) * 4; sum += src[src_idx + 2]; // R channel from BGRA } } - float a = (float)sum / (float)(SS * SS * 255); + F32 a = (F32)sum / (F32)(SS * SS * 255); a = powf(a, 0.55f); atlas_data[y * FONT_ATLAS_W + x] = (U8)(a * 255.0f + 0.5f); } @@ -573,7 +573,7 @@ static bool create_font_atlas(Renderer *r, F32 font_size) { D3D12_RANGE read_range = {0, 0}; upload_buf->Map(0, &read_range, &mapped); U8 *dst = (U8 *)mapped; - for (int y = 0; y < FONT_ATLAS_H; y++) { + for (S32 y = 0; y < FONT_ATLAS_H; y++) { memcpy(dst + y * footprint.Footprint.RowPitch, atlas_data + y * FONT_ATLAS_W, FONT_ATLAS_W); @@ -631,7 +631,7 @@ static bool create_font_atlas(Renderer *r, F32 font_size) { //////////////////////////////// // UI rendering pipeline setup -static bool create_ui_pipeline(Renderer *r) { +static B32 create_ui_pipeline(Renderer *r) { ID3DBlob *vs_blob = nullptr; ID3DBlob *ps_blob = nullptr; ID3DBlob *error_blob = nullptr; @@ -769,11 +769,11 @@ static bool create_ui_pipeline(Renderer *r) { return SUCCEEDED(hr); } -static bool create_ui_buffers(Renderer *r) { +static B32 create_ui_buffers(Renderer *r) { D3D12_HEAP_PROPERTIES heap_props = {}; heap_props.Type = D3D12_HEAP_TYPE_UPLOAD; - for (int i = 0; i < NUM_BACK_BUFFERS; i++) { + for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) { D3D12_RESOURCE_DESC buf_desc = {}; buf_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; buf_desc.Width = MAX_VERTICES * sizeof(UIVertex); @@ -792,7 +792,7 @@ static bool create_ui_buffers(Renderer *r) { r->vertex_buffers[i]->Map(0, &read_range, &r->vb_mapped[i]); } - for (int i = 0; i < NUM_BACK_BUFFERS; i++) { + for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) { D3D12_RESOURCE_DESC buf_desc = {}; buf_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; buf_desc.Width = MAX_INDICES * sizeof(U32); @@ -817,7 +817,7 @@ static bool create_ui_buffers(Renderer *r) { //////////////////////////////// // Text measurement callback for UI system -Vec2F32 renderer_measure_text(const char *text, int32_t length, float font_size, void *user_data) { +Vec2F32 renderer_measure_text(const char *text, S32 length, F32 font_size, void *user_data) { Renderer *r = (Renderer *)user_data; if (!r || length == 0) return v2f32(0, font_size); @@ -839,12 +839,12 @@ struct DrawBatch { }; static void emit_quad(DrawBatch *batch, - float x0, float y0, float x1, float y1, - float u0, float v0, float u1, float v1, - float cr, float cg, float cb, float ca, - float rmin_x, float rmin_y, float rmax_x, float rmax_y, - float cr_tl, float cr_tr, float cr_br, float cr_bl, - float border_thickness, float softness, float mode) + F32 x0, F32 y0, F32 x1, F32 y1, + F32 u0, F32 v0, F32 u1, F32 v1, + F32 cr, F32 cg, F32 cb, F32 ca, + F32 rmin_x, F32 rmin_y, F32 rmax_x, F32 rmax_y, + F32 cr_tl, F32 cr_tr, F32 cr_br, F32 cr_bl, + F32 border_thickness, F32 softness, F32 mode) { if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES) return; @@ -853,9 +853,9 @@ static void emit_quad(DrawBatch *batch, UIVertex *v = &batch->vertices[base]; // For SDF mode, expand quad slightly for anti-aliasing - float px0 = x0, py0 = y0, px1 = x1, py1 = y1; + F32 px0 = x0, py0 = y0, px1 = x1, py1 = y1; if (mode < 0.5f) { - float pad = softness + 1.0f; + F32 pad = softness + 1.0f; px0 -= pad; py0 -= pad; px1 += pad; py1 += pad; } @@ -864,7 +864,7 @@ static void emit_quad(DrawBatch *batch, v[2].pos[0] = px1; v[2].pos[1] = py1; v[2].uv[0] = u1; v[2].uv[1] = v1; v[3].pos[0] = px0; v[3].pos[1] = py1; v[3].uv[0] = u0; v[3].uv[1] = v1; - for (int i = 0; i < 4; i++) { + for (S32 i = 0; i < 4; i++) { v[i].col[0] = cr; v[i].col[1] = cg; v[i].col[2] = cb; v[i].col[3] = ca; v[i].rect_min[0] = rmin_x; v[i].rect_min[1] = rmin_y; v[i].rect_max[0] = rmax_x; v[i].rect_max[1] = rmax_y; @@ -884,10 +884,10 @@ static void emit_quad(DrawBatch *batch, } static void emit_quad_rotated(DrawBatch *batch, - float x0, float y0, float x1, float y1, - float u0, float v0, float u1, float v1, - float cr, float cg, float cb, float ca, - float angle_rad) + F32 x0, F32 y0, F32 x1, F32 y1, + F32 u0, F32 v0, F32 u1, F32 v1, + F32 cr, F32 cg, F32 cb, F32 ca, + F32 angle_rad) { if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES) return; @@ -895,13 +895,13 @@ static void emit_quad_rotated(DrawBatch *batch, U32 base = batch->vertex_count; UIVertex *v = &batch->vertices[base]; - float cx = (x0 + x1) * 0.5f; - float cy = (y0 + y1) * 0.5f; - float cosA = cosf(angle_rad); - float sinA = sinf(angle_rad); + F32 cx = (x0 + x1) * 0.5f; + F32 cy = (y0 + y1) * 0.5f; + F32 cosA = cosf(angle_rad); + F32 sinA = sinf(angle_rad); - float dx0 = x0 - cx, dy0 = y0 - cy; - float dx1 = x1 - cx, dy1 = y1 - cy; + F32 dx0 = x0 - cx, dy0 = y0 - cy; + F32 dx1 = x1 - cx, dy1 = y1 - cy; v[0].pos[0] = cx + dx0 * cosA - dy0 * sinA; v[0].pos[1] = cy + dx0 * sinA + dy0 * cosA; @@ -919,7 +919,7 @@ static void emit_quad_rotated(DrawBatch *batch, v[3].pos[1] = cy + dx0 * sinA + dy1 * cosA; v[3].uv[0] = u0; v[3].uv[1] = v1; - for (int i = 0; i < 4; i++) { + for (S32 i = 0; i < 4; i++) { v[i].col[0] = cr; v[i].col[1] = cg; v[i].col[2] = cb; v[i].col[3] = ca; v[i].rect_min[0] = 0; v[i].rect_min[1] = 0; v[i].rect_max[0] = 0; v[i].rect_max[1] = 0; @@ -939,10 +939,10 @@ static void emit_quad_rotated(DrawBatch *batch, } static void emit_rect(DrawBatch *batch, - float x0, float y0, float x1, float y1, - float cr, float cg, float cb, float ca, - float cr_tl, float cr_tr, float cr_br, float cr_bl, - float border_thickness, float softness) + F32 x0, F32 y0, F32 x1, F32 y1, + F32 cr, F32 cg, F32 cb, F32 ca, + F32 cr_tl, F32 cr_tr, F32 cr_br, F32 cr_bl, + F32 border_thickness, F32 softness) { emit_quad(batch, x0, y0, x1, y1, 0, 0, 0, 0, @@ -953,11 +953,11 @@ static void emit_rect(DrawBatch *batch, } static void emit_rect_vgradient(DrawBatch *batch, - float x0, float y0, float x1, float y1, - float tr, float tg, float tb, float ta, - float br, float bg, float bb_, float ba, - float cr_tl, float cr_tr, float cr_br, float cr_bl, - float softness) + F32 x0, F32 y0, F32 x1, F32 y1, + F32 tr, F32 tg, F32 tb, F32 ta, + F32 br, F32 bg, F32 bb_, F32 ba, + F32 cr_tl, F32 cr_tr, F32 cr_br, F32 cr_bl, + F32 softness) { if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES) return; @@ -965,8 +965,8 @@ static void emit_rect_vgradient(DrawBatch *batch, U32 base = batch->vertex_count; UIVertex *v = &batch->vertices[base]; - float pad = softness + 1.0f; - float px0 = x0 - pad, py0 = y0 - pad, px1 = x1 + pad, py1 = y1 + pad; + F32 pad = softness + 1.0f; + F32 px0 = x0 - pad, py0 = y0 - pad, px1 = x1 + pad, py1 = y1 + pad; v[0].pos[0] = px0; v[0].pos[1] = py0; v[0].uv[0] = 0; v[0].uv[1] = 0; v[1].pos[0] = px1; v[1].pos[1] = py0; v[1].uv[0] = 0; v[1].uv[1] = 0; @@ -979,7 +979,7 @@ static void emit_rect_vgradient(DrawBatch *batch, v[2].col[0] = br; v[2].col[1] = bg; v[2].col[2] = bb_; v[2].col[3] = ba; v[3].col[0] = br; v[3].col[1] = bg; v[3].col[2] = bb_; v[3].col[3] = ba; - for (int i = 0; i < 4; i++) { + for (S32 i = 0; i < 4; i++) { v[i].rect_min[0] = x0; v[i].rect_min[1] = y0; v[i].rect_max[0] = x1; v[i].rect_max[1] = y1; v[i].corner_radii[0] = cr_tl; v[i].corner_radii[1] = cr_tr; @@ -998,16 +998,16 @@ static void emit_rect_vgradient(DrawBatch *batch, } static void emit_text_glyphs(DrawBatch *batch, Renderer *r, - Clay_BoundingBox bbox, Clay_Color color, const char *text, int32_t text_len, - uint16_t font_size) + Clay_BoundingBox bbox, Clay_Color color, const char *text, S32 text_len, + U16 font_size) { if (text_len == 0 || color.a < 0.1f) return; // Color is 0-255 in Clay convention, normalize to 0-1 - float cr = color.r / 255.f; - float cg = color.g / 255.f; - float cb = color.b / 255.f; - float ca = color.a / 255.f; + F32 cr = color.r / 255.f; + F32 cg = color.g / 255.f; + F32 cb = color.b / 255.f; + F32 ca = color.a / 255.f; F32 scale = (F32)font_size / r->font_atlas_size; F32 text_h = r->font_line_height * scale; @@ -1016,18 +1016,18 @@ static void emit_text_glyphs(DrawBatch *batch, Renderer *r, F32 x = floorf(bbox.x + 0.5f); F32 y = floorf(bbox.y + (bbox.height - text_h) * 0.5f + 0.5f); - for (int32_t i = 0; i < text_len; i++) { + for (S32 i = 0; i < text_len; i++) { char ch = text[i]; if (ch < GLYPH_FIRST || ch > GLYPH_LAST) { if (ch == ' ') { - int gi = ' ' - GLYPH_FIRST; + S32 gi = ' ' - GLYPH_FIRST; if (gi >= 0 && gi < GLYPH_COUNT) x += r->glyphs[gi].x_advance * scale; continue; } ch = '?'; } - int gi = ch - GLYPH_FIRST; + S32 gi = ch - GLYPH_FIRST; if (gi < 0 || gi >= GLYPH_COUNT) continue; GlyphInfo *g = &r->glyphs[gi]; @@ -1056,7 +1056,7 @@ static void flush_batch(Renderer *r, DrawBatch *batch, UINT buf_idx, U32 *flush_ r->command_list->SetPipelineState(r->pipeline_state); r->command_list->SetGraphicsRootSignature(r->root_signature); - float constants[4] = { (float)r->width, (float)r->height, 0, 0 }; + F32 constants[4] = { (F32)r->width, (F32)r->height, 0, 0 }; r->command_list->SetGraphicsRoot32BitConstants(0, 4, constants, 0); // Bind texture (font or icon) @@ -1122,7 +1122,7 @@ void renderer_destroy(Renderer *r) { wait_for_pending(r); - for (int i = 0; i < NUM_BACK_BUFFERS; i++) { + for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) { if (r->vertex_buffers[i]) r->vertex_buffers[i]->Release(); if (r->index_buffers[i]) r->index_buffers[i]->Release(); } @@ -1139,7 +1139,7 @@ void renderer_destroy(Renderer *r) { if (r->swap_chain) { r->swap_chain->SetFullscreenState(false, nullptr); r->swap_chain->Release(); } if (r->swap_chain_waitable) CloseHandle(r->swap_chain_waitable); - for (int i = 0; i < r->frame_count; i++) + for (S32 i = 0; i < r->frame_count; i++) if (r->frames[i].command_allocator) r->frames[i].command_allocator->Release(); if (r->command_queue) r->command_queue->Release(); if (r->command_list) r->command_list->Release(); @@ -1160,7 +1160,7 @@ void renderer_destroy(Renderer *r) { delete r; } -bool renderer_begin_frame(Renderer *r) { +B32 renderer_begin_frame(Renderer *r) { if ((r->swap_chain_occluded && r->swap_chain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED) || IsIconic(r->hwnd)) { @@ -1188,7 +1188,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; r->command_list->ResourceBarrier(1, &barrier); - const float clear_color[4] = { r->clear_r, r->clear_g, r->clear_b, 1.0f }; + const F32 clear_color[4] = { r->clear_r, r->clear_g, r->clear_b, 1.0f }; r->command_list->ClearRenderTargetView(r->rtv_descriptors[back_buffer_idx], clear_color, 0, nullptr); r->command_list->OMSetRenderTargets(1, &r->rtv_descriptors[back_buffer_idx], FALSE, nullptr); @@ -1210,7 +1210,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { batch.index_count = 0; // Track which texture is currently bound (0 = font, 1 = icon) - int bound_texture = 0; + S32 bound_texture = 0; U32 flush_index_start = 0; auto bind_font = [&]() { @@ -1228,7 +1228,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { } }; - for (int32_t i = 0; i < render_commands.length; i++) { + for (S32 i = 0; i < render_commands.length; i++) { Clay_RenderCommand *cmd = Clay_RenderCommandArray_Get(&render_commands, i); Clay_BoundingBox bb = cmd->boundingBox; @@ -1247,15 +1247,15 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { case CLAY_RENDER_COMMAND_TYPE_BORDER: { Clay_BorderRenderData *border = &cmd->renderData.border; Clay_Color c = border->color; - float cr_norm = c.r / 255.f; - float cg_norm = c.g / 255.f; - float cb_norm = c.b / 255.f; - float ca_norm = c.a / 255.f; + F32 cr_norm = c.r / 255.f; + F32 cg_norm = c.g / 255.f; + F32 cb_norm = c.b / 255.f; + F32 ca_norm = c.a / 255.f; // Use SDF rounded border when corner radius is present and widths are uniform Clay_CornerRadius cr = border->cornerRadius; - bool has_radius = cr.topLeft > 0 || cr.topRight > 0 || cr.bottomLeft > 0 || cr.bottomRight > 0; - bool uniform = border->width.top == border->width.bottom && + B32 has_radius = cr.topLeft > 0 || cr.topRight > 0 || cr.bottomLeft > 0 || cr.bottomRight > 0; + B32 uniform = border->width.top == border->width.bottom && border->width.top == border->width.left && border->width.top == border->width.right && border->width.top > 0; @@ -1265,7 +1265,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { bb.x, bb.y, bb.x + bb.width, bb.y + bb.height, cr_norm, cg_norm, cb_norm, ca_norm, cr.topLeft, cr.topRight, cr.bottomRight, cr.bottomLeft, - (float)border->width.top, 1.0f); + (F32)border->width.top, 1.0f); } else { if (border->width.top > 0) { emit_rect(&batch, bb.x, bb.y, bb.x + bb.width, bb.y + border->width.top, @@ -1335,8 +1335,8 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { bind_icon(); CustomIconData *icon = (CustomIconData *)custom->customData; Clay_Color c = icon->color; - float cr = c.r / 255.f, cg = c.g / 255.f; - float cb = c.b / 255.f, ca = c.a / 255.f; + F32 cr = c.r / 255.f, cg = c.g / 255.f; + F32 cb = c.b / 255.f, ca = c.a / 255.f; UI_IconInfo *info = &g_icons[icon->icon_id]; emit_quad(&batch, bb.x, bb.y, bb.x + bb.width, bb.y + bb.height, @@ -1349,8 +1349,8 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { bind_icon(); CustomRotatedIconData *ri = (CustomRotatedIconData *)custom->customData; Clay_Color c = ri->color; - float cr = c.r / 255.f, cg = c.g / 255.f; - float cb = c.b / 255.f, ca = c.a / 255.f; + F32 cr = c.r / 255.f, cg = c.g / 255.f; + F32 cb = c.b / 255.f, ca = c.a / 255.f; UI_IconInfo *info = &g_icons[ri->icon_id]; emit_quad_rotated(&batch, bb.x, bb.y, bb.x + bb.width, bb.y + bb.height, @@ -1386,7 +1386,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { r->frame_index++; } -void renderer_create_icon_atlas(Renderer *r, const uint8_t *data, int32_t w, int32_t h) { +void renderer_create_icon_atlas(Renderer *r, const U8 *data, S32 w, S32 h) { // Create texture resource D3D12_HEAP_PROPERTIES heap_props = {}; heap_props.Type = D3D12_HEAP_TYPE_DEFAULT; @@ -1431,7 +1431,7 @@ void renderer_create_icon_atlas(Renderer *r, const uint8_t *data, int32_t w, int D3D12_RANGE read_range = {0, 0}; upload_buf->Map(0, &read_range, &mapped); U8 *dst = (U8 *)mapped; - for (int y = 0; y < h; y++) { + for (S32 y = 0; y < h; y++) { memcpy(dst + y * footprint.Footprint.RowPitch, data + y * w * 4, w * 4); } upload_buf->Unmap(0, nullptr); @@ -1481,7 +1481,7 @@ void renderer_create_icon_atlas(Renderer *r, const uint8_t *data, int32_t w, int &srv_view, r->icon_srv_heap->GetCPUDescriptorHandleForHeapStart()); } -void renderer_resize(Renderer *r, int32_t width, int32_t height) { +void renderer_resize(Renderer *r, S32 width, S32 height) { if (width <= 0 || height <= 0) return; wait_for_pending(r); @@ -1497,14 +1497,14 @@ void renderer_resize(Renderer *r, int32_t width, int32_t height) { r->height = height; } -void renderer_set_clear_color(Renderer *r, float cr, float cg, float cb) { +void renderer_set_clear_color(Renderer *r, F32 cr, F32 cg, F32 cb) { r->clear_r = cr; r->clear_g = cg; r->clear_b = cb; } -void renderer_set_font_scale(Renderer *r, float scale) { - float target_size = 15.0f * scale; +void renderer_set_font_scale(Renderer *r, F32 scale) { + F32 target_size = 15.0f * scale; if (fabsf(target_size - r->font_atlas_size) < 0.1f) return; wait_for_pending(r); if (r->font_texture) { r->font_texture->Release(); r->font_texture = nullptr; } diff --git a/src/renderer/renderer_metal.mm b/src/renderer/renderer_metal.mm index 3b79efc..ac9e198 100644 --- a/src/renderer/renderer_metal.mm +++ b/src/renderer/renderer_metal.mm @@ -146,10 +146,10 @@ fragment float4 fragment_main(Fragment in [[stage_in]], // Renderer struct struct Renderer { - int32_t width; - int32_t height; - int32_t frame_count; - uint32_t frame_index; + S32 width; + S32 height; + S32 frame_count; + U32 frame_index; F32 backing_scale; id device; @@ -187,11 +187,11 @@ struct Renderer { //////////////////////////////// // Font atlas (Core Text + CoreGraphics) -static bool create_font_atlas(Renderer *r, F32 font_size) { - const int SS = 2; +static B32 create_font_atlas(Renderer *r, F32 font_size) { + const S32 SS = 2; F32 render_size = font_size * SS; - int render_w = FONT_ATLAS_W * SS; - int render_h = FONT_ATLAS_H * SS; + S32 render_w = FONT_ATLAS_W * SS; + S32 render_h = FONT_ATLAS_H * SS; r->font_atlas_size = font_size; @@ -228,23 +228,23 @@ static bool create_font_atlas(Renderer *r, F32 font_size) { CGContextSetTextMatrix(ctx, CGAffineTransformMake(1, 0, 0, -1, 0, 0)); // Render each glyph - int pen_x = SS, pen_y = SS; - int row_height = 0; + S32 pen_x = SS, pen_y = SS; + S32 row_height = 0; NSDictionary *attrs = @{ (id)kCTFontAttributeName: (__bridge id)font, (id)kCTForegroundColorFromContextAttributeName: @YES }; - for (int i = 0; i < GLYPH_COUNT; i++) { + for (S32 i = 0; i < GLYPH_COUNT; i++) { char ch = (char)(GLYPH_FIRST + i); NSString *str = [[NSString alloc] initWithBytes:&ch length:1 encoding:NSASCIIStringEncoding]; NSAttributedString *astr = [[NSAttributedString alloc] initWithString:str attributes:attrs]; CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)astr); CGRect bounds = CTLineGetBoundsWithOptions(line, 0); - int gw = (int)ceilf((float)bounds.size.width) + 2 * SS; - int gh = (int)ceilf((float)(ascent + descent)) + 2 * SS; + S32 gw = (S32)ceilf((F32)bounds.size.width) + 2 * SS; + S32 gh = (S32)ceilf((F32)(ascent + descent)) + 2 * SS; if (pen_x + gw >= render_w) { pen_x = SS; @@ -252,7 +252,7 @@ static bool create_font_atlas(Renderer *r, F32 font_size) { row_height = 0; } - if (pen_y + gh >= render_h) { CFRelease(line); break; } + if (pen_y + gh >= render_h) { CFRelease(line); [astr release]; [str release]; break; } // Context is flipped to top-left origin. Position baseline: // pen_y + SS is the top of the glyph cell, baseline is ascent below that. @@ -275,24 +275,26 @@ static bool create_font_atlas(Renderer *r, F32 font_size) { pen_x += gw + SS; CFRelease(line); + [astr release]; + [str release]; } // Box-filter downsample (context is flipped, so bitmap is already top-down) - uint8_t *src = (uint8_t *)CGBitmapContextGetData(ctx); - uint8_t *atlas_data = (uint8_t *)malloc(FONT_ATLAS_W * FONT_ATLAS_H); + U8 *src = (U8 *)CGBitmapContextGetData(ctx); + U8 *atlas_data = (U8 *)malloc(FONT_ATLAS_W * FONT_ATLAS_H); - for (int y = 0; y < FONT_ATLAS_H; y++) { - for (int x = 0; x < FONT_ATLAS_W; x++) { - int sum = 0; - for (int sy = 0; sy < SS; sy++) { - for (int sx = 0; sx < SS; sx++) { - int src_idx = (y * SS + sy) * render_w + (x * SS + sx); + for (S32 y = 0; y < FONT_ATLAS_H; y++) { + for (S32 x = 0; x < FONT_ATLAS_W; x++) { + S32 sum = 0; + for (S32 sy = 0; sy < SS; sy++) { + for (S32 sx = 0; sx < SS; sx++) { + S32 src_idx = (y * SS + sy) * render_w + (x * SS + sx); sum += src[src_idx]; } } - float a = (float)sum / (float)(SS * SS * 255); + F32 a = (F32)sum / (F32)(SS * SS * 255); a = powf(a, 0.55f); - atlas_data[y * FONT_ATLAS_W + x] = (uint8_t)(a * 255.0f + 0.5f); + atlas_data[y * FONT_ATLAS_W + x] = (U8)(a * 255.0f + 0.5f); } } @@ -335,23 +337,29 @@ static void ensure_measure_font(Renderer *r, F32 font_size) { r->measure_font_size = font_size; } -Vec2F32 renderer_measure_text(const char *text, int32_t length, float font_size, void *user_data) { +Vec2F32 renderer_measure_text(const char *text, S32 length, F32 font_size, void *user_data) { Renderer *r = (Renderer *)user_data; if (!r || length == 0) return v2f32(0, font_size); ensure_measure_font(r, font_size); - NSString *str = [[NSString alloc] initWithBytes:text length:length encoding:NSUTF8StringEncoding]; - if (!str) return v2f32(0, font_size); + Vec2F32 result = v2f32(0, font_size); + @autoreleasepool { + NSString *str = [[NSString alloc] initWithBytes:text length:length encoding:NSUTF8StringEncoding]; + if (!str) return result; - NSDictionary *attrs = @{ (id)kCTFontAttributeName: (__bridge id)r->measure_font }; - NSAttributedString *astr = [[NSAttributedString alloc] initWithString:str attributes:attrs]; - CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)astr); + NSDictionary *attrs = @{ (id)kCTFontAttributeName: (__bridge id)r->measure_font }; + NSAttributedString *astr = [[NSAttributedString alloc] initWithString:str attributes:attrs]; + CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)astr); - CGRect bounds = CTLineGetBoundsWithOptions(line, 0); - CFRelease(line); + CGRect bounds = CTLineGetBoundsWithOptions(line, 0); + CFRelease(line); + [astr release]; + [str release]; - return v2f32((F32)bounds.size.width, (F32)bounds.size.height); + result = v2f32((F32)bounds.size.width, (F32)bounds.size.height); + } + return result; } //////////////////////////////// @@ -365,12 +373,12 @@ struct DrawBatch { }; static void emit_quad(DrawBatch *batch, - float x0, float y0, float x1, float y1, - float u0, float v0, float u1, float v1, - float cr, float cg, float cb, float ca, - float rmin_x, float rmin_y, float rmax_x, float rmax_y, - float cr_tl, float cr_tr, float cr_br, float cr_bl, - float border_thickness, float softness, float mode) + F32 x0, F32 y0, F32 x1, F32 y1, + F32 u0, F32 v0, F32 u1, F32 v1, + F32 cr, F32 cg, F32 cb, F32 ca, + F32 rmin_x, F32 rmin_y, F32 rmax_x, F32 rmax_y, + F32 cr_tl, F32 cr_tr, F32 cr_br, F32 cr_bl, + F32 border_thickness, F32 softness, F32 mode) { if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES) return; @@ -378,9 +386,9 @@ static void emit_quad(DrawBatch *batch, U32 base = batch->vertex_count; UIVertex *v = &batch->vertices[base]; - float px0 = x0, py0 = y0, px1 = x1, py1 = y1; + F32 px0 = x0, py0 = y0, px1 = x1, py1 = y1; if (mode < 0.5f) { - float pad = softness + 1.0f; + F32 pad = softness + 1.0f; px0 -= pad; py0 -= pad; px1 += pad; py1 += pad; } @@ -389,7 +397,7 @@ static void emit_quad(DrawBatch *batch, v[2].pos[0] = px1; v[2].pos[1] = py1; v[2].uv[0] = u1; v[2].uv[1] = v1; v[3].pos[0] = px0; v[3].pos[1] = py1; v[3].uv[0] = u0; v[3].uv[1] = v1; - for (int i = 0; i < 4; i++) { + for (S32 i = 0; i < 4; i++) { v[i].col[0] = cr; v[i].col[1] = cg; v[i].col[2] = cb; v[i].col[3] = ca; v[i].rect_min[0] = rmin_x; v[i].rect_min[1] = rmin_y; v[i].rect_max[0] = rmax_x; v[i].rect_max[1] = rmax_y; @@ -409,10 +417,10 @@ static void emit_quad(DrawBatch *batch, } static void emit_quad_rotated(DrawBatch *batch, - float x0, float y0, float x1, float y1, - float u0, float v0, float u1, float v1, - float cr, float cg, float cb, float ca, - float angle_rad) + F32 x0, F32 y0, F32 x1, F32 y1, + F32 u0, F32 v0, F32 u1, F32 v1, + F32 cr, F32 cg, F32 cb, F32 ca, + F32 angle_rad) { if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES) return; @@ -420,14 +428,14 @@ static void emit_quad_rotated(DrawBatch *batch, U32 base = batch->vertex_count; UIVertex *v = &batch->vertices[base]; - float cx = (x0 + x1) * 0.5f; - float cy = (y0 + y1) * 0.5f; - float cosA = cosf(angle_rad); - float sinA = sinf(angle_rad); + F32 cx = (x0 + x1) * 0.5f; + F32 cy = (y0 + y1) * 0.5f; + F32 cosA = cosf(angle_rad); + F32 sinA = sinf(angle_rad); // Corner offsets from center - float dx0 = x0 - cx, dy0 = y0 - cy; - float dx1 = x1 - cx, dy1 = y1 - cy; + F32 dx0 = x0 - cx, dy0 = y0 - cy; + F32 dx1 = x1 - cx, dy1 = y1 - cy; // Rotate each corner around center v[0].pos[0] = cx + dx0 * cosA - dy0 * sinA; @@ -446,7 +454,7 @@ static void emit_quad_rotated(DrawBatch *batch, v[3].pos[1] = cy + dx0 * sinA + dy1 * cosA; v[3].uv[0] = u0; v[3].uv[1] = v1; - for (int i = 0; i < 4; i++) { + for (S32 i = 0; i < 4; i++) { v[i].col[0] = cr; v[i].col[1] = cg; v[i].col[2] = cb; v[i].col[3] = ca; v[i].rect_min[0] = 0; v[i].rect_min[1] = 0; v[i].rect_max[0] = 0; v[i].rect_max[1] = 0; @@ -466,10 +474,10 @@ static void emit_quad_rotated(DrawBatch *batch, } static void emit_rect(DrawBatch *batch, - float x0, float y0, float x1, float y1, - float cr, float cg, float cb, float ca, - float cr_tl, float cr_tr, float cr_br, float cr_bl, - float border_thickness, float softness) + F32 x0, F32 y0, F32 x1, F32 y1, + F32 cr, F32 cg, F32 cb, F32 ca, + F32 cr_tl, F32 cr_tr, F32 cr_br, F32 cr_bl, + F32 border_thickness, F32 softness) { emit_quad(batch, x0, y0, x1, y1, 0, 0, 0, 0, @@ -480,11 +488,11 @@ static void emit_rect(DrawBatch *batch, } static void emit_rect_vgradient(DrawBatch *batch, - float x0, float y0, float x1, float y1, - float tr, float tg, float tb, float ta, - float br, float bg, float bb_, float ba, - float cr_tl, float cr_tr, float cr_br, float cr_bl, - float softness) + F32 x0, F32 y0, F32 x1, F32 y1, + F32 tr, F32 tg, F32 tb, F32 ta, + F32 br, F32 bg, F32 bb_, F32 ba, + F32 cr_tl, F32 cr_tr, F32 cr_br, F32 cr_bl, + F32 softness) { if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES) return; @@ -492,8 +500,8 @@ static void emit_rect_vgradient(DrawBatch *batch, U32 base = batch->vertex_count; UIVertex *v = &batch->vertices[base]; - float pad = softness + 1.0f; - float px0 = x0 - pad, py0 = y0 - pad, px1 = x1 + pad, py1 = y1 + pad; + F32 pad = softness + 1.0f; + F32 px0 = x0 - pad, py0 = y0 - pad, px1 = x1 + pad, py1 = y1 + pad; v[0].pos[0] = px0; v[0].pos[1] = py0; v[0].uv[0] = 0; v[0].uv[1] = 0; v[1].pos[0] = px1; v[1].pos[1] = py0; v[1].uv[0] = 0; v[1].uv[1] = 0; @@ -505,7 +513,7 @@ static void emit_rect_vgradient(DrawBatch *batch, v[2].col[0] = br; v[2].col[1] = bg; v[2].col[2] = bb_; v[2].col[3] = ba; v[3].col[0] = br; v[3].col[1] = bg; v[3].col[2] = bb_; v[3].col[3] = ba; - for (int i = 0; i < 4; i++) { + for (S32 i = 0; i < 4; i++) { v[i].rect_min[0] = x0; v[i].rect_min[1] = y0; v[i].rect_max[0] = x1; v[i].rect_max[1] = y1; v[i].corner_radii[0] = cr_tl; v[i].corner_radii[1] = cr_tr; @@ -524,15 +532,15 @@ static void emit_rect_vgradient(DrawBatch *batch, } static void emit_text_glyphs(DrawBatch *batch, Renderer *r, - Clay_BoundingBox bbox, Clay_Color color, const char *text, int32_t text_len, - uint16_t font_size) + Clay_BoundingBox bbox, Clay_Color color, const char *text, S32 text_len, + U16 font_size) { if (text_len == 0 || color.a < 0.1f) return; - float cr = color.r / 255.f; - float cg = color.g / 255.f; - float cb = color.b / 255.f; - float ca = color.a / 255.f; + F32 cr = color.r / 255.f; + F32 cg = color.g / 255.f; + F32 cb = color.b / 255.f; + F32 ca = color.a / 255.f; F32 scale = (F32)font_size / r->font_atlas_size; F32 text_h = r->font_line_height * scale; @@ -540,18 +548,18 @@ static void emit_text_glyphs(DrawBatch *batch, Renderer *r, F32 x = floorf(bbox.x + 0.5f); F32 y = floorf(bbox.y + (bbox.height - text_h) * 0.5f + 0.5f); - for (int32_t i = 0; i < text_len; i++) { + for (S32 i = 0; i < text_len; i++) { char ch = text[i]; if (ch < GLYPH_FIRST || ch > GLYPH_LAST) { if (ch == ' ') { - int gi = ' ' - GLYPH_FIRST; + S32 gi = ' ' - GLYPH_FIRST; if (gi >= 0 && gi < GLYPH_COUNT) x += r->glyphs[gi].x_advance * scale; continue; } ch = '?'; } - int gi = ch - GLYPH_FIRST; + S32 gi = ch - GLYPH_FIRST; if (gi < 0 || gi >= GLYPH_COUNT) continue; GlyphInfo *g = &r->glyphs[gi]; @@ -595,6 +603,7 @@ Renderer *renderer_create(RendererDesc *desc) { layer.device = r->device; layer.pixelFormat = MTLPixelFormatBGRA8Unorm; layer.framebufferOnly = YES; + layer.maximumDrawableCount = NUM_BACK_BUFFERS; NSWindow *window = [view window]; r->backing_scale = (F32)[window backingScaleFactor]; @@ -672,8 +681,8 @@ Renderer *renderer_create(RendererDesc *desc) { return nullptr; } - // Create double-buffered vertex/index buffers - for (int i = 0; i < NUM_BACK_BUFFERS; i++) { + // Create F64-buffered vertex/index buffers + for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) { r->vertex_buffers[i] = [r->device newBufferWithLength:MAX_VERTICES * sizeof(UIVertex) options:MTLResourceStorageModeShared]; r->index_buffers[i] = [r->device newBufferWithLength:MAX_INDICES * sizeof(U32) @@ -704,14 +713,16 @@ void renderer_destroy(Renderer *r) { delete r; } -bool renderer_begin_frame(Renderer *r) { +B32 renderer_begin_frame(Renderer *r) { if (r->width <= 0 || r->height <= 0) return false; // Wait for an in-flight frame to finish, then acquire a drawable. // Doing this BEFORE input sampling ensures the freshest mouse position // is used for rendering, reducing perceived drag latency. dispatch_semaphore_wait(r->frame_semaphore, DISPATCH_TIME_FOREVER); - r->current_drawable = [r->metal_layer nextDrawable]; + @autoreleasepool { + r->current_drawable = [[r->metal_layer nextDrawable] retain]; + } if (!r->current_drawable) { dispatch_semaphore_signal(r->frame_semaphore); return false; @@ -724,7 +735,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { id drawable = r->current_drawable; r->current_drawable = nil; - uint32_t buf_idx = r->frame_index % NUM_BACK_BUFFERS; + U32 buf_idx = r->frame_index % NUM_BACK_BUFFERS; MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; pass.colorAttachments[0].texture = drawable.texture; @@ -741,8 +752,8 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { // Viewport MTLViewport viewport = {}; - viewport.width = (double)r->width; - viewport.height = (double)r->height; + viewport.width = (F64)r->width; + viewport.height = (F64)r->height; viewport.zfar = 1.0; [encoder setViewport:viewport]; @@ -751,7 +762,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { [encoder setScissorRect:full_scissor]; // Constants - float constants[2] = { (float)r->width, (float)r->height }; + F32 constants[2] = { (F32)r->width, (F32)r->height }; [encoder setVertexBytes:constants length:sizeof(constants) atIndex:1]; // Process Clay render commands @@ -763,7 +774,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { batch.index_count = 0; // Track which texture is currently bound (0 = font, 1 = icon) - int bound_texture = 0; + S32 bound_texture = 0; U32 flush_index_start = 0; auto flush_batch = [&]() { @@ -796,7 +807,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { } }; - for (int32_t i = 0; i < render_commands.length; i++) { + for (S32 i = 0; i < render_commands.length; i++) { Clay_RenderCommand *cmd = Clay_RenderCommandArray_Get(&render_commands, i); Clay_BoundingBox bb = cmd->boundingBox; @@ -815,15 +826,15 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { case CLAY_RENDER_COMMAND_TYPE_BORDER: { Clay_BorderRenderData *border = &cmd->renderData.border; Clay_Color c = border->color; - float cr_norm = c.r / 255.f; - float cg_norm = c.g / 255.f; - float cb_norm = c.b / 255.f; - float ca_norm = c.a / 255.f; + F32 cr_norm = c.r / 255.f; + F32 cg_norm = c.g / 255.f; + F32 cb_norm = c.b / 255.f; + F32 ca_norm = c.a / 255.f; // Use SDF rounded border when corner radius is present and widths are uniform Clay_CornerRadius cr = border->cornerRadius; - bool has_radius = cr.topLeft > 0 || cr.topRight > 0 || cr.bottomLeft > 0 || cr.bottomRight > 0; - bool uniform = border->width.top == border->width.bottom && + B32 has_radius = cr.topLeft > 0 || cr.topRight > 0 || cr.bottomLeft > 0 || cr.bottomRight > 0; + B32 uniform = border->width.top == border->width.bottom && border->width.top == border->width.left && border->width.top == border->width.right && border->width.top > 0; @@ -833,7 +844,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { bb.x, bb.y, bb.x + bb.width, bb.y + bb.height, cr_norm, cg_norm, cb_norm, ca_norm, cr.topLeft, cr.topRight, cr.bottomRight, cr.bottomLeft, - (float)border->width.top, 1.0f); + (F32)border->width.top, 1.0f); } else { if (border->width.top > 0) { emit_rect(&batch, bb.x, bb.y, bb.x + bb.width, bb.y + border->width.top, @@ -899,8 +910,8 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { bind_icon_texture(); CustomIconData *icon = (CustomIconData *)custom->customData; Clay_Color c = icon->color; - float cr = c.r / 255.f, cg = c.g / 255.f; - float cb = c.b / 255.f, ca = c.a / 255.f; + F32 cr = c.r / 255.f, cg = c.g / 255.f; + F32 cb = c.b / 255.f, ca = c.a / 255.f; UI_IconInfo *info = &g_icons[icon->icon_id]; emit_quad(&batch, bb.x, bb.y, bb.x + bb.width, bb.y + bb.height, @@ -913,8 +924,8 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { bind_icon_texture(); CustomRotatedIconData *ri = (CustomRotatedIconData *)custom->customData; Clay_Color c = ri->color; - float cr = c.r / 255.f, cg = c.g / 255.f; - float cb = c.b / 255.f, ca = c.a / 255.f; + F32 cr = c.r / 255.f, cg = c.g / 255.f; + F32 cb = c.b / 255.f, ca = c.a / 255.f; UI_IconInfo *info = &g_icons[ri->icon_id]; emit_quad_rotated(&batch, bb.x, bb.y, bb.x + bb.width, bb.y + bb.height, @@ -943,12 +954,13 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) { }]; [cmd_buf commit]; + [drawable release]; } r->frame_index++; } -void renderer_create_icon_atlas(Renderer *r, const uint8_t *data, int32_t w, int32_t h) { +void renderer_create_icon_atlas(Renderer *r, const U8 *data, S32 w, S32 h) { MTLTextureDescriptor *tex_desc = [[MTLTextureDescriptor alloc] init]; tex_desc.pixelFormat = MTLPixelFormatRGBA8Unorm; tex_desc.width = w; @@ -962,21 +974,23 @@ void renderer_create_icon_atlas(Renderer *r, const uint8_t *data, int32_t w, int bytesPerRow:w * 4]; } -void renderer_set_clear_color(Renderer *r, float cr, float cg, float cb) { +void renderer_set_clear_color(Renderer *r, F32 cr, F32 cg, F32 cb) { r->clear_r = cr; r->clear_g = cg; r->clear_b = cb; } -void renderer_set_font_scale(Renderer *r, float scale) { - float target_size = 15.0f * scale; +void renderer_set_font_scale(Renderer *r, F32 scale) { + F32 target_size = 15.0f * scale; if (fabsf(target_size - r->font_atlas_size) < 0.1f) return; + [r->font_texture release]; + [r->font_sampler release]; r->font_texture = nil; r->font_sampler = nil; create_font_atlas(r, target_size); } -void renderer_resize(Renderer *r, int32_t width, int32_t height) { +void renderer_resize(Renderer *r, S32 width, S32 height) { if (width <= 0 || height <= 0) return; r->width = width; r->height = height; diff --git a/src/ui/ui_core.cpp b/src/ui/ui_core.cpp index 0a34814..dba659e 100644 --- a/src/ui/ui_core.cpp +++ b/src/ui/ui_core.cpp @@ -146,7 +146,7 @@ void ui_set_accent(S32 accent_id) { static void clay_error_handler(Clay_ErrorData error) { char buf[512]; - int len = error.errorText.length < 511 ? error.errorText.length : 511; + S32 len = error.errorText.length < 511 ? error.errorText.length : 511; memcpy(buf, error.errorText.chars, len); buf[len] = '\0'; fprintf(stderr, "[Clay Error] %s\n", buf); @@ -161,7 +161,7 @@ static UI_Context *g_measure_ctx = nullptr; static Clay_Dimensions clay_measure_text(Clay_StringSlice text, Clay_TextElementConfig *config, void *user_data) { UI_Context *ctx = (UI_Context *)user_data; if (!ctx || !ctx->measure_text_fn || text.length == 0) { - return Clay_Dimensions{0, (float)config->fontSize}; + return Clay_Dimensions{0, (F32)config->fontSize}; } Vec2F32 result = ctx->measure_text_fn(text.chars, text.length, (F32)config->fontSize, ctx->measure_text_user_data); return Clay_Dimensions{result.x, result.y}; @@ -173,7 +173,7 @@ static Clay_Dimensions clay_measure_text(Clay_StringSlice text, Clay_TextElement UI_Context *ui_create(F32 viewport_w, F32 viewport_h) { UI_Context *ctx = (UI_Context *)calloc(1, sizeof(UI_Context)); - uint32_t min_memory = Clay_MinMemorySize(); + U32 min_memory = Clay_MinMemorySize(); ctx->clay_memory = malloc(min_memory); Clay_Arena clay_arena = Clay_CreateArenaWithCapacityAndMemory(min_memory, ctx->clay_memory); diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index fabc451..72db8ef 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -92,14 +92,14 @@ void ui_set_accent(S32 accent_id); extern F32 g_ui_scale; -// Scale a float value (for CLAY_SIZING_FIXED, corner radii, etc.) -static inline float uis(float x) { return x * g_ui_scale; } +// Scale a F32 value (for CLAY_SIZING_FIXED, corner radii, etc.) +static inline F32 uis(F32 x) { return x * g_ui_scale; } -// Scale to uint16_t (for Clay_Padding, childGap, etc.) -static inline uint16_t uip(float x) { return (uint16_t)(x * g_ui_scale + 0.5f); } +// Scale to U16 (for Clay_Padding, childGap, etc.) +static inline U16 uip(F32 x) { return (U16)(x * g_ui_scale + 0.5f); } -// Scale to uint16_t font size -static inline uint16_t uifs(float x) { return (uint16_t)(x * g_ui_scale + 0.5f); } +// Scale to U16 font size +static inline U16 uifs(F32 x) { return (U16)(x * g_ui_scale + 0.5f); } //////////////////////////////// // Tab styling diff --git a/src/ui/ui_widgets.cpp b/src/ui/ui_widgets.cpp index 0381056..0920237 100644 --- a/src/ui/ui_widgets.cpp +++ b/src/ui/ui_widgets.cpp @@ -44,7 +44,7 @@ static CustomGradientData *alloc_gradient(Clay_Color top, Clay_Color bottom) { // Per-frame shadow layer ID counter (each shadow uses N unique IDs) static S32 g_shadow_id_counter = 0; -// Frame counter for double-click detection +// Frame counter for F64-click detection static S32 g_frame_number = 0; // Emit a smooth multi-layer drop shadow as floating rects. @@ -59,16 +59,16 @@ static S32 g_frame_number = 0; #define SHADOW_LAYERS 7 static void emit_shadow(Clay_BoundingBox bb, F32 ox, F32 oy, F32 radius, - float peak_alpha, int16_t z, - B32 attach_to_root, uint32_t parent_id, + F32 peak_alpha, S16 z, + B32 attach_to_root, U32 parent_id, Clay_FloatingAttachPointType parent_attach) { if (bb.width <= 0) return; - float per_layer = peak_alpha / (float)SHADOW_LAYERS; + F32 per_layer = peak_alpha / (F32)SHADOW_LAYERS; // Draw outermost first (largest, lowest alpha contribution), innermost last for (S32 i = SHADOW_LAYERS - 1; i >= 0; i--) { - float t = (float)(i + 1) / (float)SHADOW_LAYERS; // 1/N .. 1.0 + F32 t = (F32)(i + 1) / (F32)SHADOW_LAYERS; // 1/N .. 1.0 F32 expand = radius * t; S32 sid = g_shadow_id_counter++; @@ -268,8 +268,8 @@ B32 ui_button(const char *id, const char *text) { B32 hovered = Clay_PointerOver(eid); Clay_Color base = hovered ? g_theme.accent_hover : g_theme.accent; - Clay_Color top = {(float)Min((int)base.r+12,255), (float)Min((int)base.g+12,255), (float)Min((int)base.b+12,255), base.a}; - Clay_Color bot = {(float)Max((int)base.r-15,0), (float)Max((int)base.g-15,0), (float)Max((int)base.b-15,0), base.a}; + Clay_Color top = {(F32)Min((S32)base.r+12,255), (F32)Min((S32)base.g+12,255), (F32)Min((S32)base.b+12,255), base.a}; + Clay_Color bot = {(F32)Max((S32)base.r-15,0), (F32)Max((S32)base.g-15,0), (F32)Max((S32)base.b-15,0), base.a}; CustomGradientData *grad = alloc_gradient(top, bot); CLAY(eid, @@ -526,7 +526,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) { // Key events for (S32 k = 0; k < g_wstate.input.key_count; k++) { - uint8_t key = g_wstate.input.keys[k]; + U8 key = g_wstate.input.keys[k]; // Skip Tab — handled via tab cycling if (key == PKEY_TAB) continue; @@ -656,7 +656,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) { // Character input (printable only, skip control chars) if (is_focused) { for (S32 c = 0; c < g_wstate.input.char_count; c++) { - uint16_t ch = g_wstate.input.chars[c]; + U16 ch = g_wstate.input.chars[c]; if (ch >= 32 && ch < 127) { // Delete selection first if any if (text_input_has_sel()) { @@ -726,8 +726,8 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) { Clay_Color border_color = is_focused ? g_theme.accent : g_theme.border; // Inset effect: darker top, lighter bottom (recessed look) - Clay_Color inset_top = {(float)Max((int)bg.r-8,0), (float)Max((int)bg.g-8,0), (float)Max((int)bg.b-8,0), bg.a}; - Clay_Color inset_bot = {(float)Min((int)bg.r+3,255), (float)Min((int)bg.g+3,255), (float)Min((int)bg.b+3,255), bg.a}; + Clay_Color inset_top = {(F32)Max((S32)bg.r-8,0), (F32)Max((S32)bg.g-8,0), (F32)Max((S32)bg.b-8,0), bg.a}; + Clay_Color inset_bot = {(F32)Min((S32)bg.r+3,255), (F32)Min((S32)bg.g+3,255), (F32)Min((S32)bg.b+3,255), bg.a}; CustomGradientData *inset_grad = alloc_gradient(inset_top, inset_bot); CLAY(eid, @@ -820,13 +820,13 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected) static char dd_trunc_buf[256]; const char *display_label = current_label; Clay_ElementId text_eid = WIDI(id, 500); - float avail_w = Clay_GetElementData(text_eid).boundingBox.width; + F32 avail_w = Clay_GetElementData(text_eid).boundingBox.width; if (avail_w > 0) { S32 label_len = (S32)strlen(current_label); Vec2F32 text_size = ui_measure_text(current_label, label_len, FONT_SIZE_NORMAL); if (text_size.x > avail_w) { Vec2F32 dots = ui_measure_text("...", 3, FONT_SIZE_NORMAL); - float target_w = avail_w - dots.x; + F32 target_w = avail_w - dots.x; S32 lo = 0, hi = label_len; while (lo < hi) { S32 mid = (lo + hi + 1) / 2; @@ -845,7 +845,7 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected) Clay_Color bg = is_open ? g_theme.bg_dark : g_theme.bg_medium; if (header_hovered && !is_open) bg = g_theme.bg_lighter; - Clay_Color dd_top = {(float)Min((int)bg.r+6,255), (float)Min((int)bg.g+6,255), (float)Min((int)bg.b+6,255), bg.a}; + Clay_Color dd_top = {(F32)Min((S32)bg.r+6,255), (F32)Min((S32)bg.g+6,255), (F32)Min((S32)bg.b+6,255), bg.a}; CustomGradientData *dd_grad = alloc_gradient(dd_top, bg); CLAY(eid, @@ -892,7 +892,7 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected) // Draw dropdown list if open (floating so it escapes modal/container clipping) if (is_open) { Clay_ElementId list_id = WIDI(id, 502); - float header_width = Clay_GetElementData(eid).boundingBox.width; + F32 header_width = Clay_GetElementData(eid).boundingBox.width; // Dropdown list shadow { @@ -1052,7 +1052,7 @@ S32 ui_modal(const char *id, const char *title, const char *message, // Title bar (gradient: lighter top) { Clay_Color mtb = g_theme.title_bar; - Clay_Color mtb_top = {(float)Min((int)mtb.r+12,255), (float)Min((int)mtb.g+12,255), (float)Min((int)mtb.b+12,255), mtb.a}; + Clay_Color mtb_top = {(F32)Min((S32)mtb.r+12,255), (F32)Min((S32)mtb.g+12,255), (F32)Min((S32)mtb.b+12,255), mtb.a}; CustomGradientData *mtb_grad = alloc_gradient(mtb_top, mtb); CLAY(WIDI(id, 2002), @@ -1099,8 +1099,8 @@ S32 ui_modal(const char *id, const char *title, const char *message, B32 btn_hovered = Clay_PointerOver(btn_id); Clay_Color mbtn_base = btn_hovered ? g_theme.accent_hover : g_theme.accent; - Clay_Color mbtn_top = {(float)Min((int)mbtn_base.r+12,255), (float)Min((int)mbtn_base.g+12,255), (float)Min((int)mbtn_base.b+12,255), mbtn_base.a}; - Clay_Color mbtn_bot = {(float)Max((int)mbtn_base.r-15,0), (float)Max((int)mbtn_base.g-15,0), (float)Max((int)mbtn_base.b-15,0), mbtn_base.a}; + Clay_Color mbtn_top = {(F32)Min((S32)mbtn_base.r+12,255), (F32)Min((S32)mbtn_base.g+12,255), (F32)Min((S32)mbtn_base.b+12,255), mbtn_base.a}; + Clay_Color mbtn_bot = {(F32)Max((S32)mbtn_base.r-15,0), (F32)Max((S32)mbtn_base.g-15,0), (F32)Max((S32)mbtn_base.b-15,0), mbtn_base.a}; CustomGradientData *mbtn_grad = alloc_gradient(mbtn_top, mbtn_bot); CLAY(btn_id, @@ -1136,7 +1136,7 @@ S32 ui_modal(const char *id, const char *title, const char *message, //////////////////////////////// // Draggable window -static UI_WindowSlot *find_or_create_window_slot(uint32_t id, Vec2F32 initial_pos, Vec2F32 initial_size) { +static UI_WindowSlot *find_or_create_window_slot(U32 id, Vec2F32 initial_pos, Vec2F32 initial_size) { // Look for existing slot for (S32 i = 0; i < g_wstate.window_count; i++) { if (g_wstate.windows[i].id == id) { @@ -1157,25 +1157,25 @@ static UI_WindowSlot *find_or_create_window_slot(uint32_t id, Vec2F32 initial_po static void bring_window_to_front(UI_WindowSlot *slot) { // Renormalize if approaching modal z-range if (g_wstate.next_z > 800) { - int16_t sorted[UI_WIDGET_MAX_WINDOWS]; + S16 sorted[UI_WIDGET_MAX_WINDOWS]; S32 count = g_wstate.window_count; for (S32 i = 0; i < count; i++) sorted[i] = g_wstate.windows[i].z_order; // Bubble sort (tiny array) for (S32 i = 0; i < count - 1; i++) { for (S32 j = i + 1; j < count; j++) { if (sorted[j] < sorted[i]) { - int16_t tmp = sorted[i]; sorted[i] = sorted[j]; sorted[j] = tmp; + S16 tmp = sorted[i]; sorted[i] = sorted[j]; sorted[j] = tmp; } } } for (S32 i = 0; i < count; i++) { for (S32 j = 0; j < count; j++) { if (g_wstate.windows[j].z_order == sorted[i]) { - g_wstate.windows[j].z_order = (int16_t)i; + g_wstate.windows[j].z_order = (S16)i; } } } - g_wstate.next_z = (int16_t)count; + g_wstate.next_z = (S16)count; } slot->z_order = g_wstate.next_z++; } @@ -1233,7 +1233,7 @@ B32 ui_window(const char *id, const char *title, B32 *open, // Use absolute position since window uses offset-based floating Clay_BoundingBox shadow_bb = { slot->position.x, slot->position.y, win_bb.width, win_bb.height }; emit_shadow(shadow_bb, uis(3), uis(3), uis(8), - g_theme.shadow.a, (int16_t)(100 + slot->z_order - 1), + g_theme.shadow.a, (S16)(100 + slot->z_order - 1), 1, 0, CLAY_ATTACH_POINT_LEFT_TOP); } @@ -1247,7 +1247,7 @@ B32 ui_window(const char *id, const char *title, B32 *open, .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS), .floating = { .offset = { slot->position.x, slot->position.y }, - .zIndex = (int16_t)(100 + slot->z_order), + .zIndex = (S16)(100 + slot->z_order), .attachPoints = { .element = CLAY_ATTACH_POINT_LEFT_TOP, .parent = CLAY_ATTACH_POINT_LEFT_TOP, @@ -1259,7 +1259,7 @@ B32 ui_window(const char *id, const char *title, B32 *open, ) { // Title bar (gradient: lighter top) Clay_Color tb = g_theme.title_bar; - Clay_Color tb_top = {(float)Min((int)tb.r+12,255), (float)Min((int)tb.g+12,255), (float)Min((int)tb.b+12,255), tb.a}; + Clay_Color tb_top = {(F32)Min((S32)tb.r+12,255), (F32)Min((S32)tb.g+12,255), (F32)Min((S32)tb.b+12,255), tb.a}; CustomGradientData *tb_grad = alloc_gradient(tb_top, tb); CLAY(title_bar_id, @@ -1346,7 +1346,7 @@ S32 ui_tab_bar(const char *id, const char **labels, S32 count, S32 *selected) { .border = { .color = g_theme.border, .width = { .bottom = 1 } }, ) { for (S32 i = 0; i < count; i++) { - Clay_ElementId tab_eid = Clay__HashStringWithOffset(id_str, (uint32_t)i, 0); + Clay_ElementId tab_eid = Clay__HashStringWithOffset(id_str, (U32)i, 0); B32 is_active = (i == *selected); B32 hovered = Clay_PointerOver(tab_eid); @@ -1421,7 +1421,7 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 * }; for (S32 k = 0; k < g_wstate.input.key_count; k++) { - uint8_t key = g_wstate.input.keys[k]; + U8 key = g_wstate.input.keys[k]; if (ctrl) { if (key == PKEY_A) { @@ -1500,7 +1500,7 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 * if (!commit && !cancel) { for (S32 c = 0; c < g_wstate.input.char_count; c++) { - uint16_t ch = g_wstate.input.chars[c]; + U16 ch = g_wstate.input.chars[c]; B32 valid = (ch >= '0' && ch <= '9') || ch == '.' || ch == '-'; if (valid) { if (KE_HAS_SEL()) elen = ke_delete_sel(); @@ -1537,8 +1537,8 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 * } // Render the text edit box with selection/cursor display. -static void value_edit_render(uint32_t hash, F32 width) { - Clay_ElementId edit_eid = CLAY_IDI("ValEdit", (int)hash); +static void value_edit_render(U32 hash, F32 width) { + Clay_ElementId edit_eid = CLAY_IDI("ValEdit", (S32)hash); char *ebuf = g_wstate.knob_edit_buf; S32 elen = (S32)strlen(ebuf); @@ -1588,7 +1588,7 @@ static void value_edit_render(uint32_t hash, F32 width) { S32 n = sel_hi - sel_lo; memcpy(ke_dbuf_sel, &ebuf[sel_lo], n); ke_dbuf_sel[n] = '\0'; Clay_String s_sel = { .length = n, .chars = ke_dbuf_sel }; - CLAY(CLAY_IDI("ValEditSel", (int)hash), + CLAY(CLAY_IDI("ValEditSel", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() } }, .backgroundColor = g_theme.accent ) { @@ -1616,8 +1616,8 @@ static void value_edit_render(uint32_t hash, F32 width) { } // Get the Clay element ID of the current edit box (for click-away detection). -static Clay_ElementId value_edit_eid(uint32_t hash) { - return CLAY_IDI("ValEdit", (int)hash); +static Clay_ElementId value_edit_eid(U32 hash) { + return CLAY_IDI("ValEdit", (S32)hash); } // Handle click-outside to commit the edit. @@ -1636,7 +1636,7 @@ static void value_edit_click_away(Clay_ElementId eid, F32 *value, F32 max_val, B } // Enter text edit mode for a widget. -static void value_edit_enter(uint32_t hash, F32 value, B32 is_signed) { +static void value_edit_enter(U32 hash, F32 value, B32 is_signed) { g_wstate.knob_edit_id = hash; g_wstate.focused_id = 0; if (is_signed) { @@ -1684,7 +1684,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s F32 deg_to_rad = 3.14159265f / 180.0f; F32 angle_rad = (-135.0f + normalized * 270.0f) * deg_to_rad; - uint32_t knob_hash = Clay__HashString(clay_str(id), 0).id; + U32 knob_hash = Clay__HashString(clay_str(id), 0).id; B32 is_editing = (editable && g_wstate.knob_edit_id == knob_hash); UI_KnobDragState *kd = &g_wstate.knob_drag; @@ -1732,7 +1732,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s .layoutDirection = CLAY_TOP_TO_BOTTOM, } ) { - Clay_ElementId knob_eid = CLAY_IDI("KnobBg", (int)knob_hash); + Clay_ElementId knob_eid = CLAY_IDI("KnobBg", (S32)knob_hash); B32 hovered = Clay_PointerOver(knob_eid); CLAY(knob_eid, @@ -1761,7 +1761,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s } } - // Click: double-click resets, single click starts drag + // Click: F64-click resets, single click starts drag if (!is_editing && hovered && g_wstate.mouse_clicked && kd->dragging_id == 0) { B32 is_double_click = (kd->last_click_id == knob_hash && (g_frame_number - kd->last_click_frame) < 20); @@ -1785,7 +1785,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s value_edit_render(knob_hash, knob_size); value_edit_click_away(value_edit_eid(knob_hash), value, max_val, is_signed, &changed); } else if (val_text && val_len > 0) { - Clay_ElementId val_eid = CLAY_IDI("KnobVal", (int)knob_hash); + Clay_ElementId val_eid = CLAY_IDI("KnobVal", (S32)knob_hash); B32 val_hovered = Clay_PointerOver(val_eid); Clay_String val_str = { .isStaticallyAllocated = false, .length = val_len, .chars = val_text }; @@ -1824,7 +1824,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32 B32 changed = 0; F32 normalized = value_normalize(*value, max_val, is_signed); - uint32_t hash = Clay__HashString(clay_str(id), 0).id; + U32 hash = Clay__HashString(clay_str(id), 0).id; B32 is_editing = (editable && g_wstate.knob_edit_id == hash); UI_KnobDragState *kd = &g_wstate.knob_drag; @@ -1883,7 +1883,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32 CLAY_TEXT(clay_str(label), &g_widget_text_config_dim); // Hit area (transparent, sized to encompass thumb travel) - Clay_ElementId hit_eid = CLAY_IDI("SlHHit", (int)hash); + Clay_ElementId hit_eid = CLAY_IDI("SlHHit", (S32)hash); B32 hovered = Clay_PointerOver(hit_eid); CLAY(hit_eid, @@ -1893,7 +1893,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32 } ) { // Visible track (centered inside hit area) - CLAY(CLAY_IDI("SlHTrack", (int)hash), + CLAY(CLAY_IDI("SlHTrack", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) }, }, @@ -1903,7 +1903,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32 // Fill bar F32 fill_w = normalized * track_w; if (fill_w < 1.0f) fill_w = 1.0f; - CLAY(CLAY_IDI("SlHFill", (int)hash), + CLAY(CLAY_IDI("SlHFill", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(fill_w), .height = CLAY_SIZING_GROW() }, }, @@ -1919,7 +1919,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32 idata->icon_id = (S32)UI_ICON_SLIDER_THUMB; idata->color = g_theme.accent; - CLAY(CLAY_IDI("SlHThumb", (int)hash), + CLAY(CLAY_IDI("SlHThumb", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(thumb_w), .height = CLAY_SIZING_FIXED(thumb_h) }, }, @@ -1941,7 +1941,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32 } } - // Click: double-click resets, single click starts drag + // Click: F64-click resets, single click starts drag if (!is_editing && hovered && g_wstate.mouse_clicked && kd->dragging_id == 0) { B32 is_double_click = (kd->last_click_id == hash && (g_frame_number - kd->last_click_frame) < 20); @@ -1964,7 +1964,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32 value_edit_render(hash, track_w); value_edit_click_away(value_edit_eid(hash), value, max_val, is_signed, &changed); } else if (val_text && val_len > 0) { - Clay_ElementId val_eid = CLAY_IDI("SlHVal", (int)hash); + Clay_ElementId val_eid = CLAY_IDI("SlHVal", (S32)hash); B32 val_hovered = Clay_PointerOver(val_eid); Clay_String val_str = { .isStaticallyAllocated = false, .length = val_len, .chars = val_text }; @@ -2000,7 +2000,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32 B32 changed = 0; F32 normalized = value_normalize(*value, max_val, is_signed); - uint32_t hash = Clay__HashString(clay_str(id), 0).id; + U32 hash = Clay__HashString(clay_str(id), 0).id; B32 is_editing = (editable && g_wstate.knob_edit_id == hash); UI_KnobDragState *kd = &g_wstate.knob_drag; @@ -2059,7 +2059,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32 CLAY_TEXT(clay_str(label), &g_widget_text_config_dim); // Hit area (transparent, sized to encompass thumb travel) - Clay_ElementId hit_eid = CLAY_IDI("SlVHit", (int)hash); + Clay_ElementId hit_eid = CLAY_IDI("SlVHit", (S32)hash); B32 hovered = Clay_PointerOver(hit_eid); CLAY(hit_eid, @@ -2069,7 +2069,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32 } ) { // Visible track (centered inside hit area) - CLAY(CLAY_IDI("SlVTrack", (int)hash), + CLAY(CLAY_IDI("SlVTrack", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) }, .childAlignment = { .y = CLAY_ALIGN_Y_BOTTOM }, @@ -2080,7 +2080,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32 // Fill bar (from bottom) F32 fill_h = normalized * track_h; if (fill_h < 1.0f) fill_h = 1.0f; - CLAY(CLAY_IDI("SlVFill", (int)hash), + CLAY(CLAY_IDI("SlVFill", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(fill_h) }, }, @@ -2096,7 +2096,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32 idata->icon_id = (S32)UI_ICON_SLIDER_THUMB; idata->color = g_theme.accent; - CLAY(CLAY_IDI("SlVThumb", (int)hash), + CLAY(CLAY_IDI("SlVThumb", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(thumb_w), .height = CLAY_SIZING_FIXED(thumb_h) }, }, @@ -2118,7 +2118,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32 } } - // Click: double-click resets, single click starts drag + // Click: F64-click resets, single click starts drag if (!is_editing && hovered && g_wstate.mouse_clicked && kd->dragging_id == 0) { B32 is_double_click = (kd->last_click_id == hash && (g_frame_number - kd->last_click_frame) < 20); @@ -2141,7 +2141,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32 value_edit_render(hash, thumb_w * 2.0f); value_edit_click_away(value_edit_eid(hash), value, max_val, is_signed, &changed); } else if (val_text && val_len > 0) { - Clay_ElementId val_eid = CLAY_IDI("SlVVal", (int)hash); + Clay_ElementId val_eid = CLAY_IDI("SlVVal", (S32)hash); B32 val_hovered = Clay_PointerOver(val_eid); Clay_String val_str = { .isStaticallyAllocated = false, .length = val_len, .chars = val_text }; @@ -2177,7 +2177,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ B32 changed = 0; F32 normalized = value_normalize(*value, max_val, is_signed); - uint32_t hash = Clay__HashString(clay_str(id), 0).id; + U32 hash = Clay__HashString(clay_str(id), 0).id; B32 is_editing = (editable && g_wstate.knob_edit_id == hash); UI_KnobDragState *kd = &g_wstate.knob_drag; @@ -2239,7 +2239,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ CLAY_TEXT(clay_str(label), &g_widget_text_config_dim); // Hit area (transparent, sized to encompass fader cap travel) - Clay_ElementId hit_eid = CLAY_IDI("FdrHit", (int)hash); + Clay_ElementId hit_eid = CLAY_IDI("FdrHit", (S32)hash); B32 hovered = Clay_PointerOver(hit_eid); CLAY(hit_eid, @@ -2249,7 +2249,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ } ) { // Visible track (centered inside hit area, empty) - CLAY(CLAY_IDI("FdrTrack", (int)hash), + CLAY(CLAY_IDI("FdrTrack", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) }, }, @@ -2264,7 +2264,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ F32 tw = (i % 5 == 0) ? tick_major_w : tick_minor_w; // Left tick - CLAY(CLAY_IDI("FdrTkL", (int)(hash * 100 + i)), + CLAY(CLAY_IDI("FdrTkL", (S32)(hash * 100 + i)), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(tw), .height = CLAY_SIZING_FIXED(tick_h) }, }, @@ -2285,7 +2285,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ ) {} // Right tick - CLAY(CLAY_IDI("FdrTkR", (int)(hash * 100 + i)), + CLAY(CLAY_IDI("FdrTkR", (S32)(hash * 100 + i)), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(tw), .height = CLAY_SIZING_FIXED(tick_h) }, }, @@ -2315,7 +2315,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ F32 cap_y = (1.0f - normalized) * (track_h - cap_h); - CLAY(CLAY_IDI("FdrCap", (int)hash), + CLAY(CLAY_IDI("FdrCap", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(cap_h) }, }, @@ -2336,7 +2336,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ Clay_Color tint = g_theme.accent; tint.a = 80; F32 cap_corner = cap_w * (3.0f / 62.2f); - CLAY(CLAY_IDI("FdrTint", (int)hash), + CLAY(CLAY_IDI("FdrTint", (S32)hash), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(cap_h) }, }, @@ -2356,7 +2356,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ } } - // Click: double-click resets, single click starts drag + // Click: F64-click resets, single click starts drag if (!is_editing && hovered && g_wstate.mouse_clicked && kd->dragging_id == 0) { B32 is_double_click = (kd->last_click_id == hash && (g_frame_number - kd->last_click_frame) < 20); @@ -2379,7 +2379,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_ value_edit_render(hash, cap_w * 2.0f); value_edit_click_away(value_edit_eid(hash), value, max_val, is_signed, &changed); } else if (val_text && val_len > 0) { - Clay_ElementId val_eid = CLAY_IDI("FdrVal", (int)hash); + Clay_ElementId val_eid = CLAY_IDI("FdrVal", (S32)hash); B32 val_hovered = Clay_PointerOver(val_eid); Clay_String val_str = { .isStaticallyAllocated = false, .length = val_len, .chars = val_text }; diff --git a/src/ui/ui_widgets.h b/src/ui/ui_widgets.h index 407a36e..79c665b 100644 --- a/src/ui/ui_widgets.h +++ b/src/ui/ui_widgets.h @@ -19,51 +19,51 @@ struct UI_ModalState { B32 active; - uint32_t id; // Hash of the modal's string ID + U32 id; // Hash of the modal's string ID S32 result; // Button index pressed, -1 = pending }; struct UI_WindowSlot { - uint32_t id; // Hash of the window's string ID (0 = unused) + U32 id; // Hash of the window's string ID (0 = unused) Vec2F32 position; Vec2F32 size; B32 open; - int16_t z_order; + S16 z_order; }; struct UI_KnobDragState { - uint32_t dragging_id; // Hash of the knob being dragged (0 = none) + U32 dragging_id; // Hash of the knob being dragged (0 = none) F32 drag_start_y; // Mouse Y when drag started F32 drag_start_x; // Mouse X when drag started (for h-slider) F32 value_at_start; // Value when drag started B32 was_shift; // Shift state last frame (to re-anchor on change) - uint32_t last_click_id; // Knob hash of last click (for double-click detection) + U32 last_click_id; // Knob hash of last click (for F64-click detection) S32 last_click_frame; // Frame number of last click }; struct UI_DragState { - uint32_t dragging_id; // Window ID currently being dragged (0 = none) + U32 dragging_id; // Window ID currently being dragged (0 = none) Vec2F32 drag_anchor; // Mouse position when drag started Vec2F32 pos_anchor; // Window position when drag started }; struct UI_WidgetState { // Text input focus - uint32_t focused_id; // Clay element ID hash of the focused text input (0 = none) - int32_t cursor_pos; // Cursor position in focused text input + U32 focused_id; // Clay element ID hash of the focused text input (0 = none) + S32 cursor_pos; // Cursor position in focused text input F32 cursor_blink; // Blink timer (seconds) // Text selection (sel_start == sel_end means no selection) - int32_t sel_start; // Selection anchor (where selection began) - int32_t sel_end; // Selection extent (moves with cursor) + S32 sel_start; // Selection anchor (where selection began) + S32 sel_end; // Selection extent (moves with cursor) // Tab cycling: registered text input IDs in order of declaration - uint32_t text_input_ids[UI_WIDGET_MAX_TEXT_INPUTS]; - int32_t text_input_count; + U32 text_input_ids[UI_WIDGET_MAX_TEXT_INPUTS]; + S32 text_input_count; B32 tab_pressed; // True on the frame Tab was pressed // Dropdown - uint32_t open_dropdown_id; // Clay element ID hash of the open dropdown (0 = none) + U32 open_dropdown_id; // Clay element ID hash of the open dropdown (0 = none) // Input for this frame PlatformInput input; @@ -77,14 +77,14 @@ struct UI_WidgetState { // Window state UI_WindowSlot windows[UI_WIDGET_MAX_WINDOWS]; S32 window_count; - int16_t next_z; + S16 next_z; UI_DragState drag; // Knob drag state UI_KnobDragState knob_drag; // Knob text edit state - uint32_t knob_edit_id; // Hash of knob in text edit mode (0 = none) + U32 knob_edit_id; // Hash of knob in text edit mode (0 = none) char knob_edit_buf[32]; // Text buffer for numeric entry S32 knob_edit_cursor; // Cursor position in edit buffer S32 knob_edit_sel_start; // Selection anchor @@ -154,7 +154,7 @@ B32 ui_window(const char *id, const char *title, B32 *open, // Knob / potentiometer. Vertical drag to change value. // unsigned (is_signed=0): value in [0, max_val] // signed (is_signed=1): value in [-max_val, +max_val] -// default_val: value restored on double-click. +// default_val: value restored on F64-click. // editable: if true, clicking the value text opens a text input for direct entry. // Hold Shift while dragging for fine control. // Returns true if value changed this frame.