diff options
author | admin <admin@optics-design.com> | 2025-08-06 16:24:05 +0200 |
---|---|---|
committer | admin <admin@optics-design.com> | 2025-08-06 16:24:05 +0200 |
commit | 91c024d42e54c3db70fa9693525c0dc2b5e775fc (patch) | |
tree | ff52dd8da83533a277a8c5d320a5eab7a4d19054 | |
parent | a3389f25f786be7139feaca837c86442f7745745 (diff) |
last version with windows
-rw-r--r-- | include/glamac/graphics/glamac_view.h | 12 | ||||
-rw-r--r-- | src/glamac/glamac.c | 70 | ||||
-rw-r--r-- | src/glamac/glamac_render.c | 56 | ||||
-rw-r--r-- | src/glamac/glamac_view.c | 134 |
4 files changed, 200 insertions, 72 deletions
diff --git a/include/glamac/graphics/glamac_view.h b/include/glamac/graphics/glamac_view.h index a15aaf1..c7b00d9 100644 --- a/include/glamac/graphics/glamac_view.h +++ b/include/glamac/graphics/glamac_view.h @@ -8,8 +8,8 @@ #include "../core/glamacdef.h"
// Constants for view
-#define MIN_PADDING 15 // Minimum padding in pixels (reduced for small windows)
-#define MAX_PADDING_PERCENT 0.06f // Maximum padding as percentage of window size (increased for responsiveness)
+#define MIN_PADDING 20 // Minimum padding in pixels
+#define MAX_PADDING_PERCENT 0.04f // Maximum padding as percentage of window size
#define PAN_STEP 0.05f // Step size for keyboard panning
#define ZOOM_FACTOR 1.2f // Zoom factor for zoom operations
#define MIN_ZOOM 0.5f // Minimum zoom level
@@ -59,6 +59,7 @@ typedef struct { u32 gKeyTime; // Time when 'g' was pressed for sequence timing
i32 selectedGlass; // Index of selected glass (-1 if none)
b32 viewDirty; // Flag to track if view needs re-rendering
+ u32 forceRenderFrames; // Number of additional frames to force rendering (for transitions)
// Tight clustering data
TightCluster* tightClusters; // Array of tight clusters
@@ -79,6 +80,13 @@ static inline i32 get_adaptive_padding(const ViewState* view) { return padding > MIN_PADDING ? padding : MIN_PADDING;
}
+// Helper function to calculate adaptive padding for specific dimensions
+static inline i32 get_adaptive_padding_for_size(i32 windowWidth, i32 windowHeight) {
+ (void)windowHeight; // Suppress unused parameter warning
+ i32 padding = (i32)(windowWidth * MAX_PADDING_PERCENT);
+ return padding > MIN_PADDING ? padding : MIN_PADDING;
+}
+
// Convert glass data to screen coordinates with zoom and offset
static inline void data_to_screen_coords(f32 abbeNumber, f32 refractiveIndex,
const ViewState* view, i32 *x, i32 *y) {
diff --git a/src/glamac/glamac.c b/src/glamac/glamac.c index a26c7e6..7f361ab 100644 --- a/src/glamac/glamac.c +++ b/src/glamac/glamac.c @@ -36,9 +36,9 @@ b32 reload_fonts_if_needed(FontSet *fonts, ViewState *view, f32 dpi) { }
// Hysteresis parameters - reduced for better responsiveness
- const f32 threshold = 0.15f; // 15% change threshold (more sensitive for fullscreen)
- const u32 minReloadInterval = 50; // Minimum 50ms between font reloads (faster response)
- const u32 maxPendingTime = 300; // Maximum time to wait for pending reload
+ const f32 threshold = 0.25f; // 25% change threshold
+ const u32 minReloadInterval = 100; // Minimum 100ms between font reloads
+ const u32 maxPendingTime = 500; // Maximum time to wait for pending reload
u32 currentTime = SDL_GetTicks();
@@ -48,20 +48,13 @@ b32 reload_fonts_if_needed(FontSet *fonts, ViewState *view, f32 dpi) { b32 significantChange = (widthDiff > (i32)(view->windowWidth * threshold) ||
heightDiff > (i32)(view->windowHeight * threshold));
- // Detect major changes (like fullscreen transitions) - force immediate reload
- b32 majorChange = (widthDiff > 200 || heightDiff > 200 ||
- (lastWidth > 0 && lastHeight > 0 &&
- (abs(view->windowWidth - lastWidth) > (view->windowWidth / 2) ||
- abs(view->windowHeight - lastHeight) > (view->windowHeight / 2))));
-
- if (significantChange || majorChange) {
+ if (significantChange) {
// Update pending dimensions
pendingWidth = view->windowWidth;
pendingHeight = view->windowHeight;
- // For major changes, force immediate reload regardless of timing
- // For normal changes, check if enough time has passed since last reload
- if (majorChange || currentTime - lastReloadTime >= minReloadInterval) {
+ // Check if enough time has passed since last reload
+ if (currentTime - lastReloadTime >= minReloadInterval) {
if (is_debug_mode()) {
printf("Window size changed significantly: %dx%d -> %dx%d, reloading fonts...\n",
lastWidth, lastHeight, view->windowWidth, view->windowHeight);
@@ -111,7 +104,10 @@ b32 reload_fonts_if_needed(FontSet *fonts, ViewState *view, f32 dpi) { pendingWidth = pendingHeight = 0; // Clear pending state
// Mark view as dirty to re-render with new fonts
- mark_view_dirty(view);
+ // Only if not in the middle of forced rendering (e.g., from reset_view)
+ if (view->forceRenderFrames == 0) {
+ mark_view_dirty(view);
+ }
if (is_debug_mode()) {
printf("Fonts successfully reloaded for window size: %dx%d\n",
@@ -146,52 +142,6 @@ b32 reload_fonts_if_needed(FontSet *fonts, ViewState *view, f32 dpi) { return 1;
}
-// Force font reload (for fullscreen transitions and other critical updates)
-b32 force_font_reload(FontSet *fonts, ViewState *view, f32 dpi) {
- if (!fonts || !view) {
- printf("Error: Invalid parameters for forced font reload\n");
- return 0;
- }
-
- if (is_debug_mode()) {
- printf("Force reloading fonts for window size: %dx%d\n",
- view->windowWidth, view->windowHeight);
- }
-
- // Clear text cache first
- clear_text_cache();
-
- // Store current fonts as backup
- FontSet backup_fonts = *fonts;
-
- // Try to reload with new size
- if (!load_adaptive_fonts(fonts, view->windowWidth, view->windowHeight, dpi)) {
- printf("Error: Failed to force reload fonts, restoring backup\n");
-
- // Restore backup fonts
- *fonts = backup_fonts;
- return 0;
- }
-
- // Free backup fonts if new loading succeeded
- if (backup_fonts.regular != fonts->regular && backup_fonts.regular) {
- TTF_CloseFont(backup_fonts.regular);
- }
- if (backup_fonts.title != fonts->title && backup_fonts.title) {
- TTF_CloseFont(backup_fonts.title);
- }
- if (backup_fonts.label != fonts->label && backup_fonts.label) {
- TTF_CloseFont(backup_fonts.label);
- }
- if (backup_fonts.axis != fonts->axis && backup_fonts.axis) {
- TTF_CloseFont(backup_fonts.axis);
- }
- if (backup_fonts.label_bold != fonts->label_bold && backup_fonts.label_bold) {
- TTF_CloseFont(backup_fonts.label_bold);
- }
-
- return 1;
-}
// Initial window dimensions
#define INITIAL_WIDTH 800
diff --git a/src/glamac/glamac_render.c b/src/glamac/glamac_render.c index 9743e7f..c375754 100644 --- a/src/glamac/glamac_render.c +++ b/src/glamac/glamac_render.c @@ -366,6 +366,16 @@ void draw_axes(SDL_Renderer *renderer, const FontSet *fonts, const ViewState* vi f32 visibleMinAbbe, visibleMaxAbbe, visibleMinRI, visibleMaxRI;
get_visible_data_range(view, &visibleMinAbbe, &visibleMaxAbbe, &visibleMinRI, &visibleMaxRI);
+ if (is_debug_mode() && view->forceRenderFrames > 0) {
+ printf("Visible range: Abbe(%.2f-%.2f) RI(%.4f-%.4f), zoom=%.2f, offset=(%.2f,%.2f), window=%dx%d\n",
+ visibleMinAbbe, visibleMaxAbbe, visibleMinRI, visibleMaxRI,
+ view->zoomLevel, view->offsetX, view->offsetY, view->windowWidth, view->windowHeight);
+ printf("Full range: Abbe(%.2f-%.2f) RI(%.4f-%.4f)\n",
+ view->minAbbe, view->maxAbbe, view->minRI, view->maxRI);
+ printf("Plot area bounds: x=%d to %d, y=%d to %d\n",
+ padding, view->windowWidth - padding, padding, view->windowHeight - padding);
+ }
+
// Validate the visible range - fallback to full range if invalid
if (!isfinite(visibleMinAbbe) || !isfinite(visibleMaxAbbe) ||
!isfinite(visibleMinRI) || !isfinite(visibleMaxRI) ||
@@ -413,14 +423,28 @@ void draw_axes(SDL_Renderer *renderer, const FontSet *fonts, const ViewState* vi }
// Move the bottom-most number up slightly to avoid overlap with X-axis labels
i32 yOffset = (i == 0) ? -15 : -8;
- // Adaptive positioning based on window size
- i32 axisLabelOffset = (view->windowWidth < 600) ? padding - 35 : padding - 45;
+ // More conservative positioning to prevent cut-off
+ i32 axisLabelOffset;
+ if (view->windowWidth < 500) {
+ axisLabelOffset = padding - 30; // Very small windows - stay closer to axis
+ } else if (view->windowWidth < 700) {
+ axisLabelOffset = padding - 35; // Medium windows
+ } else {
+ axisLabelOffset = padding - 45; // Large windows
+ }
draw_text_direct(renderer, axisFont, buffer, axisLabelOffset, y + yOffset, black);
}
// Axis titles with subscripts - using regular font (2pt smaller than title)
- // Adaptive positioning based on window size
- i32 abbeNumberY = (view->windowHeight < 500) ? view->windowHeight - 25 : view->windowHeight - 35;
+ // More adaptive positioning to avoid collision with horizontal axis
+ i32 abbeNumberY;
+ if (view->windowHeight < 400) {
+ abbeNumberY = view->windowHeight - 20; // Very small windows
+ } else if (view->windowHeight < 600) {
+ abbeNumberY = view->windowHeight - 30; // Medium windows
+ } else {
+ abbeNumberY = view->windowHeight - 35; // Large windows
+ }
draw_text(renderer, fonts->regular, "Abbe Number (Vd)", view->windowWidth/2 - 80, abbeNumberY, black);
// Vertical text for Y-axis (simplified)
@@ -533,7 +557,20 @@ void draw_glass_points(SDL_Renderer *renderer, const FontSet *fonts, const ViewS }
// Debug output if enabled
- if (is_debug_mode()) {
+ if (is_debug_mode() && view->forceRenderFrames > 0) {
+ printf("Rendering: %u/%u glasses visible, %u labels drawn (zoom: %.2f)\n",
+ visibleCount, glassCount, labelCount, view->zoomLevel);
+
+ // Show coordinates of first few glasses for debugging
+ for (u32 i = 0; i < 3 && i < glassCount; i++) {
+ const Glass* glass = get_glass(i);
+ if (!glass) continue;
+ i32 x, y;
+ data_to_screen_coords(glass->abbeNumber, glass->refractiveIndex, view, &x, &y);
+ printf(" Glass %u (%.2f, %.4f) -> screen (%d, %d)\n",
+ i, glass->abbeNumber, glass->refractiveIndex, x, y);
+ }
+ } else if (is_debug_mode()) {
static u32 lastReportTime = 0;
u32 currentTime = SDL_GetTicks();
if (currentTime - lastReportTime > 1000) { // Report every second
@@ -732,11 +769,16 @@ void render(SDL_Renderer *renderer, const FontSet *fonts, ViewState* view) { printf("Error: Invalid fonts for render\n");
return;
}
- // Only render if view is dirty (needs update)
- if (!view->viewDirty) {
+ // Only render if view is dirty (needs update) or forced rendering is active
+ if (!view->viewDirty && view->forceRenderFrames == 0) {
return;
}
+ // Decrement forced rendering counter
+ if (view->forceRenderFrames > 0) {
+ view->forceRenderFrames--;
+ }
+
// Clear screen
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
diff --git a/src/glamac/glamac_view.c b/src/glamac/glamac_view.c index 35c5806..12c96fd 100644 --- a/src/glamac/glamac_view.c +++ b/src/glamac/glamac_view.c @@ -25,6 +25,7 @@ void init_view_state(ViewState* view, i32 windowWidth, i32 windowHeight) { view->gKeyTime = 0;
view->selectedGlass = -1; // No glass selected initially
view->viewDirty = 1; // Initial render needed
+ view->forceRenderFrames = 0; // No forced rendering initially
// Initialize tight clustering data
view->tightClusters = NULL;
@@ -61,6 +62,12 @@ void get_visible_data_range(const ViewState* view, f32 *visibleMinAbbe, f32 *vis screen_to_data_coords(view->windowWidth - padding, view->windowHeight - padding,
view, &bottomRightAbbe, &bottomRightRI);
+ if (is_debug_mode() && view->forceRenderFrames > 0) {
+ printf("Screen corners: top-left(%d,%d) -> data(%.2f,%.4f), bottom-right(%d,%d) -> data(%.2f,%.4f)\n",
+ padding, padding, topLeftAbbe, topLeftRI,
+ view->windowWidth - padding, view->windowHeight - padding, bottomRightAbbe, bottomRightRI);
+ }
+
// NOTE: With flipped axis, topLeftAbbe is now the maximum and bottomRightAbbe is minimum
*visibleMaxAbbe = topLeftAbbe;
*visibleMinAbbe = bottomRightAbbe;
@@ -130,31 +137,114 @@ void handle_mouse_wheel_zoom(i32 wheelY, i32 mouseX, i32 mouseY, ViewState* view void toggle_fullscreen(SDL_Window* window, ViewState* view) {
if (!window || !view) return;
+ // Store original windowed size for restoration
+ static i32 windowedWidth = 800; // Default windowed size
+ static i32 windowedHeight = 600;
+
bool isFullscreen = SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN;
if (!isFullscreen) {
+ // Store current windowed size before going fullscreen
+ windowedWidth = view->windowWidth;
+ windowedHeight = view->windowHeight;
+
// Entering fullscreen
SDL_SetWindowFullscreen(window, true);
} else {
- // Exiting fullscreen
+ // Exiting fullscreen - restore original windowed size
SDL_SetWindowFullscreen(window, false);
+
+ if (is_debug_mode()) {
+ printf("Restoring window size to %dx%d\n", windowedWidth, windowedHeight);
+ }
+
+ SDL_SetWindowSize(window, windowedWidth, windowedHeight);
+
+ // Also center the window for better behavior
+ SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}
- // Wait a bit longer for the window system to process the state change
- SDL_Delay(100);
+ // Wait longer for the window system to process the state change
+ SDL_Delay(200);
// Get updated window dimensions after fullscreen toggle
i32 newWidth, newHeight;
SDL_GetWindowSize(window, &newWidth, &newHeight);
+ // If we're exiting fullscreen and the size didn't change, force it
+ if (isFullscreen && (newWidth != windowedWidth || newHeight != windowedHeight)) {
+ if (is_debug_mode()) {
+ printf("Window size restoration failed (%dx%d != %dx%d), forcing update\n",
+ newWidth, newHeight, windowedWidth, windowedHeight);
+ }
+
+ // Try multiple times with delays
+ for (int attempt = 0; attempt < 3; attempt++) {
+ SDL_SetWindowSize(window, windowedWidth, windowedHeight);
+ SDL_Delay(100);
+ SDL_GetWindowSize(window, &newWidth, &newHeight);
+
+ if (newWidth == windowedWidth && newHeight == windowedHeight) {
+ if (is_debug_mode()) {
+ printf("Window size restoration succeeded on attempt %d\n", attempt + 1);
+ }
+ break;
+ }
+ }
+
+ // Final fallback - force the view state to match reality
+ if (newWidth != windowedWidth || newHeight != windowedHeight) {
+ if (is_debug_mode()) {
+ printf("Window size restoration failed completely, forcing view state update\n");
+ }
+ }
+ }
+
// Validate new dimensions
if (newWidth > 0 && newHeight > 0) {
+ if (is_debug_mode()) {
+ printf("Fullscreen toggle: %s, size: %dx%d -> %dx%d, zoom=%.2f, offset=(%.2f,%.2f)\n",
+ isFullscreen ? "OFF" : "ON",
+ view->windowWidth, view->windowHeight, newWidth, newHeight,
+ view->zoomLevel, view->offsetX, view->offsetY);
+ }
+
+ // Calculate the ratio of plotting areas to adjust zoom/offset
+ i32 oldPadding = get_adaptive_padding_for_size(view->windowWidth, view->windowHeight);
+ i32 newPadding = get_adaptive_padding_for_size(newWidth, newHeight);
+ i32 oldPlotWidth = view->windowWidth - 2 * oldPadding;
+ i32 oldPlotHeight = view->windowHeight - 2 * oldPadding;
+ i32 newPlotWidth = newWidth - 2 * newPadding;
+ i32 newPlotHeight = newHeight - 2 * newPadding;
+
+ // If plotting area changed significantly, reset zoom/offset to prevent partial view
+ f32 plotRatioX = (f32)newPlotWidth / (f32)oldPlotWidth;
+ f32 plotRatioY = (f32)newPlotHeight / (f32)oldPlotHeight;
+
+ if (is_debug_mode()) {
+ printf("Plot area change: %dx%d -> %dx%d (ratio: %.2fx%.2f)\n",
+ oldPlotWidth, oldPlotHeight, newPlotWidth, newPlotHeight, plotRatioX, plotRatioY);
+ }
+
+ // Reset view if plot area changes dramatically (more than 50% difference)
+ if (plotRatioX < 0.5f || plotRatioX > 2.0f || plotRatioY < 0.5f || plotRatioY > 2.0f) {
+ if (is_debug_mode()) {
+ printf("Dramatic plot area change detected, resetting zoom/offset\n");
+ }
+ view->zoomLevel = 1.0f;
+ view->offsetX = 0.0f;
+ view->offsetY = 0.0f;
+ }
+
view->windowWidth = newWidth;
view->windowHeight = newHeight;
// Force a complete refresh after fullscreen toggle
mark_view_dirty(view);
+ // Force rendering for several frames to ensure proper transition
+ view->forceRenderFrames = 3;
+
if (is_debug_mode()) {
printf("Fullscreen toggled: %s, new size: %dx%d\n",
isFullscreen ? "OFF" : "ON", newWidth, newHeight);
@@ -167,13 +257,51 @@ void toggle_fullscreen(SDL_Window* window, ViewState* view) { // Reset view to default
void reset_view(ViewState* view) {
+ if (is_debug_mode()) {
+ printf("Reset view: zoom=%.2f, offsetX=%.2f, offsetY=%.2f, window=%dx%d\n",
+ view->zoomLevel, view->offsetX, view->offsetY, view->windowWidth, view->windowHeight);
+ printf("Data bounds before reset: Abbe(%.2f-%.2f) RI(%.4f-%.4f)\n",
+ view->minAbbe, view->maxAbbe, view->minRI, view->maxRI);
+ }
+
view->zoomLevel = 1.0f;
view->offsetX = 0.0f;
view->offsetY = 0.0f;
view->selectedGlass = -1;
+ // Recalculate data bounds to ensure they're correct
+ find_glass_data_range(&view->minAbbe, &view->maxAbbe, &view->minRI, &view->maxRI);
+
+ // Test coordinate transformation for debugging
+ if (is_debug_mode()) {
+ i32 padding = get_adaptive_padding(view);
+ printf("Padding: %d, plot area: %dx%d\n",
+ padding, view->windowWidth - 2*padding, view->windowHeight - 2*padding);
+
+ // Test transformation of center point
+ f32 centerAbbe = (view->minAbbe + view->maxAbbe) / 2.0f;
+ f32 centerRI = (view->minRI + view->maxRI) / 2.0f;
+ i32 centerX, centerY;
+ data_to_screen_coords(centerAbbe, centerRI, view, ¢erX, ¢erY);
+ printf("Center glass (%.2f, %.4f) maps to screen (%d, %d)\n",
+ centerAbbe, centerRI, centerX, centerY);
+
+ // Expected center should be around (windowWidth/2, windowHeight/2)
+ printf("Expected center: (%d, %d)\n", view->windowWidth/2, view->windowHeight/2);
+ }
+
// Force complete refresh - this ensures fonts and layout are recalculated
mark_view_dirty(view);
+
+ // Force rendering for several frames to ensure proper reset after transitions
+ view->forceRenderFrames = 3;
+
+ if (is_debug_mode()) {
+ printf("Reset view complete: zoom=%.2f, offsetX=%.2f, offsetY=%.2f\n",
+ view->zoomLevel, view->offsetX, view->offsetY);
+ printf("Data bounds after reset: Abbe(%.2f-%.2f) RI(%.4f-%.4f)\n",
+ view->minAbbe, view->maxAbbe, view->minRI, view->maxRI);
+ }
}
// Helper function to calculate string length for name comparison
|