Font * Fonts::load(XML_Element_c &xml_element, const String &/*name*/, const String &/*filename*/) { const String filepath = xml_element["filepath"].to_string(); const float height = xml_element["height"].to_float(); const float screen_height = float(get_Window().get_height()); float virtual_screen_height = screen_height; XML_Element_c virtual_screen = xml_element["virtual_screen"]; if(virtual_screen.good()) { XML_Element_c vsw = virtual_screen["width"]; XML_Element_c vsh = virtual_screen["height"]; if(vsw.good()) { const float vsw_ratio = vsw.to_float() / get_Window().get_width(); if(vsh.good()) { virtual_screen_height = vsh.to_float(); if(vsw_ratio > virtual_screen_height / screen_height) virtual_screen_height = vsw_ratio * screen_height; } else virtual_screen_height = vsw_ratio * screen_height; } else if(vsh.good()) virtual_screen_height = vsh.to_float(); } return get_Video().create_Font(filepath, height, virtual_screen_height); }
void Play_State_Base::render() { Game_Model::get().render(); int width = get_Window().get_width(); int height = get_Window().get_height(); // get_Video().set_2d(pair<Point2f, Point2f>(Point2f(0,0), Point2f(width, height))); // get_Fonts()["system_36_800x600"].render_text(controllers[0]->give_stick_status().c_str(), Point2f(0, 0), Color(1, 0.1, 0.85, 0.1 )); // if (Game_Model::get().table.get_collided()) // get_Fonts()["system_36_800x600"].render_text("Collision detected.", Point2f(0, 300), Color(1, 0.1, 0.85, 0.1 )); }
Font_FT::Font_FT(const String &filepath, const bool &bold, const bool &italic, const float &glyph_height, const float &virtual_screen_height) : Font(bold, italic, glyph_height, (virtual_screen_height < MINIMUM_VIRTUAL_SCREEN_HEIGHT || virtual_screen_height > MAXIMUM_VIRTUAL_SCREEN_HEIGHT) ? float(get_Window().get_height()) : virtual_screen_height, filepath), m_font_height(glyph_height), m_vratio(get_Window().get_height() / get_virtual_screen_height()) { init(filepath); }
void Play_State_Base::on_pop() { get_Window().mouse_hide(false); get_Window().mouse_grab(false); get_Video().set_clear_Color(m_prev_clear_color); get_Game().joy_mouse.enabled = true; Game_Model::get().clean(); for (int i = 0 ; i < player_info->size() ; i++) delete player_info->at(i); delete player_info; for(int i = 0; i < controllers.size() ; i++) { delete controllers[i]; } }
Console_State::Console_State() : m_virtual_screen(Point2f(0.0f, 0.0f), Point2f(float(get_Window().get_width() * 600.0f / get_Window().get_height()), 600.0f)), m_projector(m_virtual_screen), m_bg(Vertex2f_Color(Point2f(0.0f, 0.0f), get_Colors()["console_border"]), Vertex2f_Color(Point2f(0.0f, 54.0f + 7.0f * get_Fonts()["system_36_x600"].get_text_height()), get_Colors()["console_border"]), Vertex2f_Color(Point2f(m_virtual_screen.second.x, 54.0f + 7.0f * get_Fonts()["system_36_x600"].get_text_height()), get_Colors()["console_border"]), Vertex2f_Color(Point2f(m_virtual_screen.second.x, 0.0f), get_Colors()["console_border"])), m_log(Point2f(18.0f, 18.0f), Point2f(m_virtual_screen.second.x - 18.0f, 18.0f + 6.0f * get_Fonts()["system_36_x600"].get_text_height()), "system_36_x600", "", get_Colors()["console_foreground"], false), m_prompt(Point2f(18.0f, 36.0f + 6.0f * get_Fonts()["system_36_x600"].get_text_height()), Point2f(m_virtual_screen.second.x - 18.0f, 36.0f + 7.0f * get_Fonts()["system_36_x600"].get_text_height()), "system_36_x600", "", get_Colors()["console_foreground"], true), m_log_dirty(false), m_child(0) { m_functions["args"] = new Console_Function; m_log.give_BG_Renderer(new Widget_Renderer_Color(get_Colors()["console_background"])); m_prompt.give_BG_Renderer(new Widget_Renderer_Color(get_Colors()["console_background"])); }
void Play_State_Base::on_push() { get_Window().mouse_hide(true); get_Window().mouse_grab(true); get_Video().set_clear_Color(Color(0,.1,.1,.1)); get_Game().joy_mouse.enabled = false; Game_Model::get().change_level(create_level(level.std_str())); Game_Model::get().start_up(*player_info); if(!isLocal) Game_Model::get().initialize_peer(isServer, host_addr); for(int i = 0; i < Game_Model::get().num_players_here() ; i++) { controllers.push_back(new Controls(false, i)); if(player_info->at(i)->controls_ == 1) controllers[i]->set_inverted(true); controllers[i]->set_input_sensitivity(player_info->at(i)->sensitivities_); } }
void Widget_Gamestate::on_pop() { get_Video().set_clear_Color(m_clear_color); #ifndef ANDROID Window &wr = get_Window(); if(m_hide_cursor) wr.mouse_hide(true); if(m_grab_input) wr.mouse_grab(true); #endif }
bool Video_DX9::begin_render() { assert(!m_render_target && !m_render_to_surface); HRESULT result = m_d3d_device->Present(0, 0, 0, 0); if(result == S_OK) { D3DVIEWPORT9 vp = {0, 0, DWORD(get_Window().get_width()), DWORD(get_Window().get_height()), 0, 1}; m_d3d_device->SetViewport(&vp); m_d3d_device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(get_clear_Color().r_ub(), get_clear_Color().g_ub(), get_clear_Color().b_ub()), 1.0f, 0); m_d3d_device->BeginScene(); return true; } else if(result == D3DERR_DEVICELOST) { g_video_dx9_reset = true; return false; } else if(result == D3DERR_DEVICEREMOVED) { throw Video_Device_Failure(); } return false; }
void Widget_Gamestate::on_push() { #ifndef ANDROID Window &wr = get_Window(); m_hide_cursor = wr.is_mouse_hidden(); if(m_hide_cursor) wr.mouse_hide(false); m_grab_input = wr.is_mouse_grabbed(); if(m_grab_input) wr.mouse_grab(false); #endif m_clear_color = get_Video().get_clear_Color(); }
void Console_State::perform_logic() { m_virtual_screen = std::make_pair(Point2f(0.0f, 0.0f), Point2f(float(get_Window().get_width() * 600.0f / get_Window().get_height()), 600.0f)); m_projector = Projector2D(m_virtual_screen); if(m_bg.c.position.x != m_virtual_screen.second.x) { m_bg.c.position.x = m_virtual_screen.second.x; m_bg.d.position.x = m_virtual_screen.second.x; const float right = m_virtual_screen.second.x - 18.0f; m_log.set_lower_right(Point2f(right, m_log.get_lower_right().y)); m_prompt.set_lower_right(Point2f(right, m_prompt.get_lower_right().y)); } m_child->perform_logic(); }
void x_gui_rep::emulate_leave_enter (widget old_widget, widget new_widget) { Window root, child; SI root_x, root_y, x, y; unsigned int mask; XQueryPointer (dpy, get_Window (old_widget), &root, &child, &root_x, &root_y, &x, &y, &mask); set_button_state (mask); x= (x * PIXEL); y= ((-y) * PIXEL); // cout << "\nLeave " << old_widget << "\n"; send_mouse (old_widget, "leave", x, y, state, 0); // cout << "Leave OK\n"; XQueryPointer (dpy, get_Window (new_widget), &root, &child, &root_x, &root_y, &x, &y, &mask); set_button_state (mask); x= (x * PIXEL); y= ((-y) * PIXEL); // cout << "Enter " << new_widget << "\n"; send_mouse (new_widget, "enter", x, y, state, 0); // cout << "Enter OK\n\n"; }
void x_gui_rep::obtain_mouse_grab (widget wid) { Window win= get_Window (wid); if ((!is_nil (grab_ptr)) && (wid==grab_ptr->item)) return; widget old_widget; if (!is_nil (grab_ptr)) old_widget= grab_ptr->item; grab_ptr= list<widget> (wid, grab_ptr); widget new_widget= grab_ptr->item; notify_mouse_grab (new_widget, true); XGrabPointer (dpy, win, false, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); // cout << "\n---> In grab " << pritty ((tree) wid) << "\n\n"; if (!is_nil (old_widget)) { notify_mouse_grab (old_widget, false); emulate_leave_enter (old_widget, new_widget); } }
Video::Video() : m_color(1.0f, 1.0f, 1.0f, 1.0f), m_preview(Matrix4f::Translate(Vector3f(-0.5f, -0.5f, 0.0f)) * Matrix4f::Scale(Vector3f(0.5f, -0.5f, -1.0f)) * Matrix4f::Translate(Vector3f(1.0f, -1.0f, 0.0f))), m_alpha_test(false), m_alpha_function(Video::ZENI_ALWAYS), m_alpha_value(0.0f), m_3d(false) { Window::remove_post_reinit(&g_reinit); Window &wr = get_Window(); wr.lend_pre_uninit(&g_uninit); wr.lend_post_reinit(&g_reinit); }
void Video::change_resolution(const Point2i &resolution) { Window &wr = get_Window(); if(wr.get_width() == resolution.x && wr.get_height() == resolution.y) return; destroy(); try { preinit_from_file(get_File_Ops().get_appdata_path() + "config/zenilib.xml"); } catch(XML_Load_Failure &) { preinit_from_file("config/zenilib.xml"); } #ifndef ANDROID wr.alert_window_resized(resolution); #endif get(); }
void Console_State::on_mouse_motion(const SDL_MouseMotionEvent &event) { m_prompt.on_event(event, m_virtual_screen); m_handled_event = (float(event.y) / get_Window().get_height()) < (m_bg.c.position.y / 600.0f); }
void Crate_State::on_push() { get_Window().set_mouse_state(Window::MOUSE_RELATIVE); }
Window * Window::create() { Window * window = 0; #ifndef ANDROID File_Ops &fo = get_File_Ops(); const String appdata_path = fo.get_appdata_path(); const String user_normal = appdata_path + "config/zenilib.xml"; const String user_backup = user_normal + ".bak"; const String local_normal = "config/zenilib.xml"; const String local_backup = local_normal + ".bak"; static bool last_resort_taken = false; #endif #ifndef ANDROID try { switch(Video::get_video_mode()) { case Video::ZENI_VIDEO_ANY: #ifndef DISABLE_GL_SHADER case Video::ZENI_VIDEO_GL_SHADER: Window::set_opengl_flag(true); break; #endif #ifndef DISABLE_DX9 case Video::ZENI_VIDEO_DX9: Window::set_opengl_flag(false); break; #endif #ifndef DISABLE_GL_FIXED case Video::ZENI_VIDEO_GL_FIXED: Window::set_opengl_flag(true); break; #endif default: throw Window_Init_Failure(); } #endif window = new Window; #ifndef ANDROID } catch(Window_Init_Failure &) { if(fo.copy_file(user_backup, user_normal) && fo.delete_file(user_backup)) { std::cerr << '\'' << user_normal << "' backup restored due to initialization failure.\n"; Video::preinit_from_file(user_normal); get_Window(); } else if(fo.copy_file(local_backup, local_normal) && fo.delete_file(local_backup)) { std::cerr << '\'' << local_normal << "' backup restored due to initialization failure.\n"; Video::preinit_from_file(local_normal); get_Window(); } else if(!last_resort_taken) { Window::set_failsafe_defaults(); last_resort_taken = true; get_Window(); } else throw; } last_resort_taken = false; #endif return window; }
void Widget_Gamestate::perform_logic() { m_viewport = get_Video().calculate_viewport(m_virtual_window, std::make_pair(Point2i(), get_Window().get_size()), m_fix_aspect_ratio); m_projector = Projector2D(m_virtual_window, m_viewport); m_widgets.perform_logic(); }
void Play_State_Base::on_uncover() { get_Window().mouse_hide(true); get_Window().mouse_grab(true); get_Game().joy_mouse.enabled = false; }
void Level_1::on_push() { get_Window().set_mouse_state(Window::MOUSE_RELATIVE); }
void Video_DX9::init() { SDL_SysWMinfo wmInfo; SDL_VERSION(&wmInfo.version); #if SDL_VERSION_ATLEAST(1,3,0) SDL_GetWindowWMInfo(get_Window().get_window(), &wmInfo); HWND hWnd = wmInfo.win.window; #else SDL_GetWMInfo(&wmInfo); HWND hWnd = wmInfo.window; #endif std::cout << "Initializing DirectX 9" << std::endl; try { m_d3d_capabilities = new D3DCAPS9; m_d3d_parameters = new D3DPRESENT_PARAMETERS; } catch (...) { throw Video_Init_Failure(); } m_d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_d3d_capabilities); m_dpi = GetDeviceCaps(GetDC(hWnd), LOGPIXELSY); ZeroMemory(m_d3d_parameters, sizeof(m_d3d_parameters)); m_d3d_parameters->hDeviceWindow = hWnd; m_d3d_parameters->Windowed = true; m_d3d_parameters->FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; m_d3d_parameters->BackBufferCount = 1; m_d3d_parameters->BackBufferWidth = UINT(get_Window().get_width()); m_d3d_parameters->BackBufferHeight = UINT(get_Window().get_height()); m_d3d_parameters->BackBufferFormat = D3DFMT_A8R8G8B8; m_d3d_parameters->SwapEffect = D3DSWAPEFFECT_DISCARD; m_d3d_parameters->PresentationInterval = get_vertical_sync() ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; m_d3d_parameters->Flags = 0; //D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; m_d3d_parameters->EnableAutoDepthStencil = true; m_d3d_parameters->AutoDepthStencilFormat = D3DFMT_D16; if(get_multisampling() > 1) switch(get_multisampling()) { case 2: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_2_SAMPLES; break; case 3: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_3_SAMPLES; break; case 4: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_4_SAMPLES; break; case 5: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_5_SAMPLES; break; case 6: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_6_SAMPLES; break; case 7: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_7_SAMPLES; break; case 8: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_8_SAMPLES; break; case 9: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_9_SAMPLES; break; case 10: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_10_SAMPLES; break; case 11: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_11_SAMPLES; break; case 12: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_12_SAMPLES; break; case 13: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_13_SAMPLES; break; case 14: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_14_SAMPLES; break; case 15: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_15_SAMPLES; break; case 16: default: m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_16_SAMPLES; break; } else if(get_multisampling() < 0) m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_16_SAMPLES; else m_d3d_parameters->MultiSampleType = D3DMULTISAMPLE_NONE; m_d3d_parameters->MultiSampleQuality = 0; // Initialize the D3D device if(!init_device()) throw Video_Init_Failure(); // Initialize the rendering context init_context(); }
inline const Point2i & Video_DX9::get_render_target_size() const { if(m_render_target) return m_render_target->get_size(); else return get_Window().get_size(); }
void Game::run() { #ifdef TEST_NASTY_CONDITIONS Random random; const float time_scale = NASTY_MIN_RATE + (NASTY_MAX_RATE - NASTY_MIN_RATE) * random.frand_lte(); Time::Second_Type time_used = Time::Second_Type(); Time start_time; #endif Sound_Source_Pool &sspr = get_Sound_Source_Pool(); Time time_processed; for(;;) { const Time time_passed; float time_step = time_passed.get_seconds_since(time_processed); time_processed = time_passed; #ifdef ENABLE_XINPUT get_Joysticks().poll(); #endif if(joy_mouse.enabled && (joy_mouse.velocity.x != 0 || joy_mouse.velocity.y != 0)) { Point2f adjusted_vel(joy_mouse.velocity.x + 0.5f, joy_mouse.velocity.y + 0.5f); if(adjusted_vel.x < 0.0f) adjusted_vel.x = std::min(0.0f, adjusted_vel.x + joy_mouse.noise_zone.x); else adjusted_vel.x = std::max(0.0f, adjusted_vel.x - joy_mouse.noise_zone.x); if(adjusted_vel.y < 0.0f) adjusted_vel.y = std::min(0.0f, adjusted_vel.y + joy_mouse.noise_zone.y); else adjusted_vel.y = std::max(0.0f, adjusted_vel.y - joy_mouse.noise_zone.y); adjusted_vel.x /= 32767.5f - joy_mouse.noise_zone.x; adjusted_vel.y /= 32767.5f - joy_mouse.noise_zone.y; int xrel = int(adjusted_vel.x * joy_mouse.pixels_per_second.x * time_step); int yrel = int(adjusted_vel.y * joy_mouse.pixels_per_second.y * time_step); if(xrel || yrel) { int x, y; SDL_GetMouseState(&x, &y); x += xrel; y += yrel; if(x < 0) x = 0; else if(x >= get_Window().get_width()) x = get_Window().get_width() - 1; if(y < 0) y = 0; else if(y >= get_Window().get_width()) y = get_Window().get_height() - 1; SDL_WarpMouse(Uint16(x), Uint16(y)); } } for(SDL_Event event; SDL_PollEvent(&event);) { if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) { const SDL_keysym &s = event.key.keysym; const bool alt = get_key_state(SDLK_LALT) || get_key_state(SDLK_RALT); const bool ctrl = get_key_state(SDLK_LCTRL) || get_key_state(SDLK_RCTRL); const bool shift = get_key_state(SDLK_LSHIFT) || get_key_state(SDLK_RSHIFT); const bool gui = #if SDL_VERSION_ATLEAST(1,3,0) get_key_state(SDLK_LGUI) || get_key_state(SDLK_RGUI); #else get_key_state(SDLK_LMETA) || get_key_state(SDLK_RMETA) || get_key_state(SDLK_LSUPER) || get_key_state(SDLK_RSUPER); #endif #ifndef NDEBUG if(s.sym == SDLK_BACKQUOTE && alt && !ctrl && !gui && !shift) { if(event.type == SDL_KEYDOWN) { if(m_console_active) deactivate_console(); else activate_console(); } continue; } #endif on_event(event); if(event.type == SDL_KEYDOWN && ( #if defined(_MACOSX) (!alt && !ctrl && gui && !shift && s.sym == SDLK_q) || #endif (!alt && ctrl && !gui && !shift && s.sym == SDLK_q) || ( alt && !ctrl && !gui && !shift && s.sym == SDLK_F4))) { throw Quit_Event(); } } #if SDL_VERSION_ATLEAST(1,3,0) else if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) { on_event(event); if(event.window.windowID == SDL_GetWindowID(get_Window().get_window())) { get_Window().alert_window_destroyed(); throw Quit_Event(); } } #endif else if(event.type == SDL_JOYAXISMOTION) { if(joy_mouse.enabled && (joy_mouse.joy_axes.x == event.jaxis.axis || joy_mouse.joy_axes.y == event.jaxis.axis)) { if(joy_mouse.joy_axes.x == event.jaxis.axis) joy_mouse.velocity.x = event.jaxis.value; else joy_mouse.velocity.y = event.jaxis.value; } else on_event(event); } else if(event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP) { #ifdef _MACOSX if(event.jbutton.which < 4 && event.jbutton.button < 4) { static bool values[4][4] = {{false, false, false, false}, {false, false, false, false}, {false, false, false, false}, {false, false, false, false}}; values[event.jbutton.which][event.jbutton.button] = event.jbutton.state == SDL_PRESSED; SDL_Event e; e.type = Uint8(SDL_JOYHATMOTION); e.jhat.which = event.jbutton.which; e.jhat.hat = 0; if(values[event.jbutton.which][0]) { if(values[event.jbutton.which][2]) e.jhat.value = SDL_HAT_LEFTUP; else if(values[event.jbutton.which][3]) e.jhat.value = SDL_HAT_RIGHTUP; else e.jhat.value = SDL_HAT_UP; } else if(values[event.jbutton.which][1]) { if(values[event.jbutton.which][2]) e.jhat.value = SDL_HAT_LEFTDOWN; else if(values[event.jbutton.which][3]) e.jhat.value = SDL_HAT_RIGHTDOWN; else e.jhat.value = SDL_HAT_DOWN; } else { if(values[event.jbutton.which][2]) e.jhat.value = SDL_HAT_LEFT; else if(values[event.jbutton.which][3]) e.jhat.value = SDL_HAT_RIGHT; else e.jhat.value = SDL_HAT_CENTERED; } SDL_PushEvent(&e); } else #endif if(joy_mouse.enabled && joy_mouse.left_click == event.jbutton.button) { SDL_Event e; e.type = Uint8(event.type == SDL_JOYBUTTONDOWN ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP); e.button.which = Uint8(event.jbutton.which + 1); e.button.state = event.jbutton.state; e.button.button = SDL_BUTTON_LEFT; int x, y; SDL_GetMouseState(&x, &y); e.button.x = Uint16(x); e.button.y = Uint16(y); on_event(e); } else if(joy_mouse.enabled && joy_mouse.escape == event.jbutton.button) { SDL_Event e; e.type = Uint8(event.type == SDL_JOYBUTTONDOWN ? SDL_KEYDOWN : SDL_KEYUP); e.key.which = Uint8(event.jbutton.which + 1); e.key.state = event.jbutton.state; e.key.keysym.mod = SDL_GetModState(); e.key.keysym.scancode = 0; e.key.keysym.sym = SDLK_ESCAPE; e.key.keysym.unicode = 0; on_event(e); } else on_event(event); } else if(event.type == SDL_JOYHATMOTION) { if(joy_mouse.enabled && joy_mouse.scroll_hat == event.jhat.hat && (event.jhat.value == SDL_HAT_DOWN || event.jhat.value == SDL_HAT_UP)) { SDL_Event e; e.type = SDL_MOUSEBUTTONDOWN; e.button.which = Uint8(event.jhat.which + 1); e.button.state = SDL_PRESSED; e.button.button = Uint8(event.jhat.value == SDL_HAT_DOWN ? SDL_BUTTON_WHEELDOWN : SDL_BUTTON_WHEELUP); int x, y; SDL_GetMouseState(&x, &y); e.button.x = Uint16(x); e.button.y = Uint16(y); on_event(e); e.type = SDL_MOUSEBUTTONUP; e.button.state = SDL_RELEASED; on_event(e); } else on_event(event); } else { on_event(event); if(event.type == SDL_QUIT) throw Quit_Event(); } } #ifdef TEST_NASTY_CONDITIONS { const Time current_time; const Time::Second_Type time_passed = time_scale * current_time.get_seconds_since(start_time); size_t step_count = 0u; while(time_used + (1 / 60.0f) < time_passed) { time_used += (1 / 60.0f); perform_logic(); if(++step_count == NASTY_RATE_CUTOFF) time_used = time_passed; } if(!random.rand_lt(NASTY_ZERO_STEP_FREQUENCY)) perform_logic(); } #else perform_logic(); #endif sspr.update(); if(Window::is_enabled()) { Video &vr = get_Video(); if(vr.begin_prerender()) { prerender(); if(vr.begin_render()) { try { render(); } catch(...) { vr.end_render(); throw; } vr.end_render(); } } } } }