//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2003 // // This file is part of Scorched3D. // // Scorched3D is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Scorched3D is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include #include #include #include <3dsparse/ModelStore.h> #include #include #include #include #include static const float TankSquareSize = 60.0f; static const float TankHalfSquareSize = TankSquareSize / 2.0f; static const float TankPadding = 20.0f; static const float TankInfo = 165.0f; GLWTankViewer::GLWTankViewer(float x, float y, int numH, int numV) : GLWidget(x, y, TankSquareSize * numH + TankPadding, TankSquareSize * numV + TankPadding), scrollBar_(w_ - 12.0f, y + 2.0f, h_ - 4.0f, 0, 0, numV), infoWindow_(x + TankSquareSize * numH + TankPadding + 10.0f, y + TankSquareSize * numV + TankPadding - TankInfo - 35.0f, TankInfo, TankInfo, true), numH_(numH), numV_(numV), rot_(0.0f), selected_(0), rotXY_(0.0f), rotYZ_(0.0f), rotXYD_(1.0f), rotYZD_(1.0f), team_(0), catagoryChoice_(x + TankSquareSize * numH + TankPadding + 10.0f, y + TankSquareSize * numV + TankPadding - 25.0f, TankInfo) { std::set &catagories = ScorchedClient::instance()->getTankModels().getModelCatagories(); std::set::iterator catItor; for (catItor = catagories.begin(); catItor != catagories.end(); catItor++) { catagoryChoice_.addText((*catItor).c_str()); } catagoryChoice_.setHandler(this); catagoryChoice_.setCurrentPosition(0); select(0, 0, GLWSelectorEntry(catagoryChoice_.getCurrentText())); catagoryChoice_.setToolTip(new GLWTip("Model Catagory", "Displays the currently selected model catagory.\n" "To make models easier to locate\n" "tank models are grouped by catagory.")); infoWindow_.setToolTip(new GLWTip("Current Model", "Displays the currently selected tank model.\n" "This is the model this player will use in game.\n" "Choose a new model from the selection on the\n" "left.")); } GLWTankViewer::~GLWTankViewer() { } void GLWTankViewer::setTeam(int team) { team_ = team; // Save current model int scrollCurrent = scrollBar_.getCurrent(); TankModel *model = 0; if (selected_ >= 0 && selected_ < (int) models_.size()) { model = models_[selected_]; } // Show new team models select(0, 0, GLWSelectorEntry(catagoryChoice_.getCurrentText())); // Select old model scrollBar_.setCurrent(scrollCurrent); for (int i=0; i<(int)models_.size(); i++) { if (models_[i] == model) selected_ = i; } } void GLWTankViewer::select(unsigned int id, const int pos, GLWSelectorEntry value) { std::vector newmodels; std::vector &models = ScorchedClient::instance()->getTankModels().getModels(); std::vector::iterator modelItor; for (modelItor = models.begin(); modelItor != models.end(); modelItor++) { TankModel *tankModel = (*modelItor); if (tankModel->isOfCatagory(value.getText())) { // Check if this tank is allowed for this team if (!tankModel->isOfTeam(team_) || !tankModel->isOfAi(false)) { continue; } // Get the model file to determine if the file is too large if (OptionsDisplay::instance()->getTankDetail() != 2) { Model *model = ModelStore::instance()->loadModel( tankModel->getTankModelID()); if (strcmp(tankModel->getName(), "Random") != 0) { // Check if the model uses too many triangles int triangles = model->getNumberTriangles(); if (OptionsDisplay::instance()->getTankDetail() == 0) { if (triangles > 250) continue; } else if (OptionsDisplay::instance()->getTankDetail() == 1) { if (triangles > 500) continue; } } } newmodels.push_back(tankModel); } } setTankModels(newmodels); } void GLWTankViewer::setTankModels(std::vector &models) { models_.clear(); models_ = models; scrollBar_.setMax((int) (models_.size() / numH_) + 1); scrollBar_.setCurrent(0); selected_ = 0; // Sort the models bool sorted = false; while (!sorted) { sorted = true; for (int i=0; i<(int) models_.size()-1; i++) { TankModel *tmp = models_[i]; TankModel *test = models_[i+1]; if (test->lessThan(tmp)) { models_[i] = test; models_[i+1] = tmp; sorted = false; } } } // Move random model to the top std::vector::iterator itor; for (itor = models_.begin(); itor != models_.end(); itor++) { TankModel *model = (*itor); if (0==strcmp(model->getName(),"Random")) { models_.erase(itor); std::vector tmpVector; tmpVector.push_back(model); tmpVector.insert(tmpVector.end(), models_.begin(), models_.end()); models_ = tmpVector; break; } } } const char *GLWTankViewer::getModelName() { const char *name = "None"; if (selected_ >= 0 && selected_ < (int) models_.size()) { name = models_[selected_]->getName(); } return name; } void GLWTankViewer::simulate(float frameTime) { rot_ += frameTime * 45.0f; rotXY_ += frameTime * rotXYD_ * 5.0f; rotYZ_ += frameTime * rotYZD_ * 5.0f; if (rotXY_ < -45.0f || rotXY_ > 45.0f) { rotXYD_ *= -1.0f; } if (rotYZ_ < 0.0f || rotYZ_ > 45.0f) { rotYZD_ *= -1.0f; } scrollBar_.simulate(frameTime); } void GLWTankViewer::draw() { Vector4 sunPosition(-100.0f, 100.0f, 400.0f, 1.0f); Vector4 sunDiffuse(0.9f, 0.9f, 0.9f, 1.0f); Vector4 sunAmbient(0.4f, 0.4f, 0.4f, 1.0f); glLightfv(GL_LIGHT1, GL_AMBIENT, sunAmbient); glLightfv(GL_LIGHT1, GL_DIFFUSE, sunDiffuse); glBegin(GL_LINE_LOOP); drawShadedRoundBox(x_, y_, w_, h_, 6.0f, false); glEnd(); infoWindow_.draw(); scrollBar_.draw(); GLState depthState(GLState::DEPTH_ON); const float heightdiv = (h_ / float(numV_)); const float widthdiv = ((w_ - TankPadding - 10) / float(numH_)); int pos = 0; for (int posV=0; posV= 0) { float posX = x_ + widthdiv * posH + TankHalfSquareSize + 2.0f; float posY = y_ + heightdiv * posV + TankHalfSquareSize + 2.0f; bool currselected = (vectorPos == selected_); if (currselected) { glColor3f(0.4f, 0.4f, 0.6f); glBegin(GL_LINE_LOOP); float SelectSize = TankHalfSquareSize - 2.0f; glVertex2f(posX - SelectSize, posY - SelectSize); glVertex2f(posX + SelectSize, posY - SelectSize); glVertex2f(posX + SelectSize, posY + SelectSize); glVertex2f(posX - SelectSize, posY + SelectSize); glEnd(); } if (GLWToolTip::instance()->addToolTip(&toolTip_, GLWTranslate::getPosX() + posX - TankHalfSquareSize, GLWTranslate::getPosY() + posY - TankHalfSquareSize, TankSquareSize, TankSquareSize)) { TankType *type = ScorchedClient::instance()->getTankModels(). getTypeByName(models_[vectorPos]->getTypeName()); toolTip_.setText( models_[vectorPos]->getName(), type->getDescription()); } float scale = 22.0f / 60.0f * TankSquareSize; glPushMatrix(); glTranslatef(posX, posY - 5.0f, 0.0f); glLightfv(GL_LIGHT1, GL_POSITION, sunPosition); glRotatef(-45.0f, 1.0f, 0.0f, 0.0f); if (currselected) glRotatef(rot_, 0.0f, 0.0f, 1.0f); glScalef(scale, scale, scale); drawItem(vectorPos, currselected); glPopMatrix(); } } } if (selected_ >= 0 && selected_ < (int) models_.size()) { const float infoX = infoWindow_.getX() + (infoWindow_.getW() / 2.0f); const float infoY = infoWindow_.getY() + (infoWindow_.getH() / 2.0f) - 15.0f; glPushMatrix(); glTranslatef(infoX, infoY, 0.0f); glLightfv(GL_LIGHT1, GL_POSITION, sunPosition); drawCaption(selected_); glRotatef(-45.0f, 1.0f, 0.0f, 0.0f); glRotatef(rot_, 0.0f, 0.0f, 1.0f); glScalef(50.0f, 50.0f, 50.0f); drawItem(selected_, true); glPopMatrix(); } GLState depthStateOff(GLState::DEPTH_OFF); catagoryChoice_.draw(); } void GLWTankViewer::mouseDown(int button, float x, float y, bool &skipRest) { scrollBar_.mouseDown(button, x, y, skipRest); if (!skipRest) { catagoryChoice_.mouseDown(button, x, y, skipRest); if (!skipRest) { if (inBox(x, y, x_, y_, w_, h_)) { int posY = int((y - y_) / (h_ / numV_)); int posX = int((x - x_) / (w_ / numH_)); int vectorPos = posX + posY * numH_ + scrollBar_.getCurrent() * numH_; if (vectorPos < (int) models_.size() && vectorPos >= 0) { selected_ = vectorPos; } } } } } void GLWTankViewer::mouseDrag(int button, float mx, float my, float x, float y, bool &skipRest) { scrollBar_.mouseDrag(button, mx, my, x, y, skipRest); } void GLWTankViewer::mouseUp(int button, float x, float y, bool &skipRest) { scrollBar_.mouseUp(button, x, y, skipRest); } void GLWTankViewer::mouseWheel(float x, float y, float z, bool &skipRest) { if (inBox(x, y, x_, y_, w_, h_)) { skipRest = true; if (z < 0.0f) scrollBar_.setCurrent(scrollBar_.getCurrent() + 1); else scrollBar_.setCurrent(scrollBar_.getCurrent() - 1); } } void GLWTankViewer::drawCaption(int pos) { GLState state(GLState::DEPTH_OFF); Vector color(0.3f, 0.3f, 0.3f); GLWFont::instance()->getSmallPtFont()-> drawWidth(TankSquareSize * 2 + TankPadding, color, 10.0f, -70.0f, 75.0f, 0.0f, models_[pos]->getName()); GLWFont::instance()->getSmallPtFont()-> drawWidth(TankSquareSize * 2 + TankPadding, color, 10.0f, -70.0f, 63.0f, 0.0f, formatString("(%i Triangles)", models_[pos]->getNoTris())); } void GLWTankViewer::drawItem(int pos, bool selected) { // Tank Vector tankPos; if (selected) { models_[pos]->draw(false, 0.0f, tankPos, 0.0f, rotXY_, rotYZ_); } else { models_[pos]->draw(false, 0.0f, tankPos, 0.0f, 45.0f, 45.0f); } // Ground GLState state(GLState::TEXTURE_OFF); glColor3f(181.0f / 255.0f, 204.0f / 255.0f, 237.0f / 255.0f); glBegin(GL_QUADS); glVertex2f(1.0f, 1.0f); glVertex2f(-1.0f, 1.0f); glVertex2f(-1.0f, -1.0f); glVertex2f(1.0f, -1.0f); glEnd(); //Shadow /*{ glDepthMask(GL_FALSE); glPushMatrix(); glScalef(1.0f, 1.0f, 0.0f); models[pos]->draw(false, tankPos, 0.0f, rotXY_, rotYZ_); glPopMatrix(); glDepthMask(GL_TRUE); }*/ } void GLWTankViewer::selectModelByName(const char *name) { DIALOG_ASSERT(models_.size()); // Ensure that all models have been loaded //select(0, 0, "All"); // Select the appropriate model int currentSel = 0; std::vector::iterator itor; for (itor = models_.begin(); itor != models_.end(); itor++, currentSel ++) { TankModel *current = (*itor); if (0 == strcmp(current->getName(), name)) { selected_ = currentSel; return; } } }