Revert "Format all"

This reverts commit c7bb89fd6d.
This commit is contained in:
2026-03-12 16:30:04 -04:00
parent 48f2c51d92
commit d5d2f6db8e
31 changed files with 3191 additions and 3280 deletions

View File

@@ -1,31 +0,0 @@
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: Never
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
AlignConsecutiveDeclarations: true
AlignConsecutiveAssignments: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AlignConsecutiveMacros: true
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true
Cpp11BracedListStyle: false
ColumnLimit: 0

View File

@@ -13,7 +13,7 @@ AudioEngine *audio_create(void *hwnd);
void audio_destroy(AudioEngine *engine);
void audio_refresh_devices(AudioEngine *engine);
S32 audio_get_device_count(AudioEngine *engine);
AudioDeviceInfo *audio_get_device(AudioEngine *engine, S32 index);
AudioDeviceInfo*audio_get_device(AudioEngine *engine, S32 index);
B32 audio_open_device(AudioEngine *engine, S32 index);
void audio_close_device(AudioEngine *engine);

View File

@@ -1,8 +1,8 @@
#include "audio/audio.h"
#include <math.h>
#include <windows.h>
#include <objbase.h>
#include <string.h>
#include <windows.h>
#include <math.h>
#define AUDIO_MAX_DEVICES 32
#define AUDIO_MAX_CHANNELS 32
@@ -124,7 +124,7 @@ enum {
// Standard ASIO vtable — inherits IUnknown
class IASIO : public IUnknown {
public:
public:
virtual ASIOBool init(void *sysHandle) = 0;
virtual void getDriverName(char *name) = 0;
virtual long getDriverVersion() = 0;

View File

@@ -1,9 +1,9 @@
#include "audio/audio.h"
#include <AudioToolbox/AudioToolbox.h>
#include <CoreAudio/CoreAudio.h>
#include <string.h>
#include <math.h>
#include <stdatomic.h>
#include <string.h>
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -44,11 +44,9 @@ static OSStatus audio_render_callback(void *inRefCon,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
(void)inRefCon;
(void)ioActionFlags;
(void)inTimeStamp;
(void)inBusNumber;
AudioBufferList *ioData)
{
(void)inRefCon; (void)ioActionFlags; (void)inTimeStamp; (void)inBusNumber;
AudioEngine *engine = g_audio_engine;
if (!engine) {
@@ -87,8 +85,7 @@ static OSStatus audio_render_callback(void *inRefCon,
// Advance phase using first channel's traversal
phase += phase_inc * samples_to_gen;
while (phase >= 2.0 * AUDIO_PI)
phase -= 2.0 * AUDIO_PI;
while (phase >= 2.0 * AUDIO_PI) phase -= 2.0 * AUDIO_PI;
engine->test_tone_phase = phase;
S32 new_remaining = atomic_fetch_sub(&engine->test_tone_samples_remaining, samples_to_gen);

View File

@@ -34,7 +34,7 @@ void arena_clear(Arena *arena);
////////////////////////////////
// Temporary scope helpers
inline Temp temp_begin(Arena *arena) { return { arena, arena->pos }; }
inline Temp temp_begin(Arena *arena) { return {arena, arena->pos}; }
inline void temp_end(Temp temp) { arena_pop_to(temp.arena, temp.pos); }
////////////////////////////////

View File

@@ -2,11 +2,11 @@
// base_core.h - Fundamental types, macros, and linked list helpers
// Inspired by raddebugger's base_core.h
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
////////////////////////////////
// Codebase keywords
@@ -60,14 +60,13 @@ typedef double F64;
#define Max(A, B) (((A) > (B)) ? (A) : (B))
#define ClampTop(A, X) Min(A, X)
#define ClampBot(X, B) Max(X, B)
#define Clamp(A, X, B) (((X) < (A)) ? (A) : ((X) > (B)) ? (B) \
: (X))
#define Clamp(A, X, B) (((X) < (A)) ? (A) : ((X) > (B)) ? (B) : (X))
////////////////////////////////
// Alignment / Sizing
#define AlignPow2(x, b) (((x) + (b)-1) & (~((b)-1)))
#define AlignDownPow2(x, b) ((x) & (~((b)-1)))
#define AlignPow2(x, b) (((x) + (b) - 1) & (~((b) - 1)))
#define AlignDownPow2(x, b) ((x) & (~((b) - 1)))
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
////////////////////////////////
@@ -110,33 +109,25 @@ typedef double F64;
#define Glue_(A, B) A##B
#define Glue(A, B) Glue_(A, B)
#define Swap(T, a, b) \
do { \
T t__ = a; \
a = b; \
b = t__; \
} while (0)
#define Swap(T, a, b) do { T t__ = a; a = b; b = t__; } while (0)
////////////////////////////////
// Assert
#if defined(_MSC_VER)
#define Trap() __debugbreak()
# define Trap() __debugbreak()
#elif defined(__clang__) || defined(__GNUC__)
#define Trap() __builtin_trap()
# define Trap() __builtin_trap()
#else
#define Trap() (*(volatile int *)0 = 0)
# define Trap() (*(volatile int *)0 = 0)
#endif
#define AssertAlways(x) \
do { \
if (!(x)) { Trap(); } \
} while (0)
#define AssertAlways(x) do { if (!(x)) { Trap(); } } while (0)
#ifdef _DEBUG
#define Assert(x) AssertAlways(x)
# define Assert(x) AssertAlways(x)
#else
#define Assert(x) (void)(x)
# define Assert(x) (void)(x)
#endif
#define InvalidPath Assert(!"Invalid Path!")
@@ -151,9 +142,14 @@ typedef double F64;
// Doubly-linked-list (with nil support)
#define DLLInsert_NPZ(nil, f, l, p, n, next, prev) \
(CheckNil(nil, f) ? ((f) = (l) = (n), SetNil(nil, (n)->next), SetNil(nil, (n)->prev)) : CheckNil(nil, p) ? ((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil, (n)->prev)) \
: ((p) == (l)) ? ((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) \
: (((!CheckNil(nil, p) && CheckNil(nil, (p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
(CheckNil(nil, f) ? \
((f) = (l) = (n), SetNil(nil, (n)->next), SetNil(nil, (n)->prev)) : \
CheckNil(nil, p) ? \
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil, (n)->prev)) : \
((p) == (l)) ? \
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) : \
(((!CheckNil(nil, p) && CheckNil(nil, (p)->next)) ? (0) : ((p)->next->prev = (n))), \
((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
#define DLLPushBack_NPZ(nil, f, l, n, next, prev) DLLInsert_NPZ(nil, f, l, l, n, next, prev)
#define DLLPushFront_NPZ(nil, f, l, n, next, prev) DLLInsert_NPZ(nil, l, f, f, n, prev, next)
@@ -171,7 +167,9 @@ typedef double F64;
// Singly-linked queue (doubly-headed)
#define SLLQueuePush_NZ(nil, f, l, n, next) \
(CheckNil(nil, f) ? ((f) = (l) = (n), SetNil(nil, (n)->next)) : ((l)->next = (n), (l) = (n), SetNil(nil, (n)->next)))
(CheckNil(nil, f) ? \
((f) = (l) = (n), SetNil(nil, (n)->next)) : \
((l)->next = (n), (l) = (n), SetNil(nil, (n)->next)))
#define SLLQueuePush(f, l, n) SLLQueuePush_NZ(0, f, l, n, next)
#define SLLQueuePushFront(f, l, n) (((n)->next = (f)), ((f) = (n)))

View File

@@ -2,7 +2,7 @@
// base_inc.h - Umbrella include for the base layer
// Include this one header to get all base types.
#include "base/base_arena.h"
#include "base/base_core.h"
#include "base/base_arena.h"
#include "base/base_math.h"
#include "base/base_strings.h"

View File

@@ -30,66 +30,51 @@ enum Corner {
////////////////////////////////
// Vector types
struct Vec2F32 {
F32 x, y;
};
struct Vec2S32 {
S32 x, y;
};
struct Vec3F32 {
F32 x, y, z;
};
struct Vec4F32 {
F32 x, y, z, w;
};
struct Vec2F32 { F32 x, y; };
struct Vec2S32 { S32 x, y; };
struct Vec3F32 { F32 x, y, z; };
struct Vec4F32 { F32 x, y, z, w; };
////////////////////////////////
// Range types
struct Rng1F32 {
F32 min, max;
};
struct Rng1S64 {
S64 min, max;
};
struct Rng2F32 {
Vec2F32 p0, p1;
};
struct Rng1F32 { F32 min, max; };
struct Rng1S64 { S64 min, max; };
struct Rng2F32 { Vec2F32 p0, p1; };
////////////////////////////////
// Constructors
static inline Vec2F32 v2f32(F32 x, F32 y) { return { x, y }; }
static inline Vec2S32 v2s32(S32 x, S32 y) { return { x, y }; }
static inline Vec3F32 v3f32(F32 x, F32 y, F32 z) { return { x, y, z }; }
static inline Vec4F32 v4f32(F32 x, F32 y, F32 z, F32 w) { return { x, y, z, w }; }
static inline Rng1F32 rng1f32(F32 min, F32 max) { return { min, max }; }
static inline Rng1S64 rng1s64(S64 min, S64 max) { return { min, max }; }
static inline Rng2F32 rng2f32(Vec2F32 p0, Vec2F32 p1) { return { p0, p1 }; }
static inline Rng2F32 rng2f32p(F32 x0, F32 y0, F32 x1, F32 y1) { return { { x0, y0 }, { x1, y1 } }; }
static inline Vec2F32 v2f32(F32 x, F32 y) { return {x, y}; }
static inline Vec2S32 v2s32(S32 x, S32 y) { return {x, y}; }
static inline Vec3F32 v3f32(F32 x, F32 y, F32 z) { return {x, y, z}; }
static inline Vec4F32 v4f32(F32 x, F32 y, F32 z, F32 w) { return {x, y, z, w}; }
static inline Rng1F32 rng1f32(F32 min, F32 max) { return {min, max}; }
static inline Rng1S64 rng1s64(S64 min, S64 max) { return {min, max}; }
static inline Rng2F32 rng2f32(Vec2F32 p0, Vec2F32 p1) { return {p0, p1}; }
static inline Rng2F32 rng2f32p(F32 x0, F32 y0, F32 x1, F32 y1) { return {{x0, y0}, {x1, y1}}; }
////////////////////////////////
// Vec2F32 operations
static inline Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b) { return { a.x + b.x, a.y + b.y }; }
static inline Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b) { return { a.x - b.x, a.y - b.y }; }
static inline Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b) { return { a.x * b.x, a.y * b.y }; }
static inline Vec2F32 scale_2f32(Vec2F32 v, F32 s) { return { v.x * s, v.y * s }; }
static inline Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b) { return {a.x + b.x, a.y + b.y}; }
static inline Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b) { return {a.x - b.x, a.y - b.y}; }
static inline Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b) { return {a.x * b.x, a.y * b.y}; }
static inline Vec2F32 scale_2f32(Vec2F32 v, F32 s) { return {v.x * s, v.y * s}; }
// Axis-indexed access
static inline F32 v2f32_axis(Vec2F32 v, Axis2 a) { return a == Axis2_X ? v.x : v.y; }
static inline void v2f32_set_axis(Vec2F32 *v, Axis2 a, F32 val) {
if (a == Axis2_X) v->x = val;
else v->y = val;
if (a == Axis2_X) v->x = val; else v->y = val;
}
////////////////////////////////
// Vec4F32 operations
static inline Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b) { return { a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
static inline Vec4F32 scale_4f32(Vec4F32 v, F32 s) { return { v.x * s, v.y * s, v.z * s, v.w * s }; }
static inline Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b) { return {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; }
static inline Vec4F32 scale_4f32(Vec4F32 v, F32 s) { return {v.x*s, v.y*s, v.z*s, v.w*s}; }
static inline Vec4F32 lerp_4f32(Vec4F32 a, Vec4F32 b, F32 t) {
return { a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t };
return {a.x + (b.x - a.x)*t, a.y + (b.y - a.y)*t, a.z + (b.z - a.z)*t, a.w + (b.w - a.w)*t};
}
////////////////////////////////
@@ -97,20 +82,20 @@ static inline Vec4F32 lerp_4f32(Vec4F32 a, Vec4F32 b, F32 t) {
static inline F32 rng2f32_width(Rng2F32 r) { return r.p1.x - r.p0.x; }
static inline F32 rng2f32_height(Rng2F32 r) { return r.p1.y - r.p0.y; }
static inline Vec2F32 rng2f32_dim(Rng2F32 r) { return { r.p1.x - r.p0.x, r.p1.y - r.p0.y }; }
static inline Vec2F32 rng2f32_center(Rng2F32 r) { return { (r.p0.x + r.p1.x) * 0.5f, (r.p0.y + r.p1.y) * 0.5f }; }
static inline Vec2F32 rng2f32_dim(Rng2F32 r) { return {r.p1.x - r.p0.x, r.p1.y - r.p0.y}; }
static inline Vec2F32 rng2f32_center(Rng2F32 r) { return {(r.p0.x + r.p1.x)*0.5f, (r.p0.y + r.p1.y)*0.5f}; }
static inline B32 rng2f32_contains(Rng2F32 r, Vec2F32 p) {
return p.x >= r.p0.x && p.x <= r.p1.x && p.y >= r.p0.y && p.y <= r.p1.y;
}
static inline Rng2F32 rng2f32_pad(Rng2F32 r, F32 p) {
return { { r.p0.x - p, r.p0.y - p }, { r.p1.x + p, r.p1.y + p } };
return {{r.p0.x - p, r.p0.y - p}, {r.p1.x + p, r.p1.y + p}};
}
static inline Rng2F32 rng2f32_shift(Rng2F32 r, Vec2F32 v) {
return { { r.p0.x + v.x, r.p0.y + v.y }, { r.p1.x + v.x, r.p1.y + v.y } };
return {{r.p0.x + v.x, r.p0.y + v.y}, {r.p1.x + v.x, r.p1.y + v.y}};
}
static inline Rng2F32 rng2f32_intersect(Rng2F32 a, Rng2F32 b) {
return { { Max(a.p0.x, b.p0.x), Max(a.p0.y, b.p0.y) },
{ Min(a.p1.x, b.p1.x), Min(a.p1.y, b.p1.y) } };
return {{Max(a.p0.x, b.p0.x), Max(a.p0.y, b.p0.y)},
{Min(a.p1.x, b.p1.x), Min(a.p1.y, b.p1.y)}};
}
// Axis-indexed range dimension

View File

@@ -12,15 +12,15 @@ Str8 str8_pushf(Arena *arena, const char *fmt, ...) {
vsnprintf(buf, len + 1, fmt, args2);
va_end(args2);
return { buf, (U64)len };
return {buf, (U64)len};
}
Str8 str8_push_copy(Arena *arena, Str8 s) {
if (s.size == 0 || !s.str) return { nullptr, 0 };
if (s.size == 0 || !s.str) return {nullptr, 0};
char *buf = push_array_no_zero(arena, char, s.size + 1);
MemoryCopy(buf, s.str, s.size);
buf[s.size] = 0;
return { buf, s.size };
return {buf, s.size};
}
void str8_list_push(Arena *arena, Str8List *list, Str8 s) {

View File

@@ -31,9 +31,9 @@ struct Arena;
////////////////////////////////
// Constructors
static inline Str8 str8(const char *s, U64 len) { return { s, len }; }
static inline Str8 str8_cstr(const char *s) { return { s, s ? (U64)strlen(s) : 0 }; }
static inline Str8 str8_lit(const char *s) { return { s, s ? (U64)strlen(s) : 0 }; }
static inline Str8 str8(const char *s, U64 len) { return {s, len}; }
static inline Str8 str8_cstr(const char *s) { return {s, s ? (U64)strlen(s) : 0}; }
static inline Str8 str8_lit(const char *s) { return {s, s ? (U64)strlen(s) : 0}; }
static inline B32 str8_match(Str8 a, Str8 b) {
if (a.size != b.size) return 0;
return MemoryCompare(a.str, b.str, a.size) == 0;

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
#include "midi/midi.h"
#include <CoreFoundation/CoreFoundation.h>
#include <CoreMIDI/CoreMIDI.h>
#include <stdatomic.h>
#include <CoreFoundation/CoreFoundation.h>
#include <string.h>
#include <stdatomic.h>
#define MIDI_MAX_DEVICES 64
#define MIDI_RELEASE_FLASH_DURATION 0.15f
@@ -46,14 +46,11 @@ static void midi_read_callback(const MIDIPacketList *pktlist, void *readProcRefC
const MIDIPacket *packet = &pktlist->packet[0];
for (UInt32 i = 0; i < pktlist->numPackets; i++) {
// Parse MIDI bytes
for (UInt16 j = 0; j < packet->length;) {
for (UInt16 j = 0; j < packet->length; ) {
U8 status = packet->data[j];
// Skip non-status bytes (running status not handled for simplicity)
if (status < 0x80) {
j++;
continue;
}
if (status < 0x80) { j++; continue; }
U8 kind = status & 0xF0;
@@ -95,8 +92,7 @@ static void midi_read_callback(const MIDIPacketList *pktlist, void *readProcRefC
} else if (kind == 0xF0) {
// System messages — skip to end or next status byte
j++;
while (j < packet->length && packet->data[j] < 0x80)
j++;
while (j < packet->length && packet->data[j] < 0x80) j++;
} else {
j += 3; // Default: 3-byte message
}

View File

@@ -1,7 +1,7 @@
#include "midi/midi.h"
#include <windows.h>
#include <mmeapi.h>
#include <string.h>
#include <windows.h>
#define MIDI_MAX_DEVICES 64
#define MIDI_RELEASE_FLASH_DURATION 0.15f

View File

@@ -4,27 +4,16 @@
// macOS virtual key codes (avoids Carbon.h include)
enum {
kVK_ANSI_A = 0x00,
kVK_ANSI_C = 0x08,
kVK_ANSI_V = 0x09,
kVK_ANSI_A = 0x00, kVK_ANSI_C = 0x08, kVK_ANSI_V = 0x09,
kVK_ANSI_X = 0x07,
kVK_Return = 0x24,
kVK_Tab = 0x30,
kVK_Delete = 0x33,
kVK_Escape = 0x35,
kVK_ForwardDelete = 0x75,
kVK_LeftArrow = 0x7B,
kVK_RightArrow = 0x7C,
kVK_DownArrow = 0x7D,
kVK_UpArrow = 0x7E,
kVK_Home = 0x73,
kVK_End = 0x77,
kVK_Command = 0x37,
kVK_Shift = 0x38,
kVK_RightShift = 0x3C,
kVK_RightCommand = 0x36,
kVK_ANSI_Equal = 0x18,
kVK_ANSI_Minus = 0x1B,
kVK_Return = 0x24, kVK_Tab = 0x30, kVK_Delete = 0x33,
kVK_Escape = 0x35, kVK_ForwardDelete = 0x75,
kVK_LeftArrow = 0x7B, kVK_RightArrow = 0x7C,
kVK_DownArrow = 0x7D, kVK_UpArrow = 0x7E,
kVK_Home = 0x73, kVK_End = 0x77,
kVK_Command = 0x37, kVK_Shift = 0x38,
kVK_RightShift = 0x3C, kVK_RightCommand = 0x36,
kVK_ANSI_Equal = 0x18, kVK_ANSI_Minus = 0x1B,
kVK_ANSI_0 = 0x1D,
kVK_ANSI_KeypadEnter = 0x4C,
};
@@ -39,7 +28,7 @@ static U8 macos_keycode_to_pkey(U16 keycode) {
case kVK_ANSI_KeypadEnter: return PKEY_RETURN;
case kVK_Tab: return PKEY_TAB;
case kVK_Delete: return PKEY_BACKSPACE;
case kVK_ForwardDelete: return PKEY_DELETE;
case kVK_ForwardDelete:return PKEY_DELETE;
case kVK_Escape: return PKEY_ESCAPE;
case kVK_LeftArrow: return PKEY_LEFT;
case kVK_RightArrow: return PKEY_RIGHT;
@@ -69,23 +58,18 @@ static PlatformWindow *g_main_window = nullptr;
@end
@implementation ASmplAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
(void)notification;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
(void)sender;
return YES;
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification { (void)notification; }
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { (void)sender; return YES; }
@end
@interface ASmplWindowDelegate : NSObject <NSWindowDelegate> {
@public
@public
PlatformWindow *_platformWindow;
}
@end
@interface ASmplView : NSView <NSTextInputClient> {
@public
@public
PlatformWindow *_platformWindow;
}
@end
@@ -117,10 +101,7 @@ static void platform_macos_insert_text_pw(PlatformWindow *pw, const char *utf8)
PlatformInput *ev = &pw->input;
while (*utf8 && ev->char_count < PLATFORM_MAX_CHARS_PER_FRAME) {
U8 c = (U8)*utf8;
if (c < 32) {
utf8++;
continue;
}
if (c < 32) { utf8++; continue; }
// Handle ASCII printable range (single-byte UTF-8)
if (c < 0x80) {
ev->chars[ev->char_count++] = (U16)c;
@@ -174,45 +155,25 @@ static void platform_macos_key_down_pw(PlatformWindow *pw, U16 keycode, NSEventM
@implementation ASmplView
- (BOOL)acceptsFirstResponder {
return YES;
}
- (BOOL)canBecomeKeyView {
return YES;
}
- (BOOL)acceptsFirstResponder { return YES; }
- (BOOL)canBecomeKeyView { return YES; }
// Needed for NSTextInputClient
- (BOOL)hasMarkedText {
return NO;
}
- (NSRange)markedRange {
return NSMakeRange(NSNotFound, 0);
}
- (NSRange)selectedRange {
return NSMakeRange(NSNotFound, 0);
}
- (BOOL)hasMarkedText { return NO; }
- (NSRange)markedRange { return NSMakeRange(NSNotFound, 0); }
- (NSRange)selectedRange { return NSMakeRange(NSNotFound, 0); }
- (void)setMarkedText:(id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange {
(void)string;
(void)selectedRange;
(void)replacementRange;
}
- (void)unmarkText {
}
- (NSArray<NSAttributedStringKey> *)validAttributesForMarkedText {
return @[];
(void)string; (void)selectedRange; (void)replacementRange;
}
- (void)unmarkText {}
- (NSArray<NSAttributedStringKey> *)validAttributesForMarkedText { return @[]; }
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
(void)range;
(void)actualRange;
(void)range; (void)actualRange;
return nil;
}
- (NSUInteger)characterIndexForPoint:(NSPoint)point {
(void)point;
return NSNotFound;
}
- (NSUInteger)characterIndexForPoint:(NSPoint)point { (void)point; return NSNotFound; }
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
(void)range;
(void)actualRange;
(void)range; (void)actualRange;
return NSZeroRect;
}
@@ -231,7 +192,7 @@ static void platform_macos_key_down_pw(PlatformWindow *pw, U16 keycode, NSEventM
platform_macos_key_down_pw(_platformWindow, [event keyCode], [event modifierFlags]);
// Feed into text input system for character generation
[self interpretKeyEvents:@[ event ]];
[self interpretKeyEvents:@[event]];
}
- (void)flagsChanged:(NSEvent *)event {
@@ -249,12 +210,8 @@ static void platform_macos_key_down_pw(PlatformWindow *pw, U16 keycode, NSEventM
if (_platformWindow) _platformWindow->mouse_down_state = 0;
}
- (void)mouseMoved:(NSEvent *)event {
(void)event;
}
- (void)mouseDragged:(NSEvent *)event {
(void)event;
}
- (void)mouseMoved:(NSEvent *)event { (void)event; }
- (void)mouseDragged:(NSEvent *)event { (void)event; }
- (void)scrollWheel:(NSEvent *)event {
if (!_platformWindow) return;
@@ -264,10 +221,7 @@ static void platform_macos_key_down_pw(PlatformWindow *pw, U16 keycode, NSEventM
_platformWindow->input.scroll_delta.y += dy;
}
- (BOOL)acceptsFirstMouse:(NSEvent *)event {
(void)event;
return YES;
}
- (BOOL)acceptsFirstMouse:(NSEvent *)event { (void)event; return YES; }
@end

View File

@@ -3,8 +3,8 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <malloc.h>
#include <windows.h>
#include <malloc.h>
struct PlatformWindow {
HWND hwnd;
@@ -143,7 +143,8 @@ PlatformWindow *platform_create_window(PlatformWindowDesc *desc) {
x, y,
rect.right - rect.left,
rect.bottom - rect.top,
parent_hwnd, nullptr, GetModuleHandleW(nullptr), nullptr);
parent_hwnd, nullptr, GetModuleHandleW(nullptr), nullptr
);
_freea(wtitle);

View File

@@ -30,8 +30,8 @@
#include "renderer/font_inter.gen.h"
// Embedded SPIR-V shaders (generated at build time by glslc)
#include "renderer/ui_frag.spv.h"
#include "renderer/ui_vert.spv.h"
#include "renderer/ui_frag.spv.h"
#define NUM_BACK_BUFFERS 2
#define MAX_VERTICES (64 * 1024)
@@ -172,9 +172,9 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(
VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT type,
const VkDebugUtilsMessengerCallbackDataEXT *data,
void *user_data) {
(void)type;
(void)user_data;
void *user_data)
{
(void)type; (void)user_data;
if (severity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
OutputDebugStringA("VK: ");
OutputDebugStringA(data->pMessage);
@@ -188,7 +188,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(
// Helper: begin/end one-shot command buffer
static VkCommandBuffer begin_one_shot(Renderer *r) {
VkCommandBufferAllocateInfo ai = { 0 };
VkCommandBufferAllocateInfo ai = {0};
ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
ai.commandPool = r->command_pool;
ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
@@ -196,7 +196,7 @@ static VkCommandBuffer begin_one_shot(Renderer *r) {
VkCommandBuffer cb;
vkAllocateCommandBuffers(r->device, &ai, &cb);
VkCommandBufferBeginInfo bi = { 0 };
VkCommandBufferBeginInfo bi = {0};
bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(cb, &bi);
@@ -205,7 +205,7 @@ static VkCommandBuffer begin_one_shot(Renderer *r) {
static void end_one_shot(Renderer *r, VkCommandBuffer cb) {
vkEndCommandBuffer(cb);
VkSubmitInfo si = { 0 };
VkSubmitInfo si = {0};
si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
si.commandBufferCount = 1;
si.pCommandBuffers = &cb;
@@ -220,8 +220,9 @@ static void end_one_shot(Renderer *r, VkCommandBuffer cb) {
static void transition_image(VkCommandBuffer cb, VkImage image,
VkImageLayout old_layout, VkImageLayout new_layout,
VkAccessFlags src_access, VkAccessFlags dst_access,
VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage) {
VkImageMemoryBarrier barrier = { 0 };
VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage)
{
VkImageMemoryBarrier barrier = {0};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = old_layout;
barrier.newLayout = new_layout;
@@ -242,7 +243,7 @@ static void transition_image(VkCommandBuffer cb, VkImage image,
// Vulkan infrastructure
static B32 create_instance(Renderer *r) {
VkApplicationInfo app_info = { 0 };
VkApplicationInfo app_info = {0};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = "autosample";
app_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
@@ -264,7 +265,7 @@ static B32 create_instance(Renderer *r) {
#endif
};
VkInstanceCreateInfo ci = { 0 };
VkInstanceCreateInfo ci = {0};
ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
ci.pApplicationInfo = &app_info;
ci.enabledExtensionCount = ArrayCount(extensions);
@@ -277,10 +278,13 @@ static B32 create_instance(Renderer *r) {
#ifdef _DEBUG
{
VkDebugUtilsMessengerCreateInfoEXT dbg = { 0 };
VkDebugUtilsMessengerCreateInfoEXT dbg = {0};
dbg.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
dbg.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
dbg.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
dbg.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
dbg.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
dbg.pfnUserCallback = vk_debug_callback;
PFN_vkCreateDebugUtilsMessengerEXT func =
@@ -293,7 +297,7 @@ static B32 create_instance(Renderer *r) {
}
static B32 create_surface(Renderer *r) {
VkWin32SurfaceCreateInfoKHR ci = { 0 };
VkWin32SurfaceCreateInfoKHR ci = {0};
ci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
ci.hinstance = GetModuleHandle(NULL);
ci.hwnd = r->hwnd;
@@ -342,7 +346,7 @@ static B32 find_queue_family(Renderer *r) {
static B32 create_device(Renderer *r) {
float priority = 1.0f;
VkDeviceQueueCreateInfo queue_ci = { 0 };
VkDeviceQueueCreateInfo queue_ci = {0};
queue_ci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_ci.queueFamilyIndex = r->queue_family;
queue_ci.queueCount = 1;
@@ -350,7 +354,7 @@ static B32 create_device(Renderer *r) {
const char *extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
VkDeviceCreateInfo ci = { 0 };
VkDeviceCreateInfo ci = {0};
ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
ci.queueCreateInfoCount = 1;
ci.pQueueCreateInfos = &queue_ci;
@@ -365,7 +369,7 @@ static B32 create_device(Renderer *r) {
}
static B32 create_vma(Renderer *r) {
VmaAllocatorCreateInfo ci = { 0 };
VmaAllocatorCreateInfo ci = {0};
ci.physicalDevice = r->physical_device;
ci.device = r->device;
ci.instance = r->instance;
@@ -422,7 +426,7 @@ static B32 create_swap_chain(Renderer *r) {
if (caps.maxImageCount > 0 && image_count > caps.maxImageCount)
image_count = caps.maxImageCount;
VkSwapchainCreateInfoKHR ci = { 0 };
VkSwapchainCreateInfoKHR ci = {0};
ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
ci.surface = r->surface;
ci.minImageCount = image_count;
@@ -447,7 +451,7 @@ static B32 create_swap_chain(Renderer *r) {
// Create image views
for (U32 i = 0; i < NUM_BACK_BUFFERS; i++) {
VkImageViewCreateInfo vi = { 0 };
VkImageViewCreateInfo vi = {0};
vi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
vi.image = r->swap_chain_images[i];
vi.viewType = VK_IMAGE_VIEW_TYPE_2D;
@@ -465,7 +469,7 @@ static B32 create_swap_chain(Renderer *r) {
}
static B32 create_render_pass(Renderer *r) {
VkAttachmentDescription color_attach = { 0 };
VkAttachmentDescription color_attach = {0};
color_attach.format = r->swap_chain_format;
color_attach.samples = VK_SAMPLE_COUNT_1_BIT;
color_attach.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
@@ -475,16 +479,16 @@ static B32 create_render_pass(Renderer *r) {
color_attach.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
color_attach.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference color_ref = { 0 };
VkAttachmentReference color_ref = {0};
color_ref.attachment = 0;
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = { 0 };
VkSubpassDescription subpass = {0};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_ref;
VkSubpassDependency dep = { 0 };
VkSubpassDependency dep = {0};
dep.srcSubpass = VK_SUBPASS_EXTERNAL;
dep.dstSubpass = 0;
dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
@@ -492,7 +496,7 @@ static B32 create_render_pass(Renderer *r) {
dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VkRenderPassCreateInfo ci = { 0 };
VkRenderPassCreateInfo ci = {0};
ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
ci.attachmentCount = 1;
ci.pAttachments = &color_attach;
@@ -506,7 +510,7 @@ static B32 create_render_pass(Renderer *r) {
static B32 create_framebuffers(Renderer *r) {
for (U32 i = 0; i < NUM_BACK_BUFFERS; i++) {
VkFramebufferCreateInfo ci = { 0 };
VkFramebufferCreateInfo ci = {0};
ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
ci.renderPass = r->render_pass;
ci.attachmentCount = 1;
@@ -521,14 +525,14 @@ static B32 create_framebuffers(Renderer *r) {
}
static B32 create_command_resources(Renderer *r) {
VkCommandPoolCreateInfo pool_ci = { 0 };
VkCommandPoolCreateInfo pool_ci = {0};
pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
pool_ci.queueFamilyIndex = r->queue_family;
if (vkCreateCommandPool(r->device, &pool_ci, NULL, &r->command_pool) != VK_SUCCESS)
return 0;
VkCommandBufferAllocateInfo alloc_info = { 0 };
VkCommandBufferAllocateInfo alloc_info = {0};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
alloc_info.commandPool = r->command_pool;
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
@@ -541,7 +545,7 @@ static B32 create_command_resources(Renderer *r) {
for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) {
r->frames[i].command_buffer = cbs[i];
VkFenceCreateInfo fence_ci = { 0 };
VkFenceCreateInfo fence_ci = {0};
fence_ci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_ci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
if (vkCreateFence(r->device, &fence_ci, NULL, &r->frames[i].fence) != VK_SUCCESS)
@@ -549,7 +553,7 @@ static B32 create_command_resources(Renderer *r) {
}
for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) {
VkSemaphoreCreateInfo sem_ci = { 0 };
VkSemaphoreCreateInfo sem_ci = {0};
sem_ci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
if (vkCreateSemaphore(r->device, &sem_ci, NULL, &r->image_available_sema[i]) != VK_SUCCESS)
return 0;
@@ -561,7 +565,7 @@ static B32 create_command_resources(Renderer *r) {
}
static B32 create_sampler(Renderer *r) {
VkSamplerCreateInfo ci = { 0 };
VkSamplerCreateInfo ci = {0};
ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
ci.magFilter = VK_FILTER_LINEAR;
ci.minFilter = VK_FILTER_LINEAR;
@@ -574,13 +578,13 @@ static B32 create_sampler(Renderer *r) {
static B32 create_descriptor_resources(Renderer *r) {
// Descriptor set layout: single combined image sampler at binding 0
VkDescriptorSetLayoutBinding binding = { 0 };
VkDescriptorSetLayoutBinding binding = {0};
binding.binding = 0;
binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding.descriptorCount = 1;
binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutCreateInfo layout_ci = { 0 };
VkDescriptorSetLayoutCreateInfo layout_ci = {0};
layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layout_ci.bindingCount = 1;
layout_ci.pBindings = &binding;
@@ -588,11 +592,11 @@ static B32 create_descriptor_resources(Renderer *r) {
return 0;
// Descriptor pool: 2 sets (font + icon)
VkDescriptorPoolSize pool_size = { 0 };
VkDescriptorPoolSize pool_size = {0};
pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
pool_size.descriptorCount = 2;
VkDescriptorPoolCreateInfo pool_ci = { 0 };
VkDescriptorPoolCreateInfo pool_ci = {0};
pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_ci.maxSets = 2;
pool_ci.poolSizeCount = 1;
@@ -601,7 +605,7 @@ static B32 create_descriptor_resources(Renderer *r) {
return 0;
// Allocate font descriptor set
VkDescriptorSetAllocateInfo alloc_info = { 0 };
VkDescriptorSetAllocateInfo alloc_info = {0};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = r->descriptor_pool;
alloc_info.descriptorSetCount = 1;
@@ -613,7 +617,7 @@ static B32 create_descriptor_resources(Renderer *r) {
}
static VkShaderModule create_shader_module(Renderer *r, const U32 *code, size_t size) {
VkShaderModuleCreateInfo ci = { 0 };
VkShaderModuleCreateInfo ci = {0};
ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
ci.codeSize = size;
ci.pCode = code;
@@ -627,7 +631,7 @@ static B32 create_pipeline(Renderer *r) {
VkShaderModule frag_module = create_shader_module(r, ui_frag_spv, sizeof(ui_frag_spv));
if (!vert_module || !frag_module) return 0;
VkPipelineShaderStageCreateInfo stages[2] = { { 0 }, { 0 } };
VkPipelineShaderStageCreateInfo stages[2] = {{0}, {0}};
stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
stages[0].module = vert_module;
@@ -638,84 +642,57 @@ static B32 create_pipeline(Renderer *r) {
stages[1].pName = "main";
// Vertex input
VkVertexInputBindingDescription binding = { 0 };
VkVertexInputBindingDescription binding = {0};
binding.binding = 0;
binding.stride = sizeof(UIVertex);
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
VkVertexInputAttributeDescription attrs[9] = {};
attrs[0].location = 0;
attrs[0].binding = 0;
attrs[0].format = VK_FORMAT_R32G32_SFLOAT;
attrs[0].offset = offsetof(UIVertex, pos);
attrs[1].location = 1;
attrs[1].binding = 0;
attrs[1].format = VK_FORMAT_R32G32_SFLOAT;
attrs[1].offset = offsetof(UIVertex, uv);
attrs[2].location = 2;
attrs[2].binding = 0;
attrs[2].format = VK_FORMAT_R32G32B32A32_SFLOAT;
attrs[2].offset = offsetof(UIVertex, col);
attrs[3].location = 3;
attrs[3].binding = 0;
attrs[3].format = VK_FORMAT_R32G32_SFLOAT;
attrs[3].offset = offsetof(UIVertex, rect_min);
attrs[4].location = 4;
attrs[4].binding = 0;
attrs[4].format = VK_FORMAT_R32G32_SFLOAT;
attrs[4].offset = offsetof(UIVertex, rect_max);
attrs[5].location = 5;
attrs[5].binding = 0;
attrs[5].format = VK_FORMAT_R32G32B32A32_SFLOAT;
attrs[5].offset = offsetof(UIVertex, corner_radii);
attrs[6].location = 6;
attrs[6].binding = 0;
attrs[6].format = VK_FORMAT_R32_SFLOAT;
attrs[6].offset = offsetof(UIVertex, border_thickness);
attrs[7].location = 7;
attrs[7].binding = 0;
attrs[7].format = VK_FORMAT_R32_SFLOAT;
attrs[7].offset = offsetof(UIVertex, softness);
attrs[8].location = 8;
attrs[8].binding = 0;
attrs[8].format = VK_FORMAT_R32_SFLOAT;
attrs[8].offset = offsetof(UIVertex, mode);
attrs[0].location = 0; attrs[0].binding = 0; attrs[0].format = VK_FORMAT_R32G32_SFLOAT; attrs[0].offset = offsetof(UIVertex, pos);
attrs[1].location = 1; attrs[1].binding = 0; attrs[1].format = VK_FORMAT_R32G32_SFLOAT; attrs[1].offset = offsetof(UIVertex, uv);
attrs[2].location = 2; attrs[2].binding = 0; attrs[2].format = VK_FORMAT_R32G32B32A32_SFLOAT; attrs[2].offset = offsetof(UIVertex, col);
attrs[3].location = 3; attrs[3].binding = 0; attrs[3].format = VK_FORMAT_R32G32_SFLOAT; attrs[3].offset = offsetof(UIVertex, rect_min);
attrs[4].location = 4; attrs[4].binding = 0; attrs[4].format = VK_FORMAT_R32G32_SFLOAT; attrs[4].offset = offsetof(UIVertex, rect_max);
attrs[5].location = 5; attrs[5].binding = 0; attrs[5].format = VK_FORMAT_R32G32B32A32_SFLOAT; attrs[5].offset = offsetof(UIVertex, corner_radii);
attrs[6].location = 6; attrs[6].binding = 0; attrs[6].format = VK_FORMAT_R32_SFLOAT; attrs[6].offset = offsetof(UIVertex, border_thickness);
attrs[7].location = 7; attrs[7].binding = 0; attrs[7].format = VK_FORMAT_R32_SFLOAT; attrs[7].offset = offsetof(UIVertex, softness);
attrs[8].location = 8; attrs[8].binding = 0; attrs[8].format = VK_FORMAT_R32_SFLOAT; attrs[8].offset = offsetof(UIVertex, mode);
VkPipelineVertexInputStateCreateInfo vertex_input = { 0 };
VkPipelineVertexInputStateCreateInfo vertex_input = {0};
vertex_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertex_input.vertexBindingDescriptionCount = 1;
vertex_input.pVertexBindingDescriptions = &binding;
vertex_input.vertexAttributeDescriptionCount = 9;
vertex_input.pVertexAttributeDescriptions = attrs;
VkPipelineInputAssemblyStateCreateInfo input_assembly = { 0 };
VkPipelineInputAssemblyStateCreateInfo input_assembly = {0};
input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
// Dynamic viewport/scissor
VkDynamicState dynamic_states[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamic_state = { 0 };
VkPipelineDynamicStateCreateInfo dynamic_state = {0};
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamic_state.dynamicStateCount = 2;
dynamic_state.pDynamicStates = dynamic_states;
VkPipelineViewportStateCreateInfo viewport_state = { 0 };
VkPipelineViewportStateCreateInfo viewport_state = {0};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 1;
viewport_state.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer = { 0 };
VkPipelineRasterizationStateCreateInfo rasterizer = {0};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_NONE;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
VkPipelineMultisampleStateCreateInfo multisample = { 0 };
VkPipelineMultisampleStateCreateInfo multisample = {0};
multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState blend_attach = { 0 };
VkPipelineColorBlendAttachmentState blend_attach = {0};
blend_attach.blendEnable = VK_TRUE;
blend_attach.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blend_attach.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
@@ -723,23 +700,24 @@ static B32 create_pipeline(Renderer *r) {
blend_attach.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blend_attach.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_attach.alphaBlendOp = VK_BLEND_OP_ADD;
blend_attach.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
blend_attach.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendStateCreateInfo blend = { 0 };
VkPipelineColorBlendStateCreateInfo blend = {0};
blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
blend.attachmentCount = 1;
blend.pAttachments = &blend_attach;
VkPipelineDepthStencilStateCreateInfo depth_stencil = { 0 };
VkPipelineDepthStencilStateCreateInfo depth_stencil = {0};
depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
// Pipeline layout: push constants + 1 descriptor set
VkPushConstantRange push_range = { 0 };
VkPushConstantRange push_range = {0};
push_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_range.offset = 0;
push_range.size = 4 * sizeof(float); // viewport_size + padding
VkPipelineLayoutCreateInfo layout_ci = { 0 };
VkPipelineLayoutCreateInfo layout_ci = {0};
layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_ci.setLayoutCount = 1;
layout_ci.pSetLayouts = &r->descriptor_set_layout;
@@ -751,7 +729,7 @@ static B32 create_pipeline(Renderer *r) {
return 0;
}
VkGraphicsPipelineCreateInfo pipeline_ci = { 0 };
VkGraphicsPipelineCreateInfo pipeline_ci = {0};
pipeline_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_ci.stageCount = 2;
pipeline_ci.pStages = stages;
@@ -777,12 +755,12 @@ static B32 create_pipeline(Renderer *r) {
static B32 create_ui_buffers(Renderer *r) {
for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) {
VkBufferCreateInfo buf_ci = { 0 };
VkBufferCreateInfo buf_ci = {0};
buf_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buf_ci.size = MAX_VERTICES * sizeof(UIVertex);
buf_ci.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
VmaAllocationCreateInfo alloc_ci = { 0 };
VmaAllocationCreateInfo alloc_ci = {0};
alloc_ci.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
@@ -806,12 +784,12 @@ static B32 create_ui_buffers(Renderer *r) {
// Helper: update a descriptor set to point to an image view
static void update_descriptor_set(Renderer *r, VkDescriptorSet set, VkImageView view) {
VkDescriptorImageInfo img_info = { 0 };
VkDescriptorImageInfo img_info = {0};
img_info.sampler = r->sampler;
img_info.imageView = view;
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkWriteDescriptorSet write = { 0 };
VkWriteDescriptorSet write = {0};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.dstSet = set;
write.dstBinding = 0;
@@ -884,7 +862,7 @@ static B32 create_font_atlas(Renderer *r, F32 font_size) {
}
// Create Vulkan image
VkImageCreateInfo img_ci = { 0 };
VkImageCreateInfo img_ci = {0};
img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
img_ci.imageType = VK_IMAGE_TYPE_2D;
img_ci.format = VK_FORMAT_R8_UNORM;
@@ -897,7 +875,7 @@ static B32 create_font_atlas(Renderer *r, F32 font_size) {
img_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
img_ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
VmaAllocationCreateInfo alloc_ci = { 0 };
VmaAllocationCreateInfo alloc_ci = {0};
alloc_ci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
if (vmaCreateImage(r->allocator, &img_ci, &alloc_ci, &r->font_image, &r->font_alloc, NULL) != VK_SUCCESS) {
@@ -906,12 +884,12 @@ static B32 create_font_atlas(Renderer *r, F32 font_size) {
}
// Staging buffer
VkBufferCreateInfo staging_ci = { 0 };
VkBufferCreateInfo staging_ci = {0};
staging_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
staging_ci.size = FONT_ATLAS_W * FONT_ATLAS_H;
staging_ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VmaAllocationCreateInfo staging_alloc_ci = { 0 };
VmaAllocationCreateInfo staging_alloc_ci = {0};
staging_alloc_ci.usage = VMA_MEMORY_USAGE_CPU_ONLY;
staging_alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
@@ -930,7 +908,7 @@ static B32 create_font_atlas(Renderer *r, F32 font_size) {
0, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VkBufferImageCopy region = { 0 };
VkBufferImageCopy region = {0};
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = 1;
region.imageExtent.width = FONT_ATLAS_W;
@@ -948,7 +926,7 @@ static B32 create_font_atlas(Renderer *r, F32 font_size) {
vmaDestroyBuffer(r->allocator, staging_buf, staging_alloc);
// Image view
VkImageViewCreateInfo view_ci = { 0 };
VkImageViewCreateInfo view_ci = {0};
view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view_ci.image = r->font_image;
view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
@@ -999,7 +977,8 @@ static void emit_quad(DrawBatch *batch,
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) {
F32 border_thickness, F32 softness, F32 mode)
{
if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES)
return;
@@ -1009,54 +988,28 @@ static void emit_quad(DrawBatch *batch,
F32 px0 = x0, py0 = y0, px1 = x1, py1 = y1;
if (mode < 0.5f) {
F32 pad = softness + 1.0f;
px0 -= pad;
py0 -= pad;
px1 += pad;
py1 += pad;
px0 -= pad; py0 -= pad; px1 += pad; py1 += pad;
}
v[0].pos[0] = px0;
v[0].pos[1] = py0;
v[0].uv[0] = u0;
v[0].uv[1] = v0;
v[1].pos[0] = px1;
v[1].pos[1] = py0;
v[1].uv[0] = u1;
v[1].uv[1] = v0;
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;
v[0].pos[0] = px0; v[0].pos[1] = py0; v[0].uv[0] = u0; v[0].uv[1] = v0;
v[1].pos[0] = px1; v[1].pos[1] = py0; v[1].uv[0] = u1; v[1].uv[1] = v0;
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 (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;
v[i].corner_radii[0] = cr_tl;
v[i].corner_radii[1] = cr_tr;
v[i].corner_radii[2] = cr_br;
v[i].corner_radii[3] = cr_bl;
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;
v[i].corner_radii[0] = cr_tl; v[i].corner_radii[1] = cr_tr;
v[i].corner_radii[2] = cr_br; v[i].corner_radii[3] = cr_bl;
v[i].border_thickness = border_thickness;
v[i].softness = softness;
v[i].mode = mode;
}
U32 *idx = &batch->indices[batch->index_count];
idx[0] = base;
idx[1] = base + 1;
idx[2] = base + 2;
idx[3] = base;
idx[4] = base + 2;
idx[5] = base + 3;
idx[0] = base; idx[1] = base + 1; idx[2] = base + 2;
idx[3] = base; idx[4] = base + 2; idx[5] = base + 3;
batch->vertex_count += 4;
batch->index_count += 6;
@@ -1066,7 +1019,8 @@ static void emit_quad_rotated(DrawBatch *batch,
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) {
F32 angle_rad)
{
if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES)
return;
@@ -1083,49 +1037,34 @@ static void emit_quad_rotated(DrawBatch *batch,
v[0].pos[0] = cx + dx0 * cosA - dy0 * sinA;
v[0].pos[1] = cy + dx0 * sinA + dy0 * cosA;
v[0].uv[0] = u0;
v[0].uv[1] = v0;
v[0].uv[0] = u0; v[0].uv[1] = v0;
v[1].pos[0] = cx + dx1 * cosA - dy0 * sinA;
v[1].pos[1] = cy + dx1 * sinA + dy0 * cosA;
v[1].uv[0] = u1;
v[1].uv[1] = v0;
v[1].uv[0] = u1; v[1].uv[1] = v0;
v[2].pos[0] = cx + dx1 * cosA - dy1 * sinA;
v[2].pos[1] = cy + dx1 * sinA + dy1 * cosA;
v[2].uv[0] = u1;
v[2].uv[1] = v1;
v[2].uv[0] = u1; v[2].uv[1] = v1;
v[3].pos[0] = cx + dx0 * cosA - dy1 * sinA;
v[3].pos[1] = cy + dx0 * sinA + dy1 * cosA;
v[3].uv[0] = u0;
v[3].uv[1] = v1;
v[3].uv[0] = u0; v[3].uv[1] = v1;
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;
v[i].corner_radii[0] = 0;
v[i].corner_radii[1] = 0;
v[i].corner_radii[2] = 0;
v[i].corner_radii[3] = 0;
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;
v[i].corner_radii[0] = 0; v[i].corner_radii[1] = 0;
v[i].corner_radii[2] = 0; v[i].corner_radii[3] = 0;
v[i].border_thickness = 0;
v[i].softness = 0;
v[i].mode = 2.0f;
}
U32 *idx = &batch->indices[batch->index_count];
idx[0] = base;
idx[1] = base + 1;
idx[2] = base + 2;
idx[3] = base;
idx[4] = base + 2;
idx[5] = base + 3;
idx[0] = base; idx[1] = base + 1; idx[2] = base + 2;
idx[3] = base; idx[4] = base + 2; idx[5] = base + 3;
batch->vertex_count += 4;
batch->index_count += 6;
@@ -1135,7 +1074,8 @@ static void emit_rect(DrawBatch *batch,
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) {
F32 border_thickness, F32 softness)
{
emit_quad(batch, x0, y0, x1, y1,
0, 0, 0, 0,
cr, cg, cb, ca,
@@ -1149,7 +1089,8 @@ static void emit_rect_vgradient(DrawBatch *batch,
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) {
F32 softness)
{
if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES)
return;
@@ -1159,61 +1100,29 @@ static void emit_rect_vgradient(DrawBatch *batch,
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;
v[2].pos[0] = px1;
v[2].pos[1] = py1;
v[2].uv[0] = 0;
v[2].uv[1] = 0;
v[3].pos[0] = px0;
v[3].pos[1] = py1;
v[3].uv[0] = 0;
v[3].uv[1] = 0;
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;
v[2].pos[0] = px1; v[2].pos[1] = py1; v[2].uv[0] = 0; v[2].uv[1] = 0;
v[3].pos[0] = px0; v[3].pos[1] = py1; v[3].uv[0] = 0; v[3].uv[1] = 0;
v[0].col[0] = tr;
v[0].col[1] = tg;
v[0].col[2] = tb;
v[0].col[3] = ta;
v[1].col[0] = tr;
v[1].col[1] = tg;
v[1].col[2] = tb;
v[1].col[3] = ta;
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;
v[0].col[0] = tr; v[0].col[1] = tg; v[0].col[2] = tb; v[0].col[3] = ta;
v[1].col[0] = tr; v[1].col[1] = tg; v[1].col[2] = tb; v[1].col[3] = ta;
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 (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;
v[i].corner_radii[2] = cr_br;
v[i].corner_radii[3] = cr_bl;
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;
v[i].corner_radii[2] = cr_br; v[i].corner_radii[3] = cr_bl;
v[i].border_thickness = 0;
v[i].softness = softness;
v[i].mode = 0;
}
U32 *idx = &batch->indices[batch->index_count];
idx[0] = base;
idx[1] = base + 1;
idx[2] = base + 2;
idx[3] = base;
idx[4] = base + 2;
idx[5] = base + 3;
idx[0] = base; idx[1] = base + 1; idx[2] = base + 2;
idx[3] = base; idx[4] = base + 2; idx[5] = base + 3;
batch->vertex_count += 4;
batch->index_count += 6;
@@ -1221,7 +1130,8 @@ 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, S32 text_len,
U16 font_size) {
U16 font_size)
{
if (text_len == 0 || color.a < 0.1f) return;
F32 cr = color.r / 255.f;
@@ -1269,7 +1179,8 @@ static void emit_text_glyphs(DrawBatch *batch, Renderer *r,
// Flush helper
static void flush_batch(Renderer *r, DrawBatch *batch, U32 buf_idx,
U32 *flush_index_start, VkDescriptorSet tex_set) {
U32 *flush_index_start, VkDescriptorSet tex_set)
{
U32 draw_index_count = batch->index_count - *flush_index_start;
if (draw_index_count == 0) return;
@@ -1495,18 +1406,18 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
VkCommandBuffer cb = fc->command_buffer;
vkResetCommandBuffer(cb, 0);
VkCommandBufferBeginInfo begin_info = { 0 };
VkCommandBufferBeginInfo begin_info = {0};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(cb, &begin_info);
VkClearValue clear_value = { 0 };
VkClearValue clear_value = {0};
clear_value.color.float32[0] = r->clear_r;
clear_value.color.float32[1] = r->clear_g;
clear_value.color.float32[2] = r->clear_b;
clear_value.color.float32[3] = 1.0f;
VkRenderPassBeginInfo rp_begin = { 0 };
VkRenderPassBeginInfo rp_begin = {0};
rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rp_begin.renderPass = r->render_pass;
rp_begin.framebuffer = r->framebuffers[image_index];
@@ -1517,20 +1428,20 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
vkCmdBeginRenderPass(cb, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport = { 0 };
VkViewport viewport = {0};
viewport.width = (float)r->width;
viewport.height = (float)r->height;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(cb, 0, 1, &viewport);
VkRect2D scissor = { 0 };
VkRect2D scissor = {0};
scissor.extent.width = (U32)r->width;
scissor.extent.height = (U32)r->height;
vkCmdSetScissor(cb, 0, 1, &scissor);
// Process Clay render commands
if (render_commands.length > 0) {
DrawBatch batch = { 0 };
DrawBatch batch = {0};
batch.vertices = (UIVertex *)r->vb_mapped[frame_idx];
batch.indices = (U32 *)r->ib_mapped[frame_idx];
@@ -1610,7 +1521,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START: {
VkDescriptorSet heap = bound_texture == 1 ? r->icon_descriptor_set : r->font_descriptor_set;
flush_batch(r, &batch, frame_idx, &flush_index_start, heap);
VkRect2D clip = { 0 };
VkRect2D clip = {0};
clip.offset.x = (S32)Max(bb.x, 0.f);
clip.offset.y = (S32)Max(bb.y, 0.f);
clip.extent.width = (U32)Min(bb.width, (F32)r->width - clip.offset.x);
@@ -1623,7 +1534,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END: {
VkDescriptorSet heap = bound_texture == 1 ? r->icon_descriptor_set : r->font_descriptor_set;
flush_batch(r, &batch, frame_idx, &flush_index_start, heap);
VkRect2D full_scissor = { 0 };
VkRect2D full_scissor = {0};
full_scissor.extent.width = (U32)r->width;
full_scissor.extent.height = (U32)r->height;
vkCmdSetScissor(cb, 0, 1, &full_scissor);
@@ -1701,7 +1612,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
// Submit
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo submit = { 0 };
VkSubmitInfo submit = {0};
submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit.waitSemaphoreCount = 1;
submit.pWaitSemaphores = &r->image_available_sema[frame_idx];
@@ -1713,7 +1624,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
vkQueueSubmit(r->graphics_queue, 1, &submit, fc->fence);
// Present
VkPresentInfoKHR present = { 0 };
VkPresentInfoKHR present = {0};
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present.waitSemaphoreCount = 1;
present.pWaitSemaphores = &r->render_finished_sema[frame_idx];
@@ -1731,7 +1642,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
void renderer_create_icon_atlas(Renderer *r, const U8 *data, S32 w, S32 h) {
// Create image
VkImageCreateInfo img_ci = { 0 };
VkImageCreateInfo img_ci = {0};
img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
img_ci.imageType = VK_IMAGE_TYPE_2D;
img_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
@@ -1744,18 +1655,18 @@ void renderer_create_icon_atlas(Renderer *r, const U8 *data, S32 w, S32 h) {
img_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
img_ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
VmaAllocationCreateInfo alloc_ci = { 0 };
VmaAllocationCreateInfo alloc_ci = {0};
alloc_ci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
vmaCreateImage(r->allocator, &img_ci, &alloc_ci, &r->icon_image, &r->icon_alloc, NULL);
// Staging buffer
VkBufferCreateInfo staging_ci = { 0 };
VkBufferCreateInfo staging_ci = {0};
staging_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
staging_ci.size = (VkDeviceSize)w * h * 4;
staging_ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VmaAllocationCreateInfo staging_alloc_ci = { 0 };
VmaAllocationCreateInfo staging_alloc_ci = {0};
staging_alloc_ci.usage = VMA_MEMORY_USAGE_CPU_ONLY;
staging_alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
@@ -1772,7 +1683,7 @@ void renderer_create_icon_atlas(Renderer *r, const U8 *data, S32 w, S32 h) {
0, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VkBufferImageCopy region = { 0 };
VkBufferImageCopy region = {0};
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = 1;
region.imageExtent.width = (U32)w;
@@ -1789,7 +1700,7 @@ void renderer_create_icon_atlas(Renderer *r, const U8 *data, S32 w, S32 h) {
vmaDestroyBuffer(r->allocator, staging_buf, staging_alloc);
// Image view
VkImageViewCreateInfo view_ci = { 0 };
VkImageViewCreateInfo view_ci = {0};
view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view_ci.image = r->icon_image;
view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
@@ -1800,7 +1711,7 @@ void renderer_create_icon_atlas(Renderer *r, const U8 *data, S32 w, S32 h) {
vkCreateImageView(r->device, &view_ci, NULL, &r->icon_view);
// Allocate icon descriptor set
VkDescriptorSetAllocateInfo ds_alloc = { 0 };
VkDescriptorSetAllocateInfo ds_alloc = {0};
ds_alloc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
ds_alloc.descriptorPool = r->descriptor_pool;
ds_alloc.descriptorSetCount = 1;
@@ -1817,14 +1728,8 @@ void renderer_resize(Renderer *r, S32 width, S32 height) {
// Clean up old swap chain resources
for (U32 i = 0; i < NUM_BACK_BUFFERS; i++) {
if (r->framebuffers[i]) {
vkDestroyFramebuffer(r->device, r->framebuffers[i], NULL);
r->framebuffers[i] = VK_NULL_HANDLE;
}
if (r->swap_chain_views[i]) {
vkDestroyImageView(r->device, r->swap_chain_views[i], NULL);
r->swap_chain_views[i] = VK_NULL_HANDLE;
}
if (r->framebuffers[i]) { vkDestroyFramebuffer(r->device, r->framebuffers[i], NULL); r->framebuffers[i] = VK_NULL_HANDLE; }
if (r->swap_chain_views[i]) { vkDestroyImageView(r->device, r->swap_chain_views[i], NULL); r->swap_chain_views[i] = VK_NULL_HANDLE; }
}
VkSwapchainKHR old_swap = r->swap_chain;
@@ -1850,14 +1755,8 @@ void renderer_set_font_scale(Renderer *r, F32 scale) {
F32 target_size = 22.0f * scale;
if (fabsf(target_size - r->font_atlas_size) < 0.1f) return;
vkDeviceWaitIdle(r->device);
if (r->font_view) {
vkDestroyImageView(r->device, r->font_view, NULL);
r->font_view = VK_NULL_HANDLE;
}
if (r->font_image) {
vmaDestroyImage(r->allocator, r->font_image, r->font_alloc);
r->font_image = VK_NULL_HANDLE;
}
if (r->font_view) { vkDestroyImageView(r->device, r->font_view, NULL); r->font_view = VK_NULL_HANDLE; }
if (r->font_image) { vmaDestroyImage(r->allocator, r->font_image, r->font_alloc); r->font_image = VK_NULL_HANDLE; }
create_font_atlas(r, target_size);
}

View File

@@ -27,54 +27,54 @@ void ui_set_theme(S32 theme_id) {
switch (theme_id) {
default:
case 0: // Dark
g_theme.bg_dark = Clay_Color{ 26, 26, 26, 255 };
g_theme.bg_medium = Clay_Color{ 36, 36, 36, 255 };
g_theme.bg_light = Clay_Color{ 46, 46, 46, 255 };
g_theme.bg_lighter = Clay_Color{ 54, 54, 54, 255 };
g_theme.border = Clay_Color{ 52, 52, 52, 255 };
g_theme.text = Clay_Color{ 220, 220, 220, 255 };
g_theme.text_dim = Clay_Color{ 105, 105, 105, 255 };
g_theme.accent = Clay_Color{ 87, 138, 176, 255 };
g_theme.accent_hover = Clay_Color{ 102, 153, 191, 255 };
g_theme.button_text = Clay_Color{ 224, 224, 224, 255 };
g_theme.disabled_bg = Clay_Color{ 44, 44, 44, 255 };
g_theme.disabled_text = Clay_Color{ 90, 90, 90, 255 };
g_theme.header_bg = Clay_Color{ 46, 46, 46, 255 };
g_theme.title_bar = Clay_Color{ 22, 22, 22, 255 };
g_theme.scrollbar_bg = Clay_Color{ 22, 22, 22, 255 };
g_theme.scrollbar_grab = Clay_Color{ 58, 58, 58, 255 };
g_theme.shadow = Clay_Color{ 0, 0, 0, 30 };
g_theme.tab_active_top = Clay_Color{ 70, 120, 160, 255 };
g_theme.tab_active_bottom = Clay_Color{ 30, 55, 80, 255 };
g_theme.tab_inactive = Clay_Color{ 40, 40, 40, 255 };
g_theme.tab_inactive_hover = Clay_Color{ 50, 50, 50, 255 };
g_theme.tab_text = Clay_Color{ 240, 240, 240, 255 };
g_theme.bg_dark = Clay_Color{ 26, 26, 26, 255};
g_theme.bg_medium = Clay_Color{ 36, 36, 36, 255};
g_theme.bg_light = Clay_Color{ 46, 46, 46, 255};
g_theme.bg_lighter = Clay_Color{ 54, 54, 54, 255};
g_theme.border = Clay_Color{ 52, 52, 52, 255};
g_theme.text = Clay_Color{220, 220, 220, 255};
g_theme.text_dim = Clay_Color{105, 105, 105, 255};
g_theme.accent = Clay_Color{ 87, 138, 176, 255};
g_theme.accent_hover = Clay_Color{102, 153, 191, 255};
g_theme.button_text = Clay_Color{224, 224, 224, 255};
g_theme.disabled_bg = Clay_Color{ 44, 44, 44, 255};
g_theme.disabled_text = Clay_Color{ 90, 90, 90, 255};
g_theme.header_bg = Clay_Color{ 46, 46, 46, 255};
g_theme.title_bar = Clay_Color{ 22, 22, 22, 255};
g_theme.scrollbar_bg = Clay_Color{ 22, 22, 22, 255};
g_theme.scrollbar_grab = Clay_Color{ 58, 58, 58, 255};
g_theme.shadow = Clay_Color{ 0, 0, 0, 30};
g_theme.tab_active_top = Clay_Color{ 70, 120, 160, 255};
g_theme.tab_active_bottom= Clay_Color{ 30, 55, 80, 255};
g_theme.tab_inactive = Clay_Color{ 40, 40, 40, 255};
g_theme.tab_inactive_hover= Clay_Color{ 50, 50, 50, 255};
g_theme.tab_text = Clay_Color{240, 240, 240, 255};
g_theme.corner_radius = 4.0f;
break;
case 1: // Light
g_theme.bg_dark = Clay_Color{ 195, 193, 190, 255 };
g_theme.bg_medium = Clay_Color{ 212, 210, 207, 255 };
g_theme.bg_light = Clay_Color{ 225, 223, 220, 255 };
g_theme.bg_lighter = Clay_Color{ 232, 230, 227, 255 };
g_theme.border = Clay_Color{ 178, 176, 173, 255 };
g_theme.text = Clay_Color{ 35, 33, 30, 255 };
g_theme.text_dim = Clay_Color{ 115, 113, 108, 255 };
g_theme.accent = Clay_Color{ 50, 110, 170, 255 };
g_theme.accent_hover = Clay_Color{ 65, 125, 185, 255 };
g_theme.button_text = Clay_Color{ 255, 255, 255, 255 };
g_theme.disabled_bg = Clay_Color{ 185, 183, 180, 255 };
g_theme.disabled_text = Clay_Color{ 145, 143, 140, 255 };
g_theme.header_bg = Clay_Color{ 202, 200, 197, 255 };
g_theme.title_bar = Clay_Color{ 202, 200, 197, 255 };
g_theme.scrollbar_bg = Clay_Color{ 202, 200, 197, 255 };
g_theme.scrollbar_grab = Clay_Color{ 168, 166, 163, 255 };
g_theme.shadow = Clay_Color{ 0, 0, 0, 18 };
g_theme.tab_active_top = Clay_Color{ 70, 130, 180, 255 };
g_theme.tab_active_bottom = Clay_Color{ 50, 100, 150, 255 };
g_theme.tab_inactive = Clay_Color{ 205, 203, 200, 255 };
g_theme.tab_inactive_hover = Clay_Color{ 195, 193, 190, 255 };
g_theme.tab_text = Clay_Color{ 255, 255, 255, 255 };
g_theme.bg_dark = Clay_Color{195, 193, 190, 255};
g_theme.bg_medium = Clay_Color{212, 210, 207, 255};
g_theme.bg_light = Clay_Color{225, 223, 220, 255};
g_theme.bg_lighter = Clay_Color{232, 230, 227, 255};
g_theme.border = Clay_Color{178, 176, 173, 255};
g_theme.text = Clay_Color{ 35, 33, 30, 255};
g_theme.text_dim = Clay_Color{115, 113, 108, 255};
g_theme.accent = Clay_Color{ 50, 110, 170, 255};
g_theme.accent_hover = Clay_Color{ 65, 125, 185, 255};
g_theme.button_text = Clay_Color{255, 255, 255, 255};
g_theme.disabled_bg = Clay_Color{185, 183, 180, 255};
g_theme.disabled_text = Clay_Color{145, 143, 140, 255};
g_theme.header_bg = Clay_Color{202, 200, 197, 255};
g_theme.title_bar = Clay_Color{202, 200, 197, 255};
g_theme.scrollbar_bg = Clay_Color{202, 200, 197, 255};
g_theme.scrollbar_grab = Clay_Color{168, 166, 163, 255};
g_theme.shadow = Clay_Color{ 0, 0, 0, 18};
g_theme.tab_active_top = Clay_Color{ 70, 130, 180, 255};
g_theme.tab_active_bottom= Clay_Color{ 50, 100, 150, 255};
g_theme.tab_inactive = Clay_Color{205, 203, 200, 255};
g_theme.tab_inactive_hover= Clay_Color{195, 193, 190, 255};
g_theme.tab_text = Clay_Color{255, 255, 255, 255};
g_theme.corner_radius = 4.0f;
break;
}
@@ -97,37 +97,37 @@ void ui_set_accent(S32 accent_id) {
// Dark-mode palettes
static const AccentColors dark_palettes[] = {
// 0: Blue
{ { 87, 138, 176, 255 }, { 102, 153, 191, 255 }, { 70, 120, 160, 255 }, { 30, 55, 80, 255 }, { 224, 224, 224, 255 }, { 240, 240, 240, 255 } },
{ {87,138,176,255}, {102,153,191,255}, {70,120,160,255}, {30,55,80,255}, {224,224,224,255}, {240,240,240,255} },
// 1: Turquoise
{ { 60, 160, 155, 255 }, { 75, 175, 170, 255 }, { 50, 140, 135, 255 }, { 25, 70, 68, 255 }, { 224, 224, 224, 255 }, { 240, 240, 240, 255 } },
{ {60,160,155,255}, {75,175,170,255}, {50,140,135,255}, {25,70,68,255}, {224,224,224,255}, {240,240,240,255} },
// 2: Orange
{ { 200, 130, 50, 255 }, { 215, 145, 65, 255 }, { 190, 120, 40, 255 }, { 100, 60, 20, 255 }, { 240, 240, 240, 255 }, { 240, 240, 240, 255 } },
{ {200,130,50,255}, {215,145,65,255}, {190,120,40,255}, {100,60,20,255}, {240,240,240,255}, {240,240,240,255} },
// 3: Purple
{ { 130, 100, 180, 255 }, { 145, 115, 195, 255 }, { 120, 90, 170, 255 }, { 60, 45, 85, 255 }, { 224, 224, 224, 255 }, { 240, 240, 240, 255 } },
{ {130,100,180,255}, {145,115,195,255}, {120,90,170,255}, {60,45,85,255}, {224,224,224,255}, {240,240,240,255} },
// 4: Pink
{ { 185, 95, 140, 255 }, { 200, 110, 155, 255 }, { 175, 85, 130, 255 }, { 88, 42, 65, 255 }, { 240, 240, 240, 255 }, { 240, 240, 240, 255 } },
{ {185,95,140,255}, {200,110,155,255}, {175,85,130,255}, {88,42,65,255}, {240,240,240,255}, {240,240,240,255} },
// 5: Red
{ { 190, 75, 75, 255 }, { 205, 90, 90, 255 }, { 180, 65, 65, 255 }, { 90, 32, 32, 255 }, { 240, 240, 240, 255 }, { 240, 240, 240, 255 } },
{ {190,75,75,255}, {205,90,90,255}, {180,65,65,255}, {90,32,32,255}, {240,240,240,255}, {240,240,240,255} },
// 6: Green
{ { 80, 155, 80, 255 }, { 95, 170, 95, 255 }, { 70, 140, 70, 255 }, { 35, 70, 35, 255 }, { 240, 240, 240, 255 }, { 240, 240, 240, 255 } },
{ {80,155,80,255}, {95,170,95,255}, {70,140,70,255}, {35,70,35,255}, {240,240,240,255}, {240,240,240,255} },
};
// Light-mode palettes (slightly more saturated for contrast on light bg)
static const AccentColors light_palettes[] = {
// 0: Blue
{ { 50, 110, 170, 255 }, { 65, 125, 185, 255 }, { 70, 130, 180, 255 }, { 50, 100, 150, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
{ {50,110,170,255}, {65,125,185,255}, {70,130,180,255}, {50,100,150,255}, {255,255,255,255}, {255,255,255,255} },
// 1: Turquoise
{ { 30, 140, 135, 255 }, { 45, 155, 150, 255 }, { 40, 150, 145, 255 }, { 25, 115, 110, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
{ {30,140,135,255}, {45,155,150,255}, {40,150,145,255}, {25,115,110,255}, {255,255,255,255}, {255,255,255,255} },
// 2: Orange
{ { 190, 115, 25, 255 }, { 205, 130, 40, 255 }, { 195, 120, 30, 255 }, { 155, 90, 15, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
{ {190,115,25,255}, {205,130,40,255}, {195,120,30,255}, {155,90,15,255}, {255,255,255,255}, {255,255,255,255} },
// 3: Purple
{ { 110, 75, 170, 255 }, { 125, 90, 185, 255 }, { 115, 80, 175, 255 }, { 85, 55, 140, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
{ {110,75,170,255}, {125,90,185,255}, {115,80,175,255}, {85,55,140,255}, {255,255,255,255}, {255,255,255,255} },
// 4: Pink
{ { 175, 70, 125, 255 }, { 190, 85, 140, 255 }, { 180, 75, 130, 255 }, { 140, 50, 100, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
{ {175,70,125,255}, {190,85,140,255}, {180,75,130,255}, {140,50,100,255}, {255,255,255,255}, {255,255,255,255} },
// 5: Red
{ { 185, 55, 55, 255 }, { 200, 70, 70, 255 }, { 190, 60, 60, 255 }, { 150, 40, 40, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
{ {185,55,55,255}, {200,70,70,255}, {190,60,60,255}, {150,40,40,255}, {255,255,255,255}, {255,255,255,255} },
// 6: Green
{ { 55, 140, 55, 255 }, { 70, 155, 70, 255 }, { 60, 145, 60, 255 }, { 40, 110, 40, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
{ {55,140,55,255}, {70,155,70,255}, {60,145,60,255}, {40,110,40,255}, {255,255,255,255}, {255,255,255,255} },
};
S32 idx = accent_id;
@@ -163,10 +163,10 @@ 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, (F32)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 };
return Clay_Dimensions{result.x, result.y};
}
////////////////////////////////
@@ -184,7 +184,7 @@ UI_Context *ui_create(F32 viewport_w, F32 viewport_h) {
err_handler.userData = ctx;
ctx->clay_ctx = Clay_Initialize(clay_arena,
Clay_Dimensions{ viewport_w, viewport_h },
Clay_Dimensions{viewport_w, viewport_h},
err_handler);
Clay_SetMeasureTextFunction(clay_measure_text, ctx);
@@ -200,12 +200,13 @@ void ui_destroy(UI_Context *ctx) {
void ui_begin_frame(UI_Context *ctx, F32 viewport_w, F32 viewport_h,
Vec2F32 mouse_pos, B32 mouse_down,
Vec2F32 scroll_delta, F32 dt) {
Vec2F32 scroll_delta, F32 dt)
{
g_measure_ctx = ctx;
Clay_SetCurrentContext(ctx->clay_ctx);
Clay_SetLayoutDimensions(Clay_Dimensions{ viewport_w, viewport_h });
Clay_SetPointerState(Clay_Vector2{ mouse_pos.x, mouse_pos.y }, mouse_down != 0);
Clay_UpdateScrollContainers(false, Clay_Vector2{ scroll_delta.x, scroll_delta.y }, dt);
Clay_SetLayoutDimensions(Clay_Dimensions{viewport_w, viewport_h});
Clay_SetPointerState(Clay_Vector2{mouse_pos.x, mouse_pos.y}, mouse_down != 0);
Clay_UpdateScrollContainers(false, Clay_Vector2{scroll_delta.x, scroll_delta.y}, dt);
Clay_BeginLayout();
}

View File

@@ -23,7 +23,7 @@ Clay_Color piano_velocity_color(S32 velocity) {
g = 175.0f + s * (50.0f - 175.0f);
b = 80.0f + s * (40.0f - 80.0f);
}
return Clay_Color{ r, g, b, 255 };
return Clay_Color{r, g, b, 255};
}
void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h) {
@@ -32,7 +32,8 @@ void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h)
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}) {
}
) {
// Compute black key size proportional to white keys
F32 black_key_h = avail_h * PIANO_BLACK_H_PCT;
if (black_key_h < uis(20)) black_key_h = uis(20);
@@ -53,14 +54,16 @@ void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h)
} else if (mouse_held) {
bg = g_theme.accent;
} else {
bg = Clay_Color{ 240, 240, 240, 255 };
bg = Clay_Color{240, 240, 240, 255};
}
CLAY(CLAY_IDI("PKey", note),
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
},
.backgroundColor = bg, .border = { .color = { 190, 190, 190, 255 }, .width = { .right = 1 } }, ) {}
.backgroundColor = bg,
.border = { .color = {190, 190, 190, 255}, .width = { .right = 1 } },
) {}
}
// Black keys (floating, attached to left white key)
@@ -76,7 +79,7 @@ void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h)
} else if (mouse_held) {
bg = g_theme.accent;
} else {
bg = Clay_Color{ 25, 25, 30, 255 };
bg = Clay_Color{25, 25, 30, 255};
}
CLAY(CLAY_IDI("PKey", note),
@@ -86,7 +89,9 @@ void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h)
.height = CLAY_SIZING_FIXED(black_key_h),
},
},
.backgroundColor = bg, .cornerRadius = { .topLeft = 0, .topRight = 0, .bottomLeft = uis(2), .bottomRight = uis(2) }, .floating = {
.backgroundColor = bg,
.cornerRadius = { .topLeft = 0, .topRight = 0, .bottomLeft = uis(2), .bottomRight = uis(2) },
.floating = {
.parentId = parent_wkey.id,
.zIndex = 100,
.attachPoints = {
@@ -94,7 +99,8 @@ void ui_piano(UI_PianoState *state, MidiEngine *midi, F32 avail_w, F32 avail_h)
.parent = CLAY_ATTACH_POINT_RIGHT_TOP,
},
.attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
}, ) {}
},
) {}
}
}
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include "midi/midi.h"
#include "ui/ui_core.h"
#include "midi/midi.h"
#define PIANO_FIRST_NOTE 21 // A0
#define PIANO_LAST_NOTE 108 // C8

View File

@@ -23,10 +23,7 @@ PopupWindow *popup_open(PlatformWindow *parent_window, Renderer *parent_renderer
// Find free slot
PopupWindow *popup = nullptr;
for (S32 i = 0; i < MAX_POPUP_WINDOWS; i++) {
if (!g_popups[i].alive) {
popup = &g_popups[i];
break;
}
if (!g_popups[i].alive) { popup = &g_popups[i]; break; }
}
if (!popup) return nullptr;
@@ -140,7 +137,8 @@ void popup_do_frame(PopupWindow *popup, F32 dt) {
.childGap = uip(8),
.layoutDirection = CLAY_TOP_TO_BOTTOM,
},
.backgroundColor = g_theme.bg_medium, ) {
.backgroundColor = g_theme.bg_medium,
) {
if (popup->content_fn) {
popup->content_fn(popup->content_user_data);
}

View File

@@ -1,8 +1,8 @@
#pragma once
#include "platform/platform.h"
#include "renderer/renderer.h"
#include "ui/ui_core.h"
#include "ui/ui_widgets.h"
#include "platform/platform.h"
#include "renderer/renderer.h"
#define MAX_POPUP_WINDOWS 4

View File

@@ -5,10 +5,10 @@
// AFTER a CLAY() block, use Clay_PointerOver(elementId).
#include "ui/ui_widgets.h"
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
UI_WidgetState g_wstate = {};
@@ -78,11 +78,13 @@ static void emit_shadow(Clay_BoundingBox bb, F32 ox, F32 oy, F32 radius,
CLAY(shadow_eid,
.layout = {
.sizing = {
.width = CLAY_SIZING_FIXED(bb.width + expand * 2),
.height = CLAY_SIZING_FIXED(bb.height + expand * 2),
.width = CLAY_SIZING_FIXED(bb.width + expand*2),
.height = CLAY_SIZING_FIXED(bb.height + expand*2),
},
},
.backgroundColor = { 0, 0, 0, per_layer }, .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS + expand), .floating = {
.backgroundColor = {0, 0, 0, per_layer},
.cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS + expand),
.floating = {
.offset = { bb.x - expand + ox, bb.y - expand + oy },
.zIndex = z,
.attachPoints = {
@@ -90,16 +92,19 @@ static void emit_shadow(Clay_BoundingBox bb, F32 ox, F32 oy, F32 radius,
.parent = CLAY_ATTACH_POINT_LEFT_TOP,
},
.attachTo = CLAY_ATTACH_TO_ROOT,
}) {}
}
) {}
} else {
CLAY(shadow_eid,
.layout = {
.sizing = {
.width = CLAY_SIZING_FIXED(bb.width + expand * 2),
.height = CLAY_SIZING_FIXED(bb.height + expand * 2),
.width = CLAY_SIZING_FIXED(bb.width + expand*2),
.height = CLAY_SIZING_FIXED(bb.height + expand*2),
},
},
.backgroundColor = { 0, 0, 0, per_layer }, .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS + expand), .floating = {
.backgroundColor = {0, 0, 0, per_layer},
.cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS + expand),
.floating = {
.offset = { -expand + ox, -expand + oy },
.parentId = parent_id,
.zIndex = z,
@@ -108,7 +113,8 @@ static void emit_shadow(Clay_BoundingBox bb, F32 ox, F32 oy, F32 radius,
.parent = parent_attach,
},
.attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
}) {}
}
) {}
}
}
}
@@ -177,7 +183,7 @@ static void ensure_widget_text_configs() {
// Selected text: white on accent background (background set on parent element)
g_widget_text_config_sel = {};
g_widget_text_config_sel.textColor = Clay_Color{ 255, 255, 255, 255 };
g_widget_text_config_sel.textColor = Clay_Color{255, 255, 255, 255};
g_widget_text_config_sel.fontSize = FONT_SIZE_NORMAL;
g_widget_text_config_sel.wrapMode = CLAY_TEXT_WRAP_NONE;
@@ -228,7 +234,8 @@ void ui_icon(UI_IconID icon, F32 size, Clay_Color color) {
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(size), .height = CLAY_SIZING_FIXED(size) },
},
.custom = { .customData = data }) {}
.custom = { .customData = data }
) {}
}
////////////////////////////////
@@ -240,7 +247,8 @@ void ui_label(const char *id, const char *text) {
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
.padding = { 0, 0, uip(2), uip(2) },
}) {
}
) {
CLAY_TEXT(clay_str(text), &g_widget_text_config);
}
}
@@ -255,8 +263,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 = { (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 };
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,
@@ -265,7 +273,10 @@ B32 ui_button(const char *id, const char *text) {
.padding = { uip(12), uip(12), uip(1), 0 },
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = base, .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS), .custom = { .customData = grad }, ) {
.backgroundColor = base,
.cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS),
.custom = { .customData = grad },
) {
CLAY_TEXT(clay_str(text), &g_widget_text_config_btn);
}
@@ -288,7 +299,8 @@ B32 ui_checkbox(const char *id, const char *label, B32 *value) {
.childGap = uip(8),
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}) {
}
) {
// Box
Clay_Color box_bg = *value ? g_theme.accent : g_theme.bg_dark;
if (hovered) {
@@ -299,7 +311,10 @@ B32 ui_checkbox(const char *id, const char *label, B32 *value) {
.sizing = { .width = CLAY_SIZING_FIXED(WIDGET_CHECKBOX_SIZE), .height = CLAY_SIZING_FIXED(WIDGET_CHECKBOX_SIZE) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = box_bg, .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS), .border = { .color = g_theme.border, .width = { 1, 1, 1, 1 } }) {
.backgroundColor = box_bg,
.cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS),
.border = { .color = g_theme.border, .width = { 1, 1, 1, 1 } }
) {
if (*value) {
ui_icon(UI_ICON_CHECK, WIDGET_CHECKBOX_SIZE * 0.75f, g_theme.button_text);
}
@@ -329,7 +344,8 @@ B32 ui_radio_group(const char *id, const char **options, S32 count, S32 *selecte
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
.childGap = uip(4),
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}) {
}
) {
for (S32 i = 0; i < count; i++) {
B32 is_selected = (*selected == i);
Clay_ElementId row_id = WIDI(id, i + 100);
@@ -341,7 +357,8 @@ B32 ui_radio_group(const char *id, const char **options, S32 count, S32 *selecte
.childGap = uip(8),
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}) {
}
) {
// Radio circle
Clay_Color dot_bg = is_selected ? g_theme.accent : g_theme.bg_dark;
if (row_hovered) {
@@ -352,13 +369,18 @@ B32 ui_radio_group(const char *id, const char **options, S32 count, S32 *selecte
.sizing = { .width = CLAY_SIZING_FIXED(WIDGET_RADIO_OUTER), .height = CLAY_SIZING_FIXED(WIDGET_RADIO_OUTER) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = dot_bg, .cornerRadius = CLAY_CORNER_RADIUS(uis(8)), .border = { .color = g_theme.border, .width = { 1, 1, 1, 1 } }) {
.backgroundColor = dot_bg,
.cornerRadius = CLAY_CORNER_RADIUS(uis(8)),
.border = { .color = g_theme.border, .width = { 1, 1, 1, 1 } }
) {
if (is_selected) {
CLAY(WIDI(id, i + 300),
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(WIDGET_RADIO_INNER), .height = CLAY_SIZING_FIXED(WIDGET_RADIO_INNER) },
},
.backgroundColor = g_theme.button_text, .cornerRadius = CLAY_CORNER_RADIUS(uis(4))) {}
.backgroundColor = g_theme.button_text,
.cornerRadius = CLAY_CORNER_RADIUS(uis(4))
) {}
}
}
@@ -398,13 +420,8 @@ void ui_text_input_reset_display_bufs() {
static void text_input_get_sel(S32 *lo, S32 *hi) {
S32 a = g_wstate.sel_start;
S32 b = g_wstate.sel_end;
if (a <= b) {
*lo = a;
*hi = b;
} else {
*lo = b;
*hi = a;
}
if (a <= b) { *lo = a; *hi = b; }
else { *lo = b; *hi = a; }
}
// Helper: true if there's an active selection
@@ -543,10 +560,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
S32 clip_len = (S32)strlen(clip);
// Filter to single line (stop at newline)
for (S32 i = 0; i < clip_len; i++) {
if (clip[i] == '\n' || clip[i] == '\r') {
clip_len = i;
break;
}
if (clip[i] == '\n' || clip[i] == '\r') { clip_len = i; break; }
}
S32 space = buf_size - 1 - len;
if (clip_len > space) clip_len = space;
@@ -594,8 +608,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
break;
case PKEY_LEFT:
if (text_input_has_sel()) {
S32 lo, hi;
text_input_get_sel(&lo, &hi);
S32 lo, hi; text_input_get_sel(&lo, &hi);
g_wstate.cursor_pos = lo;
} else if (g_wstate.cursor_pos > 0) {
g_wstate.cursor_pos--;
@@ -606,8 +619,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
break;
case PKEY_RIGHT:
if (text_input_has_sel()) {
S32 lo, hi;
text_input_get_sel(&lo, &hi);
S32 lo, hi; text_input_get_sel(&lo, &hi);
g_wstate.cursor_pos = hi;
} else if (g_wstate.cursor_pos < len) {
g_wstate.cursor_pos++;
@@ -666,10 +678,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
// our ID was just added above. Find it and advance to next.
S32 my_idx = -1;
for (S32 i = 0; i < g_wstate.text_input_count; i++) {
if (g_wstate.text_input_ids[i] == eid.id) {
my_idx = i;
break;
}
if (g_wstate.text_input_ids[i] == eid.id) { my_idx = i; break; }
}
if (my_idx >= 0) {
// Focus next (wrapping). But we might not have all inputs registered
@@ -712,8 +721,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 = { (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 };
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,
@@ -723,7 +732,11 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
.layoutDirection = CLAY_LEFT_TO_RIGHT,
},
.backgroundColor = bg, .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS), .custom = { .customData = inset_grad }, .border = { .color = border_color, .width = { 1, 1, 1, 1 } }, ) {
.backgroundColor = bg,
.cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS),
.custom = { .customData = inset_grad },
.border = { .color = border_color, .width = { 1, 1, 1, 1 } },
) {
if (len == 0 && !is_focused) {
// Placeholder
CLAY_TEXT(CLAY_STRING("..."), &g_widget_text_config_dim);
@@ -746,7 +759,8 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
.layout = {
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
},
.backgroundColor = g_theme.accent) {
.backgroundColor = g_theme.accent
) {
CLAY_TEXT(clay_str(dbuf_sel), &g_widget_text_config_sel);
}
}
@@ -812,15 +826,12 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
while (lo < hi) {
S32 mid = (lo + hi + 1) / 2;
Vec2F32 seg = ui_measure_text(current_label, mid, FONT_SIZE_NORMAL);
if (seg.x <= target_w) lo = mid;
else hi = mid - 1;
if (seg.x <= target_w) lo = mid; else hi = mid - 1;
}
if (lo + 3 < (S32)sizeof(dd_trunc_buf)) {
memcpy(dd_trunc_buf, current_label, lo);
dd_trunc_buf[lo] = '.';
dd_trunc_buf[lo + 1] = '.';
dd_trunc_buf[lo + 2] = '.';
dd_trunc_buf[lo + 3] = '\0';
dd_trunc_buf[lo] = '.'; dd_trunc_buf[lo+1] = '.'; dd_trunc_buf[lo+2] = '.';
dd_trunc_buf[lo+3] = '\0';
display_label = dd_trunc_buf;
}
}
@@ -829,7 +840,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 = { (F32)Min((S32)bg.r + 6, 255), (F32)Min((S32)bg.g + 6, 255), (F32)Min((S32)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,
@@ -839,11 +850,16 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
.layoutDirection = CLAY_LEFT_TO_RIGHT,
},
.backgroundColor = bg, .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS), .custom = { .customData = dd_grad }, .border = { .color = is_open ? g_theme.accent : g_theme.border, .width = { 1, 1, 1, 1 } }, ) {
.backgroundColor = bg,
.cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS),
.custom = { .customData = dd_grad },
.border = { .color = is_open ? g_theme.accent : g_theme.border, .width = { 1, 1, 1, 1 } },
) {
CLAY(text_eid,
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
}) {
}
) {
CLAY_TEXT(clay_str(display_label), &g_widget_text_config);
}
@@ -851,7 +867,8 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(uis(20)), .height = CLAY_SIZING_FIXED(uis(20)) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
}) {
}
) {
ui_icon(UI_ICON_CHEVRON_DOWN, uis(12), g_theme.text_dim);
}
}
@@ -885,7 +902,9 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
.sizing = { .width = CLAY_SIZING_FIT(.min = header_width), .height = CLAY_SIZING_FIT() },
.layoutDirection = CLAY_TOP_TO_BOTTOM,
},
.backgroundColor = g_theme.bg_dark, .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS), .floating = {
.backgroundColor = g_theme.bg_dark,
.cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS),
.floating = {
.parentId = eid.id,
.zIndex = 2000,
.attachPoints = {
@@ -894,7 +913,8 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
},
.attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
},
.border = { .color = g_theme.border, .width = { 1, 1, 1, 1 } }, ) {
.border = { .color = g_theme.border, .width = { 1, 1, 1, 1 } },
) {
for (S32 i = 0; i < count; i++) {
B32 is_item_selected = (*selected == i);
Clay_ElementId item_id = WIDI(id, i + 600);
@@ -904,18 +924,11 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
if (item_hovered) item_bg = g_theme.bg_lighter;
Clay_TextElementConfig *item_text = (is_item_selected && !item_hovered)
? &g_widget_text_config_btn
: &g_widget_text_config;
? &g_widget_text_config_btn : &g_widget_text_config;
Clay_CornerRadius item_radius = {};
if (i == 0) {
item_radius.topLeft = CORNER_RADIUS;
item_radius.topRight = CORNER_RADIUS;
}
if (i == count - 1) {
item_radius.bottomLeft = CORNER_RADIUS;
item_radius.bottomRight = CORNER_RADIUS;
}
if (i == 0) { item_radius.topLeft = CORNER_RADIUS; item_radius.topRight = CORNER_RADIUS; }
if (i == count - 1) { item_radius.bottomLeft = CORNER_RADIUS; item_radius.bottomRight = CORNER_RADIUS; }
CLAY(item_id,
.layout = {
@@ -923,7 +936,9 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
.padding = { uip(8), uip(8), 0, 0 },
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = item_bg, .cornerRadius = item_radius) {
.backgroundColor = item_bg,
.cornerRadius = item_radius
) {
CLAY_TEXT(clay_str(options[i]), item_text);
}
@@ -940,10 +955,7 @@ B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected)
// Check if any item was clicked (already handled above)
B32 clicked_item = 0;
for (S32 i = 0; i < count; i++) {
if (Clay_PointerOver(WIDI(id, i + 600))) {
clicked_item = 1;
break;
}
if (Clay_PointerOver(WIDI(id, i + 600))) { clicked_item = 1; break; }
}
if (!clicked_item) {
g_wstate.open_dropdown_id = 0;
@@ -973,7 +985,9 @@ S32 ui_tab_bar(const char *id, const char **labels, S32 count, S32 *selected) {
.padding = { 0, 0, 0, 0 },
.layoutDirection = CLAY_LEFT_TO_RIGHT,
},
.backgroundColor = g_theme.bg_medium, .border = { .color = g_theme.border, .width = { .bottom = 1 } }, ) {
.backgroundColor = g_theme.bg_medium,
.border = { .color = g_theme.border, .width = { .bottom = 1 } },
) {
for (S32 i = 0; i < count; i++) {
Clay_ElementId tab_eid = Clay__HashStringWithOffset(id_str, (U32)i, 0);
B32 is_active = (i == *selected);
@@ -988,7 +1002,9 @@ S32 ui_tab_bar(const char *id, const char **labels, S32 count, S32 *selected) {
.padding = { TAB_PADDING_H, TAB_PADDING_H, 0, uip(6) },
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
},
.cornerRadius = { .topLeft = TAB_CORNER_RADIUS, .topRight = TAB_CORNER_RADIUS, .bottomLeft = 0, .bottomRight = 0 }, .custom = { .customData = &g_tab_gradient }, ) {
.cornerRadius = { .topLeft = TAB_CORNER_RADIUS, .topRight = TAB_CORNER_RADIUS, .bottomLeft = 0, .bottomRight = 0 },
.custom = { .customData = &g_tab_gradient },
) {
CLAY_TEXT(lbl_str, &g_widget_text_config_tab);
}
} else {
@@ -999,7 +1015,9 @@ S32 ui_tab_bar(const char *id, const char **labels, S32 count, S32 *selected) {
.padding = { TAB_PADDING_H, TAB_PADDING_H, 0, uip(6) },
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = bg, .cornerRadius = { .topLeft = TAB_CORNER_RADIUS, .topRight = TAB_CORNER_RADIUS, .bottomLeft = 0, .bottomRight = 0 }, ) {
.backgroundColor = bg,
.cornerRadius = { .topLeft = TAB_CORNER_RADIUS, .topRight = TAB_CORNER_RADIUS, .bottomLeft = 0, .bottomRight = 0 },
) {
CLAY_TEXT(lbl_str, &g_widget_text_config_tab_inactive);
}
}
@@ -1031,14 +1049,10 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
if (*esel0 > elen) *esel0 = elen;
if (*esel1 > elen) *esel1 = elen;
#define KE_HAS_SEL() (*esel0 != *esel1)
#define KE_SEL_LO() (*esel0 < *esel1 ? *esel0 : *esel1)
#define KE_SEL_HI() (*esel0 < *esel1 ? *esel1 : *esel0)
#define KE_CLEAR_SEL() \
do { \
*esel0 = *ecur; \
*esel1 = *ecur; \
} while (0)
#define KE_HAS_SEL() (*esel0 != *esel1)
#define KE_SEL_LO() (*esel0 < *esel1 ? *esel0 : *esel1)
#define KE_SEL_HI() (*esel0 < *esel1 ? *esel1 : *esel0)
#define KE_CLEAR_SEL() do { *esel0 = *ecur; *esel1 = *ecur; } while(0)
auto ke_delete_sel = [&]() -> S32 {
S32 lo = KE_SEL_LO(), hi = KE_SEL_HI();
@@ -1054,19 +1068,13 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
if (ctrl) {
if (key == PKEY_A) {
*esel0 = 0;
*esel1 = elen;
*ecur = elen;
continue;
*esel0 = 0; *esel1 = elen; *ecur = elen; continue;
}
if (key == PKEY_C) {
if (KE_HAS_SEL()) {
S32 lo = KE_SEL_LO(), hi = KE_SEL_HI();
char tmp[32];
S32 n = hi - lo;
if (n > 31) n = 31;
memcpy(tmp, &ebuf[lo], n);
tmp[n] = '\0';
char tmp[32]; S32 n = hi - lo; if (n > 31) n = 31;
memcpy(tmp, &ebuf[lo], n); tmp[n] = '\0';
platform_clipboard_set(tmp);
}
continue;
@@ -1074,11 +1082,8 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
if (key == PKEY_X) {
if (KE_HAS_SEL()) {
S32 lo = KE_SEL_LO(), hi = KE_SEL_HI();
char tmp[32];
S32 n = hi - lo;
if (n > 31) n = 31;
memcpy(tmp, &ebuf[lo], n);
tmp[n] = '\0';
char tmp[32]; S32 n = hi - lo; if (n > 31) n = 31;
memcpy(tmp, &ebuf[lo], n); tmp[n] = '\0';
platform_clipboard_set(tmp);
elen = ke_delete_sel();
}
@@ -1089,8 +1094,7 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
if (clip) {
if (KE_HAS_SEL()) elen = ke_delete_sel();
S32 clip_len = (S32)strlen(clip);
char filtered[32];
S32 flen = 0;
char filtered[32]; S32 flen = 0;
for (S32 i = 0; i < clip_len && flen < 30; i++) {
char c = clip[i];
if ((c >= '0' && c <= '9') || c == '.' || c == '-')
@@ -1101,8 +1105,7 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
if (flen > 0) {
memmove(&ebuf[*ecur + flen], &ebuf[*ecur], elen - *ecur + 1);
memcpy(&ebuf[*ecur], filtered, flen);
*ecur += flen;
elen += flen;
*ecur += flen; elen += flen;
}
KE_CLEAR_SEL();
}
@@ -1111,40 +1114,29 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
continue;
}
if (key == PKEY_RETURN) {
commit = 1;
} else if (key == PKEY_ESCAPE) {
cancel = 1;
} else if (key == PKEY_BACKSPACE) {
if (KE_HAS_SEL()) {
elen = ke_delete_sel();
} else if (*ecur > 0) {
if (key == PKEY_RETURN) { commit = 1; }
else if (key == PKEY_ESCAPE) { cancel = 1; }
else if (key == PKEY_BACKSPACE) {
if (KE_HAS_SEL()) { elen = ke_delete_sel(); }
else if (*ecur > 0) {
memmove(&ebuf[*ecur - 1], &ebuf[*ecur], elen - *ecur + 1);
(*ecur)--;
elen--;
(*ecur)--; elen--;
}
KE_CLEAR_SEL();
} else if (key == PKEY_DELETE) {
if (KE_HAS_SEL()) {
elen = ke_delete_sel();
} else if (*ecur < elen) {
if (KE_HAS_SEL()) { elen = ke_delete_sel(); }
else if (*ecur < elen) {
memmove(&ebuf[*ecur], &ebuf[*ecur + 1], elen - *ecur);
elen--;
}
KE_CLEAR_SEL();
} else if (key == PKEY_LEFT) {
if (KE_HAS_SEL()) {
*ecur = KE_SEL_LO();
} else if (*ecur > 0) {
(*ecur)--;
}
if (KE_HAS_SEL()) { *ecur = KE_SEL_LO(); }
else if (*ecur > 0) { (*ecur)--; }
KE_CLEAR_SEL();
} else if (key == PKEY_RIGHT) {
if (KE_HAS_SEL()) {
*ecur = KE_SEL_HI();
} else if (*ecur < elen) {
(*ecur)++;
}
if (KE_HAS_SEL()) { *ecur = KE_SEL_HI(); }
else if (*ecur < elen) { (*ecur)++; }
KE_CLEAR_SEL();
}
}
@@ -1157,19 +1149,17 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
if (KE_HAS_SEL()) elen = ke_delete_sel();
if (elen < 30) {
memmove(&ebuf[*ecur + 1], &ebuf[*ecur], elen - *ecur + 1);
ebuf[*ecur] = (char)ch;
(*ecur)++;
elen++;
ebuf[*ecur] = (char)ch; (*ecur)++; elen++;
}
KE_CLEAR_SEL();
}
}
}
#undef KE_HAS_SEL
#undef KE_SEL_LO
#undef KE_SEL_HI
#undef KE_CLEAR_SEL
#undef KE_HAS_SEL
#undef KE_SEL_LO
#undef KE_SEL_HI
#undef KE_CLEAR_SEL
if (commit) {
char *end = nullptr;
@@ -1178,10 +1168,7 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
F32 lo = is_signed ? -max_val : 0.0f;
if (parsed < lo) parsed = lo;
if (parsed > max_val) parsed = max_val;
if (parsed != *value) {
*value = parsed;
*changed = 1;
}
if (parsed != *value) { *value = parsed; *changed = 1; }
}
g_wstate.knob_edit_id = 0;
return 1;
@@ -1218,7 +1205,7 @@ static void value_edit_render(U32 hash, F32 width) {
edit_cfg.wrapMode = CLAY_TEXT_WRAP_NONE;
static Clay_TextElementConfig edit_sel_cfg = {};
edit_sel_cfg.textColor = Clay_Color{ 255, 255, 255, 255 };
edit_sel_cfg.textColor = Clay_Color{255, 255, 255, 255};
edit_sel_cfg.fontSize = FONT_SIZE_SMALL;
edit_sel_cfg.wrapMode = CLAY_TEXT_WRAP_NONE;
@@ -1229,30 +1216,31 @@ static void value_edit_render(U32 hash, F32 width) {
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
.layoutDirection = CLAY_LEFT_TO_RIGHT,
},
.backgroundColor = g_theme.bg_dark, .cornerRadius = CLAY_CORNER_RADIUS(uis(2)), .border = { .color = g_theme.accent, .width = { 1, 1, 1, 1 } }) {
.backgroundColor = g_theme.bg_dark,
.cornerRadius = CLAY_CORNER_RADIUS(uis(2)),
.border = { .color = g_theme.accent, .width = { 1, 1, 1, 1 } }
) {
if (has_sel) {
if (sel_lo > 0) {
S32 n = sel_lo;
memcpy(ke_dbuf_before, ebuf, n);
ke_dbuf_before[n] = '\0';
memcpy(ke_dbuf_before, ebuf, n); ke_dbuf_before[n] = '\0';
Clay_String s_before = { .length = n, .chars = ke_dbuf_before };
CLAY_TEXT(s_before, &edit_cfg);
}
{
S32 n = sel_hi - sel_lo;
memcpy(ke_dbuf_sel, &ebuf[sel_lo], n);
ke_dbuf_sel[n] = '\0';
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", (S32)hash),
.layout = { .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() } },
.backgroundColor = g_theme.accent) {
.backgroundColor = g_theme.accent
) {
CLAY_TEXT(s_sel, &edit_sel_cfg);
}
}
if (sel_hi < elen) {
S32 n = elen - sel_hi;
memcpy(ke_dbuf_after, &ebuf[sel_hi], n);
ke_dbuf_after[n] = '\0';
memcpy(ke_dbuf_after, &ebuf[sel_hi], n); ke_dbuf_after[n] = '\0';
Clay_String s_after = { .length = n, .chars = ke_dbuf_after };
CLAY_TEXT(s_after, &edit_cfg);
}
@@ -1284,10 +1272,7 @@ static void value_edit_click_away(Clay_ElementId eid, F32 *value, F32 max_val, B
F32 lo = is_signed ? -max_val : 0.0f;
if (parsed < lo) parsed = lo;
if (parsed > max_val) parsed = max_val;
if (parsed != *value) {
*value = parsed;
*changed = 1;
}
if (parsed != *value) { *value = parsed; *changed = 1; }
}
g_wstate.knob_edit_id = 0;
}
@@ -1311,11 +1296,8 @@ static void value_edit_enter(U32 hash, F32 value, B32 is_signed) {
// Normalize a value to [0,1] range.
static F32 value_normalize(F32 value, F32 max_val, B32 is_signed) {
F32 n;
if (is_signed) {
n = (value + max_val) / (2.0f * max_val);
} else {
n = value / max_val;
}
if (is_signed) { n = (value + max_val) / (2.0f * max_val); }
else { n = value / max_val; }
if (n < 0.0f) n = 0.0f;
if (n > 1.0f) n = 1.0f;
return n;
@@ -1325,11 +1307,8 @@ static F32 value_normalize(F32 value, F32 max_val, B32 is_signed) {
static char *value_format_text(F32 value, B32 is_signed, S32 *out_len) {
if (g_knob_text_buf_count >= UI_MAX_KNOB_TEXT_BUFS) return nullptr;
char *buf = g_knob_text_bufs[g_knob_text_buf_count++];
if (is_signed) {
*out_len = snprintf(buf, 32, "%+.1f", value);
} else {
*out_len = snprintf(buf, 32, "%.1f", value);
}
if (is_signed) { *out_len = snprintf(buf, 32, "%+.1f", value); }
else { *out_len = snprintf(buf, 32, "%.1f", value); }
return buf;
}
@@ -1368,10 +1347,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
F32 lo = is_signed ? -max_val : 0.0f;
if (new_val < lo) new_val = lo;
if (new_val > max_val) new_val = max_val;
if (new_val != *value) {
*value = new_val;
changed = 1;
}
if (new_val != *value) { *value = new_val; changed = 1; }
normalized = value_normalize(*value, max_val, is_signed);
angle_rad = (-135.0f + normalized * 270.0f) * deg_to_rad;
}
@@ -1397,7 +1373,8 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
.childGap = WIDGET_KNOB_LABEL_GAP,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}) {
}
) {
Clay_ElementId knob_eid = CLAY_IDI("KnobBg", (S32)knob_hash);
B32 hovered = Clay_PointerOver(knob_eid);
@@ -1406,7 +1383,9 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
.sizing = { .width = CLAY_SIZING_FIXED(knob_size), .height = CLAY_SIZING_FIXED(knob_size) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = g_theme.bg_dark, .cornerRadius = CLAY_CORNER_RADIUS(knob_size / 2.0f)) {
.backgroundColor = g_theme.bg_dark,
.cornerRadius = CLAY_CORNER_RADIUS(knob_size / 2.0f)
) {
if (g_rotated_icon_pool_count < UI_MAX_ROTATED_ICONS_PER_FRAME) {
S32 ri_idx = g_rotated_icon_pool_count;
CustomRotatedIconData *rdata = &g_rotated_icon_pool[g_rotated_icon_pool_count++];
@@ -1420,7 +1399,8 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(icon_size), .height = CLAY_SIZING_FIXED(icon_size) },
},
.custom = { .customData = rdata }) {}
.custom = { .customData = rdata }
) {}
}
}
@@ -1432,10 +1412,7 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
kd->last_click_frame = g_frame_number;
if (is_double_click) {
if (*value != default_val) {
*value = default_val;
changed = 1;
}
if (*value != default_val) { *value = default_val; changed = 1; }
normalized = value_normalize(*value, max_val, is_signed);
angle_rad = (-135.0f + normalized * 270.0f) * deg_to_rad;
kd->last_click_id = 0;
@@ -1465,7 +1442,8 @@ B32 ui_knob(const char *id, const char *label, F32 *value, F32 max_val, B32 is_s
.sizing = { .width = CLAY_SIZING_FIXED(knob_size), .height = CLAY_SIZING_FIT() },
.padding = { uip(2), uip(2), uip(1), uip(1) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
}) {
}
) {
CLAY_TEXT(val_str, &knob_val_cfg);
}
@@ -1514,10 +1492,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
F32 lo = is_signed ? -max_val : 0.0f;
if (new_val < lo) new_val = lo;
if (new_val > max_val) new_val = max_val;
if (new_val != *value) {
*value = new_val;
changed = 1;
}
if (new_val != *value) { *value = new_val; changed = 1; }
normalized = value_normalize(*value, max_val, is_signed);
}
@@ -1545,7 +1520,8 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
.childGap = WIDGET_KNOB_LABEL_GAP,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}) {
}
) {
// Label
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
@@ -1557,13 +1533,16 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(thumb_h) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
}) {
}
) {
// Visible track (centered inside hit area)
CLAY(CLAY_IDI("SlHTrack", (S32)hash),
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
},
.backgroundColor = g_theme.bg_dark, .cornerRadius = CLAY_CORNER_RADIUS(track_h / 2.0f)) {
.backgroundColor = g_theme.bg_dark,
.cornerRadius = CLAY_CORNER_RADIUS(track_h / 2.0f)
) {
// Fill bar
F32 fill_w = normalized * track_w;
if (fill_w < 1.0f) fill_w = 1.0f;
@@ -1571,7 +1550,9 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(fill_w), .height = CLAY_SIZING_GROW() },
},
.backgroundColor = fill_color, .cornerRadius = CLAY_CORNER_RADIUS(track_h / 2.0f)) {}
.backgroundColor = fill_color,
.cornerRadius = CLAY_CORNER_RADIUS(track_h / 2.0f)
) {}
}
// Floating icon thumb (attached to hit area)
@@ -1598,7 +1579,8 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
.attachTo = CLAY_ATTACH_TO_PARENT,
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
},
.custom = { .customData = idata }, ) {}
.custom = { .customData = idata },
) {}
}
}
@@ -1610,10 +1592,7 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
kd->last_click_frame = g_frame_number;
if (is_double_click) {
if (*value != default_val) {
*value = default_val;
changed = 1;
}
if (*value != default_val) { *value = default_val; changed = 1; }
normalized = value_normalize(*value, max_val, is_signed);
kd->last_click_id = 0;
} else {
@@ -1642,7 +1621,8 @@ B32 ui_slider_h(const char *id, const char *label, F32 *value, F32 max_val, B32
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIT() },
.padding = { uip(2), uip(2), uip(1), uip(1) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
}) {
}
) {
CLAY_TEXT(val_str, &sl_val_cfg);
}
@@ -1688,10 +1668,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
F32 lo = is_signed ? -max_val : 0.0f;
if (new_val < lo) new_val = lo;
if (new_val > max_val) new_val = max_val;
if (new_val != *value) {
*value = new_val;
changed = 1;
}
if (new_val != *value) { *value = new_val; changed = 1; }
normalized = value_normalize(*value, max_val, is_signed);
}
@@ -1719,7 +1696,8 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
.childGap = WIDGET_KNOB_LABEL_GAP,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}) {
}
) {
// Label
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
@@ -1731,14 +1709,17 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(thumb_w), .height = CLAY_SIZING_FIXED(track_h) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
}) {
}
) {
// Visible track (centered inside hit area)
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 },
},
.backgroundColor = g_theme.bg_dark, .cornerRadius = CLAY_CORNER_RADIUS(track_w / 2.0f)) {
.backgroundColor = g_theme.bg_dark,
.cornerRadius = CLAY_CORNER_RADIUS(track_w / 2.0f)
) {
// Fill bar (from bottom)
F32 fill_h = normalized * track_h;
if (fill_h < 1.0f) fill_h = 1.0f;
@@ -1746,7 +1727,9 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(fill_h) },
},
.backgroundColor = fill_color, .cornerRadius = CLAY_CORNER_RADIUS(track_w / 2.0f)) {}
.backgroundColor = fill_color,
.cornerRadius = CLAY_CORNER_RADIUS(track_w / 2.0f)
) {}
}
// Floating icon thumb (attached to hit area)
@@ -1773,7 +1756,8 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
.attachTo = CLAY_ATTACH_TO_PARENT,
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
},
.custom = { .customData = idata }, ) {}
.custom = { .customData = idata },
) {}
}
}
@@ -1785,10 +1769,7 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
kd->last_click_frame = g_frame_number;
if (is_double_click) {
if (*value != default_val) {
*value = default_val;
changed = 1;
}
if (*value != default_val) { *value = default_val; changed = 1; }
normalized = value_normalize(*value, max_val, is_signed);
kd->last_click_id = 0;
} else {
@@ -1817,7 +1798,8 @@ B32 ui_slider_v(const char *id, const char *label, F32 *value, F32 max_val, B32
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
.padding = { uip(2), uip(2), uip(1), uip(1) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
}) {
}
) {
CLAY_TEXT(val_str, &sl_val_cfg);
}
@@ -1863,10 +1845,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
F32 lo = is_signed ? -max_val : 0.0f;
if (new_val < lo) new_val = lo;
if (new_val > max_val) new_val = max_val;
if (new_val != *value) {
*value = new_val;
changed = 1;
}
if (new_val != *value) { *value = new_val; changed = 1; }
normalized = value_normalize(*value, max_val, is_signed);
}
@@ -1897,7 +1876,8 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.childGap = WIDGET_KNOB_LABEL_GAP,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}) {
}
) {
// Label
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
@@ -1909,13 +1889,16 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(track_h) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
}) {
}
) {
// Visible track (centered inside hit area, empty)
CLAY(CLAY_IDI("FdrTrack", (S32)hash),
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
},
.backgroundColor = g_theme.bg_dark, .cornerRadius = CLAY_CORNER_RADIUS(track_w / 2.0f)) {}
.backgroundColor = g_theme.bg_dark,
.cornerRadius = CLAY_CORNER_RADIUS(track_w / 2.0f)
) {}
// Tick marks on both sides of the track
for (S32 i = 0; i <= num_ticks; i++) {
@@ -1928,7 +1911,8 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(tw), .height = CLAY_SIZING_FIXED(tick_h) },
},
.backgroundColor = g_theme.text_dim, .floating = {
.backgroundColor = g_theme.text_dim,
.floating = {
.offset = {
.x = track_left - tw,
.y = tick_y,
@@ -1940,14 +1924,16 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH,
.attachTo = CLAY_ATTACH_TO_PARENT,
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
}, ) {}
},
) {}
// Right tick
CLAY(CLAY_IDI("FdrTkR", (S32)(hash * 100 + i)),
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(tw), .height = CLAY_SIZING_FIXED(tick_h) },
},
.backgroundColor = g_theme.text_dim, .floating = {
.backgroundColor = g_theme.text_dim,
.floating = {
.offset = {
.x = track_left + track_w,
.y = tick_y,
@@ -1959,7 +1945,8 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH,
.attachTo = CLAY_ATTACH_TO_PARENT,
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
}, ) {}
},
) {}
}
// Floating fader cap (RGBA icon from asset SVG)
@@ -1967,7 +1954,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
CustomIconData *idata = &g_icon_pool[g_icon_pool_count++];
idata->type = CUSTOM_RENDER_ICON;
idata->icon_id = (S32)UI_ICON_FADER;
idata->color = Clay_Color{ 255, 255, 255, 255 };
idata->color = Clay_Color{255, 255, 255, 255};
F32 cap_y = (1.0f - normalized) * (track_h - cap_h);
@@ -1985,7 +1972,8 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.attachTo = CLAY_ATTACH_TO_PARENT,
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
},
.custom = { .customData = idata }, ) {}
.custom = { .customData = idata },
) {}
// Color tint overlay on top of fader cap
Clay_Color tint = g_theme.accent;
@@ -1995,7 +1983,9 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(cap_h) },
},
.backgroundColor = tint, .cornerRadius = CLAY_CORNER_RADIUS(cap_corner), .floating = {
.backgroundColor = tint,
.cornerRadius = CLAY_CORNER_RADIUS(cap_corner),
.floating = {
.offset = { .x = 0, .y = cap_y },
.attachPoints = {
.element = CLAY_ATTACH_POINT_LEFT_TOP,
@@ -2004,7 +1994,8 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH,
.attachTo = CLAY_ATTACH_TO_PARENT,
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
}, ) {}
},
) {}
}
}
@@ -2016,10 +2007,7 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
kd->last_click_frame = g_frame_number;
if (is_double_click) {
if (*value != default_val) {
*value = default_val;
changed = 1;
}
if (*value != default_val) { *value = default_val; changed = 1; }
normalized = value_normalize(*value, max_val, is_signed);
kd->last_click_id = 0;
} else {
@@ -2048,7 +2036,8 @@ B32 ui_fader(const char *id, const char *label, F32 *value, F32 max_val, B32 is_
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
.padding = { uip(2), uip(2), uip(1), uip(1) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
}) {
}
) {
CLAY_TEXT(val_str, &fdr_val_cfg);
}

View File

@@ -6,9 +6,9 @@
// The caller owns all data — the widget layer only stores transient UI state
// like which text field is focused or which dropdown is open.
#include "platform/platform.h"
#include "ui/ui_core.h"
#include "ui/ui_icons.h"
#include "platform/platform.h"
////////////////////////////////
// Widget state (global, managed by widget layer)