ui tweaks
This commit is contained in:
26
README.md
26
README.md
@@ -26,7 +26,7 @@ cc build.c -o build
|
||||
open build_debug/autosample.app
|
||||
```
|
||||
|
||||
The first command is a one-time bootstrap. After that, `./build` detects changes to `build.c` and rebuilds itself automatically. Pass `debug` for a debug build (output in `build_debug/`) or omit for release (`build_release/`). Pass `clean` to wipe the build directory.
|
||||
The first command is a one-time bootstrap. After that, `./build` detects changes to `build.c` and rebuilds itself automatically. Pass `debug` for a debug build (output in `build_debug/`) or omit for release (`build_release/`). Pass `clean` to wipe both build directories, vendor libraries, and generated sources. Invalid arguments produce an error with usage info.
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -40,7 +40,7 @@ Foundational types and utilities shared across the project. Provides sized integ
|
||||
|
||||
Abstracts window creation, event polling, menus, clipboard, and native handles behind a C-style API with opaque `PlatformWindow` handles.
|
||||
|
||||
- **Windows**: `platform_win32.cpp` — Win32/HWND, `WM_*` message loop
|
||||
- **Windows**: `platform_win32.cpp` — Win32/HWND, `WM_*` message loop, per-monitor DPI awareness (v2) with `WM_DPICHANGED` handling
|
||||
- **macOS**: `platform_macos.mm` — Cocoa/AppKit, NSWindow, NSTextInputClient
|
||||
|
||||
### UI layer (`src/ui/`)
|
||||
@@ -74,10 +74,10 @@ Interactive elements use subtle visual effects for a DAW-style look:
|
||||
|
||||
Custom SDF-based pipeline for UI rendering. Processes Clay's `Clay_RenderCommandArray` output directly — no intermediate scene graph.
|
||||
|
||||
- **Windows**: `renderer_dx12.cpp` — DirectX 12, HLSL shaders, GDI font atlas (Segoe UI)
|
||||
- **macOS**: `renderer_metal.mm` — Metal, MSL shaders, Core Text font atlas (SF Pro)
|
||||
- **Windows**: `renderer_dx12.cpp` — DirectX 12, HLSL shaders
|
||||
- **macOS**: `renderer_metal.mm` — Metal, MSL shaders
|
||||
|
||||
Both renderers share the same vertex format (18 floats), SDF rounded-rect shader, and Clay command processing logic. Text measurement uses GDI on Windows and Core Text on macOS.
|
||||
Both renderers share the same vertex format (18 floats), SDF rounded-rect shader, and Clay command processing logic. Font rasterization and text measurement use FreeType on both platforms with the embedded [Inter](https://rsms.me/inter/) typeface. The font atlas is a 1024x1024 R8 texture containing ASCII glyphs 32–126 rasterized at a fixed pixel size; text at other sizes is scaled from the atlas. The Inter TTF is embedded at build time as a C byte array (`font_inter.gen.h`) so there are no runtime font file dependencies. Font scale is multiplied by the platform DPI scale factor for crisp rendering on high-DPI displays.
|
||||
|
||||
### Audio (`src/audio/`)
|
||||
|
||||
@@ -96,12 +96,19 @@ MIDI device enumeration with real-time input monitoring.
|
||||
## Project structure
|
||||
|
||||
```
|
||||
build.c Build script (cc build.c -o nob)
|
||||
build.c Build script (cc build.c -o build)
|
||||
assets/
|
||||
fonts/
|
||||
Inter-Regular.ttf Inter typeface (SIL Open Font License)
|
||||
OFL.txt Font license
|
||||
vendor/
|
||||
nob/
|
||||
nob.h nob build system (vendored, single-header)
|
||||
clay/
|
||||
clay.h Clay v0.14 (modified for MSVC C++ compatibility)
|
||||
freetype/
|
||||
include/ FreeType 2.13.3 public headers
|
||||
src/ FreeType source (minimal module set)
|
||||
src/
|
||||
main.cpp Entry point, unity build includes, Clay layout
|
||||
menus.cpp Menu bar setup
|
||||
@@ -113,12 +120,13 @@ src/
|
||||
base_inc.h / .cpp Aggregate include/impl
|
||||
platform/
|
||||
platform.h Window management API (platform-agnostic)
|
||||
platform_win32.cpp Win32 implementation
|
||||
platform_win32.cpp Win32 implementation (per-monitor DPI aware)
|
||||
platform_macos.mm macOS Cocoa implementation
|
||||
renderer/
|
||||
renderer.h Renderer API (graphics-agnostic)
|
||||
renderer_dx12.cpp DirectX 12 implementation
|
||||
renderer_metal.mm Metal implementation
|
||||
font_inter.gen.h Generated at build time — embedded font data
|
||||
ui/
|
||||
ui_core.h Clay wrapper, UI_Theme, scale helpers, custom render types
|
||||
ui_core.cpp Clay init, text measurement bridge, theme/accent palettes
|
||||
@@ -157,8 +165,10 @@ Memory should be managed with arena allocators where possible rather than indivi
|
||||
|
||||
## Dependencies
|
||||
|
||||
All dependencies are vendored as source. On Windows, nothing to install beyond the Windows SDK. On macOS, only Xcode Command Line Tools are needed — all frameworks (Metal, Cocoa, CoreAudio, CoreMIDI, CoreText, etc.) ship with the OS.
|
||||
All dependencies are vendored as source. On Windows, nothing to install beyond the Windows SDK. On macOS, only Xcode Command Line Tools are needed — all frameworks (Metal, Cocoa, CoreAudio, CoreMIDI, etc.) ship with the OS.
|
||||
|
||||
- [nob.h](https://github.com/tsoding/nob.h) — build system
|
||||
- [Clay](https://github.com/nicbarker/clay) — single-header C layout library (v0.14, with MSVC C++ patches)
|
||||
- [FreeType](https://freetype.org/) — font rasterizer (v2.13.3, FreeType License). Compiled as a static library with a minimal module set (truetype, sfnt, smooth, autofit, psnames, pshinter, gzip). Replaces platform-specific font backends (GDI on Windows, Core Text on macOS) for consistent cross-platform text rendering. Static libraries are built into their vendor directories (`vendor/freetype/freetype.lib` on Windows, `vendor/freetype/libfreetype.a` on macOS); debug builds on Windows use a `_d` suffix to avoid CRT mismatch.
|
||||
- [Inter](https://rsms.me/inter/) — typeface (v4.1, SIL Open Font License). Embedded at build time as a C byte array header so there are no runtime font file dependencies.
|
||||
- [LunaSVG](https://github.com/nicbarker/lunasvg) — SVG rendering library (MIT, by Samuel Ugochukwu) used to rasterize icon SVGs into an R8 texture atlas at startup. Icons (close, check, chevron, knob) are defined as inline SVG strings in `ui_icons.cpp` and rendered at a fixed pixel size into a packed atlas. The atlas is uploaded to the GPU once and sampled by the renderer for icon and rotated-icon custom elements. Bundled with [PlutoVG](https://github.com/nicbarker/plutovg) as its 2D vector graphics backend.
|
||||
|
||||
47
src/main.cpp
47
src/main.cpp
@@ -1004,10 +1004,35 @@ static void update_panel_splitters(AppState *app) {
|
||||
B32 mouse_released = !input.mouse_down && input.was_mouse_down;
|
||||
PlatformCursor cursor = PLATFORM_CURSOR_ARROW;
|
||||
|
||||
// Check hover on splitter elements (uses previous-frame layout)
|
||||
B32 hover_browser = Clay_PointerOver(CLAY_ID("SplitBrowser"));
|
||||
B32 hover_right = Clay_PointerOver(CLAY_ID("SplitRight"));
|
||||
B32 hover_log = Clay_PointerOver(CLAY_ID("SplitLog"));
|
||||
// Check hover on splitter elements with expanded hit area (splitters are 1px)
|
||||
F32 grab_margin = uis(3);
|
||||
F32 mx = input.mouse_pos.x, my = input.mouse_pos.y;
|
||||
|
||||
B32 hover_browser = false, hover_right = false, hover_log = false;
|
||||
{
|
||||
Clay_ElementData d = Clay_GetElementData(CLAY_ID("SplitBrowser"));
|
||||
if (d.found) {
|
||||
Clay_BoundingBox b = d.boundingBox;
|
||||
hover_browser = mx >= b.x - grab_margin && mx <= b.x + b.width + grab_margin &&
|
||||
my >= b.y && my <= b.y + b.height;
|
||||
}
|
||||
}
|
||||
{
|
||||
Clay_ElementData d = Clay_GetElementData(CLAY_ID("SplitRight"));
|
||||
if (d.found) {
|
||||
Clay_BoundingBox b = d.boundingBox;
|
||||
hover_right = mx >= b.x - grab_margin && mx <= b.x + b.width + grab_margin &&
|
||||
my >= b.y && my <= b.y + b.height;
|
||||
}
|
||||
}
|
||||
{
|
||||
Clay_ElementData d = Clay_GetElementData(CLAY_ID("SplitLog"));
|
||||
if (d.found) {
|
||||
Clay_BoundingBox b = d.boundingBox;
|
||||
hover_log = mx >= b.x && mx <= b.x + b.width &&
|
||||
my >= b.y - grab_margin && my <= b.y + b.height + grab_margin;
|
||||
}
|
||||
}
|
||||
|
||||
// Start drag
|
||||
if (mouse_clicked && app->panel_drag == 0) {
|
||||
@@ -1061,7 +1086,7 @@ static void update_panel_splitters(AppState *app) {
|
||||
// Header bar — transport / layout toggle
|
||||
|
||||
static void build_header_bar(AppState *app) {
|
||||
Clay_Color bar_bg = g_theme.bg_dark;
|
||||
Clay_Color bar_bg = g_theme.header_bg;
|
||||
Clay_Color border_bot = {(F32)Max((S32)bar_bg.r - 12, 0), (F32)Max((S32)bar_bg.g - 12, 0), (F32)Max((S32)bar_bg.b - 12, 0), 255};
|
||||
|
||||
static Clay_TextElementConfig header_btn_active_text = {};
|
||||
@@ -1796,10 +1821,10 @@ static void build_ui(AppState *app) {
|
||||
) {
|
||||
build_browser_panel(app);
|
||||
|
||||
// Browser splitter (vertical, 4px wide)
|
||||
// Browser splitter (vertical, 1px line)
|
||||
if (app->show_browser) {
|
||||
CLAY(CLAY_ID("SplitBrowser"),
|
||||
.layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(4)), .height = CLAY_SIZING_GROW() } },
|
||||
.layout = { .sizing = { .width = CLAY_SIZING_FIXED(1), .height = CLAY_SIZING_GROW() } },
|
||||
.backgroundColor = g_theme.border
|
||||
) {}
|
||||
}
|
||||
@@ -1807,9 +1832,9 @@ static void build_ui(AppState *app) {
|
||||
build_main_panel(app);
|
||||
|
||||
if (app->show_props || app->show_midi_devices) {
|
||||
// Right splitter (vertical, 4px wide)
|
||||
// Right splitter (vertical, 1px line)
|
||||
CLAY(CLAY_ID("SplitRight"),
|
||||
.layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(4)), .height = CLAY_SIZING_GROW() } },
|
||||
.layout = { .sizing = { .width = CLAY_SIZING_FIXED(1), .height = CLAY_SIZING_GROW() } },
|
||||
.backgroundColor = g_theme.border
|
||||
) {}
|
||||
|
||||
@@ -1824,10 +1849,10 @@ static void build_ui(AppState *app) {
|
||||
}
|
||||
}
|
||||
|
||||
// Log splitter (horizontal, 4px tall)
|
||||
// Log splitter (horizontal, 1px line)
|
||||
if (app->show_log) {
|
||||
CLAY(CLAY_ID("SplitLog"),
|
||||
.layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(uis(4)) } },
|
||||
.layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(1) } },
|
||||
.backgroundColor = g_theme.border
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ void ui_set_theme(S32 theme_id) {
|
||||
g_theme.button_text = Clay_Color{224, 224, 224, 255};
|
||||
g_theme.disabled_bg = Clay_Color{ 44, 44, 44, 255};
|
||||
g_theme.disabled_text = Clay_Color{ 90, 90, 90, 255};
|
||||
g_theme.header_bg = Clay_Color{ 46, 46, 46, 255};
|
||||
g_theme.title_bar = Clay_Color{ 22, 22, 22, 255};
|
||||
g_theme.scrollbar_bg = Clay_Color{ 22, 22, 22, 255};
|
||||
g_theme.scrollbar_grab = Clay_Color{ 58, 58, 58, 255};
|
||||
@@ -64,6 +65,7 @@ void ui_set_theme(S32 theme_id) {
|
||||
g_theme.button_text = Clay_Color{255, 255, 255, 255};
|
||||
g_theme.disabled_bg = Clay_Color{185, 183, 180, 255};
|
||||
g_theme.disabled_text = Clay_Color{145, 143, 140, 255};
|
||||
g_theme.header_bg = Clay_Color{202, 200, 197, 255};
|
||||
g_theme.title_bar = Clay_Color{202, 200, 197, 255};
|
||||
g_theme.scrollbar_bg = Clay_Color{202, 200, 197, 255};
|
||||
g_theme.scrollbar_grab = Clay_Color{168, 166, 163, 255};
|
||||
|
||||
@@ -61,6 +61,7 @@ struct UI_Theme {
|
||||
Clay_Color button_text;
|
||||
Clay_Color disabled_bg;
|
||||
Clay_Color disabled_text;
|
||||
Clay_Color header_bg;
|
||||
Clay_Color title_bar;
|
||||
Clay_Color scrollbar_bg;
|
||||
Clay_Color scrollbar_grab;
|
||||
|
||||
Reference in New Issue
Block a user