Exemple #1
0
//---------------------------------------------------------------------------
void HeatVisionListener::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
    if(pass_id == 0xDEADBABE)
    {
        // "random_fractions" parameter
        fpParams->setNamedConstant("random_fractions", Ogre::Vector4(Ogre::Math::RangeRandom(0.0, 1.0), Ogre::Math::RangeRandom(0, 1.0), 0, 0));

        // "depth_modulator" parameter
        float inc = ((float)timer->getMilliseconds())/1000.0f;
        if ( (fabs(curr-end) <= 0.001) )
        {
            // take a new value to reach
            end = Ogre::Math::RangeRandom(0.95, 1.0);
            start = curr;
        }
        else
        {
            if (curr > end) curr -= inc;
            else curr += inc;
        }
        timer->reset();

        fpParams->setNamedConstant("depth_modulator", Ogre::Vector4(curr, 0, 0, 0));
    }
}
Exemple #2
0
	/**
	 * Releases the object's resources
	 */
	void MediaPlayerOCV::end()
	{
		// Check if already released
		if ( !isValid() )
			return;
		
        // Release thread
        if ( m_multithreaded && m_captureThread )
        {
            // Signal the thread and wait for it to be done
            m_captureThread->signal();
            Ogre::Timer timerLimit;
            timerLimit.reset();
            while( (m_captureThread->get_finished() == false) && (timerLimit.getMilliseconds() < 250) )
                ;
			if ( m_captureThread->get_finished() )
            {
                delete m_captureThread;
            }
            else
                LOG_CRITICAL( "MediaPlayerOCV: capture thread timer expired, and the thread did not finish. Something is wrong, there will be a memory leak" );
            m_captureThread = NULL;
        }
        
		// Clear resources
		m_capture.release();
        
        m_frameImg.end();
        
		// Clear flags
		m_bIsValid			= false;
		m_newBufferReady	= false;
		m_loopPending		= false;
	}
Exemple #3
0
void OMW::Engine::go()
{
    assert (!mContentFiles.empty());
    assert (!mOgre);

    Settings::Manager settings;
    std::string settingspath;

    settingspath = loadSettings (settings);

    // Create encoder
    ToUTF8::Utf8Encoder encoder (mEncoding);
    mEncoder = &encoder;

    prepareEngine (settings);

    // Play some good 'ol tunes
    MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore"));

    if (!mSaveGameFile.empty())
    {
        MWBase::Environment::get().getStateManager()->loadGame(mSaveGameFile);
    }
    else if (!mSkipMenu)
    {
        // start in main menu
        MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
        try
        {
            // Is there an ini setting for this filename or something?
            MWBase::Environment::get().getSoundManager()->streamMusic("Special/morrowind title.mp3");

            std::string logo = mFallbackMap["Movies_Morrowind_Logo"];
            if (!logo.empty())
                MWBase::Environment::get().getWindowManager()->playVideo(logo, true);
        }
        catch (...) {}
    }
    else
    {
        MWBase::Environment::get().getStateManager()->newGame (!mNewGame);
    }

    // Start the main rendering loop
    Ogre::Timer timer;
    while (!MWBase::Environment::get().getStateManager()->hasQuitRequest())
    {
        float dt = timer.getMilliseconds()/1000.f;
        dt = std::min(dt, 0.2f);

        timer.reset();
        Ogre::Root::getSingleton().renderOneFrame(dt);
    }
    // Save user settings
    settings.saveUser(settingspath);

    std::cout << "Quitting peacefully." << std::endl;
}
Exemple #4
0
	::FreeConsole();
}

