Пример #1
0
void GradientRenderer::GradientRendererJob::execute ()
{
	size_t n;
	for (int x=0;x<width;++x)
	{
		Real value = *data++;
		ColourValue color = renderer->mGradients.front().color;
		for (n=0;n<renderer->mGradients.size();++n)
		{
			if (renderer->mGradients[n].value > value)
				break;
		}
		if (n < renderer->mGradients.size())
		{
			if (n > 0)
			{
				const Gradient &left = renderer->mGradients[n-1];
				const Gradient &right = renderer->mGradients[n];
				const float a = (float)((value - left.value) / (right.value - left.value));
				color = left.color * (1.0f-a) + right.color * a;
			}
		}
		else
			color = renderer->mGradients.back().color;
		color.writeRGB (buffer);
	}
}
Пример #2
0
	//! fills the surface with given color
	void CImage::fill(const ColourValue &color)
	{
		UINT32 c;

		switch (Format)
		{
		case ECF_A1R5G5B5:
			c = A8R8G8B8toA1R5G5B5(color.getAsARGB());
			c |= c << 16;
			break;
		case ECF_R5G6B5:
			c = A8R8G8B8toR5G6B5(color.getAsARGB());
			c |= c << 16;
			break;
		case ECF_A8R8G8B8:
			c = color.getAsARGB();
			break;
		case ECF_R8G8B8:
		{
			UINT8 rgb[3];
			CColorConverter::convert_A8R8G8B8toR8G8B8(&color, 1, rgb);
			const UINT32 size = getImageDataSizeInBytes();
			for (UINT32 i = 0; i<size; i += 3)
			{
				memcpy(Data + i, rgb, 3);
			}
			return;
		}
		break;
		default:
			// TODO: Handle other formats
			return;
		}
		memset32(Data, c, getImageDataSizeInBytes());
	}
Пример #3
0
Vector3 SColor::GetRGB() const
{
	ColourValue cl;
	cl.setHSB(h, s, 1.f);
	return Vector3(
		cl.r * v -n,
		cl.g * v -n,
		cl.b * v -n);
}
Пример #4
0
//  get clr
Vector3 SColor::GetRGB1() const
{
	ColourValue cl;
	cl.setHSB(h, s, 1.f);
	float vv = std::min(1.f, v);  // * (1.f - n)
	return Vector3(
		cl.r * vv,
		cl.g * vv,
		cl.b * vv);
}
Пример #5
0
	//! get a filtered pixel
	inline ColourValue CImage::getPixelBox(SINT32 x, SINT32 y, SINT32 fx, SINT32 fy, SINT32 bias) const
	{
		ColourValue c;
		SINT32 a = 0, r = 0, g = 0, b = 0;

		for (SINT32 dx = 0; dx != fx; ++dx)
		{
			for (SINT32 dy = 0; dy != fy; ++dy)
			{
				c = getPixel(SINT32_min(x + dx, Size.Width - 1),
					SINT32_min(y + dy, Size.Height - 1)
					);

				a += c.getAlpha();
				r += c.getRed();
				g += c.getGreen();
				b += c.getBlue();
			}

		}

		SINT32 sdiv = s32_log2_f32(fx * fy);

		a = SINT32_clamp((a >> sdiv) + bias, 0, 255);
		r = SINT32_clamp((r >> sdiv) + bias, 0, 255);
		g = SINT32_clamp((g >> sdiv) + bias, 0, 255);
		b = SINT32_clamp((b >> sdiv) + bias, 0, 255);

		c.setAlpha(a);
		c.setRed(r);
		c.setBlue(b);
		c.setGreen(g);
		//c.set(a, r, g, b);
		return c;
	}
Пример #6
0
	void Line::_render( Menge::RenderServiceInterface * _renderService, const RenderObjectState * _state )
	{
		const mt::mat4f & wm = this->getWorldMatrix();

		mt::vec3f fromWM;
		mt::mul_v3_v3_m4( fromWM, m_from, wm );

		mt::vec3f toWM;
		mt::mul_v3_v3_m4( toWM, m_to, wm );

		mt::vec3f dir;
		mt::sub_v3_v3( dir, toWM, fromWM );

		mt::vec3f dir_norm;
		mt::norm_v3_v3( dir_norm, dir );

		mt::vec2f perp;
		mt::perp_v2( perp, mt::vec2f(dir_norm.x, dir_norm.y) );
				
		m_vertices[0].position.x = fromWM.x + perp.x * m_width;
		m_vertices[0].position.y = fromWM.y + perp.y * m_width;
		m_vertices[0].position.z = fromWM.z;

		m_vertices[1].position.x = toWM.x + perp.x * m_width;
		m_vertices[1].position.y = toWM.y + perp.y * m_width;
		m_vertices[1].position.z = toWM.z;

		m_vertices[2].position.x = toWM.x - perp.x * m_width;
		m_vertices[2].position.y = toWM.y - perp.y * m_width;
		m_vertices[2].position.z = toWM.z;

		m_vertices[3].position.x = fromWM.x - perp.x * m_width;
		m_vertices[3].position.y = fromWM.y - perp.y * m_width;
		m_vertices[3].position.z = fromWM.z;
		
		ColourValue color;
		this->calcTotalColor(color);

		uint32_t argb = color.getAsARGB();

		for( uint32_t i = 0; i != 4; ++i )
		{
			m_vertices[i].color = argb;
			m_vertices[i].uv[0].x = 0.f;
			m_vertices[i].uv[0].y = 0.f;
			m_vertices[i].uv[1].x = 0.f;
			m_vertices[i].uv[1].y = 0.f;
		}

		RenderMaterialInterfacePtr material = RENDERMATERIAL_SERVICE(m_serviceProvider)
			->getMaterial( STRINGIZE_STRING_LOCAL( m_serviceProvider, "Debug" ), PT_TRIANGLELIST, 0, nullptr );

		_renderService
			->addRenderQuad( _state, material, m_vertices, 4, nullptr, false );
	}
Пример #7
0
	//! returns a pixel
	ColourValue CImage::getPixel(UINT32 x, UINT32 y) const
	{
		ColourValue c;
		if (x >= Size.Width || y >= Size.Height)
			return c;
		
		switch (Format)
		{
		case ECF_A1R5G5B5:
			c.setAsARGB(A1R5G5B5toA8R8G8B8(((UINT16*)Data)[y*Size.Width + x]));
			return c; //A1R5G5B5toA8R8G8B8(((UINT16*)Data)[y*Size.Width + x]);
		case ECF_R5G6B5:
			c.setAsARGB(R5G6B5toA8R8G8B8(((UINT16*)Data)[y*Size.Width + x]));
			return c;//R5G6B5toA8R8G8B8(((UINT16*)Data)[y*Size.Width + x]);
		case ECF_A8R8G8B8:
			c.setAsARGB(((UINT32*)Data)[y*Size.Width + x]);
			return c;// ((UINT32*)Data)[y*Size.Width + x];
		case ECF_R8G8B8:
		{
			UINT8* p = Data + (y * 3)*Size.Width + (x * 3);
			c.setAlpha(255);
			c.setRed(p[0]);
			c.setBlue(p[1]);
			c.setGreen(p[2]);
			return c;
		}
#ifndef _DEBUG
		default:
			break;
#endif
		}

		return ColourValue(0);
	}
void GameObjectFlashLight::setColour(int colour)
{
		ColourValue ogreColour;
		ogreColour.setAsRGBA(colour);
		mRenderComponentLight->setDiffuseColor(ogreColour);
		mRenderComponentLight->setSpecularColor(ogreColour);
		//TODO: radius, etc, should also be modified here
		if (mFlashlightDecalComponent.get())
		{
			mFlashlightDecalComponent->changeColour(colour);
			if (mFlashlightDecalComponent->isVisible())
			{	
				mFlashlightDecalComponent->hide();
				mFlashlightDecalComponent->show();
			}
		}
		if (mConeEntity)
		{
			applyTintColour(colour);
		}
}
int GameObjectFlashLight::calculateCurrentColour(double elapsedSeconds)
{
	int nextColour;

	ColourValue ogreTargetColour;
	ColourValue ogreCurrentColour;
	ColourValue ogreNextColour;
	double incr;

	ogreTargetColour.setAsRGBA(mTargetColour);
	ogreCurrentColour.setAsRGBA(mCurrentColour);
	incr=mGameWorldManager->CHANGE_FLASHLIGHT_COLOUR_SPEED*elapsedSeconds;

	ogreNextColour.r=ogreCurrentColour.r+(ogreTargetColour.r-ogreCurrentColour.r)*incr;
	ogreNextColour.g=ogreCurrentColour.g+(ogreTargetColour.g-ogreCurrentColour.g)*incr;
	ogreNextColour.b=ogreCurrentColour.b+(ogreTargetColour.b-ogreCurrentColour.b)*incr;
	ogreNextColour.a=1;

	if(Ogre::Math::Abs(ogreTargetColour.r-ogreCurrentColour.r)<incr &&
		Ogre::Math::Abs(ogreTargetColour.g-ogreCurrentColour.g)<incr &&
		Ogre::Math::Abs(ogreTargetColour.b-ogreCurrentColour.b)<incr)
	{
		nextColour=mTargetColour;
	}
	else
	{
		nextColour=ogreNextColour.getAsRGBA();
	}

	return nextColour;
}	
	//! constructor
	CLightSceneNode::CLightSceneNode(ISceneNode* parent, ISceneManager* mgr, SINT32 id,
		const Vector3& position, ColourValue color, FLOAT32 radius)
		: ILightSceneNode(parent, mgr, id, position), DriverLightIndex(-1), LightIsOn(true)
	{
#ifdef _DEBUG
		setDebugName("CLightSceneNode");
#endif

		LightData.DiffuseColor = color;
		// set some useful specular color
		LightData.SpecularColor = color.getInterpolated(ColourValue::getColourValue(255, 255, 255, 255), 0.7f);

		setRadius(radius);
	}
Пример #11
0
	//! sets a pixel
	void CImage::setPixel(UINT32 x, UINT32 y, const ColourValue &color, bool blend)
	{
		ColourValue c = color;
		if (x >= Size.Width || y >= Size.Height)
			return;

		switch (Format)
		{
		case ECF_A1R5G5B5:
		{
			UINT16 * dest = (UINT16*)(Data + (y * Pitch) + (x << 1));
			*dest = A8R8G8B8toA1R5G5B5(color.getAsARGB());
		} break;

		case ECF_R5G6B5:
		{
			UINT16 * dest = (UINT16*)(Data + (y * Pitch) + (x << 1));
			*dest = A8R8G8B8toR5G6B5(color.getAsARGB());
		} break;

		case ECF_R8G8B8:
		{
			UINT8* dest = Data + (y * Pitch) + (x * 3);
			
			dest[0] = (UINT8)c.getRed();
			dest[1] = (UINT8)c.getGreen();
			dest[2] = (UINT8)c.getBlue();
		} break;

		case ECF_A8R8G8B8:
		{
			UINT32 * dest = (UINT32*)(Data + (y * Pitch) + (x << 2));
			*dest = blend ? PixelBlend32(*dest, color.getAsARGB()) : color.getAsARGB();
		} break;
#ifndef _DEBUG
		default:
			break;
#endif
		}
	}
