00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <GLW/GLWPlanView.h>
00022 #include <GLW/GLWTranslate.h>
00023 #include <GLEXT/GLState.h>
00024 #include <GLEXT/GLViewPort.h>
00025 #include <image/ImageFactory.h>
00026 #include <tankgraph/TargetRendererImplTank.h>
00027 #include <client/ScorchedClient.h>
00028 #include <client/ClientState.h>
00029 #include <graph/MainCamera.h>
00030 #include <client/ClientLinesHandler.h>
00031 #include <landscape/Landscape.h>
00032 #include <landscape/LandscapePoints.h>
00033 #include <landscapemap/LandscapeMaps.h>
00034 #include <tank/TankContainer.h>
00035 #include <tank/TankState.h>
00036 #include <tank/TankPosition.h>
00037 #include <common/Vector.h>
00038 #include <common/Defines.h>
00039 #include <common/Logger.h>
00040 #include <common/OptionsTransient.h>
00041 #include <common/ToolTipResource.h>
00042 #include <coms/ComsMessageSender.h>
00043 #include <coms/ComsLinesMessage.h>
00044 #include <graph/OptionsDisplay.h>
00045 #include <lang/LangResource.h>
00046 #include <math.h>
00047
00048 REGISTER_CLASS_SOURCE(GLWPlanView);
00049
00050 static const float degToRad = 3.14f / 180.0f;
00051 static const float maxAnimationTime = 2.0f;
00052
00053 GLWPlanView::GLWPlanView(float x, float y, float w, float h) :
00054 GLWidget(x, y, w, h),
00055 animationTime_(0.0f), flashTime_(0.0f), totalTime_(0.0f), pointTime_(0.0f),
00056 flash_(true), dragging_(false), firstTime_(true),
00057 planColor_(1.0f)
00058 {
00059 setToolTip(new ToolTipResource(ToolTip::ToolTipHelp,
00060 "PLAN_VIEW", "Plan View",
00061 "PLAN_VIEW_TOOLTIP", "Shows the position of the the tanks\n"
00062 "on a overhead map of the island.\n"
00063 "Flashing tanks are still to make a move.\n"
00064 "Clicking on the plan will move the camera\n"
00065 "to look at that point."));
00066 }
00067
00068 GLWPlanView::~GLWPlanView()
00069 {
00070 }
00071
00072 void GLWPlanView::simulate(float frameTime)
00073 {
00074 planColor_ += frameTime * 0.2f;
00075 if (planColor_ > 1.0f) planColor_ = 1.0f;
00076
00077 totalTime_ += frameTime;
00078 flashTime_ += frameTime;
00079 if (flashTime_ > 0.3f)
00080 {
00081 flashTime_ = 0.0f;
00082 flash_ = !flash_;
00083 }
00084
00085 animationTime_ += frameTime;
00086 if (animationTime_ > maxAnimationTime)
00087 {
00088 animationTime_ = 0.0f;
00089 }
00090
00091
00092
00093 pointTime_ += frameTime;
00094 if (pointTime_ > 2.0f)
00095 {
00096 pointTime_ = 0.0f;
00097
00098 if (!sendPoints.empty())
00099 {
00100 Vector last = sendPoints.back();
00101 last[2] = 0.0f;
00102
00103 ComsLinesMessage message(
00104 ScorchedClient::instance()->getTankContainer().getCurrentPlayerId());
00105 message.getLines() = sendPoints;
00106 if (dragging_) message.getLines().push_back(Vector::getNullVector());
00107 sendPoints.clear();
00108 ComsMessageSender::sendToServer(message);
00109
00110 if (dragging_) sendPoints.push_back(last);
00111 }
00112 }
00113
00114
00115 simulateLine(localPoints_);
00116 std::list<PlayerDrawnInfo>::iterator playeritor;
00117 for (playeritor = dragPoints_.begin();
00118 playeritor != dragPoints_.end();
00119 )
00120 {
00121 PlayerDrawnInfo &info = (*playeritor);
00122 std::list<Vector>::iterator recieveitor;
00123 for (recieveitor = info.recievepoints.begin();
00124 recieveitor != info.recievepoints.end();
00125 recieveitor++)
00126 {
00127 Vector &v = (*recieveitor);
00128 if (v[2] > 3.0f) v[2] = 3.0f;
00129 v[2] -= frameTime;
00130 }
00131
00132 if (!simulateLine(info))
00133 {
00134 playeritor = dragPoints_.erase(playeritor);
00135 }
00136 else
00137 {
00138 playeritor++;
00139 }
00140 }
00141 }
00142
00143 void GLWPlanView::draw()
00144 {
00145 landscapeWidth_ = (float) ScorchedClient::instance()->
00146 getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00147 landscapeHeight_ = (float) ScorchedClient::instance()->
00148 getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00149 arenaX_ = (float) ScorchedClient::instance()->
00150 getLandscapeMaps().getGroundMaps().getArenaX();
00151 arenaY_ = (float) ScorchedClient::instance()->
00152 getLandscapeMaps().getGroundMaps().getArenaY();
00153 arenaWidth_ = (float) ScorchedClient::instance()->
00154 getLandscapeMaps().getGroundMaps().getArenaWidth();
00155 arenaHeight_ = (float) ScorchedClient::instance()->
00156 getLandscapeMaps().getGroundMaps().getArenaHeight();
00157
00158 if (firstTime_)
00159 {
00160 firstTime_ = false;
00161 if (!OptionsDisplay::instance()->getNoPlanDraw())
00162 {
00163 ClientLinesHandler::instance()->registerCallback(this);
00164 }
00165 }
00166
00167 GLWidget::draw();
00168 drawMap();
00169 }
00170
00171 void GLWPlanView::drawMap()
00172 {
00173 GLState currentState(GLState::DEPTH_OFF | GLState::BLEND_ON | GLState::TEXTURE_ON);
00174
00175 float maxWidth = MAX(arenaWidth_, arenaHeight_);
00176
00177 static bool createdTexture = false;
00178 if (!createdTexture)
00179 {
00180 createdTexture = true;
00181 ImageHandle logoMap = ImageFactory::loadAlphaImageHandle(
00182 S3D::getDataFile("data/windows/arrow_s.png"));
00183 arrowTex_.create(logoMap);
00184
00185 ImageHandle circleTank = ImageFactory::loadImageHandle(
00186 S3D::getDataFile("data/textures/circle.bmp"),
00187 S3D::getDataFile("data/textures/circlem.bmp"),
00188 true);
00189 ImageHandle circleSmall = ImageFactory::loadImageHandle(
00190 S3D::getDataFile("data/textures/circlew.bmp"),
00191 S3D::getDataFile("data/textures/circlem.bmp"),
00192 true);
00193 tankTex_.create(circleTank);
00194 circleTex_.create(circleSmall);
00195 }
00196
00197 glPushMatrix();
00198 glTranslatef(x_ + 10.0f, y_ + 10.0f, 0.0f);
00199 glScalef((w_ - 20.0f) / maxWidth, (h_ - 20.0f) / maxWidth, 1.0f);
00200 glTranslatef((maxWidth - arenaWidth_) / 2.0f - arenaX_,
00201 (maxWidth - arenaHeight_) / 2.0f - arenaY_, 0.0f);
00202
00203 drawTexture();
00204 drawTanks();
00205 drawBuoys();
00206 drawCameraPointer();
00207 glPopMatrix();
00208
00209 drawLines();
00210 }
00211
00212 void GLWPlanView::drawLines()
00213 {
00214 if (localPoints_.points.empty() &&
00215 dragPoints_.empty()) return;
00216
00217 GLState currentState2(GLState::TEXTURE_OFF);
00218 glPushMatrix();
00219 glTranslatef(x_ + 2.0f, y_ + 2.0f, 0.0f);
00220 glScalef(w_ - 4.0f, h_ - 4.0f, 1.0f);
00221
00222 glLineWidth(2.0f);
00223 if (!localPoints_.points.empty())
00224 {
00225 localPoints_.playerId = ScorchedClient::instance()->
00226 getTankContainer().getCurrentPlayerId();
00227 drawLine(localPoints_);
00228 }
00229
00230 if (!dragPoints_.empty())
00231 {
00232 std::list<PlayerDrawnInfo>::iterator playeritor;
00233 for (playeritor = dragPoints_.begin();
00234 playeritor != dragPoints_.end();
00235 playeritor++)
00236 {
00237 PlayerDrawnInfo &info = (*playeritor);
00238 drawLine(info);
00239 }
00240 }
00241 glLineWidth(1.0f);
00242
00243 glPopMatrix();
00244 }
00245
00246 bool GLWPlanView::simulateLine(PlayerDrawnInfo &info)
00247 {
00248 while (!info.recievepoints.empty())
00249 {
00250 Vector &first = info.recievepoints.front();
00251 if (first[2] > 0.0f) break;
00252 first[2] = totalTime_;
00253 info.points.push_back(first);
00254 info.recievepoints.pop_front();
00255 }
00256
00257 while (!info.points.empty())
00258 {
00259 Vector &first = info.points.front();
00260 float time = totalTime_ - first[2];
00261 if (time < 3.0f) break;
00262 info.points.pop_front();
00263 }
00264
00265 return !(info.points.empty() && info.recievepoints.empty());
00266 }
00267
00268 void GLWPlanView::drawLine(PlayerDrawnInfo &info)
00269 {
00270 Tank *current =
00271 ScorchedClient::instance()->getTankContainer().getTankById(
00272 info.playerId);
00273 if (!current)
00274 {
00275 info.points.clear();
00276 info.recievepoints.clear();
00277 return;
00278 }
00279
00280 if (info.points.empty()) return;
00281
00282 glBegin(GL_LINE_STRIP);
00283 std::list<Vector>::iterator itor;
00284 for (itor = info.points.begin();
00285 itor != info.points.end();
00286 itor++)
00287 {
00288 Vector &v = (*itor);
00289
00290 if (v[0] == 0.0f && v[1] == 0.0f)
00291 {
00292 glEnd();
00293 glBegin(GL_LINE_STRIP);
00294 }
00295 else
00296 {
00297 if (v[0] >= 0.0f && v[1] >= 0.0f &&
00298 v[0] <= 1.0f && v[1] <= 1.0f)
00299 {
00300 float time = totalTime_ - v[2];
00301 time = 1.0f - (time / 3.0f);
00302 glColor4f(
00303 current->getColor()[0],
00304 current->getColor()[1],
00305 current->getColor()[2],
00306 time);
00307 glVertex2f(v[0], v[1]);
00308 }
00309 }
00310 }
00311 glEnd();
00312 }
00313
00314 void GLWPlanView::drawTexture()
00315 {
00316 float leftScale = (arenaX_) / landscapeWidth_;
00317 float rightScale = (arenaX_ + arenaWidth_) / landscapeWidth_;
00318 float bottomScale = (arenaY_) / landscapeHeight_;
00319 float topScale = (arenaY_ + arenaHeight_) / landscapeHeight_;
00320
00321
00322 glColor3f(planColor_, planColor_, planColor_);
00323 Landscape::instance()->getPlanATexture().draw(true);
00324 glBegin(GL_QUADS);
00325 glTexCoord2f(rightScale, bottomScale);
00326 glVertex2f(arenaX_ + arenaWidth_, arenaY_);
00327 glTexCoord2f(rightScale, topScale);
00328 glVertex2f(arenaX_ + arenaWidth_, arenaY_ + arenaHeight_);
00329 glTexCoord2f(leftScale, topScale);
00330 glVertex2f(arenaX_, arenaY_ + arenaHeight_);
00331 glTexCoord2f(leftScale, bottomScale);
00332 glVertex2f(arenaX_, arenaY_);
00333 glEnd();
00334 }
00335
00336 void GLWPlanView::drawCameraPointer()
00337 {
00338 float maxWidth = MAX(arenaWidth_, arenaHeight_);
00339 float width = maxWidth / w_ * 10.0f;
00340 float height = maxWidth / h_ * 10.0f;
00341
00342 arrowTex_.draw();
00343
00344
00345 Vector currentPos = MainCamera::instance()->getCamera().getCurrentPos();
00346 Vector lookAt = MainCamera::instance()->getCamera().getLookAt();
00347 Vector direction = (currentPos - lookAt).Normalize2D();
00348 Vector directionPerp = direction.get2DPerp().Normalize2D();
00349
00350 direction[0] *= width;
00351 direction[1] *= height;
00352 directionPerp[0] *= width;
00353 directionPerp[1] *= height;
00354
00355 glColor4f(1.0f, 1.0f, 1.0f, 0.8f);
00356 glPushMatrix();
00357 glTranslatef(lookAt[0] + direction[0], lookAt[1] + direction[1], 0.0f);
00358 glBegin(GL_QUADS);
00359 glTexCoord2f(1.0f, 0.0f);
00360 glVertex3fv(-direction - directionPerp);
00361 glTexCoord2f(0.0f, 0.0f);
00362 glVertex3fv(-direction + directionPerp);
00363 glTexCoord2f(0.0f, 1.0f);
00364 glVertex3fv(direction + directionPerp);
00365 glTexCoord2f(1.0f, 1.0f);
00366 glVertex3fv(direction - directionPerp);
00367 glEnd();
00368 glPopMatrix();
00369 }
00370
00371 static void drawQuad(float x, float y, float w, float h)
00372 {
00373 glTexCoord2f(0.0f, 1.0f);
00374 glVertex2f(x + w, y + h);
00375 glTexCoord2f(0.0f, 0.0f);
00376 glVertex2f(x - w, y + h);
00377 glTexCoord2f(1.0f, 0.0f);
00378 glVertex2f(x - w, y - h);
00379 glTexCoord2f(1.0f, 1.0f);
00380 glVertex2f(x + w, y - h);
00381 }
00382
00383 void GLWPlanView::drawBuoys()
00384 {
00385 if (ScorchedClient::instance()->getOptionsTransient().getWallType() ==
00386 OptionsTransient::wallNone) return;
00387
00388 Vector &wallColor = ScorchedClient::instance()->getOptionsTransient().getWallColor();
00389 glColor3fv(wallColor);
00390
00391 std::vector<Vector> &points = Landscape::instance()->getPoints().getPoints();
00392 circleTex_.draw();
00393 glBegin(GL_QUADS);
00394 for (int i=0; i<(int) points.size(); i++)
00395 {
00396 drawQuad(points[i][0], points[i][1], 6.0f, 6.0f);
00397 }
00398 glEnd();
00399 }
00400 void GLWPlanView::drawTanks()
00401 {
00402 float maxWidth = MAX(arenaWidth_, arenaHeight_);
00403
00404 std::map<unsigned int, Tank *> ¤tTanks =
00405 ScorchedClient::instance()->getTankContainer().getPlayingTanks();
00406 if (currentTanks.empty()) return;
00407
00408 Vector position;
00409
00410 tankTex_.draw();
00411 glBegin(GL_QUADS);
00412
00413 std::map<unsigned int, Tank *>::iterator itor;
00414 for (itor = currentTanks.begin();
00415 itor != currentTanks.end();
00416 itor++)
00417 {
00418 Tank *tank = (*itor).second;
00419 if (tank->getState().getState() == TankState::sNormal &&
00420 !tank->getState().getSpectator())
00421 {
00422 tank->getPosition().getTankPosition().asVector(position);
00423
00424 if ((flash_ && tank->getState().getReadyState() == TankState::SNotReady) ||
00425 tank->getState().getReadyState() == TankState::sReady)
00426 {
00427 glColor3fv(tank->getColor());
00428 drawQuad(position[0], position[1], 8.0f, 8.0f);
00429 }
00430
00431 TargetRendererImplTank *renderer = (TargetRendererImplTank *)
00432 tank->getRenderer();
00433 if (renderer)
00434 {
00435 GLWToolTip::instance()->addToolTip(&renderer->getTips()->tankTip,
00436 GLWTranslate::getPosX() + x_ + 10.0f +
00437 (position[0] - arenaX_ + (maxWidth - arenaWidth_)/2.0f) / maxWidth * (w_ - 20.0f) - 4.0f,
00438 GLWTranslate::getPosY() + y_ + 10.0f +
00439 (position[1] - arenaY_ + (maxWidth - arenaHeight_)/2.0f) / maxWidth * (h_ - 20.0f) - 4.0f,
00440 8.0f, 8.0f);
00441 }
00442 }
00443 }
00444 glEnd();
00445 }
00446
00447 void GLWPlanView::mouseDown(int button, float x, float y, bool &skipRest)
00448 {
00449 if (inBox(x, y, x_, y_, w_, h_))
00450 {
00451 skipRest = true;
00452
00453 if (button == GameState::MouseButtonLeft)
00454 {
00455 int arenaX = ScorchedClient::instance()->
00456 getLandscapeMaps().getGroundMaps().getArenaX();
00457 int arenaY = ScorchedClient::instance()->
00458 getLandscapeMaps().getGroundMaps().getArenaY();
00459 int arenaWidth = ScorchedClient::instance()->
00460 getLandscapeMaps().getGroundMaps().getArenaWidth();
00461 int arenaHeight = ScorchedClient::instance()->
00462 getLandscapeMaps().getGroundMaps().getArenaHeight();
00463
00464 float maxWidth = (float) MAX(arenaWidth, arenaHeight);
00465 float mapX = (((x - x_ - 10.0f) / (w_ - 20.0f)) * maxWidth) + arenaX_ -
00466 (maxWidth - arenaWidth_) / 2.0f;
00467 float mapY = (((y - y_ - 10.0f) / (h_ - 20.0f)) * maxWidth) + arenaY_ -
00468 (maxWidth - arenaHeight_) / 2.0f;
00469
00470 if (mapX > arenaX && mapY > arenaY &&
00471 mapX < arenaX + arenaWidth &&
00472 mapY < arenaY + arenaHeight)
00473 {
00474 Vector lookAt(mapX, mapY, ScorchedClient::instance()->
00475 getLandscapeMaps().getGroundMaps().getInterpHeight(
00476 fixed::fromFloat(mapX), fixed::fromFloat(mapY)).asFloat() + 5.0f);
00477 MainCamera::instance()->getTarget().setCameraType(TargetCamera::CamFree);
00478 MainCamera::instance()->getCamera().setLookAt(lookAt);
00479 }
00480 }
00481 else if (button == GameState::MouseButtonRight)
00482 {
00483 dragging_ = true;
00484
00485 dragLastX_ = x;
00486 dragLastY_ = y;
00487
00488 float mapX = ((x - x_) / w_);
00489 float mapY = ((y - y_) / h_);
00490 localPoints_.points.push_back(Vector(mapX, mapY, totalTime_));
00491 sendPoints.push_back(Vector(mapX, mapY, pointTime_));
00492 }
00493 }
00494 }
00495
00496 void GLWPlanView::mouseDrag(int button, float mx, float my, float x, float y, bool &skipRest)
00497 {
00498 if (dragging_)
00499 {
00500 skipRest = true;
00501 if (inBox(mx, my, x_, y_, w_, h_))
00502 {
00503 if (fabsf(mx - dragLastX_) > 5.0f ||
00504 fabsf(my - dragLastY_) > 5.0f)
00505 {
00506 dragLastX_ = mx;
00507 dragLastY_ = my;
00508
00509 float mapX = ((mx - x_) / w_);
00510 float mapY = ((my - y_) / h_);
00511 localPoints_.points.push_back(Vector(mapX, mapY, totalTime_));
00512 sendPoints.push_back(Vector(mapX, mapY, pointTime_));
00513 }
00514 }
00515 }
00516 }
00517
00518 void GLWPlanView::mouseUp(int button, float x, float y, bool &skipRest)
00519 {
00520 if (dragging_)
00521 {
00522 dragging_ = false;
00523 localPoints_.points.push_back(Vector::getNullVector());
00524 sendPoints.push_back(Vector::getNullVector());
00525 }
00526 }
00527
00528 void GLWPlanView::addRecievePoints(unsigned int playerId,
00529 std::list<Vector> &recievepoints)
00530 {
00531 PlayerDrawnInfo *foundInfo = 0;
00532 std::list<PlayerDrawnInfo>::iterator dragItor;
00533 for (dragItor = dragPoints_.begin();
00534 dragItor != dragPoints_.end();
00535 dragItor++)
00536 {
00537 PlayerDrawnInfo &info = (*dragItor);
00538 if (info.playerId == playerId)
00539 {
00540 foundInfo = &info;
00541 }
00542 }
00543 if (!foundInfo)
00544 {
00545 planColor_ = 0.2f;
00546
00547 dragPoints_.push_back(PlayerDrawnInfo());
00548 foundInfo = &dragPoints_.back();
00549 foundInfo->playerId = playerId;
00550 }
00551
00552 foundInfo->recievepoints.insert(foundInfo->recievepoints.end(),
00553 recievepoints.begin(), recievepoints.end());
00554 }