Thu, 18 Apr 2024 22:53:55 +0200
consistently refer to windows by ID - fixes #381
This change discovered that the font cache is completely broken. We created issue #387 for this.
src/ascension/context.h | file | annotate | diff | comparison | revisions | |
src/ascension/input.h | file | annotate | diff | comparison | revisions | |
src/ascension/ui.h | file | annotate | diff | comparison | revisions | |
src/ascension/ui/font.h | file | annotate | diff | comparison | revisions | |
src/ascension/ui/text.h | file | annotate | diff | comparison | revisions | |
src/ascension/window.h | file | annotate | diff | comparison | revisions | |
src/context.c | file | annotate | diff | comparison | revisions | |
src/font.c | file | annotate | diff | comparison | revisions | |
src/primitives.c | file | annotate | diff | comparison | revisions | |
src/scene.c | file | annotate | diff | comparison | revisions | |
src/text.c | file | annotate | diff | comparison | revisions | |
src/window.c | file | annotate | diff | comparison | revisions | |
test/snake.c | file | annotate | diff | comparison | revisions |
1.1 --- a/src/ascension/context.h Thu Apr 18 21:53:53 2024 +0200 1.2 +++ b/src/ascension/context.h Thu Apr 18 22:53:55 2024 +0200 1.3 @@ -52,10 +52,11 @@ 1.4 CxBuffer error_buffer; 1.5 AscInput input; 1.6 AscWindow windows[ASC_MAX_WINDOWS]; 1.7 - AscWindow *active_window; 1.8 + // TODO: rework how fonts are cached 1.9 AscFont fonts[ASC_MAX_FONTS]; 1.10 - unsigned int fonts_loaded; 1.11 - AscFont const *active_font; 1.12 + unsigned char fonts_loaded; 1.13 + unsigned char active_window; 1.14 + unsigned char active_font; 1.15 asc_col4i ink; 1.16 uint64_t frame_nanos; 1.17 uint64_t total_nanos; 1.18 @@ -64,6 +65,29 @@ 1.19 /** Global ascension context. */ 1.20 extern AscContext asc_context; 1.21 1.22 +/** 1.23 + * The currently active font. 1.24 + * @see asc_font() 1.25 + */ 1.26 +#define asc_active_font \ 1.27 + (&asc_context.fonts[asc_context.active_font]) 1.28 + 1.29 +/** 1.30 + * The currently active window in the context. 1.31 + * @see asc_window_activate() 1.32 + */ 1.33 +#define asc_active_window \ 1.34 + (&asc_context.windows[asc_context.active_window]) 1.35 + 1.36 +static inline bool asc_assert_active_window() { 1.37 + if (asc_context.active_window < ASC_MAX_WINDOWS) { 1.38 + return true; 1.39 + } else { 1.40 + asc_error("A graphics operation was performed without active window"); 1.41 + return false; 1.42 + } 1.43 +} 1.44 + 1.45 void asc_context_initialize(void); 1.46 void asc_context_destroy(void); 1.47 1.48 @@ -86,10 +110,5 @@ 1.49 #define asc_ink_rgba(r,g,b,a) asc_context.ink = (asc_col4i){(r),(g),(b),(a)} 1.50 #define asc_ink_rgb(r,g,b) asc_context.ink = (asc_col4i){(r),(g),(b),255u} 1.51 1.52 -/** 1.53 - * Sets the active drawing font. 1.54 - */ 1.55 -#define asc_set_font(font) asc_context.active_font = (font) 1.56 - 1.57 #endif /* ASCENSION_CONTEXT_H */ 1.58
2.1 --- a/src/ascension/input.h Thu Apr 18 21:53:53 2024 +0200 2.2 +++ b/src/ascension/input.h Thu Apr 18 22:53:55 2024 +0200 2.3 @@ -45,4 +45,12 @@ 2.4 #define asc_key_pressed(scancode) \ 2.5 (asc_context.input.keys[SDL_SCANCODE_##scancode]) 2.6 2.7 +#define asc_mouse_x asc_context.input.mouse_x 2.8 +#define asc_mouse_y asc_context.input.mouse_y 2.9 +#define asc_mouse_pos (asc_vec2i) {asc_mouse_x, asc_mouse_y} 2.10 + 2.11 +#define asc_mouse_move_x asc_context.input.mouse_xrel 2.12 +#define asc_mouse_move_y asc_context.input.mouse_yrel 2.13 +#define asc_mouse_move (asc_vec2i) {asc_mouse_move_x, asc_mouse_move_y} 2.14 + 2.15 #endif //ASCENSION_INPUT_H
3.1 --- a/src/ascension/ui.h Thu Apr 18 21:53:53 2024 +0200 3.2 +++ b/src/ascension/ui.h Thu Apr 18 22:53:55 2024 +0200 3.3 @@ -31,7 +31,7 @@ 3.4 #include "ui/text.h" 3.5 3.6 #define asc_add_ui_node(node) \ 3.7 - asc_scene_node_link(asc_window_active->ui, node) 3.8 + asc_scene_node_link(asc_active_window->ui, node) 3.9 3.10 #endif /* ASCENSION_UI_H */ 3.11
4.1 --- a/src/ascension/ui/font.h Thu Apr 18 21:53:53 2024 +0200 4.2 +++ b/src/ascension/ui/font.h Thu Apr 18 22:53:55 2024 +0200 4.3 @@ -52,43 +52,25 @@ 4.4 */ 4.5 int size; 4.6 /** 4.7 + * TODO: remove from public struct 4.8 * Pointer to the SDL TTF font structure. 4.9 */ 4.10 TTF_Font *ptr; 4.11 } AscFont; 4.12 4.13 /** 4.14 - * Loads a font with the given style and size. 4.15 + * Activates a font with the given style and size. 4.16 * 4.17 - * The font is cached and returned faster the next time you call this 4.18 + * The font is cached and activated faster the next time you call this 4.19 * function with the same arguments. However, when you reach the maximum 4.20 * number of fonts, the cache is completely cleared and rebuilt. 4.21 * 4.22 * That means in general, that you should not be using too many fonts of 4.23 - * different sizes at the same time, and you should not keep the pointer 4.24 - * returned by this function too long, because you would risking cache misses. 4.25 + * different sizes at the same time. 4.26 * 4.27 * @param style the style 4.28 * @param size the point size 4.29 - * @return a pointer to the font structure (do not free) 4.30 */ 4.31 -AscFont const *asc_font(enum AscFontStyle style, int size); 4.32 - 4.33 -/** 4.34 - * Unloads all cached fonts from the context. 4.35 - */ 4.36 -void asc_font_cache_clear(void); 4.37 - 4.38 -/** 4.39 - * Checks, if the font is still loaded and reloads it, if required. 4.40 - * 4.41 - * There is no need to call this function manually. Every Ascension function 4.42 - * that you pass a font will do that for you and use the returned pointer in 4.43 - * case of a cache miss. 4.44 - * 4.45 - * @param font the font to validate 4.46 - * @return \p font, or a pointer to the new location of the loaded font 4.47 - */ 4.48 -AscFont const *asc_font_cache_validate(AscFont const *font); 4.49 +void asc_font(enum AscFontStyle style, int size); 4.50 4.51 #endif //ASCENSION_FONT_H
5.1 --- a/src/ascension/ui/text.h Thu Apr 18 21:53:53 2024 +0200 5.2 +++ b/src/ascension/ui/text.h Thu Apr 18 22:53:55 2024 +0200 5.3 @@ -38,7 +38,7 @@ 5.4 typedef struct AscText { 5.5 extend_asc_scene_node; 5.6 cxmutstr text; 5.7 - AscFont const *font; 5.8 + AscFont font; 5.9 asc_col4i color; 5.10 unsigned short max_width; 5.11 unsigned short offx;
6.1 --- a/src/ascension/window.h Thu Apr 18 21:53:53 2024 +0200 6.2 +++ b/src/ascension/window.h Thu Apr 18 22:53:55 2024 +0200 6.3 @@ -56,12 +56,6 @@ 6.4 } AscWindow; 6.5 6.6 /** 6.7 - * The currently active window in the context. 6.8 - * @see asc_window_activate() 6.9 - */ 6.10 -#define asc_window_active asc_context.active_window 6.11 - 6.12 -/** 6.13 * Initializes the settings structure with default values. 6.14 * 6.15 * @param settings an uninitialized settings object 6.16 @@ -78,31 +72,33 @@ 6.17 * 6.18 * @param index the index of the new window 6.19 * @param settings the settings to be used for initialization 6.20 - * @return a pointer to the window data or \c NULL if initialization failed 6.21 */ 6.22 -AscWindow *asc_window_initialize(unsigned int index, AscWindowSettings const* settings); 6.23 +void asc_window_initialize(unsigned int index, AscWindowSettings const* settings); 6.24 6.25 /** 6.26 * Destroys the window and its OpenGL context. 6.27 * 6.28 - * When this window is currently active, there will be \em no active window afterwards. 6.29 + * When this window is currently active, there 6.30 + * will be \em no active window afterwards. 6.31 * 6.32 * Still alive windows will also be destroyed by asc_context_destroy() 6.33 * automatically. 6.34 * 6.35 - * @param window the window 6.36 + * @param index the index of the window 6.37 */ 6.38 -void asc_window_destroy(AscWindow* window); 6.39 +void asc_window_destroy(unsigned int index); 6.40 6.41 /** 6.42 * Swaps buffers and adjusts the viewport to the current window size. 6.43 * 6.44 - * This function is automatically invoked for all initialized windows 6.45 - * by asc_loop_next(). You usually do not need to call this function manually. 6.46 + * This function is automatically invoked by asc_loop_next(). 6.47 + * You usually should not call this function manually. 6.48 * 6.49 - * @param window the window 6.50 + * If this function is invoked on a non-initialized window, nothing happens. 6.51 + * 6.52 + * @param index the index of the window 6.53 */ 6.54 -void asc_window_sync(AscWindow *window); 6.55 +void asc_window_sync(unsigned int index); 6.56 6.57 /** 6.58 * Switches the active window. 6.59 @@ -110,9 +106,9 @@ 6.60 * In particular that makes the corresponding OpenGL context "current". 6.61 * When you only want to draw into one window, you'll never need this. 6.62 * 6.63 - * @param the window to activate 6.64 + * @param index the index of the window 6.65 */ 6.66 -void asc_window_activate(AscWindow *window); 6.67 +void asc_window_activate(unsigned int index); 6.68 6.69 #endif /* ASCENSION_WINDOW_H */ 6.70
7.1 --- a/src/context.c Thu Apr 18 21:53:53 2024 +0200 7.2 +++ b/src/context.c Thu Apr 18 22:53:55 2024 +0200 7.3 @@ -47,6 +47,10 @@ 7.4 return; 7.5 memset(&asc_context, 0, sizeof(AscContext)); 7.6 7.7 + // nothing is active right after initialization 7.8 + asc_context.active_window = ASC_MAX_WINDOWS; 7.9 + asc_context.active_font = ASC_MAX_FONTS; 7.10 + 7.11 // initialize error buffer 7.12 cxBufferInit( 7.13 &asc_context.error_buffer, 7.14 @@ -72,9 +76,9 @@ 7.15 7.16 void asc_context_destroy(void) { 7.17 for (unsigned int i = 0 ; i < ASC_MAX_WINDOWS ; i++) { 7.18 - asc_window_destroy(&asc_context.windows[i]); 7.19 + asc_window_destroy(i); 7.20 } 7.21 - asc_font_cache_clear(); 7.22 + // TODO: fix that fonts are currently leaking by reworking the font cache 7.23 7.24 // quit SDL 7.25 if (TTF_WasInit()) 7.26 @@ -143,9 +147,7 @@ 7.27 7.28 // sync the windows 7.29 for (unsigned int i = 0 ; i < ASC_MAX_WINDOWS ; i++) { 7.30 - if (asc_context.windows[i].id > 0) { 7.31 - asc_window_sync(&asc_context.windows[i]); 7.32 - } 7.33 + asc_window_sync(i); 7.34 } 7.35 7.36 // compute frame time
8.1 --- a/src/font.c Thu Apr 18 21:53:53 2024 +0200 8.2 +++ b/src/font.c Thu Apr 18 22:53:55 2024 +0200 8.3 @@ -43,17 +43,19 @@ 8.4 } 8.5 } 8.6 8.7 -AscFont const *asc_font(enum AscFontStyle style, int size) { 8.8 +void asc_font(enum AscFontStyle style, int size) { 8.9 for (unsigned int i = 0 ; i < asc_context.fonts_loaded ; i++) { 8.10 AscFont *font = &asc_context.fonts[i]; 8.11 if (font->size == size && font->style == style) { 8.12 - return font; 8.13 + asc_context.active_font = i; 8.14 + return; 8.15 } 8.16 } 8.17 8.18 if (asc_context.fonts_loaded == ASC_MAX_FONTS) { 8.19 - asc_dprintf("WARNING: Maximum number of fonts reached, wiping cache!"); 8.20 - asc_font_cache_clear(); 8.21 + asc_error("Too many fonts. Cannot load more until cache is repaired."); 8.22 + asc_context.active_font = ASC_MAX_FONTS; 8.23 + return; 8.24 } 8.25 8.26 unsigned int slot = asc_context.fonts_loaded++; 8.27 @@ -64,27 +66,8 @@ 8.28 if (font->ptr == NULL) { 8.29 asc_context.fonts_loaded--; 8.30 asc_error(TTF_GetError()); 8.31 - return NULL; 8.32 - } 8.33 - asc_dprintf("Loaded font size %u, style %u in slot %u", size, style, slot); 8.34 - return font; 8.35 -} 8.36 - 8.37 -void asc_font_cache_clear(void) { 8.38 - asc_dprintf("Fonts in cache that are being unloaded: %u", asc_context.fonts_loaded); 8.39 - while (asc_context.fonts_loaded > 0) { 8.40 - unsigned int i = --asc_context.fonts_loaded; 8.41 - AscFont *font = &asc_context.fonts[i]; 8.42 - TTF_CloseFont(font->ptr); 8.43 - font->ptr = NULL; 8.44 + } else { 8.45 + asc_dprintf("Loaded font size %u, style %u in slot %u", size, style, slot); 8.46 + asc_context.active_font = slot; 8.47 } 8.48 } 8.49 - 8.50 -AscFont const *asc_font_cache_validate(AscFont const *font) { 8.51 - if (font->ptr) { 8.52 - return font; 8.53 - } else { 8.54 - asc_dprintf("Cache miss for font size %u, style %u", font->size, font->style); 8.55 - return asc_font(font->style, font->size); 8.56 - } 8.57 -}
9.1 --- a/src/primitives.c Thu Apr 18 21:53:53 2024 +0200 9.2 +++ b/src/primitives.c Thu Apr 18 22:53:55 2024 +0200 9.3 @@ -87,7 +87,7 @@ 9.4 } 9.5 9.6 void asc_primitives_draw_plane(void) { 9.7 - AscMesh const *mesh = &(asc_window_active->glctx.primitives.plane); 9.8 + AscMesh const *mesh = &(asc_active_window->glctx.primitives.plane); 9.9 glBindVertexArray(mesh->vao); 9.10 glDrawArrays(GL_TRIANGLE_STRIP, 0, mesh->vertices); 9.11 } 9.12 \ No newline at end of file
10.1 --- a/src/scene.c Thu Apr 18 21:53:53 2024 +0200 10.2 +++ b/src/scene.c Thu Apr 18 22:53:55 2024 +0200 10.3 @@ -151,7 +151,7 @@ 10.4 // Sprites 10.5 // ------- 10.6 // TODO: implement view matrix for 2D worlds 10.7 - shader = &asc_window_active->glctx.shader.sprite.base; 10.8 + shader = &asc_active_window->glctx.shader.sprite.base; 10.9 glUseProgram(shader->id); 10.10 glUniformMatrix4fv(shader->projection, 1, 10.11 GL_FALSE, camera->projection);
11.1 --- a/src/text.c Thu Apr 18 21:53:53 2024 +0200 11.2 +++ b/src/text.c Thu Apr 18 22:53:55 2024 +0200 11.3 @@ -36,7 +36,7 @@ 11.4 11.5 static void asc_text_draw(AscText const *node) { 11.6 // Obtain shader 11.7 - AscShaderSprite *shader = &asc_window_active->glctx.shader.sprite; 11.8 + AscShaderSprite *shader = &asc_active_window->glctx.shader.sprite; 11.9 11.10 // Upload model matrix 11.11 glUniformMatrix4fv(shader->base.model, 1, 11.12 @@ -59,7 +59,8 @@ 11.13 } 11.14 11.15 // Render text onto a surface 11.16 - TTF_Font *font = asc_font_cache_validate(node->font)->ptr; 11.17 + // TODO: obtain TTF_Font from font cache once it is repaired 11.18 + TTF_Font *font = node->font.ptr; 11.19 static int alignments[] = { 11.20 TTF_WRAPPED_ALIGN_LEFT, 11.21 TTF_WRAPPED_ALIGN_CENTER, 11.22 @@ -101,7 +102,7 @@ 11.23 node->base.position.x = (float) args.x; 11.24 node->base.position.y = (float) args.y; 11.25 node->max_width = args.max_width; 11.26 - node->font = asc_context.active_font; 11.27 + node->font = *asc_active_font; 11.28 node->color = asc_context.ink; 11.29 if (args.text == NULL) { 11.30 node->text = cx_mutstr(strdup(" "));
12.1 --- a/src/window.c Thu Apr 18 21:53:53 2024 +0200 12.2 +++ b/src/window.c Thu Apr 18 22:53:55 2024 +0200 12.3 @@ -43,16 +43,16 @@ 12.4 settings->title = "Ascended Window"; 12.5 } 12.6 12.7 -AscWindow *asc_window_initialize(unsigned int index, AscWindowSettings const *settings) { 12.8 +void asc_window_initialize(unsigned int index, AscWindowSettings const *settings) { 12.9 if (index >= ASC_MAX_WINDOWS) { 12.10 asc_error("Maximum number of windows exceeded."); 12.11 - return NULL; 12.12 + return; 12.13 } 12.14 AscWindow *window = &asc_context.windows[index]; 12.15 if (window->id > 0) { 12.16 asc_error("Cannot create window - slot already occupied."); 12.17 asc_dprintf("Tried to create window with index %u twice", index); 12.18 - return NULL; 12.19 + return; 12.20 } 12.21 if (window->ui != NULL) { 12.22 asc_dprintf("Window with index %u has a dangling UI pointer", index); 12.23 @@ -72,7 +72,7 @@ 12.24 ); 12.25 if (window->window == NULL) { 12.26 asc_error(SDL_GetError()); 12.27 - return NULL; 12.28 + return; 12.29 } 12.30 12.31 window->id = SDL_GetWindowID(window->window); 12.32 @@ -85,27 +85,31 @@ 12.33 if (asc_gl_context_initialize(&window->glctx, window->window, &settings->glsettings)) { 12.34 window->ui = asc_scene_node_empty(); 12.35 asc_dprintf("Window %u initialized", window->id); 12.36 - asc_window_active = window; 12.37 - return window; 12.38 + asc_context.active_window = index; 12.39 } else { 12.40 asc_dprintf("Creating GL context failed for window %u", window->id); 12.41 // cleanup on error 12.42 SDL_DestroyWindow(window->window); 12.43 window->window = NULL; 12.44 window->id = 0; 12.45 - return NULL; 12.46 } 12.47 } 12.48 12.49 -void asc_window_destroy(AscWindow* window) { 12.50 +void asc_window_destroy(unsigned int index) { 12.51 // safeguard 12.52 - if (window->id == 0) return; 12.53 + if (asc_context.windows[index].id == 0) return; 12.54 12.55 // this window cannot be active anymore 12.56 - if (asc_window_active == window) { 12.57 - asc_window_active = NULL; 12.58 + if (asc_context.active_window == index) { 12.59 + asc_context.active_window = ASC_MAX_WINDOWS; 12.60 } 12.61 12.62 + // pointer to the window 12.63 + AscWindow *window = &asc_context.windows[index]; 12.64 + 12.65 + // for releasing OpenGL resources, we need to make the context current 12.66 + asc_gl_context_activate(&window->glctx); 12.67 + 12.68 // destroy all scenes 12.69 asc_scene_node_free(window->ui); 12.70 window->ui = NULL; 12.71 @@ -119,8 +123,8 @@ 12.72 } 12.73 12.74 // if another window was active, make the other context current again 12.75 - if (asc_window_active != NULL) { 12.76 - asc_gl_context_activate(&asc_window_active->glctx); 12.77 + if (asc_context.active_window < ASC_MAX_WINDOWS) { 12.78 + asc_gl_context_activate(&asc_active_window->glctx); 12.79 } 12.80 12.81 // clean the data 12.82 @@ -128,15 +132,19 @@ 12.83 memset(window, 0, sizeof(AscWindow)); 12.84 } 12.85 12.86 -void asc_window_sync(AscWindow* window) { 12.87 - AscWindow *active_window = asc_window_active; 12.88 - if (window != active_window) { 12.89 - asc_window_activate(window); 12.90 +void asc_window_sync(unsigned int index) { 12.91 + // necessary safeguard 12.92 + if (asc_context.windows[index].id == 0) return; 12.93 + 12.94 + // active the window that shall be synced temporarily 12.95 + unsigned int active_index = asc_context.active_window; 12.96 + if (index != active_index) { 12.97 + asc_window_activate(index); 12.98 } 12.99 12.100 // Clear the color buffer for the window frame 12.101 - int window_width = window->dimensions.width; 12.102 - int window_height = window->dimensions.height; 12.103 + int window_width = asc_active_window->dimensions.width; 12.104 + int window_height = asc_active_window->dimensions.height; 12.105 glViewport(0, 0, window_width, window_height); 12.106 glClear(GL_COLOR_BUFFER_BIT); 12.107 asc_recti viewport = {0, 0, window_width, window_height}; 12.108 @@ -144,20 +152,20 @@ 12.109 // Draw the UI 12.110 AscCamera ui_camera; 12.111 asc_camera_ortho(&ui_camera, viewport); 12.112 - asc_scene_draw(window->ui, viewport, &ui_camera); 12.113 + asc_scene_draw(asc_active_window->ui, viewport, &ui_camera); 12.114 12.115 // Swap Buffers 12.116 - SDL_GL_SwapWindow(window->window); 12.117 + SDL_GL_SwapWindow(asc_active_window->window); 12.118 12.119 // Clear Flags 12.120 - window->resized = false; 12.121 + asc_active_window->resized = false; 12.122 12.123 - if (window != active_window) { 12.124 - asc_window_activate(active_window); 12.125 + if (index != active_index) { 12.126 + asc_window_activate(active_index); 12.127 } 12.128 } 12.129 12.130 -void asc_window_activate(AscWindow *window) { 12.131 - asc_gl_context_activate(&window->glctx); 12.132 - asc_window_active = (AscWindow *)window; 12.133 +void asc_window_activate(unsigned int index) { 12.134 + asc_context.active_window = index; 12.135 + asc_gl_context_activate(&asc_active_window->glctx); 12.136 }
13.1 --- a/test/snake.c Thu Apr 18 21:53:53 2024 +0200 13.2 +++ b/test/snake.c Thu Apr 18 22:53:55 2024 +0200 13.3 @@ -47,7 +47,7 @@ 13.4 } 13.5 13.6 static void create_fps_counter(void) { 13.7 - asc_set_font(asc_font(ASC_FONT_REGULAR, 24)); 13.8 + asc_font(ASC_FONT_REGULAR, 24); 13.9 asc_ink_rgb(255, 0, 0); 13.10 AscSceneNode* node = asc_text( .x = 10, .y = 10 ); 13.11 asc_scene_add_behavior(node, update_fps_counter); 13.12 @@ -56,8 +56,8 @@ 13.13 13.14 static void update_score_counter(AscSceneNode *node) { 13.15 // tie to bottom right of the screen 13.16 - if (asc_window_active->resized) { 13.17 - asc_vec2i bottom_right = asc_window_active->dimensions; 13.18 + if (asc_active_window->resized) { 13.19 + asc_vec2i bottom_right = asc_active_window->dimensions; 13.20 asc_vec2i scale = asc_get_scale2d(node); 13.21 asc_set_position2d( 13.22 node, 13.23 @@ -68,7 +68,7 @@ 13.24 } 13.25 13.26 static void create_score_counter(void) { 13.27 - asc_set_font(asc_font(ASC_FONT_BOLD, 14)); 13.28 + asc_font(ASC_FONT_BOLD, 14); 13.29 asc_ink_rgb(0, 255, 0); 13.30 AscSceneNode* node = asc_text(.text = "Score: 0" ); 13.31 asc_scene_add_behavior(node, update_score_counter); 13.32 @@ -87,7 +87,7 @@ 13.33 AscWindowSettings settings; 13.34 asc_window_settings_init_defaults(&settings); 13.35 settings.title = "Snake"; 13.36 - AscWindow *window = asc_window_initialize(0, &settings); 13.37 + asc_window_initialize(0, &settings); 13.38 13.39 // create UI elements 13.40 create_fps_counter(); 13.41 @@ -98,7 +98,8 @@ 13.42 // quit application on any error 13.43 if (asc_has_error()) { 13.44 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, 13.45 - "Fatal Error", asc_get_error(), window->window); 13.46 + "Fatal Error", asc_get_error(), 13.47 + asc_active_window->window); 13.48 asc_clear_error(); 13.49 asc_context_quit(); 13.50 }