/** ******************************************************************************* @file /gui/engine/MapControllers.cpp @brief Zakladni kontrolery pro mapu -kamera -manager kontroleru @author Vajicek @version 0.1 ******************************************************************************/ #include "gui/common/Sounds.h" #include "gui/model/guimap.h" #include "gui/GUI.h" #include "gui/engine/MapControllers.h" #include "gui/engine/MapCamera.h" #include "gui/common/mymath_ext.h" #include "common/Log.h" // #include "gui/contexts/Game.h" #include "world/world_client.h" #ifdef _DEBUG static TLog glog(1); #endif #define MCLOG //glog.LogMsg namespace gui{ /*TMapControllerManager********************************************************/ void TMapControllerManager::updateControlers(int absTime){ TControllerManager::updateControlers(absTime); } void TMapControllerManager::updateInput(INPUT *in){ input = in; } TMapControllerManager::TMapControllerManager(){ input = NULL; } void TMapControllerManager::setSpeed(int sf){ iSpeed = sf; switch(iSpeed){ case 1: setTimeRatio(5,true); break; case 2: setTimeRatio(15,true); break; case 3: setTimeRatio(30,true); break; } } /*TInputController*************************************************************/ TInputController::TInputController(TMapControllerManager *mcm){ RTTID("inpctrl"); pmcm = mcm; } INPUT* TInputController::getInput(){ return (pmcm->input); } /*TMainCameraController*******************************************************/ #define SCROLL_DELAY 37 void TMainCameraController::update(int absoluteTime){ // if(!iActived)return; // TMainCamera* maincam = (TMainCamera*)data; INPUT* input = getInput(); if(!input)return; // Uint8 *pkeys; int knum; if (input->type==SDL_NOEVENT){ /* kamera */ SDL_PumpEvents(); pkeys = SDL_GetKeyState(&knum); if ((!pkeys[SDLK_LALT])&&(!pkeys[SDLK_RALT])) maincam->editing = false; if (maincam->editing){ // maincam->turn(CAM_TURN_STEP*(input->mousepos.x-maincam->startEdit[0]), CAM_TURN_STEP*(input->mousepos.y-maincam->startEdit[1]) ); // maincam->startEdit[0] = input->mousepos.x; maincam->startEdit[1] = input->mousepos.y; } else if (TaoKernel::aoKernel->isKeyboardFree() && ((absoluteTime - iLastTime) > SCROLL_DELAY)) { if ( input->mousepos.x==0 ) maincam->scroll(-CAM_SCROLL_STEP,0); if ( input->mousepos.x==SCREEN_WIDTH-1 ) maincam->scroll(CAM_SCROLL_STEP,0); if ( input->mousepos.y==0 ) maincam->scroll(0,CAM_SCROLL_STEP); if ( input->mousepos.y==SCREEN_HEIGHT-1 ) maincam->scroll(0,-CAM_SCROLL_STEP); } if (TaoKernel::aoKernel->isKeyboardFree() && ((absoluteTime - iLastTime) > SCROLL_DELAY)) { if(pkeys[SDLK_UP]) maincam->scroll(0,CAM_SCROLL_STEP); if(pkeys[SDLK_DOWN]) maincam->scroll(0,-CAM_SCROLL_STEP); if(pkeys[SDLK_RIGHT]) maincam->scroll(CAM_SCROLL_STEP,0); if(pkeys[SDLK_LEFT]) maincam->scroll(-CAM_SCROLL_STEP,0); if (pkeys[SDLK_p]) maincam->incRadius(-CAM_RADIUS_STEP); if (pkeys[SDLK_l]) maincam->incRadius(CAM_RADIUS_STEP); } if ((absoluteTime - iLastTime) > SCROLL_DELAY) iLastTime = absoluteTime; } // if (input->type==SDL_NOEVENT) else { if (input->type == INPUT_KEY_DOWN){ //reset if (input->key.sym == SDLK_HOME) maincam->base(); //rotace if ((input->key.sym == SDLK_LALT)||(input->key.sym == SDLK_RALT)) { // maincam->startEdit[0] = input->mousepos.x; maincam->startEdit[1] = input->mousepos.y; maincam->editing = true; } } // if (input->type == INPUT_KEY_DOWN) if (input->type == INPUT_KEY_UP){ if ((input->key.sym == SDLK_LALT)||(input->key.sym == SDLK_RALT)) { maincam->editing = false; } } // if (input->type == INPUT_KEY_UP) if (input->type==INPUT_MOUSE_DOWN){ //zoom if (input->button == SDL_BUTTON_WHEELUP) maincam->incRadius(-CAM_RADIUS_STEP); if (input->button == SDL_BUTTON_WHEELDOWN) maincam->incRadius(CAM_RADIUS_STEP); } } // if (input->type==SDL_NOEVENT) else } TMainCameraController::TMainCameraController(TMapControllerManager *mcm, TMainCamera* cam) :TInputController(mcm) { RTTID("maincam_c"); activate(0,0); data = (void*)cam; iLastTime = KTime(); } /******************************************************************************/ void TMovingCameraController::move(P3F* pos1, P3F* dir1, P3F* pos2, P3F* dir2){ if(path) delete path; // path = new TJoinHermiteanCubic(20); // float dist = DISTV3(pos1->p, pos2->p); float ang = Angle3Db(dir1, dir2); // NormalizeV3(dir1->p); NormalizeV3(dir2->p); MulV3(dir1->p,dist); MulV3(dir2->p,dist/*(1.1 - cos(ang))*/); // path->addPoint(pos1); path->addPoint(dir1); path->addPoint(pos2); path->addPoint(dir2); // path->build(); iDuration = ROUND( path->length()*3.0f ); } void TMovingCameraController::moveTo(P3F* pos, P3F* dir){ if(path) delete path; // path = new TJoinHermiteanCubic(20); // P3F campos; P3F camdir; CopyV4toV3(campos.p, camera->p4fPos.p); CopyV4toV3(camdir.p, camera->p4fDir.p); // float dist = DISTV3(pos->p, campos.p); NormalizeV3(camdir.p); MulV3(camdir.p, dist); NormalizeV3(dir->p); MulV3(dir->p, dist); // path->addPoint(&campos); path->addPoint(&camdir); path->addPoint(pos); path->addPoint(dir); // path->build(); iDuration = ROUND( path->length()/fSpeed ); } TMovingCameraController::TMovingCameraController(TguiMap* _map, TCamera* cam){ RTTID("movcam_c"); camera = cam; data = _map; path = NULL; iFreeFlight = 0; fSpeed = 0.1f; } int TMovingCameraController::focusTo(P3F* pos, float speed){ moveType = cmtFocus; p3fStart = ((TMainCamera*)camera)->centre; p3fFocus = *pos; // float dist = DISTV3(p3fFocus.p, p3fStart.p); iDuration = (int)ceil( dist/speed ); // activate(KTime(), 0); // return ROUND( iDuration/fTimeRatio+iActivationTime ); } void TMovingCameraController::setTimeRatio(float tr, int recursive){ TController::setTimeRatio(tr, recursive); fTimeRatio = 1; } void TMovingCameraController::freeFlight(){ P3F newpos, newdir; fFlightAltitude = 100; moveType = cmtFreeFlight; activate(KTime(), 0); //todo: okraje newpos.x = RAND(500, ((TguiMap*)data)->aabbDim.x-500); newpos.y = RAND(500, ((TguiMap*)data)->aabbDim.y-500); ((TguiMap*)data)->altitude(newpos.x, newpos.y, &(newpos.z)); newpos.z += fFlightAltitude; // newdir = TVector( TVector(camera->aabbCenter) - TVector(newpos) ).toP3F(); newdir.z = 0; moveTo(&newpos, &newdir); } void TMovingCameraController::cancelFreeFlight(){ deactivate(); delete path; path = NULL; iFreeFlight = 0; } void TMovingCameraController::update(int absoluteTime){ TguiMap* map = (TguiMap*)data; // int rtime = (int)((absoluteTime - iActivationTime)*fTimeRatio); // float t = float(rtime)/iDuration; //out-of range if(t > 1) t = 1; if(t < 0) t = 0; // switch( moveType ){ case cmtFreeFlight: case cmtFly:{ P3F pos, dir, up; SETV3(up.p, 0,0,1); path->eval(t,&pos); path->evalDerivation(t,&dir); // float z; map->altitude(pos.x,pos.y,&z); pos.z = z + fFlightAltitude; // camera->lookAt( pos.x,pos.y,pos.z, pos.x+dir.x,pos.y+dir.y,pos.z+dir.z, up.x,up.y,up.z); }break; case cmtFocus:{ TVector c = TVector(p3fStart)*(1-t)+TVector(p3fFocus)*t; ((TMainCamera*)camera)->setCentre(c.x, c.y); }break; }//switch // if(t == 1){ deactivate(); switch( moveType ){ case cmtFreeFlight:{ delete path; path = NULL; freeFlight(); }break; case cmtFly:{ delete path; path = NULL; }break; case cmtFocus:{ }break; }//switch }//if } /******************************************************************************/ TEventInfo::TEventInfo(TEventInfoType t, wchar_t* m, int l, void* d1, void* d2){ type = t; msg = KInitWString(m); location = l; data1 = d1; data2 = d2; } /******************************************************************************/ void TEventVector::releaseEventsVector() { for(iterator it = begin(); it != end(); it++) { // KReleaseWString( (*it)->msg ); delete (*it); } clear(); } /******************************************************************************/ #define EVENT_SHOW 1 #define EVENT_NEXT 2 #define EVENT_FINISH 3 #define EVENT_FINISH_DELAY 500 #define EVENT_NEXT_DELAY 500 TEventPlayer::TEventPlayer(TguiMap* m) { map = m; events.clear(); } TEventPlayer::~TEventPlayer(){ } void TEventPlayer::showEvents(TEventVector* ev){ //restart if( !iActived || (iActived && current == events.end()) ){ //odstran ukoncovak removeActions( EVENT_FINISH ); // events = *ev; current = events.begin(); //prehraj aktualni playEvent(); } //napojeni else { //uloz aktualniho TEventInfo* e = *current; //vloz nove for(TEventVector::iterator it1 = ev->begin(); it1 != ev->end(); it1++) events.push_back(*it1); //najdi aktualniho for(TEventVector::iterator it2 = events.begin(); it2 != events.end(); it2++) if(*it2 == e){ current = it2; break; } } //aktivuj if(!iActived) activate( KTime() ); } void TEventPlayer::playEvent(){ TSheduledAction* sa; int t = KTime(); // if(current==events.end()){ MCLOG("playEvent: cur==end\n"); //na jednotku TUnit* u = ((TGame*)TGUI::gui_inst->game)->nextUnit(); if(u)t = scrollToHex(u->hexWhereIam->getIndex()); //konec sa = createAction(EVENT_FINISH, NULL, t+EVENT_FINISH_DELAY, 0); insertAction(sa); } else{ TEventInfo* ei = *current; //speciality switch(ei->type){ case eitUnitDeserted: case eitUnitDied: case eitUnitMembersDied: case eitUnitInterrupted: case eitVisibilityUpdate: case eitWarning: case eitComment: case eitInfo: case eitEndGame: default: if( ei->location >= 0 ){ MCLOG("playEvent: scrollToHex :%d\n", ei->location); t = scrollToHex(ei->location); } break; }//switch eventtype MCLOG("playEvent: insert :%d\n", t); //naplanuj akci sa = createAction(EVENT_SHOW, ei, t, 0); insertAction(sa); }//else } int TEventPlayer::scrollToHex(int h){ P3F p3f; map->hexCentre(&p3f, h); return map->focus(p3f.x, p3f.y); } void TEventPlayer::showMsg(wchar_t* msg){ ((TGame*)TGUI::gui_inst->game)->GAME_MSG(msg, 1, 1, 1); } int TEventPlayer::updateAction(int rtime, TSheduledAction* sa) { int t = KTime(); //akce switch(sa->iAction) { // === prehrej udalost === case EVENT_SHOW:{ //zobrazit udalost TEventInfo* ei = (TEventInfo*)(sa->pData); MCLOG("updateAction EVENT_SHOW: t: %d, ei->type: %d\n", t, ei->type); switch(ei->type) { case eitEndGame: { //ztmivacka t+=5000; ((TGame*)TGUI::gui_inst->game)->curtain->fadeIn(4000); }break; case eitExitGame: { //odemkni ((TGame*)TGUI::gui_inst->game)->unlockInput("UNLOCK::TEventPlayer::updateAction::EVENT_SHOW::eitExitGame\n"); //prepni kontext TGUI::gui_inst->screen->selectContext( "FINALSTATISTIC", TContextParameter(context_endgame, (void*)ei->data1) ); //preskoc naplanovani dalsi akce(EVENT_NEXT) return 1; }break; case eitUnitDeserted:{ //dezertuj jednotku ((TUnit*)ei->data1)->desert(); showMsg(ei->msg); }break; case eitUnitDied:{ //umri jednotku TIntContainer h; ((TUnit*)ei->data1)->realeaseUnit(h); showMsg(ei->msg); }break; case eitUnitMembersDied:{ //zabij panacky int count = *((int*)&ei->data2); ((TUnit*)ei->data1)->membersDied(count); showMsg(ei->msg); }break; case eitUnitInterrupted:{ //stop stavby ((TUnit*)ei->data1)->stopBuilding(); showMsg(ei->msg); }break; case eitVisibilityUpdate:{ TIntContainer* shown = (TIntContainer*)ei->data1; TIntContainer* hidden = (TIntContainer*)ei->data2; ((TGame*)TGUI::gui_inst->game)->updateVisibility( ((TGame*)TGUI::gui_inst->game)->iGUIOwner, shown, hidden ); delete shown; delete hidden; }break; //nic special case eitWarning: case eitComment: case eitInfo: default: //ukaz zpravu if (ei->location>=-5000) // BUG .. content of ei is not initialized { showMsg(ei->msg); } else { showMsg(L"A bug has occured ... the game might have crashed now"); printf("Bug?\n"); } break; }//switch eventtype //naplanuj dalsi akci sa = createAction(EVENT_NEXT, NULL, t+((ei->location>=0)?EVENT_NEXT_DELAY:0), 0); insertAction(sa); }break; // === prepni udalost === case EVENT_NEXT:{ MCLOG("EVENT_NEXT: playing NEXT\n"); //prejdi na dalsi udalost current++; // playEvent(); }break; // === ukonci retezec udalosti === case EVENT_FINISH:{ MCLOG("EVENT_FINISH\n"); //prehrej gong if(TSoundInterface::si) TSoundInterface::si->playSample(SAMPLE_GONG); //update gui ((TGame*)TGUI::gui_inst->game)->updateStatusBar(); //otevri infookno #ifndef CLIENT_AUTOPLAY ((TGame*)TGUI::gui_inst->game)->eventswindow->showModal(); #endif //odemkni gui ((TGame*)TGUI::gui_inst->game)->unlockInput("UNLOCK::TEventPlayer::updateAction::EVENT_FINISH\n"); //deaktivuj events.clear(); deactivate(); }break; }//switch action return 1; } /******************************************************************************/ TVisibilityScheduler::TVisibilityScheduler(TguiMap* m) { map = m; } void TVisibilityScheduler::alterVisibility(TIntContainer* h, TIntContainer* s, int player, int delay){ TSheduledAction* sa; TVisibilityModification* vm; int ktime = KTime(); // vm = new TVisibilityModification; if(h)vm->h = *h; if(s)vm->s = *s; vm->player = player; // sa = createAction(/*cislo akce*/1, vm, ktime+delay, 0); sa->pData = (void*)vm; // insertAction(sa); // if(!iActived)activate(ktime, 0); } int TVisibilityScheduler::updateAction(int rtime, TSheduledAction* sa){ // TVisibilityModification* vm = (TVisibilityModification*)sa->pData; if(vm){ // TGame* g = ((TGame*)TGUI::gui_inst->game); if( g->iGUIOwner == vm->player) { g->updateVisibility(vm->player, &(vm->s), &(vm->h)); } // delete vm; } return 1; } }//namespace /******************************************************************************/