/** * glamac_view.h - header file from glamac_view.c. */ #ifndef GLAMAC_VIEW_H #define GLAMAC_VIEW_H #include #include "glamacdef.h" // Constants for view #define PADDING_PERCENT 0.08f // 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 #define MAX_ZOOM 10.0f // Maximum zoom level // State for zooming and panning typedef struct { f32 zoomLevel; f32 offsetX; f32 offsetY; i32 windowWidth; i32 windowHeight; f32 minAbbe; f32 maxAbbe; f32 minRI; f32 maxRI; b32 showHelp; // Flag to show/hide help window b32 gKeyPressed; // Flag to track if 'g' was pressed u32 gKeyTime; // Time when 'g' was pressed for sequence timing i32 selectedGlass; // Index of selected glass (-1 if none) } ViewState; // Initialize a view state with default values void init_view_state(ViewState* view, i32 windowWidth, i32 windowHeight); // 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) { const i32 padding = (i32)(view->windowWidth * PADDING_PERCENT); // Apply zoom and offset transformation // FLIPPED: Use 1.0f - normalized to flip the Abbe number axis f32 normalizedX = 1.0f - (abbeNumber - view->minAbbe) / (view->maxAbbe - view->minAbbe); f32 normalizedY = (refractiveIndex - view->minRI) / (view->maxRI - view->minRI); // Transform with zoom and offset normalizedX = (normalizedX - 0.5f) * view->zoomLevel + 0.5f + view->offsetX; normalizedY = (normalizedY - 0.5f) * view->zoomLevel + 0.5f + view->offsetY; // Convert to screen coordinates *x = padding + (i32)(normalizedX * (view->windowWidth - 2 * padding)); *y = view->windowHeight - padding - (i32)(normalizedY * (view->windowHeight - 2 * padding)); } // Convert screen coordinates to data values static inline void screen_to_data_coords(i32 x, i32 y, const ViewState* view, f32 *abbeNumber, f32 *refractiveIndex) { const i32 padding = (i32)(view->windowWidth * PADDING_PERCENT); // Convert to normalized coordinates f32 normalizedX = (f32)(x - padding) / (view->windowWidth - 2 * padding); f32 normalizedY = (f32)(view->windowHeight - y - padding) / (view->windowHeight - 2 * padding); // Reverse transform with zoom and offset normalizedX = (normalizedX - view->offsetX - 0.5f) / view->zoomLevel + 0.5f; normalizedY = (normalizedY - view->offsetY - 0.5f) / view->zoomLevel + 0.5f; // Convert to data values - FLIPPED axis logic for Abbe *abbeNumber = view->maxAbbe - normalizedX * (view->maxAbbe - view->minAbbe); *refractiveIndex = view->minRI + normalizedY * (view->maxRI - view->minRI); } // Find the nearest glass to a given screen position i32 find_nearest_glass(i32 x, i32 y, const ViewState* view, f32 maxDistance); // Calculate visible data range based on current view void get_visible_data_range(const ViewState* view, f32 *visibleMinAbbe, f32 *visibleMaxAbbe, f32 *visibleMinRI, f32 *visibleMaxRI); // Handle mouse wheel zoom void handle_mouse_wheel_zoom(i32 wheelY, i32 mouseX, i32 mouseY, ViewState* view); // Toggle fullscreen void toggle_fullscreen(SDL_Window* window); // Reset view to default void reset_view(ViewState* view); #endif /* GLAMAC_VIEW_H */