00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00039
00040
00041
00042 void Chunk_terrain::insert_in_queue
00043 (
00044 )
00045 {
00046 if (render_queue_next)
00047 {
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++;
00053 if (!render_queue)
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
00067
00068
00069 void Chunk_terrain::remove_from_queue
00070 (
00071 )
00072 {
00073 if (!render_queue_next)
00074 return;
00075 queue_size--;
00076 if (render_queue_next == this)
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
00090
00091
00092 inline void Chunk_terrain::paint_tile
00093 (
00094 int tilex, int tiley
00095 )
00096 {
00097 Shape_frame *shape = get_shape(tilex, tiley);
00098 if (shape && !shape->is_rle())
00099 rendered_flats->copy8(shape->get_data(),
00100 c_tilesize, c_tilesize, tilex*c_tilesize,
00101 tiley*c_tilesize);
00102 }
00103
00104
00105
00106
00107
00108 Chunk_terrain::Chunk_terrain
00109 (
00110 unsigned char *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
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
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
00161
00162
00163
00164 void Chunk_terrain::set_flat
00165 (
00166 int tilex, int tiley,
00167 ShapeID id
00168 )
00169 {
00170 if (!undo_shapes)
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
00182
00183
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();
00195 return true;
00196 }
00197
00198
00199
00200
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
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
00226 int cw = (w + c_chunksize - 1)/c_chunksize,
00227 ch = (h + c_chunksize - 1)/c_chunksize;
00228
00229 return 6;
00230 }
00231
00232
00233
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 {
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
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)
00264 glflats = glman->create(rendered_flats);
00265 #endif
00266 return rendered_flats;
00267 }
00268
00269
00270
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
00287
00288
00289
00290 void Chunk_terrain::render_all
00291 (
00292 int cx, int cy
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
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
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
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