1 #include "pch.h"
2 #include "Def_Str.h"
3 #include "Gui_Def.h"
4 #include "GuiCom.h"
5 #include "../../road/Road.h"
6 #include "../../vdrift/pathmanager.h"
7 #include "data/SceneXml.h"
8 #include "data/TracksXml.h"
9 #include "data/CData.h"
10 #include "CScene.h"
11 #ifndef SR_EDITOR
12 	#include "../../vdrift/game.h"
13 	#include "../CGame.h"
14 	#include "../CHud.h"
15 	#include "../CGui.h"
16 	#include "../SplitScreen.h"
17 #else
18 	#include "../../editor/CApp.h"
19 	#include "../../editor/CGui.h"
20 	#include "../../editor/settings.h"
21 #endif
22 #include "MultiList2.h"
23 #include <OgreRoot.h>
24 #include <OgreMaterialManager.h>
25 #include <OgreSceneManager.h>
26 #include <OgreTerrain.h>
27 #include <OgreRenderWindow.h>
28 #include <MyGUI.h>
29 //#include <MyGUI_Delegate.h>
30 //#include <MyGUI_Widget.h>
31 //#include <MyGUI_EditBox.h>
32 //#include <MyGUI_ImageBox.h>
33 //#include <MyGUI_Gui.h>
34 //#include <MyGUI_Window.h>
35 //#include <MyGUI_TabItem.h>
36 using namespace MyGUI;
37 using namespace Ogre;
38 using namespace std;
39 
40 
41 ///  * * * *  CONST  * * * *
42 //-----------------------------------------------------------------------------------------------------------
43 
44 //  track difficulties colors from value
45 const String CGuiCom::clrsDiff[9] =  // difficulty
46 	{"#60C0FF", "#00FF00", "#60FF00", "#C0FF00", "#FFFF00", "#FFC000", "#FF6000", "#FF4040", "#FF7090"};
47 const String CGuiCom::clrsRating[6] =  // rating
48 	{"#808080", "#606060", "#7090A0", "#60C8D8", "#A0D0F0", "#E0F0FF"};
49 const String CGuiCom::clrsLong[10] =  // long
50 	{"#E0D0D0", "#E8C0C0", "#F0B0B0", "#F8A0A0", "#FF9090", "#FF8080", "#F07070", "#F06060", "#E04040", "#D03030"};
51 
52 
53 //  * * * *  CONST  * * * *
54 //  column widths in MultiList2,  track detailed
55 const int wi = 17;            // id name nm   N  scn ver
56 const int CGuiCom::colTrk[32] = {40, 90, 80, 25, 70, 25, wi, wi, wi, wi, wi, wi, wi, wi, wi, wi, wi, wi, 24};
57 #ifndef SR_EDITOR
58 const int CGui::colCar[16] = {34, 27, 37, 52, 24};  // car
59 const int CGui::colCh [16] = {16, 200, 120, 50, 80, 80, 60, 40};  // champs
60 const int CGui::colChL[16] = {16, 180, 90, 100, 50, 60, 60, 60, 50};  // challs
61 const int CGui::colSt [16] = {30, 170, 100, 90, 50, 80, 70};  // stages
62 #endif
63 
64 //  get scenery color string from track name
GetSceneryColor(String name,String * sc)65 String CGuiCom::GetSceneryColor(String name, String* sc)
66 {
67 	if (name.length() < 3)  return "#707070";
68 
69 	int id = app->scn->data->tracks->trkmap[name];
70 	const TrackInfo* pTrk = id==0 ? 0 : &app->scn->data->tracks->trks[id-1];
71 
72 	char ch = name.c_str()[0];  // vdr
73 	if (ch == 'T' && name.c_str()[1] == 'e')  // Test,TestC
74 		return (name.length() > 5 && name.c_str()[4] == 'C') ? "#A0C0D0" : "#A0A0A0";
75 	else
76 	if (pTrk)
77 	{	//if (sc)  *sc = pTrk->scenery;
78 		return scnClr[pTrk->scenery];
79 	}
80 	else  // user *
81 	{
82 		if (name.c_str()[0]=='*')
83 			name = name.substr(1);
84 		String ss;
85 		size_t p = name.find_first_of("-0123456789");
86 		if (p != string::npos)
87 		{	ss = name.substr(0, p);  //LogO(ss);
88 			String s1 = scnN[ss];  if (sc)  *sc = s1;
89 			return scnClr[s1];
90 		}else
91 		{	ss += name.c_str()[0];
92 			String s1 = scnN[ss];  if (sc)  *sc = s1;
93 			return scnClr[s1];
94 	}	}
95 }
96 //-----------------------------------------------------------------------------------------------------------
97 
98 
99 //  Add tracks list item
AddTrkL(std::string name,int user,const TrackInfo * ti)100 void CGuiCom::AddTrkL(std::string name, int user, const TrackInfo* ti)
101 {
102 	String sc, c = GetSceneryColor(name, &sc);
103 	Mli2 li = trkList;
104 
105 	//  split -
106 	string pre, shrt;
107 	size_t p = name.find("-");  // Test
108 	if (p != string::npos /*&& !(name[0]=='T' && name[1]=='e')*/)
109 	{
110 		pre = name.substr(0,p);
111 		shrt = name.substr(p+1);  // short name
112 	}else
113 	{	pre = name;  shrt = name;  }
114 
115 	//  add  name = prefix-short
116 	li->addItem(c+ pre, 0);
117 	int l = li->getItemCount()-1;
118 	li->setSubItemNameAt(1,l, c+ name);
119 	li->setSubItemNameAt(2,l, c+ shrt);
120 
121 	if (!ti)  //  user (or new) trks
122 	{	if (!sc.empty())
123 			li->setSubItemNameAt(4,l, c+ TR("#{SC_"+sc+"}"));
124 		return;
125 	}
126 	//  details
127 	li->setSubItemNameAt(3,l, c+ toStr(ti->n/10)+toStr(ti->n%10));
128 	li->setSubItemNameAt(4,l, c+ TR("#{SC_"+ti->scenery+"}"));
129 	li->setSubItemNameAt(5,l, c+ fToStr(ti->crtver,1,3));
130 
131 	//list->setSubItemNameAt(4,l, ti->created);  list->setSubItemNameAt(5,l, ti->modified);
132 	#define toS(clr,v)  (v > 0) ? (String(clr)+"  "+toStr(v)) : " "
133 	li->setSubItemNameAt(6,l, toS(clrsDiff[ti->diff], ti->diff));
134 	li->setSubItemNameAt(7,l, toS(clrsRating[ti->rating], ti->rating));
135 
136 	//todo: rateuser drivenlaps
137 	li->setSubItemNameAt(8,l, toS("#D070A0",ti->objects));
138 	li->setSubItemNameAt(9,l, toS("#C09060",ti->obstacles));
139 	li->setSubItemNameAt(10,l,toS("#80C0FF",ti->fluids));
140 	li->setSubItemNameAt(11,l,toS("#40FF00",ti->bumps));
141 	li->setSubItemNameAt(12,l,toS("#FFA030",ti->jumps));
142 	li->setSubItemNameAt(13,l,toS("#00FFFF",ti->loops));
143 	li->setSubItemNameAt(14,l,toS("#FFFF00",ti->pipes));
144 	li->setSubItemNameAt(15,l,toS("#C0C0C0",ti->banked));
145 	li->setSubItemNameAt(16,l,toS("#C080FF",ti->frenzy));
146 	li->setSubItemNameAt(17,l,toS(clrsLong[ti->longn], ti->longn));
147 	//li->setSubItemNameAt(18,l,clrsDiff[std::min(8, 5*ti->sum/10)]+" "+toStr(ti->sum));
148 }
149 
150 
initMiniPos(int i)151 void CGuiCom::initMiniPos(int i)
152 {
153 	imgMiniPos[i] = fImg(i==0 ? "TrackPos" : "TrackPos2");
154 	imgMiniRot[i] = imgMiniPos[i]->getSubWidgetMain()->castType<RotatingSkin>();
155 	IntSize si = imgMiniPos[i]->getSize();
156 	imgMiniRot[i]->setCenter(IntPoint(si.width*0.7f, si.height*0.7f));  //0.5?
157 }
158 
159 
160 //  Gui Init [Track] once
161 //-----------------------------------------------------------------------------------------------------------
GuiInitTrack()162 void CGuiCom::GuiInitTrack()
163 {
164 	Tbi trktab = fTbi("TabTrack");
165 	Mli2 li = trktab->createWidget<MultiList2>("MultiListBox",0,0,500,300, Align::Left | Align::VStretch);
166 	li->setColour(Colour(0.8,0.9,0.8));  li->setInheritsAlpha(false);
167 	trkList = li;
168    	li->eventListChangePosition += newDelegate(this, &CGuiCom::listTrackChng);
169    	li->setVisible(false);
170 
171 	//  preview images
172 	imgPrv[0] = fImg("TrackImg");   imgPrv[0]->setImageTexture("PrvView");
173 	imgTer[0] = fImg("TrkTerImg");  imgTer[0]->setImageTexture("PrvTer");
174 	imgMini[0] = fImg("TrackMap");  imgMini[0]->setImageTexture("PrvRoad");
175 	initMiniPos(0);
176 
177 	//  stats text
178 	int i, st;
179 	#ifdef SR_EDITOR
180 	st = 9;
181 	#else
182 	st = StTrk;
183 	#endif
184 	for (i=0; i < st; ++i)   stTrk[0][i] = fTxt("st"+toStr(i));
185 	for (i=0; i < 4; ++i)  imStTrk[0][i] = fImg("ist"+toStr(i));
186 	for (i=0; i < InfTrk; ++i){  infTrk[0][i] = fTxt("ti"+toStr(i));  imInfTrk[0][i] =  fImg("iti"+toStr(i));  }
187 
188 	EdC(edTrkFind, "TrkFind", editTrkFind);
189 
190 	ButtonPtr btn;
191 	BtnC("TrkView1", btnTrkView1);  imgTrkIco1 = fImg("TrkView2icons1");
192 	BtnC("TrkView2", btnTrkView2);  imgTrkIco2 = fImg("TrkView2icons2");
193 	BtnC("TrkFilter", btnTrkFilter);
194 	SV* sv;  Ck* ck;
195 	ck= &ckTrkFilter;  ck->Init("TracksFilter", &pSet->tracks_filter);  CevC(TrkFilter);
196 	txtTracksFAll = fTxt("TracksFAll");
197 	txtTracksFCur = fTxt("TracksFCur");
198 
199 	//  columns  ----
200 	li->removeAllColumns();  int c=0;
201 	li->addColumn("#C0E0C0""id", colTrk[c++]);  // prefix
202 	li->addColumn("#D0FFD0"+TR("#{Name}"), colTrk[c++]);  // full
203 	li->addColumn("#E0FFE0"+TR("#{Name}"), colTrk[c++]);  // short
204 
205 	li->addColumn("#80FF80""N", colTrk[c++]);
206 	li->addColumn("#80FFC0"+TR("#{Scenery}"), colTrk[c++]);
207 	li->addColumn("#80FF80""ver", colTrk[c++]);  // created- modified-
208 
209 	li->addColumn("#C0D0FF""diff", colTrk[c++]);  //todo: rateuser, drivenlaps ..
210 	li->addColumn("#C0E0FF""*", colTrk[c++]);   // rating
211 
212 	li->addColumn("#FF80C0""o", colTrk[c++]);   // objects
213 	li->addColumn("#C09060""c", colTrk[c++]);   // obstacles
214 	li->addColumn("#80C0FF""f", colTrk[c++]);   //  fluids
215 	li->addColumn("#40FF00""B", colTrk[c++]);   //  Bumps
216 	li->addColumn("#FFA030""J", colTrk[c++]);   // Jumps
217 	li->addColumn("#00FFFF""L", colTrk[c++]);   // Loops
218 	li->addColumn("#FFFF00""P", colTrk[c++]);   // Pipes
219 	li->addColumn("#C0C0C0""b", colTrk[c++]);   //  banked
220 	li->addColumn("#C080FF""f", colTrk[c++]);   //  frenzy
221 	li->addColumn("#FFA0A0""l", colTrk[c++]);	// longn
222 	//li->addColumn("#9060FF""E", colTrk[c++]);	// sigma
223 	li->addColumn(" ", colTrk[c++]);
224 
225 	//  columns, filters  ---
226 	for (i=0; i < COL_VIS; ++i)
227 	{
228 		ck= &ckTrkColVis[i];  ck->Init("col"+toStr(i), &pSet->col_vis[pSet->tracks_view][i]);  CevC(TrkColVis);
229 	}
230 	//ChkUpd_Col();
231 	for (i=0; i < COL_FIL; ++i)
232 	{	string si = toStr(i);
233 		int a = pSet->colFil[0][i], b = pSet->colFil[1][i];
234 		sv= &svTrkFilMin[i];  sv->Init("min"+si, &pSet->col_fil[0][i], a,b);  sv->DefaultI(a);  SevC(TrkFil);
235 		sv= &svTrkFilMax[i];  sv->Init("max"+si, &pSet->col_fil[1][i], a,b);  sv->DefaultI(b);  SevC(TrkFil);
236 	}
237 
238 	FillTrackLists();  //once
239 
240 	li->mSortColumnIndex = pSet->tracks_sort;
241 	li->mSortUp = pSet->tracks_sortup;
242 
243     TrackListUpd(true);  //upd
244 	listTrackChng(trkList,0);  //-
245 
246 	ChangeTrackView();
247 }
248 
ChkUpd_Col()249 void CGuiCom::ChkUpd_Col()
250 {
251 	for (int i=0; i < COL_VIS; ++i)
252 		ckTrkColVis[i].Upd(&pSet->col_vis[pSet->tracks_view][i]);
253 }
254 
255 
256 //  done once to fill tracks list from dirs
257 //-----------------------------------------------------------------------------------------------------------
FillTrackLists()258 void CGuiCom::FillTrackLists()
259 {
260 	liTracks.clear();  liTracksUser.clear();
261 	std::string chkfile = "/scene.xml";
262 
263 	PATHMANAGER::DirList(pathTrk[0], liTracks);
264 	PATHMANAGER::DirList(pathTrk[1], liTracksUser);  //name duplicates
265 	if (liTracks.size() == 0)
266 		LogO("Error: NO tracks !!!  in data/tracks/  crashing.");
267 
268 	//  original
269 	strlist::iterator i;
270 	i = liTracks.begin();
271 	while (i != liTracks.end())
272 	{
273 		std::string s = pathTrk[0] + *i + chkfile;
274 		if (!PATHMANAGER::FileExists(s))
275 			i = liTracks.erase(i);
276 		else  ++i;
277 	}
278 	//  user
279 	i = liTracksUser.begin();
280 	while (i != liTracksUser.end())
281 	{
282 		std::string s = pathTrk[1] + *i + chkfile;
283 		if (!PATHMANAGER::FileExists(s))
284 			i = liTracksUser.erase(i);
285 		else  ++i;
286 	}
287 
288 	//  get info for track name, from data->tracks
289 	liTrk.clear();
290 	for (strlist::iterator i = liTracks.begin(); i != liTracks.end(); ++i)
291 	{
292 		TrkL trl;  trl.name = *i;  //trl.pA = this;
293 		int id = app->scn->data->tracks->trkmap[*i];
294 		const TrackInfo* pTrk = id==0 ? 0 : &app->scn->data->tracks->trks[id-1];
295 		trl.ti = pTrk;  // 0 if not in data->tracks
296 		liTrk.push_back(trl);
297 	}
298 }
299 
300 
301 ///  . .  util tracks stats  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
302 //----------------------------------------------------------------------------------------------------------------
303 
ReadTrkStats()304 void CGuiCom::ReadTrkStats()
305 {
306 	String sRd = PathListTrk() + "/road.xml";
307 	String sSc = PathListTrk() + "/scene.xml";
308 
309 	Scene* sc = new Scene();  sc->LoadXml(sSc);  // fails to defaults
310 #ifndef SR_EDITOR  // game
311 	SplineRoad rd(app->pGame);  rd.LoadFile(sRd,false);  // load
312 
313 	TIMER tim;  tim.Load(PATHMANAGER::Records()+"/"+ pSet->gui.sim_mode+"/"+ sListTrack+".txt", 0.f);
314 	tim.AddCar(app->gui->sListCar);
315 
316 	bool reverse = sc->denyReversed ? false : pSet->gui.trackreverse;
317 	app->gui->ckReverse.setVisible(!sc->denyReversed);  //
318 	UpdGuiRdStats(&rd,sc, sListTrack, tim.GetBestLap(0, reverse), reverse, 0);
319 #else
320 	SplineRoad rd(app);  rd.LoadFile(sRd,false);  // load
321 	UpdGuiRdStats(&rd,sc, sListTrack, 0.f, false, 0);
322 #endif
323 	delete sc;
324 }
325 
326 #ifndef SR_EDITOR  // game
ReadTrkStatsChamp(String track,bool reverse)327 void CGui::ReadTrkStatsChamp(String track, bool reverse)
328 {
329 	String sRd = gcom->pathTrk[0] + track + "/road.xml";
330 	String sSc = gcom->pathTrk[0] + track + "/scene.xml";
331 
332 	Scene* sc = new Scene();  sc->LoadXml(sSc);  // fails to defaults
333 	SplineRoad rd(pGame);  rd.LoadFile(sRd,false);  // load
334 
335 	TIMER tim;  tim.Load(PATHMANAGER::Records()+"/"+ pSet->gui.sim_mode+"/"+ track+".txt", 0.f);
336 	tim.AddCar(sListCar);
337 
338 	gcom->UpdGuiRdStats(&rd,sc, track, tim.GetBestLap(0, reverse), reverse, 1);
339 }
340 #endif
341 
342 
343 #ifndef SR_EDITOR  // game
TrkDir()344 String CGuiCom::TrkDir() {
345 	int u = pSet->game.track_user ? 1 : 0;		return pathTrk[u] + pSet->game.track + "/";  }
346 #else
TrkDir()347 String CGuiCom::TrkDir() {
348 	int u = pSet->gui.track_user ? 1 : 0;		return pathTrk[u] + pSet->gui.track + "/";  }
349 #endif
350 
PathListTrk(int user)351 String CGuiCom::PathListTrk(int user) {
352 	int u = user == -1 ? bListTrackU : user;	return pathTrk[u] + sListTrack;  }
353 
PathListTrkPrv(int user,String track)354 String CGuiCom::PathListTrkPrv(int user, String track) {
355 	int u = user == -1 ? bListTrackU : user;	return pathTrk[u] + track + "/preview/";  }
356 
357 
TrackExists(String name)358 bool CGuiCom::TrackExists(String name/*, bool user*/)
359 {
360 	// ignore letters case..
361 	for (strlist::const_iterator it = liTracks.begin(); it != liTracks.end(); ++it)
362 		if (*it == name)  return true;
363 	for (strlist::const_iterator it = liTracksUser.begin(); it != liTracksUser.end(); ++it)
364 		if (*it == name)  return true;
365 	return false;
366 }
367 
368 
UpdGuiRdStats(const SplineRoad * rd,const Scene * sc,const String & sTrack,float timeCur,bool reverse,int ch)369 void CGuiCom::UpdGuiRdStats(const SplineRoad* rd, const Scene* sc, const String& sTrack,
370 	float timeCur, bool reverse, int ch)
371 {
372 	#ifndef SR_EDITOR  // game
373 	bool mph = pSet->show_mph;
374 	#else
375 	bool mph = false;
376 	#endif
377 	float m = mph ? 0.621371f : 1.f;
378 	String km = mph ? TR(" #{UnitMi}") : TR(" #{UnitKm}");
379 	String sm = TR(" #{UnitM}");
380 
381 	//  road stats
382 	//---------------------------------------------------------------------------
383 	stTrk[ch][1]->setCaption(fToStr(sc->td.fTerWorldSize*0.001f*m ,1,3) + km);
384 	if (!rd)  return;
385 	float len = rd->st.Length;					//3,5
386 	stTrk[ch][0]->setCaption(fToStr(len*0.001f*m ,1,3) + km);
387 
388 	stTrk[ch][2]->setCaption(fToStr(rd->st.WidthAvg ,1,3) + sm);
389 	stTrk[ch][3]->setCaption(fToStr(rd->st.HeightDiff ,0,2) + sm);
390 
391 	bool h = rd->st.Pipes > 99.f && rd->st.OnTer > 99.f;  // hide bridge 100% when pipe is 100%
392 	float a;
393 	stTrk[ch][4]->setCaption(fToStr(rd->st.OnTer ,0,1)/*+"%"*/);
394 	a = h || rd->st.OnTer < 1.f ? 0.f :  (0.5f + 0.5f * rd->st.OnTer / 100.f);
395 	stTrk[ch][4]->setAlpha(a);  imStTrk[ch][0]->setAlpha(a);
396 
397 	stTrk[ch][5]->setCaption(fToStr(rd->st.Pipes ,0,1)/*+"%"*/);
398 	a =      rd->st.Pipes < 1.f ? 0.f :  (0.4f + 0.4f * rd->st.Pipes / 100.f);
399 	stTrk[ch][5]->setAlpha(a);  imStTrk[ch][1]->setAlpha(a);
400 
401 	stTrk[ch][6]->setCaption(fToStr(rd->st.bankAvg,0,1)+"\'");
402 	stTrk[ch][7]->setCaption(fToStr(rd->st.bankMax,0,1)+"\'");
403 	a = std::min(1.f,  0.3f + 0.7f * rd->st.bankMax / 80.f);  //rd->st.bankAvg / 30.f);
404 	stTrk[ch][6]->setAlpha(a);  stTrk[ch][7]->setAlpha(a);  imStTrk[ch][2]->setAlpha(a);
405 
406 	stTrk[ch][8]->setCaption(fToStr(rd->st.OnPipe,0,1)/*+"%"*/);
407 	a = rd->st.OnPipe < 0.1f ? 0.f : (0.5f + 0.5f * rd->st.OnPipe / 100.f);
408 	stTrk[ch][8]->setAlpha(a);  imStTrk[ch][3]->setAlpha(a);
409 
410 	#ifndef SR_EDITOR
411 	if (app->gui->txTrackAuthor)
412 		app->gui->txTrackAuthor->setCaption("");  // user trks
413 	#endif
414 
415 	int id = app->scn->data->tracks->trkmap[sTrack];
416 	for (int i=0; i < InfTrk; ++i)
417 		if (infTrk[ch][i])  infTrk[ch][i]->setCaption("");
418 	if (id > 0)
419 	{	const TrackInfo& ti = app->scn->data->tracks->trks[id-1];
420 
421 		#define str0(v)  ((v)==0 ? "" : toStr(v))
422 		#define inf(i,t,m)  infTrk[ch][i]->setCaption(str0(t));\
423 			imInfTrk[ch][i]->setAlpha(t==0 ? 0.f : std::min(1.f, 0.2f + 0.8f * float(t)/m))
424 
425 		inf(0, ti.fluids,5);  inf(1, ti.bumps, 4);
426 		inf(2, ti.jumps, 3);  inf(3, ti.loops, 4);  inf(4, ti.pipes, 5);
427 		inf(5, ti.banked,4);  inf(6, ti.frenzy,4);
428 		inf(7, ti.obstacles,3);  inf(8, ti.objects,3);
429 
430 		infTrk[ch][11]->setCaption(clrsLong[ti.longn] + str0(ti.longn));
431 		a = ti.longn / 9.f;
432 		imInfTrk[ch][11]->setAlpha(a);  infTrk[ch][11]->setAlpha(0.5f + 0.5f * a);
433 		  infTrk[ch][9]->setCaption(ti.diff==0   ? "" : (clrsDiff[ti.diff] + toStr(ti.diff)));
434 		imInfTrk[ch][9]->setAlpha(0.2f + 0.8f * ti.diff / 6.f);
435 		  infTrk[ch][10]->setCaption(ti.rating==0 ? "" : (clrsRating[ti.rating] + toStr(ti.rating)));
436 		imInfTrk[ch][10]->setAlpha(0.2f + 0.8f * ti.rating / 5.f);
437 
438 		#ifndef SR_EDITOR
439 		if (app->gui->txTrackAuthor)
440 			app->gui->txTrackAuthor->setCaption(ti.author=="CH" ? "CryHam" : ti.author);
441 		#endif
442 	}
443 
444 #ifndef SR_EDITOR  // game
445 	//  best time, avg vel
446 	std::string unit = mph ? TR(" #{UnitMph}") : TR(" #{UnitKmh}");
447 	m = pSet->show_mph ? 2.23693629f : 3.6f;
448 
449 	//  track time
450 	float carMul = app->GetCarTimeMul(pSet->gui.car[0], pSet->gui.sim_mode);
451 	float timeTrk = app->scn->data->tracks->times[sTrack];
452 	bool noTrk = timeTrk < 2.f;
453 	std::string speedTrk = fToStr(len / timeTrk * m, 0,3) + unit;
454 	float timeT = (/*place*/1 * app->scn->data->cars->magic * timeTrk + timeTrk) / carMul;
455 	bool no = timeCur < 0.1f || !rd;
456 	if (ch==1)  no = false;  // show track's not current
457 
458 	stTrk[ch][9]->setCaption(StrTime(noTrk ? 0.f : timeT));
459 	stTrk[ch][10]->setCaption(noTrk ? "--" : speedTrk);
460 
461 	if (ch==0)
462 	if (no)
463 	{	stTrk[ch][11]->setCaption(StrTime(0.f));
464 		stTrk[ch][12]->setCaption("--");
465 		stTrk[ch][13]->setCaption("--");
466 	}else
467 	{	//  car record
468 		std::string speed = fToStr(len / timeCur * m, 0,3) + unit;
469 		stTrk[ch][11]->setCaption(StrTime(timeCur));
470 		stTrk[ch][12]->setCaption(speed);
471 		//  points
472 		float points = 0.f;
473 		app->GetRacePos(timeCur, timeTrk, carMul, false, &points);
474 		stTrk[ch][13]->setCaption(fToStr(points ,1,3));
475 	}
476 #else
477 	if (app->gui->trkName)  //
478 		app->gui->trkName->setCaption(sTrack.c_str());
479 #endif
480 	if (trkDesc[ch])  // desc
481 		trkDesc[ch]->setCaption(rd->sTxtDesc.c_str());
482 
483 
484 	//  preview images
485 	//---------------------------------------------------------------------------
486 #ifndef SR_EDITOR
487 	if (pSet->dev_no_prvs)  return;
488 	bool any = pSet->inMenu == MNU_Tutorial || pSet->inMenu == MNU_Champ || pSet->inMenu == MNU_Challenge;
489 #else
490 	bool any = false;
491 #endif
492 	String path = PathListTrkPrv(any ? 0 : -1, sTrack);
493 
494 	app->prvView.Load(path+"view.jpg");
495 	app->prvRoad.Load(path+"road.png");
496 	app->prvTer.Load(path+"terrain.jpg");
497 
498 
499 	//  start pos on minimap
500 	//---------------------------------------------------------------------------
501 	float t = sc->td.fTerWorldSize,
502 		xp = sc->startPos[1]/t, yp = sc->startPos[0]/t;
503 	const IntSize& si = imgTer[ch]->getSize(), st = imgMiniPos[ch]->getSize();
504 	int x = (xp + 0.5f) * si.width  - st.width *0.5f,
505 		y = (yp + 0.5f) * si.height - st.height*0.5f;
506 	imgMiniPos[ch]->setPosition(IntPoint(x,y));
507 
508 	//  rot
509 	const float* rot = &sc->startRot[0];
510 	Quaternion q(rot[0],rot[1],rot[2],rot[3]);
511 	a = q.getPitch().valueRadians();
512 	if (reverse)  a += PI_d;
513 	//static float a=0.f; a+=0.1f;  //test center
514 	imgMiniRot[ch]->setAngle(a);
515 }
516