chunkter.cc

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2001 The Exult Team
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #  include <config.h>
00027 #endif
00028 #include "chunkter.h"
00029 #include "gamewin.h"
00030 #ifdef INCL_OPENGL
00031 #include "glshape.h"
00032 #endif
00033 
00034 Chunk_terrain *Chunk_terrain::render_queue = 0;
00035 int Chunk_terrain::queue_size = 0;
00036 
00037 /*
00038  *  Insert at start of render queue.  It may already be there, but it's
00039  *  assumed that it's already tested as not being at the start.
00040  */
00041 
00042 void Chunk_terrain::insert_in_queue
00043   (
00044   )
00045   {
00046   if (render_queue_next)    // In queue already?
00047     {     // !!Assuming it's not at head!!
00048     render_queue_next->render_queue_prev = render_queue_prev;
00049     render_queue_prev->render_queue_next = render_queue_next;
00050     }
00051   else
00052     queue_size++;   // Adding, so increment count.
00053   if (!render_queue)    // First?
00054     render_queue_next = render_queue_prev = this;
00055   else
00056     {
00057     render_queue_next = render_queue;
00058     render_queue_prev = render_queue->render_queue_prev;
00059     render_queue_prev->render_queue_next = this;
00060     render_queue->render_queue_prev = this;
00061     }
00062   render_queue = this;
00063   }
00064 
00065 /*
00066  *  Remove from render queue.
00067  */
00068 
00069 void Chunk_terrain::remove_from_queue
00070   (
00071   )
00072   {
00073   if (!render_queue_next)
00074     return;     // Not in queue.
00075   queue_size--;
00076   if (render_queue_next == this)  // Only element?
00077     render_queue = 0;
00078   else
00079     {
00080     if (render_queue == this)
00081       render_queue = render_queue_next;
00082     render_queue_next->render_queue_prev = render_queue_prev;
00083     render_queue_prev->render_queue_next = render_queue_next;
00084     }
00085   render_queue_next = render_queue_prev = 0;
00086   }
00087 
00088 /*
00089  *  Paint a flat tile into our cached buffer.
00090  */
00091 
00092 inline void Chunk_terrain::paint_tile
00093   (
00094   int tilex, int tiley    // Tile within chunk.
00095   )
00096   {
00097   Shape_frame *shape = get_shape(tilex, tiley);
00098   if (shape && !shape->is_rle())    // Only do flat tiles.
00099     rendered_flats->copy8(shape->get_data(), 
00100       c_tilesize, c_tilesize, tilex*c_tilesize,
00101             tiley*c_tilesize);
00102   }
00103 
00104 /*
00105  *  Create list for a given chunk.
00106  */
00107 
00108 Chunk_terrain::Chunk_terrain
00109   (
00110   unsigned char *data   // Chunk data.
00111   ) : undo_shapes(0),
00112       rendered_flats(0), glflats(0), 
00113       num_clients(0), render_queue_next(0),
00114       render_queue_prev(0), modified(false)
00115   {
00116   for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++)
00117     for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++)
00118       {
00119       ShapeID id(data[0], (unsigned char) (data[1]&0x7f));
00120       shapes[16*tiley + tilex] = id;
00121       data += 2;
00122       }
00123   }
00124 
00125 /*
00126  *  Copy another.  The 'modified' flag is set to true.
00127  */
00128 
00129 Chunk_terrain::Chunk_terrain
00130   (
00131   const Chunk_terrain& c2
00132   ) : undo_shapes(0),
00133       rendered_flats(0), glflats(0),
00134       num_clients(0), render_queue_next(0),
00135       render_queue_prev(0), modified(true)
00136   {
00137   for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++)
00138     for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++)
00139       shapes[16*tiley + tilex] = c2.shapes[16*tiley + tilex];
00140   }
00141 
00142 /*
00143  *  Clean up.
00144  */
00145 
00146 Chunk_terrain::~Chunk_terrain
00147   (
00148   )
00149   {
00150   delete [] undo_shapes;
00151   delete rendered_flats;
00152 #ifdef HAVE_OPENGL
00153   delete glflats;
00154 #endif
00155   remove_from_queue();
00156   }
00157 
00158 
00159 /*
00160  *  Set tile's shape.
00161  *  NOTE:  Set's 'modified' flag.
00162  */
00163 
00164 void Chunk_terrain::set_flat
00165   (
00166   int tilex, int tiley,
00167   ShapeID id
00168   )
00169   {
00170   if (!undo_shapes)   // Create backup.
00171     {
00172     undo_shapes = new ShapeID[256];
00173     std::memcpy((char *) undo_shapes, (char *) &shapes[0],
00174               sizeof(shapes));
00175     }
00176   shapes[16*tiley + tilex] = id;
00177   modified = true;
00178   }
00179 
00180 /*
00181  *  Commit changes.
00182  *
00183  *  Output: True if this was edited, else false.
00184  */
00185 
00186 bool Chunk_terrain::commit_edits
00187   (
00188   )
00189   {
00190   if (!undo_shapes)
00191     return false;
00192   delete [] undo_shapes;
00193   undo_shapes = 0;
00194   render_flats();     // Update with new data.
00195   return true;
00196   }
00197 
00198 /*
00199  *  Undo changes.   Note:  We don't clear 'modified', since this could
00200  *  still have been moved to a different position.
00201  */
00202 
00203 void Chunk_terrain::abort_edits
00204   (
00205   )
00206   {
00207   if (undo_shapes)
00208     {
00209     std::memcpy((char *) &shapes[0], (char *) undo_shapes,
00210               sizeof(shapes));
00211     delete [] undo_shapes;
00212     undo_shapes = 0;
00213     }
00214   }
00215 
00216 /*
00217  *  Figure max. queue size for given game window.
00218  */
00219 static int Figure_queue_size
00220   (
00221   )
00222   {
00223   Game_window *gwin = Game_window::get_instance();
00224   int w = gwin->get_width(), h = gwin->get_height();
00225           // Figure # chunks, rounding up.
00226   int cw = (w + c_chunksize - 1)/c_chunksize,
00227       ch = (h + c_chunksize - 1)/c_chunksize;
00228           // Add extra in each dir.
00229   return 6;//(cw + 3)*(ch + 3);
00230   }
00231 
00232 /*
00233  *  Create rendered_flats buffer.
00234  */
00235 
00236 Image_buffer8 *Chunk_terrain::render_flats
00237   (
00238   )
00239   {
00240   if (!rendered_flats)
00241     {
00242     if (queue_size > Figure_queue_size())
00243       {   // Grown too big.  Remove last.
00244       Chunk_terrain *last = render_queue->render_queue_prev;
00245       last->free_rendered_flats();
00246       render_queue->render_queue_prev = 
00247             last->render_queue_prev;
00248       last->render_queue_prev->render_queue_next = 
00249             render_queue;
00250       last->render_queue_next = last->render_queue_prev = 0;
00251       queue_size--;
00252       }
00253     rendered_flats = new Image_buffer8(c_chunksize, c_chunksize);
00254     }
00255           // Go through array of tiles.
00256   for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++)
00257     for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++)
00258       paint_tile(tilex, tiley);
00259 #ifdef HAVE_OPENGL
00260   delete glflats;
00261   glflats = 0;
00262   GL_manager *glman = GL_manager::get_instance();
00263   if (glman)      // Using OpenGL?
00264     glflats = glman->create(rendered_flats);
00265 #endif
00266   return rendered_flats;
00267   }
00268 
00269 /*
00270  *  Free pre-rendered landscape.
00271  */
00272 
00273 void Chunk_terrain::free_rendered_flats
00274   (
00275   )
00276   {
00277   delete rendered_flats; 
00278   rendered_flats = 0; 
00279 #ifdef HAVE_OPENGL
00280   delete glflats;
00281   glflats = 0;
00282 #endif
00283   }
00284 
00285 /*
00286  *  This method is only used in 'terrain-editor' mode, NOT in normal
00287  *  gameplay.
00288  */
00289 
00290 void Chunk_terrain::render_all
00291   (
00292   int cx, int cy      // Chunk rendering too.
00293   )
00294   {
00295   Image_window8 *iwin = gwin->get_win();
00296   int ctx = cx*c_tiles_per_chunk, cty = cy*c_tiles_per_chunk;
00297   int scrolltx = gwin->get_scrolltx(), scrollty = gwin->get_scrollty();
00298           // Go through array of tiles.
00299   for (int tiley = 0; tiley < c_tiles_per_chunk; tiley++)
00300     for (int tilex = 0; tilex < c_tiles_per_chunk; tilex++)
00301       {
00302       Shape_frame *shape = get_shape(tilex, tiley);
00303       if (!shape)
00304         continue;
00305       if (!shape->is_rle())
00306         iwin->copy8(shape->get_data(), c_tilesize, 
00307           c_tilesize, 
00308           (ctx + tilex - scrolltx)*c_tilesize,
00309           (cty + tiley - scrollty)*c_tilesize);
00310       else    // RLE.
00311         {
00312         int x, y;
00313         Tile_coord tile(ctx + tilex, cty + tiley, 0);
00314         gwin->get_shape_location(tile, x, y);
00315         sman->paint_shape(x, y, shape);
00316         }
00317       }
00318   }
00319 
00320 /*
00321  *  Write out to a chunk.
00322  */
00323   
00324 void Chunk_terrain::write_flats
00325   (
00326   unsigned char *chunk_data
00327   )
00328   {
00329   for (int ty = 0; ty < c_tiles_per_chunk; ty++)
00330     for (int tx = 0; tx < c_tiles_per_chunk; tx++)
00331       {
00332       ShapeID id = get_flat(tx, ty);
00333       int shapenum = id.get_shapenum(), 
00334           framenum = id.get_framenum();
00335       *chunk_data++ = shapenum&0xff;
00336       *chunk_data++ = ((shapenum>>8)&3) | (framenum<<2);
00337       }
00338   }
00339 

Generated on Mon Jul 9 14:42:49 2007 for ExultEngine by  doxygen 1.5.1