/** * @brief Kills the window. * * @param wid ID of window to destroy. */ static void window_kill( Window *wdw ) { Widget *wgt, *wgtkill; /* Run the close function first. */ if (wdw->close_fptr != NULL) wdw->close_fptr( wdw->id, wdw->name); /* Destroy the window. */ if (wdw->name) free(wdw->name); wgt = wdw->widgets; while (wgt != NULL) { wgtkill = wgt; wgt = wgtkill->next; widget_kill(wgtkill); } free(wdw); /* Clear key repeat, since toolkit could miss the keyup event. */ toolkit_clearKey(); }
/** * @brief Creates a window. * * @param name Name of the window to create. * @param x X position of the window (-1 centers). * @param y Y position of the window (-1 centers). * @param w Width of the window (-1 fullscreen). * @param h Height of the window (-1 fullscreen). * @return Newly created window's ID. */ unsigned int window_create( const char* name, const int x, const int y, const int w, const int h ) { Window *wcur, *wlast, *wdw; /* Allocate memory. */ wdw = malloc( sizeof(Window) ); memset( wdw, 0, sizeof(Window) ); const int wid = (++genwid); /* unique id */ /* Create the window. */ wdw->id = wid; wdw->name = strdup(name); /* Sane defaults. */ wdw->idgen = -1; wdw->focus = -1; /* Dimensions. */ wdw->w = (w == -1) ? SCREEN_W : (double) w; wdw->h = (h == -1) ? SCREEN_H : (double) h; if ((w == -1) && (h == -1)) { window_setFlag( wdw, WINDOW_FULLSCREEN ); wdw->x = 0.; wdw->y = 0.; } else { /* x pos */ if (x==-1) /* center */ wdw->x = (SCREEN_W - wdw->w)/2.; else if (x < 0) wdw->x = SCREEN_W - wdw->w + (double) x; else wdw->x = (double) x; /* y pos */ if (y==-1) /* center */ wdw->y = (SCREEN_H - wdw->h)/2.; else if (y < 0) wdw->y = SCREEN_H - wdw->h + (double) y; else wdw->y = (double) y; } if (toolkit_open==0) { /* toolkit is on */ SDL_ShowCursor(SDL_ENABLE); toolkit_open = 1; /* enable toolkit */ pause_game(); gl_defViewport(); /* Reset the default viewport */ } /* Clear key repeat. */ toolkit_clearKey(); /* Add to list. */ wdw->next = NULL; if (windows == NULL) windows = wdw; else { for (wcur = windows; wcur != NULL; wcur = wcur->next) wlast = wcur; wlast->next = wdw; } return wid; }
/** * @brief Displays the introduction sequence. * * @brief text Path of text file to use. * @brief mus Type of music to use (run through music.lua). * @return 0 on success. */ int intro_display( const char *text, const char *mus ) { double offset; /* distance from bottom of the top line. */ double line_height; /* # pixels per line. */ int lines_per_screen; /* max appearing lines on the screen. */ scroll_buf_t *sb_arr; /* array of lines to render. */ scroll_buf_t *sb_list; /* list " " " " */ double vel = 16.; /* velocity: speed of text. */ int stop = 0; /* stop the intro. */ unsigned int tcur, tlast; /* timers. */ double delta; /* time diff from last render to this one. */ int line_index = 0; /* index into the big list of intro lines. */ intro_img_t side_image; /* image to go along with the text. */ intro_img_t transition; /* image for transitioning. */ /* Load the introduction. */ if (intro_load(text) < 0) return -1; /* Change music to intro music. */ if (mus != NULL) music_choose(mus); /* We need to clear key repeat to avoid infinite loops. */ toolkit_clearKey(); /* Enable keyrepeat just for the intro. */ SDL_EnableKeyRepeat( conf.repeat_delay, conf.repeat_freq ); /* Do a few calculations to figure out how many lines can be present on the screen at any given time. */ line_height = (double)intro_font.h * 1.3; lines_per_screen = (int)(SCREEN_H / line_height + 1.5); /* round up + 1 */ sb_arr = (scroll_buf_t*)malloc( sizeof(scroll_buf_t) * lines_per_screen ); /* Force the first line to be loaded immediately. */ offset = line_height; /* Create a cycle of lines. */ sb_list = arrange_scroll_buf( sb_arr, lines_per_screen ); /* Unset the side image. */ initialize_image( &side_image ); initialize_image( &transition ); tlast = SDL_GetTicks(); while (!stop) { tcur = SDL_GetTicks(); delta = (double)(tcur - tlast) / 1000.; tlast = tcur; /* Increment position. */ offset += vel * delta; while (! (offset < line_height)) { /* One line has scrolled off, and another one on. */ if (line_index < intro_nlines) { switch (intro_lines[line_index][0]) { case 't': /* plain ol' text. */ sb_list->text = &intro_lines[line_index][1]; offset -= line_height; sb_list = sb_list->next; break; case 'i': /* fade in image. */ intro_fade_image_in( &side_image, &transition, &intro_lines[line_index][1] ); break; case 'o': /* fade out image. */ if (NULL == side_image.tex) { WARN("Tried to fade out without an image." ); break; } side_image.fade_rate = -0.1; side_image.c.a = 0.99; break; default: /* unknown. */ break; } ++line_index; } else { sb_list->text = NULL; offset -= line_height; sb_list = sb_list->next; } } /* while (offset > line_height) */ /* Fade the side image. */ if (side_image.tex != NULL && side_image.c.a < 1.0) { side_image.c.a += delta * vel * side_image.fade_rate; if (transition.tex != NULL && transition.fade_rate > 0.0) { transition.c.a += delta * vel * transition.fade_rate; } if (side_image.c.a > 1.0) { /* Faded in... */ side_image.c.a = 1.0; side_image.fade_rate = 0.0; } else if (side_image.c.a < 0.0) { /* Faded out... */ gl_freeTexture( side_image.tex ); if (transition.tex != NULL) { side_image.tex = transition.tex; side_image.c.a = transition.c.a; side_image.y = transition.y; side_image.fade_rate = 0.1; transition.tex = NULL; transition.c.a = 1.0; } else { side_image.c.a = 1.0; side_image.tex = NULL; side_image.fade_rate = 0.0; } } } /* Clear stuff. */ glClear(GL_COLOR_BUFFER_BIT); /* Only thing we actually care about updating is music. */ music_update( 0. ); /* Draw text. */ stop = intro_draw_text( sb_list, offset, line_height ); if (NULL != side_image.tex) { /* Draw the image next to the text. */ gl_blitScale( side_image.tex, side_image.x, side_image.y, side_image.tex->w, side_image.tex->h, &side_image.c ); } if (NULL != transition.tex && transition.c.a > 0.0) { /* Draw the image in transition. */ gl_blitScale( transition.tex, transition.x, transition.y, transition.tex->w, transition.tex->h, &transition.c ); } /* Display stuff. */ SDL_GL_SwapBuffers(); SDL_Delay(10); /* No need to burn CPU. */ /* Handle user events. */ intro_event_handler( &stop, &offset, &vel ); } /* while (!stop) */ /* free malloc'd memory. */ free( sb_arr ); if (NULL != side_image.tex) { gl_freeTexture( side_image.tex ); } if (NULL != transition.tex) { gl_freeTexture( transition.tex ); } /* Disable intro's key repeat. */ SDL_EnableKeyRepeat( 0, 0 ); /* Stop music, normal music will start shortly after. */ music_stop(); /* Clean up after the introduction. */ intro_cleanup(); return 0; }
/** * @brief Unregisters a key. * * @param key Key to unregister. */ static void toolkit_unregKey( SDLKey key ) { if (input_key == key) toolkit_clearKey(); }
/** * @brief Displays the introduction sequence. * * @brief text Path of text file to use. * @brief mus Type of music to use (run through music.lua). * @return 0 on success. */ int intro_display( const char *text, const char *mus ) { int i, max; unsigned int tcur, tlast; double dt; double x, y, vel; double offset; double density; SDL_Event event; /* Load the introduction. */ if (intro_load(text) < 0) return -1; /* Calculate velocity. */ density = ((double)intro_length / (double)intro_nlines); /* char / line */ density /= (double)intro_font.h; /* char / pixel */ vel = INTRO_SPEED / density; /* (char / s) * (pixel / char) = pixel / s */ /* Change music to intro music. */ if (mus != NULL) music_choose(mus); /* We need to clear key repeat to avoid infinite loops. */ toolkit_clearKey(); /* Prepare for intro loop. */ x = 100.; y = 0.; tlast = SDL_GetTicks(); offset = 0.; max = intro_nlines + SCREEN_H / ((intro_font.h + 5.)); while (1) { /* Get delta tick in seconds. */ tcur = SDL_GetTicks(); dt = (double)(tcur - tlast) / 1000.; tlast = tcur; /* Handle events. */ while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: /* Escape skips directly. */ if (event.key.keysym.sym == SDLK_ESCAPE) offset = max * (intro_font.h + 5.); /* Only Handle space from here down. */ else if (!nstd_isspace(event.key.keysym.sym)) break; /* Purpose fallthrough. */ case SDL_JOYBUTTONDOWN: offset += 250.; default: break; } } /* Increment position. */ offset += vel * dt; /* Clear stuff. */ glClear(GL_COLOR_BUFFER_BIT); /* Draw the text. */ i = (int)(offset / (intro_font.h + 5.)); if (i > max) /* Out of lines. */ break; y = offset - (i+1) * (intro_font.h + 5.); while (i >= 0) { /* Skip in line isn't valid. */ if (i >= intro_nlines) { i--; y += intro_font.h + 5.; continue; } gl_print( &intro_font, x, y, &cConsole, intro_lines[i] ); /* Increment line and position. */ i--; y += intro_font.h + 5.; } /* Only thing we actually care about updating is music. */ music_update(); /* Display stuff. */ SDL_GL_SwapBuffers(); SDL_Delay(10); /* No need to burn CPU. */ } /* Stop music, normal music will start shortly after. */ music_stop(); /* Clean up after the introduction. */ intro_cleanup(); return 0; }