00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "cockpit/cMap.h"
00028 #include "cockpit/cCockpit.h"
00029 #include "nConfig.h"
00030 #include "tCoord.h"
00031
00032 #ifndef DEDICATED
00033
00034 #include "rRender.h"
00035 #include "rScreen.h"
00036 #include "gWinZone.h"
00037 #include "eRectangle.h"
00038 #include "ePlayer.h"
00039 #include "eTimer.h"
00040
00041 #include "rViewport.h"
00042 #include "eGrid.h"
00043 #include "eCamera.h"
00044 #include "gCycle.h"
00045
00046 #endif
00047
00048 #include <vector>
00049
00050 static bool stc_forbidHudMap = false;
00051
00052
00053 static nSettingItem<bool> fcs("FORBID_HUD_MAP", stc_forbidHudMap);
00054 extern std::vector<tCoord> se_rimWallRubberBand;
00055
00056 #ifndef DEDICATED
00057
00058 extern std::deque<gZone *> sg_Zones;
00059
00060 namespace cWidget {
00061
00062 void Map::ClipperRect::Begin(Map &map, tCoord const &e1, tCoord const &e2) {
00063
00064 GLdouble pl0[4] = {1.0, 0.0, 0.0, -e1.x };
00065 GLdouble pl1[4] = {-1.0, 0.0, 0.0, e2.x };
00066 GLdouble pl2[4] = {0.0, 1.0, 0.0, -e1.y };
00067 GLdouble pl3[4] = {0.0, -1.0, 0.0, e2.y };
00068 glClipPlane(GL_CLIP_PLANE0, pl0);
00069 glEnable(GL_CLIP_PLANE0);
00070 glClipPlane(GL_CLIP_PLANE1, pl1);
00071 glEnable(GL_CLIP_PLANE1);
00072 glClipPlane(GL_CLIP_PLANE2, pl2);
00073 glEnable(GL_CLIP_PLANE2);
00074 glClipPlane(GL_CLIP_PLANE3, pl3);
00075 glEnable(GL_CLIP_PLANE3);
00076
00077 map.m_foreground.BeginDraw();
00078 glBegin(GL_LINE_STRIP);
00079
00080 map.m_foreground.DrawPoint(e1);
00081 map.m_foreground.DrawPoint(tCoord(e2.x, e1.y));
00082 map.m_foreground.DrawPoint(e2);
00083 map.m_foreground.DrawPoint(tCoord(e1.x, e2.y));
00084 map.m_foreground.DrawPoint(e1);
00085 glEnd();
00086 map.m_background.SetGradientEdges(e1, e2);
00087 map.m_background.DrawRect(e1, e2);
00088 }
00089
00090 void Map::ClipperRect::End() {
00091 glDisable(GL_CLIP_PLANE0);
00092 glDisable(GL_CLIP_PLANE1);
00093 glDisable(GL_CLIP_PLANE2);
00094 glDisable(GL_CLIP_PLANE3);
00095 }
00096
00097 Map::ClipperCircle::ClipperCircle() {
00098 glGetIntegerv(GL_MAX_CLIP_PLANES, (GLint *)(&m_edges));
00099 if(m_edges > 20) {
00100 m_edges = 20;
00101 }
00102 }
00103
00104 void Map::ClipperCircle::Clip(int i, tCoord const &u, tCoord const &v) {
00105
00106
00107
00108
00109
00110
00111 if(u.x == v.x) {
00112 GLdouble factor = (u.y>v.y) ? 1 : -1;
00113 GLdouble pl[4] = {factor*1.0, 0.0, 0.0, -factor*v.x };
00114 glClipPlane(GL_CLIP_PLANE0+i, pl);
00115 glEnable(GL_CLIP_PLANE0+i);
00116 } else {
00117 GLdouble factor = (u.x<v.x) ? -1 : 1;
00118 GLdouble a = (v.y-u.y)/(v.x-u.x);
00119 GLdouble pl[4] = {
00120 factor*-a,
00121 factor,
00122 0.,
00123 factor*-(u.y-a*u.x)
00124 };
00125 glClipPlane(GL_CLIP_PLANE0+i, pl);
00126 glEnable(GL_CLIP_PLANE0+i);
00127 }
00128 }
00129 void Map::ClipperCircle::Begin(Map &map, tCoord const &e1, tCoord const &e2) {
00130 tCoord centre = .5*(e1+e2);
00131 tCoord ab = .5*(e2-e1);
00132 ab.x = fabs(ab.x); ab.y = fabs(ab.y);
00133 float stepsize=M_PI*2/m_edges;
00134
00135 map.m_background.BeginDraw();
00136 map.m_background.SetGradientEdges(centre - ab, centre + ab);
00137 glBegin(GL_POLYGON);
00138 for(int i = 0; i < m_edges; ++i) {
00139 float t = (i+1)*stepsize;
00140 tCoord next(centre.x+ab.x*cos(t), centre.y-ab.y*sin(t));
00141 map.m_background.DrawPoint(next);
00142 }
00143 glEnd();
00144 glDisable(GL_TEXTURE_2D);
00145 tCoord last = centre + tCoord(ab.x, 0);
00146 map.m_foreground.SetGradientEdges(centre - ab, centre + ab);
00147 map.m_foreground.BeginDraw();
00148 for(int i = 0; i < m_edges; ++i) {
00149 float t = (i+1)*stepsize;
00150 tCoord next(centre.x+ab.x*cos(t), centre.y-ab.y*sin(t));
00151 glBegin(GL_LINES);
00152 glVertex2f(next.x, next.y);
00153 glVertex2f(last.x, last.y);
00154 map.m_foreground.DrawPoint(next);
00155 map.m_foreground.DrawPoint(last);
00156 glEnd();
00157 Clip(i, last, next);
00158 last = next;
00159 }
00160 glDisable(GL_TEXTURE_2D);
00161 }
00162 void Map::ClipperCircle::End() {
00163 for(int i = 0; i < m_edges; ++i) {
00164 glDisable(GL_CLIP_PLANE0 + i);
00165 }
00166 }
00167
00168 bool Map::Process(tXmlParser::node cur) {
00169 if (
00170 WithCoordinates ::Process(cur) ||
00171 WithForeground ::Process(cur) ||
00172 WithBackground ::Process(cur))
00173 return true;
00174 if(cur.IsOfType("MapModes")) {
00175 int toggleKey;
00176 cur.GetProp("toggleKey", toggleKey);
00177 if(toggleKey > 0) {
00178 m_toggleKey = toggleKey;
00179 m_Cockpit->AddEventHandler(toggleKey, this);
00180 }
00181 for(cur = cur.GetFirstChild(); cur; ++cur) {
00182 if(cur.IsOfType("MapMode")) {
00183 m_modes.push_back(Mode(cur));
00184 if(m_modes.size() == 1) {
00185 Apply(m_modes[0]);
00186 }
00187 }
00188 }
00189 return true;
00190 }
00191 DisplayError(cur);
00192 return false;
00193 }
00194 Map::Mode::Mode(tXmlParser::node cur) {
00195 cur.GetProp("zoomFactor", m_zoom);
00196 tString mode = cur.GetProp("mode");
00197 if(mode == "closestZone") m_mode = MODE_ZONE;
00198 else if(mode == "cycle") m_mode = MODE_CYCLE;
00199 else m_mode = MODE_STD;
00200
00201 tString rotation = cur.GetProp("rotation");
00202 if(rotation == "fixed") m_rotation = ROTATION_FIXED;
00203 else if(rotation == "cycle") m_rotation = ROTATION_CYCLE;
00204 else if(rotation == "camera") m_rotation = ROTATION_CAMERA;
00205 else m_rotation = ROTATION_SPAWN;
00206
00207 tString clipper = cur.GetProp("clipMode");
00208 if(clipper == "ellipse") {
00209 m_clipper = ClipperCircle::create;
00210 } else {
00211 m_clipper = ClipperRect::create;
00212 }
00213 }
00214 void Map::Apply(Mode const &mode) {
00215 m_mode = mode.m_mode;
00216 m_rotation = mode.m_rotation;
00217 m_zoom = mode.m_zoom;
00218 m_clipper.reset((*mode.m_clipper)());
00219 }
00220 void Map::HandleEvent(bool state, int id) {
00221 if(id == m_toggleKey) {
00222 if(state) {
00223 ToggleMode();
00224 }
00225 } else {
00226 Base::HandleEvent(state, id);
00227 }
00228 }
00229
00230 void Map::Render() {
00231
00232 if(stc_forbidHudMap) return;
00233 glMatrixMode(GL_PROJECTION);
00234 glLoadIdentity();
00235 glMatrixMode(GL_MODELVIEW);
00236 glLoadIdentity();
00237 glDisable(GL_TEXTURE_2D);
00238 glDisable(GL_LIGHTING);
00239 glDisable(GL_LINE_SMOOTH);
00240 glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST);
00241 DrawMap(true, true,
00242 5.5, 0.,
00243 m_position.x-m_size.x, m_position.y-m_size.y, 2.*m_size.x, 2.*m_size.y,
00244 sr_screenWidth*m_size.x, sr_screenWidth*m_size.y, .5, .5);
00245 }
00246 void Map::DrawMap(bool rimWalls, bool cycleWalls,
00247 double cycleSize, double border,
00248 double x, double y, double w, double h,
00249 double rw, double rh, double ix, double iy) {
00250 double pl_CurSpeed, min_dist2, dist2, rad, zoom = 1;
00251 tCoord pl_CurPos, rotate;
00252 cCockpit* cp = m_Cockpit;
00253 if(!rimWalls && !cycleWalls) return;
00254 const eRectangle &bounds = eWallRim::GetBounds();
00255 double lx = bounds.GetLow().x - border, hx = bounds.GetHigh().x + border;
00256 double ly = bounds.GetLow().y - border, hy = bounds.GetHigh().y + border;
00257 double mw = hx - lx, mh = hy - ly;
00258 double xpos, ypos, xscale, yscale;
00259 double xrat = (rw * mh) / (rh * mw);
00260 double yrat = (rh * mw) / (rw * mh);
00261
00262 if(xrat > yrat) {
00263 xscale = (w * rh) / (mh * rw);
00264 yscale = h / mh;
00265 } else {
00266 xscale = w / mw;
00267 yscale = (h * rw) / (mw * rh);
00268 }
00269 rotate.x = 1;
00270 rotate.y = 0;
00271
00272
00273 switch(m_rotation) {
00274 case ROTATION_SPAWN:
00275 if(!cp->GetFocusCycle()) { break; }
00276 rotate = cp->GetFocusCycle()->SpawnDirection().Turn(0,-1);
00277 break;
00278 case ROTATION_CYCLE:
00279 if(!cp->GetFocusCycle()) { break; }
00280 rotate = cp->GetFocusCycle()->Direction().Turn(0,-1);
00281 break;
00282 case ROTATION_CAMERA:
00283 {
00284 ePlayer const *player = cp->GetPlayer();
00285 if(!player) break;
00286 eCamera const *cam = player->cam;
00287 if(cam) {
00288 rotate = cam->CameraDir().Turn(0,-1);
00289 } else {
00290 rotate = tCoord(1, 0);
00291 }
00292 }
00293 break;
00294 default:
00295 rotate = tCoord(1, 0);
00296 break;
00297 }
00298
00299
00300 switch (m_mode) {
00301 case MODE_ZONE:
00302 if(!cp->GetFocusCycle()) { break; }
00303 pl_CurPos = cp->GetFocusCycle()->Position();
00304 min_dist2 = (mw*mw+mh*mh)*1000;
00305 rad = 0;
00306 for(std::deque<gZone *>::const_iterator i = sg_Zones.begin(); i != sg_Zones.end(); ++i) {
00307 tASSERT(*i);
00308 tCoord const &position = (*i)->GetPosition();
00309 const float radius = (*i)->GetRadius();
00310 dist2 = (position-pl_CurPos).Norm();
00311 if (dist2<min_dist2) {
00312 min_dist2 = dist2;
00313 m_centre = position;
00314 rad = radius;
00315 }
00316 }
00317 rad = (rad<15)?15:rad;
00318 zoom = (w>h)?h/(yscale*m_zoom*rad):w/(xscale*m_zoom*rad);
00319 zoom = (zoom<1)?1:zoom;
00320
00321 if (rad==0) {
00322 m_mode = MODE_CYCLE;
00323 } else {
00324 break;
00325 }
00326 case MODE_CYCLE:
00327 if(!cp->GetFocusCycle()) { break; }
00328 m_centre = cp->GetFocusCycle()->Position();
00329 pl_CurSpeed = cp->GetFocusCycle()->Speed();
00330 zoom = (w>h)?h/(yscale*m_zoom*pl_CurSpeed):w/(xscale*m_zoom*pl_CurSpeed);
00331 zoom = (zoom<1)?1:zoom;
00332 break;
00333 default :
00334 zoom = 1;
00335 m_centre.x = lx + mw / 2;
00336 m_centre.y = ly + mh / 2;
00337 break;
00338 }
00339 xscale *=zoom;
00340 yscale *=zoom;
00341 xpos = x - m_centre.x * xscale + w / 2;
00342 ypos = y - m_centre.y * yscale + h / 2;
00343 if(m_mode != MODE_STD) {
00344 m_clipper->Begin(*this, tCoord(x,y), tCoord(x+w, y+h));
00345 }
00346
00347 glPushMatrix();
00348 glTranslatef(xpos, ypos, 0);
00349 glScalef(xscale, yscale, 1);
00350
00351 GLfloat r[16] = {
00352 rotate.x, -rotate.y, 0, 0,
00353 rotate.y, rotate.x, 0, 0,
00354 0, 0, 1, 0,
00355 m_centre.x, m_centre.y, 0, 1};
00356 glMultMatrixf(r);
00357 glTranslatef(-m_centre.x,-m_centre.y,0);
00358 if(rimWalls)
00359 DrawRimWalls(se_rimWalls);
00360 if(cycleWalls) {
00361 DrawWalls(sg_netPlayerWallsGridded);
00362 DrawWalls(sg_netPlayerWalls);
00363 }
00364 DrawObjects(tCoord((cycleSize * w) / (rw * xscale), (cycleSize * h) / (rh * yscale)));
00365 glPopMatrix();
00366 if(m_mode != MODE_STD) {
00367 m_clipper->End();
00368 }
00369 }
00370
00371 void Map::DrawRimWalls( tList<eWallRim> &list ) {
00372 if(sr_alphaBlend && m_mode == MODE_STD) {
00373 const eRectangle &bounds = eWallRim::GetBounds();
00374 const tCoord dims = bounds.GetHigh() - bounds.GetLow();
00375 const float max = fmax(dims.x, dims.y);
00376 m_background.SetGradientEdges(bounds.GetLow(), tCoord(bounds.GetLow().x + max, bounds.GetLow().y + max));
00377 m_background.BeginDraw();
00378 glBegin(GL_POLYGON);
00379 for(std::vector<tCoord>::iterator iter = se_rimWallRubberBand.begin(); iter != se_rimWallRubberBand.end(); ++iter) {
00380 m_background.DrawPoint(*iter);
00381 }
00382 m_background.DrawPoint(se_rimWallRubberBand.front());
00383 glEnd();
00384 }
00385 glDisable(GL_TEXTURE_2D);
00386 glColor4f(1, 1, 1, .5);
00387 glBegin(GL_LINES);
00388 {
00389 for (int i=list.Len()-1; i >= 0; --i)
00390 {
00391 eWallRim *wall = list[i];
00392 eCoord begin = wall->EndPoint(0), end = wall->EndPoint(1);
00393 glVertex2f(begin.x, begin.y);
00394 glVertex2f(end.x, end.y);
00395 }
00396
00397
00398 }
00399 glEnd();
00400 }
00401
00402 void Map::DrawWalls(tList<gNetPlayerWall> &list) {
00403 unsigned i, len=list.Len();
00404 double currentTime = se_GameTime();
00405 bool limitedLength = gCycle::WallsLength() > 0;
00406 double wallsStayUpDelay = gCycle::WallsStayUpDelay();
00407 glBegin(GL_LINES);
00408 for(i=0; i<len; i++) {
00409 gNetPlayerWall *wall = list[i];
00410 gCycle *cycle = wall->Cycle();
00411 if(!cycle) continue;
00412 double wallsLength = cycle->ThisWallsLength();
00413 double alpha = 1;
00414 if(!cycle->Alive() && wallsStayUpDelay >= 0) {
00415 alpha -= 2 * (currentTime - cycle->DeathTime() - wallsStayUpDelay);
00416 if(alpha <= 0) continue;
00417 }
00418 glColor4f(cycle->color_.r, cycle->color_.g, cycle->color_.b, alpha);
00419 double cycleDist = cycle->GetDistance();
00420 double minDist = limitedLength && cycleDist > wallsLength ? cycleDist - wallsLength : 0;
00421 const eCoord &begPos = wall->EndPoint(0), &endPos = wall->EndPoint(1);
00422 tArray<gPlayerWallCoord> &coords = wall->Coords();
00423 double begDist = wall->BegPos();
00424 double lenDist = wall->EndPos() - begDist;
00425 unsigned j, numcoords = coords.Len();
00426 if(numcoords < 2) continue;
00427 bool prevDangerous = coords[0].IsDangerous;
00428 double prevDist = coords[0].Pos;
00429 if(prevDist < minDist) prevDist = minDist;
00430 prevDist = (prevDist - begDist) / lenDist;
00431 for(j=1; j<numcoords; j++) {
00432 bool curDangerous = coords[j].IsDangerous;
00433 double curDist = coords[j].Pos;
00434 if(curDist < minDist) curDist = minDist;
00435 curDist = (curDist - begDist) / lenDist;
00436 if(prevDangerous) {
00437 glVertex2f(begPos.x + prevDist * (endPos.x - begPos.x), begPos.y + prevDist * (endPos.y - begPos.y));
00438 glVertex2f(begPos.x + curDist * (endPos.x - begPos.x), begPos.y + curDist * (endPos.y - begPos.y));
00439 }
00440 prevDangerous = curDangerous;
00441 prevDist = curDist;
00442 }
00443 }
00444 glEnd();
00445 }
00446
00447 void Map::DrawObjects(tCoord scale) {
00448 tList<eGameObject> const &gameObjects = eGrid::CurrentGrid()->GameObjects();
00449 size_t len = gameObjects.Len();
00450 for(size_t i = 0; i < len; ++i) {
00451 eGameObject const *obj = gameObjects(i);
00452 tASSERT(obj);
00453 obj->Render2D(scale);
00454 }
00455 }
00456
00457 void Map::ToggleMode(void) {
00458 if(m_modes.empty()) return;
00459 m_currentMode = (m_currentMode+1) % m_modes.size();
00460 Apply(m_modes[m_currentMode]);
00461 }
00462
00463 Map::Map():
00464 m_mode(MODE_STD),
00465 m_zoom(3),
00466 m_rotation(ROTATION_SPAWN),
00467 m_toggleKey(0),
00468 m_clipper(new ClipperRect()),
00469 m_currentMode(0)
00470 {}
00471
00472 }
00473 #endif