// newPoses - Get new car pos from game // caution: called from GAME, 2nd thread, no Ogre stuff here /// Todo: move arrow update and ChampionshipAdvance to updatePoses ... //--------------------------------------------------------------------------------------------------------------- void App::newPoses(float time) // time only for camera update { if (!pGame || bLoading || pGame->cars.empty() /*|| carPoses.empty() || iCurPoses.empty()*/) return; PROFILER.beginBlock(".newPos "); double rplTime = pGame->timer.GetReplayTime(0); // from start double lapTime = pGame->timer.GetPlayerTime(0); double rewTime = pSet->rpl_ghostrewind ? pGame->timer.GetRewindTimeGh(0) : lapTime; // iterate through all car models and set new pos info (from vdrift sim or replay) CarModel* carM0 = carModels[0]; for (int c = 0; c < carModels.size(); ++c) { CarModel* carM = carModels[c]; bool bGhost = carM->isGhost(); CAR* pCar = carM->pCar; PosInfo pi; // new, to fill data // car perf test logic //-------------------------------- if (bPerfTest && c==0) newPerfTest(time); // play get data from replay / ghost ///----------------------------------------------------------------------- if (bGhost) { ///>> track's ghost if (carM->isGhostTrk()) { TrackFrame tf; // par: sec after, 1st lap float lap1 = pGame->timer.GetCurrentLap(0) > 0 ? 2.f : 0.f; bool ok = ghtrk.GetFrame(rewTime + lap1, &tf); // car Axes::toOgre(pi.pos, tf.pos); pi.rot = Axes::toOgre(tf.rot); pi.braking = tf.brake; pi.steer = tf.steer / 127.f; //pi.fboost = 0.f; pi.speed = 0.f; pi.percent = 0.f; //pi.fHitTime = 0.f; pi.fParIntens = 0.f; pi.fParVel = 0.f; //pi.vHitPos = Vector3::ZERO; pi.vHitNorm = Vector3::UNIT_Y; // wheels //dynamics.SetSteering(state.steer, pGame->GetSteerRange()); //peers can have other game settins.. for (int w=0; w < carM->numWheels; ++w) { MATHVECTOR<float,3> whP = carM->whPos[w]; whP[2] += 0.05f; // up tf.rot.RotateVector(whP); Axes::toOgre(pi.whPos[w], tf.pos + whP); if (w < 2) // front steer { float a = (pi.steer * carM->maxangle) * -PI_d/180.f; QUATERNION<float> q; q.Rotate(a, 0,0,1); pi.whRot[w] = Axes::toOgreW(tf.rot * carM->qFixWh[w%2] * q); } else pi.whRot[w] = Axes::toOgreW(tf.rot * carM->qFixWh[w%2]); } } else ///>> ghost { ReplayFrame2 gf; float ti = std::min((float)rewTime, ghplay.GetTimeLength()); bool ok = ghplay.GetFrame(ti, &gf, 0); if (ok) pi.FromRpl2(&gf, 0); if (carM->vtype == V_Sphere) { // weird fix, mini rot pi.carY = Vector3::UNIT_Y; pi.hov_roll = -pi.hov_roll; } } } else ///>> replay if (bRplPlay) { #ifdef DEBUG assert(c < frm.size()); #endif ReplayFrame2& rf = frm[c]; // frm also used in car.cpp for sounds if (c < replay.header.numPlayers) { bool ok = replay.GetFrame(rplTime, &rf, c); if (ok) { pi.FromRpl2(&rf, &pCar->dynamics); pCar->SetPosition(rf.pos, rf.rot); // for objs hit carM->trackPercent = rf.percent /255.f*100.f; } else { carM->fCam->First(); pGame->timer.RestartReplay(0); //at end } } } else ///>> sim, game - get data from vdrift if (pCar) { pi.FromCar(pCar); pi.percent = carM->trackPercent; } pi.bNew = true; //<< rewind ///----------------------------------------------------------------------- if (!bRplPlay && !pGame->pause && !bGhost && pCar) if (pCar->bRewind && pSet->game.rewind_type > 0) { // do rewind (go back) double& gtime = pGame->timer.GetRewindTime(c); gtime = std::max(0.0, gtime - time * gPar.rewindSpeed); double& ghtim = pGame->timer.GetRewindTimeGh(c); ghtim = std::max(0.0, ghtim - time * gPar.rewindSpeed); //rewind ghost time too if (gPar.backTime) { pGame->timer.Back(c, - time * gPar.rewindSpeed); ghost.DeleteFrames(0, ghtim); } RewindFrame rf; bool ok = rewind.GetFrame(gtime, &rf, c); pCar->SetPosRewind(rf.pos, rf.rot, rf.vel, rf.angvel); pCar->dynamics.fDamage = rf.fDamage; // take damage back if (carModels[c]->vtype == V_Sphere) pCar->dynamics.sphereYaw = rf.hov_roll; carModels[c]->First(); } else if (c < 4) // save data { const CARDYNAMICS& cd = pCar->dynamics; RewindFrame fr; fr.time = pGame->timer.GetRewindTime(c); fr.pos = cd.body.GetPosition(); fr.rot = cd.body.GetOrientation(); fr.vel = cd.GetVelocity(); fr.angvel = cd.GetAngularVelocity(); fr.fDamage = cd.fDamage; if (cd.vtype == V_Sphere) fr.hov_roll = cd.sphereYaw; else fr.hov_roll = cd.hov_roll; //? fr.hov_throttle = cd.hov_throttle; rewind.AddFrame(fr, c); // rec rewind } //<< record save data ///----------------------------------------------------------------------- if (pSet->rpl_rec && !bRplPlay && !pGame->pause && !bGhost && pCar) { if (iRplSkip++ >= 1) // 1 half game framerate { iRplSkip = 0; ReplayFrame2 fr; fr.time = rplTime; fr.percent = carM->trackPercent /100.f*255.f; fr.FromCar(pCar, replay.GetLastHitTime(c)); replay.AddFrame(fr, c); // rec replay if (c==0) /// rec ghost lap { fr.time = lapTime; ghost.AddFrame(fr, 0); } // recorded info ..in update { int size = replay.GetNumFrames() * 232; //par approx sizeof(ReplayFrame); std::string s = fToStr( float(size)/1000000.f, 2,5); String ss = String( TR("#{RplRecTime}: ")) + CHud::StrTime(replay.GetTimeLength()) + TR(" #{RplSize}: ") + s + TR(" #{UnitMB}"); gui->valRplName2->setCaption(ss); } } } if (bRplPlay) gui->valRplName2->setCaption(""); ///----------------------------------------------------------------------- // checkpoints, lap start //----------------------------------------------------------------------- if (bRplPlay || bGhost) // dont check for replay or ghost carM->bWrongChk = false; else { /// arrow update -------------------------------------- SplineRoad* road = scn->road; if (pSet->check_arrow && carM->eType == CarModel::CT_LOCAL && !bRplPlay && hud->arrow.node && road && road->mChks.size()>0) { // set animation start to old orientation hud->arrow.qStart = hud->arrow.qCur; // game start: no animation bool noAnim = carM->iNumChks == 0; // get vector from camera to checkpoint Vector3 chkPos = road->mChks[std::max(0, std::min((int)road->mChks.size()-1, carM->iNextChk))].pos; // last checkpoint, point to start pos if (carM->iNumChks == road->mChks.size()) chkPos = carM->vStartPos; const Vector3& playerPos = pi.pos; Vector3 dir = chkPos - playerPos; dir[1] = 0; // only x and z rotation Quaternion quat = Vector3::UNIT_Z.getRotationTo(-dir); const bool valid = !quat.isNaN(); if (valid) { if (noAnim) hud->arrow.qStart = quat; hud->arrow.qEnd = quat; // calc angle towards cam Real angle = (hud->arrow.qCur.zAxis().dotProduct(carM->fCam->mCamera->getOrientation().zAxis())+1)/2.0f; // set color in material (red for wrong dir) Vector3 col1 = angle * Vector3(0.0, 1.0, 0.0) + (1-angle) * Vector3(1.0, 0.0, 0.0); Vector3 col2 = angle * Vector3(0.0, 0.4, 0.0) + (1-angle) * Vector3(0.4, 0.0, 0.0); sh::Vector3* v1 = new sh::Vector3(col1.x, col1.y, col1.z); sh::Vector3* v2 = new sh::Vector3(col2.x, col2.y, col2.z); sh::Factory::getInstance().setSharedParameter("arrowColour1", sh::makeProperty <sh::Vector3>(v1)); sh::Factory::getInstance().setSharedParameter("arrowColour2", sh::makeProperty <sh::Vector3>(v2)); } } //---------------------------------------------------------------------------- if (carM->bGetStPos) // first pos is at start { carM->bGetStPos = false; carM->matStPos.makeInverseTransform(pi.pos, Vector3::UNIT_SCALE, pi.rot); carM->ResetChecks(); } if (road && !carM->bGetStPos) { // start/finish box dist Vector4 carP(pi.pos.x,pi.pos.y,pi.pos.z,1); carM->vStDist = carM0->matStPos * carP; // start pos from 1st car always carM->bInSt = abs(carM->vStDist.x) < road->vStBoxDim.x && abs(carM->vStDist.y) < road->vStBoxDim.y && abs(carM->vStDist.z) < road->vStBoxDim.z; carM->iInChk = -1; carM->bWrongChk = false; bool locar = carM->eType == CarModel::CT_LOCAL; int ncs = road->mChks.size(); if (ncs > 0) { // Finish -------------------------------------- if (locar && (carM->bInSt && carM->iNumChks == ncs && carM->iCurChk != -1)) { /// Lap bool finished = (pGame->timer.GetCurrentLap(c) >= pSet->game.num_laps) && (mClient || pSet->game.local_players > 1); // multiplay or split bool best = finished ? false : // dont inc laps when race over (in multiplayer or splitscreen mode) pGame->timer.Lap(c, !finished, pSet->game.trackreverse); //,boost_type? double timeCur = pGame->timer.GetPlayerTimeTot(c); // Network notification, send: car id, lap time ---- if (mClient && c == 0 && !finished) mClient->lap(pGame->timer.GetCurrentLap(c), pGame->timer.GetLastLap(c)); /// new best lap, save ghost bool newbest = false; if (!pSet->rpl_bestonly || best || gPar.backTime) if (c==0 && pSet->rpl_rec) // for many, only 1st car { ghost.SaveFile(gui->GetGhostFile()); //,boost_type? ghplay.CopyFrom(ghost); isGhost2nd = false; // hide 2nd ghost newbest = true; } bool champ = pSet->game.champ_num >= 0, chall = pSet->game.chall_num >= 0; bool chs = champ || chall; if (!chs) { if (newbest) pGame->snd_lapbest->start(); //) else pGame->snd_lap->start(); //) } ghost.Clear(); carM->ResetChecks(); // restore boost fuel, each lap ---- if (pSet->game.boost_type == 1 && carM->pCar) carM->pCar->dynamics.boostFuel = carM->pCar->dynamics.boostFuelStart; // damage decrease, each lap --- if (pSet->game.damage_dec > 0.f) carM->pCar->dynamics.fDamage = std::max(0.f, carM->pCar->dynamics.fDamage - pSet->game.damage_dec); // upd lap results ---- carM->updLap = false; carM->fLapAlpha = 1.f; /// all laps finished = pGame->timer.GetCurrentLap(c) >= pSet->game.num_laps; if (finished && !mClient) { if (!chs) { if (carM->iWonPlace == 0) // split screen winner places { if (pSet->game.local_players > 1) { int n = std::min(2, std::max(0, 3 - carIdWin)); pGame->snd_win[n]->start(); //) } carM->iWonPlace = carIdWin++; } } else if (champ) gui->ChampionshipAdvance(timeCur); else gui->ChallengeAdvance(timeCur); } } // checkpoints -------------------------------------- for (int i=0; i < ncs; ++i) { const CheckSphere& cs = road->mChks[i]; Real d2 = pi.pos.squaredDistance(cs.pos); if (d2 < cs.r2) // car in checkpoint { carM->iInChk = i; //\ loop camera change if (pSet->cam_loop_chng && carM->fCam && cs.loop && (carM->iLoopChk == -1 || carM->iLoopChk != i) && pCar->dynamics.vtype != V_Sphere) { carM->iLoopChk = i; if (carM->iLoopLastCam == -1) { carM->iLoopLastCam = carM->fCam->miCurrent; carM->fCam->setCamera(pSet->cam_in_loop); } else { carM->fCam->setCamera(carM->iLoopLastCam); carM->iLoopLastCam = -1; } } // next check if (i == carM->iNextChk && carM->iNumChks < ncs) { carM->iCurChk = i; carM->iNumChks++; carM->timeAtCurChk = pGame->timer.GetPlayerTime(c); int ii = (pSet->game.trackreverse ? -1 : 1) * road->iDir; carM->iNextChk = (carM->iCurChk + ii + ncs) % ncs; carM->UpdNextCheck(); // save car pos and rot carM->pCar->SavePosAtCheck(); carM->updTimes = true; if (pSet->snd_chk && locar) pGame->snd_chk->start(); //) } else if (carM->iInChk != carM->iCurChk && !scn->sc->noWrongChks) // denies { carM->bWrongChk = true; if (carM->iInWrChk != carM->iInChk) { carM->iInWrChk = carM->iInChk; if (pSet->snd_chkwr && locar) pGame->snd_chkwr->start(); //) } } break; } } } } } /// store new pos info in queue _________ if (!(isFocGui || isTweakTab()) || mClient) // dont if gui, but network always { int qn = (iCurPoses[c] + 1) % CarPosCnt; // next index in queue carPoses[qn][c] = pi; // update camera if (carM->fCam) carM->fCam->update(time, pi, &carPoses[qn][c], &pGame->collision, !bRplPlay && pSet->cam_bounce); iCurPoses[c] = qn; // atomic, set new index in queue ///)) upd sound camera if (c == 0 && pGame->snd) { Vector3 x,y,z; carPoses[qn][c].camRot.ToAxes(x,y,z); pGame->snd->setCamera(carPoses[qn][c].camPos, -z, y, Vector3::ZERO); } } } PROFILER.endBlock(".newPos "); }
bool App::keyPressed( const OIS::KeyEvent &arg ) { // update all keystates (needed for all action("..") from oisb) if (mOISBsys) mOISBsys->process(0.0001/*?0*/); // action key == pressed key #define action(s) actionIsActive(s, mKeyboard->getAsString(arg.key)) if (!bAssignKey) { // change gui tabs if (isFocGui && !pSet->isMain) { MyGUI::TabPtr tab = 0; MyGUI::TabControl* sub = 0; switch (pSet->inMenu) { case WND_Game: case WND_Champ: tab = mWndTabsGame; sub = vSubTabsGame[tab->getIndexSelected()]; break; case WND_Replays: tab = mWndTabsRpl; break; case WND_Help: tab = mWndTabsHelp; break; case WND_Options: tab = mWndTabsOpts; sub = vSubTabsOpts[tab->getIndexSelected()]; break; } if (tab) if (shift) { if (action("PrevTab")) { // prev gui subtab if (sub) { int num = sub->getItemCount(); sub->setIndexSelected( (sub->getIndexSelected() - 1 + num) % num ); } } else if (action("NextTab")) { // next gui subtab if (sub) { int num = sub->getItemCount(); sub->setIndexSelected( (sub->getIndexSelected() + 1) % num ); } } }else { int num = tab->getItemCount()-1, i = 0, n = 0; if (action("PrevTab")) { i = tab->getIndexSelected(); do{ if (i==1) i = num; else --i; ++n; } while (n < num && tab->getButtonWidthAt(i) == 1); tab->setIndexSelected(i); MenuTabChg(tab,i); return true; } else if (action("NextTab")) { i = tab->getIndexSelected(); do{ if (i==num) i = 1; else ++i; ++n; } while (n < num && tab->getButtonWidthAt(i) == 1); tab->setIndexSelected(i); MenuTabChg(tab,i); return true; } } } else if (!isFocGui && pSet->show_graphs) // change graphs type { int& v = pSet->graphs_type; int vo = v; if (action("PrevTab")) v = (v-1 + graph_types) % graph_types; if (action("NextTab")) v = (v+1) % graph_types; if (vo != v) { float fv = float(v) / graph_types; slGraphsType(slGraphT, fv); slGraphT->setValue(fv); if (v == 4) iUpdTireGr = 1; //upd now } } // gui on/off or close wnds if (action("ShowOptions") && !alt) { if (mWndNetEnd && mWndNetEnd->getVisible()) { mWndNetEnd->setVisible(false); // hide netw end return false; } else { if (mWndChampEnd && mWndChampEnd->getVisible()) mWndChampEnd->setVisible(false); // hide champs end toggleGui(true); return false; } } // new game - reload not in multiplayer if (action("RestartGame") && !mClient) { NewGame(); return false; } // new game - fast (same track & cars) if (action("ResetGame") && !mClient) { for (int c=0; c < carModels.size(); ++c) { CarModel* cm = carModels[c]; if (cm->pCar) cm->pCar->bResetPos = true; if (cm->fCam) cm->fCam->first = true; cm->ResetChecks(); cm->iWonPlace = 0; cm->iWonPlaceOld = 0; cm->iWonMsgTime = 0.f; } pGame->timer.Reset(-1); pGame->timer.pretime = mClient ? 2.0f : pSet->game.pre_time; // same for all multi players carIdWin = 1; // ghost.Clear(); // } // Screen shot //if (action("Screenshot")) //isnt working const OISB::Action* act = OISB::System::getSingleton().lookupAction("General/Screenshot",false); if (act && act->isActive()) { mWindow->writeContentsToTimestampedFile(PATHMANAGER::GetScreenShotDir() + "/", ".jpg"); return false; } using namespace OIS; // main menu keys if (pSet->isMain && isFocGui) { switch (arg.key) { case KC_UP: case KC_NUMPAD8: pSet->inMenu = (pSet->inMenu-1+WND_ALL)%WND_ALL; toggleGui(false); return true; case KC_DOWN: case KC_NUMPAD2: pSet->inMenu = (pSet->inMenu+1)%WND_ALL; toggleGui(false); return true; case KC_RETURN: pSet->isMain = false; toggleGui(false); return true; } } // esc if (arg.key == KC_ESCAPE) { if (pSet->escquit) mShutDown = true; // quit else if (mWndChampStage->getVisible()) /// close champ wnds btnChampStageStart(0); else toggleGui(true); // gui on/off return true; } // shortcut keys for gui access (alt-T,H,S,G,V,.. ) if (alt) switch (arg.key) { case KC_Q: case KC_T: GuiShortcut(WND_Game, 1); return true; // Q,T Track case KC_C: GuiShortcut(WND_Game, 2); return true; // C Car case KC_H: GuiShortcut(WND_Champ, 6); return true; // H Champs case KC_U: GuiShortcut(WND_Game, 5); return true; // U Multiplayer case KC_W: GuiShortcut(WND_Game, 4); return true; // W Setup case KC_R: GuiShortcut(WND_Replays, 1); return true; // R Replays case KC_S: GuiShortcut(WND_Options, 1); return true; // S Screen case KC_E: GuiShortcut(WND_Options, 1,1); return true; // E -Effects case KC_G: GuiShortcut(WND_Options, 2); return true; // G Graphics case KC_N: GuiShortcut(WND_Options, 2,2); return true; // N -Vegetation case KC_V: GuiShortcut(WND_Options, 3); return true; // V View case KC_M: GuiShortcut(WND_Options, 3,1); return true; // M -Minimap case KC_O: GuiShortcut(WND_Options, 3,3); return true; // O -Other case KC_I: GuiShortcut(WND_Options, 4); return true; // I Input } ///* tire edit */ if (pSet->graphs_type == 4) { int& iCL = iEdTire==1 ? iCurLong : (iEdTire==0 ? iCurLat : iCurAlign); int iCnt = iEdTire==1 ? 11 : (iEdTire==0 ? 15 : 18); switch (arg.key) { case KC_HOME: case KC_NUMPAD7: // mode long/lat iEdTire = iEdTire==1 ? 0 : 1; iUpdTireGr=1; return true; case KC_END: case KC_NUMPAD1: // mode align iEdTire = iEdTire==2 ? 0 : 2; iUpdTireGr=1; return true; /*case KC_1:*/ case KC_PGUP: case KC_NUMPAD9: // prev val iCL = (iCL-1 +iCnt)%iCnt; iUpdTireGr=1; return true; /*case KC_2:*/ case KC_PGDOWN: case KC_NUMPAD3: // next val iCL = (iCL+1)%iCnt; iUpdTireGr=1; return true; } } // not main menus //if (/*&& !pSet->isMain*/) { Widget* wf = MyGUI::InputManager::getInstance().getKeyFocusWidget(); bool edFoc = wf && wf->getTypeName() == "EditBox"; //if (wf) LogO(wf->getTypeName()+" " +toStr(edFoc)); switch (arg.key) { case KC_BACK: if (mClient && !isFocGui) // show/hide players net wnd { mWndNetEnd->setVisible(!mWndNetEnd->getVisible()); return true; } if (mWndChampStage->getVisible()) // back from champs stage wnd { btnChampStageBack(0); return true; } if (pSet->isMain) break; if (isFocGui) { if (edFoc) break; pSet->isMain = true; toggleGui(false); } else if (mWndRpl && !isFocGui) bRplWnd = !bRplWnd; // replay controls return true; case KC_P: // replay play/pause if (bRplPlay && !isFocGui) { bRplPause = !bRplPause; UpdRplPlayBtn(); return true; } break; case KC_K: // replay car ofs if (bRplPlay && !isFocGui) { --iRplCarOfs; return true; } break; case KC_L: // replay car ofs if (bRplPlay && !isFocGui) { ++iRplCarOfs; return true; } break; case KC_F: // focus on find edit if (ctrl && edFind && isFocGui && !pSet->isMain && pSet->inMenu == WND_Game && mWndTabsGame->getIndexSelected() == 1) { MyGUI::InputManager::getInstance().resetKeyFocusWidget(); MyGUI::InputManager::getInstance().setKeyFocusWidget(edFind); return true; } break; case KC_F7: // Times if (shift) { WP wp = chOpponents; ChkEv(show_opponents); ShowHUD(); } else if (!ctrl) { WP wp = chTimes; ChkEv(show_times); ShowHUD(); } return false; case KC_F8: // graphs if (ctrl) { WP wp = chGraphs; ChkEv(show_graphs); for (int i=0; i < graphs.size(); ++i) graphs[i]->SetVisible(pSet->show_graphs); } else // Minimap if (!shift) { WP wp = chMinimp; ChkEv(trackmap); for (int c=0; c < 4; ++c) if (ndMap[c]) ndMap[c]->setVisible(pSet->trackmap); } return false; case KC_F9: if (ctrl) // car debug surfaces { WP wp = chDbgS; ChkEv(car_dbgsurf); ShowHUD(); } else if (shift) // car debug text { WP wp = chDbgT; ChkEv(car_dbgtxt); ShowHUD(); } else // car debug bars { WP wp = chDbgB; ChkEv(car_dbgbars); ShowHUD(); } return true; case KC_F11: if (shift) // profiler times { WP wp = chProfTxt; ChkEv(profilerTxt); ShowHUD(); } else if (!ctrl) // Fps { WP wp = chFps; ChkEv(show_fps); if (pSet->show_fps) mFpsOverlay->show(); else mFpsOverlay->hide(); return false; } break; case KC_F10: // blt debug, txt if (shift) { WP wp = chBltTxt; ChkEv(bltProfilerTxt); return false; } else if (ctrl) { WP wp = chBlt; ChkEv(bltDebug); return false; } else // wireframe toggleWireframe(); return false; case KC_F5: // new game NewGame(); return false; case KC_RETURN: /// close champ wnds if (mWndChampStage->getVisible()) btnChampStageStart(0); else // chng trk/car + new game after up/dn if (isFocGui && !pSet->isMain) switch (pSet->inMenu) { case WND_Replays: btnRplLoad(0); break; case WND_Game: case WND_Champ: { switch (mWndTabsGame->getIndexSelected()) { case 1: changeTrack(); btnNewGame(0); break; case 2: changeCar(); btnNewGame(0); break; case 4: chatSendMsg(); break; case 5: btnChampStart(0); break; } break; } } return false; } } } InputBind(arg.key); if (isFocGui && mGUI) // gui { MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(arg.key), arg.text); return false; } return true; }
void App::channelChanged(ICS::Channel *channel, float currentValue, float previousValue) { if (currentValue != 1.f) return; #define action(a) (channel->getNumber() == a) // change tabs //---------------------------------------------------------------------------------------- // tweak if (mWndTweak->getVisible()) { TabPtr tab = gui->tabTweak; if (!shift && tab->getIndexSelected() == 0) tab = gui->tabEdCar; // car edit sections if (action(A_PrevTab)) { // prev gui subtab int num = tab->getItemCount(); tab->setIndexSelected( (tab->getIndexSelected() - 1 + num) % num ); } else if (action(A_NextTab)) { // next gui subtab int num = tab->getItemCount(); tab->setIndexSelected( (tab->getIndexSelected() + 1) % num ); } if (tab == gui->tabEdCar) // focus ed { pSet->car_ed_tab = tab->getIndexSelected(); MyGUI::InputManager::getInstance().resetKeyFocusWidget(); MyGUI::InputManager::getInstance().setKeyFocusWidget(gui->edCar[tab->getIndexSelected()]); } } // change gui tabs else if (isFocGui && !pSet->isMain) { MyGUI::TabPtr tab = 0; MyGUI::TabControl* sub = 0; switch (pSet->inMenu) { case MNU_Replays: tab = mWndTabsRpl; break; case MNU_Help: tab = mWndTabsHelp; break; case MNU_Options: tab = mWndTabsOpts; sub = gui->vSubTabsOpts[tab->getIndexSelected()]; break; default: tab = mWndTabsGame; sub = gui->vSubTabsGame[tab->getIndexSelected()]; break; } if (tab) if (shift) { if (sub) // prev, next subtab { bool chng = false; if (action(A_PrevTab)) { int num = sub->getItemCount(); chng = true; sub->setIndexSelected( (sub->getIndexSelected() - 1 + num) % num ); }else if (action(A_NextTab)) { int num = sub->getItemCount(); chng = true; sub->setIndexSelected( (sub->getIndexSelected() + 1) % num ); } if (chng && !sub->eventTabChangeSelect.empty()) sub->eventTabChangeSelect(sub, sub->getIndexSelected()); } } else // prev, next tab { int num = tab->getItemCount()-1, i = tab->getIndexSelected(), n = 0; bool chng = false; if (action(A_PrevTab)) { do{ if (i==1) i = num; else --i; ++n; } while (n < num && tab->getButtonWidthAt(i) == 1); chng = true; }else if (action(A_NextTab)) { do{ if (i==num) i = 1; else ++i; ++n; } while (n < num && tab->getButtonWidthAt(i) == 1); chng = true; } if (chng) { tab->setIndexSelected(i); gcom->tabMainMenu(tab,i); return; } } } // change graphs type else if (!isFocGui && pSet->show_graphs) { int& v = (int&)pSet->graphs_type; int vo = v; if (action(A_PrevTab)) v = (v-1 + Gh_ALL) % Gh_ALL; if (action(A_NextTab)) v = (v+1) % Gh_ALL; if (vo != v) { gui->cmbGraphs->setIndexSelected(v); gui->comboGraphs(gui->cmbGraphs, v); if (v == 4) iUpdTireGr = 1; //upd now } } //---------------------------------------------------------------------------------------- // Gui on/off or close wnds if (action(A_ShowOptions) && !alt) { Wnd wnd = mWndNetEnd; if (wnd && wnd->getVisible()) { wnd->setVisible(false); // hide netw end return; } else { wnd = mWndChampEnd; if (wnd && wnd->getVisible()) wnd->setVisible(false); // hide champs end wnd = mWndChallEnd; if (wnd && wnd->getVisible()) wnd->setVisible(false); // chall gui->toggleGui(true); return; } } // new game - Reload not in multiplayer if (action(A_RestartGame) && !mClient) { bPerfTest = ctrl; // ctrl-F5 start perf test if (bPerfTest) { pSet->gui.track = "Test10-FlatPerf"; pSet->gui.track_user = false; } iPerfTestStage = PT_StartWait; NewGame(); return; } // new game - fast (same track & cars) if (action(A_ResetGame) && !mClient) { for (int c=0; c < carModels.size(); ++c) { CarModel* cm = carModels[c]; if (cm->pCar) cm->pCar->bResetPos = true; if (cm->iLoopLastCam != -1 && cm->fCam) { cm->fCam->setCamera(cm->iLoopLastCam); //o restore cm->iLoopLastCam = -1; } cm->First(); cm->ResetChecks(); cm->iWonPlace = 0; cm->iWonPlaceOld = 0; cm->iWonMsgTime = 0.f; } pGame->timer.Reset(-1); pGame->timer.pretime = mClient ? 2.0f : pSet->game.pre_time; // same for all multi players carIdWin = 1; // ghost.Clear(); // } // Screen shot if (action(A_Screenshot)) mWindow->writeContentsToTimestampedFile(PATHMANAGER::Screenshots() + "/", ".jpg"); }
// newPoses - Get new car pos from game //--------------------------------------------------------------------------------------------------------------- void App::newPoses() { if (!pGame) return; if (pGame->cars.size() == 0) return; double rplTime = pGame->timer.GetReplayTime(); double lapTime = pGame->timer.GetPlayerTime(); // Iterate through all car models and get new pos info int iCarNum = 0; CarModel* carM0 = 0; std::vector<CarModel*>::iterator carMIt = carModels.begin(); std::vector<PosInfo>::iterator newPosIt = newPosInfos.begin(); while (carMIt != carModels.end()) { CarModel* carM = *carMIt; if (iCarNum==0) carM0 = carM; CAR* pCar = carM->pCar; PosInfo posInfo; bool bGhost = carM->eType == CarModel::CT_GHOST; // local data car,wheels MATHVECTOR <float,3> pos, whPos[4]; QUATERNION <float> rot, whRot[4]; //?double ///----------------------------------------------------------------------- // play get data from replay ///----------------------------------------------------------------------- if (bGhost) { ReplayFrame frame; bool ok = ghplay.GetFrame(lapTime, &frame, 0); // car pos = frame.pos; rot = frame.rot; // wheels for (int w=0; w < 4; ++w) { whPos[w] = frame.whPos[w]; whRot[w] = frame.whRot[w]; posInfo.whVel[w] = frame.whVel[w]; posInfo.whSlide[w] = frame.slide[w]; posInfo.whSqueal[w] = frame.squeal[w]; posInfo.whR[w] = replay.header.whR[iCarNum][w];// posInfo.whTerMtr[w] = frame.whTerMtr[w]; posInfo.whRoadMtr[w] = frame.whRoadMtr[w]; posInfo.fboost = frame.fboost; } ghostFrame = frame; } else if (bRplPlay) { // time from start bool ok = replay.GetFrame(rplTime, &fr, iCarNum); if (!ok) pGame->timer.RestartReplay(); // car pos = fr.pos; rot = fr.rot; // wheels for (int w=0; w < 4; ++w) { whPos[w] = fr.whPos[w]; whRot[w] = fr.whRot[w]; posInfo.whVel[w] = fr.whVel[w]; posInfo.whSlide[w] = fr.slide[w]; posInfo.whSqueal[w] = fr.squeal[w]; posInfo.whR[w] = replay.header.whR[iCarNum][w];// posInfo.whTerMtr[w] = fr.whTerMtr[w]; posInfo.whRoadMtr[w] = fr.whRoadMtr[w]; posInfo.fboost = fr.fboost; } } else // get data from vdrift //----------------------------------------------------------------------- if (pCar) { pos = pCar->dynamics.GetPosition(); rot = pCar->dynamics.GetOrientation(); for (int w=0; w < 4; ++w) { WHEEL_POSITION wp = WHEEL_POSITION(w); whPos[w] = pCar->dynamics.GetWheelPosition(wp); whRot[w] = pCar->dynamics.GetWheelOrientation(wp); //float wR = pCar->GetTireRadius(wp); posInfo.whVel[w] = pCar->dynamics.GetWheelVelocity(wp).Magnitude(); posInfo.whSlide[w] = -1.f; posInfo.whSqueal[w] = pCar->GetTireSquealAmount(wp, &posInfo.whSlide[w]); posInfo.whR[w] = pCar->GetTireRadius(wp);// posInfo.whTerMtr[w] = carM->whTerMtr[w]; posInfo.whRoadMtr[w] = carM->whRoadMtr[w]; } posInfo.fboost = pCar->dynamics.boostVal; } // transform axes, vdrift to ogre car & wheels //----------------------------------------------------------------------- posInfo.pos = Vector3(pos[0],pos[2],-pos[1]); Quaternion q(rot[0],rot[1],rot[2],rot[3]), q1; Radian rad; Vector3 axi; q.ToAngleAxis(rad, axi); q1.FromAngleAxis(-rad,Vector3(axi.z,-axi.x,-axi.y)); posInfo.rot = q1 * qFixCar; Vector3 vcx,vcz; q1.ToAxes(vcx,posInfo.carY,vcz); if (!isnan(whPos[0][0])) for (int w=0; w < 4; w++) { posInfo.whPos[w] = Vector3(whPos[w][0],whPos[w][2],-whPos[w][1]); Quaternion q(whRot[w][0],whRot[w][1],whRot[w][2],whRot[w][3]), q1; Radian rad; Vector3 axi; q.ToAngleAxis(rad, axi); q1.FromAngleAxis(-rad,Vector3(axi.z,-axi.x,-axi.y)); posInfo.whRot[w] = q1 * qFixWh; } posInfo.bNew = true; /// sound listener - - - - - if (!bGhost) { if (pGame->sound.Enabled()) // TODO: set from camera, for each player? .. { pGame->sound.SetListener( MATHVECTOR <float,3> (pos[0], pos[1], pos[2]), QUATERNION <float>(), //QUATERNION <float> (rot.x(), rot.y(), rot.z(), rot.w()), MATHVECTOR <float,3>()); } bool incar = true; if (pCar) { std::list <SOUNDSOURCE *> soundlist; pCar->GetEngineSoundList(soundlist); for (std::list <SOUNDSOURCE *>::iterator s = soundlist.begin(); s != soundlist.end(); s++) (*s)->Set3DEffects(!incar); } } ///----------------------------------------------------------------------- // record save data for replay ///----------------------------------------------------------------------- if (pSet->rpl_rec && !pGame->pause && !bGhost && pCar) { //static int ii = 0; //if (ii++ >= 0) // 1 half game framerate { //ii = 0; ReplayFrame fr; fr.time = rplTime; // time from start fr.pos = pos; fr.rot = rot; // car // wheels for (int w=0; w < 4; w++) { fr.whPos[w] = whPos[w]; fr.whRot[w] = whRot[w]; WHEEL_POSITION wp = WHEEL_POSITION(w); const TRACKSURFACE* surface = pCar->dynamics.GetWheelContact(wp).GetSurfacePtr(); fr.surfType[w] = !surface ? TRACKSURFACE::NONE : surface->type; // squeal fr.slide[w] = -1.f; fr.squeal[w] = pCar->GetTireSquealAmount(wp, &fr.slide[w]); fr.whVel[w] = pCar->dynamics.GetWheelVelocity(wp).Magnitude(); // susp fr.suspVel[w] = pCar->dynamics.GetSuspension(wp).GetVelocity(); fr.suspDisp[w] = pCar->dynamics.GetSuspension(wp).GetDisplacementPercent(); //replay.header.whR[w] = pCar->GetTireRadius(wp);// fr.whTerMtr[w] = carM->whTerMtr[w]; fr.whRoadMtr[w] = carM->whRoadMtr[w]; } // hud fr.vel = pCar->GetSpeedometer(); fr.rpm = pCar->GetEngineRPM(); fr.gear = pCar->GetGear(); fr.clutch = pCar->GetClutch(); fr.throttle = pCar->dynamics.GetEngine().GetThrottle(); fr.steer = pCar->GetLastSteer(); fr.fboost = pCar->dynamics.doBoost; // eng snd fr.posEngn = pCar->dynamics.GetEnginePosition(); fr.speed = pCar->GetSpeed(); fr.dynVel = pCar->dynamics.GetVelocity().Magnitude(); replay.AddFrame(fr, iCarNum); // rec replay if (iCarNum==0) /// rec ghost lap { fr.time = lapTime; ghost.AddFrame(fr, 0); } if (valRplName2) // recorded info { int size = replay.GetNumFrames() * sizeof(ReplayFrame); sprintf(s, "%5.2f", float(size)/1000000.f); String ss = String( TR("#{RplRecTime}: ")) + GetTimeString(replay.GetTimeLength()) + TR(" #{RplSize}: ") + s + TR(" #{UnitMB}"); valRplName2->setCaption(ss); } } } if (bRplPlay && valRplName2) valRplName2->setCaption(""); ///----------------------------------------------------------------------- // chekpoints, lap start //----------------------------------------------------------------------- if (bRplPlay || bGhost || !sc.ter) // dont check when replay play carM->bWrongChk = false; else { // checkpoint arrow if (pSet->check_arrow && !bRplPlay && arrowNode && road && road->mChks.size()>0) { // set animation start to old orientation arrowAnimStart = arrowAnimCur; // game start: no animation bool noAnim = carM->iNumChks == 0; // get vector from camera to checkpoint Vector3 chkPos = road->mChks[std::max(0, std::min((int)road->mChks.size()-1, carM->iNextChk))].pos; // workaround for last checkpoint if (carM->iNumChks == road->mChks.size()) { // point arrow to start position chkPos = carM->vStartPos; } //const Vector3& playerPos = carM->fCam->mCamera->getPosition(); const Vector3& playerPos = carM->pMainNode->getPosition(); Vector3 dir = chkPos - playerPos; dir[1] = 0; // only x and z rotation Quaternion quat = Vector3::UNIT_Z.getRotationTo(-dir); // convert to quaternion const bool valid = !quat.isNaN(); if (valid) { if (noAnim) arrowAnimStart = quat; arrowAnimEnd = quat; // set arrow color (wrong direction: red arrow) // calc angle towards cam Real angle = (arrowAnimCur.zAxis().dotProduct(carM->fCam->mCamera->getOrientation().zAxis())+1)/2.0f; // set color in material MaterialPtr arrowMat = MaterialManager::getSingleton().getByName("Arrow"); if (arrowMat->getTechnique(0)->getPass(1)->hasFragmentProgram()) { GpuProgramParametersSharedPtr fparams = arrowMat->getTechnique(0)->getPass(1)->getFragmentProgramParameters(); // green: 0.0 1.0 0.0 0.0 0.4 0.0 // red: 1.0 0.0 0.0 0.4 0.0 0.0 Vector3 col1 = angle * Vector3(0.0, 1.0, 0.0) + (1-angle) * Vector3(1.0, 0.0, 0.0); Vector3 col2 = angle * Vector3(0.0, 0.4, 0.0) + (1-angle) * Vector3(0.4, 0.0, 0.0); fparams->setNamedConstant("color1", col1); fparams->setNamedConstant("color2", col2); } } } if (carM->bGetStPos) // first pos is at start { carM->bGetStPos = false; carM->matStPos.makeInverseTransform(posInfo.pos, Vector3::UNIT_SCALE, posInfo.rot); carM->ResetChecks(); } if (road && !carM->bGetStPos) { // start/finish box dist Vector4 carP(posInfo.pos.x,posInfo.pos.y,posInfo.pos.z,1); carM->vStDist = carM0->matStPos * carP; // start pos from 1st car always carM->bInSt = abs(carM->vStDist.x) < road->vStBoxDim.x && abs(carM->vStDist.y) < road->vStBoxDim.y && abs(carM->vStDist.z) < road->vStBoxDim.z; carM->iInChk = -1; carM->bWrongChk = false; int ncs = road->mChks.size(); if (ncs > 0) { if (carM->bInSt && carM->iNumChks == ncs && carM->iCurChk != -1) // finish { bool best = pGame->timer.Lap(iCarNum, 0,0, true, pSet->trackreverse); //pGame->cartimerids[pCar] ? if (!pSet->rpl_bestonly || best) /// new best lap, save ghost if (iCarNum==0 && pSet->rpl_rec) // for many, only 1st- { ghost.SaveFile(GetGhostFile()); ghplay.CopyFrom(ghost); } ghost.Clear(); carM->ResetChecks(); // restore boost fuel, each lap if (pSet->boost_type == 1 && carM->pCar) carM->pCar->dynamics.boostFuel = gfBoostFuelStart; /// winner places for local players > 1 if (carM->iWonPlace == 0 && pGame->timer.GetCurrentLap(iCarNum) >= pSet->num_laps) carM->iWonPlace = carIdWin++; } for (int i=0; i < ncs; ++i) { const CheckSphere& cs = road->mChks[i]; Real d2 = posInfo.pos.squaredDistance(cs.pos); if (d2 < cs.r2) // car in checkpoint { carM->iInChk = i; // next check if (i == carM->iNextChk && carM->iNumChks < ncs) { carM->iCurChk = i; carM->iNumChks++; int ii = (pSet->trackreverse ? -1 : 1) * road->iDir; carM->iNextChk = (carM->iCurChk + ii + ncs) % ncs; // save car pos and rot carM->pCar->SavePosAtCheck(); } else if (carM->iInChk != carM->iCurChk) carM->bWrongChk = true; break; } } } } } (*newPosIt) = posInfo; carMIt++; newPosIt++; iCarNum++; // next } }