grid.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software 
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00010 /*!****************************************************************************
00011  * \file    grid.cpp
00012  * \author  Philip Vorsilak, gorzuate@allacrost.org
00013  * \brief   Source file for editor's grid, used for the OpenGL map portion
00014  *          where tiles are painted, edited, etc.
00015  *****************************************************************************/
00016 
00017 #include <iostream>
00018 #include "grid.h"
00019 
00020 using namespace hoa_script;
00021 using namespace hoa_editor;
00022 using namespace hoa_video;
00023 using namespace std;
00024 
00025 namespace hoa_editor
00026 {
00027   LAYER_TYPE& operator++(LAYER_TYPE& value, int dummy) 
00028   {
00029     value = static_cast<LAYER_TYPE>(static_cast<int>(value) + 1);
00030     return value;
00031   }
00032 }
00033 
00034 Grid::Grid(QWidget* parent, const QString& name, int width, int height)
00035   : QGLWidget(parent, (const char*) name)
00036 { 
00037   _file_name = name;      // gives the map a name
00038 
00039   // Initial size
00040   _height = height;
00041   _width  = width;
00042   resize(_width * TILE_WIDTH, _height * TILE_HEIGHT);
00043 
00044   // Default properties
00045   _changed = false;       // map has not yet been modified
00046   _grid_on = true;        // grid lines default to on
00047   _ll_on = true;          // lower layer default to on
00048   _ml_on = false;         // middle layer default to off
00049   _ul_on = false;         // upper layer default to off
00050 
00051   // Initialize layers
00052   for (int i = 0; i < _width * _height; i++)
00053   {
00054     _lower_layer.push_back(-1);
00055     _middle_layer.push_back(-1);
00056     _upper_layer.push_back(-1);
00057   } // -1 is used for no tiles
00058   // -1 is used for no tiles
00059 
00060   // Create the video engine's singleton
00061   VideoManager = GameVideo::SingletonCreate();
00062 } // Grid constructor
00063 
00064 Grid::~Grid()
00065 {
00066   // FIXME
00067 //  VideoManager->DeleteImage();
00068   GameVideo::SingletonDestroy();
00069 } // Grid destructor
00070 
00071 
00072 
00073 // ********** Public functions **********
00074 
00075 void Grid::SetChanged(bool value)
00076 {
00077   _changed = value;
00078 } // SetChanged(...)
00079 
00080 void Grid::SetFileName(QString filename)
00081 {
00082   _file_name = filename;
00083 } // SetFileName(...)
00084 
00085 void Grid::SetHeight(int height)
00086 {
00087   _height = height;
00088   _changed = true;
00089 } // SetHeight(...)
00090 
00091 void Grid::SetWidth(int width)
00092 {
00093   _width = width;
00094   _changed = true;
00095 } // SetWidth(...)
00096 
00097 void Grid::SetLLOn(bool value)
00098 {
00099   _ll_on = value;
00100   updateGL();
00101 } // SetLLOn(...)
00102 
00103 void Grid::SetMLOn(bool value)
00104 {
00105   _ml_on = value;
00106   updateGL();
00107 } // SetMLOn(...)
00108 
00109 void Grid::SetULOn(bool value)
00110 {
00111   _ul_on = value;
00112   updateGL();
00113 } // SetULOn(...)
00114 
00115 void Grid::SetGridOn(bool value)
00116 {
00117   _grid_on = value;
00118   updateGL();
00119 } // SetGridOn(...)
00120 
00121 std::vector<int32>& Grid::GetLayer(LAYER_TYPE layer) 
00122 {
00123   switch(layer) {
00124     case LOWER_LAYER:
00125       return _lower_layer;
00126     case MIDDLE_LAYER:
00127       return _middle_layer;
00128     case UPPER_LAYER:
00129       return _upper_layer;
00130     case INVALID_LAYER:
00131       /* FALLTHRU */
00132     case TOTAL_LAYER:
00133       /* FALLTHRU */
00134     default:
00135       return _lower_layer;
00136   } // switch on the current layer
00137 } // GetLayer(...)
00138 
00139 void Grid::SetMusic(const QString& music_file) 
00140 {
00141   _music_file = music_file;
00142 } // SetMusic(...)
00143 
00144 const QString& Grid::GetMusic() const 
00145 {
00146   return _music_file;
00147 } // GetMusic()
00148 
00149 void Grid::LoadMap()
00150 {
00151   ReadScriptDescriptor read_data;
00152   vector<int32> vect;             // used to read in vectors from the file
00153 
00154   if (!read_data.OpenFile(std::string(_file_name.toAscii())))
00155     QMessageBox::warning(this, "Loading File...", QString("ERROR: could not open %1 for reading!").arg(_file_name));
00156 
00157   tileset_names.clear();
00158   tilesets.clear();
00159   _lower_layer.clear();
00160   _middle_layer.clear();
00161   _upper_layer.clear();
00162   
00163   _height = read_data.ReadInt("num_tile_rows");
00164   _width  = read_data.ReadInt("num_tile_cols");
00165   resize(_width * TILE_WIDTH, _height * TILE_HEIGHT);
00166 
00167   read_data.OpenTable("tileset_filenames");
00168   uint32 table_size = read_data.GetTableSize();
00169   for (uint32 i = 1; i <= table_size; i++)
00170     tileset_names.append(QString(read_data.ReadString(i).c_str()));
00171   read_data.CloseTable();
00172 
00173   // Loading the tileset images using LoadMultiImage is done in editor.cpp in FileOpen via
00174   // creation of the TilesetTable(s)
00175 
00176   read_data.OpenTable("lower_layer");
00177   for (int32 i = 0; i < _height; i++)
00178   {
00179     read_data.ReadIntVector(i, vect);
00180     for (vector<int32>::iterator it = vect.begin(); it != vect.end(); it++)
00181       _lower_layer.push_back(*it);
00182     vect.clear();
00183   } // iterate through the rows of the lower layer
00184   read_data.CloseTable();
00185 
00186   read_data.OpenTable("middle_layer");
00187   for (int32 i = 0; i < _height; i++)
00188   {
00189     read_data.ReadIntVector(i, vect);
00190     for (vector<int32>::iterator it = vect.begin(); it != vect.end(); it++)
00191       _middle_layer.push_back(*it);
00192     vect.clear();
00193   } // iterate through the rows of the lower layer
00194   read_data.CloseTable();
00195 
00196   read_data.OpenTable("upper_layer");
00197   for (int32 i = 0; i < _height; i++)
00198   {
00199     read_data.ReadIntVector(i, vect);
00200     for (vector<int32>::iterator it = vect.begin(); it != vect.end(); it++)
00201       _upper_layer.push_back(*it);
00202     vect.clear();
00203   } // iterate through the rows of the lower layer
00204   read_data.CloseTable();
00205   
00206   // The map_grid is 4x as big as the map: 2x in the width and 2x in the height. Starting
00207   // with row 0 (and doing the same thing for every row that is a multiple of 2), we take the first 2 entries,
00208   // bit-wise AND them, and put them into a temporary vector called walk_temp. We keep doing this for every 2
00209   // entries until the row is exhausted. walk_temp should now be the same length or size as the width of the map.
00210   //
00211   // Now we go on to the next row (and we do the same thing here for every other row, or rows that are not
00212   // multiples of 2. We do the same thing that we did for the multiples-of-2 rows, except now we bit-wise AND the
00213   // 2 entries with their corresponding entry in the walk_temp vector. We have now reconstructed the walkability
00214   // for each tile.
00215   /*read_data.ReadOpenTable("map_grid");
00216   uint32 walk_west;
00217   vector<uint32> walk_temp;
00218   vector<uint32>::iterator wit;
00219   for (int32 i = 0; i < _height * 2; i++)
00220   {
00221     read_data.ReadIntVector(i, vect);
00222     wit = walk_temp.begin();
00223     for (vector<int32>::iterator it = vect.begin(); it != vect.end(); it++)
00224     {
00225       walk_west = *it;
00226       it++;
00227       if (i % 2 == 0)
00228         walk_temp.push_back(walk_west & *it);
00229       else
00230       {
00231         indiv_walkable.push_back(*wit & walk_west & *it);
00232         wit++;
00233       } // remainder means entire tile has been read
00234     } // iterate through the row
00235     vect.clear();
00236     if (i % 2 != 0)
00237       walk_temp.clear();
00238   } // iterate through the rows of the walkability table
00239   read_data.ReadCloseTable();*/
00240 
00241   // Load music
00242   read_data.OpenTable("music_filenames");
00243   if (read_data.IsErrorDetected() == false)
00244   {
00245     int size = read_data.GetTableSize();
00246     if (size == 0)
00247       _music_file = "None";
00248     else
00249       _music_file = QString(read_data.ReadString(1).c_str());
00250     read_data.CloseTable();
00251   }
00252 
00253   _grid_on = true;        // grid lines default to on
00254   _ll_on   = true;        // lower layer default to on
00255   _ml_on   = true;        // middle layer default to off
00256   _ul_on   = true;        // upper layer default to off
00257   _changed = false;       // map has not been changed yet
00258 } // LoadMap()
00259 
00260 void Grid::SaveMap()
00261 {
00262   char buffer[5]; // used for converting an int to a string with sprintf
00263   int i;          // Lua table index / Loop counter variable
00264   vector<int32>::iterator it;  // used to iterate through the layers
00265   vector<int32> layer_row;     // one row of a layer
00266   WriteScriptDescriptor write_data;
00267   int tileset_index;
00268   int tile_index;
00269   
00270   if (write_data.OpenFile(std::string(_file_name.toAscii())) == false) {
00271     QMessageBox::warning(this, "Saving File...", QString("ERROR: could not open %1 for writing!").arg(_file_name));
00272     return;
00273   }
00274 
00275   write_data.WriteComment(std::string(_file_name.toAscii()));
00276   write_data.InsertNewLine();
00277 
00278   write_data.WriteComment("A reference to the C++ MapMode object that was created with this file");
00279   write_data.WriteLine("map = {}\n");
00280 
00281   write_data.WriteComment("The number of rows and columns of tiles that compose the map");
00282   write_data.WriteInt("num_tile_cols", _width);
00283   write_data.WriteInt("num_tile_rows", _height);
00284   write_data.InsertNewLine();
00285 
00286   write_data.WriteComment("The sound files used on this map.");
00287   write_data.BeginTable("sound_filenames");
00288   // TEMP: currently sound_filenames table is not populated with sounds
00289   write_data.EndTable();
00290   write_data.InsertNewLine();
00291 
00292   write_data.WriteComment("The music files used as background music on this map.");
00293   write_data.BeginTable("music_filenames");
00294   if (_music_file != "None")
00295     write_data.WriteString(1, std::string(_music_file.toAscii()));
00296   write_data.EndTable();
00297   write_data.InsertNewLine();
00298 
00299   write_data.WriteComment("The names of the tilesets used, with the path and file extension omitted");
00300   write_data.BeginTable("tileset_filenames");
00301   i = 0;
00302   for (QStringList::Iterator qit = tileset_names.begin(); qit != tileset_names.end(); ++qit)
00303   {
00304     i++;
00305     write_data.WriteString(i, (*qit).ascii());
00306   } // iterate through tileset_list writing each element
00307   write_data.EndTable();
00308   write_data.InsertNewLine();
00309 
00310   // Create vector of 0s.
00311   vector<int32> vect_0s(_width, 0);
00312 
00313   write_data.WriteComment("The map grid to indicate walkability. The size of the grid is 4x the size of the tile layer tables");
00314   write_data.WriteComment("Walkability status of tiles for 32 contexts. Zero indicates walkable. Valid range: [0:2^32-1]");
00315   write_data.BeginTable("map_grid");
00316   vector<int32> ll_vect;
00317   vector<int32> ml_vect;
00318   vector<int32> ul_vect;
00319   int row = 0;
00320   bool twice = false;
00321   while (row < _height)
00322   {
00323     for (int32 i = row * _width; i < row * _width + _width; i++)
00324     {
00325       // Get walkability for lower layer tile.
00326       tileset_index = _lower_layer[i] / 256;
00327       if (tileset_index == 0)
00328         tile_index = _lower_layer[i];
00329       else  // Don't divide by 0
00330         tile_index = _lower_layer[i] % (tileset_index * 256);
00331       if (tile_index == -1)
00332       {
00333         ll_vect.push_back(0);
00334         ll_vect.push_back(0);
00335         ll_vect.push_back(0);
00336         ll_vect.push_back(0);
00337       }
00338       else
00339         ll_vect = tilesets[tileset_index]->walkability[tile_index];
00340 
00341       // Get walkability for middle layer tile.
00342       tileset_index = _middle_layer[i] / 256;
00343       if (tileset_index == 0)
00344         tile_index = _middle_layer[i];
00345       else  // Don't divide by 0
00346         tile_index = _middle_layer[i] % (tileset_index * 256);
00347       if (tile_index == -1)
00348       {
00349         ml_vect.push_back(0);
00350         ml_vect.push_back(0);
00351         ml_vect.push_back(0);
00352         ml_vect.push_back(0);
00353       }
00354       else
00355         ml_vect = tilesets[tileset_index]->walkability[tile_index];
00356 
00357       // Get walkability for upper layer tile.
00358       tileset_index = _upper_layer[i] / 256;
00359       if (tileset_index == 0)
00360         tile_index = _upper_layer[i];
00361       else  // Don't divide by 0
00362         tile_index = _upper_layer[i] % (tileset_index * 256);
00363       if (tile_index == -1)
00364       {
00365         ul_vect.push_back(0);
00366         ul_vect.push_back(0);
00367         ul_vect.push_back(0);
00368         ul_vect.push_back(0);
00369       }
00370       else
00371         ul_vect = tilesets[tileset_index]->walkability[tile_index];
00372 
00373       if (twice)
00374       {
00375         layer_row.push_back(ll_vect[2] | ml_vect[2] | ul_vect[2]);  // SW corner
00376         layer_row.push_back(ll_vect[3] | ml_vect[3] | ul_vect[3]);  // SE corner
00377       }
00378       else
00379       {
00380         layer_row.push_back(ll_vect[0] | ml_vect[0] | ul_vect[0]);  // NW corner
00381         layer_row.push_back(ll_vect[1] | ml_vect[1] | ul_vect[1]);  // NE corner
00382       }
00383       
00384       ll_vect.clear();
00385       ml_vect.clear();
00386       ul_vect.clear();
00387     } // iterate through the columns of the layers
00388 
00389     if (twice)
00390       sprintf(buffer, "%d", row*2+1);
00391     else
00392       sprintf(buffer, "%d", row*2);
00393     write_data.WriteIntVector(buffer, layer_row);
00394     layer_row.clear();
00395     if (twice)
00396     {
00397       twice = false;
00398       row++;
00399     }
00400     else
00401       twice = true;
00402   } // iterate through the rows of the layers
00403   write_data.EndTable();
00404   write_data.InsertNewLine();
00405 
00406   write_data.WriteComment("The lower tile layer. The numbers are indeces to the tile_mappings table.");
00407   write_data.BeginTable("lower_layer");
00408   it = _lower_layer.begin();
00409   for (int row = 0; row < _height; row++)
00410   {
00411     for (int col = 0; col < _width; col++)
00412     {
00413       layer_row.push_back(*it);
00414       it++;
00415     } // iterate through the columns of the lower layer
00416     sprintf(buffer, "%d", row);
00417     write_data.WriteIntVector(buffer, layer_row);
00418     layer_row.clear();
00419   } // iterate through the rows of the lower layer
00420   write_data.EndTable();
00421   write_data.InsertNewLine();
00422 
00423   write_data.WriteComment("The middle tile layer. The numbers are indeces to the tile_mappings table.");
00424   write_data.BeginTable("middle_layer");
00425   it = _middle_layer.begin();
00426   for (int row = 0; row < _height; row++)
00427   {
00428     for (int col = 0; col < _width; col++)
00429     {
00430       layer_row.push_back(*it);
00431       it++;
00432     } // iterate through the columns of the middle layer
00433     sprintf(buffer, "%d", row);
00434     write_data.WriteIntVector(buffer, layer_row);
00435     layer_row.clear();
00436   } // iterate through the rows of the middle layer
00437   write_data.EndTable();
00438   write_data.InsertNewLine();
00439 
00440   write_data.WriteComment("The upper tile layer. The numbers are indeces to the tile_mappings table.");
00441   write_data.BeginTable("upper_layer");
00442   it = _upper_layer.begin();
00443   for (int row = 0; row < _height; row++)
00444   {
00445     for (int col = 0; col < _width; col++)
00446     {
00447       layer_row.push_back(*it);
00448       it++;
00449     } // iterate through the columns of the upper layer
00450     sprintf(buffer, "%d", row);
00451     write_data.WriteIntVector(buffer, layer_row);
00452     layer_row.clear();
00453   } // iterate through the rows of the upper layer
00454   write_data.EndTable();
00455   write_data.InsertNewLine();
00456 
00457   write_data.CloseFile();
00458 
00459   _changed = false;
00460 } // SaveMap()
00461 
00462 
00463 
00464 // ********** Protected slots **********
00465 
00466 void Grid::initializeGL()
00467 {
00468   VideoManager->SetTarget(VIDEO_TARGET_QT_WIDGET);
00469   VideoManager->SingletonInitialize();
00470   VideoManager->ToggleFPS();
00471 } // initializeGL()
00472 
00473 void Grid::paintGL()
00474 {
00475   int32 col;                       // tile array loop index
00476   vector<int32>::iterator it;      // used to iterate through tile arrays
00477   int tileset_index;               // index into the tileset_names vector
00478   int tile_index;                  // ranges from 0-255
00479 
00480   // Setup drawing parameters
00481   VideoManager->SetCoordSys(0.0f, VideoManager->GetWidth() / TILE_WIDTH,
00482     VideoManager->GetHeight() / TILE_HEIGHT, 0.0f);
00483   VideoManager->SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_TOP, VIDEO_BLEND, 0);
00484   VideoManager->Clear(Color::black);
00485 
00486   // Draw lower layer
00487   if (_ll_on)
00488   {
00489     VideoManager->Move(0.0f, 0.0f);
00490     col = 0;
00491     for (it = _lower_layer.begin(); it != _lower_layer.end(); it++)
00492     {
00493       if (*it != -1)
00494       {
00495         tileset_index = *it / 256;
00496         if (tileset_index == 0)
00497           tile_index = *it;
00498         else  // Don't divide by 0
00499           tile_index = *it % (tileset_index * 256);
00500         VideoManager->DrawImage(tilesets[tileset_index]->tiles[tile_index]);
00501       } // a tile exists to draw
00502       col = ++col % _width;
00503       if (col == 0)
00504         VideoManager->MoveRelative(-_width + 1, 1.0f);
00505       else
00506         VideoManager->MoveRelative(1.0f, 0.0f);
00507     } // iterate through lower layer
00508   } // lower layer must be viewable
00509 
00510   // Draw middle layer
00511   if (_ml_on)
00512   {
00513     VideoManager->Move(0.0f, 0.0f);
00514     col = 0;
00515     for (it = _middle_layer.begin(); it != _middle_layer.end(); it++)
00516     {
00517       if (*it != -1)
00518       {
00519         tileset_index = *it / 256;
00520         if (tileset_index == 0)
00521           tile_index = *it;
00522         else  // Don't divide by 0
00523           tile_index = *it % (tileset_index * 256);
00524         VideoManager->DrawImage(tilesets[tileset_index]->tiles[tile_index]);
00525       } // a tile exists to draw
00526       col = ++col % _width;
00527       if (col == 0)
00528         VideoManager->MoveRelative(-_width + 1, 1.0f);
00529       else
00530         VideoManager->MoveRelative(1.0f, 0.0f);
00531     } // iterate through middle layer
00532   } // middle layer must be viewable
00533 
00534   // Draw upper layer
00535   if (_ul_on)
00536   {
00537     VideoManager->Move(0.0f, 0.0f);
00538     col = 0;
00539     for (it = _upper_layer.begin(); it != _upper_layer.end(); it++)
00540     {
00541       if (*it != -1)
00542       {
00543         tileset_index = *it / 256;
00544         if (tileset_index == 0)
00545           tile_index = *it;
00546         else  // Don't divide by 0
00547           tile_index = *it % (tileset_index * 256);
00548         VideoManager->DrawImage(tilesets[tileset_index]->tiles[tile_index]);
00549       } // a tile exists to draw
00550       col = ++col % _width;
00551       if (col == 0)
00552         VideoManager->MoveRelative(-_width + 1, 1.0f);
00553       else
00554         VideoManager->MoveRelative(1.0f, 0.0f);
00555     } // iterate through upper layer
00556   } // upper layer must be viewable
00557 
00558   // If grid is toggled on, draw it
00559   if (_grid_on)
00560     VideoManager->DrawGrid(0.0f, 0.0f, 1.0f, 1.0f, Color::black);
00561 } // paintGL()
00562 
00563 void Grid::resizeGL(int w, int h)
00564 {
00565   VideoManager->SetResolution(w, h);
00566   VideoManager->ApplySettings();
00567 } // resizeGL(...)

Generated on Fri Jul 6 23:11:15 2007 for Hero of Allacrost by  doxygen 1.5.1