Ejemplo n.º 1
0
void ofxGuiGroup::render(){
    
    prerender();
        
	border.draw();
	headerBg.draw();

	ofBlendMode blendMode = ofGetStyle().blendingMode;
	if(blendMode!=OF_BLENDMODE_ALPHA){
		ofEnableAlphaBlending();
	}
	ofColor c = ofGetStyle().color;
	ofSetColor(thisTextColor);

	bindFontTexture();
	textMesh.draw();
	unbindFontTexture();
    
	if(!minimized){
		for(int i = 0; i < (int)collection.size(); i++){
            collection[i]->draw(useFbo);
		}
	}

	ofSetColor(c);
	if(blendMode!=OF_BLENDMODE_ALPHA){
		ofEnableBlendMode(blendMode);
	}
    
    postrender();
}
Ejemplo n.º 2
0
 void Canvas::render()
 {
     prerender();
     _positions.submit();
     _colors.submit();
     _indices.submit();
     glDrawElements(GL_TRIANGLES, _indices.getCount(), GL_UNSIGNED_SHORT, _indices.getPointer());
 }
Ejemplo n.º 3
0
 void Circle::render()
 {
     bool retina = Manager::instance().isRetinaDisplay();
     Vec2f absolute = getAbsolutePosition();
     absolute = native::worldToGLPixels(absolute);
     
     prerender();
     assert(_positions.submit());
     
     glUniform2f(_centerUniformLocation, absolute.x, absolute.y);
     glUniform1f(_radiusUniformLocation, retina ? _radius * 2.0 : _radius);
     glUniform1f(_edgeWidthUniformLocation, retina ? edgeWidth * 2.0 : edgeWidth);
     glUniform4f(_fillColorUniformLocation, fill.r, fill.g, fill.b, fill.a);
     glUniform4f(_edgeColorUniformLocation, edge.r, edge.g, edge.b, edge.a);
     
     glDrawArrays(GL_TRIANGLE_STRIP, 0, _positions.getCount());
 }
