@@ -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
|
|
||||||
@@ -13,7 +13,7 @@ AudioEngine *audio_create(void *hwnd);
|
|||||||
void audio_destroy(AudioEngine *engine);
|
void audio_destroy(AudioEngine *engine);
|
||||||
void audio_refresh_devices(AudioEngine *engine);
|
void audio_refresh_devices(AudioEngine *engine);
|
||||||
S32 audio_get_device_count(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);
|
B32 audio_open_device(AudioEngine *engine, S32 index);
|
||||||
void audio_close_device(AudioEngine *engine);
|
void audio_close_device(AudioEngine *engine);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "audio/audio.h"
|
#include "audio/audio.h"
|
||||||
#include <math.h>
|
#include <windows.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <windows.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define AUDIO_MAX_DEVICES 32
|
#define AUDIO_MAX_DEVICES 32
|
||||||
#define AUDIO_MAX_CHANNELS 32
|
#define AUDIO_MAX_CHANNELS 32
|
||||||
@@ -124,7 +124,7 @@ enum {
|
|||||||
// Standard ASIO vtable — inherits IUnknown
|
// Standard ASIO vtable — inherits IUnknown
|
||||||
|
|
||||||
class IASIO : public IUnknown {
|
class IASIO : public IUnknown {
|
||||||
public:
|
public:
|
||||||
virtual ASIOBool init(void *sysHandle) = 0;
|
virtual ASIOBool init(void *sysHandle) = 0;
|
||||||
virtual void getDriverName(char *name) = 0;
|
virtual void getDriverName(char *name) = 0;
|
||||||
virtual long getDriverVersion() = 0;
|
virtual long getDriverVersion() = 0;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "audio/audio.h"
|
#include "audio/audio.h"
|
||||||
#include <AudioToolbox/AudioToolbox.h>
|
#include <AudioToolbox/AudioToolbox.h>
|
||||||
#include <CoreAudio/CoreAudio.h>
|
#include <CoreAudio/CoreAudio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
|
||||||
@@ -44,11 +44,9 @@ static OSStatus audio_render_callback(void *inRefCon,
|
|||||||
const AudioTimeStamp *inTimeStamp,
|
const AudioTimeStamp *inTimeStamp,
|
||||||
UInt32 inBusNumber,
|
UInt32 inBusNumber,
|
||||||
UInt32 inNumberFrames,
|
UInt32 inNumberFrames,
|
||||||
AudioBufferList *ioData) {
|
AudioBufferList *ioData)
|
||||||
(void)inRefCon;
|
{
|
||||||
(void)ioActionFlags;
|
(void)inRefCon; (void)ioActionFlags; (void)inTimeStamp; (void)inBusNumber;
|
||||||
(void)inTimeStamp;
|
|
||||||
(void)inBusNumber;
|
|
||||||
|
|
||||||
AudioEngine *engine = g_audio_engine;
|
AudioEngine *engine = g_audio_engine;
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
@@ -87,8 +85,7 @@ static OSStatus audio_render_callback(void *inRefCon,
|
|||||||
|
|
||||||
// Advance phase using first channel's traversal
|
// Advance phase using first channel's traversal
|
||||||
phase += phase_inc * samples_to_gen;
|
phase += phase_inc * samples_to_gen;
|
||||||
while (phase >= 2.0 * AUDIO_PI)
|
while (phase >= 2.0 * AUDIO_PI) phase -= 2.0 * AUDIO_PI;
|
||||||
phase -= 2.0 * AUDIO_PI;
|
|
||||||
engine->test_tone_phase = phase;
|
engine->test_tone_phase = phase;
|
||||||
|
|
||||||
S32 new_remaining = atomic_fetch_sub(&engine->test_tone_samples_remaining, samples_to_gen);
|
S32 new_remaining = atomic_fetch_sub(&engine->test_tone_samples_remaining, samples_to_gen);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ void arena_clear(Arena *arena);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Temporary scope helpers
|
// 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); }
|
inline void temp_end(Temp temp) { arena_pop_to(temp.arena, temp.pos); }
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
// base_core.h - Fundamental types, macros, and linked list helpers
|
// base_core.h - Fundamental types, macros, and linked list helpers
|
||||||
// Inspired by raddebugger's base_core.h
|
// Inspired by raddebugger's base_core.h
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Codebase keywords
|
// Codebase keywords
|
||||||
@@ -60,14 +60,13 @@ typedef double F64;
|
|||||||
#define Max(A, B) (((A) > (B)) ? (A) : (B))
|
#define Max(A, B) (((A) > (B)) ? (A) : (B))
|
||||||
#define ClampTop(A, X) Min(A, X)
|
#define ClampTop(A, X) Min(A, X)
|
||||||
#define ClampBot(X, B) Max(X, B)
|
#define ClampBot(X, B) Max(X, B)
|
||||||
#define Clamp(A, X, B) (((X) < (A)) ? (A) : ((X) > (B)) ? (B) \
|
#define Clamp(A, X, B) (((X) < (A)) ? (A) : ((X) > (B)) ? (B) : (X))
|
||||||
: (X))
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Alignment / Sizing
|
// Alignment / Sizing
|
||||||
|
|
||||||
#define AlignPow2(x, b) (((x) + (b)-1) & (~((b)-1)))
|
#define AlignPow2(x, b) (((x) + (b) - 1) & (~((b) - 1)))
|
||||||
#define AlignDownPow2(x, b) ((x) & (~((b)-1)))
|
#define AlignDownPow2(x, b) ((x) & (~((b) - 1)))
|
||||||
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
|
#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) A##B
|
||||||
#define Glue(A, B) Glue_(A, B)
|
#define Glue(A, B) Glue_(A, B)
|
||||||
|
|
||||||
#define Swap(T, a, b) \
|
#define Swap(T, a, b) do { T t__ = a; a = b; b = t__; } while (0)
|
||||||
do { \
|
|
||||||
T t__ = a; \
|
|
||||||
a = b; \
|
|
||||||
b = t__; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#define Trap() __debugbreak()
|
# define Trap() __debugbreak()
|
||||||
#elif defined(__clang__) || defined(__GNUC__)
|
#elif defined(__clang__) || defined(__GNUC__)
|
||||||
#define Trap() __builtin_trap()
|
# define Trap() __builtin_trap()
|
||||||
#else
|
#else
|
||||||
#define Trap() (*(volatile int *)0 = 0)
|
# define Trap() (*(volatile int *)0 = 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define AssertAlways(x) \
|
#define AssertAlways(x) do { if (!(x)) { Trap(); } } while (0)
|
||||||
do { \
|
|
||||||
if (!(x)) { Trap(); } \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#define Assert(x) AssertAlways(x)
|
# define Assert(x) AssertAlways(x)
|
||||||
#else
|
#else
|
||||||
#define Assert(x) (void)(x)
|
# define Assert(x) (void)(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define InvalidPath Assert(!"Invalid Path!")
|
#define InvalidPath Assert(!"Invalid Path!")
|
||||||
@@ -151,9 +142,14 @@ typedef double F64;
|
|||||||
|
|
||||||
// Doubly-linked-list (with nil support)
|
// Doubly-linked-list (with nil support)
|
||||||
#define DLLInsert_NPZ(nil, f, l, p, n, next, prev) \
|
#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)) \
|
(CheckNil(nil, f) ? \
|
||||||
: ((p) == (l)) ? ((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) \
|
((f) = (l) = (n), SetNil(nil, (n)->next), SetNil(nil, (n)->prev)) : \
|
||||||
: (((!CheckNil(nil, p) && CheckNil(nil, (p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
|
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 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)
|
#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)
|
// Singly-linked queue (doubly-headed)
|
||||||
#define SLLQueuePush_NZ(nil, f, l, n, next) \
|
#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 SLLQueuePush(f, l, n) SLLQueuePush_NZ(0, f, l, n, next)
|
||||||
#define SLLQueuePushFront(f, l, n) (((n)->next = (f)), ((f) = (n)))
|
#define SLLQueuePushFront(f, l, n) (((n)->next = (f)), ((f) = (n)))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// base_inc.h - Umbrella include for the base layer
|
// base_inc.h - Umbrella include for the base layer
|
||||||
// Include this one header to get all base types.
|
// Include this one header to get all base types.
|
||||||
|
|
||||||
#include "base/base_arena.h"
|
|
||||||
#include "base/base_core.h"
|
#include "base/base_core.h"
|
||||||
|
#include "base/base_arena.h"
|
||||||
#include "base/base_math.h"
|
#include "base/base_math.h"
|
||||||
#include "base/base_strings.h"
|
#include "base/base_strings.h"
|
||||||
|
|||||||
@@ -30,66 +30,51 @@ enum Corner {
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Vector types
|
// Vector types
|
||||||
|
|
||||||
struct Vec2F32 {
|
struct Vec2F32 { F32 x, y; };
|
||||||
F32 x, y;
|
struct Vec2S32 { S32 x, y; };
|
||||||
};
|
struct Vec3F32 { F32 x, y, z; };
|
||||||
struct Vec2S32 {
|
struct Vec4F32 { F32 x, y, z, w; };
|
||||||
S32 x, y;
|
|
||||||
};
|
|
||||||
struct Vec3F32 {
|
|
||||||
F32 x, y, z;
|
|
||||||
};
|
|
||||||
struct Vec4F32 {
|
|
||||||
F32 x, y, z, w;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Range types
|
// Range types
|
||||||
|
|
||||||
struct Rng1F32 {
|
struct Rng1F32 { F32 min, max; };
|
||||||
F32 min, max;
|
struct Rng1S64 { S64 min, max; };
|
||||||
};
|
struct Rng2F32 { Vec2F32 p0, p1; };
|
||||||
struct Rng1S64 {
|
|
||||||
S64 min, max;
|
|
||||||
};
|
|
||||||
struct Rng2F32 {
|
|
||||||
Vec2F32 p0, p1;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
static inline Vec2F32 v2f32(F32 x, F32 y) { return { x, y }; }
|
static inline Vec2F32 v2f32(F32 x, F32 y) { return {x, y}; }
|
||||||
static inline Vec2S32 v2s32(S32 x, S32 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 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 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 Rng1F32 rng1f32(F32 min, F32 max) { return {min, max}; }
|
||||||
static inline Rng1S64 rng1s64(S64 min, S64 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 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 Rng2F32 rng2f32p(F32 x0, F32 y0, F32 x1, F32 y1) { return {{x0, y0}, {x1, y1}}; }
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Vec2F32 operations
|
// Vec2F32 operations
|
||||||
|
|
||||||
static inline Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b) { return { a.x + b.x, a.y + b.y }; }
|
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 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 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 scale_2f32(Vec2F32 v, F32 s) { return {v.x * s, v.y * s}; }
|
||||||
|
|
||||||
// Axis-indexed access
|
// Axis-indexed access
|
||||||
static inline F32 v2f32_axis(Vec2F32 v, Axis2 a) { return a == Axis2_X ? v.x : v.y; }
|
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) {
|
static inline void v2f32_set_axis(Vec2F32 *v, Axis2 a, F32 val) {
|
||||||
if (a == Axis2_X) v->x = val;
|
if (a == Axis2_X) v->x = val; else v->y = val;
|
||||||
else v->y = val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Vec4F32 operations
|
// 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 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 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) {
|
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_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 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_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_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) {
|
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;
|
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) {
|
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) {
|
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) {
|
static inline Rng2F32 rng2f32_intersect(Rng2F32 a, Rng2F32 b) {
|
||||||
return { { Max(a.p0.x, b.p0.x), Max(a.p0.y, b.p0.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) } };
|
{Min(a.p1.x, b.p1.x), Min(a.p1.y, b.p1.y)}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Axis-indexed range dimension
|
// Axis-indexed range dimension
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ Str8 str8_pushf(Arena *arena, const char *fmt, ...) {
|
|||||||
vsnprintf(buf, len + 1, fmt, args2);
|
vsnprintf(buf, len + 1, fmt, args2);
|
||||||
va_end(args2);
|
va_end(args2);
|
||||||
|
|
||||||
return { buf, (U64)len };
|
return {buf, (U64)len};
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 str8_push_copy(Arena *arena, Str8 s) {
|
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);
|
char *buf = push_array_no_zero(arena, char, s.size + 1);
|
||||||
MemoryCopy(buf, s.str, s.size);
|
MemoryCopy(buf, s.str, s.size);
|
||||||
buf[s.size] = 0;
|
buf[s.size] = 0;
|
||||||
return { buf, s.size };
|
return {buf, s.size};
|
||||||
}
|
}
|
||||||
|
|
||||||
void str8_list_push(Arena *arena, Str8List *list, Str8 s) {
|
void str8_list_push(Arena *arena, Str8List *list, Str8 s) {
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ struct Arena;
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
static inline Str8 str8(const char *s, U64 len) { return { s, len }; }
|
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_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_lit(const char *s) { return {s, s ? (U64)strlen(s) : 0}; }
|
||||||
static inline B32 str8_match(Str8 a, Str8 b) {
|
static inline B32 str8_match(Str8 a, Str8 b) {
|
||||||
if (a.size != b.size) return 0;
|
if (a.size != b.size) return 0;
|
||||||
return MemoryCompare(a.str, b.str, a.size) == 0;
|
return MemoryCompare(a.str, b.str, a.size) == 0;
|
||||||
|
|||||||
402
src/main.cpp
402
src/main.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
|||||||
#include "midi/midi.h"
|
#include "midi/midi.h"
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
#include <CoreMIDI/CoreMIDI.h>
|
#include <CoreMIDI/CoreMIDI.h>
|
||||||
#include <stdatomic.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
#define MIDI_MAX_DEVICES 64
|
#define MIDI_MAX_DEVICES 64
|
||||||
#define MIDI_RELEASE_FLASH_DURATION 0.15f
|
#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];
|
const MIDIPacket *packet = &pktlist->packet[0];
|
||||||
for (UInt32 i = 0; i < pktlist->numPackets; i++) {
|
for (UInt32 i = 0; i < pktlist->numPackets; i++) {
|
||||||
// Parse MIDI bytes
|
// Parse MIDI bytes
|
||||||
for (UInt16 j = 0; j < packet->length;) {
|
for (UInt16 j = 0; j < packet->length; ) {
|
||||||
U8 status = packet->data[j];
|
U8 status = packet->data[j];
|
||||||
|
|
||||||
// Skip non-status bytes (running status not handled for simplicity)
|
// Skip non-status bytes (running status not handled for simplicity)
|
||||||
if (status < 0x80) {
|
if (status < 0x80) { j++; continue; }
|
||||||
j++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
U8 kind = status & 0xF0;
|
U8 kind = status & 0xF0;
|
||||||
|
|
||||||
@@ -95,8 +92,7 @@ static void midi_read_callback(const MIDIPacketList *pktlist, void *readProcRefC
|
|||||||
} else if (kind == 0xF0) {
|
} else if (kind == 0xF0) {
|
||||||
// System messages — skip to end or next status byte
|
// System messages — skip to end or next status byte
|
||||||
j++;
|
j++;
|
||||||
while (j < packet->length && packet->data[j] < 0x80)
|
while (j < packet->length && packet->data[j] < 0x80) j++;
|
||||||
j++;
|
|
||||||
} else {
|
} else {
|
||||||
j += 3; // Default: 3-byte message
|
j += 3; // Default: 3-byte message
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "midi/midi.h"
|
#include "midi/midi.h"
|
||||||
|
#include <windows.h>
|
||||||
#include <mmeapi.h>
|
#include <mmeapi.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#define MIDI_MAX_DEVICES 64
|
#define MIDI_MAX_DEVICES 64
|
||||||
#define MIDI_RELEASE_FLASH_DURATION 0.15f
|
#define MIDI_RELEASE_FLASH_DURATION 0.15f
|
||||||
|
|||||||
@@ -4,27 +4,16 @@
|
|||||||
|
|
||||||
// macOS virtual key codes (avoids Carbon.h include)
|
// macOS virtual key codes (avoids Carbon.h include)
|
||||||
enum {
|
enum {
|
||||||
kVK_ANSI_A = 0x00,
|
kVK_ANSI_A = 0x00, kVK_ANSI_C = 0x08, kVK_ANSI_V = 0x09,
|
||||||
kVK_ANSI_C = 0x08,
|
|
||||||
kVK_ANSI_V = 0x09,
|
|
||||||
kVK_ANSI_X = 0x07,
|
kVK_ANSI_X = 0x07,
|
||||||
kVK_Return = 0x24,
|
kVK_Return = 0x24, kVK_Tab = 0x30, kVK_Delete = 0x33,
|
||||||
kVK_Tab = 0x30,
|
kVK_Escape = 0x35, kVK_ForwardDelete = 0x75,
|
||||||
kVK_Delete = 0x33,
|
kVK_LeftArrow = 0x7B, kVK_RightArrow = 0x7C,
|
||||||
kVK_Escape = 0x35,
|
kVK_DownArrow = 0x7D, kVK_UpArrow = 0x7E,
|
||||||
kVK_ForwardDelete = 0x75,
|
kVK_Home = 0x73, kVK_End = 0x77,
|
||||||
kVK_LeftArrow = 0x7B,
|
kVK_Command = 0x37, kVK_Shift = 0x38,
|
||||||
kVK_RightArrow = 0x7C,
|
kVK_RightShift = 0x3C, kVK_RightCommand = 0x36,
|
||||||
kVK_DownArrow = 0x7D,
|
kVK_ANSI_Equal = 0x18, kVK_ANSI_Minus = 0x1B,
|
||||||
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_0 = 0x1D,
|
||||||
kVK_ANSI_KeypadEnter = 0x4C,
|
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_ANSI_KeypadEnter: return PKEY_RETURN;
|
||||||
case kVK_Tab: return PKEY_TAB;
|
case kVK_Tab: return PKEY_TAB;
|
||||||
case kVK_Delete: return PKEY_BACKSPACE;
|
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_Escape: return PKEY_ESCAPE;
|
||||||
case kVK_LeftArrow: return PKEY_LEFT;
|
case kVK_LeftArrow: return PKEY_LEFT;
|
||||||
case kVK_RightArrow: return PKEY_RIGHT;
|
case kVK_RightArrow: return PKEY_RIGHT;
|
||||||
@@ -69,23 +58,18 @@ static PlatformWindow *g_main_window = nullptr;
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation ASmplAppDelegate
|
@implementation ASmplAppDelegate
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
|
- (void)applicationDidFinishLaunching:(NSNotification *)notification { (void)notification; }
|
||||||
(void)notification;
|
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { (void)sender; return YES; }
|
||||||
}
|
|
||||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
|
|
||||||
(void)sender;
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASmplWindowDelegate : NSObject <NSWindowDelegate> {
|
@interface ASmplWindowDelegate : NSObject <NSWindowDelegate> {
|
||||||
@public
|
@public
|
||||||
PlatformWindow *_platformWindow;
|
PlatformWindow *_platformWindow;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASmplView : NSView <NSTextInputClient> {
|
@interface ASmplView : NSView <NSTextInputClient> {
|
||||||
@public
|
@public
|
||||||
PlatformWindow *_platformWindow;
|
PlatformWindow *_platformWindow;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
@@ -117,10 +101,7 @@ static void platform_macos_insert_text_pw(PlatformWindow *pw, const char *utf8)
|
|||||||
PlatformInput *ev = &pw->input;
|
PlatformInput *ev = &pw->input;
|
||||||
while (*utf8 && ev->char_count < PLATFORM_MAX_CHARS_PER_FRAME) {
|
while (*utf8 && ev->char_count < PLATFORM_MAX_CHARS_PER_FRAME) {
|
||||||
U8 c = (U8)*utf8;
|
U8 c = (U8)*utf8;
|
||||||
if (c < 32) {
|
if (c < 32) { utf8++; continue; }
|
||||||
utf8++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Handle ASCII printable range (single-byte UTF-8)
|
// Handle ASCII printable range (single-byte UTF-8)
|
||||||
if (c < 0x80) {
|
if (c < 0x80) {
|
||||||
ev->chars[ev->char_count++] = (U16)c;
|
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
|
@implementation ASmplView
|
||||||
|
|
||||||
- (BOOL)acceptsFirstResponder {
|
- (BOOL)acceptsFirstResponder { return YES; }
|
||||||
return YES;
|
- (BOOL)canBecomeKeyView { return YES; }
|
||||||
}
|
|
||||||
- (BOOL)canBecomeKeyView {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Needed for NSTextInputClient
|
// Needed for NSTextInputClient
|
||||||
- (BOOL)hasMarkedText {
|
- (BOOL)hasMarkedText { return NO; }
|
||||||
return NO;
|
- (NSRange)markedRange { return NSMakeRange(NSNotFound, 0); }
|
||||||
}
|
- (NSRange)selectedRange { return NSMakeRange(NSNotFound, 0); }
|
||||||
- (NSRange)markedRange {
|
|
||||||
return NSMakeRange(NSNotFound, 0);
|
|
||||||
}
|
|
||||||
- (NSRange)selectedRange {
|
|
||||||
return NSMakeRange(NSNotFound, 0);
|
|
||||||
}
|
|
||||||
- (void)setMarkedText:(id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange {
|
- (void)setMarkedText:(id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange {
|
||||||
(void)string;
|
(void)string; (void)selectedRange; (void)replacementRange;
|
||||||
(void)selectedRange;
|
|
||||||
(void)replacementRange;
|
|
||||||
}
|
|
||||||
- (void)unmarkText {
|
|
||||||
}
|
|
||||||
- (NSArray<NSAttributedStringKey> *)validAttributesForMarkedText {
|
|
||||||
return @[];
|
|
||||||
}
|
}
|
||||||
|
- (void)unmarkText {}
|
||||||
|
- (NSArray<NSAttributedStringKey> *)validAttributesForMarkedText { return @[]; }
|
||||||
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
|
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
|
||||||
(void)range;
|
(void)range; (void)actualRange;
|
||||||
(void)actualRange;
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
- (NSUInteger)characterIndexForPoint:(NSPoint)point {
|
- (NSUInteger)characterIndexForPoint:(NSPoint)point { (void)point; return NSNotFound; }
|
||||||
(void)point;
|
|
||||||
return NSNotFound;
|
|
||||||
}
|
|
||||||
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
|
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
|
||||||
(void)range;
|
(void)range; (void)actualRange;
|
||||||
(void)actualRange;
|
|
||||||
return NSZeroRect;
|
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]);
|
platform_macos_key_down_pw(_platformWindow, [event keyCode], [event modifierFlags]);
|
||||||
|
|
||||||
// Feed into text input system for character generation
|
// Feed into text input system for character generation
|
||||||
[self interpretKeyEvents:@[ event ]];
|
[self interpretKeyEvents:@[event]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)flagsChanged:(NSEvent *)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;
|
if (_platformWindow) _platformWindow->mouse_down_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseMoved:(NSEvent *)event {
|
- (void)mouseMoved:(NSEvent *)event { (void)event; }
|
||||||
(void)event;
|
- (void)mouseDragged:(NSEvent *)event { (void)event; }
|
||||||
}
|
|
||||||
- (void)mouseDragged:(NSEvent *)event {
|
|
||||||
(void)event;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)scrollWheel:(NSEvent *)event {
|
- (void)scrollWheel:(NSEvent *)event {
|
||||||
if (!_platformWindow) return;
|
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;
|
_platformWindow->input.scroll_delta.y += dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)acceptsFirstMouse:(NSEvent *)event {
|
- (BOOL)acceptsFirstMouse:(NSEvent *)event { (void)event; return YES; }
|
||||||
(void)event;
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
#include <malloc.h>
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
struct PlatformWindow {
|
struct PlatformWindow {
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
@@ -143,7 +143,8 @@ PlatformWindow *platform_create_window(PlatformWindowDesc *desc) {
|
|||||||
x, y,
|
x, y,
|
||||||
rect.right - rect.left,
|
rect.right - rect.left,
|
||||||
rect.bottom - rect.top,
|
rect.bottom - rect.top,
|
||||||
parent_hwnd, nullptr, GetModuleHandleW(nullptr), nullptr);
|
parent_hwnd, nullptr, GetModuleHandleW(nullptr), nullptr
|
||||||
|
);
|
||||||
|
|
||||||
_freea(wtitle);
|
_freea(wtitle);
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
#include "renderer/font_inter.gen.h"
|
#include "renderer/font_inter.gen.h"
|
||||||
|
|
||||||
// Embedded SPIR-V shaders (generated at build time by glslc)
|
// 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_vert.spv.h"
|
||||||
|
#include "renderer/ui_frag.spv.h"
|
||||||
|
|
||||||
#define NUM_BACK_BUFFERS 2
|
#define NUM_BACK_BUFFERS 2
|
||||||
#define MAX_VERTICES (64 * 1024)
|
#define MAX_VERTICES (64 * 1024)
|
||||||
@@ -172,9 +172,9 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(
|
|||||||
VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
||||||
VkDebugUtilsMessageTypeFlagsEXT type,
|
VkDebugUtilsMessageTypeFlagsEXT type,
|
||||||
const VkDebugUtilsMessengerCallbackDataEXT *data,
|
const VkDebugUtilsMessengerCallbackDataEXT *data,
|
||||||
void *user_data) {
|
void *user_data)
|
||||||
(void)type;
|
{
|
||||||
(void)user_data;
|
(void)type; (void)user_data;
|
||||||
if (severity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
|
if (severity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
|
||||||
OutputDebugStringA("VK: ");
|
OutputDebugStringA("VK: ");
|
||||||
OutputDebugStringA(data->pMessage);
|
OutputDebugStringA(data->pMessage);
|
||||||
@@ -188,7 +188,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(
|
|||||||
// Helper: begin/end one-shot command buffer
|
// Helper: begin/end one-shot command buffer
|
||||||
|
|
||||||
static VkCommandBuffer begin_one_shot(Renderer *r) {
|
static VkCommandBuffer begin_one_shot(Renderer *r) {
|
||||||
VkCommandBufferAllocateInfo ai = { 0 };
|
VkCommandBufferAllocateInfo ai = {0};
|
||||||
ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
ai.commandPool = r->command_pool;
|
ai.commandPool = r->command_pool;
|
||||||
ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
@@ -196,7 +196,7 @@ static VkCommandBuffer begin_one_shot(Renderer *r) {
|
|||||||
VkCommandBuffer cb;
|
VkCommandBuffer cb;
|
||||||
vkAllocateCommandBuffers(r->device, &ai, &cb);
|
vkAllocateCommandBuffers(r->device, &ai, &cb);
|
||||||
|
|
||||||
VkCommandBufferBeginInfo bi = { 0 };
|
VkCommandBufferBeginInfo bi = {0};
|
||||||
bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
vkBeginCommandBuffer(cb, &bi);
|
vkBeginCommandBuffer(cb, &bi);
|
||||||
@@ -205,7 +205,7 @@ static VkCommandBuffer begin_one_shot(Renderer *r) {
|
|||||||
|
|
||||||
static void end_one_shot(Renderer *r, VkCommandBuffer cb) {
|
static void end_one_shot(Renderer *r, VkCommandBuffer cb) {
|
||||||
vkEndCommandBuffer(cb);
|
vkEndCommandBuffer(cb);
|
||||||
VkSubmitInfo si = { 0 };
|
VkSubmitInfo si = {0};
|
||||||
si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
si.commandBufferCount = 1;
|
si.commandBufferCount = 1;
|
||||||
si.pCommandBuffers = &cb;
|
si.pCommandBuffers = &cb;
|
||||||
@@ -220,8 +220,9 @@ static void end_one_shot(Renderer *r, VkCommandBuffer cb) {
|
|||||||
static void transition_image(VkCommandBuffer cb, VkImage image,
|
static void transition_image(VkCommandBuffer cb, VkImage image,
|
||||||
VkImageLayout old_layout, VkImageLayout new_layout,
|
VkImageLayout old_layout, VkImageLayout new_layout,
|
||||||
VkAccessFlags src_access, VkAccessFlags dst_access,
|
VkAccessFlags src_access, VkAccessFlags dst_access,
|
||||||
VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage) {
|
VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage)
|
||||||
VkImageMemoryBarrier barrier = { 0 };
|
{
|
||||||
|
VkImageMemoryBarrier barrier = {0};
|
||||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
barrier.oldLayout = old_layout;
|
barrier.oldLayout = old_layout;
|
||||||
barrier.newLayout = new_layout;
|
barrier.newLayout = new_layout;
|
||||||
@@ -242,7 +243,7 @@ static void transition_image(VkCommandBuffer cb, VkImage image,
|
|||||||
// Vulkan infrastructure
|
// Vulkan infrastructure
|
||||||
|
|
||||||
static B32 create_instance(Renderer *r) {
|
static B32 create_instance(Renderer *r) {
|
||||||
VkApplicationInfo app_info = { 0 };
|
VkApplicationInfo app_info = {0};
|
||||||
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
app_info.pApplicationName = "autosample";
|
app_info.pApplicationName = "autosample";
|
||||||
app_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
|
app_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
|
||||||
@@ -264,7 +265,7 @@ static B32 create_instance(Renderer *r) {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
VkInstanceCreateInfo ci = { 0 };
|
VkInstanceCreateInfo ci = {0};
|
||||||
ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
ci.pApplicationInfo = &app_info;
|
ci.pApplicationInfo = &app_info;
|
||||||
ci.enabledExtensionCount = ArrayCount(extensions);
|
ci.enabledExtensionCount = ArrayCount(extensions);
|
||||||
@@ -277,10 +278,13 @@ static B32 create_instance(Renderer *r) {
|
|||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
{
|
{
|
||||||
VkDebugUtilsMessengerCreateInfoEXT dbg = { 0 };
|
VkDebugUtilsMessengerCreateInfoEXT dbg = {0};
|
||||||
dbg.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
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.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_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;
|
| 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;
|
dbg.pfnUserCallback = vk_debug_callback;
|
||||||
|
|
||||||
PFN_vkCreateDebugUtilsMessengerEXT func =
|
PFN_vkCreateDebugUtilsMessengerEXT func =
|
||||||
@@ -293,7 +297,7 @@ static B32 create_instance(Renderer *r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static B32 create_surface(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.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||||
ci.hinstance = GetModuleHandle(NULL);
|
ci.hinstance = GetModuleHandle(NULL);
|
||||||
ci.hwnd = r->hwnd;
|
ci.hwnd = r->hwnd;
|
||||||
@@ -342,7 +346,7 @@ static B32 find_queue_family(Renderer *r) {
|
|||||||
|
|
||||||
static B32 create_device(Renderer *r) {
|
static B32 create_device(Renderer *r) {
|
||||||
float priority = 1.0f;
|
float priority = 1.0f;
|
||||||
VkDeviceQueueCreateInfo queue_ci = { 0 };
|
VkDeviceQueueCreateInfo queue_ci = {0};
|
||||||
queue_ci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
queue_ci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
queue_ci.queueFamilyIndex = r->queue_family;
|
queue_ci.queueFamilyIndex = r->queue_family;
|
||||||
queue_ci.queueCount = 1;
|
queue_ci.queueCount = 1;
|
||||||
@@ -350,7 +354,7 @@ static B32 create_device(Renderer *r) {
|
|||||||
|
|
||||||
const char *extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
const char *extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
||||||
|
|
||||||
VkDeviceCreateInfo ci = { 0 };
|
VkDeviceCreateInfo ci = {0};
|
||||||
ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
ci.queueCreateInfoCount = 1;
|
ci.queueCreateInfoCount = 1;
|
||||||
ci.pQueueCreateInfos = &queue_ci;
|
ci.pQueueCreateInfos = &queue_ci;
|
||||||
@@ -365,7 +369,7 @@ static B32 create_device(Renderer *r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static B32 create_vma(Renderer *r) {
|
static B32 create_vma(Renderer *r) {
|
||||||
VmaAllocatorCreateInfo ci = { 0 };
|
VmaAllocatorCreateInfo ci = {0};
|
||||||
ci.physicalDevice = r->physical_device;
|
ci.physicalDevice = r->physical_device;
|
||||||
ci.device = r->device;
|
ci.device = r->device;
|
||||||
ci.instance = r->instance;
|
ci.instance = r->instance;
|
||||||
@@ -422,7 +426,7 @@ static B32 create_swap_chain(Renderer *r) {
|
|||||||
if (caps.maxImageCount > 0 && image_count > caps.maxImageCount)
|
if (caps.maxImageCount > 0 && image_count > caps.maxImageCount)
|
||||||
image_count = caps.maxImageCount;
|
image_count = caps.maxImageCount;
|
||||||
|
|
||||||
VkSwapchainCreateInfoKHR ci = { 0 };
|
VkSwapchainCreateInfoKHR ci = {0};
|
||||||
ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
ci.surface = r->surface;
|
ci.surface = r->surface;
|
||||||
ci.minImageCount = image_count;
|
ci.minImageCount = image_count;
|
||||||
@@ -447,7 +451,7 @@ static B32 create_swap_chain(Renderer *r) {
|
|||||||
|
|
||||||
// Create image views
|
// Create image views
|
||||||
for (U32 i = 0; i < NUM_BACK_BUFFERS; i++) {
|
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.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
vi.image = r->swap_chain_images[i];
|
vi.image = r->swap_chain_images[i];
|
||||||
vi.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
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) {
|
static B32 create_render_pass(Renderer *r) {
|
||||||
VkAttachmentDescription color_attach = { 0 };
|
VkAttachmentDescription color_attach = {0};
|
||||||
color_attach.format = r->swap_chain_format;
|
color_attach.format = r->swap_chain_format;
|
||||||
color_attach.samples = VK_SAMPLE_COUNT_1_BIT;
|
color_attach.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
color_attach.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
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.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
color_attach.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
color_attach.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
|
|
||||||
VkAttachmentReference color_ref = { 0 };
|
VkAttachmentReference color_ref = {0};
|
||||||
color_ref.attachment = 0;
|
color_ref.attachment = 0;
|
||||||
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
VkSubpassDescription subpass = { 0 };
|
VkSubpassDescription subpass = {0};
|
||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
subpass.colorAttachmentCount = 1;
|
subpass.colorAttachmentCount = 1;
|
||||||
subpass.pColorAttachments = &color_ref;
|
subpass.pColorAttachments = &color_ref;
|
||||||
|
|
||||||
VkSubpassDependency dep = { 0 };
|
VkSubpassDependency dep = {0};
|
||||||
dep.srcSubpass = VK_SUBPASS_EXTERNAL;
|
dep.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
dep.dstSubpass = 0;
|
dep.dstSubpass = 0;
|
||||||
dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
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.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_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.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
ci.attachmentCount = 1;
|
ci.attachmentCount = 1;
|
||||||
ci.pAttachments = &color_attach;
|
ci.pAttachments = &color_attach;
|
||||||
@@ -506,7 +510,7 @@ static B32 create_render_pass(Renderer *r) {
|
|||||||
|
|
||||||
static B32 create_framebuffers(Renderer *r) {
|
static B32 create_framebuffers(Renderer *r) {
|
||||||
for (U32 i = 0; i < NUM_BACK_BUFFERS; i++) {
|
for (U32 i = 0; i < NUM_BACK_BUFFERS; i++) {
|
||||||
VkFramebufferCreateInfo ci = { 0 };
|
VkFramebufferCreateInfo ci = {0};
|
||||||
ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
ci.renderPass = r->render_pass;
|
ci.renderPass = r->render_pass;
|
||||||
ci.attachmentCount = 1;
|
ci.attachmentCount = 1;
|
||||||
@@ -521,14 +525,14 @@ static B32 create_framebuffers(Renderer *r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static B32 create_command_resources(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.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
pool_ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
pool_ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||||
pool_ci.queueFamilyIndex = r->queue_family;
|
pool_ci.queueFamilyIndex = r->queue_family;
|
||||||
if (vkCreateCommandPool(r->device, &pool_ci, NULL, &r->command_pool) != VK_SUCCESS)
|
if (vkCreateCommandPool(r->device, &pool_ci, NULL, &r->command_pool) != VK_SUCCESS)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo alloc_info = { 0 };
|
VkCommandBufferAllocateInfo alloc_info = {0};
|
||||||
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
alloc_info.commandPool = r->command_pool;
|
alloc_info.commandPool = r->command_pool;
|
||||||
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
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++) {
|
for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) {
|
||||||
r->frames[i].command_buffer = cbs[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.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
fence_ci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
fence_ci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
if (vkCreateFence(r->device, &fence_ci, NULL, &r->frames[i].fence) != VK_SUCCESS)
|
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++) {
|
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;
|
sem_ci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
if (vkCreateSemaphore(r->device, &sem_ci, NULL, &r->image_available_sema[i]) != VK_SUCCESS)
|
if (vkCreateSemaphore(r->device, &sem_ci, NULL, &r->image_available_sema[i]) != VK_SUCCESS)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -561,7 +565,7 @@ static B32 create_command_resources(Renderer *r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static B32 create_sampler(Renderer *r) {
|
static B32 create_sampler(Renderer *r) {
|
||||||
VkSamplerCreateInfo ci = { 0 };
|
VkSamplerCreateInfo ci = {0};
|
||||||
ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||||
ci.magFilter = VK_FILTER_LINEAR;
|
ci.magFilter = VK_FILTER_LINEAR;
|
||||||
ci.minFilter = 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) {
|
static B32 create_descriptor_resources(Renderer *r) {
|
||||||
// Descriptor set layout: single combined image sampler at binding 0
|
// Descriptor set layout: single combined image sampler at binding 0
|
||||||
VkDescriptorSetLayoutBinding binding = { 0 };
|
VkDescriptorSetLayoutBinding binding = {0};
|
||||||
binding.binding = 0;
|
binding.binding = 0;
|
||||||
binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
binding.descriptorCount = 1;
|
binding.descriptorCount = 1;
|
||||||
binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
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.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||||
layout_ci.bindingCount = 1;
|
layout_ci.bindingCount = 1;
|
||||||
layout_ci.pBindings = &binding;
|
layout_ci.pBindings = &binding;
|
||||||
@@ -588,11 +592,11 @@ static B32 create_descriptor_resources(Renderer *r) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Descriptor pool: 2 sets (font + icon)
|
// 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.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
pool_size.descriptorCount = 2;
|
pool_size.descriptorCount = 2;
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo pool_ci = { 0 };
|
VkDescriptorPoolCreateInfo pool_ci = {0};
|
||||||
pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
pool_ci.maxSets = 2;
|
pool_ci.maxSets = 2;
|
||||||
pool_ci.poolSizeCount = 1;
|
pool_ci.poolSizeCount = 1;
|
||||||
@@ -601,7 +605,7 @@ static B32 create_descriptor_resources(Renderer *r) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Allocate font descriptor set
|
// Allocate font descriptor set
|
||||||
VkDescriptorSetAllocateInfo alloc_info = { 0 };
|
VkDescriptorSetAllocateInfo alloc_info = {0};
|
||||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
alloc_info.descriptorPool = r->descriptor_pool;
|
alloc_info.descriptorPool = r->descriptor_pool;
|
||||||
alloc_info.descriptorSetCount = 1;
|
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) {
|
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.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
ci.codeSize = size;
|
ci.codeSize = size;
|
||||||
ci.pCode = code;
|
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));
|
VkShaderModule frag_module = create_shader_module(r, ui_frag_spv, sizeof(ui_frag_spv));
|
||||||
if (!vert_module || !frag_module) return 0;
|
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].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
stages[0].module = vert_module;
|
stages[0].module = vert_module;
|
||||||
@@ -638,84 +642,57 @@ static B32 create_pipeline(Renderer *r) {
|
|||||||
stages[1].pName = "main";
|
stages[1].pName = "main";
|
||||||
|
|
||||||
// Vertex input
|
// Vertex input
|
||||||
VkVertexInputBindingDescription binding = { 0 };
|
VkVertexInputBindingDescription binding = {0};
|
||||||
binding.binding = 0;
|
binding.binding = 0;
|
||||||
binding.stride = sizeof(UIVertex);
|
binding.stride = sizeof(UIVertex);
|
||||||
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
|
||||||
VkVertexInputAttributeDescription attrs[9] = {};
|
VkVertexInputAttributeDescription attrs[9] = {};
|
||||||
attrs[0].location = 0;
|
attrs[0].location = 0; attrs[0].binding = 0; attrs[0].format = VK_FORMAT_R32G32_SFLOAT; attrs[0].offset = offsetof(UIVertex, pos);
|
||||||
attrs[0].binding = 0;
|
attrs[1].location = 1; attrs[1].binding = 0; attrs[1].format = VK_FORMAT_R32G32_SFLOAT; attrs[1].offset = offsetof(UIVertex, uv);
|
||||||
attrs[0].format = VK_FORMAT_R32G32_SFLOAT;
|
attrs[2].location = 2; attrs[2].binding = 0; attrs[2].format = VK_FORMAT_R32G32B32A32_SFLOAT; attrs[2].offset = offsetof(UIVertex, col);
|
||||||
attrs[0].offset = offsetof(UIVertex, pos);
|
attrs[3].location = 3; attrs[3].binding = 0; attrs[3].format = VK_FORMAT_R32G32_SFLOAT; attrs[3].offset = offsetof(UIVertex, rect_min);
|
||||||
attrs[1].location = 1;
|
attrs[4].location = 4; attrs[4].binding = 0; attrs[4].format = VK_FORMAT_R32G32_SFLOAT; attrs[4].offset = offsetof(UIVertex, rect_max);
|
||||||
attrs[1].binding = 0;
|
attrs[5].location = 5; attrs[5].binding = 0; attrs[5].format = VK_FORMAT_R32G32B32A32_SFLOAT; attrs[5].offset = offsetof(UIVertex, corner_radii);
|
||||||
attrs[1].format = VK_FORMAT_R32G32_SFLOAT;
|
attrs[6].location = 6; attrs[6].binding = 0; attrs[6].format = VK_FORMAT_R32_SFLOAT; attrs[6].offset = offsetof(UIVertex, border_thickness);
|
||||||
attrs[1].offset = offsetof(UIVertex, uv);
|
attrs[7].location = 7; attrs[7].binding = 0; attrs[7].format = VK_FORMAT_R32_SFLOAT; attrs[7].offset = offsetof(UIVertex, softness);
|
||||||
attrs[2].location = 2;
|
attrs[8].location = 8; attrs[8].binding = 0; attrs[8].format = VK_FORMAT_R32_SFLOAT; attrs[8].offset = offsetof(UIVertex, mode);
|
||||||
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.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
vertex_input.vertexBindingDescriptionCount = 1;
|
vertex_input.vertexBindingDescriptionCount = 1;
|
||||||
vertex_input.pVertexBindingDescriptions = &binding;
|
vertex_input.pVertexBindingDescriptions = &binding;
|
||||||
vertex_input.vertexAttributeDescriptionCount = 9;
|
vertex_input.vertexAttributeDescriptionCount = 9;
|
||||||
vertex_input.pVertexAttributeDescriptions = attrs;
|
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.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
|
||||||
// Dynamic viewport/scissor
|
// Dynamic viewport/scissor
|
||||||
VkDynamicState dynamic_states[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_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.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
dynamic_state.dynamicStateCount = 2;
|
dynamic_state.dynamicStateCount = 2;
|
||||||
dynamic_state.pDynamicStates = dynamic_states;
|
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.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
viewport_state.viewportCount = 1;
|
viewport_state.viewportCount = 1;
|
||||||
viewport_state.scissorCount = 1;
|
viewport_state.scissorCount = 1;
|
||||||
|
|
||||||
VkPipelineRasterizationStateCreateInfo rasterizer = { 0 };
|
VkPipelineRasterizationStateCreateInfo rasterizer = {0};
|
||||||
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
rasterizer.lineWidth = 1.0f;
|
rasterizer.lineWidth = 1.0f;
|
||||||
rasterizer.cullMode = VK_CULL_MODE_NONE;
|
rasterizer.cullMode = VK_CULL_MODE_NONE;
|
||||||
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||||
|
|
||||||
VkPipelineMultisampleStateCreateInfo multisample = { 0 };
|
VkPipelineMultisampleStateCreateInfo multisample = {0};
|
||||||
multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState blend_attach = { 0 };
|
VkPipelineColorBlendAttachmentState blend_attach = {0};
|
||||||
blend_attach.blendEnable = VK_TRUE;
|
blend_attach.blendEnable = VK_TRUE;
|
||||||
blend_attach.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
blend_attach.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
blend_attach.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_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.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||||
blend_attach.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
blend_attach.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
blend_attach.alphaBlendOp = VK_BLEND_OP_ADD;
|
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.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||||
blend.attachmentCount = 1;
|
blend.attachmentCount = 1;
|
||||||
blend.pAttachments = &blend_attach;
|
blend.pAttachments = &blend_attach;
|
||||||
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depth_stencil = { 0 };
|
VkPipelineDepthStencilStateCreateInfo depth_stencil = {0};
|
||||||
depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||||
|
|
||||||
// Pipeline layout: push constants + 1 descriptor set
|
// 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.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
push_range.offset = 0;
|
push_range.offset = 0;
|
||||||
push_range.size = 4 * sizeof(float); // viewport_size + padding
|
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.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
layout_ci.setLayoutCount = 1;
|
layout_ci.setLayoutCount = 1;
|
||||||
layout_ci.pSetLayouts = &r->descriptor_set_layout;
|
layout_ci.pSetLayouts = &r->descriptor_set_layout;
|
||||||
@@ -751,7 +729,7 @@ static B32 create_pipeline(Renderer *r) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipeline_ci = { 0 };
|
VkGraphicsPipelineCreateInfo pipeline_ci = {0};
|
||||||
pipeline_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
pipeline_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
pipeline_ci.stageCount = 2;
|
pipeline_ci.stageCount = 2;
|
||||||
pipeline_ci.pStages = stages;
|
pipeline_ci.pStages = stages;
|
||||||
@@ -777,12 +755,12 @@ static B32 create_pipeline(Renderer *r) {
|
|||||||
|
|
||||||
static B32 create_ui_buffers(Renderer *r) {
|
static B32 create_ui_buffers(Renderer *r) {
|
||||||
for (S32 i = 0; i < NUM_BACK_BUFFERS; i++) {
|
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.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
buf_ci.size = MAX_VERTICES * sizeof(UIVertex);
|
buf_ci.size = MAX_VERTICES * sizeof(UIVertex);
|
||||||
buf_ci.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
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.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
|
||||||
alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
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
|
// Helper: update a descriptor set to point to an image view
|
||||||
|
|
||||||
static void update_descriptor_set(Renderer *r, VkDescriptorSet set, VkImageView 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.sampler = r->sampler;
|
||||||
img_info.imageView = view;
|
img_info.imageView = view;
|
||||||
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
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.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
write.dstSet = set;
|
write.dstSet = set;
|
||||||
write.dstBinding = 0;
|
write.dstBinding = 0;
|
||||||
@@ -884,7 +862,7 @@ static B32 create_font_atlas(Renderer *r, F32 font_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create Vulkan image
|
// Create Vulkan image
|
||||||
VkImageCreateInfo img_ci = { 0 };
|
VkImageCreateInfo img_ci = {0};
|
||||||
img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
img_ci.imageType = VK_IMAGE_TYPE_2D;
|
img_ci.imageType = VK_IMAGE_TYPE_2D;
|
||||||
img_ci.format = VK_FORMAT_R8_UNORM;
|
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.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
img_ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
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;
|
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) {
|
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
|
// Staging buffer
|
||||||
VkBufferCreateInfo staging_ci = { 0 };
|
VkBufferCreateInfo staging_ci = {0};
|
||||||
staging_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
staging_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
staging_ci.size = FONT_ATLAS_W * FONT_ATLAS_H;
|
staging_ci.size = FONT_ATLAS_W * FONT_ATLAS_H;
|
||||||
staging_ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
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.usage = VMA_MEMORY_USAGE_CPU_ONLY;
|
||||||
staging_alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
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,
|
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_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.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
region.imageSubresource.layerCount = 1;
|
region.imageSubresource.layerCount = 1;
|
||||||
region.imageExtent.width = FONT_ATLAS_W;
|
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);
|
vmaDestroyBuffer(r->allocator, staging_buf, staging_alloc);
|
||||||
|
|
||||||
// Image view
|
// Image view
|
||||||
VkImageViewCreateInfo view_ci = { 0 };
|
VkImageViewCreateInfo view_ci = {0};
|
||||||
view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
view_ci.image = r->font_image;
|
view_ci.image = r->font_image;
|
||||||
view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
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 cr, F32 cg, F32 cb, F32 ca,
|
||||||
F32 rmin_x, F32 rmin_y, F32 rmax_x, F32 rmax_y,
|
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 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)
|
if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1009,54 +988,28 @@ static void emit_quad(DrawBatch *batch,
|
|||||||
F32 px0 = x0, py0 = y0, px1 = x1, py1 = y1;
|
F32 px0 = x0, py0 = y0, px1 = x1, py1 = y1;
|
||||||
if (mode < 0.5f) {
|
if (mode < 0.5f) {
|
||||||
F32 pad = softness + 1.0f;
|
F32 pad = softness + 1.0f;
|
||||||
px0 -= pad;
|
px0 -= pad; py0 -= pad; px1 += pad; py1 += pad;
|
||||||
py0 -= pad;
|
|
||||||
px1 += pad;
|
|
||||||
py1 += pad;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v[0].pos[0] = px0;
|
v[0].pos[0] = px0; v[0].pos[1] = py0; v[0].uv[0] = u0; v[0].uv[1] = v0;
|
||||||
v[0].pos[1] = py0;
|
v[1].pos[0] = px1; v[1].pos[1] = py0; v[1].uv[0] = u1; v[1].uv[1] = v0;
|
||||||
v[0].uv[0] = u0;
|
v[2].pos[0] = px1; v[2].pos[1] = py1; v[2].uv[0] = u1; v[2].uv[1] = v1;
|
||||||
v[0].uv[1] = v0;
|
v[3].pos[0] = px0; v[3].pos[1] = py1; v[3].uv[0] = u0; v[3].uv[1] = v1;
|
||||||
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++) {
|
for (S32 i = 0; i < 4; i++) {
|
||||||
v[i].col[0] = cr;
|
v[i].col[0] = cr; v[i].col[1] = cg; v[i].col[2] = cb; v[i].col[3] = ca;
|
||||||
v[i].col[1] = cg;
|
v[i].rect_min[0] = rmin_x; v[i].rect_min[1] = rmin_y;
|
||||||
v[i].col[2] = cb;
|
v[i].rect_max[0] = rmax_x; v[i].rect_max[1] = rmax_y;
|
||||||
v[i].col[3] = ca;
|
v[i].corner_radii[0] = cr_tl; v[i].corner_radii[1] = cr_tr;
|
||||||
v[i].rect_min[0] = rmin_x;
|
v[i].corner_radii[2] = cr_br; v[i].corner_radii[3] = cr_bl;
|
||||||
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].border_thickness = border_thickness;
|
||||||
v[i].softness = softness;
|
v[i].softness = softness;
|
||||||
v[i].mode = mode;
|
v[i].mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 *idx = &batch->indices[batch->index_count];
|
U32 *idx = &batch->indices[batch->index_count];
|
||||||
idx[0] = base;
|
idx[0] = base; idx[1] = base + 1; idx[2] = base + 2;
|
||||||
idx[1] = base + 1;
|
idx[3] = base; idx[4] = base + 2; idx[5] = base + 3;
|
||||||
idx[2] = base + 2;
|
|
||||||
idx[3] = base;
|
|
||||||
idx[4] = base + 2;
|
|
||||||
idx[5] = base + 3;
|
|
||||||
|
|
||||||
batch->vertex_count += 4;
|
batch->vertex_count += 4;
|
||||||
batch->index_count += 6;
|
batch->index_count += 6;
|
||||||
@@ -1066,7 +1019,8 @@ static void emit_quad_rotated(DrawBatch *batch,
|
|||||||
F32 x0, F32 y0, F32 x1, F32 y1,
|
F32 x0, F32 y0, F32 x1, F32 y1,
|
||||||
F32 u0, F32 v0, F32 u1, F32 v1,
|
F32 u0, F32 v0, F32 u1, F32 v1,
|
||||||
F32 cr, F32 cg, F32 cb, F32 ca,
|
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)
|
if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1083,49 +1037,34 @@ static void emit_quad_rotated(DrawBatch *batch,
|
|||||||
|
|
||||||
v[0].pos[0] = cx + dx0 * cosA - dy0 * sinA;
|
v[0].pos[0] = cx + dx0 * cosA - dy0 * sinA;
|
||||||
v[0].pos[1] = cy + dx0 * sinA + dy0 * cosA;
|
v[0].pos[1] = cy + dx0 * sinA + dy0 * cosA;
|
||||||
v[0].uv[0] = u0;
|
v[0].uv[0] = u0; v[0].uv[1] = v0;
|
||||||
v[0].uv[1] = v0;
|
|
||||||
|
|
||||||
v[1].pos[0] = cx + dx1 * cosA - dy0 * sinA;
|
v[1].pos[0] = cx + dx1 * cosA - dy0 * sinA;
|
||||||
v[1].pos[1] = cy + dx1 * sinA + dy0 * cosA;
|
v[1].pos[1] = cy + dx1 * sinA + dy0 * cosA;
|
||||||
v[1].uv[0] = u1;
|
v[1].uv[0] = u1; v[1].uv[1] = v0;
|
||||||
v[1].uv[1] = v0;
|
|
||||||
|
|
||||||
v[2].pos[0] = cx + dx1 * cosA - dy1 * sinA;
|
v[2].pos[0] = cx + dx1 * cosA - dy1 * sinA;
|
||||||
v[2].pos[1] = cy + dx1 * sinA + dy1 * cosA;
|
v[2].pos[1] = cy + dx1 * sinA + dy1 * cosA;
|
||||||
v[2].uv[0] = u1;
|
v[2].uv[0] = u1; v[2].uv[1] = v1;
|
||||||
v[2].uv[1] = v1;
|
|
||||||
|
|
||||||
v[3].pos[0] = cx + dx0 * cosA - dy1 * sinA;
|
v[3].pos[0] = cx + dx0 * cosA - dy1 * sinA;
|
||||||
v[3].pos[1] = cy + dx0 * sinA + dy1 * cosA;
|
v[3].pos[1] = cy + dx0 * sinA + dy1 * cosA;
|
||||||
v[3].uv[0] = u0;
|
v[3].uv[0] = u0; v[3].uv[1] = v1;
|
||||||
v[3].uv[1] = v1;
|
|
||||||
|
|
||||||
for (S32 i = 0; i < 4; i++) {
|
for (S32 i = 0; i < 4; i++) {
|
||||||
v[i].col[0] = cr;
|
v[i].col[0] = cr; v[i].col[1] = cg; v[i].col[2] = cb; v[i].col[3] = ca;
|
||||||
v[i].col[1] = cg;
|
v[i].rect_min[0] = 0; v[i].rect_min[1] = 0;
|
||||||
v[i].col[2] = cb;
|
v[i].rect_max[0] = 0; v[i].rect_max[1] = 0;
|
||||||
v[i].col[3] = ca;
|
v[i].corner_radii[0] = 0; v[i].corner_radii[1] = 0;
|
||||||
v[i].rect_min[0] = 0;
|
v[i].corner_radii[2] = 0; v[i].corner_radii[3] = 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].border_thickness = 0;
|
||||||
v[i].softness = 0;
|
v[i].softness = 0;
|
||||||
v[i].mode = 2.0f;
|
v[i].mode = 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 *idx = &batch->indices[batch->index_count];
|
U32 *idx = &batch->indices[batch->index_count];
|
||||||
idx[0] = base;
|
idx[0] = base; idx[1] = base + 1; idx[2] = base + 2;
|
||||||
idx[1] = base + 1;
|
idx[3] = base; idx[4] = base + 2; idx[5] = base + 3;
|
||||||
idx[2] = base + 2;
|
|
||||||
idx[3] = base;
|
|
||||||
idx[4] = base + 2;
|
|
||||||
idx[5] = base + 3;
|
|
||||||
|
|
||||||
batch->vertex_count += 4;
|
batch->vertex_count += 4;
|
||||||
batch->index_count += 6;
|
batch->index_count += 6;
|
||||||
@@ -1135,7 +1074,8 @@ static void emit_rect(DrawBatch *batch,
|
|||||||
F32 x0, F32 y0, F32 x1, F32 y1,
|
F32 x0, F32 y0, F32 x1, F32 y1,
|
||||||
F32 cr, F32 cg, F32 cb, F32 ca,
|
F32 cr, F32 cg, F32 cb, F32 ca,
|
||||||
F32 cr_tl, F32 cr_tr, F32 cr_br, F32 cr_bl,
|
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,
|
emit_quad(batch, x0, y0, x1, y1,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
cr, cg, cb, ca,
|
cr, cg, cb, ca,
|
||||||
@@ -1149,7 +1089,8 @@ static void emit_rect_vgradient(DrawBatch *batch,
|
|||||||
F32 tr, F32 tg, F32 tb, F32 ta,
|
F32 tr, F32 tg, F32 tb, F32 ta,
|
||||||
F32 br, F32 bg, F32 bb_, F32 ba,
|
F32 br, F32 bg, F32 bb_, F32 ba,
|
||||||
F32 cr_tl, F32 cr_tr, F32 cr_br, F32 cr_bl,
|
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)
|
if (batch->vertex_count + 4 > MAX_VERTICES || batch->index_count + 6 > MAX_INDICES)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1159,61 +1100,29 @@ static void emit_rect_vgradient(DrawBatch *batch,
|
|||||||
F32 pad = softness + 1.0f;
|
F32 pad = softness + 1.0f;
|
||||||
F32 px0 = x0 - pad, py0 = y0 - pad, px1 = x1 + pad, py1 = y1 + pad;
|
F32 px0 = x0 - pad, py0 = y0 - pad, px1 = x1 + pad, py1 = y1 + pad;
|
||||||
|
|
||||||
v[0].pos[0] = px0;
|
v[0].pos[0] = px0; v[0].pos[1] = py0; v[0].uv[0] = 0; v[0].uv[1] = 0;
|
||||||
v[0].pos[1] = py0;
|
v[1].pos[0] = px1; v[1].pos[1] = py0; v[1].uv[0] = 0; v[1].uv[1] = 0;
|
||||||
v[0].uv[0] = 0;
|
v[2].pos[0] = px1; v[2].pos[1] = py1; v[2].uv[0] = 0; v[2].uv[1] = 0;
|
||||||
v[0].uv[1] = 0;
|
v[3].pos[0] = px0; v[3].pos[1] = py1; v[3].uv[0] = 0; v[3].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[0] = tr; v[0].col[1] = tg; v[0].col[2] = tb; v[0].col[3] = ta;
|
||||||
v[0].col[1] = tg;
|
v[1].col[0] = tr; v[1].col[1] = tg; v[1].col[2] = tb; v[1].col[3] = ta;
|
||||||
v[0].col[2] = tb;
|
v[2].col[0] = br; v[2].col[1] = bg; v[2].col[2] = bb_; v[2].col[3] = ba;
|
||||||
v[0].col[3] = ta;
|
v[3].col[0] = br; v[3].col[1] = bg; v[3].col[2] = bb_; v[3].col[3] = ba;
|
||||||
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++) {
|
for (S32 i = 0; i < 4; i++) {
|
||||||
v[i].rect_min[0] = x0;
|
v[i].rect_min[0] = x0; v[i].rect_min[1] = y0;
|
||||||
v[i].rect_min[1] = y0;
|
v[i].rect_max[0] = x1; v[i].rect_max[1] = y1;
|
||||||
v[i].rect_max[0] = x1;
|
v[i].corner_radii[0] = cr_tl; v[i].corner_radii[1] = cr_tr;
|
||||||
v[i].rect_max[1] = y1;
|
v[i].corner_radii[2] = cr_br; v[i].corner_radii[3] = cr_bl;
|
||||||
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].border_thickness = 0;
|
||||||
v[i].softness = softness;
|
v[i].softness = softness;
|
||||||
v[i].mode = 0;
|
v[i].mode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 *idx = &batch->indices[batch->index_count];
|
U32 *idx = &batch->indices[batch->index_count];
|
||||||
idx[0] = base;
|
idx[0] = base; idx[1] = base + 1; idx[2] = base + 2;
|
||||||
idx[1] = base + 1;
|
idx[3] = base; idx[4] = base + 2; idx[5] = base + 3;
|
||||||
idx[2] = base + 2;
|
|
||||||
idx[3] = base;
|
|
||||||
idx[4] = base + 2;
|
|
||||||
idx[5] = base + 3;
|
|
||||||
|
|
||||||
batch->vertex_count += 4;
|
batch->vertex_count += 4;
|
||||||
batch->index_count += 6;
|
batch->index_count += 6;
|
||||||
@@ -1221,7 +1130,8 @@ static void emit_rect_vgradient(DrawBatch *batch,
|
|||||||
|
|
||||||
static void emit_text_glyphs(DrawBatch *batch, Renderer *r,
|
static void emit_text_glyphs(DrawBatch *batch, Renderer *r,
|
||||||
Clay_BoundingBox bbox, Clay_Color color, const char *text, S32 text_len,
|
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;
|
if (text_len == 0 || color.a < 0.1f) return;
|
||||||
|
|
||||||
F32 cr = color.r / 255.f;
|
F32 cr = color.r / 255.f;
|
||||||
@@ -1269,7 +1179,8 @@ static void emit_text_glyphs(DrawBatch *batch, Renderer *r,
|
|||||||
// Flush helper
|
// Flush helper
|
||||||
|
|
||||||
static void flush_batch(Renderer *r, DrawBatch *batch, U32 buf_idx,
|
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;
|
U32 draw_index_count = batch->index_count - *flush_index_start;
|
||||||
if (draw_index_count == 0) return;
|
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;
|
VkCommandBuffer cb = fc->command_buffer;
|
||||||
vkResetCommandBuffer(cb, 0);
|
vkResetCommandBuffer(cb, 0);
|
||||||
|
|
||||||
VkCommandBufferBeginInfo begin_info = { 0 };
|
VkCommandBufferBeginInfo begin_info = {0};
|
||||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
vkBeginCommandBuffer(cb, &begin_info);
|
vkBeginCommandBuffer(cb, &begin_info);
|
||||||
|
|
||||||
VkClearValue clear_value = { 0 };
|
VkClearValue clear_value = {0};
|
||||||
clear_value.color.float32[0] = r->clear_r;
|
clear_value.color.float32[0] = r->clear_r;
|
||||||
clear_value.color.float32[1] = r->clear_g;
|
clear_value.color.float32[1] = r->clear_g;
|
||||||
clear_value.color.float32[2] = r->clear_b;
|
clear_value.color.float32[2] = r->clear_b;
|
||||||
clear_value.color.float32[3] = 1.0f;
|
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.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
rp_begin.renderPass = r->render_pass;
|
rp_begin.renderPass = r->render_pass;
|
||||||
rp_begin.framebuffer = r->framebuffers[image_index];
|
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);
|
vkCmdBeginRenderPass(cb, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
VkViewport viewport = { 0 };
|
VkViewport viewport = {0};
|
||||||
viewport.width = (float)r->width;
|
viewport.width = (float)r->width;
|
||||||
viewport.height = (float)r->height;
|
viewport.height = (float)r->height;
|
||||||
viewport.maxDepth = 1.0f;
|
viewport.maxDepth = 1.0f;
|
||||||
vkCmdSetViewport(cb, 0, 1, &viewport);
|
vkCmdSetViewport(cb, 0, 1, &viewport);
|
||||||
|
|
||||||
VkRect2D scissor = { 0 };
|
VkRect2D scissor = {0};
|
||||||
scissor.extent.width = (U32)r->width;
|
scissor.extent.width = (U32)r->width;
|
||||||
scissor.extent.height = (U32)r->height;
|
scissor.extent.height = (U32)r->height;
|
||||||
vkCmdSetScissor(cb, 0, 1, &scissor);
|
vkCmdSetScissor(cb, 0, 1, &scissor);
|
||||||
|
|
||||||
// Process Clay render commands
|
// Process Clay render commands
|
||||||
if (render_commands.length > 0) {
|
if (render_commands.length > 0) {
|
||||||
DrawBatch batch = { 0 };
|
DrawBatch batch = {0};
|
||||||
batch.vertices = (UIVertex *)r->vb_mapped[frame_idx];
|
batch.vertices = (UIVertex *)r->vb_mapped[frame_idx];
|
||||||
batch.indices = (U32 *)r->ib_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: {
|
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START: {
|
||||||
VkDescriptorSet heap = bound_texture == 1 ? r->icon_descriptor_set : r->font_descriptor_set;
|
VkDescriptorSet heap = bound_texture == 1 ? r->icon_descriptor_set : r->font_descriptor_set;
|
||||||
flush_batch(r, &batch, frame_idx, &flush_index_start, heap);
|
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.x = (S32)Max(bb.x, 0.f);
|
||||||
clip.offset.y = (S32)Max(bb.y, 0.f);
|
clip.offset.y = (S32)Max(bb.y, 0.f);
|
||||||
clip.extent.width = (U32)Min(bb.width, (F32)r->width - clip.offset.x);
|
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: {
|
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END: {
|
||||||
VkDescriptorSet heap = bound_texture == 1 ? r->icon_descriptor_set : r->font_descriptor_set;
|
VkDescriptorSet heap = bound_texture == 1 ? r->icon_descriptor_set : r->font_descriptor_set;
|
||||||
flush_batch(r, &batch, frame_idx, &flush_index_start, heap);
|
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.width = (U32)r->width;
|
||||||
full_scissor.extent.height = (U32)r->height;
|
full_scissor.extent.height = (U32)r->height;
|
||||||
vkCmdSetScissor(cb, 0, 1, &full_scissor);
|
vkCmdSetScissor(cb, 0, 1, &full_scissor);
|
||||||
@@ -1701,7 +1612,7 @@ void renderer_end_frame(Renderer *r, Clay_RenderCommandArray render_commands) {
|
|||||||
|
|
||||||
// Submit
|
// Submit
|
||||||
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
VkSubmitInfo submit = { 0 };
|
VkSubmitInfo submit = {0};
|
||||||
submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
submit.waitSemaphoreCount = 1;
|
submit.waitSemaphoreCount = 1;
|
||||||
submit.pWaitSemaphores = &r->image_available_sema[frame_idx];
|
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);
|
vkQueueSubmit(r->graphics_queue, 1, &submit, fc->fence);
|
||||||
|
|
||||||
// Present
|
// Present
|
||||||
VkPresentInfoKHR present = { 0 };
|
VkPresentInfoKHR present = {0};
|
||||||
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
present.waitSemaphoreCount = 1;
|
present.waitSemaphoreCount = 1;
|
||||||
present.pWaitSemaphores = &r->render_finished_sema[frame_idx];
|
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) {
|
void renderer_create_icon_atlas(Renderer *r, const U8 *data, S32 w, S32 h) {
|
||||||
// Create image
|
// Create image
|
||||||
VkImageCreateInfo img_ci = { 0 };
|
VkImageCreateInfo img_ci = {0};
|
||||||
img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
img_ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
img_ci.imageType = VK_IMAGE_TYPE_2D;
|
img_ci.imageType = VK_IMAGE_TYPE_2D;
|
||||||
img_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
|
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.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
img_ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
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;
|
alloc_ci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||||
|
|
||||||
vmaCreateImage(r->allocator, &img_ci, &alloc_ci, &r->icon_image, &r->icon_alloc, NULL);
|
vmaCreateImage(r->allocator, &img_ci, &alloc_ci, &r->icon_image, &r->icon_alloc, NULL);
|
||||||
|
|
||||||
// Staging buffer
|
// Staging buffer
|
||||||
VkBufferCreateInfo staging_ci = { 0 };
|
VkBufferCreateInfo staging_ci = {0};
|
||||||
staging_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
staging_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
staging_ci.size = (VkDeviceSize)w * h * 4;
|
staging_ci.size = (VkDeviceSize)w * h * 4;
|
||||||
staging_ci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
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.usage = VMA_MEMORY_USAGE_CPU_ONLY;
|
||||||
staging_alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
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,
|
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_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.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
region.imageSubresource.layerCount = 1;
|
region.imageSubresource.layerCount = 1;
|
||||||
region.imageExtent.width = (U32)w;
|
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);
|
vmaDestroyBuffer(r->allocator, staging_buf, staging_alloc);
|
||||||
|
|
||||||
// Image view
|
// Image view
|
||||||
VkImageViewCreateInfo view_ci = { 0 };
|
VkImageViewCreateInfo view_ci = {0};
|
||||||
view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
view_ci.image = r->icon_image;
|
view_ci.image = r->icon_image;
|
||||||
view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
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);
|
vkCreateImageView(r->device, &view_ci, NULL, &r->icon_view);
|
||||||
|
|
||||||
// Allocate icon descriptor set
|
// Allocate icon descriptor set
|
||||||
VkDescriptorSetAllocateInfo ds_alloc = { 0 };
|
VkDescriptorSetAllocateInfo ds_alloc = {0};
|
||||||
ds_alloc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
ds_alloc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
ds_alloc.descriptorPool = r->descriptor_pool;
|
ds_alloc.descriptorPool = r->descriptor_pool;
|
||||||
ds_alloc.descriptorSetCount = 1;
|
ds_alloc.descriptorSetCount = 1;
|
||||||
@@ -1817,14 +1728,8 @@ void renderer_resize(Renderer *r, S32 width, S32 height) {
|
|||||||
|
|
||||||
// Clean up old swap chain resources
|
// Clean up old swap chain resources
|
||||||
for (U32 i = 0; i < NUM_BACK_BUFFERS; i++) {
|
for (U32 i = 0; i < NUM_BACK_BUFFERS; i++) {
|
||||||
if (r->framebuffers[i]) {
|
if (r->framebuffers[i]) { vkDestroyFramebuffer(r->device, r->framebuffers[i], NULL); r->framebuffers[i] = VK_NULL_HANDLE; }
|
||||||
vkDestroyFramebuffer(r->device, r->framebuffers[i], NULL);
|
if (r->swap_chain_views[i]) { vkDestroyImageView(r->device, r->swap_chain_views[i], NULL); r->swap_chain_views[i] = VK_NULL_HANDLE; }
|
||||||
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;
|
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;
|
F32 target_size = 22.0f * scale;
|
||||||
if (fabsf(target_size - r->font_atlas_size) < 0.1f) return;
|
if (fabsf(target_size - r->font_atlas_size) < 0.1f) return;
|
||||||
vkDeviceWaitIdle(r->device);
|
vkDeviceWaitIdle(r->device);
|
||||||
if (r->font_view) {
|
if (r->font_view) { vkDestroyImageView(r->device, r->font_view, NULL); r->font_view = VK_NULL_HANDLE; }
|
||||||
vkDestroyImageView(r->device, r->font_view, NULL);
|
if (r->font_image) { vmaDestroyImage(r->allocator, r->font_image, r->font_alloc); r->font_image = VK_NULL_HANDLE; }
|
||||||
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);
|
create_font_atlas(r, target_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,54 +27,54 @@ void ui_set_theme(S32 theme_id) {
|
|||||||
switch (theme_id) {
|
switch (theme_id) {
|
||||||
default:
|
default:
|
||||||
case 0: // Dark
|
case 0: // Dark
|
||||||
g_theme.bg_dark = Clay_Color{ 26, 26, 26, 255 };
|
g_theme.bg_dark = Clay_Color{ 26, 26, 26, 255};
|
||||||
g_theme.bg_medium = Clay_Color{ 36, 36, 36, 255 };
|
g_theme.bg_medium = Clay_Color{ 36, 36, 36, 255};
|
||||||
g_theme.bg_light = Clay_Color{ 46, 46, 46, 255 };
|
g_theme.bg_light = Clay_Color{ 46, 46, 46, 255};
|
||||||
g_theme.bg_lighter = Clay_Color{ 54, 54, 54, 255 };
|
g_theme.bg_lighter = Clay_Color{ 54, 54, 54, 255};
|
||||||
g_theme.border = Clay_Color{ 52, 52, 52, 255 };
|
g_theme.border = Clay_Color{ 52, 52, 52, 255};
|
||||||
g_theme.text = Clay_Color{ 220, 220, 220, 255 };
|
g_theme.text = Clay_Color{220, 220, 220, 255};
|
||||||
g_theme.text_dim = Clay_Color{ 105, 105, 105, 255 };
|
g_theme.text_dim = Clay_Color{105, 105, 105, 255};
|
||||||
g_theme.accent = Clay_Color{ 87, 138, 176, 255 };
|
g_theme.accent = Clay_Color{ 87, 138, 176, 255};
|
||||||
g_theme.accent_hover = Clay_Color{ 102, 153, 191, 255 };
|
g_theme.accent_hover = Clay_Color{102, 153, 191, 255};
|
||||||
g_theme.button_text = Clay_Color{ 224, 224, 224, 255 };
|
g_theme.button_text = Clay_Color{224, 224, 224, 255};
|
||||||
g_theme.disabled_bg = Clay_Color{ 44, 44, 44, 255 };
|
g_theme.disabled_bg = Clay_Color{ 44, 44, 44, 255};
|
||||||
g_theme.disabled_text = Clay_Color{ 90, 90, 90, 255 };
|
g_theme.disabled_text = Clay_Color{ 90, 90, 90, 255};
|
||||||
g_theme.header_bg = Clay_Color{ 46, 46, 46, 255 };
|
g_theme.header_bg = Clay_Color{ 46, 46, 46, 255};
|
||||||
g_theme.title_bar = Clay_Color{ 22, 22, 22, 255 };
|
g_theme.title_bar = Clay_Color{ 22, 22, 22, 255};
|
||||||
g_theme.scrollbar_bg = 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.scrollbar_grab = Clay_Color{ 58, 58, 58, 255};
|
||||||
g_theme.shadow = Clay_Color{ 0, 0, 0, 30 };
|
g_theme.shadow = Clay_Color{ 0, 0, 0, 30};
|
||||||
g_theme.tab_active_top = Clay_Color{ 70, 120, 160, 255 };
|
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_active_bottom= Clay_Color{ 30, 55, 80, 255};
|
||||||
g_theme.tab_inactive = Clay_Color{ 40, 40, 40, 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_inactive_hover= Clay_Color{ 50, 50, 50, 255};
|
||||||
g_theme.tab_text = Clay_Color{ 240, 240, 240, 255 };
|
g_theme.tab_text = Clay_Color{240, 240, 240, 255};
|
||||||
g_theme.corner_radius = 4.0f;
|
g_theme.corner_radius = 4.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // Light
|
case 1: // Light
|
||||||
g_theme.bg_dark = Clay_Color{ 195, 193, 190, 255 };
|
g_theme.bg_dark = Clay_Color{195, 193, 190, 255};
|
||||||
g_theme.bg_medium = Clay_Color{ 212, 210, 207, 255 };
|
g_theme.bg_medium = Clay_Color{212, 210, 207, 255};
|
||||||
g_theme.bg_light = Clay_Color{ 225, 223, 220, 255 };
|
g_theme.bg_light = Clay_Color{225, 223, 220, 255};
|
||||||
g_theme.bg_lighter = Clay_Color{ 232, 230, 227, 255 };
|
g_theme.bg_lighter = Clay_Color{232, 230, 227, 255};
|
||||||
g_theme.border = Clay_Color{ 178, 176, 173, 255 };
|
g_theme.border = Clay_Color{178, 176, 173, 255};
|
||||||
g_theme.text = Clay_Color{ 35, 33, 30, 255 };
|
g_theme.text = Clay_Color{ 35, 33, 30, 255};
|
||||||
g_theme.text_dim = Clay_Color{ 115, 113, 108, 255 };
|
g_theme.text_dim = Clay_Color{115, 113, 108, 255};
|
||||||
g_theme.accent = Clay_Color{ 50, 110, 170, 255 };
|
g_theme.accent = Clay_Color{ 50, 110, 170, 255};
|
||||||
g_theme.accent_hover = Clay_Color{ 65, 125, 185, 255 };
|
g_theme.accent_hover = Clay_Color{ 65, 125, 185, 255};
|
||||||
g_theme.button_text = Clay_Color{ 255, 255, 255, 255 };
|
g_theme.button_text = Clay_Color{255, 255, 255, 255};
|
||||||
g_theme.disabled_bg = Clay_Color{ 185, 183, 180, 255 };
|
g_theme.disabled_bg = Clay_Color{185, 183, 180, 255};
|
||||||
g_theme.disabled_text = Clay_Color{ 145, 143, 140, 255 };
|
g_theme.disabled_text = Clay_Color{145, 143, 140, 255};
|
||||||
g_theme.header_bg = Clay_Color{ 202, 200, 197, 255 };
|
g_theme.header_bg = Clay_Color{202, 200, 197, 255};
|
||||||
g_theme.title_bar = 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_bg = Clay_Color{202, 200, 197, 255};
|
||||||
g_theme.scrollbar_grab = Clay_Color{ 168, 166, 163, 255 };
|
g_theme.scrollbar_grab = Clay_Color{168, 166, 163, 255};
|
||||||
g_theme.shadow = Clay_Color{ 0, 0, 0, 18 };
|
g_theme.shadow = Clay_Color{ 0, 0, 0, 18};
|
||||||
g_theme.tab_active_top = Clay_Color{ 70, 130, 180, 255 };
|
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_active_bottom= Clay_Color{ 50, 100, 150, 255};
|
||||||
g_theme.tab_inactive = Clay_Color{ 205, 203, 200, 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_inactive_hover= Clay_Color{195, 193, 190, 255};
|
||||||
g_theme.tab_text = Clay_Color{ 255, 255, 255, 255 };
|
g_theme.tab_text = Clay_Color{255, 255, 255, 255};
|
||||||
g_theme.corner_radius = 4.0f;
|
g_theme.corner_radius = 4.0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -97,37 +97,37 @@ void ui_set_accent(S32 accent_id) {
|
|||||||
// Dark-mode palettes
|
// Dark-mode palettes
|
||||||
static const AccentColors dark_palettes[] = {
|
static const AccentColors dark_palettes[] = {
|
||||||
// 0: Blue
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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)
|
// Light-mode palettes (slightly more saturated for contrast on light bg)
|
||||||
static const AccentColors light_palettes[] = {
|
static const AccentColors light_palettes[] = {
|
||||||
// 0: Blue
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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;
|
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) {
|
static Clay_Dimensions clay_measure_text(Clay_StringSlice text, Clay_TextElementConfig *config, void *user_data) {
|
||||||
UI_Context *ctx = (UI_Context *)user_data;
|
UI_Context *ctx = (UI_Context *)user_data;
|
||||||
if (!ctx || !ctx->measure_text_fn || text.length == 0) {
|
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);
|
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;
|
err_handler.userData = ctx;
|
||||||
|
|
||||||
ctx->clay_ctx = Clay_Initialize(clay_arena,
|
ctx->clay_ctx = Clay_Initialize(clay_arena,
|
||||||
Clay_Dimensions{ viewport_w, viewport_h },
|
Clay_Dimensions{viewport_w, viewport_h},
|
||||||
err_handler);
|
err_handler);
|
||||||
|
|
||||||
Clay_SetMeasureTextFunction(clay_measure_text, ctx);
|
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,
|
void ui_begin_frame(UI_Context *ctx, F32 viewport_w, F32 viewport_h,
|
||||||
Vec2F32 mouse_pos, B32 mouse_down,
|
Vec2F32 mouse_pos, B32 mouse_down,
|
||||||
Vec2F32 scroll_delta, F32 dt) {
|
Vec2F32 scroll_delta, F32 dt)
|
||||||
|
{
|
||||||
g_measure_ctx = ctx;
|
g_measure_ctx = ctx;
|
||||||
Clay_SetCurrentContext(ctx->clay_ctx);
|
Clay_SetCurrentContext(ctx->clay_ctx);
|
||||||
Clay_SetLayoutDimensions(Clay_Dimensions{ viewport_w, viewport_h });
|
Clay_SetLayoutDimensions(Clay_Dimensions{viewport_w, viewport_h});
|
||||||
Clay_SetPointerState(Clay_Vector2{ mouse_pos.x, mouse_pos.y }, mouse_down != 0);
|
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_UpdateScrollContainers(false, Clay_Vector2{scroll_delta.x, scroll_delta.y}, dt);
|
||||||
Clay_BeginLayout();
|
Clay_BeginLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ Clay_Color piano_velocity_color(S32 velocity) {
|
|||||||
g = 175.0f + s * (50.0f - 175.0f);
|
g = 175.0f + s * (50.0f - 175.0f);
|
||||||
b = 80.0f + s * (40.0f - 80.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) {
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
||||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Compute black key size proportional to white keys
|
// Compute black key size proportional to white keys
|
||||||
F32 black_key_h = avail_h * PIANO_BLACK_H_PCT;
|
F32 black_key_h = avail_h * PIANO_BLACK_H_PCT;
|
||||||
if (black_key_h < uis(20)) black_key_h = uis(20);
|
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) {
|
} else if (mouse_held) {
|
||||||
bg = g_theme.accent;
|
bg = g_theme.accent;
|
||||||
} else {
|
} else {
|
||||||
bg = Clay_Color{ 240, 240, 240, 255 };
|
bg = Clay_Color{240, 240, 240, 255};
|
||||||
}
|
}
|
||||||
|
|
||||||
CLAY(CLAY_IDI("PKey", note),
|
CLAY(CLAY_IDI("PKey", note),
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
|
.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)
|
// 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) {
|
} else if (mouse_held) {
|
||||||
bg = g_theme.accent;
|
bg = g_theme.accent;
|
||||||
} else {
|
} else {
|
||||||
bg = Clay_Color{ 25, 25, 30, 255 };
|
bg = Clay_Color{25, 25, 30, 255};
|
||||||
}
|
}
|
||||||
|
|
||||||
CLAY(CLAY_IDI("PKey", note),
|
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),
|
.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,
|
.parentId = parent_wkey.id,
|
||||||
.zIndex = 100,
|
.zIndex = 100,
|
||||||
.attachPoints = {
|
.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,
|
.parent = CLAY_ATTACH_POINT_RIGHT_TOP,
|
||||||
},
|
},
|
||||||
.attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
|
.attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
|
||||||
}, ) {}
|
},
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "midi/midi.h"
|
|
||||||
#include "ui/ui_core.h"
|
#include "ui/ui_core.h"
|
||||||
|
#include "midi/midi.h"
|
||||||
|
|
||||||
#define PIANO_FIRST_NOTE 21 // A0
|
#define PIANO_FIRST_NOTE 21 // A0
|
||||||
#define PIANO_LAST_NOTE 108 // C8
|
#define PIANO_LAST_NOTE 108 // C8
|
||||||
|
|||||||
@@ -23,10 +23,7 @@ PopupWindow *popup_open(PlatformWindow *parent_window, Renderer *parent_renderer
|
|||||||
// Find free slot
|
// Find free slot
|
||||||
PopupWindow *popup = nullptr;
|
PopupWindow *popup = nullptr;
|
||||||
for (S32 i = 0; i < MAX_POPUP_WINDOWS; i++) {
|
for (S32 i = 0; i < MAX_POPUP_WINDOWS; i++) {
|
||||||
if (!g_popups[i].alive) {
|
if (!g_popups[i].alive) { popup = &g_popups[i]; break; }
|
||||||
popup = &g_popups[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!popup) return nullptr;
|
if (!popup) return nullptr;
|
||||||
|
|
||||||
@@ -140,7 +137,8 @@ void popup_do_frame(PopupWindow *popup, F32 dt) {
|
|||||||
.childGap = uip(8),
|
.childGap = uip(8),
|
||||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||||
},
|
},
|
||||||
.backgroundColor = g_theme.bg_medium, ) {
|
.backgroundColor = g_theme.bg_medium,
|
||||||
|
) {
|
||||||
if (popup->content_fn) {
|
if (popup->content_fn) {
|
||||||
popup->content_fn(popup->content_user_data);
|
popup->content_fn(popup->content_user_data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "platform/platform.h"
|
|
||||||
#include "renderer/renderer.h"
|
|
||||||
#include "ui/ui_core.h"
|
#include "ui/ui_core.h"
|
||||||
#include "ui/ui_widgets.h"
|
#include "ui/ui_widgets.h"
|
||||||
|
#include "platform/platform.h"
|
||||||
|
#include "renderer/renderer.h"
|
||||||
|
|
||||||
#define MAX_POPUP_WINDOWS 4
|
#define MAX_POPUP_WINDOWS 4
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
// AFTER a CLAY() block, use Clay_PointerOver(elementId).
|
// AFTER a CLAY() block, use Clay_PointerOver(elementId).
|
||||||
|
|
||||||
#include "ui/ui_widgets.h"
|
#include "ui/ui_widgets.h"
|
||||||
#include <math.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <math.h>
|
||||||
|
|
||||||
UI_WidgetState g_wstate = {};
|
UI_WidgetState g_wstate = {};
|
||||||
|
|
||||||
@@ -78,11 +78,13 @@ static void emit_shadow(Clay_BoundingBox bb, F32 ox, F32 oy, F32 radius,
|
|||||||
CLAY(shadow_eid,
|
CLAY(shadow_eid,
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = {
|
.sizing = {
|
||||||
.width = CLAY_SIZING_FIXED(bb.width + expand * 2),
|
.width = CLAY_SIZING_FIXED(bb.width + expand*2),
|
||||||
.height = CLAY_SIZING_FIXED(bb.height + 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 },
|
.offset = { bb.x - expand + ox, bb.y - expand + oy },
|
||||||
.zIndex = z,
|
.zIndex = z,
|
||||||
.attachPoints = {
|
.attachPoints = {
|
||||||
@@ -90,16 +92,19 @@ static void emit_shadow(Clay_BoundingBox bb, F32 ox, F32 oy, F32 radius,
|
|||||||
.parent = CLAY_ATTACH_POINT_LEFT_TOP,
|
.parent = CLAY_ATTACH_POINT_LEFT_TOP,
|
||||||
},
|
},
|
||||||
.attachTo = CLAY_ATTACH_TO_ROOT,
|
.attachTo = CLAY_ATTACH_TO_ROOT,
|
||||||
}) {}
|
}
|
||||||
|
) {}
|
||||||
} else {
|
} else {
|
||||||
CLAY(shadow_eid,
|
CLAY(shadow_eid,
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = {
|
.sizing = {
|
||||||
.width = CLAY_SIZING_FIXED(bb.width + expand * 2),
|
.width = CLAY_SIZING_FIXED(bb.width + expand*2),
|
||||||
.height = CLAY_SIZING_FIXED(bb.height + 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 },
|
.offset = { -expand + ox, -expand + oy },
|
||||||
.parentId = parent_id,
|
.parentId = parent_id,
|
||||||
.zIndex = z,
|
.zIndex = z,
|
||||||
@@ -108,7 +113,8 @@ static void emit_shadow(Clay_BoundingBox bb, F32 ox, F32 oy, F32 radius,
|
|||||||
.parent = parent_attach,
|
.parent = parent_attach,
|
||||||
},
|
},
|
||||||
.attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID,
|
.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)
|
// Selected text: white on accent background (background set on parent element)
|
||||||
g_widget_text_config_sel = {};
|
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.fontSize = FONT_SIZE_NORMAL;
|
||||||
g_widget_text_config_sel.wrapMode = CLAY_TEXT_WRAP_NONE;
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(size), .height = CLAY_SIZING_FIXED(size) },
|
.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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
|
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
|
||||||
.padding = { 0, 0, uip(2), uip(2) },
|
.padding = { 0, 0, uip(2), uip(2) },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
CLAY_TEXT(clay_str(text), &g_widget_text_config);
|
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);
|
B32 hovered = Clay_PointerOver(eid);
|
||||||
|
|
||||||
Clay_Color base = hovered ? g_theme.accent_hover : g_theme.accent;
|
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 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 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);
|
CustomGradientData *grad = alloc_gradient(top, bot);
|
||||||
|
|
||||||
CLAY(eid,
|
CLAY(eid,
|
||||||
@@ -265,7 +273,10 @@ B32 ui_button(const char *id, const char *text) {
|
|||||||
.padding = { uip(12), uip(12), uip(1), 0 },
|
.padding = { uip(12), uip(12), uip(1), 0 },
|
||||||
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
.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);
|
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),
|
.childGap = uip(8),
|
||||||
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
||||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Box
|
// Box
|
||||||
Clay_Color box_bg = *value ? g_theme.accent : g_theme.bg_dark;
|
Clay_Color box_bg = *value ? g_theme.accent : g_theme.bg_dark;
|
||||||
if (hovered) {
|
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) },
|
.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 },
|
.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) {
|
if (*value) {
|
||||||
ui_icon(UI_ICON_CHECK, WIDGET_CHECKBOX_SIZE * 0.75f, g_theme.button_text);
|
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() },
|
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
|
||||||
.childGap = uip(4),
|
.childGap = uip(4),
|
||||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
for (S32 i = 0; i < count; i++) {
|
for (S32 i = 0; i < count; i++) {
|
||||||
B32 is_selected = (*selected == i);
|
B32 is_selected = (*selected == i);
|
||||||
Clay_ElementId row_id = WIDI(id, i + 100);
|
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),
|
.childGap = uip(8),
|
||||||
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
||||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Radio circle
|
// Radio circle
|
||||||
Clay_Color dot_bg = is_selected ? g_theme.accent : g_theme.bg_dark;
|
Clay_Color dot_bg = is_selected ? g_theme.accent : g_theme.bg_dark;
|
||||||
if (row_hovered) {
|
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) },
|
.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 },
|
.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) {
|
if (is_selected) {
|
||||||
CLAY(WIDI(id, i + 300),
|
CLAY(WIDI(id, i + 300),
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(WIDGET_RADIO_INNER), .height = CLAY_SIZING_FIXED(WIDGET_RADIO_INNER) },
|
.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) {
|
static void text_input_get_sel(S32 *lo, S32 *hi) {
|
||||||
S32 a = g_wstate.sel_start;
|
S32 a = g_wstate.sel_start;
|
||||||
S32 b = g_wstate.sel_end;
|
S32 b = g_wstate.sel_end;
|
||||||
if (a <= b) {
|
if (a <= b) { *lo = a; *hi = b; }
|
||||||
*lo = a;
|
else { *lo = b; *hi = a; }
|
||||||
*hi = b;
|
|
||||||
} else {
|
|
||||||
*lo = b;
|
|
||||||
*hi = a;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: true if there's an active selection
|
// 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);
|
S32 clip_len = (S32)strlen(clip);
|
||||||
// Filter to single line (stop at newline)
|
// Filter to single line (stop at newline)
|
||||||
for (S32 i = 0; i < clip_len; i++) {
|
for (S32 i = 0; i < clip_len; i++) {
|
||||||
if (clip[i] == '\n' || clip[i] == '\r') {
|
if (clip[i] == '\n' || clip[i] == '\r') { clip_len = i; break; }
|
||||||
clip_len = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
S32 space = buf_size - 1 - len;
|
S32 space = buf_size - 1 - len;
|
||||||
if (clip_len > space) clip_len = space;
|
if (clip_len > space) clip_len = space;
|
||||||
@@ -594,8 +608,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
|
|||||||
break;
|
break;
|
||||||
case PKEY_LEFT:
|
case PKEY_LEFT:
|
||||||
if (text_input_has_sel()) {
|
if (text_input_has_sel()) {
|
||||||
S32 lo, hi;
|
S32 lo, hi; text_input_get_sel(&lo, &hi);
|
||||||
text_input_get_sel(&lo, &hi);
|
|
||||||
g_wstate.cursor_pos = lo;
|
g_wstate.cursor_pos = lo;
|
||||||
} else if (g_wstate.cursor_pos > 0) {
|
} else if (g_wstate.cursor_pos > 0) {
|
||||||
g_wstate.cursor_pos--;
|
g_wstate.cursor_pos--;
|
||||||
@@ -606,8 +619,7 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
|
|||||||
break;
|
break;
|
||||||
case PKEY_RIGHT:
|
case PKEY_RIGHT:
|
||||||
if (text_input_has_sel()) {
|
if (text_input_has_sel()) {
|
||||||
S32 lo, hi;
|
S32 lo, hi; text_input_get_sel(&lo, &hi);
|
||||||
text_input_get_sel(&lo, &hi);
|
|
||||||
g_wstate.cursor_pos = hi;
|
g_wstate.cursor_pos = hi;
|
||||||
} else if (g_wstate.cursor_pos < len) {
|
} else if (g_wstate.cursor_pos < len) {
|
||||||
g_wstate.cursor_pos++;
|
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.
|
// our ID was just added above. Find it and advance to next.
|
||||||
S32 my_idx = -1;
|
S32 my_idx = -1;
|
||||||
for (S32 i = 0; i < g_wstate.text_input_count; i++) {
|
for (S32 i = 0; i < g_wstate.text_input_count; i++) {
|
||||||
if (g_wstate.text_input_ids[i] == eid.id) {
|
if (g_wstate.text_input_ids[i] == eid.id) { my_idx = i; break; }
|
||||||
my_idx = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (my_idx >= 0) {
|
if (my_idx >= 0) {
|
||||||
// Focus next (wrapping). But we might not have all inputs registered
|
// 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;
|
Clay_Color border_color = is_focused ? g_theme.accent : g_theme.border;
|
||||||
|
|
||||||
// Inset effect: darker top, lighter bottom (recessed look)
|
// 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_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_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);
|
CustomGradientData *inset_grad = alloc_gradient(inset_top, inset_bot);
|
||||||
|
|
||||||
CLAY(eid,
|
CLAY(eid,
|
||||||
@@ -723,7 +732,11 @@ B32 ui_text_input(const char *id, char *buf, S32 buf_size) {
|
|||||||
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
||||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
.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) {
|
if (len == 0 && !is_focused) {
|
||||||
// Placeholder
|
// Placeholder
|
||||||
CLAY_TEXT(CLAY_STRING("..."), &g_widget_text_config_dim);
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
|
.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);
|
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) {
|
while (lo < hi) {
|
||||||
S32 mid = (lo + hi + 1) / 2;
|
S32 mid = (lo + hi + 1) / 2;
|
||||||
Vec2F32 seg = ui_measure_text(current_label, mid, FONT_SIZE_NORMAL);
|
Vec2F32 seg = ui_measure_text(current_label, mid, FONT_SIZE_NORMAL);
|
||||||
if (seg.x <= target_w) lo = mid;
|
if (seg.x <= target_w) lo = mid; else hi = mid - 1;
|
||||||
else hi = mid - 1;
|
|
||||||
}
|
}
|
||||||
if (lo + 3 < (S32)sizeof(dd_trunc_buf)) {
|
if (lo + 3 < (S32)sizeof(dd_trunc_buf)) {
|
||||||
memcpy(dd_trunc_buf, current_label, lo);
|
memcpy(dd_trunc_buf, current_label, lo);
|
||||||
dd_trunc_buf[lo] = '.';
|
dd_trunc_buf[lo] = '.'; dd_trunc_buf[lo+1] = '.'; dd_trunc_buf[lo+2] = '.';
|
||||||
dd_trunc_buf[lo + 1] = '.';
|
dd_trunc_buf[lo+3] = '\0';
|
||||||
dd_trunc_buf[lo + 2] = '.';
|
|
||||||
dd_trunc_buf[lo + 3] = '\0';
|
|
||||||
display_label = dd_trunc_buf;
|
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;
|
Clay_Color bg = is_open ? g_theme.bg_dark : g_theme.bg_medium;
|
||||||
if (header_hovered && !is_open) bg = g_theme.bg_lighter;
|
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);
|
CustomGradientData *dd_grad = alloc_gradient(dd_top, bg);
|
||||||
|
|
||||||
CLAY(eid,
|
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 },
|
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
||||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
.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,
|
CLAY(text_eid,
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
|
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
CLAY_TEXT(clay_str(display_label), &g_widget_text_config);
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(uis(20)), .height = CLAY_SIZING_FIXED(uis(20)) },
|
.sizing = { .width = CLAY_SIZING_FIXED(uis(20)), .height = CLAY_SIZING_FIXED(uis(20)) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
ui_icon(UI_ICON_CHEVRON_DOWN, uis(12), g_theme.text_dim);
|
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() },
|
.sizing = { .width = CLAY_SIZING_FIT(.min = header_width), .height = CLAY_SIZING_FIT() },
|
||||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
.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,
|
.parentId = eid.id,
|
||||||
.zIndex = 2000,
|
.zIndex = 2000,
|
||||||
.attachPoints = {
|
.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,
|
.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++) {
|
for (S32 i = 0; i < count; i++) {
|
||||||
B32 is_item_selected = (*selected == i);
|
B32 is_item_selected = (*selected == i);
|
||||||
Clay_ElementId item_id = WIDI(id, i + 600);
|
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;
|
if (item_hovered) item_bg = g_theme.bg_lighter;
|
||||||
|
|
||||||
Clay_TextElementConfig *item_text = (is_item_selected && !item_hovered)
|
Clay_TextElementConfig *item_text = (is_item_selected && !item_hovered)
|
||||||
? &g_widget_text_config_btn
|
? &g_widget_text_config_btn : &g_widget_text_config;
|
||||||
: &g_widget_text_config;
|
|
||||||
|
|
||||||
Clay_CornerRadius item_radius = {};
|
Clay_CornerRadius item_radius = {};
|
||||||
if (i == 0) {
|
if (i == 0) { item_radius.topLeft = CORNER_RADIUS; item_radius.topRight = CORNER_RADIUS; }
|
||||||
item_radius.topLeft = CORNER_RADIUS;
|
if (i == count - 1) { item_radius.bottomLeft = CORNER_RADIUS; item_radius.bottomRight = CORNER_RADIUS; }
|
||||||
item_radius.topRight = CORNER_RADIUS;
|
|
||||||
}
|
|
||||||
if (i == count - 1) {
|
|
||||||
item_radius.bottomLeft = CORNER_RADIUS;
|
|
||||||
item_radius.bottomRight = CORNER_RADIUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLAY(item_id,
|
CLAY(item_id,
|
||||||
.layout = {
|
.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 },
|
.padding = { uip(8), uip(8), 0, 0 },
|
||||||
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
.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);
|
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)
|
// Check if any item was clicked (already handled above)
|
||||||
B32 clicked_item = 0;
|
B32 clicked_item = 0;
|
||||||
for (S32 i = 0; i < count; i++) {
|
for (S32 i = 0; i < count; i++) {
|
||||||
if (Clay_PointerOver(WIDI(id, i + 600))) {
|
if (Clay_PointerOver(WIDI(id, i + 600))) { clicked_item = 1; break; }
|
||||||
clicked_item = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!clicked_item) {
|
if (!clicked_item) {
|
||||||
g_wstate.open_dropdown_id = 0;
|
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 },
|
.padding = { 0, 0, 0, 0 },
|
||||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
.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++) {
|
for (S32 i = 0; i < count; i++) {
|
||||||
Clay_ElementId tab_eid = Clay__HashStringWithOffset(id_str, (U32)i, 0);
|
Clay_ElementId tab_eid = Clay__HashStringWithOffset(id_str, (U32)i, 0);
|
||||||
B32 is_active = (i == *selected);
|
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) },
|
.padding = { TAB_PADDING_H, TAB_PADDING_H, 0, uip(6) },
|
||||||
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
.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);
|
CLAY_TEXT(lbl_str, &g_widget_text_config_tab);
|
||||||
}
|
}
|
||||||
} else {
|
} 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) },
|
.padding = { TAB_PADDING_H, TAB_PADDING_H, 0, uip(6) },
|
||||||
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER },
|
.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);
|
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 (*esel0 > elen) *esel0 = elen;
|
||||||
if (*esel1 > elen) *esel1 = elen;
|
if (*esel1 > elen) *esel1 = elen;
|
||||||
|
|
||||||
#define KE_HAS_SEL() (*esel0 != *esel1)
|
#define KE_HAS_SEL() (*esel0 != *esel1)
|
||||||
#define KE_SEL_LO() (*esel0 < *esel1 ? *esel0 : *esel1)
|
#define KE_SEL_LO() (*esel0 < *esel1 ? *esel0 : *esel1)
|
||||||
#define KE_SEL_HI() (*esel0 < *esel1 ? *esel1 : *esel0)
|
#define KE_SEL_HI() (*esel0 < *esel1 ? *esel1 : *esel0)
|
||||||
#define KE_CLEAR_SEL() \
|
#define KE_CLEAR_SEL() do { *esel0 = *ecur; *esel1 = *ecur; } while(0)
|
||||||
do { \
|
|
||||||
*esel0 = *ecur; \
|
|
||||||
*esel1 = *ecur; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
auto ke_delete_sel = [&]() -> S32 {
|
auto ke_delete_sel = [&]() -> S32 {
|
||||||
S32 lo = KE_SEL_LO(), hi = KE_SEL_HI();
|
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 (ctrl) {
|
||||||
if (key == PKEY_A) {
|
if (key == PKEY_A) {
|
||||||
*esel0 = 0;
|
*esel0 = 0; *esel1 = elen; *ecur = elen; continue;
|
||||||
*esel1 = elen;
|
|
||||||
*ecur = elen;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (key == PKEY_C) {
|
if (key == PKEY_C) {
|
||||||
if (KE_HAS_SEL()) {
|
if (KE_HAS_SEL()) {
|
||||||
S32 lo = KE_SEL_LO(), hi = KE_SEL_HI();
|
S32 lo = KE_SEL_LO(), hi = KE_SEL_HI();
|
||||||
char tmp[32];
|
char tmp[32]; S32 n = hi - lo; if (n > 31) n = 31;
|
||||||
S32 n = hi - lo;
|
memcpy(tmp, &ebuf[lo], n); tmp[n] = '\0';
|
||||||
if (n > 31) n = 31;
|
|
||||||
memcpy(tmp, &ebuf[lo], n);
|
|
||||||
tmp[n] = '\0';
|
|
||||||
platform_clipboard_set(tmp);
|
platform_clipboard_set(tmp);
|
||||||
}
|
}
|
||||||
continue;
|
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 (key == PKEY_X) {
|
||||||
if (KE_HAS_SEL()) {
|
if (KE_HAS_SEL()) {
|
||||||
S32 lo = KE_SEL_LO(), hi = KE_SEL_HI();
|
S32 lo = KE_SEL_LO(), hi = KE_SEL_HI();
|
||||||
char tmp[32];
|
char tmp[32]; S32 n = hi - lo; if (n > 31) n = 31;
|
||||||
S32 n = hi - lo;
|
memcpy(tmp, &ebuf[lo], n); tmp[n] = '\0';
|
||||||
if (n > 31) n = 31;
|
|
||||||
memcpy(tmp, &ebuf[lo], n);
|
|
||||||
tmp[n] = '\0';
|
|
||||||
platform_clipboard_set(tmp);
|
platform_clipboard_set(tmp);
|
||||||
elen = ke_delete_sel();
|
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 (clip) {
|
||||||
if (KE_HAS_SEL()) elen = ke_delete_sel();
|
if (KE_HAS_SEL()) elen = ke_delete_sel();
|
||||||
S32 clip_len = (S32)strlen(clip);
|
S32 clip_len = (S32)strlen(clip);
|
||||||
char filtered[32];
|
char filtered[32]; S32 flen = 0;
|
||||||
S32 flen = 0;
|
|
||||||
for (S32 i = 0; i < clip_len && flen < 30; i++) {
|
for (S32 i = 0; i < clip_len && flen < 30; i++) {
|
||||||
char c = clip[i];
|
char c = clip[i];
|
||||||
if ((c >= '0' && c <= '9') || c == '.' || c == '-')
|
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) {
|
if (flen > 0) {
|
||||||
memmove(&ebuf[*ecur + flen], &ebuf[*ecur], elen - *ecur + 1);
|
memmove(&ebuf[*ecur + flen], &ebuf[*ecur], elen - *ecur + 1);
|
||||||
memcpy(&ebuf[*ecur], filtered, flen);
|
memcpy(&ebuf[*ecur], filtered, flen);
|
||||||
*ecur += flen;
|
*ecur += flen; elen += flen;
|
||||||
elen += flen;
|
|
||||||
}
|
}
|
||||||
KE_CLEAR_SEL();
|
KE_CLEAR_SEL();
|
||||||
}
|
}
|
||||||
@@ -1111,40 +1114,29 @@ static S32 value_edit_process_keys(F32 *value, F32 max_val, B32 is_signed, B32 *
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == PKEY_RETURN) {
|
if (key == PKEY_RETURN) { commit = 1; }
|
||||||
commit = 1;
|
else if (key == PKEY_ESCAPE) { cancel = 1; }
|
||||||
} else if (key == PKEY_ESCAPE) {
|
else if (key == PKEY_BACKSPACE) {
|
||||||
cancel = 1;
|
if (KE_HAS_SEL()) { elen = ke_delete_sel(); }
|
||||||
} else if (key == PKEY_BACKSPACE) {
|
else if (*ecur > 0) {
|
||||||
if (KE_HAS_SEL()) {
|
|
||||||
elen = ke_delete_sel();
|
|
||||||
} else if (*ecur > 0) {
|
|
||||||
memmove(&ebuf[*ecur - 1], &ebuf[*ecur], elen - *ecur + 1);
|
memmove(&ebuf[*ecur - 1], &ebuf[*ecur], elen - *ecur + 1);
|
||||||
(*ecur)--;
|
(*ecur)--; elen--;
|
||||||
elen--;
|
|
||||||
}
|
}
|
||||||
KE_CLEAR_SEL();
|
KE_CLEAR_SEL();
|
||||||
} else if (key == PKEY_DELETE) {
|
} else if (key == PKEY_DELETE) {
|
||||||
if (KE_HAS_SEL()) {
|
if (KE_HAS_SEL()) { elen = ke_delete_sel(); }
|
||||||
elen = ke_delete_sel();
|
else if (*ecur < elen) {
|
||||||
} else if (*ecur < elen) {
|
|
||||||
memmove(&ebuf[*ecur], &ebuf[*ecur + 1], elen - *ecur);
|
memmove(&ebuf[*ecur], &ebuf[*ecur + 1], elen - *ecur);
|
||||||
elen--;
|
elen--;
|
||||||
}
|
}
|
||||||
KE_CLEAR_SEL();
|
KE_CLEAR_SEL();
|
||||||
} else if (key == PKEY_LEFT) {
|
} else if (key == PKEY_LEFT) {
|
||||||
if (KE_HAS_SEL()) {
|
if (KE_HAS_SEL()) { *ecur = KE_SEL_LO(); }
|
||||||
*ecur = KE_SEL_LO();
|
else if (*ecur > 0) { (*ecur)--; }
|
||||||
} else if (*ecur > 0) {
|
|
||||||
(*ecur)--;
|
|
||||||
}
|
|
||||||
KE_CLEAR_SEL();
|
KE_CLEAR_SEL();
|
||||||
} else if (key == PKEY_RIGHT) {
|
} else if (key == PKEY_RIGHT) {
|
||||||
if (KE_HAS_SEL()) {
|
if (KE_HAS_SEL()) { *ecur = KE_SEL_HI(); }
|
||||||
*ecur = KE_SEL_HI();
|
else if (*ecur < elen) { (*ecur)++; }
|
||||||
} else if (*ecur < elen) {
|
|
||||||
(*ecur)++;
|
|
||||||
}
|
|
||||||
KE_CLEAR_SEL();
|
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 (KE_HAS_SEL()) elen = ke_delete_sel();
|
||||||
if (elen < 30) {
|
if (elen < 30) {
|
||||||
memmove(&ebuf[*ecur + 1], &ebuf[*ecur], elen - *ecur + 1);
|
memmove(&ebuf[*ecur + 1], &ebuf[*ecur], elen - *ecur + 1);
|
||||||
ebuf[*ecur] = (char)ch;
|
ebuf[*ecur] = (char)ch; (*ecur)++; elen++;
|
||||||
(*ecur)++;
|
|
||||||
elen++;
|
|
||||||
}
|
}
|
||||||
KE_CLEAR_SEL();
|
KE_CLEAR_SEL();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef KE_HAS_SEL
|
#undef KE_HAS_SEL
|
||||||
#undef KE_SEL_LO
|
#undef KE_SEL_LO
|
||||||
#undef KE_SEL_HI
|
#undef KE_SEL_HI
|
||||||
#undef KE_CLEAR_SEL
|
#undef KE_CLEAR_SEL
|
||||||
|
|
||||||
if (commit) {
|
if (commit) {
|
||||||
char *end = nullptr;
|
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;
|
F32 lo = is_signed ? -max_val : 0.0f;
|
||||||
if (parsed < lo) parsed = lo;
|
if (parsed < lo) parsed = lo;
|
||||||
if (parsed > max_val) parsed = max_val;
|
if (parsed > max_val) parsed = max_val;
|
||||||
if (parsed != *value) {
|
if (parsed != *value) { *value = parsed; *changed = 1; }
|
||||||
*value = parsed;
|
|
||||||
*changed = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g_wstate.knob_edit_id = 0;
|
g_wstate.knob_edit_id = 0;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1218,7 +1205,7 @@ static void value_edit_render(U32 hash, F32 width) {
|
|||||||
edit_cfg.wrapMode = CLAY_TEXT_WRAP_NONE;
|
edit_cfg.wrapMode = CLAY_TEXT_WRAP_NONE;
|
||||||
|
|
||||||
static Clay_TextElementConfig edit_sel_cfg = {};
|
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.fontSize = FONT_SIZE_SMALL;
|
||||||
edit_sel_cfg.wrapMode = CLAY_TEXT_WRAP_NONE;
|
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 },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
.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 (has_sel) {
|
||||||
if (sel_lo > 0) {
|
if (sel_lo > 0) {
|
||||||
S32 n = sel_lo;
|
S32 n = sel_lo;
|
||||||
memcpy(ke_dbuf_before, ebuf, n);
|
memcpy(ke_dbuf_before, ebuf, n); ke_dbuf_before[n] = '\0';
|
||||||
ke_dbuf_before[n] = '\0';
|
|
||||||
Clay_String s_before = { .length = n, .chars = ke_dbuf_before };
|
Clay_String s_before = { .length = n, .chars = ke_dbuf_before };
|
||||||
CLAY_TEXT(s_before, &edit_cfg);
|
CLAY_TEXT(s_before, &edit_cfg);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
S32 n = sel_hi - sel_lo;
|
S32 n = sel_hi - sel_lo;
|
||||||
memcpy(ke_dbuf_sel, &ebuf[sel_lo], n);
|
memcpy(ke_dbuf_sel, &ebuf[sel_lo], n); ke_dbuf_sel[n] = '\0';
|
||||||
ke_dbuf_sel[n] = '\0';
|
|
||||||
Clay_String s_sel = { .length = n, .chars = ke_dbuf_sel };
|
Clay_String s_sel = { .length = n, .chars = ke_dbuf_sel };
|
||||||
CLAY(CLAY_IDI("ValEditSel", (S32)hash),
|
CLAY(CLAY_IDI("ValEditSel", (S32)hash),
|
||||||
.layout = { .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() } },
|
.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);
|
CLAY_TEXT(s_sel, &edit_sel_cfg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sel_hi < elen) {
|
if (sel_hi < elen) {
|
||||||
S32 n = elen - sel_hi;
|
S32 n = elen - sel_hi;
|
||||||
memcpy(ke_dbuf_after, &ebuf[sel_hi], n);
|
memcpy(ke_dbuf_after, &ebuf[sel_hi], n); ke_dbuf_after[n] = '\0';
|
||||||
ke_dbuf_after[n] = '\0';
|
|
||||||
Clay_String s_after = { .length = n, .chars = ke_dbuf_after };
|
Clay_String s_after = { .length = n, .chars = ke_dbuf_after };
|
||||||
CLAY_TEXT(s_after, &edit_cfg);
|
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;
|
F32 lo = is_signed ? -max_val : 0.0f;
|
||||||
if (parsed < lo) parsed = lo;
|
if (parsed < lo) parsed = lo;
|
||||||
if (parsed > max_val) parsed = max_val;
|
if (parsed > max_val) parsed = max_val;
|
||||||
if (parsed != *value) {
|
if (parsed != *value) { *value = parsed; *changed = 1; }
|
||||||
*value = parsed;
|
|
||||||
*changed = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g_wstate.knob_edit_id = 0;
|
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.
|
// Normalize a value to [0,1] range.
|
||||||
static F32 value_normalize(F32 value, F32 max_val, B32 is_signed) {
|
static F32 value_normalize(F32 value, F32 max_val, B32 is_signed) {
|
||||||
F32 n;
|
F32 n;
|
||||||
if (is_signed) {
|
if (is_signed) { n = (value + max_val) / (2.0f * max_val); }
|
||||||
n = (value + max_val) / (2.0f * max_val);
|
else { n = value / max_val; }
|
||||||
} else {
|
|
||||||
n = value / max_val;
|
|
||||||
}
|
|
||||||
if (n < 0.0f) n = 0.0f;
|
if (n < 0.0f) n = 0.0f;
|
||||||
if (n > 1.0f) n = 1.0f;
|
if (n > 1.0f) n = 1.0f;
|
||||||
return n;
|
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) {
|
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;
|
if (g_knob_text_buf_count >= UI_MAX_KNOB_TEXT_BUFS) return nullptr;
|
||||||
char *buf = g_knob_text_bufs[g_knob_text_buf_count++];
|
char *buf = g_knob_text_bufs[g_knob_text_buf_count++];
|
||||||
if (is_signed) {
|
if (is_signed) { *out_len = snprintf(buf, 32, "%+.1f", value); }
|
||||||
*out_len = snprintf(buf, 32, "%+.1f", value);
|
else { *out_len = snprintf(buf, 32, "%.1f", value); }
|
||||||
} else {
|
|
||||||
*out_len = snprintf(buf, 32, "%.1f", value);
|
|
||||||
}
|
|
||||||
return buf;
|
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;
|
F32 lo = is_signed ? -max_val : 0.0f;
|
||||||
if (new_val < lo) new_val = lo;
|
if (new_val < lo) new_val = lo;
|
||||||
if (new_val > max_val) new_val = max_val;
|
if (new_val > max_val) new_val = max_val;
|
||||||
if (new_val != *value) {
|
if (new_val != *value) { *value = new_val; changed = 1; }
|
||||||
*value = new_val;
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
normalized = value_normalize(*value, max_val, is_signed);
|
normalized = value_normalize(*value, max_val, is_signed);
|
||||||
angle_rad = (-135.0f + normalized * 270.0f) * deg_to_rad;
|
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,
|
.childGap = WIDGET_KNOB_LABEL_GAP,
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
Clay_ElementId knob_eid = CLAY_IDI("KnobBg", (S32)knob_hash);
|
Clay_ElementId knob_eid = CLAY_IDI("KnobBg", (S32)knob_hash);
|
||||||
B32 hovered = Clay_PointerOver(knob_eid);
|
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) },
|
.sizing = { .width = CLAY_SIZING_FIXED(knob_size), .height = CLAY_SIZING_FIXED(knob_size) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
.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) {
|
if (g_rotated_icon_pool_count < UI_MAX_ROTATED_ICONS_PER_FRAME) {
|
||||||
S32 ri_idx = g_rotated_icon_pool_count;
|
S32 ri_idx = g_rotated_icon_pool_count;
|
||||||
CustomRotatedIconData *rdata = &g_rotated_icon_pool[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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(icon_size), .height = CLAY_SIZING_FIXED(icon_size) },
|
.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;
|
kd->last_click_frame = g_frame_number;
|
||||||
|
|
||||||
if (is_double_click) {
|
if (is_double_click) {
|
||||||
if (*value != default_val) {
|
if (*value != default_val) { *value = default_val; changed = 1; }
|
||||||
*value = default_val;
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
normalized = value_normalize(*value, max_val, is_signed);
|
normalized = value_normalize(*value, max_val, is_signed);
|
||||||
angle_rad = (-135.0f + normalized * 270.0f) * deg_to_rad;
|
angle_rad = (-135.0f + normalized * 270.0f) * deg_to_rad;
|
||||||
kd->last_click_id = 0;
|
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() },
|
.sizing = { .width = CLAY_SIZING_FIXED(knob_size), .height = CLAY_SIZING_FIT() },
|
||||||
.padding = { uip(2), uip(2), uip(1), uip(1) },
|
.padding = { uip(2), uip(2), uip(1), uip(1) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
CLAY_TEXT(val_str, &knob_val_cfg);
|
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;
|
F32 lo = is_signed ? -max_val : 0.0f;
|
||||||
if (new_val < lo) new_val = lo;
|
if (new_val < lo) new_val = lo;
|
||||||
if (new_val > max_val) new_val = max_val;
|
if (new_val > max_val) new_val = max_val;
|
||||||
if (new_val != *value) {
|
if (new_val != *value) { *value = new_val; changed = 1; }
|
||||||
*value = new_val;
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
normalized = value_normalize(*value, max_val, is_signed);
|
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,
|
.childGap = WIDGET_KNOB_LABEL_GAP,
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Label
|
// Label
|
||||||
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(thumb_h) },
|
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(thumb_h) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Visible track (centered inside hit area)
|
// Visible track (centered inside hit area)
|
||||||
CLAY(CLAY_IDI("SlHTrack", (S32)hash),
|
CLAY(CLAY_IDI("SlHTrack", (S32)hash),
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
|
.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
|
// Fill bar
|
||||||
F32 fill_w = normalized * track_w;
|
F32 fill_w = normalized * track_w;
|
||||||
if (fill_w < 1.0f) fill_w = 1.0f;
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(fill_w), .height = CLAY_SIZING_GROW() },
|
.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)
|
// 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,
|
.attachTo = CLAY_ATTACH_TO_PARENT,
|
||||||
.clipTo = CLAY_CLIP_TO_ATTACHED_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;
|
kd->last_click_frame = g_frame_number;
|
||||||
|
|
||||||
if (is_double_click) {
|
if (is_double_click) {
|
||||||
if (*value != default_val) {
|
if (*value != default_val) { *value = default_val; changed = 1; }
|
||||||
*value = default_val;
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
normalized = value_normalize(*value, max_val, is_signed);
|
normalized = value_normalize(*value, max_val, is_signed);
|
||||||
kd->last_click_id = 0;
|
kd->last_click_id = 0;
|
||||||
} else {
|
} 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() },
|
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIT() },
|
||||||
.padding = { uip(2), uip(2), uip(1), uip(1) },
|
.padding = { uip(2), uip(2), uip(1), uip(1) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
CLAY_TEXT(val_str, &sl_val_cfg);
|
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;
|
F32 lo = is_signed ? -max_val : 0.0f;
|
||||||
if (new_val < lo) new_val = lo;
|
if (new_val < lo) new_val = lo;
|
||||||
if (new_val > max_val) new_val = max_val;
|
if (new_val > max_val) new_val = max_val;
|
||||||
if (new_val != *value) {
|
if (new_val != *value) { *value = new_val; changed = 1; }
|
||||||
*value = new_val;
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
normalized = value_normalize(*value, max_val, is_signed);
|
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,
|
.childGap = WIDGET_KNOB_LABEL_GAP,
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Label
|
// Label
|
||||||
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(thumb_w), .height = CLAY_SIZING_FIXED(track_h) },
|
.sizing = { .width = CLAY_SIZING_FIXED(thumb_w), .height = CLAY_SIZING_FIXED(track_h) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Visible track (centered inside hit area)
|
// Visible track (centered inside hit area)
|
||||||
CLAY(CLAY_IDI("SlVTrack", (S32)hash),
|
CLAY(CLAY_IDI("SlVTrack", (S32)hash),
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
|
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
|
||||||
.childAlignment = { .y = CLAY_ALIGN_Y_BOTTOM },
|
.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)
|
// Fill bar (from bottom)
|
||||||
F32 fill_h = normalized * track_h;
|
F32 fill_h = normalized * track_h;
|
||||||
if (fill_h < 1.0f) fill_h = 1.0f;
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(fill_h) },
|
.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)
|
// 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,
|
.attachTo = CLAY_ATTACH_TO_PARENT,
|
||||||
.clipTo = CLAY_CLIP_TO_ATTACHED_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;
|
kd->last_click_frame = g_frame_number;
|
||||||
|
|
||||||
if (is_double_click) {
|
if (is_double_click) {
|
||||||
if (*value != default_val) {
|
if (*value != default_val) { *value = default_val; changed = 1; }
|
||||||
*value = default_val;
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
normalized = value_normalize(*value, max_val, is_signed);
|
normalized = value_normalize(*value, max_val, is_signed);
|
||||||
kd->last_click_id = 0;
|
kd->last_click_id = 0;
|
||||||
} else {
|
} 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() },
|
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
|
||||||
.padding = { uip(2), uip(2), uip(1), uip(1) },
|
.padding = { uip(2), uip(2), uip(1), uip(1) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
CLAY_TEXT(val_str, &sl_val_cfg);
|
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;
|
F32 lo = is_signed ? -max_val : 0.0f;
|
||||||
if (new_val < lo) new_val = lo;
|
if (new_val < lo) new_val = lo;
|
||||||
if (new_val > max_val) new_val = max_val;
|
if (new_val > max_val) new_val = max_val;
|
||||||
if (new_val != *value) {
|
if (new_val != *value) { *value = new_val; changed = 1; }
|
||||||
*value = new_val;
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
normalized = value_normalize(*value, max_val, is_signed);
|
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,
|
.childGap = WIDGET_KNOB_LABEL_GAP,
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Label
|
// Label
|
||||||
CLAY_TEXT(clay_str(label), &g_widget_text_config_dim);
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(track_h) },
|
.sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(track_h) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
// Visible track (centered inside hit area, empty)
|
// Visible track (centered inside hit area, empty)
|
||||||
CLAY(CLAY_IDI("FdrTrack", (S32)hash),
|
CLAY(CLAY_IDI("FdrTrack", (S32)hash),
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(track_w), .height = CLAY_SIZING_FIXED(track_h) },
|
.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
|
// Tick marks on both sides of the track
|
||||||
for (S32 i = 0; i <= num_ticks; i++) {
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(tw), .height = CLAY_SIZING_FIXED(tick_h) },
|
.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 = {
|
.offset = {
|
||||||
.x = track_left - tw,
|
.x = track_left - tw,
|
||||||
.y = tick_y,
|
.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,
|
.pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH,
|
||||||
.attachTo = CLAY_ATTACH_TO_PARENT,
|
.attachTo = CLAY_ATTACH_TO_PARENT,
|
||||||
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
|
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
|
||||||
}, ) {}
|
},
|
||||||
|
) {}
|
||||||
|
|
||||||
// Right tick
|
// Right tick
|
||||||
CLAY(CLAY_IDI("FdrTkR", (S32)(hash * 100 + i)),
|
CLAY(CLAY_IDI("FdrTkR", (S32)(hash * 100 + i)),
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(tw), .height = CLAY_SIZING_FIXED(tick_h) },
|
.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 = {
|
.offset = {
|
||||||
.x = track_left + track_w,
|
.x = track_left + track_w,
|
||||||
.y = tick_y,
|
.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,
|
.pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH,
|
||||||
.attachTo = CLAY_ATTACH_TO_PARENT,
|
.attachTo = CLAY_ATTACH_TO_PARENT,
|
||||||
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
|
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
|
||||||
}, ) {}
|
},
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Floating fader cap (RGBA icon from asset SVG)
|
// 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++];
|
CustomIconData *idata = &g_icon_pool[g_icon_pool_count++];
|
||||||
idata->type = CUSTOM_RENDER_ICON;
|
idata->type = CUSTOM_RENDER_ICON;
|
||||||
idata->icon_id = (S32)UI_ICON_FADER;
|
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);
|
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,
|
.attachTo = CLAY_ATTACH_TO_PARENT,
|
||||||
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
|
.clipTo = CLAY_CLIP_TO_ATTACHED_PARENT,
|
||||||
},
|
},
|
||||||
.custom = { .customData = idata }, ) {}
|
.custom = { .customData = idata },
|
||||||
|
) {}
|
||||||
|
|
||||||
// Color tint overlay on top of fader cap
|
// Color tint overlay on top of fader cap
|
||||||
Clay_Color tint = g_theme.accent;
|
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 = {
|
.layout = {
|
||||||
.sizing = { .width = CLAY_SIZING_FIXED(cap_w), .height = CLAY_SIZING_FIXED(cap_h) },
|
.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 },
|
.offset = { .x = 0, .y = cap_y },
|
||||||
.attachPoints = {
|
.attachPoints = {
|
||||||
.element = CLAY_ATTACH_POINT_LEFT_TOP,
|
.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,
|
.pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH,
|
||||||
.attachTo = CLAY_ATTACH_TO_PARENT,
|
.attachTo = CLAY_ATTACH_TO_PARENT,
|
||||||
.clipTo = CLAY_CLIP_TO_ATTACHED_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;
|
kd->last_click_frame = g_frame_number;
|
||||||
|
|
||||||
if (is_double_click) {
|
if (is_double_click) {
|
||||||
if (*value != default_val) {
|
if (*value != default_val) { *value = default_val; changed = 1; }
|
||||||
*value = default_val;
|
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
normalized = value_normalize(*value, max_val, is_signed);
|
normalized = value_normalize(*value, max_val, is_signed);
|
||||||
kd->last_click_id = 0;
|
kd->last_click_id = 0;
|
||||||
} else {
|
} 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() },
|
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
|
||||||
.padding = { uip(2), uip(2), uip(1), uip(1) },
|
.padding = { uip(2), uip(2), uip(1), uip(1) },
|
||||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
.childAlignment = { .x = CLAY_ALIGN_X_CENTER },
|
||||||
}) {
|
}
|
||||||
|
) {
|
||||||
CLAY_TEXT(val_str, &fdr_val_cfg);
|
CLAY_TEXT(val_str, &fdr_val_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
// The caller owns all data — the widget layer only stores transient UI state
|
// The caller owns all data — the widget layer only stores transient UI state
|
||||||
// like which text field is focused or which dropdown is open.
|
// like which text field is focused or which dropdown is open.
|
||||||
|
|
||||||
#include "platform/platform.h"
|
|
||||||
#include "ui/ui_core.h"
|
#include "ui/ui_core.h"
|
||||||
#include "ui/ui_icons.h"
|
#include "ui/ui_icons.h"
|
||||||
|
#include "platform/platform.h"
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Widget state (global, managed by widget layer)
|
// Widget state (global, managed by widget layer)
|
||||||
|
|||||||
Reference in New Issue
Block a user