GLWPlanView.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         // Send messages about lines that have been drawn once every
00092         // 2 seconds
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         // Simulate all points
00115         simulateLine(localPoints_); // Local
00116         std::list<PlayerDrawnInfo>::iterator playeritor; // Remote
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         // Draw the square of land
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         // Get camera positions
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 *> &currentTanks =
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 }

Generated on Mon Feb 16 15:14:45 2009 for Scorched3D by  doxygen 1.5.3