part_ui::RESULT part_ui::show() { if(p_.music().empty() != true) { sound::play_music_repeatedly(p_.music()); } if(p_.sound().empty() != true) { sound::play_sound(p_.sound()); } render_background(); if(p_.show_title()) { render_title_box(); } if(!imgs_.empty()) { if(!render_floating_images()) { return ret_; } } try { render_story_box(); } catch(utf8::invalid_utf8_exception const&) { ERR_NG << "invalid UTF-8 sequence in story text, skipping part..." << std::endl; } return ret_; }
void part_ui::render_background() { sdl::draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); sdl_blit(background_, NULL, video_.getSurface(), NULL); // Render the titlebox over the background render_title_box(); }
void part_ui::render_story_box() { #ifdef SDL_GPU LOG_NG << "ENTER part_ui()::render_story_box()\n"; const std::string& storytxt = p_.text(); if(storytxt.empty()) { video_.flip(); wait_for_input(); return; } const part::BLOCK_LOCATION tbl = p_.story_text_location(); const int max_width = buttons_x_ - storybox_padding - text_x_; const int max_height = screen_area().h - storybox_padding; skip_ = false; last_key_ = true; font::ttext t; if(!t.set_text(p_.text(), true)) { ERR_NG << "Text: Invalid markup in '" << p_.text() << "' rendered as is.\n"; t.set_text(p_.text(), false); } t.set_font_style(font::ttext::STYLE_NORMAL) .set_font_size(storybox_font_size) .set_foreground_color(storybox_font_color) .set_maximum_width(max_width) .set_maximum_height(max_height, true); sdl::timage txttxt = t.render_as_texture(); if(txttxt.null()) { ERR_NG << "storyscreen text area rendering resulted in a null texture" << std::endl; return; } int fix_text_y = text_y_; if(fix_text_y + 2*(storybox_padding+1) + txttxt.height() > screen_area().h && tbl != part::BLOCK_TOP) { fix_text_y = (screen_area().h > txttxt.height() + 1) ? (std::max(0, screen_area().h - txttxt.height() - 2*(storybox_padding+1))) : (0); } int fix_text_h; switch(tbl) { case part::BLOCK_TOP: fix_text_h = std::max(txttxt.height() + 2*storybox_padding, screen_area().h/4); break; case part::BLOCK_MIDDLE: fix_text_h = std::max(txttxt.height() + 2*storybox_padding, screen_area().h/3); break; default: fix_text_h = screen_area().h - fix_text_y; break; } SDL_Rect update_area = sdl::create_rect(0 , fix_text_y , screen_area().w , fix_text_h); /* do */ { // this should kill the tiniest flickering caused // by the buttons being hidden and unhidden in this scope. update_locker locker(video_); next_button_.hide(); back_button_.hide(); play_button_.hide(); //TODO: blurring const SDL_Rect box = sdl::create_rect(0, fix_text_y, screen_area().w, fix_text_h); sdl::fill_rect(video_, box, storyshadow_r, storyshadow_g, storyshadow_b, storyshadow_a); render_story_box_borders(update_area); // no-op if LOW_MEM is defined next_button_.hide(false); back_button_.hide(false); play_button_.hide(false); } // Time to do some f*****g visual effect. const int scan_height = 1, scan_width = txttxt.width(); SDL_Rect scan = sdl::create_rect(0, 0, scan_width, scan_height); SDL_Rect dstrect = sdl::create_rect(text_x_, 0, scan_width, scan_height); bool scan_finished = false; while(true) { scan_finished = scan.y >= txttxt.base_height(); if (!scan_finished) { dstrect.y = fix_text_y + scan.y + storybox_padding; txttxt.set_clip(scan); video_.draw_texture(txttxt, dstrect.x, dstrect.y); video_.flip(); ++scan.y; } else skip_ = true; if (handle_interface()) break; if (!skip_ || scan_finished) { CVideo::delay(20); } } const SDL_Rect rect = sdl::create_rect(0, 0, video_.getx(), video_.gety()); sdl::fill_rect(video_, rect, 0, 0, 0, SDL_ALPHA_OPAQUE); #else LOG_NG<< "ENTER part_ui()::render_story_box()\n"; bool first = true; render_background(); if(p_.show_title()) { render_title_box(); } if(!imgs_.empty()) { if(!render_floating_images()) { return; } } const std::string& storytxt = p_.text(); if(storytxt.empty()) { wait_for_input(); return; } skip_ = false; last_key_ = true; font::ttext t; bool scan_finished = false; SDL_Rect scan; SDL_Rect dstrect; while(true) { if (dirty_) { render_background(); if(p_.show_title()) { render_title_box(); } if(!imgs_.empty()) { if(!render_floating_images()) { return; } } } part::BLOCK_LOCATION tbl = p_.story_text_location(); int max_width = buttons_x_ - storybox_padding - text_x_; int max_height = screen_area().h - storybox_padding; if(!t.set_text(p_.text(), true)) { ERR_NG << "Text: Invalid markup in '" << p_.text() << "' rendered as is.\n"; t.set_text(p_.text(), false); } t.set_font_style(font::ttext::STYLE_NORMAL) .set_font_size(storybox_font_size) .set_foreground_color(storybox_font_color) .set_maximum_width(max_width) .set_maximum_height(max_height, true); surface txtsurf = t.render(); if(txtsurf.null()) { ERR_NG << "storyscreen text area rendering resulted in a null surface" << std::endl; return; } int fix_text_y = text_y_; if(fix_text_y + 2*(storybox_padding+1) + txtsurf->h > screen_area().h && tbl != part::BLOCK_TOP) { fix_text_y = (screen_area().h > txtsurf->h + 1) ? (std::max(0, screen_area().h - txtsurf->h - 2*(storybox_padding+1))) : (0); } int fix_text_h; switch(tbl) { case part::BLOCK_TOP: fix_text_h = std::max(txtsurf->h + 2*storybox_padding, screen_area().h/4); break; case part::BLOCK_MIDDLE: fix_text_h = std::max(txtsurf->h + 2*storybox_padding, screen_area().h/3); break; default: fix_text_h = screen_area().h - fix_text_y; break; } SDL_Rect update_area = sdl::create_rect(0 , fix_text_y , screen_area().w , fix_text_h); /* do */{ // this should kill the tiniest flickering caused // by the buttons being hidden and unhidden in this scope. update_locker locker(video_); next_button_.hide(); back_button_.hide(); play_button_.hide(); #ifndef LOW_MEM if (dirty_ || first) { blur_area(video_, fix_text_y, fix_text_h); } #endif if (dirty_ || first) { sdl::draw_solid_tinted_rectangle( 0, fix_text_y, screen_area().w, fix_text_h, storyshadow_r, storyshadow_g, storyshadow_b, storyshadow_opacity, video_.getSurface() ); } render_story_box_borders(update_area); // no-op if LOW_MEM is defined next_button_.hide(false); back_button_.hide(false); play_button_.hide(false); } if (dirty_ || first) { if(!imgs_.empty() && update_area.h > 0) { update_rect(update_area); } } // Time to do some visual effecta. if (dirty_ || first) { const int scan_height = 1, scan_width = txtsurf->w; scan = sdl::create_rect(0, 0, scan_width, scan_height); dstrect = sdl::create_rect(text_x_, 0, scan_width, scan_height); } /* This needs to happen before poll for events */ dirty_ = false; first = false; scan_finished = scan.y >= txtsurf->h; if (!scan_finished) { //dstrect.x = text_x_; dstrect.y = fix_text_y + scan.y + storybox_padding; // NOTE: ::blit_surface() screws up with antialiasing and hinting when // on backgroundless (e.g. black) screens; ttext::draw() // uses it nonetheless, no idea why... // Here we'll use CVideo::blit_surface() instead. video_.blit_surface(dstrect.x, dstrect.y, txtsurf, &scan); update_rect(dstrect); ++scan.y; } else { skip_ = true; } if (handle_interface()) break; if (!skip_ || scan_finished) { CVideo::delay(20); } } sdl::draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); #endif }