Fix zoom to cursor, trigger re-render on palette/dB changes, improve controls

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-03-27 23:10:16 -07:00
parent 377ba3616a
commit 10e7a68baa
+53 -27
View File
@@ -813,20 +813,20 @@ static void DrawInfo(Rectangle bounds)
DrawText("No audio file loaded", 10, y, fontSize, RED);
}
y = GetScreenHeight() - 240;
y = GetScreenHeight() - 260;
DrawText("Controls:", 10, y, fontSize, LIGHTGRAY); y += 20;
DrawText(" O - Open file browser", 10, y, fontSize, GRAY); y += 18;
DrawText(" Drag & drop WAV file", 10, y, fontSize, GRAY); y += 18;
DrawText(" Mouse Wheel - Zoom time", 10, y, fontSize, GRAY); y += 18;
DrawText(" Alt+Drag - Pan view", 10, y, fontSize, GRAY); y += 18;
DrawText(" LMB Drag - Select time", 10, y, fontSize, GRAY); y += 18;
DrawText(" Shift+LMB - Select freq", 10, y, fontSize, GRAY); y += 18;
DrawText(" Mouse Wheel - Zoom to cursor", 10, y, fontSize, GRAY); y += 18;
DrawText(" Alt/Middle+Drag - Pan view", 10, y, fontSize, GRAY); y += 18;
DrawText(" LMB Drag - Select time region", 10, y, fontSize, GRAY); y += 18;
DrawText(" Shift+LMB - Select freq range", 10, y, fontSize, GRAY); y += 18;
DrawText(" SPACE - Play selection", 10, y, fontSize, GRAY); y += 18;
DrawText(" M - Change colormap", 10, y, fontSize, GRAY); y += 18;
DrawText(" M - Cycle colormap", 10, y, fontSize, GRAY); y += 18;
DrawText(" W/S - Adjust dB floor", 10, y, fontSize, GRAY); y += 18;
DrawText(" G - Toggle grid", 10, y, fontSize, GRAY); y += 18;
DrawText(" R - Reset selections", 10, y, fontSize, GRAY); y += 18;
DrawText(" Home/End - Full view/Zoom in", 10, y, fontSize, GRAY); y += 18;
DrawText(" Home - Full view, End - Zoom in", 10, y, fontSize, GRAY); y += 18;
DrawText(" ESC - Clear selections", 10, y, fontSize, GRAY);
y = GetScreenHeight() - 60;
@@ -917,55 +917,77 @@ int main(int argc, char* argv[])
// View controls
if (app.loaded && !app.showFileBrowser) {
// Zoom with mouse wheel
if (CheckCollisionPointRec(GetMousePosition(), (Rectangle){ 100, 50, GetScreenWidth() - 150, GetScreenHeight() - 150 })) {
Rectangle viewBounds = { 100, 50, GetScreenWidth() - 150, GetScreenHeight() - 150 };
// Zoom with mouse wheel (zooms to cursor position)
if (CheckCollisionPointRec(GetMousePosition(), viewBounds)) {
int wheel = GetMouseWheelMove();
if (wheel != 0) {
float viewCenter = (app.viewStart + app.viewEnd) / 2;
// Calculate mouse position as normalized time (0-1)
float mouseT = (GetMousePosition().x - viewBounds.x) / viewBounds.width;
mouseT = Clamp(mouseT + app.viewStart, 0.0f, 1.0f);
float viewWidth = app.viewEnd - app.viewStart;
float zoomFactor = (wheel > 0) ? 0.8f : 1.2f;
float newWidth = viewWidth * zoomFactor;
if (newWidth < 0.05f) newWidth = 0.05f;
if (newWidth < 0.02f) newWidth = 0.02f;
if (newWidth > 1.0f) newWidth = 1.0f;
app.viewStart = viewCenter - newWidth / 2;
app.viewEnd = viewCenter + newWidth / 2;
// Zoom around cursor position
float leftOfMouse = mouseT - app.viewStart;
float rightOfMouse = app.viewEnd - mouseT;
float newLeftOfMouse = leftOfMouse * (newWidth / viewWidth);
float newRightOfMouse = rightOfMouse * (newWidth / viewWidth);
app.viewStart = mouseT - newLeftOfMouse;
app.viewEnd = mouseT + newRightOfMouse;
// Clamp to valid range
if (app.viewStart < 0) { app.viewStart = 0; app.viewEnd = newWidth; }
if (app.viewEnd > 1) { app.viewEnd = 1; app.viewStart = 1 - newWidth; }
// Invalidate texture cache
app.visibleTextureValid = false;
}
}
// Pan with Alt+drag
bool altHeld = IsKeyDown(KEY_LEFT_ALT) || IsKeyDown(KEY_RIGHT_ALT);
if (altHeld && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
// Pan with Alt+drag or middle mouse button
bool canPan = IsKeyDown(KEY_LEFT_ALT) || IsKeyDown(KEY_RIGHT_ALT) || IsMouseButtonDown(MOUSE_BUTTON_MIDDLE);
if (canPan && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
app.isPanning = true;
app.panStartPos = GetMousePosition();
app.panStartViewStart = app.viewStart;
app.panStartViewEnd = app.viewEnd;
}
if (app.isPanning && IsMouseButtonDown(MOUSE_LEFT_BUTTON)) {
Rectangle bounds = { 100, 50, GetScreenWidth() - 150, GetScreenHeight() - 150 };
if (CheckCollisionPointRec(app.panStartPos, bounds)) {
float dx = (GetMousePosition().x - app.panStartPos.x) / bounds.width;
float viewWidth = app.panStartViewEnd - app.panStartViewStart;
app.viewStart = app.panStartViewStart - dx * viewWidth;
app.viewEnd = app.panStartViewEnd - dx * viewWidth;
if (app.viewStart < 0) { app.viewStart = 0; app.viewEnd = viewWidth; }
if (app.viewEnd > 1) { app.viewEnd = 1; app.viewStart = 1 - viewWidth; }
}
float dx = (GetMousePosition().x - app.panStartPos.x) / viewBounds.width;
float viewWidth = app.panStartViewEnd - app.panStartViewStart;
app.viewStart = app.panStartViewStart - dx * viewWidth;
app.viewEnd = app.panStartViewEnd - dx * viewWidth;
if (app.viewStart < 0) { app.viewStart = 0; app.viewEnd = viewWidth; }
if (app.viewEnd > 1) { app.viewEnd = 1; app.viewStart = 1 - viewWidth; }
app.visibleTextureValid = false;
}
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) app.isPanning = false;
// Home/End keys
if (IsKeyPressed(KEY_HOME)) { app.viewStart = 0.0f; app.viewEnd = 1.0f; }
if (IsKeyPressed(KEY_HOME)) {
app.viewStart = 0.0f; app.viewEnd = 1.0f;
app.visibleTextureValid = false;
}
if (IsKeyPressed(KEY_END)) {
float newWidth = 0.1f;
app.viewStart = 0.0f;
app.viewEnd = newWidth;
app.visibleTextureValid = false;
}
}
// Other controls
if (IsKeyPressed(KEY_G) && !app.showFileBrowser) app.showGrid = !app.showFileBrowser;
if (IsKeyPressed(KEY_G) && !app.showFileBrowser) {
app.showGrid = !app.showGrid;
}
if (IsKeyPressed(KEY_R) && !app.showFileBrowser) {
app.timeSelectionStart = app.viewStart;
app.timeSelectionEnd = app.viewEnd;
@@ -975,16 +997,20 @@ int main(int argc, char* argv[])
if (IsKeyPressed(KEY_M) && !app.showFileBrowser) {
app.colormap = (ColormapType)((app.colormap + 1) % COLORMAP_COUNT);
GenerateColormapTexture();
if (app.stftComputed) GenerateSpectrogramTexture(&app.stft, &app.spectrogramImage, &app.spectrogramTexture);
app.visibleTextureValid = false;
}
if (IsKeyPressed(KEY_W) && !app.showFileBrowser) {
app.amplitudeFloorDb += 2.0f;
if (app.amplitudeFloorDb > app.amplitudeCeilingDb - 5) app.amplitudeFloorDb = app.amplitudeCeilingDb - 5;
if (app.stftComputed) GenerateSpectrogramTexture(&app.stft, &app.spectrogramImage, &app.spectrogramTexture);
app.visibleTextureValid = false;
}
if (IsKeyPressed(KEY_S) && !app.showFileBrowser) {
app.amplitudeFloorDb -= 2.0f;
if (app.amplitudeFloorDb < -100) app.amplitudeFloorDb = -100;
if (app.stftComputed) GenerateSpectrogramTexture(&app.stft, &app.spectrogramImage, &app.spectrogramTexture);
app.visibleTextureValid = false;
}
if (IsKeyPressed(KEY_SPACE) && !app.showFileBrowser) PlaySelectedRegion();