Пример #12
0
///---------------------------------------------------------------------------------------------------------------
//  Update HUD
///---------------------------------------------------------------------------------------------------------------
void CHud::Update(int carId, float time)
{
	PROFILER.beginBlock("g.hud");

	
	//  update HUD elements for all cars that have a viewport (local or replay)
	//-----------------------------------------------------------------------------------
	int cnt = std::min(6/**/, (int)app->carModels.size());  // all cars
	int cntC = std::min(4/**/, cnt - (app->isGhost2nd && !app->bRplPlay ? 1 : 0));  // all vis plr
	int c;
	
	//  gui viewport - done once for all
	if (carId == -1)
	for (c = 0; c < cntC; ++c)
	if (app->carModels[c]->eType == CarModel::CT_LOCAL)
	{
		//  hud rpm,vel
		float vel=0.f, rpm=0.f, clutch=1.f;  int gear=1;
		GetVals(c,&vel,&rpm,&clutch,&gear);
		
		//  update all mini pos tri
		for (int i=0; i < cnt; ++i)
			UpdRot(c, i, vel, rpm);
	}

	///  all minimap car pos-es rot
	const static Real tc[4][2] = {{0,1}, {1,1}, {0,0}, {1,0}};
	const float z = pSet->size_minipos;  // tri size
	
	if (carId == -1 && moPos)
	{	moPos->beginUpdate(0);

		const int plr = app->mSplitMgr->mNumViewports;
		for (int v = 0; v < plr; ++v)  // all viewports
		{
			const Hud& h = hud[v];
			const float sc = pSet->size_minimap * app->mSplitMgr->mDims[v].avgsize;
			const Vector3& pos = h.ndMap->getPosition();
			
			for (c = 0; c < cntC; ++c)  // all mini pos for one car
			{
				const SMiniPos& sp = h.vMiniPos[c];
				const ColourValue& clr = app->carModels[c]->color;

				for (int p=0; p < 4; ++p)  // all 4 points
				{
					float x = pos.x + (sp.x + sp.px[p]*z)*sc;
					float y = pos.y + (sp.y + sp.py[p]*z)*sc*asp;
					moPos->position(x, y, 0);
					moPos->textureCoord(tc[p][0], tc[p][1]);
					moPos->colour(clr);
		}	}	}
		
		int ii = plr * cntC;
		for (int i=0; i < ii; ++i)
		{	int n = i*4;
			moPos->quad(n,n+1,n+3,n+2);
		}
		moPos->end();
	}

	//  track% local, updated always
	for (c = 0; c < cntC; ++c)
	{	CarModel* cm = app->carModels[c];
		if (cm->eType == CarModel::CT_LOCAL ||
			cm->eType == CarModel::CT_REPLAY)
			cm->UpdTrackPercent();
	}
	
	if (carId == -1 || app->carModels.empty())
	{
		PROFILER.endBlock("g.hud");
		return;
	}

	#ifdef DEBUG
	assert(carId >= 0);
	assert(carId < app->carModels.size());
	#endif


	CarModel* pCarM = app->carModels[carId];
	CAR* pCar = pCarM ? pCarM->pCar : 0;

	float vel=0.f, rpm=0.f, clutch=1.f;  int gear=1;
	GetVals(carId,&vel,&rpm,&clutch,&gear);
	Hud& h = hud[carId];


	///  multiplayer
	// -----------------------------------------------------------------------------------
	static float tm = 0.f;  tm += time;
	if (tm > 0.2f /**/&& app->mClient/**/)  // not every frame, each 0.2s
	// if (pSet->game.isNetw) ..
	{
		//  sort winners
		std::list<CarModel*> cms;
		for (c=0; c < cnt; ++c)
			cms.push_back(app->carModels[c]);

		cms.sort(SortWin);
		//stable_sort(cms.begin(), cms.end(), SortWin);
		
		String msg = "";  int place = 1;  // assing places
		for (std::list<CarModel*>::iterator it = cms.begin(); it != cms.end(); ++it)
		{
			CarModel* cm = *it;
			bool end = app->pGame->timer.GetCurrentLap(cm->iIndex) >= pSet->game.num_laps;
			cm->iWonPlace = end ? place++ : 0;  // when ended race

			//  detect change (won),  can happen more than once, if time diff < ping delay
			if (cm->iWonPlace != cm->iWonPlaceOld)
			{	cm->iWonPlaceOld = cm->iWonPlace;
				cm->iWonMsgTime = gPar.timeWonMsg;
				if (cm->iIndex == 0)  // for local player, show end wnd
					app->mWndNetEnd->setVisible(true);
			}
			if (cm->iWonMsgTime > 0.f)
			{	cm->iWonMsgTime -= tm;
				if (cm->iWonPlace != 0)
					msg += cm->sDispName + " " + TR("#{FinishedCommaPlace}") + ": " + toStr(cm->iWonPlace) + "\n";
			}
		}
		if (app->mClient && /*ap->pGame->timer.pretime <= 0.f &&*/ app->pGame->timer.waiting)
			msg += TR("#{NetWaitingForOthers}")+"...\n";
			
		//  chat 2 last lines
		if (gui->sChatLast1 != "")	msg += gui->sChatLast1 + "\n";
		if (gui->sChatLast2 != "")	msg += gui->sChatLast2;
			
		++gui->iChatMove;
		if (gui->iChatMove >= 10)  //par 2sec
		{	gui->iChatMove = 0;
			gui->sChatLast1 = gui->sChatLast2;
			gui->sChatLast2 = "";
		}
		
		//  upd hud msgs
		if (txMsg)
		{	txMsg->setCaption(msg);
			bckMsg->setVisible(!msg.empty());
		}

		//  upd end list
		if (app->mWndNetEnd->getVisible())
		{
			MyGUI::MultiList2* li = gui->liNetEnd;
			li->removeAllItems();
			for (std::list<CarModel*>::iterator it = cms.begin(); it != cms.end(); ++it)
			{
				CarModel* cm = *it;
				String clr = StrClr(cm->color);

				li->addItem(""/*clr+ toStr(c+1)*/, 0);  int l = li->getItemCount()-1;
				li->setSubItemNameAt(1,l, clr+ (cm->iWonPlace == 0 ? "--" : toStr(cm->iWonPlace)));
				li->setSubItemNameAt(2,l, clr+ cm->sDispName);
				li->setSubItemNameAt(3,l, clr+ StrTime( cm->iWonPlace == 0 ? 0.f : app->pGame->timer.GetPlayerTimeTot(cm->iIndex) ));
				//li->setSubItemNameAt(4,l, clr+ fToStr(cm->iWonMsgTime,1,3));
				li->setSubItemNameAt(4,l, clr+ StrTime( app->pGame->timer.GetBestLapRace(cm->iIndex) ));
				li->setSubItemNameAt(5,l, clr+ toStr( app->pGame->timer.GetCurrentLap(cm->iIndex) ));
		}	}
		tm = 0.f;
	}


	///  opponents list
	// -----------------------------------------------------------------------------------
	bool visOpp = h.txOpp[0] && pSet->show_opponents;
	if (visOpp && pCarM && pCarM->pMainNode)
	{
		std::list<CarModel*> cms;  // sorted list
		for (c=0; c < cnt; ++c)
		{	//  cars only
			CarModel* cm = app->carModels[c];
			if (!cm->isGhost())
			{	if (app->bRplPlay)
					cm->trackPercent = app->carPoses[app->iCurPoses[c]][c].percent;
				cms.push_back(cm);
		}	}
		if (pSet->opplist_sort)
			cms.sort(SortPerc);
		
		for (c=0; c < cnt; ++c)
		{	//  add last, if visible, ghost1 (dont add 2nd) and track's ghost
			CarModel* cm = app->carModels[c];
			if (cm->eType == (app->isGhost2nd ? CarModel::CT_GHOST2 : CarModel::CT_GHOST) && pSet->rpl_ghost ||
				cm->isGhostTrk() && pSet->rpl_trackghost)
			{
				cm->trackPercent = app->carPoses[app->iCurPoses[c]][c].percent;  // ghost,rpl
				cms.push_back(cm);
		}	}

		bool bGhostEnd = app->pGame->timer.GetPlayerTime(0) > app->ghplay.GetTimeLength();
		String s0,s1,s2;  // Track% Dist Nick
		ColourValue clr;  c = 0;
		for (std::list<CarModel*>::iterator it = cms.begin(); it != cms.end(); ++it)
		{
			CarModel* cm = *it;
			if (cm->pMainNode)
			{
				bool bGhost = cm->isGhost() && !cm->isGhostTrk();
				bool bGhostVis = (app->ghplay.GetNumFrames() > 0) && pSet->rpl_ghost;
				bool bGhEmpty = bGhost && !bGhostVis;

				//  dist  -----------
				if (cm == pCarM || bGhEmpty)  // no dist to self or to empty ghost
					s1 += "\n";
				else
				{	Vector3 v = cm->pMainNode->getPosition() - pCarM->pMainNode->getPosition();
					float dist = v.length();  // meters
					Real h = std::min(60.f, dist) / 60.f;
					clr.setHSB(0.5f - h * 0.4f, 1, 1);
					s1 += StrClr(clr)+ fToStr(dist,0,3)+"m\n";
				}
					
				//  percent %  -----------
				if (bGhEmpty || cm->isGhostTrk())
					s0 += "\n";
				else
				{	float perc = bGhost && bGhostEnd ? 100.f : cm->trackPercent;
					clr.setHSB(perc*0.01f * 0.4f, 0.7f, 1);
					s0 += StrClr(clr)+ fToStr(perc,0,3)+"%\n";
				}
				
				//  nick name  -----------
				if (cm->eType != CarModel::CT_REPLAY)
				{
					s2 += StrClr(cm->color)+ cm->sDispName;
					bool end = app->pGame->timer.GetCurrentLap(cm->iIndex) >= pSet->game.num_laps
							&& (app->mClient || pSet->game.local_players > 1);  // multiplay or split
					if (end)  //  place (1)
						s2 += "  (" + toStr(cm->iWonPlace) + ")";
				}
				s2 += "\n";  ++c;
		}	}
		//  upd pos, size
		if (h.lastOppH != c)
		{	h.lastOppH = c;
			int y = c*25 +4, yo = h.yOpp - y-4;

			for (int n=0; n < 3; ++n)
			{	h.txOpp[n]->setPosition(h.xOpp + n*65+5, yo + 3);
				h.txOpp[n]->setSize(90,y);
			}
			h.bckOpp->setPosition(h.xOpp, yo);
			h.bckOpp->setSize(230,y);
		}
		h.txOpp[0]->setCaption(s0);  h.txOpp[1]->setCaption(s1);  h.txOpp[2]->setCaption(s2);
	}

	//  Set motion blur intensity for this viewport, depending on car's linear velocity
	//-----------------------------------------------------------------------------------
	if (pSet->blur)
	{
		// use velocity squared to achieve an exponential motion blur
		float speed = pCar->GetVelocity().MagnitudeSquared();
		
		// peak at 250 kmh (=69 m/s), 69² = 4761
		// motion blur slider: 1.0 = peak at 100 km/h   0.0 = peak at 400 km/h   -> 0.5 = peak at 250 km/h
		// lerp(100, 400, 1-motionBlurIntensity)
		float peakSpeed = 100 + (1-pSet->blur_int) * (400-100);
		float intens = fabs(speed) / pow((peakSpeed/3.6f), 2);
		
		// higher fps = less perceived motion blur time a frame will be still visible on screen:
		// each frame, 1-intens of the original image is lost
		// example (intens = 0.7):
		//	   frame 1: full img		   frame 2: 0.7  * image
		//	   frame 3: 0.7² * image	   frame 4: 0.7³ * image
		// portion of image visible after 'n' frames: pow(intens, n);
		//	   example 1: 60 fps	   0.7³ image after 4 frames: 0.066 sec
		//	   example 2: 120 fps	   0.7³ image after 4 frames: 0.033 sec
		// now: need to achieve *same* time for both fps values
		// to do this, adjust intens
		// (1.0/fps) * pow(intens, n) == (1.0/fps2) * pow(intens2, n)
		// set n=4  intens_new = sqrt(sqrt((intens^4 * fpsReal/desiredFps))
		intens = sqrt(sqrt( pow(intens, 4) * ((1.0f/time) / 120.0f) ));
			
		intens = std::min(intens, 0.9f);  // clamp to 0.9f
		app->motionBlurIntensity = intens;
	}


	///  gear, vel texts  -----------------------------
	if (h.txVel && h.txGear && pCar)
	{
		float cl = clutch*0.8f + 0.2f;
		if (gear == -1)
		{	h.txGear->setCaption("R");  h.txGear->setTextColour(Colour(0.3,1,1,cl));  }
		else if (gear == 0)
		{	h.txGear->setCaption("N");  h.txGear->setTextColour(Colour(0.3,1,0.3,cl));  }
		else if (gear > 0 && gear < 8)
		{	h.txGear->setCaption(toStr(gear));  h.txGear->setTextColour(Colour(1,1-gear*0.1,0.2,cl));  }

		h.txVel->setCaption(fToStr(fabs(vel),0,3));

		float k = pCar->GetSpeedometer() * 3.6f * 0.0025f;	// vel clr
		#define m01(x)  std::min(1.0f, std::max(0.0f, (float) (x) ))
		h.txVel->setTextColour(Colour(m01(k*2), m01(0.5+k*1.5-k*k*2.5), m01(1+k*0.8-k*k*3.5)));
	}

	//  boost fuel (time)  ------
	if (h.txBFuel && pCar && h.txBFuel->getVisible())
	{
		h.txBFuel->setCaption(fToStr(pCar->dynamics.boostFuel,1,3));
	}

	//  damage %  ------
	if (h.txDamage && pCar && h.txDamage->getVisible())
	{
		float d = std::min(100.f, pCar->dynamics.fDamage);
		//h.txDamage->setCaption(TR("#{Damage}\n     ")+fToStr(d,0,3)+" %");  d*=0.01f;
		h.txDamage->setCaption(fToStr(d,0,3)+" %");  d*=0.01f;
		float e = std::min(1.f, 0.8f + d*2.f);
		h.txDamage->setTextColour(Colour(e-d*d*0.4f, std::max(0.f, e-d), std::max(0.f, e-d*2.f) ));
	}
	
	//  abs, tcs on  ------
	if (h.txAbs && h.txTcs && pCar)
	{
		bool vis = pCar->GetABSEnabled();  h.txAbs->setVisible(vis);
		if (vis)  h.txAbs->setAlpha(pCar->GetABSActive() ? 1.f : 0.6f);
		
		vis = pCar->GetTCSEnabled();  h.txTcs->setVisible(vis);
		if (vis)  h.txTcs->setAlpha(pCar->GetTCSActive() ? 1.f : 0.6f);
	}
	
	
	///  times, race pos  -----------------------------
	if (pSet->show_times && pCar)
	{
		TIMER& tim = app->pGame->timer;
		bool hasLaps = pSet->game.local_players > 1 || pSet->game.champ_num >= 0 || pSet->game.chall_num >= 0 || app->mClient;
		if (hasLaps)
		{	//  place
			if (pCarM->iWonPlace > 0 && h.txPlace)
			{
				String s = TR("---  "+toStr(pCarM->iWonPlace)+" #{TBPlace}  ---");
				h.txPlace->setCaption(s);
				const static Colour clrPlace[4] = {
					Colour(0.4,1,0.2), Colour(1,1,0.3), Colour(1,0.7,0.2), Colour(1,0.5,0.2) };
				h.txPlace->setTextColour(clrPlace[pCarM->iWonPlace-1]);
				h.bckPlace->setVisible(true);
		}	}

		//  times  ------------------------------
		bool cur = pCarM->iCurChk >= 0 && !app->vTimeAtChks.empty();
		float ghTimeES = cur ? app->vTimeAtChks[pCarM->iCurChk] : 0.f;
		float part = ghTimeES / app->fLastTime;  // fraction which track ghost has driven

		bool coldStart = tim.GetCurrentLap(carId) == 1;  // was 0
		float carMul = app->GetCarTimeMul(pSet->game.car[carId], pSet->game.sim_mode);
		//| cur
		float ghTimeC = ghTimeES + (coldStart ? 0 : 1);
		float ghTime = ghTimeC * carMul;  // scaled
		float diffT = pCarM->timeAtCurChk - ghTime;  // cur car diff at chk
		float diff = 0.f;  // on hud
		
		//!- if (pCarM->updTimes || pCarM->updLap)
		{	pCarM->updTimes = false;

			//  track time, points
			float last = tim.GetLastLap(carId), best = tim.GetBestLap(carId, pSet->game.trackreverse);
			float timeCur = last < 0.1f ? best : last;
			float timeTrk = app->data->tracks->times[pSet->game.track];
			bool b = timeTrk > 0.f && timeCur > 0.f;

			//bool coldStart = tim.GetCurrentLap(carId) == 1;  // was 0
			float time = (/*place*/1 * app->data->cars->magic * timeTrk + timeTrk) / carMul;  // trk time (for 1st place)
			//float t1pl = data->carsXml.magic * timeTrk;

			float points = 0.f, curPoints = 0.f;
			int place = app->GetRacePos(timeCur, timeTrk, carMul, coldStart, &points);
			//| cur
			float timCC = timeTrk + (coldStart ? 0 : 1);
			float timCu = timCC * carMul;
			diff = pCarM->timeAtCurChk + /*(coldStart ? 1:0)*carMul*/ - time * part;  ///new

			float chkPoints = 0.f;  // cur, at chk, assume diff time later than track ghost
			int chkPlace = app->GetRacePos(timCu + diffT, timeTrk, carMul, coldStart, &chkPoints);
			bool any = cur || b;
	
			h.sTimes =
				"\n#80E080" + StrTime(time)+
				"\n#D0D040" + (cur ? toStr( chkPlace )     : "--")+
				"\n#F0A040" + (cur ? fToStr(chkPoints,1,3) : "--");
			float dlap = last - time;
			h.sLap =
				"#D0E8FF"+TR("#{TBLapResults}") +
				"\n#80C8FF" + StrTime(last)+
				(last > 0.f ? String("  ") + (dlap > 0.f ? "#80E0FF+" : "#60FF60-") + fToStr(fabs(dlap), 1,3) : "")+
				"\n#80E0E0" + StrTime(best)+
				"\n#80E080" + StrTime(time)+
				"\n#D0D040" + (b ? toStr(place)      : "--")+
				"\n#F0A040" + (b ? fToStr(points,1,3) : "--");
			if (h.txLap)
				h.txLap->setCaption(h.sLap);
		}
		if (h.txTimes)
			h.txTimes->setCaption(
				(hasLaps ? "#A0E0D0"+toStr(tim.GetCurrentLap(carId)+1)+" / "+toStr(pSet->game.num_laps) : "") +
				"\n#A0E0E0" + StrTime(tim.GetPlayerTime(carId))+
				(cur ? String("  ") + (diff > 0.f ? "#80E0FF+" : "#60FF60-")+
					fToStr(fabs(diff), 1,3) : "")+
				h.sTimes+
				"\n#E0B090" + fToStr(pCarM->trackPercent,0,1)+"%" );

		if (h.txLap)
		{
			//if (pCarM->updLap)
			//{	pCarM->updLap = false;
				//h.txLap->setCaption(h.sLap);
			//}
			float a = std::min(1.f, pCarM->fLapAlpha * 2.f);
			bool hasRoad = app->scn->road && app->scn->road->getNumPoints() > 2;
			bool vis = pSet->show_times && hasRoad && a > 0.f;
			if (vis)
			{	if (app->iLoad1stFrames == -2)  //bLoading)  //  fade out
				{	pCarM->fLapAlpha -= !hasRoad ? 1.f : time * gPar.fadeLapResults;
					if (pCarM->fLapAlpha < 0.f)  pCarM->fLapAlpha = 0.f;
				}
				h.bckLap->setAlpha(a);
				h.txLapTxt->setAlpha(a);  h.txLap->setAlpha(a);
			}
			h.bckLap->setVisible(vis);
			h.txLapTxt->setVisible(vis);  h.txLap->setVisible(vis);
		}
	}


	//  checkpoint warning  --------
	if (app->scn->road && h.bckWarn && pCarM)
	{
		/* checks debug *
		if (ov[0].oU)  {
			//"ghost:  "  + GetTimeString(ghost.GetTimeLength()) + "  "  + toStr(ghost.GetNumFrames()) + "\n" +
			//"ghplay: " + GetTimeString(ghplay.GetTimeLength()) + "  " + toStr(ghplay.GetNumFrames()) + "\n" +
			ov[0].oU->setCaption(String("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n") +
				"         st " + toStr(pCarM->bInSt ? 1:0) + " in" + toStr(pCarM->iInChk) +
				"  |  cur" + toStr(pCarM->iCurChk) + " > next " + toStr(pCarM->iNextChk) +
				"  |  Num " + toStr(pCarM->iNumChks) + " / All " + toStr(road->mChks.size()));
		}	/**/

		if (pCarM->bWrongChk)
			pCarM->fChkTime = gPar.timeShowChkWarn;
			
		bool show = pCarM->fChkTime > 0.f;
		if (show)  pCarM->fChkTime -= time;
		h.bckWarn->setVisible(show && pSet->show_times);
	}

	//  race countdown  ------
	if (h.txCountdown)
	{
		bool vis = app->pGame->timer.pretime > 0.f && !app->pGame->timer.waiting;
		if (vis)
			h.txCountdown->setCaption(fToStr(app->pGame->timer.pretime,1,3));
		h.txCountdown->setVisible(vis);
	}

	//  camera cur  ------
	if (h.txCam)
	{	FollowCamera* cam = pCarM->fCam;
		if (cam && cam->updName)
		{	cam->updName = false;
			h.txCam->setCaption(cam->sName);
	}	}


	//-------------------------------------------------------------------------------------------------------------------
	///  debug infos
	//-------------------------------------------------------------------------------------------------------------------
	
	static int oldTxtClr = -2;  // clr upd
	if (oldTxtClr != pSet->car_dbgtxtclr)
	{	oldTxtClr = pSet->car_dbgtxtclr;
		UpdDbgTxtClr();
	}

	//  car debug text  --------
	static bool oldCarTxt = false;
	if (pCar && ov[0].oU)
	{
		if (pSet->car_dbgtxt)
		{	std::stringstream s1,s2,s3,s4;
			pCar->DebugPrint(s1, true, false, false, false);  ov[0].oU->setCaption(s1.str());
			pCar->DebugPrint(s2, false, true, false, false);  ov[1].oU->setCaption(s2.str());
			pCar->DebugPrint(s3, false, false, true, false);  ov[2].oU->setCaption(s3.str());
			pCar->DebugPrint(s4, false, false, false, true);  ov[3].oU->setCaption(s4.str());
		}else
		if (pSet->car_dbgtxt != oldCarTxt)
		{	ov[0].oU->setCaption(""); /*ovU[1]->setCaption(""); ovU[2]->setCaption(""); ovU[3]->setCaption("");*/	}
	}
	oldCarTxt = pSet->car_dbgtxt;
	

	//  profiling times --------
	if (pSet->profilerTxt && ov[1].oU)
	{
		PROFILER.endCycle();
		static int frame=0;  ++frame;

		if (frame > 10)  //par
		{	frame = 0;
			std::string sProf = PROFILER.getAvgSummary(quickprof::MILLISECONDS);
			//sProf = "PROF "+fToStr(1000.f/PROFILER.getAvgDuration(" frameSt",quickprof::MILLISECONDS), 2,4);
			ov[1].oU->setCaption(sProf);
		}
		//if (newPosInfos.size() > 0)
		//ov[3].oU->setCaption("carm: " + toStr(ap->carModels.size()) + " newp: " + toStr((*newPosInfos.begin()).pos));
	}


	//  bullet profiling text  --------
	static bool oldBltTxt = false;
	if (ov[1].oU)
	{
		if (pSet->bltProfilerTxt)
		{
			static int cc = 0;  ++cc;
			if (cc > 40)
			{	cc = 0;
				std::stringstream os;
				bltDumpAll(os);
				ov[1].oU->setCaption(os.str());
			}
		}
		else
		if (pSet->bltProfilerTxt != oldBltTxt)
			ov[1].oU->setCaption("");
	}
	oldBltTxt = pSet->bltProfilerTxt;

	
	//  wheels slide, susp bars  --------
	if (pSet->car_dbgbars && pCar)
	{
		const Real xp = 80, yp = -530, ln = 20, y4 = 104;
		//const static char swh[4][6] = {"F^L<","F^R>","RvL<","RvR>"};
		for (int w=0; w < 4; ++w)
		if (ov[3-w].oL && ov[3-w].oR && ov[3-w].oS)
		{	
			float slide = /*-1.f*/0.f, sLong = 0.f, sLat = 0.f;
			float squeal = pCar->GetTireSquealAmount((WHEEL_POSITION)w, &slide, &sLong, &sLat);

			//MATHVECTOR<float,3> vwhVel = pCar->dynamics.GetWheelVelocity((WHEEL_POSITION)w);
			//float whVel = vwhVel.Magnitude() * 3.6f;

			/**  //  info
			static char ss[256];
			sprintf(ss, "%s %6.3f %6.3f  %6.3f %6.3f\n", swh[w],
				sLong/4.f, sLat/3.f, slide, squeal);
			ColourValue clr;  clr.setHSB( slide/20.f, 0.8f, 1.f );  //clr.a = min(0.f, slide/2.f);
			ovL[3-w]->setCaption(String(ss));
			ovL[3-w]->setColour(clr);
			//ovL[3-w]->setPosition(0.f, 230 + w*22);
			/**/

			//  bar meters |
			float susp = pCar->dynamics.GetSuspension(WHEEL_POSITION(w)).GetDisplacementPercent();
			sLong = fabs(sLong);
			float slng = sLong / sLong * powf(sLong, 0.3f);  // slide*20.f

			ov[3-w].oR->setPosition(slng * 14.f +xp, yp + w*ln);
			ov[3-w].oL->setPosition(sLat * 14.f +xp, yp + w*ln +y4);
			ov[3-w].oS->setPosition(susp * 70.f +xp, yp + w*ln -y4);
		}
		if (ov[4].oL)  ov[4].oL->setPosition(xp, yp + -20 +y4+3);
		if (ov[4].oS)  ov[4].oS->setPosition(xp + 70, yp + -20 -104-3);

		//ov[3-w].oR->setCaption("|");  ov[3-w].oR->setColour(ColourValue(0.6,1.0,0.7));
	}


	//  input values
	/*if (pCar && ap->pGame && ap->pGame->profilingmode)
	{	const std::vector<float>& inp = pCar->dynamics.inputsCopy;
	if (ov[2].oU && inp.size() == CARINPUT::ALL)
	{	sprintf(s, 
		" Throttle %5.2f\n Brake %5.2f\n Steer %5.2f\n"
		" Handbrake %5.2f\n Boost %5.2f\n Flip %5.2f\n"
		,inp[CARINPUT::THROTTLE], inp[CARINPUT::BRAKE], -inp[CARINPUT::STEER_LEFT]+inp[CARINPUT::STEER_RIGHT]
		,inp[CARINPUT::HANDBRAKE],inp[CARINPUT::BOOST], inp[CARINPUT::FLIP] );
		ov[2].oU->setCaption(String(s));
	}	}/**/


	//  wheels ter mtr, surface info  ---------
	if (pSet->car_dbgsurf && pCar)
	{
		String ss = "";
		ss = pCarM->txtDbgSurf;

		//  surfaces  info
		/*ss += "\n";
		for (int i=0; i < ap->pGame->track.tracksurfaces.size(); ++i)
			ss += String(ap->pGame->track.tracksurfaces[i].name.c_str()) + "\n";/**/

		//ovCarDbg->show();
		if (ov[4].oX)  {  //ov[4].oL->setTop(400);
			ov[4].oX->setCaption(ss);  }
	}
	

	///  tire vis circles  + + + +
	if (pCar && moTireVis[0] && pSet->car_tirevis)
	{
		const Real z = 6000.f / pSet->tc_r, zy = pSet->tc_xr,
			m_z = 2.f * z;  // scale, max factor
		const int na = 32;  // circle quality
		const Real ad = 2.f*PI_d/na, u = 0.02f;  // u line thickness
		const ColourValue cb(0.8,0.8,0.8),cl(0.2,1,0.2),cr(0.9,0.4,0),cc(1,1,0);
		
		for (int i=0; i < 4; ++i)
		{
			const CARDYNAMICS& cd = pCar->dynamics;
			const CARWHEEL::SlideSlip& t = cd.wheel[i].slips;
			float d = cd.wheel_contact[i].GetDepth() - 2*cd.wheel[i].GetRadius();
			bool off = !(d > -0.1f && d <= -0.01f);  // not in air
			//bool on = cd.wheel_contact[i].GetColObj();
			
			ManualObject* m = moTireVis[i];
			m->beginUpdate(0);
			//  back +
			m->position(-1,0,0);  m->colour(cb);
			m->position( 1,0,0);  m->colour(cb);
			m->position(0,-1,0);  m->colour(cb);
			m->position(0, 1,0);  m->colour(cb);
			
			//  tire, before combine
			Real lx = off ? 0.f : t.preFy/z*zy,  ly = off ? 0.f : t.preFx/z;
			for (int y=-1; y<=1; ++y)
			for (int x=-1; x<=1; ++x)  {
				m->position(0  +x*u, 0  +y*u, 0);  m->colour(cr);
				m->position(lx +x*u, ly +y*u, 0);  m->colour(cr);  }

			//  tire line /
			lx = off ? 0.f : t.Fy/z*zy;  ly = off ? 0.f : t.Fx/z;
			for (int y=-2; y<=2; ++y)
			for (int x=-2; x<=2; ++x)  {
				m->position(0  +x*u, 0  +y*u, 0);  m->colour(cl);
				m->position(lx +x*u, ly +y*u, 0);  m->colour(cl);  }

			//  max circle o
			Real rx = off || t.Fym > m_z ? 0.f : t.Fym/z,
			     ry = off || t.Fxm > m_z ? 0.f : t.Fxm/z, a = 0.f;
			Vector3 p(0,0,0),po(0,0,0);
			
			for (int n=0; n <= na; ++n)
			{
				p.x = rx*cosf(a)*zy;  p.y =-ry*sinf(a);
				if (n > 0)  {
					m->position(po);  m->colour(cc);
					m->position(p);   m->colour(cc);  }
				a += ad;  po = p;
			}
			m->end();
		}
	}

	PROFILER.endBlock("g.hud");
}
Пример #13
0
void CGui::InitGui()
{
	mGui = app->mGui;
	gcom->mGui = mGui;
	Check::pGUI = mGui;  SliderValue::pGUI = mGui;
	Check::bGI = &bGI;   SliderValue::bGI = &bGI;

	popup->mGui = mGui;
	popup->mPlatform = app->mPlatform;

	if (!mGui)  return;
	Ogre::Timer ti;
	int i;


	//  new widgets
	FactoryManager::getInstance().registerFactory<MultiList2>("Widget");
	FactoryManager::getInstance().registerFactory<Slider>("Widget");

	//  load
	app->vwGui = LayoutManager::getInstance().loadLayout("Game.layout");


	//  wnds
	app->mWndMain = fWnd("MainMenuWnd");
	app->mWndGame = fWnd("GameWnd");
	app->mWndReplays = fWnd("ReplaysWnd");
	app->mWndHelp = fWnd("HelpWnd");
	app->mWndOpts = fWnd("OptionsWnd");

	app->mWndChampStage = fWnd("WndChampStage");  app->mWndChampStage->setVisible(false);
	app->mWndChampEnd   = fWnd("WndChampEnd");    app->mWndChampEnd->setVisible(false);
	app->mWndChallStage = fWnd("WndChallStage");  app->mWndChallStage->setVisible(false);
	app->mWndChallEnd   = fWnd("WndChallEnd");    app->mWndChallEnd->setVisible(false);

	app->mWndNetEnd = fWnd("WndNetEnd");  app->mWndNetEnd->setVisible(false);
	app->mWndTweak = fWnd("WndTweak");    app->mWndTweak->setVisible(false);
	app->mWndTweak->setPosition(0,40);
	

	//  for find defines
	Btn btn, bchk;  Cmb cmb;
	Slider* sl;  SV* sv;  Ck* ck;


	//  Tabs
	Tab tab,sub;
	fTabW("TabWndGame");    app->mWndTabsGame = tab;
	fTabW("TabWndReplays"); app->mWndTabsRpl = tab;
	fTabW("TabWndHelp");    app->mWndTabsHelp = tab;
	fTabW("TabWndOptions"); app->mWndTabsOpts = tab;

	//  get sub tabs
	vSubTabsGame.clear();
	for (i=0; i < app->mWndTabsGame->getItemCount(); ++i)
	{	// todo: startsWith("SubTab")..
		sub = (Tab)app->mWndTabsGame->getItemAt(i)->findWidget(
			i==TAB_Champs ? "ChampType" : (i==TAB_Multi ? "tabsNet" : "tabPlayer") );
		vSubTabsGame.push_back(sub);  // 0 for not found
	}
	vSubTabsOpts.clear();
	for (i=0; i < app->mWndTabsOpts->getItemCount(); ++i)
	{
		sub = (Tab)app->mWndTabsOpts->getItemAt(i)->findWidget(
			i==TABo_Input ? "InputTab" : "SubTab");
		vSubTabsOpts.push_back(sub);
	}

	if (pSet->inMenu > MNU_Single && pSet->inMenu <= MNU_Challenge)
		app->mWndTabsGame->setIndexSelected(TAB_Champs);

	app->mWndRpl = fWnd("RplWnd");


	///  Gui common init  ---
	gcom->InitMainMenu();
	gcom->GuiInitTooltip();
	gcom->GuiInitLang();

	gcom->GuiInitGraphics();
	gcom->InitGuiScreenRes();


	loadReadme = true;
	toggleGui(false);
	app->updMouse();
	gcom->bnQuit->setVisible(app->isFocGui);
	

	///  Sliders
	//------------------------------------------------------------------------
	    
	//  Hud view sizes  ----
	sv= &svSizeGaug;	sv->Init("SizeGaug",	&pSet->size_gauges,    0.1f, 0.3f,  1.f, 3,4);  sv->DefaultF(0.19f);  Sev(HudSize);
	sv= &svTypeGaug;	sv->Init("TypeGaug",	&pSet->gauges_type,    0, 5);  sv->DefaultI(5);  Sev(HudCreate);
	//sv= &svLayoutGaug;	sv->Init("LayoutGaug",	&pSet->gauges_layout,  0, 2);  sv->DefaultI(1);  Sev(HudCreate);

	sv= &svSizeMinimap;	sv->Init("SizeMinimap",	&pSet->size_minimap,   0.05f, 0.3f, 1.f, 3,4);  sv->DefaultF(0.165f);  Sev(HudSize);
	sv= &svZoomMinimap;	sv->Init("ZoomMinimap",	&pSet->zoom_minimap,   0.9f, 4.f,   1.f, 2,4);  sv->DefaultF(1.6f);    Sev(HudSize);
	sv= &svSizeArrow;	sv->Init("SizeArrow",   &pSet->size_arrow,     0.1f, 0.5f,  1.f, 3,4);  sv->DefaultF(0.26f);  Sev(SizeArrow);
	Slv(CountdownTime,  pSet->gui.pre_time / 0.5f /10.f);  sl->mfDefault = 4.f /10.f;


	//  graphs
	valGraphsType = fTxt("GraphsTypeVal");
	Cmb(cmb, "CmbGraphsType", comboGraphs);  cmbGraphs = cmb;
	if (cmb)
	{	cmb->removeAllItems();
		for (i=0; i < Gh_ALL; ++i)
			cmb->addItem(csGraphNames[i]);
		cmb->setIndexSelected(pSet->graphs_type);
	}
	valGraphsType->setCaption(toStr(pSet->graphs_type));


	//  Options  ----
	sv= &svParticles;	sv->Init("Particles",	&pSet->particles_len, 0.f, 4.f, 2.f);  sv->DefaultF(1.5f);
	sv= &svTrails;		sv->Init("Trails",		&pSet->trails_len,    0.f, 4.f, 2.f);  sv->DefaultF(3.f);

	//  reflection
	sv= &svReflSkip;	sv->Init("ReflSkip",	&pSet->refl_skip,    0,1000, 2.f);  sv->DefaultI(0);
	sv= &svReflFaces;	sv->Init("ReflFaces",	&pSet->refl_faces,   1,6);  sv->DefaultI(1);
	sv= &svReflSize;
		for (i=0; i < ciShadowSizesNum; ++i)  sv->strMap[i] = toStr(ciShadowSizesA[i]);
						sv->Init("ReflSize",	&pSet->refl_size,    0,ciShadowSizesNum-1);  sv->DefaultI(1.5f);

	sv= &svReflDist;	sv->Init("ReflDist",	&pSet->refl_dist,   20.f,1500.f, 2.f, 0,4, 1.f," m");
																	Sev(ReflDist);  sv->DefaultF(300.f);
	sv= &svReflMode;
		sv->strMap[0] = TR("#{ReflMode_static}");  sv->strMap[1] = TR("#{ReflMode_single}");
		sv->strMap[2] = TR("#{ReflMode_full}");
						sv->Init("ReflMode",	&pSet->refl_mode,   0,2);  Sev(ReflMode);  sv->DefaultI(1);

	//  Sound
	sv= &svVolMaster;	sv->Init("VolMaster",	&pSet->vol_master, 0.f, 1.6f);  sv->DefaultF(0.80f);  Sev(VolMaster);

	sv= &svVolEngine;	sv->Init("VolEngine",	&pSet->vol_engine, 0.f, 1.4f);  sv->DefaultF(0.56f);
	sv= &svVolTires;	sv->Init("VolTires",	&pSet->vol_tires,  0.f, 1.4f);  sv->DefaultF(0.80f);
	sv= &svVolSusp;		sv->Init("VolSusp",		&pSet->vol_susp,   0.f, 1.4f);  sv->DefaultF(0.714f);
	sv= &svVolEnv;		sv->Init("VolEnv",		&pSet->vol_env,    0.f, 1.4f);  sv->DefaultF(0.928f);

	sv= &svVolFlSplash;	sv->Init("VolFlSplash",	&pSet->vol_fl_splash, 0.f, 1.4f);  sv->DefaultF(0.80f);
	sv= &svVolFlCont;	sv->Init("VolFlCont",	&pSet->vol_fl_cont,   0.f, 1.4f);  sv->DefaultF(0.878f);
	sv= &svVolCarCrash;	sv->Init("VolCarCrash",	&pSet->vol_car_crash, 0.f, 1.4f);  sv->DefaultF(0.703f);
	sv= &svVolCarScrap;	sv->Init("VolCarScrap",	&pSet->vol_car_scrap, 0.f, 1.4f);  sv->DefaultF(1.00f);


	//  car color
	float f;  // temp
	sv= &svCarClrH;		sv->Init("CarClrH", &f, 0.f,1.f);  Sev(CarClr);
	sv= &svCarClrS;		sv->Init("CarClrS", &f, 0.f,1.f);  Sev(CarClr);
	sv= &svCarClrV;		sv->Init("CarClrV", &f, 0.f,1.f);  Sev(CarClr);
	sv= &svCarClrGloss;	sv->Init("CarClrGloss", &f, 0.f,1.f, 1.6f);  Sev(CarClr);
	sv= &svCarClrRefl;	sv->Init("CarClrRefl",  &f, 0.f,1.4f);  Sev(CarClr);
	UpdCarClrSld();


	///  Checks
	//------------------------------------------------------------------------
	ck= &ckReverse;		ck->Init("ReverseOn",	&pSet->gui.trackreverse);  Cev(Reverse);

	//  Options  ----
	ck= &ckParticles;	ck->Init("ParticlesOn", &pSet->particles);   Cev(ParTrl);
	ck= &ckTrails;		ck->Init("TrailsOn",    &pSet->trails);      Cev(ParTrl);

	//  Hud  ----
	ck= &ckDigits;		ck->Init("Digits",      &pSet->show_digits);   Cev(HudShow);
	ck= &ckGauges;		ck->Init("Gauges",      &pSet->show_gauges);   Cev(HudShow);

	ck= &ckArrow;		ck->Init("Arrow",       &pSet->check_arrow);   Cev(Arrow);
	ck= &ckBeam;		ck->Init("ChkBeam",     &pSet->check_beam);    Cev(Beam);

	//  minimap
	ck= &ckMinimap;		ck->Init("Minimap",     &pSet->trackmap);      Cev(Minimap);
	ck= &ckMiniZoom;	ck->Init("MiniZoom",    &pSet->mini_zoomed);   Cev(MiniUpd);
	ck= &ckMiniRot;		ck->Init("MiniRot",     &pSet->mini_rotated);
	ck= &ckMiniTer;		ck->Init("MiniTer",     &pSet->mini_terrain);  Cev(MiniUpd);
	ck= &ckMiniBorder;	ck->Init("MiniBorder",  &pSet->mini_border);   Cev(MiniUpd);

	//  camera
	ck= &ckCamInfo;		ck->Init("CamInfo",     &pSet->show_cam);   Cev(HudShow);
	ck= &ckCamTilt;		ck->Init("CamTilt",     &pSet->cam_tilt);
	ck= &ckCamLoop;		ck->Init("CamLoop",     &pSet->cam_loop_chng);

	ck= &ckCamBnc;		ck->Init("CamBounce",   &pSet->cam_bounce);
	sv= &svCamBnc;		sv->Init("CamBnc",		&pSet->cam_bnc_mul, 0.f, 2.f);

	sv= &svFov;			sv->Init("Fov",			&pSet->fov_min,   50.f, 180.f, 1.f, 1,4);  sv->DefaultF(90.f);
	sv= &svFovMax;		sv->Init("FovMax",		&pSet->fov_max,   50.f, 180.f, 1.f, 1,4);  sv->DefaultF(120.f);
	sv= &svFovSm;		sv->Init("FovSm",		&pSet->fov_smooth, 0.f, 15.f, 1.5f);  sv->DefaultF(5.f);


	//  times, opp
	ck= &ckTimes;		ck->Init("Times",       &pSet->show_times);      Cev(HudShow);
	ck= &ckOpponents;	ck->Init("Opponents",   &pSet->show_opponents);  Cev(HudShow);
	ck= &ckOppSort;		ck->Init("OppSort",     &pSet->opplist_sort);


	//  dbg,other
	ck= &ckFps;			ck->Init("Fps",			&pSet->show_fps);
	app->bckFps->setVisible(pSet->show_fps);
	ck= &ckWireframe;	ck->Init("Wireframe",   &app->mbWireFrame);  Cev(Wireframe);

	ck= &ckProfilerTxt;	ck->Init("ProfilerTxt",  &pSet->profilerTxt);
	ck= &ckBulletDebug;	ck->Init("BulletDebug",  &pSet->bltDebug);
	ck= &ckBltProfTxt;	ck->Init("BltProfTxt",   &pSet->bltProfilerTxt);

	ck= &ckCarDbgBars;	ck->Init("CarDbgBars",  &pSet->car_dbgbars);   Cev(HudShow);
	ck= &ckCarDbgTxt;	ck->Init("CarDbgTxt",   &pSet->car_dbgtxt);    Cev(HudShow);
	ck= &ckCarDbgSurf;	ck->Init("CarDbgSurf",  &pSet->car_dbgsurf);   Cev(HudShow);
	
	ck= &ckTireVis;		ck->Init("CarTireVis",  &pSet->car_tirevis);   Cev(HudCreate);
	ck= &ckGraphs;		ck->Init("Graphs",		&pSet->show_graphs);   Cev(Graphs);

	sv= &svDbgTxtClr;	sv->Init("DbgTxtClr",	&pSet->car_dbgtxtclr, 0, 1);
	sv= &svDbgTxtCnt;	sv->Init("DbgTxtCnt",	&pSet->car_dbgtxtcnt, 0, 8);


	//  car setup  todo: for each player ..
	Chk("CarABS",  chkAbs, pSet->abs[0]);  bchAbs = bchk;
	Chk("CarTCS",  chkTcs, pSet->tcs[0]);  bchTcs = bchk;
	
	ck= &ckCarGear;		ck->Init("CarGear",		&pSet->autoshift);  Cev(Gear);
	ck= &ckCarRear;		ck->Init("CarRear",		&pSet->autorear);   Cev(Gear);
	ck= &ckCarRearInv;	ck->Init("CarRearThrInv",&pSet->rear_inv);  Cev(Gear);

	TabPtr tTires = fTab("tabCarTires");  Tev(tTires, TireSet);
	
	sv= &svSSSEffect;		sv->Init("SSSEffect",		&f, 0.f, 1.f);
	sv= &svSSSVelFactor;	sv->Init("SSSVelFactor",	&f, 0.f, 2.f);
	sv= &svSteerRangeSurf;	sv->Init("SteerRangeSurf",	&f, 0.3f, 1.3f);
	sv= &svSteerRangeSim;	sv->Init("SteerRangeSim",	&f, 0.3f, 1.3f);
	Btn("SSSReset", btnSSSReset);  Btn("SteerReset", btnSteerReset);
	SldUpd_TireSet();


	//  game  ------------------------------------------------------------
	ck= &ckVegetCollis;		ck->Init("VegetCollis",		&pSet->gui.collis_veget);
	ck= &ckCarCollis;		ck->Init("CarCollis",		&pSet->gui.collis_cars);
	ck= &ckRoadWCollis;		ck->Init("RoadWCollis",		&pSet->gui.collis_roadw);
	ck= &ckDynamicObjs;		ck->Init("DynamicObjects",	&pSet->gui.dyn_objects);

	Cmb(cmb, "CmbBoost", comboBoost);	cmbBoost = cmb;
		cmb->removeAllItems();
		cmb->addItem(TR("#{Never}"));		cmb->addItem(TR("#{FuelLap}"));
		cmb->addItem(TR("#{FuelTime}"));	cmb->addItem(TR("#{Always}"));
		cmb->setIndexSelected(pSet->gui.boost_type);

	Cmb(cmb, "CmbFlip", comboFlip);		cmbFlip = cmb;
		cmb->removeAllItems();
		cmb->addItem(TR("#{Never}"));		cmb->addItem(TR("#{FuelBoost}"));
		cmb->addItem(TR("#{Always}"));
		cmb->setIndexSelected(pSet->gui.flip_type);

	Cmb(cmb, "CmbDamage", comboDamage);	cmbDamage = cmb;
		cmb->removeAllItems();
		cmb->addItem(TR("#{None}"));		cmb->addItem(TR("#{Reduced}"));
		cmb->addItem(TR("#{Normal}"));
		cmb->setIndexSelected(pSet->gui.damage_type);

	Cmb(cmb, "CmbRewind", comboRewind);	cmbRewind = cmb;
		cmb->removeAllItems();
		cmb->addItem(TR("#{None}"));		cmb->addItem(TR("#{Always}"));
		//cmb->addItem(TR("#{FuelLap}"));		cmb->addItem(TR("#{FuelTime}"));
		cmb->setIndexSelected(pSet->gui.rewind_type);

	sv= &svDamageDec;	sv->Init("DamageDec",	&pSet->gui.damage_dec, 0.f, 100.f, 1.f, 0,1, 1.f, " %");
	sv= &svBmin;	sv->Init("Bmin",	&pSet->gui.boost_min,     0.f, 10.f,1.f, 1,3);  sv->DefaultF(2.f);
	sv= &svBmax;	sv->Init("Bmax",	&pSet->gui.boost_max,     2.f, 20.f,1.f, 1,3);  sv->DefaultF(6.f);
	sv= &svBpow;	sv->Init("Bpow",	&pSet->gui.boost_power,   0.f, 2.5f,1.f, 1,3);  sv->DefaultF(1.f);
	sv= &svBperKm;	sv->Init("BperKm",	&pSet->gui.boost_per_km,  0.f, 4.f, 1.f, 1,3);  sv->DefaultF(1.f);
	sv= &svBaddSec;	sv->Init("BaddSec",	&pSet->gui.boost_add_sec, 0.f, 1.f, 1.f, 2,4);  sv->DefaultF(0.1f);

	//  split
	Btn("btnPlayers1", btnNumPlayers);	Btn("btnPlayers2", btnNumPlayers);
	Btn("btnPlayers3", btnNumPlayers);	Btn("btnPlayers4", btnNumPlayers);
	
	ck= &ckSplitVert;	ck->Init("chkSplitVertically", &pSet->split_vertically);
	Chk("chkStartOrderRev", chkStartOrd, pSet->gui.start_order);
	valLocPlayers = fTxt("valLocPlayers");
	if (valLocPlayers)  valLocPlayers->setCaption(toStr(pSet->gui.local_players));


	//  sim mode radio
	Btn("SimModeEasy", radSimEasy);  bRsimEasy = btn;  btn->setStateSelected(pSet->gui.sim_mode == "easy");
	Btn("SimModeNorm", radSimNorm);	 bRsimNorm = btn;  btn->setStateSelected(pSet->gui.sim_mode == "normal");
	Btn("SimModeHard", radSimHard);	 bRsimHard = btn;  btn->setStateSelected(pSet->gui.sim_mode == "hard");

	//  kmh/mph radio
	Btn("kmh", radKmh);  bRkmh = btn;  bRkmh->setStateSelected(!pSet->show_mph);
	Btn("mph", radMph);	 bRmph = btn;  bRmph->setStateSelected( pSet->show_mph);


	//  startup
	ck= &ckStartInMain;	ck->Init("StartInMain", &pSet->startInMain);
	ck= &ckAutoStart;	ck->Init("AutoStart",   &pSet->autostart);
	ck= &ckEscQuits;	ck->Init("EscQuits",    &pSet->escquit);
	ck= &ckOgreDialog;	ck->Init("OgreDialog",  &pSet->ogre_dialog);
	ck= &ckMouseCapture;ck->Init("MouseCapture",&pSet->mouse_capture);

	ck= &ckBltLines;	ck->Init("BltLines",	&pSet->bltLines);
	ck= &ckShowPics;	ck->Init("ShowPictures",&pSet->loadingbackground);
	Chk("MultiThread", chkMultiThread, pSet->multi_thr > 0);
	ck= &ckDevKeys;		ck->Init("DevKeys",		&pSet->dev_keys);

	
	//  effects
	ck= &ckAllEffects;	ck->Init("AllEffects",	&pSet->all_effects);  Cev(AllEffects);
	ck= &ckBoostFOV;	ck->Init("BoostFOV",	&pSet->boost_fov);

	ck= &ckBloom;		ck->Init("Bloom",		&pSet->bloom);  Cev(EffUpd);
	sv= &svBloomInt;	sv->Init("BloomInt",	&pSet->bloom_int);   sv->DefaultF(0.13f);
	sv= &svBloomOrig;	sv->Init("BloomOrig",	&pSet->bloom_orig);	 sv->DefaultF(0.91f);
	
	ck= &ckBlur;		ck->Init("MotionBlur",	&pSet->blur);  Cev(EffUpdShd);
	sv= &svBlurIntens;	sv->Init("BlurIntens",	&pSet->blur_int);	sv->DefaultF(0.4f);

	ck= &ckSSAO;		ck->Init("SSAO",		&pSet->ssao);  Cev(EffUpdShd);
	ck= &ckSoftPar;		ck->Init("SoftParticles",&pSet->softparticles);  Cev(EffUpdShd);
	ck= &ckGodRays;		ck->Init("GodRays",		&pSet->godrays);  Cev(EffUpdShd);
	
	ck= &ckDoF;			ck->Init("DepthOfField",&pSet->dof);  Cev(EffUpdShd);
	sv= &svDofFocus;	sv->Init("DofFocus",	&pSet->dof_focus, 0.f, 2000.f, 2.f, 0,3);	sv->DefaultF(100.f);
	sv= &svDofFar;		sv->Init("DofFar",		&pSet->dof_far,   0.f, 2000.f, 2.f, 0,4);	sv->DefaultF(1000.f);

	//  hdr
	ck= &ckHDR;				ck->Init("HDR",				&pSet->hdr);  Cev(EffUpd);
	sv= &svHDRParam1;		sv->Init("HDRParam1",		&pSet->hdrParam1);  sv->DefaultF(0.62f);
	sv= &svHDRParam2;		sv->Init("HDRParam2",		&pSet->hdrParam2, 0.f, 1.f, 2.f);  sv->DefaultF(0.10f);
	sv= &svHDRParam3;		sv->Init("HDRParam3",		&pSet->hdrParam3);  sv->DefaultF(0.79f);
	sv= &svHDRAdaptScale;	sv->Init("HDRAdaptScale",	&pSet->hdrAdaptationScale, 0.f, 1.f, 2.f);  sv->DefaultF(0.10f);
	sv= &svHDRBloomInt;		sv->Init("HDRBloomInt",		&pSet->hdrBloomint);   sv->DefaultF(0.81f);
	sv= &svHDRBloomOrig;	sv->Init("HDRBloomOrig",	&pSet->hdrBloomorig);  sv->DefaultF(0.34f);
	sv= &svHDRVignRadius;	sv->Init("HDRVignRadius",	&pSet->vignRadius, 0.f, 10.f);  sv->DefaultF(2.85f);
	sv= &svHDRVignDark;		sv->Init("HDRVignDark",		&pSet->vignDarkness);  sv->DefaultF(0.34f);
	
	
	//  replays  ------------------------------------------------------------
	Btn("RplLoad",   btnRplLoad);    Btn("RplSave",   btnRplSave);
	Btn("RplDelete", btnRplDelete);  Btn("RplRename", btnRplRename);
	//  settings
	ck= &ckRplAutoRec;		ck->Init("RplChkAutoRec",	&app->bRplRec);
	ck= &ckRplBestOnly;		ck->Init("RplChkBestOnly",	&pSet->rpl_bestonly);
	ck= &ckRplGhost;		ck->Init("RplChkGhost",		&pSet->rpl_ghost);
	ck= &ckRplParticles;	ck->Init("RplChkParticles",	&pSet->rpl_ghostpar);
		   
	ck= &ckRplRewind;		ck->Init("RplChkRewind",	&pSet->rpl_ghostrewind);
	ck= &ckRplGhostOther;	ck->Init("RplChkGhostOther",&pSet->rpl_ghostother);
	ck= &ckRplTrackGhost;	ck->Init("RplChkTrackGhost",&pSet->rpl_trackghost);
	Slv(RplNumViewports, (pSet->rpl_numViews-1) / 3.f);

	//  radios, filter
	ck= &ckRplGhosts;	ck->Init("RplBtnGhosts",  &pSet->rpl_listghosts);  Cev(RplGhosts);
	Btn("RplBtnAll", btnRplAll);  rbRplAll = btn;
	Btn("RplBtnCur", btnRplCur);  rbRplCur = btn;
	btn = pSet->rpl_listview == 0 ? rbRplAll : rbRplCur;
	if (btn)  btn->setStateSelected(true);

	
    if (app->mWndRpl)
	{	//  replay controls
		Btn("RplToStart", btnRplToStart);  Btn("RplToEnd", btnRplToEnd)
		Btn("RplPlay", btnRplPlay);  btRplPl = btn;
		btn = fBtn("RplBack");		btn->eventMouseButtonPressed += newDelegate(this, &CGui::btnRplBackDn);  btn->eventMouseButtonReleased += newDelegate(this, &CGui::btnRplBackUp);
		btn = fBtn("RplForward");	btn->eventMouseButtonPressed += newDelegate(this, &CGui::btnRplFwdDn);   btn->eventMouseButtonReleased += newDelegate(this, &CGui::btnRplFwdUp);
		
		//  info
		slRplPos = (Slider*)app->mWndRpl->findWidget("RplSlider");
		if (slRplPos)  slRplPos->eventValueChanged += newDelegate(this, &CGui::slRplPosEv);

		valRplPerc = fTxt("RplPercent");
    	valRplCur = fTxt("RplTimeCur");
    	valRplLen = fTxt("RplTimeLen");
	}
	//  text desc, stats
	valRplName = fTxt("RplName");  valRplName2 = fTxt("RplName2");
	valRplInfo = fTxt("RplInfo");  valRplInfo2 = fTxt("RplInfo2");
	edRplName = fEd("RplNameEdit");
	//edRplDesc = fEd("RplDesc");

	rplList = fLi("RplList");
	Lev(rplList, RplChng);
	updReplaysList();


	///  Car
	//------------------------------------------------------------
	const int clrBtn = 30;
	Real hsv[clrBtn][5] = {  // color buttons  hue,sat,val, gloss,refl
	{0.05,0.64,0.27, 0.10,0.9}, {0.00,0.97,0.90, 0.3, 1.2},  // cherry, red
	{0.91,1.00,1.00, 0.5, 1.0}, {0.86,1.00,0.97, 0.8, 0.6},  // orange, yellow
	{0.75,0.95,0.90, 1.0, 0.4}, {0.70,1.00,0.70, 0.03,1.3}, // lime, green
	{0.54,0.88,0.60, 0.7, 0.85},{0.51,0.90,0.50, 0.1, 0.7},  // cyan
	{0.41,0.34,0.30, 0.01,0.3}, {0.43,0.58,0.23, 0.1, 1.0},  // dark-cyan  //{0.45,0.54,0.37, 0.5,1.0},
	{0.37,0.78,0.21, 0.34,0.5}, {0.35,0.70,0.40, 0.5, 1.0}, {0.38,0.97,0.52, 0.5, 1.0},  // dark-blue
	{0.44,0.90,0.71, 1.0, 1.1}, {0.47,0.80,0.80, 0.2, 0.9}, // sky-blue
	{0.50,0.33,0.90, 0.9, 1.0}, {0.42,0.20,0.94, 0.5, 0.4}, // sky-white
	{0.63,0.21,0.62, 0.1, 1.2}, {0.80,0.52,0.32, 0.1, 0.6}, {0.62,0.74,0.12, 0.8, 0.7},  // olive-
	{0.28,0.00,0.12, 0.09,0.0}, {0.28,0.00,0.07, 0.14,0.84},  // black
	{0.83,0.00,0.20, 0.0, 0.8}, {0.41,0.00,0.86, 0.15,0.37}, // silver,white
	{0.83,0.31,0.31, 0.0, 0.6}, {0.91,0.40,0.37, 0.0, 1.0}, {0.20,0.40,0.37, 0.05,1.0},  // orng-white-
	{0.24,0.90,0.26, 0.04,0.8}, {0.28,0.57,0.17, 0.3, 1.0}, {0.27,0.38,0.23, 0.03,0.6},  // dark violet
	};
	for (i=0; i < clrBtn; ++i)
	{
		Img img = fImg("carClr"+toStr(i));
		Real h = hsv[i][0], s = hsv[i][1], v = hsv[i][2], g = hsv[i][3], r = hsv[i][4];
		ColourValue c;  c.setHSB(1.f-h, s, v);
		img->setColour(Colour(c.r,c.g,c.b));
		img->eventMouseButtonClick += newDelegate(this, &CGui::imgBtnCarClr);
		img->setUserString("s", toStr(s));  img->setUserString("h", toStr(h));
		img->setUserString("v", toStr(v));  img->setUserString("g", toStr(g));  img->setUserString("r", toStr(r));
	}
	Btn("CarClrRandom", btnCarClrRandom);
	sv= &svNumLaps;  sv->Init("NumLaps",  &pSet->gui.num_laps, 1,10, 1.3f);  sv->DefaultI(2);

	txCarStatsTxt = fTxt("CarStatsTxt");    txCarSpeed = fTxt("CarSpeed");
	txCarStatsVals = fTxt("CarStatsVals");  txCarType = fTxt("CarType");

    txCarAuthor = fTxt("CarAuthor");  txTrackAuthor = fTxt("TrackAuthor");
	
	TabPtr tPlr = fTab("tabPlayer");  Tev(tPlr, Player);
	Btn("btnPlayers1", btnNumPlayers);	Btn("btnPlayers2", btnNumPlayers);
	Btn("btnPlayers3", btnNumPlayers);	Btn("btnPlayers4", btnNumPlayers);
	ck= &ckSplitVert;	ck->Init("chkSplitVertically",  &pSet->split_vertically);


	///  Multiplayer
	//------------------------------------------------------------------------
	tabsNet = fTab("tabsNet");
		//TabItem* t1 = tabsNet->getItemAt(0);
		//t1->setEnabled(0);
	//int num = tabsNet ? tabsNet->getItemCount() : 0;
	//tabsNet->setIndexSelected( (tabsNet->getIndexSelected() - 1 + num) % num );
	
	//  server, games
	listServers = fMli("MListServers");  int c=0;
	Mli ml = listServers;
		ml->addColumn("#C0FFC0"+TR("#{Game name}"), 160);  ++c;
		ml->addColumn("#50FF50"+TR("#{Track}"), 120);  ++c;
		ml->addColumn("#80FFC0"+TR("#{Laps}"), 60);  ++c;
		ml->addColumn("#FFFF00"+TR("#{Players}"), 60);  ++c;
		ml->addColumn("#80FFFF"+TR("#{Collis.}"), 70);  ++c;
		ml->addColumn("#A0D0FF"+TR("#{Simulation}"), 80);  ++c;
		ml->addColumn("#A0D0FF"+TR("#{Boost}"), 90);  ++c;
		ml->addColumn("#FF6060"+TR("#{Locked}"), 60);  iColLock = c;  ++c;
		ml->addColumn("#FF9000"+TR("#{NetHost}"), 140);  iColHost = c;  ++c;
		ml->addColumn("#FFB000"+TR("#{NetPort}"), 80);  iColPort = c;  ++c;

	Btn("btnNetRefresh",evBtnNetRefresh); btnNetRefresh = btn;
	Btn("btnNetJoin",   evBtnNetJoin);    btnNetJoin = btn;
	Btn("btnNetCreate", evBtnNetCreate);  btnNetCreate = btn;
	Btn("btnNetDirect", evBtnNetDirect);  btnNetDirect = btn;

	//  game, players
	Edt(edNetGameName, "edNetGameName", evEdNetGameName);  edNetGameName->setCaption(pSet->netGameName);
	valNetPassword = fTxt("valNetPassword");
	Edt(edNetPassword, "edNetPassword", evEdNetPassword);

	listPlayers = fMli("MListPlayers");
	ml = listPlayers;
		ml->addColumn("#80C0FF"+TR("#{Player}"), 140);
		ml->addColumn("#F08080"+TR("#{Car}"), 60);
		ml->addColumn("#C0C060"+TR("#{Peers}"), 60);
		ml->addColumn("#60F0F0"+TR("#{Ping}"), 60);
		ml->addColumn("#40F040"+TR("#{NetReady}"), 60);

	Btn("btnNetReady", evBtnNetReady);  btnNetReady = btn;
	Btn("btnNetLeave", evBtnNetLeave);	btnNetLeave = btn;

	//  panels to hide tabs
	panNetServer = fWP("panelNetServer");  panNetServer->setVisible(false);
	panNetGame = fWP("panelNetGame");      panNetGame->setVisible(true);

    //  chat
    edNetChat = fEd("edNetChat");  // chat area
    edNetChatMsg = fEd("edNetChatMsg");  // user text
    //  track,game text
    valNetGameInfo = fTxt("valNetGameInfo");

	//  settings
	Edt(edNetNick,		"edNetNick",		evEdNetNick);		edNetNick->setCaption(		pSet->nickname);
	Edt(edNetServerIP,	"edNetServerIP",	evEdNetServerIP);	edNetServerIP->setCaption(	pSet->master_server_address);
	Edt(edNetServerPort,"edNetServerPort",	evEdNetServerPort);	edNetServerPort->setCaption(toStr(pSet->master_server_port));
	Edt(edNetLocalPort,	"edNetLocalPort",	evEdNetLocalPort);	edNetLocalPort->setCaption(	toStr(pSet->local_port));

	
	//  quick help text  ----
	Ed edHelp = fEd("QuickHelpText");
	String s = TR("#{QuickHelpText}");
	s = StringUtil::replaceAll(s, "@", "\n");
	edHelp->setCaption(s);

	//  user dir
    Ed edUserDir = fEd("EdUserDir");
	edUserDir->setCaption(PATHMANAGER::UserConfigDir());

	
	///  graphs  ----
	sv= &svTC_r;	sv->Init("TC_r",	&pSet->tc_r,  0.5f, 2.f, 1.5f, 1,4);	sv->DefaultF(1.f);
	sv= &svTC_xr;	sv->Init("TC_xr",	&pSet->tc_xr, 0.f, 5.f,  1.5f, 1,4);	sv->DefaultF(1.f);

	sv= &svTE_yf;	sv->Init("TE_yf",	&pSet->te_yf, 5000.f, 10000.f, 1.f, 0,4);	sv->DefaultF(7000.f);
	sv= &svTE_xfx;	sv->Init("TE_xfx",	&pSet->te_xfx, 4.f, 42.f,  2.f, 1,4);	sv->DefaultF(12.f);
	sv= &svTE_xfy;	sv->Init("TE_xfy",	&pSet->te_xfy, 90.f, 560.f, 2.f, 0,3);	sv->DefaultF(160.f);
	sv= &svTE_xpow;	sv->Init("TE_xpow",	&pSet->te_xf_pow, 1.f, 2.f, 1.f, 1,3);	sv->DefaultF(1.f);


	///  tweak car
	//------------------------------------------------------------
	for (i=0; i < ciEdCar; ++i)
		edCar[i] = fEd("EdCar"+toStr(i));
	edPerfTest = fEd("TweakPerfTest");
	tabEdCar = fTab("TabEdCar");  Tev(tabEdCar, CarEdChng);  tabEdCar->setIndexSelected(pSet->car_ed_tab);

	tabTweak = fTab("TabTweak");  /**/tabTweak->setIndexSelected(1);
	txtTweakPath = fTxt("TweakPath");
	Btn("TweakCarSave", btnTweakCarSave);

	edTweakCol = fEd("TweakEditCol");
	txtTweakPathCol = fTxt("TweakPathCol");
	Btn("TweakColSave", btnTweakColSave);


	///  tweak tires  ----
	Btn("TweakTireSave", btnTweakTireSave);
	txtTweakTire = fTxt("TweakTireTxtSaved");
	Edt(edTweakTireSet, "TweakTireSet", editTweakTireSet);

	liTwkTiresUser = fLi("TweakTiresUser");  Lev(liTwkTiresUser, TwkTiresUser);
	liTwkTiresOrig = fLi("TweakTiresOrig");  Lev(liTwkTiresOrig, TwkTiresOrig);
	Btn("TweakTireLoad",    btnTweakTireLoad);
	Btn("TweakTireLoadRef", btnTweakTireLoadRef);

	///  tweak surfaces  ----
	liTwkSurfaces = fLi("TweakSurfaces");  Lev(liTwkSurfaces, TwkSurfaces);
	//<Widget type="ComboBox" name="TweakSurface">
	Btn("TweakSurfPickWh", btnTwkSurfPick);
	sv= &svSuFrict;		sv->Init("SuFrict",     &f, 0.f, 1.5f,  1.0f, 2,4);	sv->DefaultF(0.65f);
	sv= &svSuFrictX;	sv->Init("SuFrictX",    &f, 0.f, 1.5f,  1.0f, 2,4);	sv->DefaultF(1.f);
	sv= &svSuFrictY;	sv->Init("SuFrictY",    &f, 0.f, 1.5f,  1.0f, 2,4);	sv->DefaultF(1.f);
	sv= &svSuBumpWave;	sv->Init("SuBumpWave",	&f, 0.f, 50.f,  1.2f, 1,4);	sv->DefaultF(20.f);
	sv= &svSuBumpAmp;	sv->Init("SuBumpAmp",	&f, 0.f, 0.4f,  1.0f, 2,4);	sv->DefaultF(0.15f);
	sv= &svSuBumpWave2;	sv->Init("SuBumpWave2",	&f, 0.f, 50.f,  1.2f, 1,4);	sv->DefaultF(20.f);
	sv= &svSuBumpAmp2;	sv->Init("SuBumpAmp2",	&f, 0.f, 0.4f,  1.0f, 2,4);	sv->DefaultF(0.15f);
	sv= &svSuRollDrag;	sv->Init("SuRollDrag",	&f, 0.f, 200.f,  2.f, 0,3);	sv->DefaultF(60.f);
	sv= &svSuRollRes;	sv->Init("SuRollRes",	&f, 0.f, 200.f,  2.f, 0,3);	sv->DefaultF(1.f);
	//TODO: <Widget type="Button" name="TweakSurfSave">
	
	Cmb(cmb, "CmbSuTire", comboSurfTire);  cmbSurfTire = cmb;
	Cmb(cmb, "CmbSuType", comboSurfType);  cmbSurfType = cmb;
	cmb->removeAllItems();
	for (i=0; i < TRACKSURFACE::NumTypes; ++i)
		cmb->addItem(csTRKsurf[i]);
		


	///  input tab  -------
	InitInputGui();
		
	
	///  cars list
    //------------------------------------------------------------------------
	Tbi carTab = fTbi("TabCar");
	Mli2 li = carTab->createWidget<MultiList2>("MultiListBox",16,48,200,110, Align::Left | Align::VStretch);
	li->setColour(Colour(0.7,0.85,1.0));
	li->removeAllColumns();  int n=0;
	li->addColumn("#FF8888"+TR("#{Car}"), colCar[n++]);
	li->addColumn("#FFC080"+TR("#{CarSpeed}"), colCar[n++]);
	li->addColumn("#B0B8C0"+TR("#{CarYear}"), colCar[n++]);
	li->addColumn("#C0C0E0"+TR("#{CarType}"), colCar[n++]);
	li->addColumn(" ", colCar[n++]);
	carList = li;

	FillCarList();  //once

	li->mSortColumnIndex = pSet->cars_sort;
	li->mSortUp = pSet->cars_sortup;
	Lev(carList, CarChng);

   	CarListUpd(false);  //upd

    sListCar = pSet->gui.car[0];
    imgCar = fImg("CarImg");
    carDesc = fEd("CarDesc");
    listCarChng(carList,0);


    ///  tracks list, text, chg btn
    //------------------------------------------------------------------------

	gcom->trkDesc[0] = fEd("TrackDesc");
	gcom->sListTrack = pSet->gui.track;

    gcom->GuiInitTrack();

	Ed ed;
	Edt(ed,"RplFind",edRplFind);

	//  netw
	Tbi trkTab = fTbi("TabTrack");
	trkTab->setColour(Colour(0.8f,0.96f,1.f));
	const IntCoord& tc = trkTab->getCoord();

	WP wp = trkTab->createWidget<Widget>(
		"PanelSkin", 0,0,tc.width*0.66f,tc.height, Align::Default/*, "Popup", "panelNetTrack"*/);
	wp->setColour(Colour(0.8f,0.96f,1.f));
	wp->setAlpha(0.8f);  wp->setVisible(false);
	panNetTrack = wp;
	//<UserString key="RelativeTo" value="OptionsWnd"/>

    //  new game
    for (i=1; i<=3; ++i)
    {	Btn("NewGame"+toStr(i), btnNewGame);  if (i==2)  btNewGameCar = btn;  }

	//  championships
	//------------------------------------------------------------------------

	//  track stats 2nd set
	gcom->trkDesc[1] = fEd("TrackDesc2");
    valTrkNet = fTxt("TrackText");

	//  preview images
	gcom->imgPrv[1] = fImg("TrackImg2");   gcom->imgPrv[1]->setImageTexture("PrvView");
	gcom->imgTer[1] = fImg("TrkTerImg2");  gcom->imgTer[1]->setImageTexture("PrvTer");
	gcom->imgMini[1] = fImg("TrackMap2");  gcom->imgMini[1]->setImageTexture("PrvRoad");
	gcom->initMiniPos(1);

	//  track stats text
	int st = gcom->StTrk;
	for (i=0; i < st; ++i)   gcom->stTrk[1][i] = fTxt("2st"+toStr(i));
	for (i=0; i < 4; ++i)  gcom->imStTrk[1][i] = fImg("2ist"+toStr(i));
	for (i=0; i < gcom->InfTrk; ++i)
	{	gcom->infTrk[1][i] = fTxt("2ti"+toStr(i));  gcom->imInfTrk[1][i] = fImg("2iti"+toStr(i));  }

	edChInfo = fEd("ChampInfo");
	if (edChInfo)  edChInfo->setVisible(pSet->champ_info);
	Btn("btnChampInfo",btnChampInfo);

	panCh = fWP("panCh");
	txtCh = fTxt("txtChDetail");
	valCh = fTxt("valChDetail");
	for (i=0; i<3; ++i) {  String s = toStr(i);
		txtChP[i] = fTxt("txtChP"+s);
		valChP[i] = fTxt("valChP"+s);  }
	edChDesc = fEd("ChampDescr");


	//  Champs list  -------------
	Tbi trktab = fTbi("TabChamps");
	li = trktab->createWidget<MultiList2>("MultiListBox",0,0,400,300, Align::Left | Align::VStretch);
	Lev(li, ChampChng);  li->setVisible(false);
	
	li->removeAllColumns();  c=0;
	li->addColumn("#80A080N", colCh[c++]);
	li->addColumn(TR("#40F040#{Name}"), colCh[c++]);		li->addColumn(TR("#F0F040#{Difficulty}"), colCh[c++]);
	li->addColumn(TR("#80F0C0#{Stages}"), colCh[c++]);		li->addColumn(TR("#80E0FF#{Time} #{TimeMS}"), colCh[c++]);
	li->addColumn(TR("#D0C0FF#{Progress}"), colCh[c++]);	li->addColumn(TR("#F0E0F0#{Score}"), colCh[c++]);
	li->addColumn(" ", colCh[c++]);
	liChamps = li;

	//  Challs list  -------------
	li = trktab->createWidget<MultiList2>("MultiListBox",0,0,400,300, Align::Left | Align::VStretch);
	Lev(li, ChallChng);  li->setVisible(false);
	
	li->removeAllColumns();  c=0;
	li->addColumn("#80A080N", colChL[c++]);
	li->addColumn(TR("#60F060#{Name}"), colChL[c++]);		li->addColumn(TR("#F0D040#{Difficulty}"), colChL[c++]);
	li->addColumn(TR("#F09090#{Cars}"), colChL[c++]);
	li->addColumn(TR("#80F0C0#{Stages}"), colChL[c++]);		li->addColumn(TR("#80E0FF#{Time} m"), colChL[c++]);
	li->addColumn(TR("#D0C0FF#{Progress}"), colChL[c++]);
	li->addColumn(TR("#F0F8FF#{Prize}"), colChL[c++]);		li->addColumn(TR("#F0D0F0#{Score}"), colChL[c++]);
	li->addColumn(" ", colChL[c++]);
	liChalls = li;

	//  Stages list  -------------
	trktab = (TabItem*)app->mWndGame->findWidget("TabStages");
	li = trktab->createWidget<MultiList2>("MultiListBox",0,0,400,300, Align::Left | Align::VStretch);
	li->setColour(Colour(0.7,0.73,0.76));
	Lev(li, StageChng);  li->setVisible(false);
	
	li->removeAllColumns();  c=0;
	li->addColumn("#80A080N", colSt[c++]);
	li->addColumn(TR("#50F050#{Track}"), colSt[c++]);		li->addColumn(TR("#80FF80#{Scenery}"), colSt[c++]);
	li->addColumn(TR("#F0F040#{Difficulty}"), colSt[c++]);	li->addColumn(TR("#60E0A0#{Laps}"), colSt[c++]);
	li->addColumn(TR("#80E0FF#{Time} #{TimeMS}"), colSt[c++]);	li->addColumn(TR("#F0E0F0#{Score}"), colSt[c++]);
	li->addColumn(" ", colSt[c++]);
	liStages = li;

	updChampListDim();
	ChampsListUpdate();  listChampChng(liChamps, liChamps->getIndexSelected());
	ChallsListUpdate();  listChallChng(liChalls, liChalls->getIndexSelected());


	//  tabs
	tabTut   = fTab("TutType");    Tev(tabTut,   TutType);    tabTut->setIndexSelected(pSet->tut_type);
	tabChamp = fTab("ChampType");  Tev(tabChamp, ChampType);  tabChamp->setIndexSelected(pSet->champ_type);
	tabChall = fTab("ChallType");  Tev(tabChall, ChallType);  tabChall->setIndexSelected(pSet->chall_type);
	imgTut   = fImg("imgTut");
	imgChamp = fImg("imgChamp");
	imgChall = fImg("imgChall");

	Btn("btnTutStart",  btnChampStart);  btStTut = btn;
	Btn("btnChampStart",btnChampStart);  btStChamp = btn;
	Btn("btnChallStart",btnChallStart);  btStChall = btn;
	Btn("btnChRestart", btnChRestart);   btChRestart = btn;


	//  ch other
	ck= &ckChampRev;	ck->Init("ChampRev",    &pSet->gui.champ_rev);   Cev(ChampRev);
	
	Btn("btnChampStageBack", btnChampStageBack);
	Btn("btnChampStageStart",btnChampStageStart);  btChampStage = btn;
	Btn("btnChampEndClose",  btnChampEndClose);

	Btn("btnChallStageBack", btnChallStageBack);
	Btn("btnChallStageStart",btnChallStageStart);  btChallStage = btn;
	Btn("btnChallEndClose",  btnChallEndClose);

	Btn("btnStageNext", btnStageNext);
	Btn("btnStagePrev", btnStagePrev);
    valStageNum = fTxt("StageNum");

	edChampStage = fEd("ChampStageText");  edChampEnd = fEd("ChampEndText");
	edChallStage = fEd("ChallStageText");  edChallEnd = fEd("ChallEndText");
	//  stage prv
	imgChampStage = fImg("ChampStageImg");  imgChampStage->setImageTexture("PrvStCh");
	imgChallStage = fImg("ChallStageImg");	imgChallStage->setImageTexture("PrvStCh");
	
	imgChampEndCup = fImg("ChampEndImgCup"); txChampEndF = fTxt("ChampEndFinished");
	imgChallFail = fImg("ChallEndImgFail");  txChallEndF = fTxt("ChallEndFinished");
	imgChallCup  = fImg("ChallEndImgCup");   txChallEndC = fTxt("ChallEndCongrats");

	UpdChampTabVis();


	//  netw end list  ------
	Btn("btnNetEndClose", btnNetEndClose);

	li = app->mWndNetEnd->createWidget<MultiList2>("MultiListBox",4,42,632,360, Align::Left | Align::VStretch);
	li->setInheritsAlpha(false);  li->setColour(Colour(0.8,0.9,1,1));
	li->removeAllColumns();
	li->addColumn("", 40);  //N
	li->addColumn(TR("#{TBPlace}"), 60);	li->addColumn(TR("#{NetNickname}"), 180);
	li->addColumn(TR("#{TBTime}"), 120);	li->addColumn(TR("#{TBBest}"), 120);
	li->addColumn(TR("#{TBLap}"), 60);
	liNetEnd = li;
	

	bGI = true;  // gui inited, gui events can now save vals
	
	LogO(String("::: Time Init Gui: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
}
//-----------------------------------------------------------------------
void RTShaderSRSSegmentedLights::updateGpuProgramsParams(Renderable* rend, Pass* pass, const AutoParamDataSource* source, 
    const LightList* pLightList)
{
    if ((mLightParamsList.empty()) && (!mUseSegmentedLightTexture))
        return;

    const Matrix4& matWorld = source->getWorldMatrix();
    Light::LightTypes curLightType = Light::LT_DIRECTIONAL; 
    unsigned int curSearchLightIndex = 0;

    //update spot strength
    float spotIntensity = 1;
    
    // Update per light parameters.
    for (unsigned int i=0; i < mLightParamsList.size(); ++i)
    {
        const LightParams& curParams = mLightParamsList[i];

        if (curLightType != curParams.mType)
        {
            curLightType = curParams.mType;
            curSearchLightIndex = 0;
        }

        Light*      srcLight = NULL;
        Vector4     vParameter;
        ColourValue colour;

        // Search a matching light from the current sorted lights of the given renderable.
        for (unsigned int j = curSearchLightIndex; j < pLightList->size(); ++j)
        {
            if (pLightList->at(j)->getType() == curLightType)
            {               
                srcLight = pLightList->at(j);
                curSearchLightIndex = j + 1;
                break;
            }           
        }

        // No matching light found -> use a blank dummy light for parameter update.
        if (srcLight == NULL)
        {                       
            srcLight = &msBlankLight;
        }


        switch (curParams.mType)
        {
        case Light::LT_DIRECTIONAL:

            // Update light direction.
            vParameter = matWorld.transformAffine(srcLight->getAs4DVector(true));
            curParams.mDirection->setGpuParameter(vParameter.ptr(),3,1);
            break;

        case Light::LT_POINT:

            // Update light position.
            vParameter = matWorld.transformAffine(srcLight->getAs4DVector(true));
            curParams.mPosition->setGpuParameter(vParameter.ptr(),3,1);

            // Update light attenuation parameters.
            curParams.mSpotParams->setGpuParameter(Ogre::Vector3(1 / srcLight->getAttenuationRange(),0,0));
            break;

        case Light::LT_SPOTLIGHT:
            {                       
                Ogre::Vector3 vec3;
                Ogre::Matrix3 matWorldIT;


                // Update light position.
                vParameter = matWorld.transformAffine(srcLight->getAs4DVector(true));
                curParams.mPosition->setGpuParameter(vParameter.ptr(),3,1);


                // Update light direction.
                source->getInverseTransposeWorldMatrix().extract3x3Matrix(matWorldIT);
                vec3 = matWorldIT * srcLight->getDerivedDirection();
                vec3.normalise();

                vParameter.x = -vec3.x;
                vParameter.y = -vec3.y;
                vParameter.z = -vec3.z;
                vParameter.w = 0.0;
                curParams.mDirection->setGpuParameter(vParameter.ptr(),3,1);

                // Update spotlight parameters.
                Real phi   = Math::Cos(srcLight->getSpotlightOuterAngle().valueRadians() * 0.5f);
                Real theta = Math::Cos(srcLight->getSpotlightInnerAngle().valueRadians() * 0.5f);
                
                vec3.x = 1 / srcLight->getAttenuationRange();
                vec3.y = phi;
                vec3.z = 1 / (theta - phi);

                curParams.mSpotParams->setGpuParameter(vec3);
            }
            break;
        }

        float lightIntensity = 1;
        if (curParams.mType == Light::LT_SPOTLIGHT)
        {
            lightIntensity = spotIntensity;
        }

        // Update diffuse colour.
        colour = srcLight->getDiffuseColour() * lightIntensity;
        if ((mTrackVertexColourType & TVC_DIFFUSE) == 0)
        {
            colour = colour * pass->getDiffuse();
        }
        curParams.mDiffuseColour->setGpuParameter(colour.ptr(),3,1);    

        // Update specular colour if need to.
        if  ((mSpecularEnable) && (curParams.mType == Light::LT_DIRECTIONAL))
        {
            // Update diffuse colour.
            colour = srcLight->getSpecularColour() * lightIntensity;
            if ((mTrackVertexColourType & TVC_SPECULAR) == 0)
            {
                colour = colour * pass->getSpecular();
            }
            curParams.mSpecularColour->setGpuParameter(colour.ptr(),3,1);       
        }                                                                           
    }

    if (mUseSegmentedLightTexture)
    {
        unsigned int indexStart = 0, indexEnd = 0;
        Ogre::Vector4 lightBounds; 
        SegmentedDynamicLightManager::getSingleton().getLightListRange(rend, lightBounds, indexStart, indexEnd);
        mPSLightTextureIndexLimit->setGpuParameter(Ogre::Vector2((Ogre::Real)indexStart, (Ogre::Real)indexEnd));
        mPSLightTextureLightBounds->setGpuParameter(lightBounds);

        Ogre::TextureUnitState* pLightTexture = pass->getTextureUnitState(mLightSamplerIndex);
        const Ogre::String& textureName = SegmentedDynamicLightManager::getSingleton().getSDLTextureName();
        if (textureName != pLightTexture->getTextureName())
        {
            pLightTexture->setTextureName(textureName, Ogre::TEX_TYPE_2D);
        }
    }
}
Пример #15
0
//  Update HUD
///---------------------------------------------------------------------------------------------------------------
void App::UpdateHUD(int carId, CarModel* pCarM, CAR* pCar, float time, Viewport* vp)
{
	if (bSizeHUD)
	{	bSizeHUD = false;  // split x num plr ?..
		SizeHUD(true);	}
		
	// show/hide for render viewport / gui viewport
	// first show everything
	ShowHUD(false);
	// now hide things we dont want
	if (!vp)
	{
		/// for gui viewport ----------------------
		if (hudGear)  hudGear->hide();		if (hudVel)  hudVel->hide();		if (ovBoost)  ovBoost->hide();
		if (ovTimes)  ovTimes->hide();		if (ovWarnWin)  ovWarnWin->hide();	if (ovOpp)  ovOpp->hide();
		if (ovCarDbg)  ovCarDbg->hide();	if (ovCarDbgTxt)  ovCarDbgTxt->hide();
	}else{
		/// for render viewport ---------
		if (ovCam)  ovCam->hide();
		if (mFpsOverlay)  mFpsOverlay->hide();
	}
	//*H*/LogO(String("car: ") + toStr(carId) +" "+ (!pCarM ? toStr(pCarM) : pCarM->sDirname) +" "+ (vp?"v+":"v-") +" "+ (pCar?"c+":"c-") +" "+ (pCarM?"m+":"m-"));
	if (!pCar)  return;  //-1 for ^above hiding in gui vp

			
	///  hud rpm,vel  --------------------------------
	if (pCar && !bRplPlay)  // for local cars only..
	{	fr.vel = pCar->GetSpeedometer();
		fr.rpm = pCar->GetEngineRPM();
		fr.gear = pCar->GetGear();
		fr.clutch = pCar->GetClutch();
		//fr.throttle = pCar->dynamics.GetEngine().GetThrottle();  // not on hud
	}

    float vel = fr.vel * (pSet->show_mph ? 2.23693629f : 3.6f);
    float rpm = fr.rpm;
	//*H*/LogO(String("car: ") + toStr(carId) + "  vel: "+ toStr(vel) +"  rpm: "+ toStr(rpm));
	UpdHUDRot(carId, pCarM, vel, rpm);


	///  update remote players  -----------
	if (carId == 0 && !pSet->mini_rotated && !pSet->mini_zoomed)  // the only fall that works
	for (int i=0; i < carModels.size(); ++i)
		if (carModels[i]->eType != CarModel::CT_LOCAL && carModels[i]->eType != CarModel::CT_REPLAY)
			UpdHUDRot(i, carModels[i], 0.f, 0.f, true);

	///  opponents list  ------------------
	if (ovOpp->isVisible() && pCarM && pCarM->pMainNode)
	{
		ColourValue c;  char ss[128];

		for (int o=0; o < carModels.size(); ++o)
		if (hudOpp[o][0])
		{
			const CarModel* cm = carModels[o];
			if (cm->eType != CarModel::CT_REPLAY && cm->pMainNode)
			{
				float rChks = road ? road->mChks.size() + 1 : 1.f,
					perc = 100.f * cm->iNumChks / rChks;
				
				//  get smooth % part
				if (rChks > 1.f && cm->eType != CarModel::CT_GHOST)
				{
					const Vector3& car = cm->pMainNode->getPosition(), next = road->mChks[cm->iNextChk].pos,
						start = cm->vStartPos, curr = road->mChks[std::max(0,cm->iCurChk)].pos;
					float dist01 = 0.f;
					//  start to 1st chk
					if (/*cm->iCurChk == -1 || */cm->iNumChks == 0)
					{
						Vector3 curDist = car - start;
						Vector3 chksDist = next - start;
						dist01 = (curDist.length() /*- road->mChks[cm->iNextChk].r*/)
								/ (chksDist.length() - road->mChks[cm->iNextChk].r);
					}
					//  last chk to finish
					else if (cm->iNumChks == road->mChks.size())
					{
						dist01 = 0.f;
						Vector3 curDist = start - car;
						Vector3 chksDist = curr - start;
						dist01 = 1.f - (curDist.length() /*- road->mChks[cm->iNextChk].r*/)
								/ (chksDist.length() - road->mChks[cm->iNextChk].r);
					}
					else  // between 2 checks
					{
						Vector3 curDist = car - next;  // car dist to next checkpoint
						Vector3 chksDist = curr - next;  // divide by cur and next checks distance

						dist01 = 1.f - (curDist.length() - road->mChks[cm->iNextChk].r)
								/ (chksDist.length() - road->mChks[cm->iCurChk].r);
					}
					
					float percD = std::min(1.f, std::max(0.f, dist01 ));  // clamp to 0..1

					perc += percD * 100.f / rChks;
				}

				if (o != carId)  // no dist to self
				{
					Vector3 v = carModels[o]->pMainNode->getPosition() - pCarM->pMainNode->getPosition();
					float dist = v.length();  // meters, mph:feet?
					//  dist m
					sprintf(ss, "%3.0fm", dist);		hudOpp[o][1]->setCaption(ss);
					Real h = std::min(60.f, dist) / 60.f;
					c.setHSB(0.5f - h * 0.4f, 1,1);		hudOpp[o][1]->setColour(c);
				}
				else  hudOpp[o][1]->setCaption("");
					
				if (cm->eType != CarModel::CT_GHOST)  // todo, save perc for ghost/replay ..
				{	//  percent %
					sprintf(ss, "%3.0f%%", perc);		hudOpp[o][0]->setCaption(ss);
					c.setHSB(perc*0.01f*0.4f, 0.7f,1);	hudOpp[o][0]->setColour(c);
				}
				else  hudOpp[o][0]->setCaption("");
				
				//  name once in CreateHUD
				hudOpp[o][2]->setColour(cm->color);
			}
		}
	}
	///------------------------------------


	///   Set motion blur intensity for this viewport, depending on car's linear velocity
	if (pSet->motionblur)
	{
		// use velocity squared to achieve an exponential motion blur - and its faster too - wow :)
		float speed = pCar->GetVelocity().MagnitudeSquared();
		
		// peak at 250 kmh (=69 m/s), 69² = 4761
		// motion blur slider: 1.0 = peak at 100 km/h
		// 					   0.0 = peak at 400 km/h
		//                  -> 0.5 = peak at 250 km/h
		// lerp(100, 400, 1-motionBlurIntensity)
		float peakSpeed = 100 + (1-pSet->motionblurintensity) * (400-100);
		float motionBlurAmount = std::abs(speed) / pow((peakSpeed/3.6f), 2);
		
		// higher fps = less perceived motion blur
		// time a frame will be still visible on screen:
		// each frame, 1-motionBlurAmount of the original image is lost
		// example (motionBlurAmount = 0.7):
		// frame 1: full img
		// frame 2: 0.7  * image
		// frame 3: 0.7² * image
		// frame 4: 0.7³ * image
		// portion of image visible after 'n' frames:
		// pow(motionBlurAmount, n);
		
		// example 1: 60 fps
		// 0.7³ image after 4 frames: 0.066 sec
		// example 2: 120 fps
		// 0.7³ image after 4 frames: 0.033 sec
		
		// now: need to achieve *same* time for both fps values
		// to do this, adjust motionBlurAmount
		// (1.0/fps) * pow(motionBlurAmount, n) == (1.0/fps2) * pow(motionBlurAmount2, n)
		// set n=4
		// motionBlurAmount_new = sqrt(sqrt((motionBlurAmount^4 * fpsReal/desiredFps))
		motionBlurAmount = sqrt(sqrt( pow(motionBlurAmount, 4) * ((1.0f/time) / 120.0f) ));
			
		// clamp to 0.9f
		motionBlurAmount = std::min(motionBlurAmount, 0.9f);
		
		motionBlurIntensity = motionBlurAmount;
	}
	/// -----------------------------------------------------------------------------------


	//  gear, vel texts  -----------------------------
	if (hudGear && hudVel && pCar)
	{
		char cg[132],sv[132];  cg[0]='1'; cg[1]=0; sv[1]=0;
		float cl = fr.clutch*0.8f + 0.2f;
		if (fr.gear == -1)
		{	cg[0]='R';  hudGear->setColour(ColourValue(0.3,1,1,cl));	}
		else if (fr.gear == 0)
		{	cg[0]='N';  hudGear->setColour(ColourValue(0.3,1,0.3,cl));	}
		else if (fr.gear > 0 && fr.gear < 8)
		{	cg[0]='0'+fr.gear;  hudGear->setColour(ColourValue(1,1-fr.gear*0.1,0.2,cl));	}

		sprintf(sv, "%3.0f", std::abs(vel));
		hudGear->setCaption(String(cg));
		hudVel->setCaption(String(sv));  int w = mWindow->getWidth();
		hudVel->setPosition(-0.055 + w/1600.f*0.045,-0.01);
		//hudVel->setPosition(-0.1 + (w-1024.f)/1600.f*0.07/*0.11*/,-0.01);

		float k = pCar->GetSpeedometer() * 3.6f * 0.0025f;	// vel clr
		#define m01(x)  std::min(1.0, std::max(0.0, (double) x))
		hudVel->setColour(ColourValue(m01(k*2), m01(0.5+k*1.5-k*k*2.5), m01(1+k*0.8-k*k*3.5)));
	}
	if (hudBoost && pCar && hudBoost->isVisible())
	{
		char sb[132];
		sprintf(sb, "%3.1f", pCar->dynamics.boostFuel);
		hudBoost->setCaption(String(sb));
	}
	
	//  abs, tcs on  --------
	if (hudAbs && hudTcs)
	{
		if (pCar)
		{
			if (pCar->GetABSEnabled())
			{	hudAbs->show();
				hudAbs->setColour(ColourValue(1,0.8,0.6, pCar->GetABSActive() ? 1 : 0.5));
			}else
				hudAbs->hide();

			if (pCar->GetTCSEnabled())
			{	hudTcs->show();
				hudTcs->setColour(ColourValue(0.7,0.9,1, pCar->GetTCSActive() ? 1 : 0.4));
			}else
				hudTcs->hide();
		}

		// hide on gui vp
		if (!vp) { hudAbs->hide(); hudTcs->hide(); }
	}
	
	//  times, score  --------
	if (pSet->show_times && pCar)
	{
		TIMER& tim = pGame->timer;	//car[playercarindex].
		tim.SetPlayerCarID(carId);
		s[0]=0;
		
		if (pCarM->bWrongChk || pSet->local_players > 1 && pCarM->iWonPlace > 0)
			ovWarnWin->show();  else  ovWarnWin->hide();  //ov
			
		if (pSet->local_players > 1)  // lap num for many
		{
			if (pCarM->iWonPlace > 0 && hudWonPlace)
			{	sprintf(s, String(TR("---  %d #{TBPlace}  ---")).c_str(), pCarM->iWonPlace );
				hudWonPlace->setCaption(s);  hudWonPlace->show();
				const static ColourValue clrPlace[4] = {
					ColourValue(0.4,1,0.2), ColourValue(1,1,0.3), ColourValue(1,0.7,0.2), ColourValue(1,0.5,0.2) };
				hudWonPlace->setColour(clrPlace[pCarM->iWonPlace-1]);
			}
			sprintf(s, String(TR("#{TBLap}  %d/%d")).c_str(), tim.GetCurrentLap(carId)+1, pSet->num_laps );
		}else
		{	if (!road)  // score on vdr track
			if (tim.GetIsDrifting(0))
				sprintf(s, String(TR("#{TBScore}  %3.0f+%2.0f")).c_str(), tim.GetDriftScore(0), tim.GetThisDriftScore(0) );
			else
				sprintf(s, String(TR("#{TBScore}  %3.0f")).c_str(), tim.GetDriftScore(0) );
		}		
		if (hudTimes)
			hudTimes->setCaption(String(s) +
				String(TR("\n#{TBTime} ")) + GetTimeString(tim.GetPlayerTime())+
				String(TR("\n#{TBLast} ")) + GetTimeString(tim.GetLastLap())+
				String(TR("\n#{TBBest} ")) + GetTimeString(tim.GetBestLap(pSet->trackreverse)) );
	}

	//-----------------------------------------------------------------------------------------------
	///  debug infos
	//-----------------------------------------------------------------------------------------------

	//  car debug text  --------
	static bool oldCarTxt = false;
	if (pCar && ovU[0])
	{
		if (pSet->car_dbgtxt)
		{	std::stringstream s1,s2,s3,s4;
			pCar->DebugPrint(s1, true, false, false, false);  ovU[0]->setCaption(s1.str());
			pCar->DebugPrint(s2, false, true, false, false);  ovU[1]->setCaption(s2.str());
			pCar->DebugPrint(s3, false, false, true, false);  ovU[2]->setCaption(s3.str());
			pCar->DebugPrint(s4, false, false, false, true);  ovU[3]->setCaption(s4.str());
		}else
		if (pSet->car_dbgtxt != oldCarTxt)
		{	ovU[0]->setCaption(""); ovU[1]->setCaption(""); ovU[2]->setCaption(""); ovU[3]->setCaption("");		}
	}
	oldCarTxt = pSet->car_dbgtxt;
	

	//  profiling times -
	if (pGame && pGame->profilingmode && ovU[3])
	{
		if (pSet->multi_thr != 1) //! this one is causing a crash sometimes with multithreading.. maybe need a mutex? i have no idea..
			ovU[3]->setCaption(pGame->strProfInfo);
		//if (newPosInfos.size() > 0)
		//ovU[3]->setCaption("carm: " + toStr(carModels.size()) + " newp: " + toStr((*newPosInfos.begin()).pos));
	}

	//  bullet profiling text  --------
	static bool oldBltTxt = false;
	if (ovU[1])
	{
		if (pSet->bltProfilerTxt)
			ovU[1]->setCaption(pGame->collision.bltProfiling);
		else
		if (pSet->bltProfilerTxt != oldBltTxt)
			ovU[1]->setCaption("");
	}
	oldBltTxt = pSet->bltProfilerTxt;

	
	//  wheels slide, susp bars  --------
	if (pSet->car_dbgbars && pCar)
	{
		const Real xp = 80, yp = -530, ln = 20, y4 = 104;
		static char ss[256];
		//const static char swh[4][6] = {"F^L<","F^R>","RvL<","RvR>"};
		for (int w=0; w < 4; ++w)
		if (ovL[3-w] && ovR[3-w] && ovS[3-w])
		{	
			float slide = /*-1.f*/0.f, sLong = 0.f, sLat = 0.f;
			float squeal = pCar->GetTireSquealAmount((WHEEL_POSITION)w, &slide, &sLong, &sLat);

			//MATHVECTOR <float,3> vwhVel = pCar->dynamics.GetWheelVelocity((WHEEL_POSITION)w);
			//float whVel = vwhVel.Magnitude() * 3.6f;

			/**  //  info
			sprintf(ss, "%s %6.3f %6.3f  %6.3f %6.3f\n", swh[w],
				sLong/4.f, sLat/3.f, slide, squeal);
			ColourValue clr;  clr.setHSB( slide/20.f, 0.8f, 1.f );  //clr.a = min(0.f, slide/2.f);
			ovL[3-w]->setCaption(String(ss));
			ovL[3-w]->setColour(clr);
			//ovL[3-w]->setPosition(0.f, 230 + w*22);
			/**/

			//  bar meters |
			float susp = pCar->dynamics.GetSuspension(WHEEL_POSITION(w)).GetDisplacementPercent();
			float slng = sLong/abs(sLong)*powf(abs(sLong),0.3f);  // slide*20.f

			ovR[3-w]->setPosition(slng * 14.f +xp, yp + w*ln);
			ovL[3-w]->setPosition(sLat * 14.f +xp, yp + w*ln +y4);
			ovS[3-w]->setPosition(susp * 70.f +xp, yp + w*ln -y4);
		}
		if (ovL[4])  ovL[4]->setPosition(xp, yp + -20 +y4+3);
		if (ovS[4])  ovS[4]->setPosition(xp + 70, yp + -20 -104-3);

		//ovR[3-w]->setCaption("|");  ovR[3-w]->setColour(ColourValue(0.6,1.0,0.7));
	}


	//  checkpoint warning  --------
	if (road && hudWarnChk && pCarM)
	{	/* checks info *
		if (ovU[0])
		//	"ghost:  "  + GetTimeString(ghost.GetTimeLength()) + "  "  + toStr(ghost.GetNumFrames()) + "\n" +
		//	"ghplay: " + GetTimeString(ghplay.GetTimeLength()) + "  " + toStr(ghplay.GetNumFrames()) + "\n" +
		{	sprintf(s, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
				"         st %d in%2d  |  cur%2d > next %d  |  Num %d / All %d  T= %4.2f"
			,pCarM->bInSt ? 1:0, pCarM->iInChk, pCarM->iCurChk, pCarM->iNextChk
			,pCarM->iNumChks, road->mChks.size(), pCarM->fChkTime);
			ovU[0]->setCaption(s);
		}	/**/

		if (pCarM->bWrongChk)
			pCarM->fChkTime = 2.f;  //par sec
		int show = pCarM->fChkTime > 0.f ? 1 : 0;
		if (show)  pCarM->fChkTime -= time;
		//if (show != pCarM->iChkWrong)  //-
		bool place = pSet->local_players > 1, won = pCarM->iWonPlace > 0;
			if (show)  {  hudWarnChk->show();  if (place && !won)  hudWonPlace->hide();  }
			else  {       hudWarnChk->hide();  if (place && won)  hudWonPlace->show();  }
		pCarM->iChkWrong = show;
	}


	//  tire params  --------
	#if 0
	if (ovU[0] && pCar)
	{
		String ss = "";
		ss += "--Lateral--\n";
		for (int a=0; a < pCar->dynamics.tire[0].transverse_parameters.size(); ++a)
			ss += "a" + toStr(a) + " " + toStr( (Real)pCar->dynamics.tire[0].transverse_parameters[a] ) + "\n";
			
		//s += "a" + toStr(pCar->dynamics.tire[0].sigma_hat alpha_hat) + "\n";
		//pCar->dynamics.tire[0].

		//std::vector <T> longitudinal_parameters;
		//std::vector <T> transverse_parameters;
		//std::vector <T> aligning_parameters;
		
		ovU[0]->setCaption(ss);
	}
	#endif

	//  input values
	/*if (pCar && pGame && pGame->profilingmode)
	{	const std::vector<float>& inp = pCar->dynamics.inputsCopy;
	if (ovU[2] && inp.size() == CARINPUT::ALL)
	{	sprintf(s, 
		" Throttle %5.2f\n Brake %5.2f\n Steer %5.2f\n"
		" Handbrake %5.2f\n Boost %5.2f\n Flip %5.2f\n"
		,inp[CARINPUT::THROTTLE], inp[CARINPUT::BRAKE], -inp[CARINPUT::STEER_LEFT]+inp[CARINPUT::STEER_RIGHT]
		,inp[CARINPUT::HANDBRAKE],inp[CARINPUT::BOOST], inp[CARINPUT::FLIP] );
		ovU[2]->setCaption(String(s));
	}	}/**/

    //update lap, place, race
	/*timer.GetStagingTimeLeft(), timer.GetPlayerCurrentLap(), race_laps, curplace.first, curplace.second,
		car.GetEngineRedline(), car.GetEngineRPMLimit(), car.GetSpeedometer(), settings->GetMPH(),
		debug_info1.str(), debug_info2.str(), debug_info3.str(), debug_info4.str(),/**/


	///  debug text  --------
	/** char s[256];  // wheel ray
	for (int i=0; i < 4; i++)
	{
		sprintf(s, "c %6.3f",
			pCar->GetWheelContact(WHEEL_POSITION(i)).GetDepth() - pCar->GetTireRadius(WHEEL_POSITION(i)));
		ovL[i]->setCaption(String(s));
	}
	/**/
	
	//  wheels ter mtr info
	#if 0
	//if (iBlendMaps > 0)
	{
		String ss = "";
		static char s_[512];

		for (int i=0; i<4; ++i)
		{
			int mtr = whTerMtr[i];
			TRACKSURFACE* tsu = pCar->dynamics.terSurf[mtr];
			mtr = std::max(0, std::min( (int)(sc.td.layers.size())-1, mtr-1));
			TerLayer& lay = mtr == 0 ? sc.td.layerRoad : sc.td.layersAll[sc.td.layers[mtr]];

			sprintf(s_,  //"c %6.2f  "
				"R%d t%d  %s  [%s]  %s  \n"
				"  %4.0f  fr %4.2f / %4.2f  ba %4.2f  bw %4.2f \n"
				//"  d %4.2f m %4.2f ds %3.1f"	//". r%4.2f g%4.2f b%4.2f a%3.1f \n"
				//,pCar->dynamics.GetWheelContact(WHEEL_POSITION(i)).GetDepth() - 2*pCar->GetTireRadius(WHEEL_POSITION(i))
				,pCar->dynamics.bWhOnRoad[i], mtr, /*whOnRoad[i]?1:0,*/ lay.texFile.c_str()
				,tsu ? tsu->name.c_str() : "-", tsu ? csTRKsurf[tsu->type] : "-"
				,tsu ? tsu->rollingDrag : 0
				,tsu ? tsu->frictionTread : 0	,tsu ? tsu->frictionNonTread : 0
				,tsu ? tsu->bumpAmplitude : 0	,tsu ? tsu->bumpWaveLength : 0
				//,lay.dust, lay.mud, lay.dustS	//,lay.tclr.r, lay.tclr.g, lay.tclr.b, lay.tclr.a
				//,pCar->dynamics.wheel_contact[i].depth, pCar->dynamics.wheel_contact[i].col
				);
			ss += String(s_);
		}

		//  surfaces  info
		/*ss += "\n";
		for (int i=0; i < pGame->track.tracksurfaces.size(); ++i)
			ss += String(pGame->track.tracksurfaces[i].name.c_str()) + "\n";/**/

		//ovCarDbg->show();
		if (ovS[4])  {  //ovL[4]->setTop(400);
			ovS[4]->setColour(ColourValue::Black);
			ovS[4]->setCaption(ss);  }
	}
	#endif
}
Пример #16
0
bool FluidsXml::LoadXml(std::string file, std::map <std::string, int>* surf_map)
{
	XMLDocument doc;
	XMLError e = doc.LoadFile(file.c_str());
	if (e != XML_SUCCESS)  return false;
		
	XMLElement* root = doc.RootElement();
	if (!root)  return false;

	//  clear
	//Default();
	fls.clear();  flMap.clear();

	///  fluids
	const char* a;  int i=1;  //0 = none
	XMLElement* eFl = root->FirstChildElement("fluid");
	while (eFl)
	{
		FluidParams fp;
		a = eFl->Attribute("name");			if (a)  fp.name = std::string(a);
		a = eFl->Attribute("material");		if (a)  fp.material = std::string(a);
		//  car buoyancy
		a = eFl->Attribute("density");		if (a)  fp.density = s2r(a);
		a = eFl->Attribute("angDamp");		if (a)  fp.angularDrag = s2r(a);
		a = eFl->Attribute("linDamp");		if (a)  fp.linearDrag = s2r(a);
		a = eFl->Attribute("heightDamp");	if (a)  fp.heightVelRes = s2r(a);

		//  wheel
		a = eFl->Attribute("bWhForce");		if (a)  fp.bWhForce = s2i(a) > 0;
		a = eFl->Attribute("whMaxAngVel");	if (a)  fp.whMaxAngVel = s2r(a);

		a = eFl->Attribute("whSpinDamp");	if (a)  fp.whSpinDamp = s2r(a);
		a = eFl->Attribute("whForceLong");	if (a)  fp.whForceLong = s2r(a);
		a = eFl->Attribute("whForceUp");	if (a)  fp.whForceUp = s2r(a);
		a = eFl->Attribute("whSteerMul");	if (a)  fp.whSteerMul = s2r(a);

		a = eFl->Attribute("bumpFqX");		if (a)  fp.bumpFqX = s2r(a);
		a = eFl->Attribute("bumpFqY");		if (a)  fp.bumpFqY = s2r(a);
		a = eFl->Attribute("bumpAmp");		if (a)  fp.bumpAmp = s2r(a);
		a = eFl->Attribute("bumpAngle");	if (a)  fp.bumpAng = s2r(a);
		
		a = eFl->Attribute("idParticles");	if (a)  fp.idParticles = s2i(a);
		a = eFl->Attribute("fDamage");		if (a)  fp.fDamage = s2r(a);

		a = eFl->Attribute("solid");		if (a)  fp.solid = s2i(a) > 0;
		a = eFl->Attribute("deep");			if (a)  fp.deep = s2i(a) > 0;
		a = eFl->Attribute("surf");
		if (a)
		{	std::string s(a);
			int id = surf_map ? (*surf_map)[s]-1 : -1;
			if (id == -1)
			{	id = 4;  // default if not found
				#ifndef SR_EDITOR
				LogO("! Warning: Surface not found: "+s+" for (solid) fluid: "+fp.name);
				#endif
			}
			fp.surf = id;
		}

		//  fluid fog
		a = eFl->Attribute("fogDens");	if (a)  fp.fog.dens = s2r(a);
		a = eFl->Attribute("fogDensH");	if (a)  fp.fog.densH = s2r(a);
		a = eFl->Attribute("fogRGBA");
		if (a)
		{	Vector4 v = s2v4(a);
			fp.fog.r = v.x;  fp.fog.g = v.y;  fp.fog.b = v.z;  fp.fog.a = v.w;
		}
		a = eFl->Attribute("fogHSVA");
		if (a)
		{	Vector4 v = s2v4(a);
			ColourValue c;  c.setHSB(v.x, v.y, v.z);
			fp.fog.r = c.r;  fp.fog.g = c.g;  fp.fog.b = c.b;  fp.fog.a = v.w;
		}
		//

		fls.push_back(fp);
		flMap[fp.name] = i++;
		eFl = eFl->NextSiblingElement("fluid");
	}
	return true;
}
Пример #17
0
	//! copies this surface into another, using the alpha mask, a cliprect and a color to add with
	void CImage::copyToWithAlpha(IImage* target, const Vector2& pos, const rect<SINT32>& sourceRect, const ColourValue &color, const rect<SINT32>* clipRect)
	{
		// color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF
		Blit(color.getAsARGB() == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND : BLITTER_TEXTURE_ALPHA_COLOR_BLEND,
			target, clipRect, &pos, this, &sourceRect, color.getAsARGB());
	}