Ejemplo n.º 4
0
void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
	if (pass == -1)
	{
		for (S32 i = 1; i < getNumPasses(); i++)
		{ //skip foot shadows
			prerender();
			beginRenderPass(i);
			renderAvatars(single_avatar, i);
			endRenderPass(i);
		}

		return;
	}

	if (mDrawFace.empty() && !single_avatar)
	{
		return;
	}

	LLVOAvatar *avatarp;

	if (single_avatar)
	{
		avatarp = single_avatar;
	}
	else
	{
		const LLFace *facep = mDrawFace[0];
		if (!facep->getDrawable())
		{
			return;
		}
		avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
	}

    if (avatarp->isDead() || avatarp->mDrawable.isNull())
	{
		return;
	}

	if (!single_avatar && !avatarp->isFullyLoaded())
	{
		if (pass == 0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
		{
			// debug code to draw a sphere in place of avatar
			gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
			gGL.setColorMask(true, true);
			LLVector3 pos = avatarp->getPositionAgent();
			gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f);

			gGL.pushMatrix();
			gGL.translatef((F32)(pos.mV[VX]), (F32)(pos.mV[VY]), (F32)(pos.mV[VZ]));
			gGL.scalef(0.15f, 0.15f, 0.3f);

			gSphere.renderGGL();

			gGL.popMatrix();
			gGL.setColorMask(true, false);
		}
		// don't render please
		return;
	}

	BOOL impostor = avatarp->isImpostor() && !single_avatar;

	if (impostor && pass != 0)
	{ //don't draw anything but the impostor for impostored avatars
		return;
	}
	
	if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender)
	{ //don't draw foot shadows under water
		return;
	}

	if (pass == 0)
	{
		if (!LLPipeline::sReflectionRender)
		{
			LLVOAvatar::sNumVisibleAvatars++;
		}

		if (impostor)
		{
			if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender &&
				avatarp->mImpostor.isComplete()) 
			{
				if (normal_channel > -1)
				{
					avatarp->mImpostor.bindTexture(2, normal_channel);
				}
				if (specular_channel > -1)
				{
					avatarp->mImpostor.bindTexture(1, specular_channel);
				}
			}
			avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel);
		}
		return;
	}

	if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview,  3=morph view
	{
		gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f));
	}
	
	if (pass == 1)
	{
		// render rigid meshes (eyeballs) first
		avatarp->renderRigid();
		return;
	}
	
	if (pass == 3)
	{
		if (is_deferred_render)
		{
			renderDeferredRiggedSimple(avatarp);
		}
		else
		{
			renderRiggedSimple(avatarp);
		}
		return;
	}

	if (pass == 4)
	{
		if (is_deferred_render)
		{
			renderDeferredRiggedBump(avatarp);
		}
		else
		{
			renderRiggedFullbright(avatarp);
		}

		return;
	}

	if (pass == 5)
	{
		renderRiggedShinySimple(avatarp);
		return;
	}

	if (pass == 6)
	{
		renderRiggedFullbrightShiny(avatarp);
		return;
	}

	if (pass >= 7 && pass < 9)
	{
		LLGLEnable blend(GL_BLEND);

		gGL.setColorMask(true, true);
		gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
					  LLRender::BF_ONE_MINUS_SOURCE_ALPHA,
					  LLRender::BF_ZERO,
					  LLRender::BF_ONE_MINUS_SOURCE_ALPHA);

		if (pass == 7)
		{
			renderRiggedAlpha(avatarp);
			return;
		}

		if (pass == 8)
		{
			renderRiggedFullbrightAlpha(avatarp);
			return;
		}
	}

	if (pass == 9)
	{
		LLGLEnable blend(GL_BLEND);
		LLGLDisable test(GL_ALPHA_TEST);
		gGL.flush();

		LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
		glPolygonOffset(-1.0f, -1.0f);
		gGL.setSceneBlendType(LLRender::BT_ADD);

		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
		gGL.setColorMask(false, true);

		renderRiggedGlow(avatarp);
		gGL.setColorMask(true, false);
		gGL.setSceneBlendType(LLRender::BT_ALPHA);
		return;
	}

	if (sShaderLevel > 0)
	{
		gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
	}
    
	if (sShaderLevel >= SHADER_LEVEL_CLOTH)
	{
		LLMatrix4 rot_mat;
		LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
		LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
		rot_mat *= cfr;
		
		LLVector4 wind;
		wind.setVec(avatarp->mWindVec);
		wind.mV[VW] = 0;
		wind = wind * rot_mat;
		wind.mV[VW] = avatarp->mWindVec.mV[VW];

		sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_WIND, wind.mV);
		F32 phase = -1.f * (avatarp->mRipplePhase);

		F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
		LLVector4 sin_params(freq, freq, freq, phase);
		sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_SINWAVE, sin_params.mV);

		LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
		gravity = gravity * rot_mat;
		sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_GRAVITY, gravity.mV);
	}

	if (!single_avatar || avatarp == single_avatar)
	{
		avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
	}
}
Ejemplo n.º 5
0
void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
	LLFastTimer t(FTM_RENDER_AVATARS);

	if (pass == -1)
	{
		for (S32 i = 1; i < getNumPasses(); i++)
		{ //skip foot shadows
			prerender();
			beginRenderPass(i);
			renderAvatars(single_avatar, i);
			endRenderPass(i);
		}

		return;
	}

	if (mDrawFace.empty() && !single_avatar)
	{
		return;
	}

	LLVOAvatar *avatarp;

	if (single_avatar)
	{
		avatarp = single_avatar;
	}
	else
	{
		const LLFace *facep = mDrawFace[0];
		if (!facep->getDrawable())
		{
			return;
		}
		avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
	}

    if (avatarp->isDead() || avatarp->mDrawable.isNull())
	{
		return;
	}

	if (!single_avatar && !avatarp->isFullyLoaded() )
	{
		if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
		{
			// debug code to draw a sphere in place of avatar
			gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
			gGL.setColorMask(true, true);
			LLVector3 pos = avatarp->getPositionAgent();
			gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f);
			
			gGL.pushMatrix();	 
			gGL.translatef((F32)(pos.mV[VX]),	 
						   (F32)(pos.mV[VY]),	 
							(F32)(pos.mV[VZ]));	 
			 gGL.scalef(0.15f, 0.15f, 0.3f);

			 gSphere.renderGGL();

			 gGL.popMatrix();
			 gGL.setColorMask(true, false);
		}
		// don't render please
		return;
	}

	BOOL impostor = avatarp->isImpostor() && !single_avatar;

	if (impostor && pass != 0)
	{ //don't draw anything but the impostor for impostored avatars
		return;
	}
	
	if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender)
	{ //don't draw foot shadows under water
		return;
	}

	if (pass == 0)
	{
		if (!LLPipeline::sReflectionRender)
		{
			LLVOAvatar::sNumVisibleAvatars++;
		}

		if (impostor)
		{
			if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete()) 
			{
				if (normal_channel > -1)
				{
					avatarp->mImpostor.bindTexture(2, normal_channel);
				}
				if (specular_channel > -1)
				{
					avatarp->mImpostor.bindTexture(1, specular_channel);
				}
			}
			avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel);
		}
		//else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred)
		//{
		//	avatarp->renderFootShadows();	
		//}
		return;
	}

	llassert(LLPipeline::sImpostorRender || !avatarp->isVisuallyMuted());

	/*if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview,  3=morph view
	{
		gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f));
	}*/
	
	if (pass == 1)
	{
		// render rigid meshes (eyeballs) first
		avatarp->renderRigid();
		return;
	}

	if (pass == 3)
	{
		if (is_deferred_render)
		{
			renderDeferredRiggedSimple(avatarp);
		}
		else
		{
			renderRiggedSimple(avatarp);
			if (LLPipeline::sRenderDeferred)
			{ //render "simple" materials
				renderRigged(avatarp, RIGGED_MATERIAL);
				renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK);
				renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE);
				renderRigged(avatarp, RIGGED_NORMMAP);
				renderRigged(avatarp, RIGGED_NORMMAP_MASK);
				renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);	
				renderRigged(avatarp, RIGGED_SPECMAP);
				renderRigged(avatarp, RIGGED_SPECMAP_MASK);
				renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE);
				renderRigged(avatarp, RIGGED_NORMSPEC);
				renderRigged(avatarp, RIGGED_NORMSPEC_MASK);
				renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE);
			}
		}
		return;
	}

	if (pass == 4)
	{
		if (is_deferred_render)
		{
			renderDeferredRiggedBump(avatarp);
		}
		else
		{
			renderRiggedFullbright(avatarp);
		}

		return;
	}

	if (is_deferred_render && pass >= 5 && pass <= 21)
	{
		S32 p = pass-5;
		if (p != 1 &&
			p != 5 &&
			p != 9 &&
			p != 13)
		{
			renderDeferredRiggedMaterial(avatarp, p);
		}
		return;
	}
	if (pass == 5)
	{
		renderRiggedShinySimple(avatarp);
		return;
	}

	if (pass == 6)
	{
		renderRiggedFullbrightShiny(avatarp);
		return;
	}

	if (pass >= 7 && pass < 13)
	{
		if (pass == 7)
		{
			renderRiggedAlpha(avatarp);
			if (LLPipeline::sRenderDeferred && !is_post_deferred_render)
			{ //render transparent materials under water
				LLGLEnable blend(GL_BLEND);
				gGL.setColorMask(true, true);
				gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
								LLRender::BF_ONE_MINUS_SOURCE_ALPHA,
								LLRender::BF_ZERO,
								LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
				renderRigged(avatarp, RIGGED_MATERIAL_ALPHA);
				renderRigged(avatarp, RIGGED_SPECMAP_BLEND);
				renderRigged(avatarp, RIGGED_NORMMAP_BLEND);
				renderRigged(avatarp, RIGGED_NORMSPEC_BLEND);
				gGL.setSceneBlendType(LLRender::BT_ALPHA);
				gGL.setColorMask(true, false);
			}
			return;
		}

		if (pass == 8)
		{
			renderRiggedFullbrightAlpha(avatarp);
			return;
		}
		if (LLPipeline::sRenderDeferred && is_post_deferred_render)
		{
			S32 p = 0;
			switch (pass)
			{
			case 9: p = 1; break;
			case 10: p = 5; break;
			case 11: p = 9; break;
			case 12: p = 13; break;
			}
			{
				LLGLEnable blend(GL_BLEND);
				renderDeferredRiggedMaterial(avatarp, p);
			}
			return;
		}
		else if (pass == 9)
		{
			renderRiggedGlow(avatarp);
			return;
		}
	}

	if (pass == 13)
	{
		renderRiggedGlow(avatarp);

		return;
	}
	
	if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
	{
		LLMatrix4 rot_mat;
		LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
		LLMatrix4 cfr(OGL_TO_CFR_ROTATION.getF32ptr());
		rot_mat *= cfr;
		
		LLVector4 wind;
		wind.setVec(avatarp->mWindVec);
		wind.mV[VW] = 0;
		wind = wind * rot_mat;
		wind.mV[VW] = avatarp->mWindVec.mV[VW];

		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV);
		F32 phase = -1.f * (avatarp->mRipplePhase);

		F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
		LLVector4 sin_params(freq, freq, freq, phase);
		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV);

		LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
		gravity = gravity * rot_mat;
		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV);
	}

	if( !single_avatar || (avatarp == single_avatar) )
	{
		avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
	}
}
Ejemplo n.º 6
0
void RCharCloth::renderforce()
{
	prerender();
	render();
	postrender();
}
Ejemplo n.º 7
0
//////////////////////////////////////////////////////////////////////////
//	render
//////////////////////////////////////////////////////////////////////////
void RCharCloth::render()
{     
	//	bHarewareBuffer = true;
	int i;

	LPDIRECT3DDEVICE9 dev =	RGetDevice(); // Get Device Pointer

	UpdateNormal();

	RMtrlMgr* pMtrlMgr = &mpMeshNode->m_pParentMesh->m_mtrl_list_ex;
	RMtrl* pMtrl = pMtrlMgr->Get_s(mpMeshNode->m_mtrl_id,-1);
	int num_mtrl = pMtrl->m_sub_mtrl_num;

	int point_index;		// 현재 버텍스의 인덱스

	for( i = 0 ; i < mpMeshNode->m_face_num ; ++i )
	{
		for( int j = 0 ; j < 3; ++j )
		{
			point_index = mpMeshNode->m_face_list[i].m_point_index[j];
			gVertices[3*i+j].p	= m_pX[point_index];
			gVertices[3*i+j].tu	= mpMeshNode->m_face_list[i].m_point_tex[j].x;
			gVertices[3*i+j].tv	= mpMeshNode->m_face_list[i].m_point_tex[j].y;
			gVertices[3*i+j].n	= m_pNormal[point_index];
		}
	}	

	if( bHarewareBuffer && gpClothVertexBuffer)
	{
		//// Copy Begin
		void *Buffer;
		if( FAILED( gpClothVertexBuffer->Lock( 0, sizeof(RVertex) * mpMeshNode->m_face_num * 3, (VOID**)&Buffer, D3DLOCK_DISCARD )))
		{
			bHarewareBuffer = false;
			REL( gpClothVertexBuffer );

			mlog("Fail to lock of Vertex Buffer\n");
			goto e2SoftRender;
		}
		//memcpy( Buffer, gVertices, sizeof(RVertex) * m_nCntP );
		memcpy( Buffer, gVertices, sizeof(RVertex) * mpMeshNode->m_face_num * 3 );

		gpClothVertexBuffer->Unlock();
		// Copy End
	}
e2SoftRender:
	prerender();

	if(mpMesh->m_pVisualMesh)
		mpMesh->m_pVisualMesh->UpdateLight();

	rmatrix rtemp;
	dev->GetTransform( D3DTS_WORLD, &rtemp );
	dev->SetTransform( D3DTS_WORLD ,  &( mLocalMat * mWorldMat ) );

	mpMesh->SetCharacterMtrl_ON( pMtrl,mpMeshNode,1 ,mpMeshNode->GetTColor());

#ifdef USE_TOON_RENDER

	mpMeshNode->ToonRenderSettingOn(pMtrl);	

#endif

	if( bHarewareBuffer )
	{			
		dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, mpMeshNode->m_face_num );
	}
	else
	{
		dev->DrawPrimitiveUP( D3DPT_TRIANGLELIST, mpMeshNode->m_face_num, gVertices, sizeof(RVertex));
	}

#ifdef USE_TOON_RENDER

//	if(Silhouette)
	{
		mpMeshNode->ToonRenderSilhouetteSettingOn();

		if( bHarewareBuffer )
			dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, mpMeshNode->m_face_num );
		else
			dev->DrawPrimitiveUP( D3DPT_TRIANGLELIST, mpMeshNode->m_face_num, gVertices, sizeof(RVertex));

		mpMeshNode->ToonRenderSilhouetteSettingOff();
	}

	mpMeshNode->ToonRenderSettingOff();	

#endif

	mpMesh->SetCharacterMtrl_OFF( pMtrl, 1 );
	dev->SetTransform( D3DTS_WORLD, &rtemp );

	postrender();

}
Ejemplo n.º 8
0
  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();
          }
        }
      }
    }
  }