void Game::Run()
{
	InitializeGame();
	ConnectToPVD();
	InitializeKinect();

	kinectController = BodyController();

	InputManager* inputManager = InputManager::GetInstance();

	inputManager->RegisterSensorListener(&kinectController);

	inputManager->BeginAllCapture();

	sceneManager = new SceneManager();
	sceneManager->Initialize(mWindow, mRoot);

	AllocConsole();
	freopen("conin$","r",stdin);
	freopen("conout$","w",stdout);
	freopen("conout$","w",stderr);
	printf("Debugging Window:\n");

	/*std::shared_ptr<GameScene> gameScene(new GameScene(sceneManager, mRoot, "Probending Arena", contestantData));
	sceneManager->FlagSceneSwitch(gameScene, true);
	gameScene.reset();*/

	std::shared_ptr<MenusScene> menuScene = std::make_shared<MenusScene>(sceneManager, mRoot, MenusScene::Screens::MainMenu);
	sceneManager->FlagSceneSwitch(menuScene, true);
	menuScene.reset();

	bool rendering = true;

	Ogre::Timer gameTimer = Ogre::Timer();
	float currentTime = 0;
	float previousTime = 0;

	while (rendering)
	{
		gameTimer.reset();
		
		if(!Update(currentTime / 1000.0f))
			rendering = false;

		//Ogre::WindowEventUtilities::messagePump();
#if(!MEMORY_LEAK_DETECT)
		mRoot->renderOneFrame();
#endif
		currentTime = (float)gameTimer.getMilliseconds();
		
    // FrameListener callback (~ idleFunc). Perform animation here
    bool frameRenderingQueued(const Ogre::FrameEvent& evt) {
        float t = mTimer.getMilliseconds()*0.001;

        // Do some simple animations by changing scene node transform parameters
        Ogre::SceneNode* triangle = mScene->getSceneNode("Triangle");
        triangle->resetToInitialState();
        triangle->rotate(Ogre::Vector3(0, 0, 1), Ogre::Radian(t));

        // Exercise 1: Use SceneNode to manipulate the object and create animation
        // ...

        return true; // Return false to quit
    }
Exemple #6
0
///  _Tool_	Warnings  ......................................................
///  check all tracks for warnings
///  Warning: takes about 16 sec
void CGui::ToolTracksWarnings()
{
	Ogre::Timer ti;
	LogO("ALL tracks warnings ---------\n");
	logWarn = true;

	for (int i=0; i < data->tracks->trks.size(); ++i)
	{	//  foreach track
		string trk = data->tracks->trks[i].name, path = gcom->pathTrk[0] +"/"+ trk +"/";
		/**/if (!(trk[0] >= 'A' && trk[0] <= 'Z'))  continue;
		/**/if (StringUtil::startsWith(trk,"test"))  continue;

		Scene sc;  sc.LoadXml(path +"scene.xml");
		SplineRoad rd(app);  rd.LoadFile(path +"road.xml");
		
		LogO("Track: "+trk);
		WarningsCheck(&sc,&rd);
	}
	LogO(String("::: Time ALL tracks: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
	LogO("ALL tracks warnings ---------");
}
Exemple #7
0
bool initOgreRoot(){
	try{
		// Create logs that funnel to android logs
		Ogre::LogManager *lm = OGRE_NEW Ogre::LogManager();
		Ogre::Log *l = lm->createLog("AndroidLog", true, true, true);
		g_ll = OGRE_NEW AndroidLogListener();
		l->addListener(g_ll);
		
		// Create a root object
		g_root = OGRE_NEW Ogre::Root("", "", "");
		
		// Register the ES2 plugin
		g_gles2Plugin = OGRE_NEW Ogre::GLES2Plugin();
		Ogre::Root::getSingleton().installPlugin(g_gles2Plugin);
		
		// Register particle plugin
		g_pfxPlugin = OGRE_NEW Ogre::ParticleFXPlugin();
		Ogre::Root::getSingleton().installPlugin(g_pfxPlugin);
		
		// Grab the available render systems
		const Ogre::RenderSystemList &renderSystemList = g_root->getAvailableRenderers();
		if(renderSystemList.empty())
		{
			return false;
		}
		
		// Set the render system and init
		Ogre::RenderSystem *system = renderSystemList.front();
		g_root->setRenderSystem(system);
		g_root->initialise(false);
		
		g_lastTime = g_timer.getMilliseconds();
		
		return true;
	}catch(Ogre::Exception &e){
	}
	return false;
}
void CGui::InitGui() 
{
	mGui = app->mGui;
	gcom->mGui = mGui;
	SliderValue::pGUI = mGui;
	SliderValue::bGI = &bGI;
	Check::pGUI = mGui;
	Check::bGI = &bGI;

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


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

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


	//  wnds
	app->mWndMain = fWnd("MainMenuWnd");
	app->mWndTrack = fWnd("TrackWnd");  app->mWndEdit = fWnd("EditorWnd");
	app->mWndOpts = fWnd("OptionsWnd"); app->mWndHelp = fWnd("HelpWnd");
	app->mWndPick = fWnd("PickWnd");

	app->mWndCam =   fWnd("CamWnd");    app->mWndCam->setPosition(0,64);
	app->mWndStart = fWnd("StartWnd");  app->mWndStart->setPosition(0,64);
	app->mWndBrush = fWnd("BrushWnd");  app->mWndBrush->setPosition(0,64);

	app->mWndRoadCur =   fWnd("RoadCur");    app->mWndRoadCur->setPosition(0,40);
	app->mWndRoadStats = fWnd("RoadStats");  app->mWndRoadStats->setPosition(0,338);

	app->mWndFluids = fWnd("FluidsWnd");   app->mWndFluids->setPosition(0,64);
	app->mWndObjects= fWnd("ObjectsWnd");  app->mWndObjects->setPosition(0,64);
	app->mWndRivers = fWnd("RiversWnd");   app->mWndRivers->setPosition(0,64);


	//  for find defines
	Btn btn, bchk;
	Sl* sl;  SV* sv;  Ck* ck;

	
	//  Tabs
	TabPtr tab,sub;
	fTabW("TabWndTrack"); app->mWndTabsTrack = tab;
	fTabW("TabWndEdit");  app->mWndTabsEdit = tab;
	fTabW("TabWndOpts");  app->mWndTabsOpts = tab;
	fTabW("TabWndHelp");  app->mWndTabsHelp = tab;

	//  get sub tabs
	vSubTabsTrack.clear();
	for (size_t i=0; i < app->mWndTabsTrack->getItemCount(); ++i)
	{
		sub = (TabPtr)app->mWndTabsTrack->getItemAt(i)->findWidget("SubTab");
		vSubTabsTrack.push_back(sub);
	}
	vSubTabsEdit.clear();
	for (size_t i=0; i < app->mWndTabsEdit->getItemCount(); ++i)
	{
		sub = (TabPtr)app->mWndTabsEdit->getItemAt(i)->findWidget("SubTab");
		vSubTabsEdit.push_back(sub);  // 0 for not found
	}
	vSubTabsHelp.clear();
	for (size_t i=0; i < app->mWndTabsHelp->getItemCount(); ++i)
	{
		sub = (TabPtr)app->mWndTabsHelp->getItemAt(i)->findWidget("SubTab");
		vSubTabsHelp.push_back(sub);
	}
	vSubTabsOpts.clear();
	for (size_t i=0; i < app->mWndTabsOpts->getItemCount(); ++i)
	{
		sub = (TabPtr)app->mWndTabsOpts->getItemAt(i)->findWidget("SubTab");
		vSubTabsOpts.push_back(sub);
	}

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

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


	//app->mWndTabs->setIndexSelected(3);  //default*--
	gcom->ResizeOptWnd(); //?


	//  center mouse pos
	app->mCursorManager->cursorVisibilityChange(app->bGuiFocus || !app->bMoveCam);
	gcom->GuiCenterMouse();
	
	//  hide  ---
	app->SetEdMode(ED_Deform);
	app->UpdEditWnds();  // UpdVisHit(); //after track
	

	#if 0  ///0 _tool_ fix video capture cursor
	imgCur = mGui->createWidget<ImageBox>("ImageBox", 100,100, 32,32, Align::Default, "Pointer");
	imgCur->setImageTexture("pointer.png");
	imgCur->setVisible(true);
	#endif


	//  tool window texts  ----------------------
	int i;
	for (i=0; i<MAX_TXT; ++i)
	{	String s = toStr(i);
		if (i<BR_TXT){  brTxt[i] = fTxt("brTxt"+s);  brVal[i] = fTxt("brVal"+s);  brKey[i] = fTxt("brKey"+s);  }
		if (i<RD_TXT){  rdTxt[i] = fTxt("rdTxt"+s);  rdVal[i] = fTxt("rdVal"+s);  rdKey[i] = fTxt("rdKey"+s);  }
		if (i<RDS_TXT){ rdTxtSt[i] = fTxt("rdTxtSt"+s);  rdValSt[i] = fTxt("rdValSt"+s);  }
		if (i<ST_TXT)   stTxt[i] = fTxt("stTxt"+s);    if (i<FL_TXT)  flTxt[i] = fTxt("flTxt"+s);
		if (i<OBJ_TXT)  objTxt[i]= fTxt("objTxt"+s);   if (i<RI_TXT)  riTxt[i] = fTxt("riTxt"+s);
	}


	///  brush presets   o o o o o o o o 
	ScrollView* scv = mGui->findWidget<ScrollView>("svBrushes");
	int j=0, n=0;  const int z = 128;
	for (i=0; i < app->brSetsNum; ++i,++n)
	{
		const App::BrushSet& st = app->brSets[i];  const String s = toStr(i);
		int x,y, xt,yt, sx, row1 = i-14;  // y,x for next lines
		if (row1 < 0)  // top row
		{	x = 10+ i*50;  y = 10;
			xt = x + 20;  yt = y + 50;  sx = 48;
		}else
		{	if (st.newLine==1 && n > 0 || n > 9) {  n=0;  ++j;  }  // 1 new line
			x = 20+ n*70;  y = 10+ j*70;
			xt = x + 25;  yt = y + 55;  sx = 64;
			if (st.newLine < 0)  n -= st.newLine;  // -1 empty x
		}
		Img img = scv->createWidget<ImageBox>("ImageBox", x,y, sx,sx, Align::Default, "brI"+s);
		img->eventMouseButtonClick += newDelegate(this, &CGui::btnBrushPreset);
		img->setUserString("tip", st.name);  img->setNeedToolTip(true);
		img->setImageTexture("brushes.png");
		img->setImageCoord(IntCoord(i%16*z,i/16*z, z,z));
		if (!st.name.empty())  img->eventToolTip += newDelegate(gcom, &CGuiCom::notifyToolTip);
		gcom->setOrigPos(img, "EditorWnd");
		
		Txt txt = scv->createWidget<TextBox>("TextBox", xt,yt, 40,22, Align::Default, "brT"+s);
		txt->setCaption(fToStr(st.Size,0,2));
			int edMode = st.edMode;
			float fB = app->brClr[edMode][0], fG = app->brClr[edMode][1], fR = app->brClr[edMode][2];
			float m = st.Size / 160.f + 0.4f;
			#define mul(v,m)  std::min(1.f, std::max(0.f, v * m))
		txt->setTextColour(Colour(mul(fB,m), mul(fG,m), mul(fR,m)) );
		gcom->setOrigPos(txt, "EditorWnd");
	}
	//scv->setCanvasSize(1020,j*90+300);


	///  [Settings]
	//------------------------------------------------------------------------
	sv= &svCamSpeed;	sv->Init("CamSpeed",	&pSet->cam_speed, 0.1f,4.f);  sv->DefaultF(0.9f);
	sv= &svCamInert;	sv->Init("CamInert",	&pSet->cam_inert, 0.f, 1.f);  sv->DefaultF(0.4f);

	ck= &ckMinimap;		ck->Init("Minimap",		&pSet->trackmap);  Cev(Minimap);
	sv= &svSizeMinimap;	sv->Init("SizeMinimap",	&pSet->size_minimap, 0.15f,2.f);  sv->DefaultF(0.55f);  Sev(SizeMinimap);

	sv= &svSizeRoadP;	sv->Init("SizeRoadP",	&pSet->road_sphr, 0.1f,12.f); sv->DefaultF(1.5f);  Sev(SizeRoadP);

	sv= &svTerUpd;		sv->Init("TerUpd",		&pSet->ter_skip,  0, 20);  sv->DefaultI(1);
	sv= &svMiniUpd;		sv->Init("MiniUpd",		&pSet->mini_skip, 0, 20);  sv->DefaultI(4);

	ck= &ckWireframe;	ck->Init("Wireframe",	&app->mbWireFrame);  Cev(Wireframe);
	ck= &ckCamPos;		ck->Init("CamPos",		&pSet->camPos);    Cev(CamPos);
	ck= &ckInputBar;	ck->Init("InputBar",	&pSet->inputBar);  Cev(InputBar);
	ck= &ckAllowSave;	ck->Init("AllowSave",	&pSet->allow_save);

	//  set camera btns
	Btn("CamView1", btnSetCam);  Btn("CamView2", btnSetCam);
	Btn("CamView3", btnSetCam);  Btn("CamView4", btnSetCam);
	Btn("CamTop",   btnSetCam);
	Btn("CamLeft",  btnSetCam);  Btn("CamRight", btnSetCam);
	Btn("CamFront", btnSetCam);  Btn("CamBack",  btnSetCam);

	//  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);
	

	///  [Sun]
	//----------------------------------------------------------------------------------------------
	sv= &svSunPitch;	sv->Init("SunPitch",	&sc->ldPitch,    0.f,90.f,  1.f, 1,4);  sv->DefaultF(54.f);    Sev(UpdSun);
	sv= &svSunYaw;		sv->Init("SunYaw",		&sc->ldYaw,   -180.f,180.f, 1.f, 1,4);  sv->DefaultF(-123.f);  Sev(UpdSun);
	sv= &svRain1Rate;	sv->Init("Rain1Rate",	&sc->rainEmit,   0.f,6000.f);  sv->DefaultF(1000.f);
	sv= &svRain2Rate;	sv->Init("Rain2Rate",	&sc->rain2Emit,  0.f,6000.f);  sv->DefaultF(1000.f);
	//  fog
	sv= &svFogStart;	sv->Init("FogStart",	&sc->fogStart,   0.f,2000.f, 2.f, 0,3);  sv->DefaultF(100.f);  Sev(UpdFog);
	sv= &svFogEnd;		sv->Init("FogEnd",		&sc->fogEnd,     0.f,2000.f, 2.f, 0,3);  sv->DefaultF(600.f);  Sev(UpdFog);
	sv= &svFogHStart;	sv->Init("FogHStart",	&sc->fogHStart,  0.f,2000.f, 2.f, 0,3);  sv->DefaultF(0.f);    Sev(UpdFog);
	sv= &svFogHEnd;		sv->Init("FogHEnd",		&sc->fogHEnd,    0.f,2000.f, 2.f, 0,3);  sv->DefaultF(60.f);   Sev(UpdFog);
	sv= &svFogHeight;	sv->Init("FogHeight",	&sc->fogHeight, -200.f,200.f, 1.f, 1,4);  sv->DefaultF(-300.f);  Sev(UpdFog);
	sv= &svFogHDensity;	sv->Init("FogHDensity",	&sc->fogHDensity,  0.f,200.f, 2.f, 1,4);  sv->DefaultF(60.f);  Sev(UpdFog);

	ck= &ckFog;			ck->Init("FogDisable",		&pSet->bFog);  Cev(Fog);
	ck= &ckWeather;		ck->Init("WeatherDisable",	&pSet->bWeather);

	//  light
	Ed(LiAmb, editLiAmb);  Ed(LiDiff, editLiDiff);  Ed(LiSpec, editLiSpec);
	Ed(FogClr, editFogClr);  Ed(FogClr2, editFogClr2);  Ed(FogClrH, editFogClrH);

	clrAmb = fImg("ClrAmb");   clrDiff = fImg("ClrDiff");
	clrSpec= fImg("ClrSpec");  clrTrail= fImg("ClrTrail");
	clrFog = fImg("ClrFog");   clrFog2 = fImg("ClrFog2");
	clrFogH= fImg("ClrFogH");  //Todo: on click event - open color dialog


	///  [Terrain]
	//------------------------------------------------------------------------
	imgTexDiff = fImg("TerImgDiff");
	Tab(tabsHmap, "TabHMapSize", tabHmap);
	sv= &svTerErrorNorm;  sv->Init("TerErrorNorm", &sc->td.errorNorm,  1.5f,15.f, 1.5f,1,3);  sv->DefaultF(3.f);  Sev(TerErrorNorm);
	sv= &svTerNormScale;  sv->Init("TerNormScale", &sc->td.normScale,  0.01f,3.f, 1.f, 1,3);  sv->DefaultF(1.f);  Sev(TerPar);
	sv= &svTerSpecPow;    sv->Init("TerSpecPow",   &sc->td.specularPow,   0.2f,128.f,2.f, 1,4);  sv->DefaultF(32.f); Sev(TerPar);
	sv= &svTerSpecPowEm;  sv->Init("TerSpecPowEm", &sc->td.specularPowEm, 0.5f,4.f,  1.f, 1,3);  sv->DefaultF(2.f);  Sev(TerPar);

	Btn("TerrainNew", btnTerrainNew);
	Btn("TerrainGenAdd", btnTerGenerate);  Btn("TerrainGenSub", btnTerGenerate);    Btn("TerrainGenMul", btnTerGenerate);
	Btn("TerrainHalf",   btnTerrainHalf);  Btn("TerrainDouble", btnTerrainDouble);  Btn("TerrainMove",   btnTerrainMove);


	///  generator  . . . . . . .
	sv= &svTerGenScale;	sv->Init("TerGenScale",	&pSet->gen_scale, 0.f,160.f, 2.f, 2,4);  sv->DefaultF(52.f);
	sv= &svTerGenOfsX;	sv->Init("TerGenOfsX",	&pSet->gen_ofsx, -12.f,12.f, 1.f, 3,5);  sv->DefaultF(0.14f);   Sev(TerGen);
	sv= &svTerGenOfsY;	sv->Init("TerGenOfsY",	&pSet->gen_ofsy, -12.f,12.f, 1.f, 3,5);  sv->DefaultF(-1.54f);  Sev(TerGen);

	sv= &svTerGenFreq;	sv->Init("TerGenFreq",	&pSet->gen_freq,   0.06f,3.f, 2.f, 3,5);  sv->DefaultF(0.914f); Sev(TerGen);
	sv= &svTerGenOct;	sv->Init("TerGenOct",	&pSet->gen_oct,    0, 9);                 sv->DefaultI(4);      Sev(TerGen);
	sv= &svTerGenPers;	sv->Init("TerGenPers",	&pSet->gen_persist,0.f, 0.7f, 1.f, 3,5);  sv->DefaultF(0.347f); Sev(TerGen);
	sv= &svTerGenPow;	sv->Init("TerGenPow",	&pSet->gen_pow,    0.f, 6.f,  2.f, 2,4);  sv->DefaultF(1.f);    Sev(TerGen);
	
	sv= &svTerGenMul;	sv->Init("TerGenMul",	&pSet->gen_mul,    0.f, 6.f,  2.f, 2,4);  sv->DefaultF(1.f);
	sv= &svTerGenOfsH;	sv->Init("TerGenOfsH",	&pSet->gen_ofsh,   0.f, 60.f, 2.f, 2,4);  sv->DefaultF(0.f);
	sv= &svTerGenRoadSm;sv->Init("TerGenRoadSm",&pSet->gen_roadsm, 0.f, 6.f,  1.f, 2,4);  sv->DefaultF(0.f);

	sv= &svTerGenAngMin;sv->Init("TerGenAngMin",&pSet->gen_terMinA, 0.f,  90.f,  1.f, 1,4);  sv->DefaultF(0.f);
	sv= &svTerGenAngMax;sv->Init("TerGenAngMax",&pSet->gen_terMaxA, 0.f,  90.f,  1.f, 1,4);  sv->DefaultF(90.f);
	sv= &svTerGenAngSm;	sv->Init("TerGenAngSm",	&pSet->gen_terSmA,  0.f,  90.f,  2.f, 1,4);  sv->DefaultF(10.f);
	sv= &svTerGenHMin;	sv->Init("TerGenHMin",	&pSet->gen_terMinH,-150.f,150.f, 1.f, 0,1);  sv->DefaultF(-300.f);
	sv= &svTerGenHMax;	sv->Init("TerGenHMax",	&pSet->gen_terMaxH,-150.f,150.f, 1.f, 0,1);  sv->DefaultF( 300.f);
	sv= &svTerGenHSm;	sv->Init("TerGenHSm",	&pSet->gen_terSmH,  0.f,  100.f, 2.f, 1,4);  sv->DefaultF(20.f);


	///  [Layers]  ------------------------------------
	bool b;
	ck= &ckTerLayOn;	ck->Init("TerLayOn",	&b);   Cev(TerLayOn);
	valTerLAll = fTxt("TerLayersAll");
	valTriplAll = fTxt("TerTriplAll");
	Tab(tabsTerLayers, "TabTerLay", tabTerLayer);
	Btn("UpdateLayers", btnUpdateLayers);

	ck= &ckTexNormAuto;	ck->Init("TexNormAuto",	&bTexNormAuto);
	ck= &ckTerLayTripl;	ck->Init("TerLayTripl",	&b);   Cev(TerLayTripl);
	ck= &ckDebugBlend;	ck->Init("DebugBlend",  &bDebugBlend);  Cev(DebugBlend);
	dbgLclr = fImg("dbgTerLclr");

	float f=0.f;  i=0;  // temp vars
	//  ter layer
	sv= &svTerTriSize;	sv->Init("TerTriSize", &sc->td.fTriangleSize,  0.5f,3.f, 1.f);  sv->DefaultF(1.4f);  Sev(TerTriSize);
	sv= &svTerLScale;	sv->Init("TerLScale",  &f, 6.0f, 72.f,  2.f);  sv->DefaultF(8.f);  //Sev(TerLay);
	//  blendmap
	sv= &svTerLAngMin;  sv->Init("TerLAngMin", &f, 0.f,  90.f,  1.f, 1,4);  sv->DefaultF(0.f);  Sev(TerLay);
	sv= &svTerLAngMax;  sv->Init("TerLAngMax", &f, 0.f,  90.f,  1.f, 1,4);  sv->DefaultF(90.f);  Sev(TerLay);
	sv= &svTerLAngSm;   sv->Init("TerLAngSm",  &f, 0.f,  90.f,  2.f, 1,4);  sv->DefaultF(20.f);  Sev(TerLay);

	sv= &svTerLHMin;    sv->Init("TerLHMin",   &f,-150.f,150.f, 1.f, 0,2);  sv->DefaultF(-300.f);  Sev(TerLay);
	sv= &svTerLHMax;    sv->Init("TerLHMax",   &f,-150.f,150.f, 1.f, 0,2);  sv->DefaultF( 300.f);  Sev(TerLay);
	sv= &svTerLHSm;     sv->Init("TerLHSm",    &f, 0.f,  100.f, 2.f, 1,4);  sv->DefaultF(20.f);  Sev(TerLay);
	Btn("TerLmoveL", btnTerLmoveL);  Btn("TerLmoveR", btnTerLmoveR);

	//  noise
	ck= &ckTerLNOnly;   ck->Init("TerLNonly",  &b);   Cev(TerLNOnly);
	sv= &svTerLNoise;   sv->Init("TerLNoise",  &f, 0.f,1.f);  sv->DefaultF(0.f);  Sev(TerLay);
	sv= &svTerLNprev;   sv->Init("TerLNprev",  &f, 0.f,1.f);  sv->DefaultF(0.f);  Sev(TerLay);
	sv= &svTerLNnext2;  sv->Init("TerLNnext2", &f, 0.f,1.f);  sv->DefaultF(0.f);  Sev(TerLay);
	//  noise params
	for (i=0; i<2; ++i)  {  String s = toStr(i+1);
	sv= &svTerLN_Freq[i];  sv->Init("TerLNFreq"+s,  &f, 1.f,300.f, 2.f, 1,3);   sv->DefaultF(30.f);  Sev(TerLay);
	sv= &svTerLN_Oct[i];   sv->Init("TerLNOct" +s,  &i, 1,5);                   sv->DefaultI(3);     Sev(TerLay);
	sv= &svTerLN_Pers[i];  sv->Init("TerLNPers"+s,  &f, 0.1f, 0.7f, 1.f, 3,5);  sv->DefaultF(0.3f);  Sev(TerLay);
	sv= &svTerLN_Pow[i];   sv->Init("TerLNPow" +s,  &f, 0.2f, 8.f,  2.f);       sv->DefaultF(1.f);   Sev(TerLay);  }
	//  noise btns
	Btn("TerLNbtn1", radN1);  bRn1 = btn;  bRn1->setStateSelected(true);
	Btn("TerLNbtn2", radN2);  bRn2 = btn;
	for (i=0; i < 15; ++i)
	{  Btn("TerLN_"+toStr(i), btnNpreset);  }
	Btn("TerLNrandom", btnNrandom);
	Btn("TerLNswap", btnNswap);
	
	//  particles
	Ed(LDust, editLDust);	Ed(LDustS, editLDust);
	Ed(LMud,  editLDust);	Ed(LSmoke, editLDust);
	Ed(LTrlClr, editLTrlClr);
	Cmb(cmbParDust, "CmbParDust", comboParDust);
	Cmb(cmbParMud,  "CmbParMud",  comboParDust);
	Cmb(cmbParSmoke,"CmbParSmoke",comboParDust);

	//  surface
	Cmb(cmbSurface, "Surface", comboSurface);  //1 txt-
	txtSuBumpWave = fTxt("SuBumpWave");   txtSuFrict  = fTxt("SuFrict");
	txtSuBumpAmp  = fTxt("SuBumpAmp");	  txtSurfTire = fTxt("SurfTire");
	txtSuRollDrag = fTxt("SuRollDrag");	  txtSurfType = fTxt("SurfType");
	SldUpd_TerL();

	
	///  [Vegetation]  ------------------------------------
	sv= &svGrassDens;	sv->Init("GrassDens",	&sc->densGrass, 0.f, 1.f, 2.f);  sv->DefaultF(0.2f);
	sv= &svTreesDens;	sv->Init("TreesDens",	&sc->densTrees, 0.f, 3.f, 2.f);  sv->DefaultF(0.3f);

	Ed(GrPage, editTrGr);  Ed(GrDist, editTrGr);
	Ed(TrPage, editTrGr);  Ed(TrDist, editTrGr);  Ed(TrImpDist, editTrGr);
	
	sv= &svTrRdDist;	sv->Init("TrRdDist",	&sc->trRdDist,     0,6);   sv->DefaultI(1);
	sv= &svGrDensSmooth;sv->Init("GrDensSmooth",&sc->grDensSmooth, 0,10);  sv->DefaultI(3);
	Ed(SceneryId, editTrGr);

	//  veget models
	ck= &ckPgLayOn;		ck->Init("LTrEnabled",	&b);   Cev(PgLayOn);
	valLTrAll = fTxt("LTrAll");
	Tab(tabsPgLayers, "LTrNumTab", tabPgLayers);
	Btn("UpdateVeget", btnUpdateVeget);

	sv= &svLTrDens;		sv->Init("LTrDens",		 &f, 0.f, 1.f, 2.f, 3,5);  sv->DefaultF(0.15f);
	
	sv= &svLTrRdDist;	sv->Init("LTrRdDist",	 &i, 0,20);  sv->DefaultI(0);
	sv= &svLTrRdDistMax;sv->Init("LTrRdDistMax", &i, 0,20);  sv->DefaultI(20);
	
	sv= &svLTrMinSc;	sv->Init("LTrMinSc",	 &f, 0.f,4.f, 3.f, 3,5);  sv->DefaultF(0.7f);  Sev(LTrSc);
	sv= &svLTrMaxSc;	sv->Init("LTrMaxSc",	 &f, 0.f,4.f, 3.f, 3,5);  sv->DefaultF(1.2f);  Sev(LTrSc);
	
	sv= &svLTrWindFx;	sv->Init("LTrWindFx",	 &f, 0.f,12.f, 3.f, 3,5);  sv->DefaultF(0.5f);
	sv= &svLTrWindFy;	sv->Init("LTrWindFy",	 &f, 0.f,0.4f, 3.f, 3,5);  sv->DefaultF(0.06f);
	
	sv= &svLTrMaxTerAng;sv->Init("LTrMaxTerAng", &f, 0.f,90.f, 2.f, 1,4);  sv->DefaultF(30.f);

	sv= &svLTrMinTerH;	sv->Init("LTrMinTerH",	 &f,-60.f,60.f, 1.f, 1,4);  sv->DefaultF(-100.f);
	sv= &svLTrMaxTerH;	sv->Init("LTrMaxTerH",	 &f, 0.f,120.f, 1.f, 1,4);  sv->DefaultF( 100.f);
	sv= &svLTrFlDepth;	sv->Init("LTrFlDepth",	 &f, 0.f,5.f, 2.f, 1,4);  sv->DefaultF(0.f);
	SldUpd_PgL();  // real &f set here

	txVCnt = fTxt("LTrInfCnt");
	txVHmin = fTxt("LTrInfHmin");  txVHmax = fTxt("LTrInfHmax");
	txVWmin = fTxt("LTrInfWmin");  txVWmax = fTxt("LTrInfWmax");
	

	///  Grass  ------------------------------------
	Ed(GrSwayDistr, editTrGr);  Ed(GrSwayLen, editTrGr);  Ed(GrSwaySpd, editTrGr);

	imgGrass = fImg("ImgGrass");  imgGrClr = fImg("ImgGrClr");
	Cmb(cmbGrassClr, "CmbGrClr", comboGrassClr);

	//  grass channels
	sv= &svGrChAngMin;	sv->Init("GrChMinA",	&f, 0.f,90.f, 1.f, 1,4);  sv->DefaultF(30.f);
	sv= &svGrChAngMax;	sv->Init("GrChMaxA",	&f, 0.f,90.f, 1.f, 1,4);  sv->DefaultF(30.f);
	sv= &svGrChAngSm;	sv->Init("GrChSmA",		&f, 0.f,50.f, 2.f, 1,4);  sv->DefaultF(20.f);
									  
	sv= &svGrChHMin;	sv->Init("GrChMinH",	&f,-60.f,60.f,  1.f, 1,4);  sv->DefaultF(-200.f);
	sv= &svGrChHMax;	sv->Init("GrChMaxH",	&f,  0.f,120.f, 1.f, 1,4);  sv->DefaultF( 200.f);
	sv= &svGrChHSm;		sv->Init("GrChSmH",		&f,  0.f,60.f,  2.f, 1,4);  sv->DefaultF(20.f);
	sv= &svGrChRdPow;	sv->Init("GrChRdPow",	&f, -8.f, 8.f,  1.f, 1,4);  sv->DefaultF(0.f);
	//  noise
	sv= &svGrChNoise;	sv->Init("GrChNoise",	&f, 0.f,2.f,   1.f, 1,4);   sv->DefaultF(0.f);
	sv= &svGrChNfreq;	sv->Init("GrChNFreq",	&f, 1.f,300.f, 2.f, 1,3);   sv->DefaultF(30.f);
	sv= &svGrChNoct;	sv->Init("GrChNOct",	&i, 1,5);                   sv->DefaultI(3);
	sv= &svGrChNpers;	sv->Init("GrChNPers",	&f, 0.1f, 0.7f, 1.f, 3,5);  sv->DefaultF(0.3f);
	sv= &svGrChNpow;	sv->Init("GrChNPow",	&f, 0.2f, 8.f,  2.f);       sv->DefaultF(1.f);
	Tab(tabsGrChan, "GrChanTab", tabGrChan);
	SldUpd_GrChan();

	//  grass layers
	ck= &ckGrLayOn;		ck->Init("LGrEnabled",	&b);   Cev(GrLayOn);
	valLGrAll = fTxt("LGrAll");
	Tab(tabsGrLayers, "LGrLayTab", tabGrLayers);
	Btn("UpdateGrass", btnUpdateGrass);

	sv= &svGrMinX;	sv->Init("GrMinX",	&f, 0.5f,4.f, 1.5f);  sv->DefaultF(1.2f);
	sv= &svGrMaxX;	sv->Init("GrMaxX",	&f, 0.5f,4.1, 1.5f);  sv->DefaultF(1.6f);
	sv= &svGrMinY;	sv->Init("GrMinY",	&f, 0.5f,4.f, 1.5f);  sv->DefaultF(1.2f);
	sv= &svGrMaxY;	sv->Init("GrMaxY",	&f, 0.5f,4.f, 1.5f);  sv->DefaultF(1.6f);
	sv= &svGrChan;	sv->Init("LGrChan",	&i, 0,3);  sv->DefaultI(0);
	sv= &svLGrDens;	sv->Init("LGrDens",	&f, 0.001f,1.f, 2.f, 3,5);  sv->DefaultF(0.22f);
	SldUpd_GrL();

	
	///  [Road]  ------------------------------------
	sv= &svRdTcMul; 	sv->Init("RdTcMul", 	&f, 0.01f,0.3f, 1.5f, 3,5);  sv->DefaultF(0.1f);
	sv= &svRdTcMulW;	sv->Init("RdTcMulW",	&f, 0.01f,0.4f, 1.5f, 3,5);  sv->DefaultF(0.1f);
	sv= &svRdTcMulP;	sv->Init("RdTcMulP",	&f, 0.01f,0.3f, 1.5f, 3,5);  sv->DefaultF(0.2f);
	sv= &svRdTcMulPW;	sv->Init("RdTcMulPW",	&f, 0.01f,0.4f, 1.5f, 3,5);  sv->DefaultF(0.2f);
	sv= &svRdTcMulC;	sv->Init("RdTcMulC",	&f, 0.01f,0.4f, 1.5f, 3,5);  sv->DefaultF(0.2f);

	sv= &svRdLenDim;	sv->Init("RdLenDim",	&f, 0.5f, 4.f, 1.5f, 2,4);  sv->DefaultF(1.f);
	sv= &svRdWidthSteps;sv->Init("RdWidthSteps",&i, 3,16, 1.5f);  sv->DefaultI(6);
	sv= &svRdPlsM;		sv->Init("RdPlsM",		&f, 1.f, 8.f, 1.5f, 1,3);  sv->DefaultF(1.f);
	sv= &svRdPwsM;		sv->Init("RdPwsM",		&f, 1.f, 8.f, 1.5f, 1,3);  sv->DefaultF(4.f);

	sv= &svRdColN;		sv->Init("RdColN",		&i, 3,16, 1.5f);  sv->DefaultI(4);
	sv= &svRdColR;		sv->Init("RdColR",		&f, 1.0f, 6.f, 1.5f, 2,4);  sv->DefaultF(2.f);
	sv= &svRdMergeLen;	sv->Init("RdMergeLen",	&f, 40.f, 2000.f, 2.f, 0,2);  sv->DefaultF(400.f);
	sv= &svRdLodPLen;	sv->Init("RdLodPLen",	&f, 10.f, 160.f, 2.f, 0,2);  sv->DefaultF(20.f);
	SldUpd_Road();
	
	Ed(RdHeightOfs, editRoad);
	Ed(RdSkirtLen, editRoad);  Ed(RdSkirtH, editRoad);
	

	///  [Game]  ------------------------------------
	sv= &svDamage;		sv->Init("DamageMul",	&sc->damageMul, 0.f,2.f, 1.f, 2,4);  sv->DefaultF(1.f);
	sv= &svWind;		sv->Init("WindAmt",		&sc->windAmt,  -6.f,6.f, 1.0f, 2,5);  sv->DefaultF(0.f);
	sv= &svGravity;		sv->Init("Gravity",		&sc->gravity,   2.f,20.f, 1.5f, 2,4);  sv->DefaultF(9.81f);
	ck= &ckDenyReversed;	ck->Init("DenyReversed",	&sc->denyReversed);
	ck= &ckTiresAsphalt;	ck->Init("TiresAsphalt",	&sc->asphalt);
	ck= &ckTerrainEmissive;	ck->Init("TerrainEmissive",	&sc->td.emissive);
	

	///  [Tools]  ------------------------------------
	Btn("TrackCopySel", btnTrkCopySel);
	valTrkCpySel = fTxt("TrkCopySelName");

	Btn("CopySun", btnCopySun);				Btn("CopyTerHmap", btnCopyTerHmap);
	Btn("CopyTerLayers", btnCopyTerLayers);	Btn("CopyVeget", btnCopyVeget);
	Btn("CopyRoad", btnCopyRoad);			Btn("CopyRoadPars", btnCopyRoadPars);

	Btn("DeleteRoad", btnDeleteRoad);		Btn("DeleteFluids", btnDeleteFluids);
	Btn("DeleteObjects", btnDeleteObjects);

	sv= &svScaleAllMul;		sv->Init("ScaleAllMul",		&fScale,    0.5f,2.f, 1.5f);  sv->DefaultF(1.f);
	sv= &svScaleTerHMul;	sv->Init("ScaleTerHMul",	&fScaleTer, 0.5f,2.f, 1.5f);  sv->DefaultF(1.f);
	Btn("ScaleAll",  btnScaleAll);  Btn("ScaleTerH", btnScaleTerH);

	sv= &svAlignWidthAdd;	sv->Init("AlignWidthAdd",	&pSet->al_w_add,  0.f,20.f,1.f, 1,3);  sv->DefaultF(10.f);
	sv= &svAlignWidthMul;	sv->Init("AlignWidthMul",	&pSet->al_w_mul,  1.f,4.f, 1.f, 2,4);  sv->DefaultF(1.f);
	sv= &svAlignSmooth;		sv->Init("AlignSmooth",		&pSet->al_smooth, 0.f,6.f, 1.f, 1,3);  sv->DefaultF(3.f);

	
	///  [Warnings]  ------------------------------------
	edWarn = fEd("Warnings");
	txWarn = mGui->createWidget<TextBox>("TextBox", 300,20, 360,32, Align::Default, "Back");
	txWarn->setTextShadow(true);  txWarn->setTextShadowColour(Colour::Black);
	txWarn->setTextColour(Colour(1.0,0.4,0.2));  txWarn->setFontHeight(24);
	txWarn->setVisible(false);

	imgWarn = fImg("ImgWarn");  imgWarn->setVisible(false);
	imgInfo = fImg("ImgInfo");

	ck= &ckCheckSave;	ck->Init("CheckSave",	&pSet->check_save);
	ck= &ckCheckLoad;	ck->Init("CheckLoad",	&pSet->check_load);
	Btn("CheckScId", btnCheckScId);
	

	///  Fill Combo boxes  . . . . . . .
	//------------------------------------------------------------------------------------------------------------

	
	//---------------------  Skies  ---------------------
	Cmb(cmbSky, "SkyCombo", comboSky);
	std::string sData = PATHMANAGER::Data();
	String sMat = sData +"/materials/scene/";  // path

	GetMaterialsMat(sMat+"sky.mat");
	for (size_t i=0; i < vsMaterials.size(); ++i)
	{	const String& s = vsMaterials[i];
		if (s != "" && s != "base_sky")
			cmbSky->addItem(s);  //LogO(s);
	}
	
	//---------------------  Weather  ---------------------
	Cmb(cmbRain1, "Rain1Cmb", comboRain1);  cmbRain1->addItem("");
	Cmb(cmbRain2, "Rain2Cmb", comboRain2);  cmbRain2->addItem("");

	GetMaterials("weather.particle", true, "particle_system");
	for (size_t i=0; i < vsMaterials.size(); ++i)
	{	const String& s = vsMaterials[i];
		cmbRain1->addItem(s);  cmbRain2->addItem(s);
	}	


	//---------------------  Terrain  ---------------------
	Cmb(cmbTexNorm, "TexNormal", comboTexNorm);  cmbTexNorm->addItem("flat_n.png");

	strlist li;
	PATHMANAGER::DirList(sData + (pSet->tex_size > 0 ? "/terrain" : "/terrain_s"), li);

	for (strlist::iterator i = li.begin(); i != li.end(); ++i)
	{	String s = *i;
		if (StringUtil::match(*i, "*_n.*", false))
			cmbTexNorm->addItem(*i);
		//else
		//if (StringUtil::match(*i, "*_d.*", false))  //_T
		//	cmbTexDiff->addItem(*i);
	}
	
	//  particles
	GetMaterials("tires.particle", true, "particle_system");
	for (size_t i=0; i < vsMaterials.size(); ++i)
	{	const String& s = vsMaterials[i];
		cmbParDust->addItem(s);  cmbParMud->addItem(s);  cmbParSmoke->addItem(s);
	}
	
	//  surfaces
	for (size_t i=0; i < app->surfaces.size(); ++i)
		cmbSurface->addItem(app->surfaces[i].name);
	

	//---------------------  Grass  ---------------------
	PATHMANAGER::DirList(sData + "/grass", li);
	for (strlist::iterator i = li.begin(); i != li.end(); ++i)
	{
		if (StringUtil::startsWith(*i, "grClr", false))
			cmbGrassClr->addItem(*i);
	}


	//---------------------  Roads  ---------------------
	GetMaterialsMat(sMat+"road.mat");
	GetMaterialsMat(sMat+"pipe.mat",false);
	for (size_t i=0; i<4; ++i)
	{
		Cmb(cmbPipeMtr[i], "RdMtrP"+toStr(i+1), comboPipeMtr);
		if (i>0)  {  cmbPipeMtr[i]->addItem("");  }
	}
	Cmb(cmbRoadWMtr, "RdMtrW1", comboRoadWMtr);
	Cmb(cmbPipeWMtr, "RdMtrPW1", comboPipeWMtr);
	Cmb(cmbRoadColMtr, "RdMtrC1", comboRoadColMtr);

	for (size_t i=0; i < vsMaterials.size(); ++i)
	{	String s = vsMaterials[i];
		if (StringUtil::startsWith(s,"pipe") && !StringUtil::startsWith(s,"pipe_"))
			for (int n=0; n<4; ++n)  cmbPipeMtr[n]->addItem(s);
		if (StringUtil::startsWith(s,"road_wall"))  cmbRoadWMtr->addItem(s);
		if (StringUtil::startsWith(s,"pipe_wall"))  cmbPipeWMtr->addItem(s);
		if (StringUtil::startsWith(s,"road_col"))  cmbRoadColMtr->addItem(s);
	}


	//---------------------  Objects  ---------------------
	app->vObjNames.clear();  strlist lo;
	PATHMANAGER::DirList(sData + "/objects", lo);
	for (strlist::iterator i = lo.begin(); i != lo.end(); ++i)
		if (StringUtil::endsWith(*i,".mesh") && !StringUtil::startsWith(*i,"sphere"))
			app->vObjNames.push_back((*i).substr(0,(*i).length()-5));  //no .ext
	
	objListDyn = fLi("ObjListDyn");  Lev(objListDyn, ObjsChng);
	objListSt  = fLi("ObjListSt");   Lev(objListSt,  ObjsChng);
	objListRck = fLi("ObjListRck");  Lev(objListRck, ObjsChng);
	objListBld = fLi("ObjListBld");  Lev(objListBld, ObjsChng);
	objPan = fWP("objPan");

	for (int i=0; i < app->vObjNames.size(); ++i)
	{	const std::string& name = app->vObjNames[i];
		if (name != "sphere")
		{
			if (StringUtil::startsWith(name,"pers_",false))
				objListBld->addItem("#E0E070"+name);  // buildings
			else
			if (StringUtil::startsWith(name,"rock",false)||StringUtil::startsWith(name,"cave",false))
				objListRck->addItem("#E0B070"+name);  // rocks
			else 
			if (boost::filesystem::exists(sData+"/objects/"+ name + ".bullet"))
				objListDyn->addItem("#A0E0FF"+name);  // dynamic
			else
				objListSt->addItem("#C8C8C8"+name);
	}	}
	//objList->setIndexSelected(0);  //objList->findItemIndexWith(modeSel)


	//---------------------  Surfaces  ---------------------
	surfList = fLi("SurfList");  Lev(surfList, Surf);
	for (n=0; n < 4; ++n)  surfList->addItem("#80FF00"+TR("#{Layer} ")+toStr(n));
	for (n=0; n < 4; ++n)  surfList->addItem("#FFB020"+TR("#{Road} ")+toStr(n));
	for (n=0; n < 4; ++n)  surfList->addItem("#FFFF80"+TR("#{Pipe} ")+toStr(n));
	surfList->setIndexSelected(0);
	
	
	//---------------------  Tweak  ---------------------
	ComboBoxPtr cmbTwk;
	Cmb(cmbTwk, "TweakMtr", comboTweakMtr);

	GetMaterialsMat(sData +"/materials/water.mat");
	GetMaterialsMat(sMat+"pipe.mat",false);
	GetMaterialsMat(sMat+"road.mat",false);
	GetMaterialsMat(sMat+"objects_static.mat",false);

	cmbTwk->addItem("");
	for (size_t i=0; i < vsMaterials.size(); ++i)
	{	String s = vsMaterials[i];
			cmbTwk->addItem(s);
	}
	cmbTwk->setIndexSelected( cmbTwk->findItemIndexWith(pSet->tweak_mtr) );

	
	///  [Pick window]
	///------------------------------------------------------------------------------------------------------------
	//  Pick btns
	Btn("PickTex", btnPickTex);      btn->eventMouseWheel += newDelegate(this, &CGui::wheelTex);  btnTexDiff = btn;
	Btn("PickGrass", btnPickGrass);  btn->eventMouseWheel += newDelegate(this, &CGui::wheelGrs);  btnGrassMtr = btn;
	Btn("PickVeget", btnPickVeget);  btn->eventMouseWheel += newDelegate(this, &CGui::wheelVeg);  btnVeget = btn;
	for (n=0; n < 4; ++n) {  Btn("RdMtr"+toStr(n+1), btnPickRoad);  btnRoad[n] = btn;  }

	ck= &ckPickSetPar;	ck->Init("PickSetPar",	&pSet->pick_setpar);
	panPick = fWP("PanelPick");
	// todo: pick filter sceneries ..
	//const char sc[17]="TJSFGWIADCVUMOER";  //chk "Pick"+sc[i]
	//"PickRadAll" "PickRadCur" "PickRadFilter"

	///  Tex Diff  --------
	Mli2 lp;  int l;
	lp = app->mWndPick->createWidget<MultiList2>("MultiListBox",8,8,400,800, Align::Left | Align::VStretch);
	liTex = lp;  lp->eventListChangePosition += newDelegate(this, &CGui::listPickTex);
	lp->setColour(Colour(0.8,0.9,0.7));  lp->setInheritsAlpha(false);
	
	lp->removeAllColumns();  lp->removeAllItems();
	lp->addColumn("#90C0F0", 25);  //+TR("#{Scenery}")
	lp->addColumn("#E0FFE0"+TR("#{Diffuse}"), 160);  ///pick dim
	lp->addColumn("#80FF80"+TR("#{Scale}"), 40);
	//lp->addColumn("#80FF80/", 40);
	lp->addColumn("#80FF80|"/*+TR("#{HighestSlopes}")*/, 27);
	lp->addColumn(" ", 20);
	liPickW[0] = 280;

	for (i=0; i < data->pre->ter.size(); ++i)
	{	const PTer& t = data->pre->ter[i];
		String c = gcom->scnClr[gcom->scnN[t.sc]];  if (c.empty())  c = "#000000";
		lp->addItem(c+ t.sc, 0);  l = lp->getItemCount()-1;

		lp->setSubItemNameAt(1,l, c+ t.texFile.substr(0, t.texFile.length()-2));  // no _d
		lp->setSubItemNameAt(2,l, c+ fToStr( t.tiling, 0,2)); //1,3
		//lp->setSubItemNameAt(3,l, c+ fToStr( t.angMin, 0,2));
		lp->setSubItemNameAt(3,l, c+ (t.triplanar?"1":"0"));
	}

	///  Grass  --------
	lp = app->mWndPick->createWidget<MultiList2>("MultiListBox",8,8,400,800, Align::Left | Align::VStretch);
	liGrs = lp;  lp->eventListChangePosition += newDelegate(this, &CGui::listPickGrs);
	lp->setColour(Colour(0.7,0.9,0.7));  lp->setInheritsAlpha(false);
	
	lp->removeAllColumns();  lp->removeAllItems();
	lp->addColumn("#90C0F0", 25);
	lp->addColumn("#E0FFE0"+TR("#{GrMaterial}"), 152);
	//lp->addColumn("#E0FFE0"+TR("#{GrColorMap}"), 120);
	lp->addColumn(" ", 20);
	liPickW[1] = 205;

	for (i=0; i < data->pre->gr.size(); ++i)
	{	const PGrass& t = data->pre->gr[i];
		String c = gcom->scnClr[gcom->scnN[t.sc]];  if (c.empty())  c = "#000000";
		lp->addItem(c+ t.sc, 0);  l = lp->getItemCount()-1;

		lp->setSubItemNameAt(1,l, c+ t.mtr);
		//lp->setSubItemNameAt(2,l, c+ t.clr.substr(5));
	}

	///  Veget  --------
	lp = app->mWndPick->createWidget<MultiList2>("MultiListBox",8,8,400,800, Align::Left | Align::VStretch);
	liVeg = lp;  lp->eventListChangePosition += newDelegate(this, &CGui::listPickVeg);
	lp->setColour(Colour(0.7,0.9,0.9));  lp->setInheritsAlpha(false);
	
	lp->removeAllColumns();  lp->removeAllItems();
	lp->addColumn("#90C0F0", 25);
	lp->addColumn("#E0FFE0"+TR("#{Model}"), 157);
	lp->addColumn("#80E0E0"+TR("#{MaxScale}"), 40);
	lp->addColumn("#80E080/"/*+TR("#{AngleMax}")*/, 30);
	lp->addColumn(" ", 20);
	liPickW[2] = 280;

	for (i=0; i < data->pre->veg.size(); ++i)
	{	const PVeget& t = data->pre->veg[i];
		String c = gcom->scnClr[gcom->scnN[t.sc]];  if (c.empty())  c = "#000000";
		lp->addItem(c+ t.sc, 0);  l = lp->getItemCount()-1;

		lp->setSubItemNameAt(1,l, c+ t.name);
		//lp->setSubItemNameAt(2,l, c+ fToStr( t.minScale, 1,3));
		lp->setSubItemNameAt(2,l, c+ fToStr( t.maxScale, 1,3));
		lp->setSubItemNameAt(3,l, c+ fToStr( t.maxTerAng, 0,2));
	}

	///  Road  --------
	lp = app->mWndPick->createWidget<MultiList2>("MultiListBox",8,8,400,800, Align::Left | Align::VStretch);
	liRd = lp;  lp->eventListChangePosition += newDelegate(this, &CGui::listPickRd);
	lp->setColour(Colour(0.9,0.8,0.7));  lp->setInheritsAlpha(false);
	
	lp->removeAllColumns();  lp->removeAllItems();
	lp->addColumn("#90C0F0", 25);
	lp->addColumn("#FFE0D0"+TR("#{GrMaterial}"), 157);
	lp->addColumn("#80E0E0"+TR("#{Surface}"), 80);
	lp->addColumn(" ", 20);
	liPickW[3] = 280;
	lp->addItem("#102030J", 0);  lp->setSubItemNameAt(1,0, "#102030");  // ""

	for (i=0; i < data->pre->rd.size(); ++i)
	{	const PRoad& t = data->pre->rd[i];
		String c = gcom->scnClr[gcom->scnN[t.sc]];  if (c.empty())  c = "#000000";
		lp->addItem(c+ t.sc, 0);  l = lp->getItemCount()-1;

		lp->setSubItemNameAt(1,l, c+ t.mtr);
		String su = t.surfName;  if (su.substr(0,4)=="road")  su = su.substr(4, su.length());
		lp->setSubItemNameAt(2,l, c+ su);
	}
	
	// todo: sort,filter pick lists..
	//lp->mSortColumnIndex = pSet->tracks_sort;
	//lp->mSortUp = pSet->tracks_sortup;

    //TrackListUpd(true);  //upd
	//listTrackChng(trkList,0);

	

	///  [Track]
	//------------------------------------------------------------------------
	gcom->sListTrack = pSet->gui.track;  //! set last
	gcom->bListTrackU = pSet->gui.track_user;
	sCopyTrack = "";  //! none
	bCopyTrackU = 0;
	
	//  text desc
	Edt(gcom->trkDesc[0], "TrackDesc", editTrkDesc);
	trkName = fEd("TrackName");
	if (trkName)  trkName->setCaption(pSet->gui.track);

	gcom->GuiInitTrack();
	
	//  btn  new, rename, delete
	Btn("TrackNew",		btnTrackNew);
	Btn("TrackRename",	btnTrackRename);
	Btn("TrackDelete",	btnTrackDel);
	
    //  load = new game
    for (int i=1; i<=2; ++i)
    {	Btn("NewGame"+toStr(i), btnNewGame);  }

	CreateGUITweakMtr();
	

	///  3d view []  (veget models, objects)
	//--------------------------------------------
	//rndCanvas = mGUI->findWidget<Canvas>("CanVeget");  //?
	viewCanvas = app->mWndEdit->createWidget<Canvas>("Canvas", GetViewSize(), Align::Stretch);
	viewCanvas->setInheritsAlpha(false);
	viewCanvas->setPointer("hand");
	viewCanvas->setVisible(false);
	viewBox->setCanvas(viewCanvas);
	viewBox->setBackgroundColour(Colour(0.32,0.35,0.37,0.7));
	viewBox->setAutoRotation(true);
	viewBox->setMouseRotation(true);
	

	bGI = true;  // gui inited, gui events can now save vals

	LogO(String("::: Time Init Gui: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
}
MainMachineEvent SponsorsState::update(MainMachineInfo &info)
{
	Ogre::Timer timer;
	float timeStamp = 0;
	MainMachineEvent result = MME_DONE;
	Ogre::Real frameTime = 0;
	float press = false;

	// check we have loaded both overlays
	ASSERT(mFader);
	ASSERT(mOverlay);

	// here is the main loop
	bool running = true;
	mAccumTime = mFaderTime;
	mFader->show();
	mOverlay->show();
	while(running) {
		timeStamp = timer.getMilliseconds();

		GLOBAL_KEYBOARD->capture();
		if(GLOBAL_KEYBOARD->isKeyDown(OIS::KC_ESCAPE)){
			break;
		}

		// depending on the state we call the function
		switch(mState){
		case STATE_FADE_IN:
			if(enterFade(frameTime)){
				mState = STATE_SPONSORS;
				mAccumTime = 0;
				mFader->hide();
			}
			break;
		case STATE_SPONSORS:
			if(showSponsors(frameTime)){
				mState = STATE_FADE_OUT;
				mAccumTime = 0;
				mFader->show();
			}
			break;
		case STATE_FADE_OUT:
			if(exitFade(frameTime)){
				mState = STATE_END;
			}
			break;
		case STATE_END:
			running = false;
			break;
		default:
			ASSERT(false);
		}

		// render the frame
		if(!GLOBAL_ROOT->renderOneFrame()){
			result = MME_DONE; //TODO: poner un erro real aca
			break;
		}

		// This must be called when we use the renderOneFrame approach
		Ogre::WindowEventUtilities::messagePump();

		frameTime = (timer.getMilliseconds() - timeStamp) * 0.001;
	}

	return result;
}
//  Create Scene
//-------------------------------------------------------------------------------------
void App::createScene()  // once, init
{
	//  prv tex
	int k=1024;
	prvView.Create(k,k,"PrvView");
	prvRoad.Create(k,k,"PrvRoad");
	 prvTer.Create(k,k,"PrvTer");

	scn->roadDens.Create(k+1,k+1,"RoadDens");
	
	///  ter lay tex
	for (int i=0; i < 6; ++i)
	{	String si = toStr(i);
		scn->texLayD[i].SetName("layD"+si);
		scn->texLayN[i].SetName("layN"+si);
	}


	//  camera
	asp = float(mWindow->getWidth())/float(mWindow->getHeight());
	mCamera->setFarClipDistance(pSet->view_distance*1.1f);
	mCamera->setNearClipDistance(0.1f);

	//  cam pos from last set
	mCamera->setPosition(Vector3(pSet->cam_x,pSet->cam_y,pSet->cam_z));
	mCamera->setDirection(Vector3(pSet->cam_dx,pSet->cam_dy,pSet->cam_dz).normalisedCopy());
	mViewport->setVisibilityMask(RV_MaskAll);  // hide prv cam rect

	//  tex fil
	MaterialManager::getSingleton().setDefaultTextureFiltering(TFO_ANISOTROPIC);
	MaterialManager::getSingleton().setDefaultAnisotropy(pSet->anisotropy);

	Ogre::Timer ti;


	//  data load xml
	scn->data->Load();
	scn->sc->pFluidsXml = scn->data->fluids;
	scn->sc->pReverbsXml = scn->data->reverbs;
	
	//  surfaces.cfg
	LoadAllSurfaces();
	
	LogO(String("::: Time load xmls: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");


	postInit();  // material factory

	//  gui  * * *
	if (pSet->startInMain)
		pSet->isMain = true;
		
	bGuiFocus = false/*true*/;  bMoveCam = true;  //*--

	gui->InitGui();
	

	///__  All  #if 0  in Release !!!

	///  _Tool_ scene  ...................
	#if 0
	gui->ToolSceneXml();
	exit(0);
	#endif
	
	///  _Tool_	warnings  ................
	///  takes some time
	#if 0
	gui->ToolTracksWarnings();
	exit(0);
	#endif
	

	TerCircleInit();
	createBrushPrv();
	
	///  _Tool_ brushes prv  .............
	#if 0
	gui->ToolBrushesPrv();
	#endif
		

	//  load
	if (pSet->autostart)
		LoadTrack();

	if (!pSet->autostart)
	{	bGuiFocus = true;  UpdVisGui();	}

	iObjTNew = 0;
	//SetObjNewType(0);  //?white


	gui->chkInputBar(0);  // upd vis
	gui->chkCamPos(0);
	gui->chkFps(0);
}
void App::LoadTrackEv()
{
	Ogre::Timer ti;
	NewCommon(false);  // full destroy
	iObjCur = -1;

	scn->DestroyRoad();
	scn->DestroyPace();
	

	// load scene
	scn->sc->LoadXml(gcom->TrkDir()+"scene.xml");
	scn->sc->vdr = IsVdrTrack();
	if (scn->sc->vdr)  scn->sc->ter = false;
	
	//  water RTT recreate
	scn->UpdateWaterRTT(mCamera);
	
	BltWorldInit();

	UpdWndTitle();

	scn->CreateFluids();

	scn->CreateWeather();


	//  set sky tex name for water
	sh::MaterialInstance* m = mFactory->getMaterialInstance(scn->sc->skyMtr);
	std::string skyTex = sh::retrieveValue<sh::StringValue>(m->getProperty("texture"), 0).get();
	sh::Factory::getInstance().setTextureAlias("SkyReflection", skyTex);
	sh::Factory::getInstance().setTextureAlias("CubeReflection", "ReflectionCube");


	bNewHmap = false;/**/
	scn->CreateTerrain(bNewHmap, scn->sc->ter);

	if (track)
	if (scn->sc->vdr)  // vdrift track
	{
		if (!LoadTrackVdr(pSet->gui.track))
			LogO("Error during track loading: " + pSet->gui.track);
		
		CreateVdrTrack(pSet->gui.track, track);
		CreateVdrTrackBlt();
	}


	//  road ~
	scn->road = new SplineRoad(this);
	scn->road->Setup("sphere.mesh", pSet->road_sphr, scn->terrain, mSceneMgr, mCamera);
	scn->road->LoadFile(gcom->TrkDir()+"road.xml");
	scn->UpdPSSMMaterials();
	
	//  pace ~ ~
	scn->pace = new PaceNotes(pSet);
	scn->pace->Setup(mSceneMgr, mCamera, scn->terrain, gui->mGui, mWindow);
	
	
	/// HW_Inst Test  * * *
	//inst = new Instanced();
	//inst->Create(mSceneMgr,"sphere_inst.mesh");
	
	
	CreateObjects();

	if (pSet->bTrees && scn->sc->ter)
		scn->CreateTrees();  // trees after objects so they aren't inside them


	//  updates after load
	//--------------------------
	gcom->ReadTrkStats();
	gui->SetGuiFromXmls();  ///
	
	Rnd2TexSetup();
	//UpdVisGui();
	//UpdStartPos();
	UpdEditWnds();  //

	try {
	TexturePtr tex = TextureManager::getSingleton().getByName("waterDepth.png");
	if (!tex.isNull())
		tex->reload();
	} catch(...) {  }

	gui->Status("#{Loaded}", 0.5,0.7,1.0);
	
	if (pSet->check_load)
		gui->WarningsCheck(scn->sc, scn->road);

	LogO(String("::: Time Load Track: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
}
Exemple #12
0
void World::processInput()
{
	using namespace OIS;
	static Ogre::Timer timer;
	static unsigned long lastTime = 0;
	unsigned long currentTime = timer.getMilliseconds();

	//Calculate the amount of time passed since the last frame
	Real timeScale = (currentTime - lastTime) * 0.001f;
	if (timeScale < 0.001f)
		timeScale = 0.001f;
	lastTime = currentTime;

	//Get the current state of the keyboard and mouse
	keyboard->capture();
	mouse->capture();
	const OIS::MouseState &ms = mouse->getMouseState();

	//[NOTE] When the left mouse button is pressed, add trees
	if (ms.buttonDown(MB_Left)){
		//Choose a random tree rotation
		Degree yaw = Degree(Math::RangeRandom(0, 360));

		//Choose a random scale
		Real scale = Math::RangeRandom(0.5f, 0.6f);

		//Calculate a position
		Ogre::Vector3 centerPos = camera->getPosition() + (camera->getOrientation() * Ogre::Vector3(0, 0, -50));
		Radian rndAng = Radian(Math::RangeRandom(0, Math::TWO_PI));
		Real rndLen = Math::RangeRandom(0, 20);
		centerPos.x += Math::Sin(rndAng) * rndLen;
		centerPos.z += Math::Cos(rndAng) * rndLen;

		//And add the tree
		treeLoader->addTree(myTree, centerPos, yaw, scale);
		//[NOTE] Dynamic trees are very easy, as you can see. No additional setup is required for
		//the dynamic addition / removal of trees to work. Simply call addTree(), etc. as needed.
	}

	//[NOTE] When the right mouse button is pressed, delete trees
	if (ms.buttonDown(MB_Right)){
		//Calculate a position in front of the camera
		Ogre::Vector3 centerPos = camera->getPosition() + (camera->getOrientation() * Ogre::Vector3(0, 0, -50));

		//Delete trees within 20 units radius of the center position
		treeLoader->deleteTrees(centerPos, 20);
		//[NOTE] Dynamic trees are very easy, as you can see. No additional setup is required for
		//the dynamic addition / removal of trees to work. Simply call deleteTrees(), etc. as needed.
	}

	//Always exit if ESC is pressed
	if (keyboard->isKeyDown(KC_ESCAPE))
		running = false;

	//Reload the scene if R is pressed
	static bool reloadedLast = false;
	if (keyboard->isKeyDown(KC_R) && !reloadedLast){
		unload();
		load();
		reloadedLast = true;
	}
	else {
		reloadedLast = false;
	}

	//Update camera rotation based on the mouse
	camYaw += Radian(-ms.X.rel / 200.0f);
	camPitch += Radian(-ms.Y.rel / 200.0f);
	camera->setOrientation(Quaternion::IDENTITY);
	camera->pitch(camPitch);
	camera->yaw(camYaw);

	//Allow the camera to move around with the arrow/WASD keys
	Ogre::Vector3 trans(0, 0, 0);
	if (keyboard->isKeyDown(KC_UP) || keyboard->isKeyDown(KC_W))
		trans.z = -1;
	if (keyboard->isKeyDown(KC_DOWN) || keyboard->isKeyDown(KC_S))
		trans.z = 1;
	if (keyboard->isKeyDown(KC_RIGHT) || keyboard->isKeyDown(KC_D))
		trans.x = 1;
	if (keyboard->isKeyDown(KC_LEFT) || keyboard->isKeyDown(KC_A))
		trans.x = -1;
	if (keyboard->isKeyDown(KC_PGUP) || keyboard->isKeyDown(KC_E))
		trans.y = 1;
	if (keyboard->isKeyDown(KC_PGDOWN) || keyboard->isKeyDown(KC_Q))
		trans.y = -1;

	//Shift = speed boost
	if (keyboard->isKeyDown(KC_LSHIFT) || keyboard->isKeyDown(KC_RSHIFT))
		trans *= 2;

	trans *= 100;
	camera->moveRelative(trans * timeScale);

	//Make sure the camera doesn't go under the terrain
	Ogre::Vector3 camPos = camera->getPosition();
	float terrY = HeightFunction::getTerrainHeight(camPos.x, camPos.z);
	if (camPos.y < terrY + 5 || keyboard->isKeyDown(KC_SPACE)){		//Space = walk
		camPos.y = terrY + 5;
		camera->setPosition(camPos);
	}
}
void World::processInput()
{
	using namespace OIS;
	static Ogre::Timer timer;
	static unsigned long lastTime = 0;
	unsigned long currentTime = timer.getMilliseconds();

	//Calculate the amount of time passed since the last frame
	Real timeScale = (currentTime - lastTime) * 0.001f;
	if (timeScale < 0.001f)
		timeScale = 0.001f;
	lastTime = currentTime;

	//Get the current state of the keyboard and mouse
	keyboard->capture();
	mouse->capture();

	//Always exit if ESC is pressed
	if (keyboard->isKeyDown(OIS::KC_ESCAPE))
		running = false;

	//Reload the scene if R is pressed
	static bool reloadedLast = false;
	if (keyboard->isKeyDown(OIS::KC_R) && !reloadedLast){
		unload();
		load();
		reloadedLast = true;
	}
	else {
		reloadedLast = false;
	}

	//Get mouse movement
	const OIS::MouseState &ms = mouse->getMouseState();

	//Update camera rotation based on the mouse
	camYaw += Radian(-ms.X.rel / 200.0f);
	camPitch += Radian(-ms.Y.rel / 200.0f);
	camera->setOrientation(Quaternion::IDENTITY);
	camera->pitch(camPitch);
	camera->yaw(camYaw);

	//Allow the camera to move around with the arrow/WASD keys
	Ogre::Vector3 trans(0, 0, 0);
	if (keyboard->isKeyDown(KC_UP) || keyboard->isKeyDown(KC_W))
		trans.z = -1;
	if (keyboard->isKeyDown(KC_DOWN) || keyboard->isKeyDown(KC_S))
		trans.z = 1;
	if (keyboard->isKeyDown(KC_RIGHT) || keyboard->isKeyDown(KC_D))
		trans.x = 1;
	if (keyboard->isKeyDown(KC_LEFT) || keyboard->isKeyDown(KC_A))
		trans.x = -1;
	if (keyboard->isKeyDown(KC_PGUP) || keyboard->isKeyDown(KC_E))
		trans.y = 1;
	if (keyboard->isKeyDown(KC_PGDOWN) || keyboard->isKeyDown(KC_Q))
		trans.y = -1;

	//Shift = speed boost
	if (keyboard->isKeyDown(KC_LSHIFT) || keyboard->isKeyDown(KC_RSHIFT))
		trans *= 4;
	else
		trans *= 0.5f;

	trans *= 30;
	camera->moveRelative(trans * timeScale);

	//Make sure the camera doesn't go under the terrain
	Ogre::Vector3 camPos = camera->getPosition();
	float terrY = HeightFunction::getTerrainHeight(camPos.x, camPos.z);
	if (camPos.y < terrY + 1.5 || !keyboard->isKeyDown(KC_SPACE)){		//Space = walk
		camPos.y = terrY + 1.5;
		camera->setPosition(camPos);
	}
}
//  Setup
//-------------------------------------------------------------------------------------
bool BaseApp::setup()
{
	Ogre::Timer ti;
	LogO("*** start setup ***");

	if (pSet->rendersystem == "Default")
	{
		#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
		pSet->rendersystem = "Direct3D9 Rendering Subsystem";
		#else
		pSet->rendersystem = "OpenGL Rendering Subsystem";
		#endif
	}
	//LogManager::getSingleton().setLogDetail(LL_BOREME);  //-

	#ifdef _DEBUG
	#define D_SUFFIX "_d"
	#else
	#define D_SUFFIX ""
	#endif

	//  when show ogre dialog is on, load both rendersystems so user can select
	if (pSet->ogre_dialog)
	{
		mRoot->loadPlugin(PATHMANAGER::OgrePluginDir() + "/RenderSystem_GL" + D_SUFFIX);
		#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
		mRoot->loadPlugin(PATHMANAGER::OgrePluginDir() + "/RenderSystem_Direct3D9" + D_SUFFIX);
		#endif
	}else{
		if (pSet->rendersystem == "OpenGL Rendering Subsystem")
			mRoot->loadPlugin(PATHMANAGER::OgrePluginDir() + "/RenderSystem_GL" + D_SUFFIX);
		else if (pSet->rendersystem == "Direct3D9 Rendering Subsystem")
			mRoot->loadPlugin(PATHMANAGER::OgrePluginDir() + "/RenderSystem_Direct3D9" + D_SUFFIX);
	}

	mRoot->loadPlugin(PATHMANAGER::OgrePluginDir() + "/Plugin_ParticleFX" + D_SUFFIX);

	setupResources();

	if (!configure())
		return false;

	mSceneMgr = mRoot->createSceneManager(/*ST_GENERIC/**/Ogre::ST_EXTERIOR_FAR/**/);

	#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 9, 0) 
	Ogre::OverlaySystem* pOverlaySystem = new Ogre::OverlaySystem();
	mSceneMgr->addRenderQueueListener(pOverlaySystem);
	#endif

	createCamera();

	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	mSceneMgr->setFog(Ogre::FOG_NONE);

	loadResources();

	baseInitGui();

	createFrameListener();

	LogO(Ogre::String("::: Time Ogre Start: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");

	createScene();

	return true;
}
Exemple #15
0
/*!
 * Starts the main event loop. This function does not return, unless the
 * application is supposed to quit - either by closing the rendering window or
 * by telling the \ref InputHandler to quit (see \ref InputHandler::queueQuit).
 */
void TestApp::startEventLoop()
{
//    try {
        Ogre::Timer timer;
        unsigned long lastFrameStarted = timer.getMilliseconds();

        mFrameCount = 0;

    #ifdef USE_CALLGRIND
        CALLGRIND_START_INSTRUMENTATION;
        CALLGRIND_TOGGLE_COLLECT; // switch collect off
    #endif
        while (!mInputHandler->getWantQuit() && (!mRenderWindow->isClosed() || !mUseGUI))
		{
            mFrameHistory->startFrame();

            // emulate Ogre's timeSinceLastFrame feature
            unsigned long now = timer.getMilliseconds();
            float timeSinceLastFrame = ((float)(now - lastFrameStarted)) / 1000.0f;
            lastFrameStarted = now;

            mInputHandler->captureInput(timeSinceLastFrame);
            Ogre::WindowEventUtilities::messagePump();

            // AB: note: a "scene frame" is not necessarily a "graphic frame".
            // -> the collision detection library may be called more often or less
            //    often than ogre.
            //    usually we should NOT couple the scene speed to the rendering
            //    speed, otherwise the scene will be VERY fast with a newer graphic
            //    card
            //
            //    we do this here atm for the sake of simplicity only. we really
            //    should use a timer instead.
            if (!mInputHandler->getPause() )
			{
                
                if (!mInputHandler->isChecked("PauseMovements"))
				{
                    mSceneUpdateHistory->startFrame();
                    mScene->beginNextSceneFrame();
                }

                    mSceneUpdateHistory->stopFrame();
            }

            if (mUseGUI)
			{
                if (!mGui->updateGui(mInputHandler->getPause()))
				{
                    mInputHandler->queueQuit();
                }

                mGraphicFrameHistory->startFrame();
                mOgreRoot->renderOneFrame();
                mGraphicFrameHistory->stopFrame();
            }

            mFrameHistory->stopFrame();

            mFrameCount++;
            if (mMaxFrameCount > 0 && mFrameCount >= mMaxFrameCount)
			{
                mInputHandler->queueQuit();
            }
        }
    //} catch (Exception e) {
    //    std::cerr   << "Unhandled exception reached main-program: \n"
    //            << e.getErrorMessage() <<std::endl;
    //    e.printBacktrace();
    //    exit(1);
    //}
}
Exemple #16
0
// This dummy rouytine lets us test some of the rendering when we don't have
// a Kinect
bool OgreCPP::noKinectBeforeFrame()
{
    static Ogre::Timer a;

    static uint32_t lastTimeMS;
    static uint32_t curTimeMS;

    curTimeMS = a.getMilliseconds();
    uint32_t timeDiffMS = curTimeMS - lastTimeMS;

    if ( timeDiffMS > 0 )
    {
      printf( "FPS = %f\n", 1000.0/(float)timeDiffMS );//1.0/((float)timeDiffMS/1000.0) );
    }
    lastTimeMS = curTimeMS;

    // Draw the crowd
    uint32_t numCrowdMembers = mCrowdMembers.size();

    // Check to see if we should add a new crowd member
    if ( numCrowdMembers < 4800 && mRecordingGapTimer.getMilliseconds() > 1 ) //TIME_BETWEEN_RECORDINGS_MS )
    {
        // Draw a moving rectangle as a stand in for a crowd member
        memset( mpImageData, 0, RECORDED_DATA_SIZE );
        memset( mpLowResImageData, 0, LOW_RES_RECORDED_DATA_SIZE );

        static const uint32_t PERSON_WIDTH = SMALL_FRAME_WIDTH/10;
        static const uint32_t PERSON_HEIGHT = SMALL_FRAME_HEIGHT/3;
        for ( uint32_t frameIdx = 0; frameIdx < NUM_FRAMES_TO_RECORD; frameIdx++ )
        {
            uint32_t leftX = 4*PERSON_WIDTH + ((float)frameIdx/(float)NUM_FRAMES_TO_RECORD)*2.0*(float)PERSON_WIDTH;

            for ( uint32_t y = SMALL_FRAME_HEIGHT - PERSON_HEIGHT; y < SMALL_FRAME_HEIGHT; y++ )
            {
                for ( uint32_t x = leftX; x < leftX + PERSON_WIDTH; x++  )
                {
                    int32_t smallPixelIdx = frameIdx*SMALL_FRAME_WIDTH*SMALL_FRAME_HEIGHT
                        + y*SMALL_FRAME_WIDTH + x;

                    mpImageData[ smallPixelIdx ] = 0xFF;

                    if ( y%LOW_RES_DIVIDE == 0 && x%LOW_RES_DIVIDE == 0 )
                    {
                        int32_t lowResPixelIdx = frameIdx*LOW_RES_SMALL_FRAME_WIDTH*LOW_RES_SMALL_FRAME_HEIGHT
                            + y/LOW_RES_DIVIDE*LOW_RES_SMALL_FRAME_WIDTH + x/LOW_RES_DIVIDE;
                        mpLowResImageData[ lowResPixelIdx ] = 0xFF;
                    }
                }
            }
        }


        createNewCrowdMember( 0.5 );
        

        mbRecording = false;
        mRecordingGapTimer.reset();     // Reset time so that there's a gap between recording
        //`printf( "Got frame\n" );

        printf( "Crowd size is now %i\n", (int32_t)mCrowdMembers.size() );
    }

    return true;
}
Exemple #17
0
bool OgreCPP::beforeFrame(void)
{	
	static Ogre::Timer a;
	
	static uint32_t lastTimeMS;
	static uint32_t curTimeMS;
	
	curTimeMS = a.getMilliseconds();
	uint32_t timeDiffMS = curTimeMS - lastTimeMS;
	
//	if ( timeDiffMS > 0 )
//	{
//		printf( "FPS = %f\n", 1000.0/(float)timeDiffMS );//1.0/((float)timeDiffMS/1000.0) );
//	}
	lastTimeMS = curTimeMS;
	
	const int32_t MAX_DEPTH_MM = 10000;
	const float FOCAL_LENGTH = 0.525f;	// Focal length in metres
	const float FADE_START_XZ_DISTANCE = 0.5f;
	const float FADE_MAX_XZ_DISTANCE = 6.0f;
	
	xn::SceneMetaData sceneMD;
	xn::DepthMetaData depthMD;
	
	mpKinectController->getContext().WaitAndUpdateAll();
	mpKinectController->getDepthGenerator().GetMetaData( depthMD );
	mpKinectController->getUserGenerator().GetUserPixels( 0, sceneMD ); // Scene data is bitmap with just user id's for pixels
	
	XnUserID userIdx[15];
	XnUInt16 numUsers = 15;
	mpKinectController->getUserGenerator().GetUsers( userIdx, numUsers );
	
	numUsers = mpKinectController->getUserGenerator().GetNumberOfUsers();
	
	// Confirm that a user is in the centre of the screen
	const XnDepthPixel* pScene = sceneMD.Data();

	pScene += SMALL_FRAME_WIDTH/2;
	bool bUserInCentreOfScreen = false;
	int maxCount = sceneMD.XRes() *  sceneMD.YRes();
	for ( uint32_t x = SMALL_FRAME_WIDTH/2; x < maxCount; x+=SMALL_FRAME_WIDTH )
	{
		if ( pScene[x] > 0 )
		{
			// User pixel found
			bUserInCentreOfScreen = 1;
			break;
		}
	}
	
	if ( !bUserInCentreOfScreen && RESET_TIMER_IF_NO_USER )
	{
		// Restart the time if there are no users to record
		mRecordingGapTimer.reset();
	}

	// Start recording if we see a person
	if ( bUserInCentreOfScreen && (numUsers > 0)
		&& (!mbRecording) && (mRecordingGapTimer.getMilliseconds() > TIME_BETWEEN_RECORDINGS_MS) )
	{
		printf("START RECORDING\n");
		mbRecording = true;
		memset( mpImageData, 0, RECORDED_DATA_SIZE );
		memset( mpLowResImageData, 0, LOW_RES_RECORDED_DATA_SIZE );
		mAnimationTimer.reset();
		mRecordingFrameIdx = 0;
	}
	
	/* Build an accumulative histogram to work out the colour for each point */
	uint32_t depthHist[ MAX_DEPTH_MM ];
	memset( depthHist, 0, sizeof( depthHist ) );
	uint32_t numPoints = 0;	
	const XnDepthPixel* pDepth = depthMD.Data();
	int32_t recordingPixelStepX = depthMD.XRes() / SMALL_FRAME_WIDTH;
	int32_t recordingPixelStepY = depthMD.YRes() / SMALL_FRAME_HEIGHT;
	if ( recordingPixelStepX <= 0 ) recordingPixelStepX = 1;
	if ( recordingPixelStepY <= 0 ) recordingPixelStepY = 1;
	int32_t lowResRecordingPixelStepX = depthMD.XRes() / LOW_RES_SMALL_FRAME_WIDTH;
    int32_t lowResRecordingPixelStepY = depthMD.YRes() / LOW_RES_SMALL_FRAME_HEIGHT;
    if ( lowResRecordingPixelStepX <= 0 ) lowResRecordingPixelStepX = 1;
    if ( lowResRecordingPixelStepY <= 0 ) lowResRecordingPixelStepY = 1;
	
	// loop through data to look for users
	for ( uint32_t y = 0; y < depthMD.YRes(); y++ ){
		for ( uint32_t x = 0; x < depthMD.XRes(); x++ ){
			XnUInt16 value = *pDepth;
			if ( 0 != value ){
				depthHist[ value ]++;
				numPoints++;
			}
			pDepth++;
		}
	}
	
	
	for ( uint32_t i = 1; i < MAX_DEPTH_MM; i++ ){
		depthHist[ i ] += depthHist[ i - 1 ];
	}
	
	if ( numPoints > 0 ){
		for ( uint32_t i = 1; i < MAX_DEPTH_MM; i++ ){
			depthHist[ i ] = (unsigned int)(256 * (1.0f - ((float)depthHist[ i ] / numPoints)));
		}
	}
	/* end of histagram setup */
	

	
	//	/* LOOP THROUGH DATA TO FIND USER */
	//	const XnDepthPixel* pScene = sceneMD.Data();
	//	for ( uint32_t y = 0; y < sceneMD.YRes(); y++ ){
	//		for ( uint32_t x = 0; x < sceneMD.XRes(); x++ ){
	//			XnUInt16 value = *pScene;
	//			
	//			//if (value > 1) {
	//				value = 0;
	//			//}
	//			
	//			//printf("%d ",value);
	//			pScene++;
	//		}
	//		//printf("\n");
	//	}
	//	/* --------------------- */
	
	
	
	
	// Update the point cloud to reflect the depth data
	pDepth = depthMD.Data();
	const XnLabel* pLabels = sceneMD.Data();
	mpRosPointCloud->clear();
	ogre_tools::PointCloud::Point* pPoints = new ogre_tools::PointCloud::Point[ numPoints ];
	int32_t pointIdx = 0;
	int32_t width = depthMD.XRes();
	int32_t height = depthMD.YRes();
	int32_t halfWidth = width / 2;
	int32_t halfHeight = height / 2;
	
	for ( int32_t y = 0; y < height; y++ )
	{
		for ( int32_t x = 0; x < width; x++ )
		{
			XnUInt16 value = *pDepth;
			XnLabel label = *pLabels;
			XnUInt32 colorId = label % NUM_COLOURS;
			
			float fade = 1.0;
			
			if (label == 0) { // Ignore background
				colorId = NUM_COLOURS;
			}
			
			float worldZ = (float)(*pDepth)/1000.0;		// Convert from mm to m
			float worldX = (((float)(x-halfWidth)/1000.0)*worldZ) / FOCAL_LENGTH;
			
			float distanceXZ = sqrtf( worldX*worldX + worldZ*worldZ );
			if ( distanceXZ > FADE_MAX_XZ_DISTANCE ){
				fade = 0.0f;
			}
			else if ( distanceXZ > FADE_START_XZ_DISTANCE ){
				fade = 1.0 - (distanceXZ - FADE_START_XZ_DISTANCE)/(FADE_MAX_XZ_DISTANCE - FADE_START_XZ_DISTANCE);
			}
			
			// I think this is purely for showing the background? ... rt user too!
			// this is where the rt user position is defined
			if ( /*mbRecording*/ (0 != value) && (fade > 0.0) && (SHOW_BACKGROUND || label != 0))
			{
				float worldZ = (float)(*pDepth)/1000.0;		// Convert from mm to m
				float worldX = (((float)(x-halfWidth)/1000.0)*worldZ) / FOCAL_LENGTH;
				float worldY = (((float)(y-halfHeight)/1000.0)*worldZ) / FOCAL_LENGTH;
				//float worldY = (((float)(((height-1)-y)-halfHeight)/1000.0)*worldZ) / FOCAL_LENGTH;
				
				float histValue = (float)depthHist[ value ]/255.0;
				
				/* COLOUR REAL TIME USER */
				colorId = 10; // force user to be white
				
				pPoints[ pointIdx ].setColor(fade * histValue * COLOURS[ colorId ][ 0 ],
											 fade * histValue * COLOURS[ colorId ][ 1 ],
											 fade * histValue * COLOURS[ colorId ][ 2 ] );
				
				pPoints[ pointIdx ].x = worldX;
				pPoints[ pointIdx ].y = worldY;
				pPoints[ pointIdx ].z = worldZ;
				
				pointIdx++;
				
				// Records a pixel if...
				// We're recording and the label is a user
				// and also if we get to a pixel whose coordinates are a multiple of the pixel
				// recording step. We don't record every pixel as the recorded image is smaller
				// than the depth bitmap
				if(mbRecording && (label != 0)
				    && (x%recordingPixelStepX == 0) && (y%recordingPixelStepY == 0))
				{
					int32_t smallFrameX = x / recordingPixelStepX;
					int32_t smallFrameY = y / recordingPixelStepY;
					
					int32_t smallPixelIdx = (mRecordingFrameIdx*SMALL_FRAME_WIDTH*SMALL_FRAME_HEIGHT)
					    + (smallFrameY*SMALL_FRAME_WIDTH) + smallFrameX;
					
					// Calculate alpha to fade image out towards the edges
					uint8_t alpha = 0xF;
					int32_t absCentreDiffX = abs( smallFrameX - SMALL_FRAME_WIDTH/2 );
					if ( ALPHA_FADE_RECORDING_EDGE && absCentreDiffX > ABS_ALPHA_FADE_START_X )
					{
						alpha = (uint8_t)((1.0f - (float)(absCentreDiffX - ABS_ALPHA_FADE_START_X) / (float)(SMALL_FRAME_WIDTH/2 - ABS_ALPHA_FADE_START_X)) * (float)0xF);
					}

					uint8_t intensity = 0xF; //(uint8_t)(fade * histValue * (float)0xF);
					uint8_t pixelValue = (alpha << 4) | intensity;
					mpImageData[ smallPixelIdx ] = pixelValue;

					// Do a further test to see if we should also record for the low res image
					if ( x%lowResRecordingPixelStepX == 0 && y%lowResRecordingPixelStepY == 0 )
					{
					    int32_t lowResX = x / lowResRecordingPixelStepX;
                        int32_t lowResY = y / lowResRecordingPixelStepY;

                        int32_t lowResPixelIdx = (mRecordingFrameIdx*LOW_RES_SMALL_FRAME_WIDTH*LOW_RES_SMALL_FRAME_HEIGHT)
                            + (lowResY*LOW_RES_SMALL_FRAME_WIDTH) + lowResX;

                        mpLowResImageData[ lowResPixelIdx ] = pixelValue;
					}
				}
			}
			
			pDepth++;
			pLabels++;
		}
	}
	
	mpRosPointCloud->addPoints( pPoints, pointIdx );
	delete [] pPoints;
	
	// Check to see if we can stop recording
	if ( mbRecording )
	{
		mRecordingFrameIdx++;
		if ( mRecordingFrameIdx >= NUM_FRAMES_TO_RECORD )
		{
			createNewCrowdMember( (float)mAnimationTimer.getMilliseconds() / 1000.0 );

			mbRecording = false;
			mRecordingGapTimer.reset();		// Reset time so that there's a gap between recording
			
			printf("STOP RECORDING\n");
		}
	}
	
	//printf("users: %d recording: %d \n", numUsers, mbRecording);
	
	return true;
}
Exemple #18
0
///  Shadows config
//---------------------------------------------------------------------------------------------------
void CScene::changeShadows()
{	
	Ogre::Timer ti;
	
	//  get settings
	SETTINGS* pSet = app->pSet;
	bool enabled = pSet->shadow_type != Sh_None;
	bool bDepth = pSet->shadow_type >= Sh_Depth;
	bool bSoft = pSet->shadow_type == Sh_Soft;
	
	pSet->shadow_size = std::max(0,std::min(ciShadowSizesNum-1, pSet->shadow_size));
	int fTex = ciShadowSizesA[pSet->shadow_size], fTex2 = fTex/2;
	int num = pSet->shadow_count;

	sh::Vector4* fade = new sh::Vector4(
		pSet->shadow_dist,
		pSet->shadow_dist * 0.6, // fade start
		0, 0);

	sh::Factory* mFactory = app->mFactory;
	SceneManager* mSceneMgr = app->mSceneMgr;

	if (terrain)
		mFactory->setTextureAlias("TerrainLightMap", terrain->getLightmap()->getName());

		
	// disable 4 shadow textures (does not work because no texcoord's left in shader)
	if (num == 4)  num = 3;


	if (!enabled)
		mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
	else
	{
		// General scene setup
		//mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
		mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);
		mSceneMgr->setShadowFarDistance(pSet->shadow_dist);  // 3000
		mSceneMgr->setShadowTextureCountPerLightType(Light::LT_DIRECTIONAL, num);

		if (num == 1)  // 1 tex, fast
		{
			ShadowCameraSetupPtr mShadowCameraSetup = ShadowCameraSetupPtr(new LiSPSMShadowCameraSetup());
			mSceneMgr->setShadowCameraSetup(mShadowCameraSetup);
		}else
		{	if (mPSSMSetup.isNull())  // pssm
			{
				PSSMShadowCameraSetup* pssmSetup = new PSSMShadowCameraSetup();
				#ifndef SR_EDITOR
				pssmSetup->setSplitPadding(app->mSplitMgr->mCameras.front()->getNearClipDistance());
				pssmSetup->calculateSplitPoints(num, app->mSplitMgr->mCameras.front()->getNearClipDistance(), mSceneMgr->getShadowFarDistance());
				#else
				pssmSetup->setSplitPadding(app->mCamera->getNearClipDistance());
				pssmSetup->calculateSplitPoints(num, app->mCamera->getNearClipDistance(), app->mSceneMgr->getShadowFarDistance());
				#endif
				for (int i=0; i < num; ++i)
				{	//int size = i==0 ? fTex : fTex2;
					const Real cAdjfA[5] = {2, 1, 0.5, 0.25, 0.125};
					pssmSetup->setOptimalAdjustFactor(i, cAdjfA[std::min(i, 4)]);
				}
				mPSSMSetup.bind(pssmSetup);
			}
			mSceneMgr->setShadowCameraSetup(mPSSMSetup);
		}

		mSceneMgr->setShadowTextureCount(num);
		for (int i=0; i < num; ++i)
		{	int size = i==0 ? fTex : fTex2;
		
			PixelFormat pf;
			if (bDepth && !bSoft) pf = PF_FLOAT32_R;
			else if (bSoft) pf = PF_FLOAT16_RGB;
			else pf = PF_X8B8G8R8;
			
			mSceneMgr->setShadowTextureConfig(i, size, size, pf);
		}
		
		mSceneMgr->setShadowTextureSelfShadow(bDepth ? true : false);  //-?
		mSceneMgr->setShadowCasterRenderBackFaces((bDepth && !bSoft) ? true : false);

		mSceneMgr->setShadowTextureCasterMaterial(bDepth ? "shadowcaster_default" : "");
	}

	mSceneMgr->setShadowColour(Ogre::ColourValue(0,0,0,1));


#if 0  /// TEST overlays
	//  add overlay elements to show shadow or terrain maps
	OverlayManager& mgr = OverlayManager::getSingleton();
	Overlay* overlay = mgr.getByName("DebugOverlay");
	if (overlay)
		mgr.destroy(overlay);
	overlay = mgr.create("DebugOverlay");
	TexturePtr tex;

	#if 0  /// shadow
	for (int i = 0; i < pSet->shadow_count; ++i)
	{	
		TexturePtr tex = mSceneMgr->getShadowTexture(i);
	#else  /// terrain
	for (int i = 0; i < 2/*pSet->shadow_count*/; ++i)
	{	
		TexturePtr tex = !terrain ? mSceneMgr->getShadowTexture(i) :
			i==0 ? terrain->getCompositeMap() : terrain->getLightmap();
	#endif
		// Set up a debug panel to display the shadow
		if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + toStr(i)))
			MaterialManager::getSingleton().remove("Ogre/DebugTexture" + toStr(i));
		MaterialPtr debugMat = MaterialManager::getSingleton().create(
			"Ogre/DebugTexture" + toStr(i), rgDef);
			
		debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
		TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
		t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);

		OverlayContainer* debugPanel;
		
		// destroy container if exists
		try
		{
			if (debugPanel = static_cast<OverlayContainer*>(mgr.getOverlayElement("Ogre/DebugTexPanel" + toStr(i))))
				mgr.destroyOverlayElement(debugPanel);
		}
		catch (Ogre::Exception&) {}
		
		debugPanel = (OverlayContainer*)
			(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i)));
		debugPanel->_setPosition(0.8, i*0.31);  //aspect.. 0.25 0.24
		debugPanel->_setDimensions(0.2, 0.3);
		debugPanel->setMaterialName(debugMat->getName());
		debugPanel->show();
		overlay->add2D(debugPanel);
		overlay->show();
	}
#endif
	
	UpdPSSMMaterials();


	//  rebuild static geom after materials change
	if (vdrTrack)
	{
		vdrTrack->destroy();
		vdrTrack->build();
	}

	LogO(String("::: Time Shadows: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
}


/// . . . . . . . . 
void CScene::UpdPSSMMaterials()
{
	if (app->pSet->shadow_type == Sh_None)  return;
	
	if (app->pSet->shadow_count == 1)  // 1 tex
	{
		float dist = app->pSet->shadow_dist;
		sh::Vector3* splits = new sh::Vector3(dist, 0,0);  //dist*2, dist*3);
		sh::Factory::getInstance().setSharedParameter("pssmSplitPoints", sh::makeProperty<sh::Vector3>(splits));
		return;
	}
	
	if (!mPSSMSetup.get())  return;
	
	//--  pssm params
	PSSMShadowCameraSetup* pssmSetup = static_cast<PSSMShadowCameraSetup*>(mPSSMSetup.get());
	const PSSMShadowCameraSetup::SplitPointList& sp = pssmSetup->getSplitPoints();
	const int last = sp.size()-1;

	sh::Vector3* splits = new sh::Vector3(
		sp[std::min(1,last)], sp[std::min(2,last)], sp[std::min(3,last)] );

	sh::Factory::getInstance().setSharedParameter("pssmSplitPoints", sh::makeProperty<sh::Vector3>(splits));
}
void CGui::ThreadConvert()
{
	LogO("====----  Converting old replays and ghosts");
	Ogre::Timer ti;
	
	std::vector<string> paths, files[3];
	//  paths
	paths.push_back(PATHMANAGER::Ghosts() +"/easy");
	paths.push_back(PATHMANAGER::Ghosts() +"/normal");
	paths.push_back(PATHMANAGER::Replays());

	iConvPathCur = 0;  iConvPathAll = paths.size();
	iConvFiles = 0;  totalConv = 0;  totalConvNew = 0;  totalConvCur = 0;

	//  List files  ------------
	strlist li;  int p;
	Replay2 rpl;
	for (p=0; p < iConvPathAll; ++p)
	{	iConvPathCur = p;

		const string& path = paths[p];
		li.clear();
		PATHMANAGER::DirList(path, li, "rpl");
		iConvCur = 0;  iConvAll = li.size();

		for (strlist::iterator i = li.begin(); i != li.end(); ++i)
		{
			if (app->mShutDown)  return;
			String file = *i, s = path +"/"+ file;

			//Replay2 rpl;
			rpl.LoadFile(s, true);  // header
			if (rpl.header.ver <= 10)  // old, not converted, 10 was last 2.5
			{
				++iConvFiles;
				files[p].push_back(file);
				boost::uintmax_t size = fs::file_size(s);
				totalConv += size;
			}
			++iConvCur;
		}
		LogO("PATH: "+path+" total size:   "+fToStr( float(totalConv)/1000000.f, 2,5)+" MiB");
		LogO("PATH: "+path+" total after:  "+fToStr( float(totalConvNew)/1000000.f, 2,5)+" MiB");
	}
	LogO(String("::: Time Convert get list: ") + fToStr(ti.getMilliseconds()/1000.f,1,4) + " s");
	LogO("====----  Converting Start");

	iConvCur = 0;  iConvAll = iConvFiles;


	LogO(String("FILES to convert: ") + toStr(iConvFiles));

	//  Convert  ------------
	for (p=0; p < iConvPathAll; ++p)
	{	iConvPathCur = p;

		const string& path = paths[p];
		iConvCur = 0;  iConvAll = files[p].size();

		while (iConvCur < iConvAll && !app->mShutDown)
		{
			const string s = path +"/"+ files[p][iConvCur];
			//Replay2 rpl;
			rpl.LoadFile(s);  // converts old
			boost::uintmax_t size = fs::file_size(s);  // for progress
			totalConvCur += size;
			std::time_t tim = fs::last_write_time(s);

			rpl.SaveFile(s);  // same name, no backup
			fs::last_write_time(s, tim);  // restore original date
			boost::uintmax_t sizeNew = fs::file_size(s);
			totalConvNew += sizeNew;
			++iConvCur;
		}
	}

	//  Results  ------------
	bConvertRpl = false;
	LogO("====----  Converting Results");
	LogO("  Sizes");
	LogO("  old:   "+ fToStr( float(totalConv)/1000000.f, 2,5) +" MiB");
	LogO("  new:  "+ fToStr( float(totalConvNew)/1000000.f, 2,5) +" MiB");
	if (totalConvCur!=totalConv || totalConv==0){} else
	LogO("  ratio:  "+ fToStr(100.f* float(totalConvNew)/float(totalConv), 2,5) +" %");

	LogO(String("::: Time Convert: ") + fToStr(ti.getMilliseconds()/1000.f,1,4) + " s");
	LogO("====----  Converting End");
}
//----------------------------------------------------------------------------------------------------------------------------------
///  Load  (.car file)
//----------------------------------------------------------------------------------------------------------------------------------
bool CARDYNAMICS::Load(GAME* game, CONFIGFILE & c, ostream & error_output)
{
	pGame = game;
	Ogre::Timer ti;

	//bTerrain = false;
	string drive = "RWD";
	int version(1);
	c.GetParam("version", version);
	if (version > 2)
	{
		error_output << "Unsupported car version: " << version << endl;
		return false;
	}
	float temp_vec3[3];

	//load the engine
	{
		float mass, rpm_limit, inertia, friction,
			start_rpm, stall_rpm, fuel_consumption;
		MATHVECTOR<double,3> position;

		if (!c.GetParam("engine.rpm-limit", rpm_limit, error_output))  return false;
		engine.SetRpmMax(rpm_limit);

		if (!c.GetParam("engine.inertia", inertia, error_output))  return false;
		engine.SetInertia(inertia);

		if (!c.GetParam("engine.friction", friction, error_output))  return false;
		engine.SetFrictionB(friction);

		if (!c.GetParam("engine.start-rpm", start_rpm, error_output))  return false;
		engine.SetStartRPM(start_rpm);

		if (!c.GetParam("engine.stall-rpm", stall_rpm, error_output))  return false;
		engine.SetStallRPM(stall_rpm);

		if (!c.GetParam("engine.fuel-consumption", fuel_consumption, error_output))  return false;
		engine.SetFuelConsumption(fuel_consumption);

		if (!c.GetParam("engine.mass", mass, error_output))  return false;
		if (!c.GetParam("engine.position", temp_vec3, error_output))  return false;
		if (version == 2)  ConvertV2to1(temp_vec3[0],temp_vec3[1],temp_vec3[2]);
		position.Set(temp_vec3[0],temp_vec3[1],temp_vec3[2]);
		engine.SetMass(mass);
		engine.SetPosition(position);
		AddMassParticle(mass, position);

		float mul = 1.f, max_torque = 0;
		c.GetParam("engine.torque-val-mul", mul);

		float torque_point[3];
		string torque_str("engine.torque-curve-00");
		vector <pair <double, double> > torques;
		int curve_num = 0;
		while (c.GetParam(torque_str, torque_point))
		{
			max_torque = max(max_torque, torque_point[1] * mul);
			torques.push_back(pair <float, float> (torque_point[0], torque_point[1] * mul));

			curve_num++;
			stringstream str;
			str << "engine.torque-curve-";  str.width(2);  str.fill('0');
			str << curve_num;
			torque_str = str.str();
		}
		if (torques.size() <= 1)
		{
			error_output << "You must define at least 2 torque curve points." << endl;
			return false;
		}
		engine.SetTorqueCurve(rpm_limit, torques);

		//load the clutch
		{
			float mul;  //max_torque = sliding * radius * area * max_pressure;
			//if (!c.GetParam("clutch.max-torque", max_torque, error_output))  return false;
			if (!c.GetParam("clutch.max-torque-mul", mul, error_output))  return false;
			clutch.SetMaxTorque(max_torque * mul);
		}

		//  factor for stats  -
		mul = 1.f;
		if (c.GetParam("engine.real-pow-tq-mul", mul))
			engine.real_pow_tq_mul = mul;
		
		mul = 1.f;
		if (c.GetParam("engine.sound-vol-mul", mul))
			engine_vol_mul = mul;
	}

	//load the transmission
	{
		float time = 0;
		float ratio;
		int gears;

		c.GetParam("transmission.shift-delay", time);
		shift_time = time;

		if (!c.GetParam("transmission.gear-ratio-r", ratio, error_output))  return false;
		transmission.SetGearRatio(-1, ratio);

		if (!c.GetParam("transmission.gears", gears, error_output))  return false;

		for (int i = 0; i < gears; i++)
		{
			stringstream s;
			s << "transmission.gear-ratio-" << i+1;
			if (!c.GetParam(s.str(), ratio, error_output))  return false;
			transmission.SetGearRatio(i+1, ratio);
		}
	}

	//load the differential(s)
	string drivetype;
	if (!c.GetParam("drive", drivetype, error_output))  return false;

	if (drivetype == "hover")  //>
	{	hover = true;  drivetype = "AWD";  }
	else if (drivetype == "sphere")
	{	sphere = true;  drivetype = "AWD";  }
	//if (!hover)
		SetDrive(drivetype);

	float final_drive, a, a_tq(0), a_tq_dec(0);
	///  new 3 sets
	if (drivetype == "AWD" &&
		c.GetParam("diff-center.final-drive", a))
	{
		c.GetParam("diff-rear.anti-slip", a, error_output);
		c.GetParam("diff-rear.torque", a_tq);
		c.GetParam("diff-rear.torque-dec", a_tq_dec);
		diff_rear.SetFinalDrive(1.0);
		diff_rear.SetAntiSlip(a, a_tq, a_tq_dec);

		c.GetParam("diff-front.anti-slip", a, error_output);
		c.GetParam("diff-front.torque", a_tq);
		c.GetParam("diff-front.torque-dec", a_tq_dec);
		diff_front.SetFinalDrive(1.0);
		diff_front.SetAntiSlip(a, a_tq, a_tq_dec);

		c.GetParam("diff-center.final-drive", final_drive, error_output);
		c.GetParam("diff-center.anti-slip", a, error_output);
		c.GetParam("diff-center.torque", a_tq);
		c.GetParam("diff-center.torque-dec", a_tq_dec);
		diff_center.SetFinalDrive(final_drive);
		diff_center.SetAntiSlip(a, a_tq, a_tq_dec);
	}
	else  // old 1 for all
	{
		if (!c.GetParam("differential.final-drive", final_drive, error_output))  return false;
		if (!c.GetParam("differential.anti-slip", a, error_output))  return false;
		c.GetParam("differential.torque", a_tq);
		c.GetParam("differential.torque-dec", a_tq_dec);

		if (drivetype == "RWD")
		{
			diff_rear.SetFinalDrive(final_drive);
			diff_rear.SetAntiSlip(a, a_tq, a_tq_dec);
		}
		else if (drivetype == "FWD")
		{
			diff_front.SetFinalDrive(final_drive);
			diff_front.SetAntiSlip(a, a_tq, a_tq_dec);
		}
		else if (drivetype == "AWD")
		{
			diff_rear.SetFinalDrive(1.0);
			diff_rear.SetAntiSlip(a, a_tq, a_tq_dec);

			diff_front.SetFinalDrive(1.0);
			diff_front.SetAntiSlip(a, a_tq, a_tq_dec);

			diff_center.SetFinalDrive(final_drive);
			diff_center.SetAntiSlip(a, a_tq, a_tq_dec);
		}else
		{	error_output << "Unknown drive type: " << drive << endl;
			return false;
		}
	}

	//load the brake
	{
		for (int i = 0; i < 2; i++)
		{
			string pos = "front";
			WHEEL_POSITION left = FRONT_LEFT;
			WHEEL_POSITION right = FRONT_RIGHT;
			if (i == 1)
			{
				left = REAR_LEFT;
				right = REAR_RIGHT;
				pos = "rear";
			}

			float friction, max_pressure, area, bias, radius, handbrake(0);

			if (!c.GetParam("brakes-"+pos+".friction", friction, error_output))  return false;
			brake[left].SetFriction(friction);
			brake[right].SetFriction(friction);

			if (!c.GetParam("brakes-"+pos+".area", area, error_output))  return false;
			brake[left].SetArea(area);
			brake[right].SetArea(area);

			if (!c.GetParam("brakes-"+pos+".radius", radius, error_output))  return false;
			brake[left].SetRadius(radius);
			brake[right].SetRadius(radius);

			c.GetParam("brakes-"+pos+".handbrake", handbrake);
			brake[left].SetHandbrake(handbrake);
			brake[right].SetHandbrake(handbrake);

			if (!c.GetParam("brakes-"+pos+".bias", bias, error_output))  return false;
			brake[left].SetBias(bias);
			brake[right].SetBias(bias);

			if (!c.GetParam("brakes-"+pos+".max-pressure", max_pressure, error_output))  return false;
			brake[left].SetMaxPressure(max_pressure*bias);
			brake[right].SetMaxPressure(max_pressure*bias);
		}
	}

	//load the fuel tank
	{
		float pos[3];
		MATHVECTOR<double,3> position;
		float capacity, volume, fuel_density;

		if (!c.GetParam("fuel-tank.capacity", capacity, error_output))  return false;
		fuel_tank.SetCapacity(capacity);

		if (!c.GetParam("fuel-tank.volume", volume, error_output))  return false;
		fuel_tank.SetVolume(volume);

		if (!c.GetParam("fuel-tank.fuel-density", fuel_density, error_output))  return false;
		fuel_tank.SetDensity(fuel_density);

		if (!c.GetParam("fuel-tank.position", pos, error_output))  return false;
		if (version == 2)  ConvertV2to1(pos[0],pos[1],pos[2]);
		position.Set(pos[0],pos[1],pos[2]);
		fuel_tank.SetPosition(position);
		//AddMassParticle(fuel_density*volume, position);
	}

	//load the suspension
	{
		for (int i = 0; i < 2; i++)
		{
			string posstr = "front";
			string posshortstr = "F";
			WHEEL_POSITION posl = FRONT_LEFT;
			WHEEL_POSITION posr = FRONT_RIGHT;
			if (i == 1)
			{
				posstr = "rear";
				posshortstr = "R";
				posl = REAR_LEFT;
				posr = REAR_RIGHT;
			}

			float spring_constant, bounce, rebound, travel, camber, caster, toe, anti_roll;//, maxcompvel;
			float hinge[3];
			MATHVECTOR<double,3> tempvec;

			if (!c.GetParam("suspension-"+posstr+".spring-constant", spring_constant, error_output))  return false;
			suspension[posl].SetSpringConstant(spring_constant);
			suspension[posr].SetSpringConstant(spring_constant);

			if (!c.GetParam("suspension-"+posstr+".bounce", bounce, error_output))  return false;
			suspension[posl].SetBounce(bounce);
			suspension[posr].SetBounce(bounce);

			if (!c.GetParam("suspension-"+posstr+".rebound", rebound, error_output))  return false;
			suspension[posl].SetRebound(rebound);
			suspension[posr].SetRebound(rebound);

			string file;
			if (c.GetParam("suspension-"+posstr+".factors-file", file))
			{
				int id = game->suspS_map[file]-1;
				if (id == -1)  {  id = 0;
					error_output << "Can't find suspension spring factors file: " << file << endl;  }

				suspension[posl].SetSpringFactorPoints(game->suspS[id]);
				suspension[posr].SetSpringFactorPoints(game->suspS[id]);

				id = game->suspD_map[file]-1;
				if (id == -1)  {  id = 0;
					error_output << "Can't find suspension damper factors file: " << file << endl;  }
				
				suspension[posl].SetDamperFactorPoints(game->suspD[id]);
				suspension[posr].SetDamperFactorPoints(game->suspD[id]);
			}else
			{	//  factor points
				vector <pair <double, double> > damper, spring;
				c.GetPoints("suspension-"+posstr, "damper-factor", damper);
				suspension[posl].SetDamperFactorPoints(damper);
				suspension[posr].SetDamperFactorPoints(damper);

				c.GetPoints("suspension-"+posstr, "spring-factor", spring);
				suspension[posl].SetSpringFactorPoints(spring);
				suspension[posr].SetSpringFactorPoints(spring);
			}

			if (!c.GetParam("suspension-"+posstr+".travel", travel, error_output))  return false;
			suspension[posl].SetTravel(travel);
			suspension[posr].SetTravel(travel);

			if (!c.GetParam("suspension-"+posstr+".camber", camber, error_output))  return false;
			suspension[posl].SetCamber(camber);
			suspension[posr].SetCamber(camber);

			if (!c.GetParam("suspension-"+posstr+".caster", caster, error_output))  return false;
			suspension[posl].SetCaster(caster);
			suspension[posr].SetCaster(caster);

			if (!c.GetParam("suspension-"+posstr+".toe", toe, error_output))  return false;
			suspension[posl].SetToe(toe);
			suspension[posr].SetToe(toe);

			if (!c.GetParam("suspension-"+posstr+".anti-roll", anti_roll, error_output))  return false;
			suspension[posl].SetAntiRollK(anti_roll);
			suspension[posr].SetAntiRollK(anti_roll);

			if (!c.GetParam("suspension-"+posshortstr+"L.hinge", hinge, error_output))  return false;
			//cap hinge to reasonable values
			for (int i = 0; i < 3; i++)
			{
				if (hinge[i] < -100)	hinge[i] = -100;
				if (hinge[i] > 100)		hinge[i] = 100;
			}
			if (version == 2)  ConvertV2to1(hinge[0],hinge[1],hinge[2]);
			tempvec.Set(hinge[0],hinge[1], hinge[2]);
			suspension[posl].SetHinge(tempvec);

			if (!c.GetParam("suspension-"+posshortstr+"R.hinge", hinge, error_output))  return false;
			for (int i = 0; i < 3; i++)
			{
				if (hinge[i] < -100)	hinge[i] = -100;
				if (hinge[i] > 100)		hinge[i] = 100;
			}
			if (version == 2)  ConvertV2to1(hinge[0],hinge[1],hinge[2]);
			tempvec.Set(hinge[0],hinge[1], hinge[2]);
			suspension[posr].SetHinge(tempvec);
		}
	}

	//load the wheels
	{
		for (int i = 0; i < 4; i++)
		{
			string sPos;
			WHEEL_POSITION wp;
			if (i == 0)		{	sPos = "FL";	wp = FRONT_LEFT;	}
			else if (i == 1){	sPos = "FR";	wp = FRONT_RIGHT;	}
			else if (i == 2){	sPos = "RL";	wp = REAR_LEFT;	}
			else			{	sPos = "RR";	wp = REAR_RIGHT;	}

			float roll_h, mass;
			float pos[3];
			MATHVECTOR<double,3> vec;

			if (!c.GetParam("wheel-"+sPos+".mass", mass, error_output))  return false;
			wheel[wp].SetMass(mass);

			if (!c.GetParam("wheel-"+sPos+".roll-height", roll_h, error_output))  return false;
			wheel[wp].SetRollHeight(roll_h);

			if (!c.GetParam("wheel-"+sPos+".position", pos, error_output))  return false;
			if (version == 2)  ConvertV2to1(pos[0],pos[1],pos[2]);
			vec.Set(pos[0],pos[1], pos[2]);
			wheel[wp].SetExtendedPosition(vec);

			AddMassParticle(mass, vec);
		}

		//load the rotational inertia parameter from the tire section
		float front_inertia;
		float rear_inertia;
		if (c.GetParam("tire-both.rotational-inertia", front_inertia, error_output))
			rear_inertia = front_inertia;
		else
		{	if (!c.GetParam("tire-front.rotational-inertia", front_inertia, error_output))  return false;
			if (!c.GetParam("tire-rear.rotational-inertia", rear_inertia, error_output))  return false;
		}
		wheel[FRONT_LEFT].SetInertia(front_inertia);
		wheel[FRONT_RIGHT].SetInertia(front_inertia);

		wheel[REAR_LEFT].SetInertia(rear_inertia);
		wheel[REAR_RIGHT].SetInertia(rear_inertia);
	}

	//load the tire parameters
	{
		WHEEL_POSITION leftside = FRONT_LEFT;
		WHEEL_POSITION rightside = FRONT_RIGHT;
		float value;
		bool both = c.GetParam("tire-both.radius", value);
		string posstr = both ? "both" : "front";

		for (int p = 0; p < 2; ++p)
		{
			if (p == 1)
			{
				leftside = REAR_LEFT;
				rightside = REAR_RIGHT;
				if (!both)  posstr = "rear";
			}

			float rolling_resistance[3];
			if (!c.GetParam("tire-"+posstr+".rolling-resistance", rolling_resistance, error_output))  return false;
			wheel[leftside].SetRollingResistance(rolling_resistance[0], rolling_resistance[1]);
			wheel[rightside].SetRollingResistance(rolling_resistance[0], rolling_resistance[1]);

			float radius;
			if (!c.GetParam("tire-"+posstr+".radius", radius, error_output))  return false;
			wheel[leftside].SetRadius(radius);
			wheel[rightside].SetRadius(radius);
		}
	}

	//load the mass-only particles
	{
		MATHVECTOR<double,3> position;
		float pos[3], mass;

		if (c.GetParam("contact-points.mass", mass))
		{
			int paramnum(0);
			string paramname("contact-points.position-00");
			stringstream output_supression;
			while (c.GetParam(paramname, pos))
			{
				if (version == 2)  ConvertV2to1(pos[0],pos[1],pos[2]);
				position.Set(pos[0],pos[1],pos[2]);
				AddMassParticle(mass, position);
				paramnum++;
				stringstream str;
				str << "contact-points.position-";  str.width(2);  str.fill('0');
				str << paramnum;
				paramname = str.str();
			}
		}

		string paramname = "particle-00";
		int paramnum = 0;
		while (c.GetParam(paramname+".mass", mass))
		{
			if (!c.GetParam(paramname+".position", pos, error_output))  return false;
			if (version == 2)  ConvertV2to1(pos[0],pos[1],pos[2]);
			position.Set(pos[0],pos[1],pos[2]);
			AddMassParticle(mass, position);
			paramnum++;
			stringstream str;
			str << "particle-";  str.width(2);  str.fill('0');
			str << paramnum;
			paramname = str.str();
		}
	}

	//load the max steering angle
	{
		float maxangle = 26.f;
		if (!c.GetParam("steering.max-angle", maxangle, error_output))  return false;
		SetMaxSteeringAngle( maxangle );

		float a = 1.f;
		c.GetParam("steering.flip-pow-mul", a);	 flip_mul = a;
	}
	///car angular damping -new
	{
		float a = 0.4f;
		c.GetParam("steering.angular-damping", a, error_output);
		SetAngDamp(a);

		a=0.f;  c.GetParam("rot_drag.roll", a);  rot_coef[0] = a;
		a=0.f;  c.GetParam("rot_drag.pitch", a); rot_coef[1] = a;
		a=0.f;  c.GetParam("rot_drag.yaw", a);	 rot_coef[2] = a;
		a=0.f;  c.GetParam("rot_drag.yaw2", a);	 rot_coef[3] = a;
	}

	//load the driver
	{
		float mass;
		float pos[3];
		MATHVECTOR<double,3> position;

		if (!c.GetParam("driver.mass", mass, error_output))  return false;
		if (!c.GetParam("driver.position", pos, error_output))  return false;
		if (version == 2)  ConvertV2to1(pos[0],pos[1],pos[2]);
		position.Set(pos[0], pos[1], pos[2]);
		AddMassParticle(mass, position);
	}

	//load the aerodynamics
	{
		float drag_area, drag_c, lift_area, lift_c, lift_eff;
		float pos[3];
		MATHVECTOR<double,3> position;

		if (!c.GetParam("drag.frontal-area", drag_area, error_output))  return false;
		if (!c.GetParam("drag.drag-coefficient", drag_c, error_output))  return false;
		if (!c.GetParam("drag.position", pos, error_output))  return false;
		if (version == 2)  ConvertV2to1(pos[0],pos[1],pos[2]);
		position.Set(pos[0], pos[1], pos[2]);
		AddAerodynamicDevice(position, drag_area, drag_c, 0,0,0);

		for (int i = 0; i < 2; i++)
		{
			string wingpos = "front";
			if (i == 1)
				wingpos = "rear";
			if (!c.GetParam("wing-"+wingpos+".frontal-area", drag_area, error_output))  return false;
			if (!c.GetParam("wing-"+wingpos+".drag-coefficient", drag_c, error_output))  return false;
			if (!c.GetParam("wing-"+wingpos+".surface-area", lift_area, error_output))  return false;
			if (!c.GetParam("wing-"+wingpos+".lift-coefficient", lift_c, error_output))  return false;
			if (!c.GetParam("wing-"+wingpos+".efficiency", lift_eff, error_output))  return false;
			if (!c.GetParam("wing-"+wingpos+".position", pos, error_output))  return false;
			if (version == 2)  ConvertV2to1(pos[0],pos[1],pos[2]);
			position.Set(pos[0], pos[1], pos[2]);
			AddAerodynamicDevice(position, drag_area, drag_c, lift_area, lift_c, lift_eff);
		}
	}

	//  hover params
	if (hover || sphere)
	{
		c.GetParam("hover.hAbove",		 hov.hAbove);		c.GetParam("hover.hRayLen",		 hov.hRayLen);
										 
		c.GetParam("hover.steerForce",	 hov.steerForce);
		c.GetParam("hover.steerDamp",	 hov.steerDamp);	c.GetParam("hover.steerDampP",	 hov.steerDampP);
										 
		c.GetParam("hover.engineForce",	 hov.engineForce);	c.GetParam("hover.engineVelDec", hov.engineVelDec);
		c.GetParam("hover.brakeForce",	 hov.brakeForce);
										 
		c.GetParam("hover.dampAirRes",	 hov.dampAirRes);	c.GetParam("hover.dampSide",	 hov.dampSide);
		c.GetParam("hover.dampUp",		 hov.dampUp);		c.GetParam("hover.dampDn",		 hov.dampDn);
		c.GetParam("hover.dampPmul",	 hov.dampPmul);

		float al[3];
		c.GetParam("hover.alignTqP", al);  hov.alp.Set(al[0],al[1],al[2]);
		c.GetParam("hover.alignTq",  al);  hov.alt.Set(al[0],al[1],al[2]);
		c.GetParam("hover.pitchTq",  hov.pitchTq);
		c.GetParam("hover.rollTq",   hov.rollTq);		c.GetParam("hover.roll",     hov.roll);

		c.GetParam("hover_h.hov_vz",   hov.hov_vz);		c.GetParam("hover_h.hov_vsat", hov.hov_vsat);
		c.GetParam("hover_h.hov_dsat", hov.hov_dsat);
		c.GetParam("hover_h.hov_dampP",hov.hov_dampP);	c.GetParam("hover_h.hov_damp", hov.hov_damp);
		c.GetParam("hover_h.hov_fall", hov.hov_fall);
		c.GetParam("hover_h.hov_riseP",hov.hov_riseP);	c.GetParam("hover_h.hov_rise", hov.hov_rise);
	}

	UpdateMass();

	LogO(Ogre::String(":::: Time car dynamics load: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
	return true;
}
Exemple #21
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");
}
Exemple #22
0
//--------------------------------------------------------------------------------------------------
bool DiscoApplication::frameStarted( const Ogre::FrameEvent& evt )
{
	static Ogre::Timer a;

	static uint32_t lastTimeMS;
	static uint32_t curTimeMS;

	curTimeMS = a.getMilliseconds();
	uint32_t timeDiffMS = curTimeMS - lastTimeMS;

	if ( timeDiffMS > 0 )
	{
		//printf( "FPS = %f\n", 1000.0/(float)timeDiffMS );//1.0/((float)timeDiffMS/1000.0) );
	}
	lastTimeMS = curTimeMS;

	const int32_t MAX_DEPTH_MM = 10000;
	const float FOCAL_LENGTH = 0.525f;	// Focal length in metres
	const float FADE_START_XZ_DISTANCE = 0.5f;
	const float FADE_MAX_XZ_DISTANCE = 6.0f;

	xn::SceneMetaData sceneMD;
	xn::DepthMetaData depthMD;

	mpKinectController->getContext().WaitAndUpdateAll();
	mpKinectController->getDepthGenerator().GetMetaData( depthMD );
	mpKinectController->getUserGenerator().GetUserPixels( 0, sceneMD );

	XnUserID userIdx[15];
	XnUInt16 numUsers = 15;
	mpKinectController->getUserGenerator().GetUsers( userIdx, numUsers );

	if ( 0 == numUsers )
	{
		// Restart the time if there are no users to record
		mRecordingGapTimer.reset();
	}
	else
	{
		for ( uint32_t i = 0; i < numUsers; i++ )
		{
			if ( tryToAttachParticleToUser( userIdx[ i ] ) )
			{
				break;
			}
		}
	}

	// Start recording if we see a person
	if ( numUsers > 0 && !mbRecording
		&& mRecordingGapTimer.getMilliseconds() > TIME_BETWEEN_RECORDINGS_MS )
	{
		mbRecording = true;
		memset( mpImageData, 0, RECORDED_DATA_SIZE );
		mRecordingFrameIdx = 0;
	}


	// Build an accumulative histogram to work out the colour for each point
	uint32_t depthHist[ MAX_DEPTH_MM ];
	memset( depthHist, 0, sizeof( depthHist ) );

	uint32_t numPoints = 0;

	const XnDepthPixel* pDepth = depthMD.Data();

	int32_t recordingPixelStepX = depthMD.XRes() / SMALL_FRAME_WIDTH;
	int32_t recordingPixelStepY = depthMD.YRes() / SMALL_FRAME_HEIGHT;
	if ( recordingPixelStepX <= 0 ) recordingPixelStepX = 1;
	if ( recordingPixelStepY <= 0 ) recordingPixelStepY = 1;

	for ( uint32_t y = 0; y < depthMD.YRes(); y++ )
	{
		for ( uint32_t x = 0; x < depthMD.XRes(); x++ )
		{
			XnUInt16 value = *pDepth;

			if ( 0 != value )
			{
				depthHist[ value ]++;
				numPoints++;
			}

			pDepth++;
		}
	}

	for ( uint32_t i = 1; i < MAX_DEPTH_MM; i++ )
	{
		depthHist[ i ] += depthHist[ i - 1 ];
	}

	if ( numPoints > 0 )
	{
		for ( uint32_t i = 1; i < MAX_DEPTH_MM; i++ )
		{
			depthHist[ i ] = (unsigned int)(256 * (1.0f - ((float)depthHist[ i ] / numPoints)));
		}
	}

	// Update the point cloud to reflect the depth data
	const float COLOURS[][3] =
	{
		{0,1,1},
		{0,0,1},
		{0,1,0},
		{1,1,0},
		{1,0,0},
		{1,.5,0},
		{.5,1,0},
		{0,.5,1},
		{.5,0,1},
		{1,1,.5},
		{1,1,1}
	};
	const uint32_t NUM_COLOURS = 10;

	pDepth = depthMD.Data();
	const XnLabel* pLabels = sceneMD.Data();


	mpRosPointCloud->clear();

	ogre_tools::PointCloud::Point* pPoints = new ogre_tools::PointCloud::Point[ numPoints ];
	int32_t pointIdx = 0;

	int32_t width = depthMD.XRes();
	int32_t height = depthMD.YRes();
	int32_t halfWidth = width / 2;
	int32_t halfHeight = height / 2;

	for ( int32_t y = 0; y < height; y++ )
	{
		for ( int32_t x = 0; x < width; x++ )
		{
			XnUInt16 value = *pDepth;
			XnLabel label = *pLabels;
			XnUInt32 colorId = label % NUM_COLOURS;

			float fade = 1.0;

			if (label == 0)
			{
				// Ignore background
				colorId = NUM_COLOURS;
			}


			{

				float worldZ = (float)(*pDepth)/1000.0;		// Convert from mm to m
				float worldX = (((float)(x-halfWidth)/1000.0)*worldZ) / FOCAL_LENGTH;

				float distanceXZ = sqrtf( worldX*worldX + worldZ*worldZ );
				if ( distanceXZ > FADE_MAX_XZ_DISTANCE )
				{
					fade = 0.0f;
				}
				else if ( distanceXZ > FADE_START_XZ_DISTANCE )
				{
					fade = 1.0 - (distanceXZ - FADE_START_XZ_DISTANCE)/(FADE_MAX_XZ_DISTANCE - FADE_START_XZ_DISTANCE);
				}
			}

			if ( //mbRecording
				0 != value && fade > 0.0
				&& ( SHOW_BACKGROUND || label != 0 ) )
			{
				float worldZ = (float)(*pDepth)/1000.0;		// Convert from mm to m
				float worldX = (((float)(x-halfWidth)/1000.0)*worldZ) / FOCAL_LENGTH;
				float worldY = (((float)(y-halfHeight)/1000.0)*worldZ) / FOCAL_LENGTH;
				//float worldY = (((float)(((height-1)-y)-halfHeight)/1000.0)*worldZ) / FOCAL_LENGTH;

				float histValue = (float)depthHist[ value ]/255.0;

				pPoints[ pointIdx ].setColor(
					fade * histValue * COLOURS[ colorId ][ 0 ],
					fade * histValue * COLOURS[ colorId ][ 1 ],
					fade * histValue * COLOURS[ colorId ][ 2 ] );

				pPoints[ pointIdx ].x = worldX;
				pPoints[ pointIdx ].y = worldY;
				pPoints[ pointIdx ].z = worldZ;

				pointIdx++;

				if ( mbRecording && label != 0
					&& x%recordingPixelStepX == 0 && y%recordingPixelStepY == 0 )
				{
					int32_t smallFrameX = x / recordingPixelStepX;
					int32_t smallFrameY = y / recordingPixelStepY;

					int32_t smallPixelIdx = mRecordingFrameIdx*SMALL_FRAME_WIDTH*SMALL_FRAME_HEIGHT
						+ smallFrameY*SMALL_FRAME_WIDTH + smallFrameX;

					//((uint16_t*)mpImageData)[ smallPixelIdx ] = 0xFFFF;
					//((uint32_t*)mpImageData)[ smallPixelIdx ] = 0xFFFFFFFF;

					mpImageData[ smallPixelIdx ] = 0xFF; // 255; //(uint8_t)(fade * histValue * 255.0);
					//printf( "recorded %i to pixel %i\n", mpImageData[ smallPixelIdx ], smallPixelIdx );
				}
			}

			pDepth++;
			pLabels++;
		}
	}

	mpRosPointCloud->addPoints( pPoints, pointIdx );
	//printf( "Added %i points\n", pointIdx );

	delete [] pPoints;

	// Draw the crowd
	uint32_t numCrowdMembers = mCrowdMembers.size();
	mpCrowdObject->clear();
	mpCrowdObject->estimateVertexCount( numCrowdMembers*4 );
	mpCrowdObject->estimateIndexCount( numCrowdMembers*12 );

	for ( uint32_t personIdx = 0; personIdx < numCrowdMembers; personIdx++ )
	{
		CrowdMember& crowdMember = mCrowdMembers[ personIdx ];

		float startV = (float)crowdMember.mFrameIdx/(float)NUM_FRAMES_TO_RECORD;
		float endV = (float)(crowdMember.mFrameIdx+1)/(float)NUM_FRAMES_TO_RECORD;

		mpCrowdObject->begin( crowdMember.mMaterialName, Ogre::RenderOperation::OT_TRIANGLE_LIST );

		//float startV = 0.0; //(float)crowdMember.mFrameIdx/(float)NUM_FRAMES_TO_RECORD;
		//float endV = 1.0;// (float)(crowdMember.mFrameIdx+1)/(float)NUM_FRAMES_TO_RECORD;

		//mpCrowdObject->begin( "Template/CutOut", Ogre::RenderOperation::OT_TRIANGLE_LIST );


		mpCrowdObject->position( crowdMember.mPos + Ogre::Vector3( -0.5f, -0.375f, 0.0f ) );
		mpCrowdObject->textureCoord( 0.0, startV );
		mpCrowdObject->colour( COLOURS[ crowdMember.mColourIdx ][ 0 ],
			COLOURS[ crowdMember.mColourIdx ][ 1 ], COLOURS[ crowdMember.mColourIdx ][ 2 ], 1.0 );

		mpCrowdObject->position( crowdMember.mPos + Ogre::Vector3( 0.5f, -0.375f, 0.0f ) );
		mpCrowdObject->textureCoord( 1.0, startV );

		mpCrowdObject->position( crowdMember.mPos + Ogre::Vector3( 0.5f, 0.375f, 0.0f ) );
		mpCrowdObject->textureCoord( 1.0, endV );

		mpCrowdObject->position( crowdMember.mPos + Ogre::Vector3( -0.5f, 0.375f, 0.0f ) );
		mpCrowdObject->textureCoord( 0.0, endV );

		//mpCrowdObject->quad( 0, 1, 2, 3 );
		mpCrowdObject->quad( 3, 2, 1, 0 );

		mpCrowdObject->end();

		// Move to the next frame
		if ( crowdMember.mbReversing )
		{
			crowdMember.mFrameIdx--;
			if ( crowdMember.mFrameIdx < 0 )
			{
				crowdMember.mFrameIdx = 1;
				crowdMember.mbReversing = false;
			}
		}
		else
		{
			crowdMember.mFrameIdx++;
			if ( crowdMember.mFrameIdx >= NUM_FRAMES_TO_RECORD )
			{
				crowdMember.mFrameIdx = NUM_FRAMES_TO_RECORD-1;
				crowdMember.mbReversing = true;
			}
		}
	}


	// Check to see if we can stop recording
	if ( mbRecording )
	{
		mRecordingFrameIdx++;
		if ( mRecordingFrameIdx >= NUM_FRAMES_TO_RECORD )
		{
			// Create a new crowd member
			Ogre::Image image;
			image.loadDynamicImage(
				mpImageData, SMALL_FRAME_WIDTH, NUM_FRAMES_TO_RECORD*SMALL_FRAME_HEIGHT, 1, Ogre::PF_A4L4 );

			std::stringstream ss;
			ss << "RecordedSequenceTex_" << numCrowdMembers;
			Ogre::String texName = ss.str();

			Ogre::TextureManager* pTextureMgr = Ogre::TextureManager::getSingletonPtr();
			Ogre::TexturePtr pTexture = pTextureMgr->loadImage( texName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image );

			ss.clear();
			ss << "RecordedSequenceMat_" << numCrowdMembers;
			Ogre::String matName = ss.str();

			Ogre::MaterialManager* pMatMgr = Ogre::MaterialManager::getSingletonPtr();
			Ogre::MaterialPtr pSrcMat = (Ogre::MaterialPtr)pMatMgr->getByName( "Template/CutOut", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
			Ogre::MaterialPtr pMat = pSrcMat->clone( matName ); //  (Ogre::MaterialPtr)pMatMgr->create( matName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );

			pMat->getTechnique( 0 )->getPass( 0 )->removeAllTextureUnitStates();
			Ogre::TextureUnitState* pTex = pMat->getTechnique( 0 )->getPass( 0 )->createTextureUnitState( texName, 0 );
			pMat->getTechnique( 0 )->getPass( 0 )->addTextureUnitState( pTex );

			/*Ogre::Technique* pTech = pMat->getTechnique( 0 );
			pTech->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );

			Ogre::Pass *pPass = pTech->createPass();

			pPass->setLightingEnabled( false );

			pPass->setAmbient( 1.0, 1.0, 1.0 );
			pPass->setDiffuse( 1.0, 1.0, 1.0, 1.0 );
			pPass->setSpecular( 0.0, 0.0, 0.0, 0.0 );

			Ogre::ColourValue val(0.0f, 0.0f, 0.0f, 1.0f);
			pPass->setSelfIllumination(val);

			//pPass->setE ( 0.0, 0.0, 0.0, 0.0 );

			pPass->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
			pPass->setDepthWriteEnabled( false );

			Ogre::TextureUnitState* pTex = pPass->createTextureUnitState( texName, 0 );
			pPass->addTextureUnitState( pTex );


			pTex->setColourOperation( Ogre::LBO_MODULATE );*/

			pMat->setCullingMode( Ogre::CULL_NONE );
			pMat->compile();

			CrowdMember crowdMember;
			crowdMember.mMaterialName = matName;
			crowdMember.mFrameIdx = 0;
			crowdMember.mColourIdx = rand()%NUM_COLOURS;
			crowdMember.mbReversing = false;

			int32_t rowIdx = rand()%NUM_ROWS;
			float angle = MIN_CROWD_ANGLE + ((float)rand()/(float)RAND_MAX)*(MAX_CROWD_ANGLE-MIN_CROWD_ANGLE);
			float x = ROW_DEPTHS[ rowIdx ]*sin( angle );
			float z = ROW_DEPTHS[ rowIdx ]*cos( angle );
			crowdMember.mPos = Ogre::Vector3( x, ROW_HEIGHTS[ rowIdx ], z );
			mCrowdMembers.push_back( crowdMember );

			mbRecording = false;
			mRecordingGapTimer.reset();		// Reset time so that there's a gap between recording
			printf( "Got frame\n" );
		}
	}

	return true;
}
///  Image from road
///  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
void App::SaveGrassDens()
{
	Ogre::Timer ti;

	for (int i=0; i < RTs-1; ++i)  //-1 preview camera manual
	{
		if (!rt[i].tex)  return;
		rt[i].tex->update();  // all have to exist
	}

	int w = rt[1].tex->getWidth(), h = rt[1].tex->getHeight();
	using Ogre::uint;
	uint *rd = new uint[w*h];   // road render
	uint *gd = new uint[w*h];   // grass dens
	PixelBox pb_rd(w,h,1, PF_BYTE_RGBA, rd);
	rt[1].tex->copyContentsToMemory(pb_rd, RenderTarget::FB_FRONT);

	const int f = std::max(0, scn->sc->grDensSmooth);
	float sum = 0.f;
	register int v,i,j,x,y, a,b,d,m;

	//  gauss kernel for smoothing
	int *mask = new int[(f*2+1)*(f*2+1)];  m = 0;
	if (f==0)
	{	mask[0] = 256.f;  sum = 256.f;  }
	else
	for (j = -f; j <= f; ++j)
	for (i = -f; i <= f; ++i, ++m)
	{
		v = std::max(0.f, (1.f - sqrtf((float)(i*i+j*j)) / float(f)) * 256.f);
		mask[m] = v;  sum += v;
	}
	sum = 2.f / sum;  //par normally would be 1.f - but road needs to stay black and be smooth outside
	//  change smooth to distance from road with fade ?..
		
	///  road - rotate, smooth  -----------
	for (y = f; y < h-f; ++y) {  a = y*w +f;
	for (x = f; x < w-f; ++x, ++a)
	{	b = x*w + (h-y);  // rot 90 ccw  b=a
		
		//  sum kernel
		v = 0;  m = 0;
		for (j = -f; j <= f; ++j) {  d = b -f + j*w;
		for (i = -f; i <= f; ++i, ++d, ++m)
			v += ((rd[d] >> 16) & 0xFF) * mask[m] / 256;  }

		v = std::max(0, (int)(255.f * (1.f - v * sum) ));  // avg, inv, clamp
		
		gd[a] = 0xFF000000 + v;  // write
	}	}

	v = 0xFF0000FF;  //  frame f []  todo: get from rd[b] not clear..
	for (y = 0;  y <= f; ++y)	for (x=0; x < w; ++x)	gd[y*w+x] = v;  // - up
	for (y=h-f-1; y < h; ++y)	for (x=0; x < w; ++x)	gd[y*w+x] = v;  // - down
	for (x = 0;  x <= f; ++x)	for (y=0; y < h; ++y)	gd[y*w+x] = v;  // | left
	for (x=w-f-1; x < w; ++x)	for (y=0; y < h; ++y)	gd[y*w+x] = v;  // | right

	LogO(String("::: Time road dens: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");  ti.reset();

	if (!IsVdrTrack())  // vdr trk no grass, only previews
	{
		Image im;  // for trees, before grass angle and height
		im.loadDynamicImage((uchar*)gd, w,h,1, PF_BYTE_RGBA);
		im.save(gcom->TrkDir()+"objects/roadDensity.png");
	}
	delete[] rd;  delete[] gd;  delete[] mask;

	//  road, terrain  ----------------
	int u = pSet->allow_save ? pSet->gui.track_user : 1;
	rt[0].tex->writeContentsToFile(gcom->pathTrk[u] + pSet->gui.track + "/preview/road.png");
	rt[2].tex->writeContentsToFile(gcom->pathTrk[u] + pSet->gui.track + "/preview/terrain.jpg");

	LogO(String("::: Time save prv : ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
}
///  save water depth map
//-----------------------------------------------------------------------------------------------------------
void App::SaveWaterDepth()
{
	if (scn->sc->fluids.empty())
	{
		gui->Delete(gcom->TrkDir()+"objects/waterDepth.png");  // no tex if no fluids
		return;
	}
	Ogre::Timer ti;

	//  2048 for bigger terrains ?
	int w = 1024, h = w;  float fh = h-1, fw = w-1;
	using Ogre::uint;
	uint *wd = new uint[w*h];   // water depth
	register int x,y,a,i,ia,id;
	register float fa,fd;
	
	///  write to img  -----------
	//  get ter height to fluid height difference for below
	for (y = 0; y < h; ++y) {  a = y*w;
	for (x = 0; x < w; ++x, ++a)
	{
		//  pos 0..1
		float fx = float(y)/fh, fz = float(x)/fw;
		//  pos on ter  -terSize..terSize
		float w = scn->sc->td.fTerWorldSize;
		float wx = (fx-0.5f) * w, wz = -(fz-0.5f) * w;

		fa = 0.f;  // fluid y pos
		for (i=0; i < scn->sc->fluids.size(); ++i)
		{
			const FluidBox& fb = scn->sc->fluids[i];
			const float sizex = fb.size.x*0.5f, sizez = fb.size.z*0.5f;
			//  check rect 2d - no rot !  todo: make 2nd type circle..
			if (wx > fb.pos.x - sizex && wx < fb.pos.x + sizex &&
				wz > fb.pos.z - sizez && wz < fb.pos.z + sizez)
			{
				float f = fb.pos.y - scn->terrain->getHeightAtTerrainPosition(fx,fz);
				if (f > fa)  fa = f;
			}
		}		//par
		fd = fa * 0.4f * 255.f;  // depth far  full at 2.5 m
		fa = fa * 8.f * 255.f;  // alpha near  full at 1/8 m

		ia = std::max(0, std::min(255, (int)fa ));  // clamp
		id = std::max(0, std::min(255, (int)fd ));
		
		wd[a] = 0xFF000000 + /*0x01 */ ia + 0x0100 * id;  // write
	}	}

	Image im;  // save img
	im.loadDynamicImage((uchar*)wd, w,h,1, PF_BYTE_RGBA);
	im.save(gcom->TrkDir()+"objects/waterDepth.png");
	delete[] wd;

	try {
	TexturePtr tex = TextureManager::getSingleton().getByName("waterDepth.png");
	if (!tex.isNull())
		tex->reload();
	else  // 1st fluid after start, refresh matdef ?..
		TextureManager::getSingleton().load("waterDepth.png", rgDef);
	} catch(...) {  }

	LogO(String("::: Time WaterDepth: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
}
void App::AlignTerToRoad()
{
	SplineRoad* road = scn->road;
	if (road->vSel.empty())  return;
	Ogre::Timer ti;

	///  create bullet road for selected segments
	road->ed_Wmul = pSet->al_w_mul;
	road->ed_Wadd = pSet->al_w_add;
	road->RebuildRoadInt(true);

	//  terrain
	float *fHmap = scn->terrain->getHeightData();
	const int w = scn->sc->td.iVertsX, h = w;
	const float fh = h-1, fw = w-1;

	float *rd = new float[w*h];  // road depth
	bool  *rh = new bool[w*h];  // road hit

	const float ws = scn->sc->td.fTerWorldSize;
	const float Len = 400;  // max ray length
	register int x,y,a;
	register float v,k, fx,fz, wx,wz;
	
	///  ray casts  -----------
	for (y = 0; y < h; ++y) {  a = y*w;
	for (x = 0; x < w; ++x, ++a)
	{
		//  pos 0..1
		fx = float(x)/fh;  fz = float(y)/fw;
		//  pos on ter  -terSize..terSize
		wx = (fx-0.5f) * ws;  wz = (fz-0.5f) * ws;

		btVector3 from(wx,wz,Len), to(wx,wz,-Len);  // x -z y
		RayResult rayRes(from, to);
		world->rayTest(from, to, rayRes);

		//  terrain height if not hit
		rh[a] = rayRes.hasHit();
		rd[a] = rayRes.hasHit() ? rayRes.m_hitPointWorld.getZ() : fHmap[a];
	}	}

	//  smooth edges, road-terrain border
	const float fv = pSet->al_smooth;
	if (fv > 0.5f)
	{
		const int f = std::ceil(fv);
		const unsigned int fs = (f*2+1)*(f*2+1);
		float ff = 0.f;
		register int i,j,m,d,b;

		//  gauss kernel for smoothing
		float *mask = new float[fs];  m = 0;
		for (j = -f; j <= f; ++j)
		for (i = -f; i <= f; ++i, ++m)
		{
			v = std::max(0.f, 1.f - sqrtf((float)(i*i+j*j)) / fv );
			mask[m] = v;  ff += v;
		}
		ff = 1.f / ff;  // smooth, outside (>1.f)
			
		//  sum kernel
		for (y = f; y < h-f; ++y) {  a = y*w +f;
		for (x = f; x < w-f; ++x, ++a)
		{		
			v = 0;  m = 0;  b = 0;
			for (j = -f; j <= f; ++j) {  d = a -f + j*w;
			for (i = -f; i <= f; ++i, ++d, ++m)
			{	k = mask[m];  //maskB ?
				v += rd[d] * k;
				if (rh[d] && k > 0.1f)  ++b;
			}	}
			if (b > 0 && b < fs*0.8f)  //par?
				rd[a] = v * ff;
		}	}
		delete[] mask;
	}

	//  set new hmap
	for (y = 0; y < h; ++y) {  a = y*w;
	for (x = 0; x < w; ++x, ++a)
	{
		fHmap[a] = rd[a];
	}	}

	delete[] rd;  delete[] rh;



	//  clear bullet world
	for (int i=0; i < road->vbtTriMesh.size(); ++i)
		delete road->vbtTriMesh[i];
	road->vbtTriMesh.clear();
	
	for (int i = world->getNumCollisionObjects() - 1; i >= 0; i--)
	{
		btCollisionObject* obj = world->getCollisionObjectArray()[i];
		if (obj->getUserPointer() == (void*)111)  // only road
		{
			delete obj->getCollisionShape();  //?
			
			btRigidBody* body = btRigidBody::upcast(obj);
			if (body && body->getMotionState())
				delete body->getMotionState();

			world->removeCollisionObject(obj);
			delete obj;
		}
	}


	//  update terrain
	scn->terrain->dirty();  //rect..
	scn->UpdBlendmap();
	bTerUpd = true;


	//  put sel segs on terrain
	for (std::set<int>::const_iterator it = scn->road->vSel.begin(); it != scn->road->vSel.end(); ++it)
		scn->road->mP[*it].onTer = true;

	//  restore orig road width
	scn->road->Rebuild(true);
	
	// todo: ?restore road sel after load F5..

	LogO(String("::: Time Ter Align: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");
}
///--------------------------------------------------------------------------------------------------------------
//  Create Terrain
///--------------------------------------------------------------------------------------------------------------
void CScene::CreateTerrain(bool bNewHmap, bool bTer, bool terLoad)
{
	Ogre::Timer tm;
	terrain = 0;

	
	///  sky
	Vector3 scl = app->pSet->view_distance*Vector3::UNIT_SCALE;
	CreateSkyDome(sc->skyMtr, scl, sc->skyYaw);
	UpdFog();

	//  light
	app->mSceneMgr->destroyAllLights();
	sun = app->mSceneMgr->createLight("Sun");
	sun->setType(Light::LT_DIRECTIONAL);  UpdSun();


if (bTer)
{
	///.
	UpdShaderParams();
	UpdLayerPars();
	

	///  --------  fill HeightField data --------
	//Ogre::Timer ti;
	if (terLoad || bNewHmap)
	{
		int wx = sc->td.iVertsX, wy = sc->td.iVertsY, wxy = wx * wy;  //wy=wx
		delete[] sc->td.hfHeight;  sc->td.hfHeight = new float[wxy];
		const int size = wxy * sizeof(float);

		String name = app->gcom->TrkDir() + (bNewHmap ? "heightmap-new.f32" : "heightmap.f32");

		//  load from f32 HMap +
		{
			std::ifstream fi;
			fi.open(name.c_str(), std::ios_base::binary);
			fi.read((char*)&sc->td.hfHeight[0], size);
			fi.close();
		}
	}

	CreateBlendTex();  //+

	//LogO(String("::: Time Hmap: ") + fToStr(ti.getMilliseconds(),0,3) + " ms");  ti.reset();  // 4MB ~13ms


	///.
	UpdBlendmap();
	

	//  Terrain
	{
		if (!mTerrainGlobals)
			mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
		OGRE_DELETE mTerrainGroup;

		mTerrainGroup = OGRE_NEW TerrainGroup(app->mSceneMgr, Terrain::ALIGN_X_Z,
			sc->td.iTerSize, sc->td.fTerWorldSize);
		mTerrainGroup->setOrigin(Vector3::ZERO);

		SetupTerrain();

		if (sc->td.hfHeight)
			mTerrainGroup->defineTerrain(0,0, sc->td.hfHeight);
		else
			mTerrainGroup->defineTerrain(0,0, 0.f);

		//  sync load since we want everything in place when we start
		mTerrainGroup->loadAllTerrains(true);

		TerrainGroup::TerrainIterator ti = mTerrainGroup->getTerrainIterator();
		while (ti.hasMoreElements())
		{
			Terrain* t = ti.getNext()->instance;
			terrain = t;  //<set
			terrain->setVisibilityFlags(RV_Terrain);
		}
		mTerrainGroup->freeTemporaryResources();
	}

	//  Horizon  ----------
	if (app->pSet->horizon)
	{
		if (!mHorizonGlobals)
			mHorizonGlobals = OGRE_NEW TerrainGlobalOptions();
		OGRE_DELETE mHorizonGroup;

		mHorizonGroup = OGRE_NEW TerrainGroup(app->mSceneMgr, Terrain::ALIGN_X_Z,
			sc->td.iTerSize, sc->td.fTerWorldSize * 16.f);
		mHorizonGroup->setOrigin(Vector3::ZERO);

		SetupHorizon();

		//if (sc->td.hfHeight)
		//	mHorizonGroup->defineTerrain(0,0, sc->td.hfHeight);
		//else
			mHorizonGroup->defineTerrain(0,0, 0.f);

		mHorizonGroup->loadAllTerrains(true);

		TerrainGroup::TerrainIterator ti = mHorizonGroup->getTerrainIterator();
		while (ti.hasMoreElements())
		{
			Terrain* t = ti.getNext()->instance;
			//initBlendMaps(t);
			horizon = t;  //<set
			horizon->setVisibilityFlags(RV_Terrain);
		}
		mHorizonGroup->freeTemporaryResources();
	}
}//bTer

	
	///.
	changeShadows();

	//UpdBlendmap();  //-

	LogO(String("::: Time Terrain: ") + fToStr(tm.getMilliseconds(),0,3) + " ms");
}
int main(int argc, char* argv[])
{
	std::unique_ptr<ExecutionArgs> exArgs(new ExecutionArgs());
	if (!processCommandLineArgs(argc, argv, *exArgs)) {
		return -1;
	} else if (exArgs->helpPrompt) {
		std::cout << "Usage: sts [--help] || [--config]" << std::endl;
		std::cout << "Options:" << std::endl;
		std::cout << "\t --help - print this message;" << std::endl;
		std::cout << "\t --config - show config dialog." << std::endl;
		std::cout << std::endl;
		return 0;
	}

	try {
		Ogre::String lConfigFileName = "ogre.cfg";
		Ogre::String lPluginsFileName = "plugins.cfg";
		Ogre::String lLogFileName = "Ogre_STS.log";

		std::unique_ptr<Ogre::Root> lRoot(new Ogre::Root(lPluginsFileName, lConfigFileName, lLogFileName));

		if (exArgs->showConfigDialog) {
			if (!lRoot->showConfigDialog()) {
				return 0;
			}
		}

		Ogre::String lWindowTitle = "STS";
		Ogre::String lCustomCapacities = "";

		/* Check for the valid ogre.cfg */
		bool lCreateAWindowAutomatically = lRoot->restoreConfig();
		if (!lCreateAWindowAutomatically) {
			initSomeRenderSystem(lRoot);
		}
		Ogre::RenderWindow* lWindow = lRoot->initialise(lCreateAWindowAutomatically, lWindowTitle, lCustomCapacities);

		if (!lWindow) {
			/* ogre.cfg is not available - start with hardcoded parameters */
			unsigned int lSizeX = 800;
			unsigned int lSizeY = 600;
			bool lFullscreen = false;

			Ogre::NameValuePairList lParams;
			lParams["FSAA"] = "0";
			lParams["vsync"] = "true";
			lWindow = lRoot->createRenderWindow(lWindowTitle, lSizeX, lSizeY, lFullscreen, &lParams);
		}

		/* Create a scene manager */
		Ogre::SceneManager* lScene = lRoot->createSceneManager(Ogre::ST_GENERIC, "SceneManager");

		Ogre::SceneNode* lRootSceneNode = lScene->getRootSceneNode();

		/* Create camera */
		Ogre::Camera* lCamera = lScene->createCamera("MyCamera");

		/* Create viewport (camera <-> window) */
		Ogre::Viewport* vp = lWindow->addViewport(lCamera);

		vp->setAutoUpdated(true);
		vp->setBackgroundColour(Ogre::ColourValue(1, 0, 1));

		lCamera->setAspectRatio(float(vp->getActualWidth()) / vp->getActualHeight());
		lCamera->setPosition(Ogre::Vector3(0, 100, -1));
		lCamera->lookAt(Ogre::Vector3(0, 0, 0));

		/* Set clipping*/
		lCamera->setNearClipDistance(1.5f);
		lCamera->setFarClipDistance(3000.0f);

		/* Lighting */
		Ogre::Light* lLight = lScene->createLight("MainLight");
		lLight->setPosition(Ogre::Vector3(0, 100, 0));

		/* Resource manager */
		Ogre::String lRcGroupName = "Main group";
		initResourceMainGroup(lRcGroupName);

		/* Load model */
		Ogre::Entity* lShipEntity = lScene->createEntity("airship.mesh");
		lShipEntity->setCastShadows(false);

		Ogre::SceneNode* lShipNode = lRootSceneNode->createChildSceneNode();
		lShipNode->attachObject(lShipEntity);
		lShipNode->setScale(Ogre::Vector3(3.15f, 3.15f, 3.15f));

		/* Starship start point */
		Ogre::Vector3 razorSP(0, -200, -100);
		lShipNode->setPosition(razorSP);

		/* Sprite billboard */
		Ogre::SceneNode* lSpriteNode = lRootSceneNode->createChildSceneNode();
		Ogre::BillboardSet* lBillboardSet = lScene->createBillboardSet();
		lBillboardSet->setMaterialName("enemy_01", lRcGroupName);
		lBillboardSet->setTextureStacksAndSlices(1, 4);
		Ogre::Billboard* lSpriteBillboard = lBillboardSet->createBillboard(Ogre::Vector3(0, 0, 0));
		lSpriteBillboard->setDimensions(48.0f / 2.0f, 58.0f / 2.0f);
		lSpriteBillboard->setTexcoordIndex(1);
		lSpriteNode->attachObject(lBillboardSet);
		lSpriteNode->setPosition(Ogre::Vector3(0, -200, 100));

		/* Obtain the timer pointer */
		Ogre::Timer* lTimer = lRoot->getTimer();

		/* Skip all the messages */
		lWindow->setAutoUpdated(false);
		lRoot->clearEventTimes();

		while (!lWindow->isClosed()) {
			float angle = Ogre::Math::Sin(float(lTimer->getMilliseconds()) * Ogre::Math::PI / 2000.0f) * Ogre::Math::PI / 4.0f;
			float diplacement = Ogre::Math::Cos(float(lTimer->getMilliseconds()) * Ogre::Math::PI / 2000.0f) * 100.0f;
			lShipNode->setOrientation(Ogre::Quaternion(Ogre::Radian(angle), Ogre::Vector3(0, 0, 1)));
			lShipNode->setPosition(razorSP + Ogre::Vector3(diplacement, 0.0f, 0.0f));

			unsigned int spriteFrame = (lTimer->getMilliseconds() / 125) % 2;
			lSpriteBillboard->setTexcoordIndex(spriteFrame);

			lWindow->update(false);
			lWindow->swapBuffers();
			lRoot->renderOneFrame();

			Ogre::WindowEventUtilities::messagePump();
		}
		Ogre::LogManager::getSingleton().logMessage("Render window closed.");
	}
	catch (Ogre::Exception &e) {
		std::cerr << "Ogre::Exception: " << e.what() << std::endl;
	}
	catch (std::exception &e) {
		std::cerr << "std::exception: " << e.what() << std::endl;
	}

	return 0;
}