bool part_ui::render_floating_images() { events::raise_draw_event(); update_whole_screen(); skip_ = false; last_key_ = true; size_t fi_n = 0; foreach(floating_image::render_input& ri, imgs_) { const floating_image& fi = p_.get_floating_images()[fi_n]; if(!ri.image.null()) { sdl_blit(ri.image, NULL, video_.getSurface(), &ri.rect); update_rect(ri.rect); } if (!skip_) { int delay = fi.display_delay(), delay_step = 20; for (int i = 0; i != (delay + delay_step - 1) / delay_step; ++i) { if (handle_interface()) return false; if (skip_) break; disp_.delay(std::min<int>(delay_step, delay - i * delay_step)); } } ++fi_n; } return true; }
void loadscreen::clear_screen() { int scrx = screen_.getx(); //< Screen width. int scry = screen_.gety(); //< Screen height. SDL_Rect area = create_rect(0, 0, scrx, scry); // Screen area. surface disp(screen_.getSurface()); // Screen surface. // Make everything black. sdl_fill_rect(disp,&area,SDL_MapRGB(disp->format,0,0,0)); update_whole_screen(); screen_.flip(); }
void the_end(display &disp, std::string text, unsigned int duration) { // // Some sane defaults. // if(text.empty()) text = _("The End"); if(!duration) duration = 3500; SDL_Rect area = screen_area(); CVideo &video = disp.video(); sdl_fill_rect(video.getSurface(),&area,0); update_whole_screen(); disp.flip(); const size_t font_size = font::SIZE_XLARGE; area = font::text_area(text,font_size); area.x = screen_area().w/2 - area.w/2; area.y = screen_area().h/2 - area.h/2; for(size_t n = 0; n < 255; n += 5) { if(n) sdl_fill_rect(video.getSurface(),&area,0); const SDL_Color col = create_color(n, n, n, n); font::draw_text(&video,area,font_size,col,text,area.x,area.y); update_rect(area); events::pump(); events::raise_process_event(); events::raise_draw_event(); disp.flip(); disp.delay(10); } // // Delay after the end of fading. // Rounded to multiples of 10. // unsigned int count = duration/10; while(count) { events::pump(); events::raise_process_event(); events::raise_draw_event(); disp.flip(); disp.delay(10); --count; } }
void loadscreen::clear_screen() { #if SDL_VERSION_ATLEAST(2,0,0) CVideo::get_window()->fill(0,0,0); #else int scrx = screen_.getx(); // Screen width. int scry = screen_.gety(); // Screen height. SDL_Rect area = sdl::create_rect(0, 0, scrx, scry); // Screen area. surface disp(screen_.getSurface()); // Screen surface. // Make everything black. sdl::fill_rect(disp,&area,SDL_MapRGB(disp->format,0,0,0)); update_whole_screen(); screen_.flip(); #endif }
void loadscreen::clear_screen() { #ifdef SDL_GPU GPU_Clear(get_render_target()); #else int scrx = screen_.getx(); // Screen width. int scry = screen_.gety(); // Screen height. SDL_Rect area = sdl::create_rect(0, 0, scrx, scry); // Screen area. surface disp(screen_.getSurface()); // Screen surface. // Make everything black. sdl::fill_rect(disp,&area,SDL_MapRGB(disp->format,0,0,0)); update_whole_screen(); screen_.flip(); #endif }
void pump() { SDL_PumpEvents(); pump_info info; //used to keep track of double click events static int last_mouse_down = -1; static int last_click_x = -1, last_click_y = -1; SDL_Event temp_event; int poll_count = 0; int begin_ignoring = 0; std::vector< SDL_Event > events; while(SDL_PollEvent(&temp_event)) { ++poll_count; if(!begin_ignoring && temp_event.type == SDL_ACTIVEEVENT) { begin_ignoring = poll_count; } else if(begin_ignoring > 0 && SDL_EVENTMASK(temp_event.type)&INPUT_MASK) { //ignore user input events that occurred after the window was activated continue; } events.push_back(temp_event); } std::vector<SDL_Event>::iterator ev_it = events.begin(); for(int i=1; i < begin_ignoring; ++i){ if(SDL_EVENTMASK(ev_it->type)&INPUT_MASK) { //ignore user input events that occurred before the window was activated ev_it = events.erase(ev_it); } else { ++ev_it; } } std::vector<SDL_Event>::iterator ev_end = events.end(); for(ev_it = events.begin(); ev_it != ev_end; ++ev_it){ SDL_Event &event = *ev_it; switch(event.type) { case SDL_ACTIVEEVENT: { SDL_ActiveEvent& ae = reinterpret_cast<SDL_ActiveEvent&>(event); if((ae.state & SDL_APPMOUSEFOCUS) != 0 || (ae.state & SDL_APPINPUTFOCUS) != 0) { cursor::set_focus(ae.gain != 0); } break; } //if the window must be redrawn, update the entire screen case SDL_VIDEOEXPOSE: { update_whole_screen(); break; } case SDL_VIDEORESIZE: { const SDL_ResizeEvent* const resize = reinterpret_cast<SDL_ResizeEvent*>(&event); info.resize_dimensions.first = resize->w; info.resize_dimensions.second = resize->h; break; } case SDL_MOUSEMOTION: { //always make sure a cursor is displayed if the //mouse moves or if the user clicks cursor::set_focus(true); raise_help_string_event(event.motion.x,event.motion.y); break; } case SDL_MOUSEBUTTONDOWN: { //always make sure a cursor is displayed if the //mouse moves or if the user clicks cursor::set_focus(true); if(event.button.button == SDL_BUTTON_LEFT) { static const int DoubleClickTime = 500; static const int DoubleClickMaxMove = 3; if(last_mouse_down >= 0 && info.ticks() - last_mouse_down < DoubleClickTime && abs(event.button.x - last_click_x) < DoubleClickMaxMove && abs(event.button.y - last_click_y) < DoubleClickMaxMove) { SDL_UserEvent user_event; user_event.type = DOUBLE_CLICK_EVENT; user_event.code = 0; user_event.data1 = reinterpret_cast<void*>(event.button.x); user_event.data2 = reinterpret_cast<void*>(event.button.y); ::SDL_PushEvent(reinterpret_cast<SDL_Event*>(&user_event)); } last_mouse_down = info.ticks(); last_click_x = event.button.x; last_click_y = event.button.y; } break; } #if defined(_X11) && !defined(__APPLE__) case SDL_SYSWMEVENT: { //clipboard support for X11 handle_system_event(event); break; } #endif case SDL_QUIT: { throw CVideo::quit(); } } if(event_contexts.empty() == false) { const std::vector<handler*>& event_handlers = event_contexts.back().handlers; //events may cause more event handlers to be added and/or removed, //so we must use indexes instead of iterators here. for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { event_handlers[i1]->handle_event(event); } } } //inform the pump monitors that an events::pump() has occurred for(size_t i1 = 0, i2 = pump_monitors.size(); i1 != i2 && i1 < pump_monitors.size(); ++i1) { pump_monitors[i1]->process(info); } }
void part_ui::render_story_box() { #ifdef SDL_GPU LOG_NG << "ENTER part_ui()::render_story_box()\n"; GPU_Target *target = get_render_target(); 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(*target, 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) { disp_.delay(20); } } const SDL_Rect rect = sdl::create_rect(0, 0, video_.getx(), video_.gety()); sdl::fill_rect(*target, rect, 0, 0, 0, 255); #else LOG_NG << "ENTER part_ui()::render_story_box()\n"; const std::string& storytxt = p_.text(); if(storytxt.empty()) { update_whole_screen(); 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); 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 blur_area(video_, fix_text_y, fix_text_h); #endif 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(imgs_.empty()) { update_whole_screen(); } else if(update_area.h > 0) { update_rect(update_area); } // Time to do some f*****g visual effect. const int scan_height = 1, scan_width = txtsurf->w; 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); surface scan_dst = video_.getSurface(); bool scan_finished = false; while(true) { 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) { disp_.delay(20); } } sdl::draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); #endif }
void pump() { SDL_PumpEvents(); #if SDL_VERSION_ATLEAST(2,0,0) peek_for_resize(); #endif pump_info info; //used to keep track of double click events static int last_mouse_down = -1; static int last_click_x = -1, last_click_y = -1; SDL_Event temp_event; int poll_count = 0; int begin_ignoring = 0; std::vector< SDL_Event > events; while(SDL_PollEvent(&temp_event)) { ++poll_count; #if SDL_VERSION_ATLEAST(2, 0, 0) peek_for_resize(); if(!begin_ignoring && temp_event.type == SDL_WINDOWEVENT && (temp_event.window.event == SDL_WINDOWEVENT_ENTER || temp_event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)) #else if(!begin_ignoring && temp_event.type == SDL_ACTIVEEVENT) #endif { begin_ignoring = poll_count; } else if(begin_ignoring > 0 && is_input(temp_event)) { //ignore user input events that occurred after the window was activated continue; } events.push_back(temp_event); } std::vector<SDL_Event>::iterator ev_it = events.begin(); for(int i=1; i < begin_ignoring; ++i){ if(is_input(*ev_it)) { //ignore user input events that occurred before the window was activated ev_it = events.erase(ev_it); } else { ++ev_it; } } std::vector<SDL_Event>::iterator ev_end = events.end(); for(ev_it = events.begin(); ev_it != ev_end; ++ev_it){ SDL_Event &event = *ev_it; switch(event.type) { #if SDL_VERSION_ATLEAST(2, 0, 0) case SDL_WINDOWEVENT: switch(event.window.event) { case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_FOCUS_GAINED: cursor::set_focus(1); break; case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_FOCUS_LOST: cursor::set_focus(1); break; case SDL_WINDOWEVENT_EXPOSED: update_whole_screen(); break; case SDL_WINDOWEVENT_RESIZED: { info.resize_dimensions.first = event.window.data1; info.resize_dimensions.second = event.window.data2; break; } } break; #else case SDL_ACTIVEEVENT: { SDL_ActiveEvent& ae = reinterpret_cast<SDL_ActiveEvent&>(event); if((ae.state & SDL_APPMOUSEFOCUS) != 0 || (ae.state & SDL_APPINPUTFOCUS) != 0) { cursor::set_focus(ae.gain != 0); } break; } //if the window must be redrawn, update the entire screen case SDL_VIDEOEXPOSE: update_whole_screen(); break; case SDL_VIDEORESIZE: { const SDL_ResizeEvent* const resize = reinterpret_cast<SDL_ResizeEvent*>(&event); info.resize_dimensions.first = resize->w; info.resize_dimensions.second = resize->h; break; } #endif case SDL_MOUSEMOTION: { //always make sure a cursor is displayed if the //mouse moves or if the user clicks cursor::set_focus(true); raise_help_string_event(event.motion.x,event.motion.y); break; } case SDL_MOUSEBUTTONDOWN: { //always make sure a cursor is displayed if the //mouse moves or if the user clicks cursor::set_focus(true); if(event.button.button == SDL_BUTTON_LEFT) { static const int DoubleClickTime = 500; static const int DoubleClickMaxMove = 3; if(last_mouse_down >= 0 && info.ticks() - last_mouse_down < DoubleClickTime && abs(event.button.x - last_click_x) < DoubleClickMaxMove && abs(event.button.y - last_click_y) < DoubleClickMaxMove) { SDL_UserEvent user_event; user_event.type = DOUBLE_CLICK_EVENT; user_event.code = 0; user_event.data1 = reinterpret_cast<void*>(event.button.x); user_event.data2 = reinterpret_cast<void*>(event.button.y); ::SDL_PushEvent(reinterpret_cast<SDL_Event*>(&user_event)); } last_mouse_down = info.ticks(); last_click_x = event.button.x; last_click_y = event.button.y; } break; } #ifndef __APPLE__ case SDL_KEYDOWN: { if(event.key.keysym.sym == SDLK_F4 && (event.key.keysym.mod == KMOD_RALT || event.key.keysym.mod == KMOD_LALT)) { quit_confirmation::quit(); continue; // this event is already handled } break; } #endif #if defined(_X11) && !defined(__APPLE__) case SDL_SYSWMEVENT: { //clipboard support for X11 desktop::clipboard::handle_system_event(event); break; } #endif #if defined _WIN32 case SDL_SYSWMEVENT: { windows_tray_notification::handle_system_event(event); break; } #endif case SDL_QUIT: { quit_confirmation::quit(); continue; //this event is already handled. } } if(event_contexts.empty() == false) { const std::vector<sdl_handler*>& event_handlers = event_contexts.back().handlers; //events may cause more event handlers to be added and/or removed, //so we must use indexes instead of iterators here. for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { event_handlers[i1]->handle_event(event); } } } //inform the pump monitors that an events::pump() has occurred for(size_t i1 = 0, i2 = pump_monitors.size(); i1 != i2 && i1 < pump_monitors.size(); ++i1) { pump_monitors[i1]->process(info); } }