00001
00002
00003 #include "stdafx.h"
00004 #include "openttd.h"
00005 #include "table/sprites.h"
00006 #include "strings_type.h"
00007 #include "table/strings.h"
00008 #include "clear_func.h"
00009 #include "company_func.h"
00010 #include "tile_type.h"
00011 #include "window_type.h"
00012 #include "gui.h"
00013 #include "rail_map.h"
00014 #include "rail_gui.h"
00015 #include "gfx_func.h"
00016 #include "settings_type.h"
00017 #include "sound_type.h"
00018 #include "sound_func.h"
00019 #include "command_type.h"
00020 #include "command_func.h"
00021 #include "tunnel_map.h"
00022 #include "bridge_map.h"
00023 #include "tunnelbridge_map.h"
00024 #include "tunnelbridge.h"
00025 #include "waypoint_base.h"
00026 #include "debug.h"
00027 #include "depot_map.h"
00028 #include "saveload/saveload.h"
00029 #include "window_func.h"
00030 #include "strings_func.h"
00031 #include "slope_type.h"
00032 #include "network/network.h"
00033 #include "command_queue.h"
00034 #include "copy_paste.h"
00035 #include "core/alloc_func.hpp"
00036 #include "core/endian_func.hpp"
00037
00038
00039 CopyPaste _copy_paste = CopyPaste();
00040
00041
00042 extern const uint32 COPYPASTE_VERSION = 1;
00043
00044 CopyPasteCommandQueue _copy_paste_command_queue = CopyPasteCommandQueue();
00045
00046 StringID error_message;
00047 StringID error_extra;
00048
00049 CopyPaste::CopyPaste()
00050 {
00051 m_width = 0;
00052 m_height = 0;
00053
00054 m_copy_with_rail = true;
00055 m_copy_with_road = true;
00056 m_copy_with_other = false;
00057 m_paste_vacant_terrain = 1;
00058 m_convert_rail = true;
00059 m_clear_before_build = true;
00060 m_toggle_signal_direction = false;
00061 }
00062
00063 void CopyPaste::AllocateMapArray(uint32 max_tiles)
00064 {
00065 this->ClearCopyArrays();
00066 m_heightmap = CallocT< int8>(max_tiles);
00067 m_terrain_needed = CallocT<uint8>(max_tiles);
00068 m_tiletype = CallocT<uint8>(max_tiles);
00069 m_railroad = CallocT<uint8>(max_tiles);
00070 m_signals = CallocT<uint16>(max_tiles);
00071 }
00072
00073 CopyPaste::~CopyPaste()
00074 {
00075 this->ClearCopyArrays();
00076 }
00077
00080 bool CopyPaste::IsSomethingCopied()
00081 {
00082 return !((GetWidth() == 0) || (GetHeight() == 0));
00083 }
00084
00087 void CopyPaste::ClearCopyArrays()
00088 {
00089 free(m_heightmap);
00090 free(m_terrain_needed);
00091 free(m_tiletype);
00092 free(m_railroad);
00093 free(m_signals);
00094 m_width = 0;
00095 m_height = 0;
00096 }
00097
00098
00104 SaveOrLoadResult CopyPaste::SaveLoadTemplate(const char *filename, int mode)
00105 {
00106 FILE* fh;
00107 uint32 hdr[4];
00108 uint32 tlen = GetWidth() * GetHeight();
00109 uint32 blen = (GetWidth() - 1) * (GetHeight() - 1);
00110 uint32 index;
00111 uint16 tmp16;
00112 uint16* ptmp16;
00113 ptmp16 = &tmp16;
00114
00115 uint32 version;
00116
00117 fh = (mode == SL_SAVE) ? fopen(filename, "wb") : fopen(filename, "rb");
00118
00119 switch(mode) {
00120 case SL_SAVE:
00121 hdr[0] = TO_BE32X('TMPL');
00122
00123 hdr[1] = TO_BE32(COPYPASTE_VERSION);
00124 hdr[2] = TO_BE32(GetWidth());
00125 hdr[3] = TO_BE32(GetHeight());
00126
00127 if (fwrite(hdr, sizeof(hdr), 1, fh) != 1) {
00128 fclose(fh);
00129 SetError(STR_TEMPLATE_SAVE_FAILED, STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
00130 return SL_ERROR;
00131 }
00132
00133 if (fwrite(m_heightmap, sizeof(int8), tlen, fh) != tlen) goto save_error;
00134 if (fwrite(m_terrain_needed, sizeof(uint8), tlen, fh) != tlen) goto save_error;
00135 if (fwrite(m_tiletype, sizeof(uint8), blen, fh) != blen) goto save_error;
00136 if (fwrite(m_railroad, sizeof(uint8), blen, fh) != blen) goto save_error;
00137
00138 for (index = 0; index < blen; index++)
00139 {
00140 tmp16 = TO_BE16(m_signals[index]);
00141 if (fwrite(ptmp16, sizeof(uint16), 1, fh) != 1) goto save_error;
00142 }
00143
00144 break;
00145
00146 case SL_LOAD:
00147 if (fread(hdr, sizeof(hdr), 1, fh) != 1) goto load_error;
00148 if (FROM_BE32(hdr[0]) != 'TMPL') {
00149 SetError(STR_TEMPLATE_LOAD_FAILED, STR_GAME_SAVELOAD_ERROR_TEMPLATE_BROKEN);
00150 return SL_ERROR;
00151 }
00152
00153 version = FROM_BE32(hdr[1]);
00154 DEBUG(sl, 1, "Loading template with version %d", version);
00155
00156
00157 if (version > COPYPASTE_VERSION) {
00158 DEBUG(sl, 1, "Can't load template with version %d, too new!", version);
00159 SetError(STR_TEMPLATE_LOAD_FAILED, STR_GAME_SAVELOAD_ERROR_TEMPLATE_TOO_NEW);
00160 return SL_ERROR;
00161 }
00162 DEBUG(sl, 1, "Getting bounds");
00163
00164 {
00165 uint32 width = FROM_BE32(hdr[2]);
00166 uint32 height = FROM_BE32(hdr[3]);
00167 AllocateMapArray(width * height);
00168 SetWidth(width);
00169 SetHeight(height);
00170 }
00171
00172 tlen = GetWidth() * GetHeight();
00173 blen = (GetWidth() - 1) * (GetHeight() - 1);
00174
00175 DEBUG(sl, 1, "Allocated arrays, loading from file");
00176
00177 if (fread(m_heightmap, sizeof(int8), tlen, fh) != tlen) goto load_error;
00178 if (fread(m_terrain_needed, sizeof(uint8), tlen, fh) != tlen) goto load_error;
00179 if (fread(m_tiletype, sizeof(uint8), blen, fh) != blen) goto load_error;
00180 if (fread(m_railroad, sizeof(uint8), blen, fh) != blen) goto load_error;
00181 DEBUG(sl, 1, "Reading signals");
00182
00183 for (index = 0; index < blen; index++) {
00184 if (fread(ptmp16, sizeof(uint16), 1, fh) != 1) goto load_error;
00185 m_signals[index] = FROM_BE16(tmp16);
00186 }
00187 SetWindowDirty(WC_COPY_PASTE, 0);
00188 break;
00189
00190 default:
00191
00192 break;
00193 }
00194
00195 fclose(fh);
00196
00197 return SL_OK;
00198
00199 save_error:
00200 SetError(STR_TEMPLATE_SAVE_FAILED);
00201 fclose(fh);
00202 return SL_ERROR;
00203
00204 load_error:
00205 SetError(STR_TEMPLATE_LOAD_FAILED);
00206 fclose(fh);
00207 return SL_ERROR;
00208 }
00209
00211 void CopyPaste::SetError(StringID message, StringID extra)
00212 {
00213 error_message = message;
00214 error_extra = extra;
00215 }
00216
00218 const char* CopyPaste::GetErrorString()
00219 {
00220
00221 SetDParam(0, error_extra);
00222
00223 static char str[512];
00224 GetString(str, error_message, lastof(str));
00225 return str;
00226 }
00227
00234 void CopyPaste::CP_DoCommand(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
00235 {
00236 if (_shift_pressed) {
00237 CommandCost res = DoCommand(tile, p1, p2, DC_QUERY_COST, cmd & 0xFF, "");
00238 if (!res.Failed())
00239 m_costs.AddCost(res);
00240 }
00241 else {
00242 #ifdef ENABLE_NETWORK
00243 if (_networking) {
00244 _copy_paste_command_queue.CopyPasteQueueCommand(tile, p1, p2, callback, cmd);
00245 }
00246 else
00247 #endif
00248 DoCommandP(tile, p1, p2, cmd, callback);
00249 }
00250 }
00251
00252
00253
00258 void CopyPaste::CP_RaiseLowerLand(TileIndex tile, int mode)
00259 {
00260 CP_DoCommand(tile, 8, (uint32)mode, NULL, CMD_TERRAFORM_LAND | CMD_MSG(mode ? STR_ERROR_CAN_T_RAISE_LAND_HERE : STR_ERROR_CAN_T_LOWER_LAND_HERE));
00261 }
00262
00263 void CopyPaste::CP_PlaceRail(TileIndex tile, int cmd, uint32 railtype)
00264 {
00265 CP_DoCommand(tile, railtype, cmd, NULL,
00266 CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)
00267 );
00268 }
00269
00270 void CopyPaste::CP_PlaceSignals(TileIndex tile, Track track, SignalType type, uint direction, bool semaphore)
00271 {
00272 if (IsPbsSignal(type) && direction > 0) direction--;
00273 CP_DoCommand(tile, track | (semaphore ? 1 : 0) << 4 | type << 5 | direction << 15, 0, NULL,
00274 CMD_BUILD_SIGNALS | CMD_MSG(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE));
00275 }
00276
00277 void CopyPaste::CP_PlaceRoad(TileIndex tile, uint8 road_bits)
00278 {
00279 CP_DoCommand(tile, road_bits, 0, NULL, CMD_BUILD_ROAD | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_HERE));
00280 }
00281
00282 void CopyPaste::CP_PlaceRoadStop(TileIndex tile, uint8 direction, uint8 roadtype, bool truck_stop, bool drive_through)
00283 {
00284 CP_DoCommand(tile, direction, truck_stop | drive_through << 1 | roadtype << 2 | INVALID_STATION << 16, NULL, CMD_BUILD_ROAD_STOP | CMD_MSG(truck_stop ? STR_ERROR_CAN_T_BUILD_TRUCK_STATION : STR_ERROR_CAN_T_BUILD_BUS_STATION));
00285 }
00286
00287 void CopyPaste::CP_PlaceRail_Tunnel(TileIndex tile, uint32 railtype)
00288 {
00289 CP_DoCommand(tile, railtype, 0, NULL,
00290 CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE));
00291 }
00292
00293 void CopyPaste::CP_PlaceRoad_Tunnel(TileIndex tile, uint8 roadtype)
00294 {
00295 CP_DoCommand(tile, 0x200 | roadtype, 0, NULL, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE));
00296 }
00297
00298 void CopyPaste::CP_Build_Bridge(TileIndex start, TileIndex end, uint8 bridgetype, uint8 transport_type, uint8 rail_road_type)
00299 {
00300 CP_DoCommand(end, start,
00301 bridgetype | (rail_road_type << 8) | (transport_type << 15), NULL,
00302 CMD_BUILD_BRIDGE | CMD_MSG(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE));
00303 }
00304
00305 void CopyPaste::CP_PlaceRail_Depot(TileIndex tile, uint8 railtype, uint8 direction)
00306 {
00307 CP_DoCommand(tile, railtype, direction, NULL,
00308 CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT));
00309 }
00310
00311 void CopyPaste::CP_PlaceRoad_Depot(TileIndex tile, uint8 direction_type)
00312 {
00313 CP_DoCommand(tile, direction_type, 0, NULL,
00314 CMD_BUILD_ROAD_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_HERE));
00315 }
00316
00317 void CopyPaste::CP_PlaceWaypoint(TileIndex tile, uint8 waypoint_type)
00318 {
00319 CP_DoCommand(tile, waypoint_type, 0, NULL, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT));
00320 }
00321
00322 void CopyPaste::CP_ClearTile(TileIndex start_tile, TileIndex end_tile)
00323 {
00324 CP_DoCommand(start_tile, end_tile, 0, NULL, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA));
00325 }
00326
00327 uint8 CopyPaste::MirrorSignalDirection(uint8 direction)
00328 {
00329 if (direction == 0) return direction;
00330 return (direction == 1 ? 2 : 1);
00331 }
00332
00333 DisallowedRoadDirections CopyPaste::MirrorOneWayRoadDirection(DisallowedRoadDirections drd)
00334 {
00335 if (drd == DRD_NONE || drd == DRD_BOTH) return drd;
00336 return drd == DRD_SOUTHBOUND ? DRD_NORTHBOUND : DRD_SOUTHBOUND;
00337 }
00338
00339 void CopyPaste::SwapSignalInfo(uint index)
00340 {
00341 uint16 signal = m_signals[index];
00342
00343 for (uint i = 2; i < 16; i++)
00344 ClrBit(m_signals[index], i);
00345
00346 SB(m_signals[index], 2, 1, GB(signal, 3, 1));
00347
00348 SB(m_signals[index], 3, 1, GB(signal, 2, 1));
00349
00350 SB(m_signals[index], 6, 2, MirrorSignalDirection(GB(signal, 8, 2)));
00351
00352 SB(m_signals[index], 8, 2, MirrorSignalDirection(GB(signal, 6, 2)));
00353
00354
00355 SB(m_signals[index], 10, 3, GB(signal, 13, 3));
00356
00357 SB(m_signals[index], 13, 3, GB(signal, 10, 3));
00358 }
00359
00361 void CopyPaste::PasteLandscape(TileIndex tile)
00362 {
00363 TileIndex sx = TileX(tile);
00364 TileIndex sy = TileY(tile);
00365 uint size_x = GetWidth();
00366 uint size_y = GetHeight();
00367 int8 count, h_diff;
00368 uint h_tile;
00369
00370 TileIndex index;
00371
00372 uint baseh = TileHeight(tile);
00373
00374 if (m_clear_before_build) {
00375 index = 0;
00376 TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
00377
00378 if (GetCPTileType(index) != CP_TILE_CLEAR) {
00379 CP_ClearTile(tile, tile);
00380 }
00381 index++;
00382
00383 }
00384 }
00385
00386
00387 if (m_paste_vacant_terrain > 0) {
00388
00389
00390
00391 index = 0;
00392 TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
00393
00394 if (HasBit(m_terrain_needed[index], 0) || (m_paste_vacant_terrain == 2)) {
00395
00396
00397
00398
00399
00400
00401 #ifdef ENABLE_NETWORK
00402 if (_networking) {
00403 h_tile = TileHeight(tile);
00404 if ((cur_h != size_y) && (cur_w != size_x)) {
00405
00406 h_tile = ClampToRight(index, baseh, h_tile);
00407 h_tile = ClampToUp(index, baseh, h_tile, size_x);
00408
00409 h_diff = GetHeight(baseh, index) - h_tile;
00410 }
00411 else {
00412 if ((cur_h == size_y) && (cur_w == size_x)) {
00413
00414 h_diff = GetHeight(baseh, index) - TileHeight(tile);
00415 }
00416 else if (cur_w == size_x) {
00417
00418 h_tile = ClampToUp(index, baseh, h_tile, size_x);
00419 h_diff = GetHeight(baseh, index) - h_tile;
00420 }
00421 else {
00422
00423 h_tile = ClampToRight(index, baseh, h_tile);
00424 h_diff = GetHeight(baseh, index) - h_tile;
00425 }
00426 }
00427 }
00428 else
00429 #endif
00430 h_diff = GetHeight(baseh, index) - TileHeight(tile);
00431
00432
00433 if (h_diff > 0) {
00434 for (count = 0; count < h_diff; count++)
00435 CP_RaiseLowerLand(tile, 1);
00436 }
00437 else if (h_diff < 0) {
00438 for (count = h_diff; count < 0; count++)
00439 CP_RaiseLowerLand(tile, 0);
00440 }
00441 }
00442 index++;
00443
00444 }
00445 }
00446
00447 }
00448
00450 void CopyPaste::PasteSignals(uint index, TileIndex tile)
00451 {
00452 uint16 signal = m_signals[index];
00453 if (m_toggle_signal_direction) {
00454 SB(signal, 6, 2, MirrorSignalDirection(GB(signal, 6, 2)));
00455 SB(signal, 8, 2, MirrorSignalDirection(GB(signal, 8, 2)));
00456 }
00457 bool firstrun = true;
00458 for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
00459 if (m_railroad[index] & TrackToTrackBits(t)) {
00460 if (((IsDiagonalTrack(t) || t == TRACK_LEFT || t == TRACK_UPPER) &&
00461 HasBit(signal, 0)) ||
00462 ((t == TRACK_RIGHT || t == TRACK_LOWER) && HasBit(signal, 1))) {
00463 CP_PlaceSignals(tile, t,
00464 (SignalType)GB(signal, firstrun ? 10 : 13, 3),
00465 GB(signal, firstrun ? 6 : 8, 2),
00466 HasBit(signal, firstrun ? 2 : 3));
00467 firstrun = false;
00468 }
00469 }
00470 }
00471 }
00472
00477 int8 CopyPaste::ClampToRight(TileIndex index, int8 baseh, int8 h_tile)
00478 {
00479 int8 h_right = GetHeight(baseh, index - 1);
00480
00481 if (h_tile > (h_right + 1)) {
00482 h_tile = h_right + 1;
00483 }
00484 else if (h_tile < (h_right - 1)) {
00485 h_tile = h_right - 1;
00486 }
00487
00488 return h_tile;
00489 }
00490
00495 int8 CopyPaste::ClampToUp(TileIndex index, int8 baseh, int8 h_tile, int32 size_x)
00496 {
00497 int8 h_up = GetHeight(baseh, index - size_x);
00498
00499 if (h_tile > (h_up + 1)) {
00500 h_tile = h_up + 1;
00501 }
00502 else if (h_tile < (h_up - 1)) {
00503 h_tile = h_up - 1;
00504 }
00505
00506 return h_tile;
00507 }
00508
00514 void CopyPaste::internal_PasteArea(TileIndex tile)
00515 {
00516 int8 baseh;
00517 TileIndex index = 0;
00518 int32 size_x, size_y;
00519 bool success = true;
00520 TileIndex sx = TileX(tile);
00521 TileIndex sy = TileY(tile);
00522 TileIndex ex = sx + GetWidth();
00523 TileIndex ey = sy + GetHeight();
00524
00525
00526 if (_shift_pressed) {
00527 m_costs.MultiplyCost(0);
00528 }
00529
00530
00531 if (! IsSomethingCopied()) return;
00532
00533
00534 if ((ex >= MapSizeX()) || (ey >= MapSizeY())) return;
00535
00536 size_x = GetWidth();
00537 size_y = GetHeight();
00538
00539
00540 baseh = (int8)TileHeight(tile);
00541
00542
00543 PasteLandscape(tile);
00544
00545
00546
00547
00548 index = 0;
00549 TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
00550
00551 uint minortt = GetCPMinorTileType(index);
00552
00553 switch(GetCPTileType(index)) {
00554 case CP_TILE_RAIL: {
00555 uint rt = GB(m_railroad[index], 6, 2);
00556 switch (minortt) {
00557 case RAIL_TILE_NORMAL:
00558 case RAIL_TILE_SIGNALS:
00559
00560 for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
00561 if (m_railroad[index] & TrackToTrackBits(t)) CP_PlaceRail(tile, t, m_convert_rail ? (uint)_cur_railtype : rt);
00562 }
00563 break;
00564
00565 case RAIL_TILE_DEPOT:
00566 CP_PlaceRail_Depot(tile, m_convert_rail ? (uint)_cur_railtype : rt, GB(m_railroad[index], 0, 2));
00567 break;
00568 }
00569 } break;
00570 case CP_TILE_ROAD: {
00571 switch(minortt) {
00572 case ROAD_TILE_CROSSING:
00573 CP_PlaceRail(tile, GB(m_railroad[index], 0, 4) == ROAD_X ? TRACK_Y : TRACK_X, m_convert_rail ? (uint)_cur_railtype : GB(m_signals[index], 4, 2));
00574
00575 case ROAD_TILE_NORMAL:
00576 if (GB(m_railroad[index], 0, 4) > 0) CP_PlaceRoad(tile, GB(m_railroad[index], 0, 4) | (ROADTYPE_ROAD << 4) | (minortt == ROAD_TILE_NORMAL ? (GB(m_signals[index], 0, 2) << 6) : 0));
00577 if (GB(m_railroad[index], 4, 4) > 0) CP_PlaceRoad(tile, GB(m_railroad[index], 4, 4) | (ROADTYPE_TRAM << 4));
00578 break;
00579 case ROAD_TILE_DEPOT:
00580 CP_PlaceRoad_Depot(tile, GB(m_railroad[index], 0, 2) | HasBit(m_railroad[index], 2) << 2);
00581 break;
00582 }
00583 } break;
00584 case CP_TILE_STATION:
00585 switch(minortt) {
00586 case CP_TILE_ROAD:
00587 CP_PlaceRoadStop(tile, GB(m_railroad[index], 0, 2), GB(m_railroad[index], 6, 2), HasBit(m_railroad[index], 2), HasBit(m_railroad[index], 3));
00588 }
00589
00590
00591 case CP_TILE_TUNNELBRIDGE:
00592 if (HasBit(minortt, 0)) {
00593
00594
00595
00596
00597 if (HasBit(m_railroad[index], 4)) {
00598 if (GB(m_railroad[index], 2, 2) == TRANSPORT_ROAD) {
00599 CP_PlaceRoad_Tunnel(tile, GB(m_railroad[index], 6, 2));
00600 } else {
00601 CP_PlaceRail_Tunnel(tile, m_convert_rail ? (uint) _cur_railtype : GB(m_railroad[index], 6, 2));
00602 }
00603 }
00604 } else if (HasBit(m_railroad[index], 4)) {
00605
00606
00607
00608
00609 bool bridge_error = false;
00610 TileIndex tmp_tile = tile;
00611 uint rdd = ReverseDiagDir((DiagDirection)GB(m_railroad[index], 0, 2));
00612 bool found = false;
00613 TileIndex i;
00614 switch (GB(m_railroad[index], 0, 2)) {
00615 case DIAGDIR_NE:
00616
00617 i = 1;
00618 while ((TileX(tile) - i) >= sx) {
00619 if (GetCPTileType(index - i) == CP_TILE_TUNNELBRIDGE &&
00620 !HasBit(GetCPMinorTileType(index - i), 0) &&
00621 !HasBit(m_railroad[index - i], 4) &&
00622 GB(m_railroad[index - i], 0, 2) == rdd) {
00623 found = true;
00624 break;
00625 }
00626 i++;
00627 }
00628 if ((TileX(tile) - i) < sx || !found)
00629 bridge_error = true;
00630 else
00631 tmp_tile += TileDiffXY(0 - i, 0);
00632 break;
00633 case DIAGDIR_SW:
00634
00635 i = 1;
00636 while ((TileX(tile) + i) < (sx + size_x - 1)) {
00637 if (GetCPTileType(index + i) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index + i), 0) && !HasBit(m_railroad[index + i], 4) && GB(m_railroad[index + i], 0, 2) == rdd) {
00638 found = true;
00639 break;
00640 }
00641 i++;
00642 }
00643 if ((TileX(tile) + i) >= (sx + size_x - 1) || !found)
00644 bridge_error = true;
00645 else
00646 tmp_tile += TileDiffXY(+i, 0);
00647 break;
00648 case DIAGDIR_SE:
00649
00650 i = 1;
00651 while ((TileY(tile) + i) < (sy + size_y - 1)) {
00652 if (GetCPTileType(index + (i * (size_x - 1))) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index + (i * (size_x - 1))), 0) && !HasBit(m_railroad[index + (i * (size_x - 1))], 4) && GB(m_railroad[index + (i * (size_x - 1))], 0, 2) == rdd) {
00653 found = true;
00654 break;
00655 }
00656 i++;
00657 }
00658 if ((TileY(tile) + i) >= (sy + size_y - 1) || !found)
00659 bridge_error = true;
00660 else
00661 tmp_tile += TileDiffXY(0, +i);
00662 break;
00663 case DIAGDIR_NW:
00664
00665 i = 1;
00666 while ((TileY(tile) + i) >= (sy + size_y - 1)) {
00667 if (GetCPTileType(index - (i * (size_x - 1))) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index - (i * (size_x - 1))), 0) && !HasBit(m_railroad[index - (i * (size_x - 1))], 4) && GB(m_railroad[index - (i * (size_x - 1))], 0, 2) == rdd) {
00668 found = true;
00669 break;
00670 }
00671 i++;
00672 }
00673 if ((TileY(tile) - i) < sy || !found)
00674 bridge_error = true;
00675 else
00676 tmp_tile += TileDiffXY(0, 0 - i);
00677 break;
00678 }
00679 if (!bridge_error) {
00680 if (GB(m_railroad[index], 2, 2) == TRANSPORT_RAIL) {
00681 CP_Build_Bridge(tile, tmp_tile, m_convert_rail ? GetFastestAvailableBridgeType(GetTunnelBridgeLength(tile, tmp_tile)) : m_signals[index], TRANSPORT_RAIL, m_convert_rail ? (uint) _cur_railtype : ((m_railroad[index] >> 6) & 3U) );
00682 } else {
00683 CP_Build_Bridge(tile, tmp_tile, m_convert_rail ? GetFastestAvailableBridgeType(GetTunnelBridgeLength(tile, tmp_tile)) : m_signals[index], TRANSPORT_ROAD, ((m_railroad[index] >> 6) & 3U) );
00684 }
00685 }
00686 }
00687 break;
00688 default: break;
00689 }
00690
00691 index++;
00692
00693 }
00694
00695
00696 index = 0;
00697 TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
00698 if (GetCPTileType(index) == CP_TILE_RAIL) {
00699 switch(GetCPMinorTileType(index)) {
00700
00701
00702
00703 case RAIL_TILE_SIGNALS:
00704 PasteSignals(index, tile);
00705 }
00706 }
00707 index++;
00708 }
00709
00710
00711
00712 if (_shift_pressed) {
00713 ShowEstimatedCostOrIncome(m_costs.GetCost(), 100, 100);
00714 }
00715 else {
00716 if (success) SndPlayTileFx(SND_1F_SPLAT, tile);
00717 }
00718 }
00719
00724 void CopyPaste::PasteArea(TileIndex tile)
00725 {
00726 if (_settings_client.gui.cp_paste_speed != 0xFF) {
00727 this->internal_PasteArea(tile);
00728 }
00729 else {
00730 ShowErrorMessage(STR_COPY_PASTE_PASTE_DISABLED, INVALID_STRING_ID, WL_ERROR, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
00731 }
00732 }
00733
00740 void CopyPaste::TerrainNeededAroundTile(TileIndex tindex, TileIndex bindex)
00741 {
00742
00743 SetBit(m_terrain_needed[tindex], 0);
00744 SetBit(m_terrain_needed[tindex + 1], 0);
00745 SetBit(m_terrain_needed[tindex + GetWidth()], 0);
00746 SetBit(m_terrain_needed[tindex + GetWidth() + 1], 0);
00747 }
00748
00752 void CopyPaste::CopyArea(TileIndex end, TileIndex start)
00753 {
00754 int8 baseh;
00755 TileIndex tindex = 0;
00756 TileIndex bindex = 0;
00757 int size_x, size_y;
00758 bool success = false;
00759 TileIndex sx = TileX(start);
00760 TileIndex sy = TileY(start);
00761 TileIndex ex = TileX(end);
00762 TileIndex ey = TileY(end);
00763 bool tunnelbridge_error;
00764 int32 maxdiff, i;
00765
00766
00767 if (ex < sx) Swap(ex, sx);
00768 if (ey < sy) Swap(ey, sy);
00769
00770 ex++;
00771 ey++;
00772 size_x = (ex - sx) + 1;
00773 size_y = (ey - sy) + 1;
00774
00775 this->AllocateMapArray(size_x * size_y);
00776 SetWidth(size_x);
00777 SetHeight(size_y);
00778
00779
00780
00781 baseh = (int8)TileHeight(TileXY(sx, sy));
00782 tindex = 0;
00783 TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
00784
00785 m_heightmap[tindex] = ((int8)TileHeight(tile)) - baseh;
00786 tindex++;
00787
00788
00789 if (cur_h == 1 || cur_w == 1) {
00790 success = true;
00791 continue;
00792 }
00793
00794
00795 switch (GetTileType(tile)) {
00796 case MP_RAILWAY:
00797
00798 if (!m_copy_with_rail) break;
00799 if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
00800 SB(m_tiletype[bindex], 0, 4, CP_TILE_RAIL);
00801 SB(m_tiletype[bindex], 4, 4, GetRailTileType(tile));
00802 TerrainNeededAroundTile(tindex - 1, bindex);
00803
00804
00805 SB(m_railroad[bindex], 6, 2, GetRailType(tile));
00806
00807 switch (GetRailTileType(tile)) {
00808 case RAIL_TILE_DEPOT:
00809
00810
00811 SB(m_railroad[bindex], 0, 2, GetDepotDirection(tile, TRANSPORT_RAIL));
00812 break;
00813
00814
00815
00816
00817
00818
00819
00820 case RAIL_TILE_SIGNALS: {
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832 bool first_run = true;
00833 for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
00834 if (HasTrack(tile, t) && HasSignalOnTrack(tile, t)) {
00835 if (t == TRACK_X || t == TRACK_Y || t == TRACK_LEFT || t == TRACK_UPPER) {
00836 SetBit(m_signals[bindex], 0);
00837 } else {
00838 SetBit(m_signals[bindex], 1);
00839 }
00840
00841 Trackdir td = TrackToTrackdir(t);
00842 if (!(HasSignalOnTrackdir(tile, td) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)))) {
00843
00844 if (t == TRACK_LEFT || t == TRACK_RIGHT) td = ReverseTrackdir(td);
00845 SB(m_signals[bindex], first_run ? 6 : 8, 2, HasSignalOnTrackdir(tile, td) ? 1 : 2);
00846 }
00847
00848 SB(m_signals[bindex], first_run ? 2 : 3, 1, GetSignalVariant(tile, t));
00849
00850 SB(m_signals[bindex], first_run ? 10 : 13, 3, GetSignalType(tile, t));
00851 first_run = false;
00852 }
00853 }
00854 }
00855
00856 case RAIL_TILE_NORMAL:
00857
00858 m_railroad[bindex] |= GetTrackBits(tile);
00859 break;
00860 }
00861
00862 break;
00863 case MP_ROAD:
00864 if (GetRoadTileType(tile) != ROAD_TILE_CROSSING && (!m_copy_with_road || !(m_copy_with_other || IsTileOwner(tile, _current_company)))) break;
00865 SB(m_tiletype[bindex], 0, 4, CP_TILE_ROAD);
00866 SB(m_tiletype[bindex], 4, 4, GetRoadTileType(tile));
00867 switch (GetRoadTileType(tile)) {
00868 case ROAD_TILE_CROSSING: {
00869
00870
00871
00872 RoadBits roadbits = GetCrossingRoadBits(tile);
00873 Track railtrack = GetCrossingRailTrack(tile);
00874 bool should_copy_rail = m_copy_with_rail && (m_copy_with_other || IsTileOwner(tile, _current_company));
00875 bool should_copy_road = m_copy_with_road;
00876 if (should_copy_rail && !should_copy_road) {
00877 SB(m_tiletype[bindex], 0, 4, CP_TILE_RAIL);
00878 SB(m_tiletype[bindex], 4, 4, RAIL_TILE_NORMAL);
00879 TerrainNeededAroundTile(tindex - 1, bindex);
00880
00881 m_railroad[bindex] |= TrackToTrackBits(railtrack);
00882 SB(m_railroad[bindex], 6, 2, GetRailType(tile));
00883 }
00884 if (should_copy_road && !should_copy_rail) {
00885 SB(m_tiletype[bindex], 4, 4, ROAD_TILE_NORMAL);
00886 }
00887 if (should_copy_road && should_copy_rail) {
00888 SB(m_signals[bindex], 4, 2, GetRailType(tile));
00889 }
00890 if (should_copy_road) {
00891
00892 for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
00893 if ((m_copy_with_other || GetRoadOwner(tile, rt) == _current_company) && GetRoadTypes(tile) & RoadTypeToRoadTypes(rt)) {
00894 TerrainNeededAroundTile(tindex - 1, bindex);
00895 SB(m_railroad[bindex], rt * 4, 4, roadbits);
00896 }
00897 }
00898 }
00899 if (!should_copy_road && !should_copy_rail) {
00900 SB(m_tiletype[bindex], 0, 4, CP_TILE_CLEAR);
00901 }
00902 } break;
00903
00904 case ROAD_TILE_DEPOT:
00905
00906 SB(m_railroad[bindex], 0, 2, GetDepotDirection(tile, TRANSPORT_ROAD));
00907
00908 if (GetRoadTypes(tile) != ROADTYPES_ROAD) SetBit(m_railroad[bindex], 2);
00909 TerrainNeededAroundTile(tindex - 1, bindex);
00910 break;
00911
00912 case ROAD_TILE_NORMAL:
00913 for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
00914 SB(m_railroad[bindex], rt * 4, 4, GetRoadBits(tile, rt));
00915 }
00916 TerrainNeededAroundTile(tindex - 1, bindex);
00917 SB(m_signals[bindex], 0, 2, GetDisallowedRoadDirections(tile));
00918 break;
00919 }
00920 break;
00921
00922 case MP_STATION:
00923
00924 SB(m_tiletype[bindex], 0, 4, CP_TILE_STATION);
00925
00926
00927 switch (GetStationType(tile)) {
00928
00929 case STATION_TRUCK:
00930 case STATION_BUS:
00931 SB(m_tiletype[bindex], 4, 4, CP_TILE_ROAD);
00932
00933 SB(m_railroad[bindex], 0, 2, GetRoadStopDir(tile));
00934 if(GetStationType(tile) == STATION_TRUCK) SetBit(m_railroad[bindex], 2);
00935 SB(m_railroad[bindex], 3, 1, IsDriveThroughStopTile(tile));
00936 SB(m_railroad[bindex], 6, 2, GetRoadTypes(tile));
00937 break;
00938
00939
00940 case STATION_RAIL:
00941 SB(m_tiletype[bindex], 4, 4, CP_TILE_RAIL);
00942
00943
00944 break;
00945
00946 default:
00947
00948 break;
00949
00950 }
00951 break;
00952
00953 case MP_TUNNELBRIDGE:
00954
00955
00956
00957 if (IsTunnelTile(tile)) {
00958
00959 if (!m_copy_with_rail && (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)) break;
00960 if (!m_copy_with_road && (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)) break;
00961 if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
00962 tunnelbridge_error = false;
00963 if ((GetTunnelBridgeDirection(tile) == DIAGDIR_SW) || (GetTunnelBridgeDirection(tile) == DIAGDIR_SE)) {
00964 int tilediff = 1;
00965
00966 SB(m_railroad[bindex], 0, 2, GetTunnelBridgeDirection(tile));
00967
00968 SB(m_railroad[bindex], 2, 2, GetTunnelBridgeTransportType(tile));
00969
00970 SetBit(m_railroad[bindex], 4);
00971
00972 if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)
00973 m_railroad[bindex] |= (GetRailType(tile) << 6);
00974 if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)
00975 m_railroad[bindex] |= (GetRoadTypes(tile) << 6);
00976
00977
00978
00979 switch (GetTunnelBridgeDirection(tile)) {
00980 case DIAGDIR_SW:
00981 maxdiff = (size_x - 1) - (bindex % (size_x - 1)) - 1;
00982 if (maxdiff <= 0) {
00983 tunnelbridge_error = true;
00984 break;
00985 }
00986 while ((!IsTunnelTile(tile + TileDiffXY(tilediff, 0))) && (tilediff <= maxdiff)) {
00987 tilediff++;
00988 }
00989 if ((!IsTunnelTile(tile + TileDiffXY(tilediff, 0))) || (tilediff > maxdiff))
00990 tunnelbridge_error = true;
00991 if (!tunnelbridge_error) {
00992
00993 for (i = 0; i <= tilediff; i++)
00994 TerrainNeededAroundTile(tindex - 1 + i, bindex + i);
00995
00996
00997 SB(m_tiletype[bindex + tilediff], 0, 4, CP_TILE_TUNNELBRIDGE);
00998 SB(m_tiletype[bindex + tilediff], 4, 1, true);
00999
01000 m_railroad[bindex + tilediff] |= GetTunnelBridgeDirection(tile + TileDiffXY(tilediff, 0));
01001
01002 SB(m_railroad[bindex + tilediff], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)));
01003
01004
01005 if (GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)) == TRANSPORT_RAIL)
01006 m_railroad[bindex + tilediff] = (GetRailType(tile + TileDiffXY(tilediff, 0)) << 6);
01007 }
01008 break;
01009 case DIAGDIR_SE:
01010 maxdiff = (size_y - 1) - (bindex / (size_x - 1)) - 1;
01011 if (maxdiff <= 0) {
01012 tunnelbridge_error = true;
01013 break;
01014 }
01015 while ((!IsTunnelTile(tile + TileDiffXY(0, tilediff))) && (tilediff <= maxdiff)) {
01016 tilediff++;
01017 }
01018 if ((!IsTunnelTile(tile + TileDiffXY(0, tilediff))) || (tilediff > maxdiff))
01019 tunnelbridge_error = true;
01020 if (!tunnelbridge_error) {
01021
01022 for (i = 0; i <= tilediff; i++)
01023 TerrainNeededAroundTile(tindex - 1 + (i * size_x), bindex + (i * (size_x - 1)));
01024
01025
01026 SB(m_tiletype[bindex + tilediff * (size_x - 1)], 0, 4, CP_TILE_TUNNELBRIDGE);
01027 SB(m_tiletype[bindex + tilediff * (size_x - 1)], 4, 1, true);
01028
01029 m_railroad[bindex + (tilediff * (size_x - 1))] |= GetTunnelBridgeDirection(tile + TileDiffXY(0, tilediff));
01030
01031 SB(m_railroad[bindex + tilediff * (size_x - 1)], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)));
01032
01033
01034 if (GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)) == TRANSPORT_RAIL)
01035 m_railroad[bindex + (tilediff * (size_x - 1))] |= (GetRailType(tile + TileDiffXY(0, tilediff)) << 6);
01036 }
01037 break;
01038 default:
01039 break;
01040 }
01041 if (tunnelbridge_error) {
01042
01043 m_railroad[bindex] = 0;
01044 } else {
01045 SB(m_tiletype[bindex], 0, 4, CP_TILE_TUNNELBRIDGE);
01046 SB(m_tiletype[bindex], 4, 1, IsTunnelTile(tile));
01047 }
01048 }
01049 else {
01050
01051 }
01052 }
01053 else {
01054
01055 if (IsBridge(tile)) {
01056 if (!m_copy_with_rail && (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)) break;
01057 if (!m_copy_with_road && (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)) break;
01058 if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
01059
01060 tunnelbridge_error = false;
01061 if ((GetTunnelBridgeDirection(tile) == DIAGDIR_SW) || (GetTunnelBridgeDirection(tile) == DIAGDIR_SE)) {
01062 int tilediff = 1;
01063
01064 SB(m_railroad[bindex], 0, 2, GetTunnelBridgeDirection(tile));
01065
01066 SB(m_railroad[bindex], 2, 2, GetTunnelBridgeTransportType(tile));
01067
01068 SetBit(m_railroad[bindex], 4);
01069
01070 m_signals[bindex] = GetBridgeType(tile);
01071
01072 if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)
01073 m_railroad[bindex] |= (GetRailType(tile) << 6);
01074 if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)
01075 m_railroad[bindex] |= (GetRoadTypes(tile) << 6);
01076
01077
01078
01079 switch (GetTunnelBridgeDirection(tile)) {
01080 TileIndex otherEnd;
01081 case DIAGDIR_SW:
01082 maxdiff = (size_x - 1) - (bindex % (size_x - 1)) - 1;
01083 if (maxdiff <= 0) {
01084 tunnelbridge_error = true;
01085 break;
01086 }
01087 otherEnd = GetOtherBridgeEnd(tile);
01088 tilediff = DistanceManhattan(tile, otherEnd);
01089 if (tilediff > maxdiff)
01090 tunnelbridge_error = true;
01091
01092 if (!tunnelbridge_error) {
01093
01094 for (i = 0; i <= tilediff; i++)
01095 TerrainNeededAroundTile(tindex - 1 + i, bindex + i);
01096
01097
01098 SB(m_tiletype[bindex + tilediff], 0, 4, CP_TILE_TUNNELBRIDGE);
01099 SB(m_tiletype[bindex + tilediff], 4, 1, IsTunnelTile(tile));
01100
01101 SB(m_railroad[bindex + tilediff], 0, 2, GetTunnelBridgeDirection(tile + TileDiffXY(tilediff, 0)));
01102
01103 SB(m_railroad[bindex + tilediff], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)));
01104
01105
01106
01107 m_signals[bindex + tilediff] = GetBridgeType(tile + TileDiffXY(tilediff, 0));
01108
01109 if (GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)) == TRANSPORT_RAIL)
01110 m_railroad[bindex + tilediff] |= (GetRailType(tile + TileDiffXY(tilediff, 0)) << 6);
01111 }
01112 break;
01113 case DIAGDIR_SE:
01114 maxdiff = (size_y - 1) - (bindex / (size_x - 1)) - 1;
01115 if (maxdiff <= 0) {
01116 tunnelbridge_error = true;
01117 break;
01118 }
01119 otherEnd = GetOtherBridgeEnd(tile);
01120 tilediff = DistanceManhattan(tile, otherEnd);
01121 if (tilediff > maxdiff)
01122 tunnelbridge_error = true;
01123 if (!tunnelbridge_error) {
01124
01125 for (i = 0; i <= tilediff; i++)
01126 TerrainNeededAroundTile(tindex - 1 + (i * size_x), bindex + (i * (size_x - 1)));
01127
01128
01129 SB(m_tiletype[bindex + (tilediff * (size_x - 1))], 0, 4, CP_TILE_TUNNELBRIDGE);
01130 SB(m_tiletype[bindex + (tilediff * (size_x - 1))], 4, 1, IsTunnelTile(tile));
01131
01132 SB(m_railroad[bindex + tilediff * (size_x - 1)], 0, 2, GetTunnelBridgeDirection(tile + TileDiffXY(0, tilediff)));
01133
01134 SB(m_railroad[bindex + tilediff * (size_x - 1)], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)));
01135
01136
01137 m_signals[bindex + tilediff * (size_x - 1)] = GetBridgeType(tile + TileDiffXY(0, tilediff));
01138
01139 if (GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)) == TRANSPORT_RAIL)
01140 m_railroad[bindex + (tilediff * (size_x - 1))] |= (GetRailType(tile + TileDiffXY(0, tilediff)) << 6);
01141 }
01142 break;
01143 default:
01144 break;
01145 }
01146 if (tunnelbridge_error) {
01147
01148 m_railroad[bindex] = 0;
01149 m_signals[bindex] = 0;
01150 } else {
01151 SB(m_tiletype[bindex], 0, 4, CP_TILE_TUNNELBRIDGE);
01152 SB(m_tiletype[bindex], 4, 1, IsTunnelTile(tile));
01153 }
01154 }
01155 else {
01156
01157 }
01158 }
01159 }
01160 break;
01161
01162 default:
01163 SB(m_tiletype[bindex], 0, 4, CP_TILE_CLEAR);
01164
01165 break;
01166 }
01167 bindex++;
01168 success = true;
01169
01170 }
01171
01172 if (success) SndPlayTileFx(SND_1F_SPLAT, end);
01173 }
01174
01175
01176 uint CopyPaste::GetHeight(uint baseh, uint index)
01177 {
01178 return baseh + m_heightmap[index];
01179 }
01180
01181 Slope CopyPaste::GetSlope(uint index)
01182 {
01183 int a = m_heightmap[index];
01184 int min = a;
01185 int b = m_heightmap[index + 1];
01186 if (min > b) min = b;
01187 int c = m_heightmap[index + GetWidth()];
01188 if (min > c) min = c;
01189 int d = m_heightmap[index + GetWidth() + 1];
01190 if (min > d) min = d;
01191
01192 uint r = SLOPE_FLAT;
01193
01194 if (a -= min != 0) r += (--a << 4) + SLOPE_N;
01195 if (c -= min != 0) r += (--c << 4) + SLOPE_E;
01196 if (d -= min != 0) r += (--d << 4) + SLOPE_S;
01197 if (b -= min != 0) r += (--b << 4) + SLOPE_W;
01198
01199 return (Slope)r;
01200 }
01201
01202 TrackBits CopyPaste::GetCPTrackBits(uint index)
01203 {
01204 if (GetCPTileType(index) == CP_TILE_RAIL) {
01205 if (GetCPMinorTileType(index) != RAIL_TILE_DEPOT) return (TrackBits)GB(m_railroad[index], 0, 6);
01206 } else if (GetCPTileType(index) == CP_TILE_ROAD) {
01207 if (GetCPMinorTileType(index) == ROAD_TILE_CROSSING) return GB(m_railroad[index], 0, 4) == ROAD_X ? TRACK_BIT_Y : TRACK_BIT_X;
01208 }
01209 return TRACK_BIT_NONE;
01210 }
01211
01213 CopyPaste::CopyPasteTileType CopyPaste::GetCPTileType(uint index)
01214 {
01215 return (CopyPasteTileType)GB(m_tiletype[index], 0, 4);
01216 }
01217
01219 uint CopyPaste::GetCPMinorTileType(uint index)
01220 {
01221 return GB(m_tiletype[index], 4, 4);
01222 }
01228 template <typename T>
01229 static void rotate(T* b, int w, int h, int dir)
01230 {
01231 int i, len, x, y, src, target;
01232
01233
01234 len = w * h;
01235 T* tmp = MallocT<T>(len);
01236
01237
01238 for (i = 0; i < len; i++)
01239 tmp[i] = b[i];
01240
01241
01242 if (dir == 1) {
01243 for (y = 0; y < h; y++) {
01244 for (x = 0; x < w; x++) {
01245
01246
01247
01248 src = (y * w) + x;
01249 target = (((w - 1) - x) * h) + y;
01250 b[target] = tmp[src];
01251 }
01252 }
01253 }
01254 else if (dir == -1) {
01255
01256 for (y = 0; y < h; y++) {
01257 for (x = 0; x < w; x++) {
01258
01259
01260
01261 src = (y * w) + x;
01262 target = (x * h) + (h - 1 - y);
01263 b[target] = tmp[src];
01264 }
01265 }
01266 }
01267
01268
01269 free(tmp);
01270 }
01271
01277 template <typename T>
01278 static void mirror(T* b, int w, int h, Axis axis)
01279 {
01280 int x, y;
01281
01282
01283 switch (axis) {
01284 case AXIS_X:
01285 for (y = 0; y < h; y++) {
01286 for (x = 0; x < (w / 2); x++) {
01287 Swap<T>(b[x + (y * w)], b[(w - x - 1) + (y * w)]);
01288 }
01289 }
01290 break;
01291 case AXIS_Y:
01292 for (y = 0; y < (h / 2); y++) {
01293 for (x = 0; x < w; x++) {
01294 Swap<T>(b[x + (y * w)], b[ x + ((h - y - 1) * w)]);
01295 }
01296 }
01297 break;
01298 default: NOT_REACHED();
01299 }
01300 }
01301
01307 void CopyPaste::RotateSelectionCW()
01308 {
01309 int w = GetWidth() - 1;
01310 int h = GetHeight() - 1;
01311 uint8 storelocation;
01312 int index, len;
01313
01314 uint8 tmp8;
01315 uint16 tmp16;
01316
01317
01318 rotate(m_heightmap, GetWidth(), GetHeight(), 1);
01319 rotate(m_terrain_needed, GetWidth(), GetHeight(), 1);
01320 rotate(m_tiletype, w, h, 1);
01321 rotate(m_railroad, w, h, 1);
01322 rotate(m_signals,w, h, 1);
01323
01324
01325 len = w * h;
01326 for (index = 0; index < len; index++) {
01327
01328 switch (GetCPTileType(index)) {
01329 case CP_TILE_RAIL:
01330 if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
01331
01332 SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
01333 break;
01334 }
01335
01336
01337 tmp8 = m_railroad[index];
01338
01339 m_railroad[index] &= ~((1 << 6) - 1);
01340
01341
01342
01343 if (tmp8 & TRACK_BIT_Y) m_railroad[index] |= TRACK_BIT_X;
01344 if (tmp8 & TRACK_BIT_X) m_railroad[index] |= TRACK_BIT_Y;
01345 if (tmp8 & TRACK_BIT_LEFT) m_railroad[index] |= TRACK_BIT_UPPER;
01346 if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_LOWER;
01347 if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_LEFT;
01348 if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_RIGHT;
01349
01350 if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
01351
01352
01353 tmp16 = m_signals[index];
01354
01355 ClrBit(m_signals[index], 0);
01356 ClrBit(m_signals[index], 1);
01357
01358 storelocation = 6;
01359
01360 if ((m_railroad[index] & TRACK_BIT_Y) && HasBit(tmp16, 0)) {
01361 SetBit(m_signals[index], 0);
01362 }
01363 if ((m_railroad[index] & TRACK_BIT_X) && HasBit(tmp16, 0)) {
01364 SetBit(m_signals[index], 0);
01365 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01366 }
01367 if ((m_railroad[index] & TRACK_BIT_RIGHT) && HasBit(tmp16, 0)) {
01368 SetBit(m_signals[index], 1);
01369 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01370 storelocation = 8;
01371 }
01372 if ((m_railroad[index] & TRACK_BIT_LEFT) && HasBit(tmp16, 1)) {
01373 SetBit(m_signals[index], 0);
01374 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01375 if (storelocation == 8) {
01376
01377 SwapSignalInfo(index);
01378 }
01379 storelocation = 8;
01380 }
01381 if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 0)) {
01382 SetBit(m_signals[index], 0);
01383 }
01384 if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 1)) {
01385 SetBit(m_signals[index], 1);
01386 }
01387
01388 }
01389 break;
01390
01391 case CP_TILE_ROAD:
01392 if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
01393
01394 SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
01395 break;
01396 }
01397
01398
01399 if (m_railroad[index] & ROAD_Y && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
01400 SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
01401 }
01402
01403 SB(m_railroad[index], 0, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 0, 4), DIAGDIRDIFF_90RIGHT));
01404
01405 SB(m_railroad[index], 4, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 4, 4), DIAGDIRDIFF_90RIGHT));
01406
01407
01408 break;
01409
01410 case CP_TILE_TUNNELBRIDGE:
01411
01412 SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
01413
01414 break;
01415
01416 default: break;
01417 }
01418
01419 }
01420
01421 Swap(this->m_width, this->m_height);
01422 }
01423
01429 void CopyPaste::RotateSelectionCCW()
01430 {
01431 int w = GetWidth() - 1;
01432 int h = GetHeight() - 1;
01433 uint8 storelocation;
01434 int index, len;
01435
01436 uint8 tmp8;
01437 uint16 tmp16;
01438
01439
01440 rotate(m_heightmap, GetWidth(), GetHeight(), -1);
01441 rotate(m_terrain_needed, GetWidth(), GetHeight(), -1);
01442 rotate(m_tiletype, w, h, -1);
01443 rotate(m_railroad, w, h, -1);
01444 rotate(m_signals,w, h, -1);
01445
01446
01447 len = w * h;
01448 for (index = 0; index < len; index++) {
01449 switch (GetCPTileType(index)) {
01450 case CP_TILE_RAIL:
01451 if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
01452
01453 SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
01454 break;
01455 }
01456 tmp8 = m_railroad[index];
01457
01458 m_railroad[index] &= ~63U;
01459
01460 if (tmp8 & TRACK_BIT_Y) m_railroad[index] |= TRACK_BIT_X;
01461 if (tmp8 & TRACK_BIT_X) m_railroad[index] |= TRACK_BIT_Y;
01462 if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_UPPER;
01463 if (tmp8 & TRACK_BIT_LEFT) m_railroad[index] |= TRACK_BIT_LOWER;
01464 if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_LEFT;
01465 if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_RIGHT;
01466 if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
01467
01468
01469 tmp16 = m_signals[index];
01470
01471 ClrBit(m_signals[index], 0);
01472 ClrBit(m_signals[index], 1);
01473
01474 storelocation = 6;
01475
01476 if (m_railroad[index] & TRACK_BIT_Y && HasBit(tmp16, 0)) {
01477 SetBit(m_signals[index], 0);
01478 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01479 }
01480 if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
01481 SetBit(m_signals[index], 0);
01482 }
01483 if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 0)) {
01484 SetBit(m_signals[index], 0);
01485 storelocation = 8;
01486 }
01487 if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 1)) {
01488 SetBit(m_signals[index], 1);
01489 storelocation = 8;
01490 }
01491 if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 0)) {
01492 SetBit(m_signals[index], 1);
01493 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01494 storelocation = 8;
01495 }
01496 if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 1)) {
01497 SetBit(m_signals[index], 0);
01498 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01499 if (storelocation == 8) {
01500
01501 SwapSignalInfo(index);
01502 }
01503 storelocation = 8;
01504 }
01505 }
01506 break;
01507
01508 case CP_TILE_ROAD:
01509 if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
01510
01511 SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
01512 break;
01513 }
01514 if (m_railroad[index] & ROAD_X && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
01515 SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
01516 }
01517
01518 SB(m_railroad[index], 0, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 0, 4), DIAGDIRDIFF_90LEFT));
01519 SB(m_railroad[index], 4, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 4, 4), DIAGDIRDIFF_90LEFT));
01520
01521 break;
01522
01523 case CP_TILE_TUNNELBRIDGE:
01524 SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
01525 break;
01526 default: break;
01527 }
01528
01529 }
01530
01531 Swap(this->m_height, this->m_width);
01532 }
01533
01534 void CopyPaste::MirrorSelectionHorizontal()
01535 {
01536 int w = GetWidth() - 1;
01537 int h = GetHeight() - 1;
01538 uint8 storelocation;
01539 int index, len;
01540
01541 uint8 tmp8;
01542 uint16 tmp16;
01543
01544
01545 mirror(m_heightmap, GetWidth(), GetHeight(), AXIS_X);
01546 mirror(m_terrain_needed, GetWidth(), GetHeight(), AXIS_X);
01547 mirror(m_tiletype, w, h, AXIS_X);
01548 mirror(m_railroad, w, h, AXIS_X);
01549 mirror(m_signals,w, h, AXIS_X);
01550
01551
01552 len = w * h;
01553 for (index = 0; index < len; index++) {
01554 switch (GetCPTileType(index)) {
01555 case CP_TILE_RAIL:
01556 if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
01557
01558 tmp8 = GB(m_railroad[index], 0, 2);
01559 if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01560 SB(m_railroad[index], 0, 2, tmp8);
01561 break;
01562 }
01563 tmp8 = m_railroad[index];
01564
01565 m_railroad[index] &= ~63U;
01566
01567 if (tmp8 & TRACK_BIT_X) m_railroad[index] |= TRACK_BIT_X;
01568 if (tmp8 & TRACK_BIT_Y) m_railroad[index] |= TRACK_BIT_Y;
01569 if (tmp8 & TRACK_BIT_LEFT) m_railroad[index] |= TRACK_BIT_UPPER;
01570 if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_LOWER;
01571 if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_LEFT;
01572 if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_RIGHT;
01573
01574 if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
01575
01576
01577 tmp16 = m_signals[index];
01578
01579 storelocation = 6;
01580 if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
01581 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01582 }
01583 if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 0)) {
01584 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01585 storelocation = 8;
01586 }
01587 if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 1)) {
01588 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01589 storelocation = 8;
01590 }
01591 if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 0)) {
01592 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01593 storelocation = 8;
01594 }
01595 if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 1)) {
01596 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01597 storelocation = 8;
01598 }
01599 }
01600 break;
01601
01602 case CP_TILE_ROAD:
01603 if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
01604
01605 tmp8 = GB(m_railroad[index], 0, 2);
01606 if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01607 SB(m_railroad[index], 0, 2, tmp8);
01608 break;
01609 }
01610
01611
01612 tmp8 = m_railroad[index];
01613 m_railroad[index] &= ~(ROAD_NE | ROAD_SW | ((ROAD_NE | ROAD_SW) << 4));
01614 if ((tmp8 & ROAD_NE) > 0) m_railroad[index] |= ROAD_SW;
01615 if ((tmp8 & ROAD_SW) > 0) m_railroad[index] |= ROAD_NE;
01616 if ((tmp8 & (ROAD_NE << 4)) > 0) m_railroad[index] |= (ROAD_SW << 4);
01617 if ((tmp8 & (ROAD_SW << 4)) > 0) m_railroad[index] |= (ROAD_NE << 4);
01618
01619 if ((tmp8 & ROAD_X) && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
01620 SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
01621 }
01622
01623 break;
01624
01625 case CP_TILE_TUNNELBRIDGE:
01626
01627
01628
01629 tmp8 = GB(m_railroad[index], 0, 2);
01630 if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01631 SB(m_railroad[index], 0, 2, tmp8);
01632
01633 break;
01634
01635 default: break;
01636 }
01637
01638 }
01639 }
01640
01641 void CopyPaste::MirrorSelectionVertical()
01642 {
01643 int w = GetWidth() - 1;
01644 int h = GetHeight() - 1;
01645 uint8 storelocation;
01646 int index, len;
01647
01648 uint8 tmp8;
01649 uint16 tmp16;
01650
01651
01652 mirror(m_heightmap, GetWidth(), GetHeight(), AXIS_Y);
01653 mirror(m_terrain_needed, GetWidth(), GetHeight(), AXIS_Y);
01654 mirror(m_tiletype, w, h, AXIS_Y);
01655 mirror(m_railroad, w, h, AXIS_Y);
01656 mirror(m_signals,w, h, AXIS_Y);
01657
01658
01659 len = w * h;
01660 for (index = 0; index < len; index++) {
01661 switch (GetCPTileType(index)) {
01662 case CP_TILE_RAIL:
01663 if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
01664
01665 tmp8 = GB(m_railroad[index], 0, 2);
01666 if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01667 SB(m_railroad[index], 0, 2, tmp8);
01668 break;
01669 }
01670 tmp8 = m_railroad[index];
01671
01672 m_railroad[index] &= ~63U;
01673
01674 if (tmp8 & TRACK_BIT_X) m_railroad[index] |= TRACK_BIT_X;
01675 if (tmp8 & TRACK_BIT_Y) m_railroad[index] |= TRACK_BIT_Y;
01676 if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_UPPER;
01677 if (tmp8 & TRACK_BIT_LEFT) m_railroad[index] |= TRACK_BIT_LOWER;
01678 if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_LEFT;
01679 if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_RIGHT;
01680 if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
01681
01682
01683 tmp16 = m_signals[index];
01684
01685 ClrBit(m_signals[index], 0);
01686 ClrBit(m_signals[index], 1);
01687
01688 storelocation = 6;
01689 if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
01690 SetBit(m_signals[index], 0);
01691 }
01692 if (m_railroad[index] & TRACK_BIT_Y && HasBit(tmp16, 0)) {
01693 SetBit(m_signals[index], 0);
01694 SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01695 }
01696 if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 0)) {
01697 SetBit(m_signals[index], 1);
01698 storelocation = 8;
01699 }
01700 if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 1)) {
01701 SetBit(m_signals[index], 0);
01702 if (storelocation == 8) {
01703
01704 SwapSignalInfo(index);
01705 }
01706 storelocation = 8;
01707 }
01708 if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 0)) {
01709 SetBit(m_signals[index], 1);
01710 storelocation = 8;
01711 }
01712 if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 1)) {
01713 SetBit(m_signals[index], 0);
01714 if (storelocation == 8) {
01715
01716 SwapSignalInfo(index);
01717 }
01718 storelocation = 8;
01719 }
01720
01721 }
01722 break;
01723
01724 case CP_TILE_ROAD:
01725 if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
01726
01727 tmp8 = GB(m_railroad[index], 0, 2);
01728 if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01729 SB(m_railroad[index], 0, 2, tmp8);
01730 break;
01731 }
01732
01733
01734 tmp8 = m_railroad[index];
01735 m_railroad[index] &= ~(ROAD_NW | ROAD_SE | ((ROAD_NW | ROAD_SE) << 4));
01736 if ((tmp8 & ROAD_NW) > 0) m_railroad[index] |= ROAD_SE;
01737 if ((tmp8 & ROAD_SE) > 0) m_railroad[index] |= ROAD_NW;
01738 if ((tmp8 & (ROAD_NW << 4)) > 0) m_railroad[index] |= (ROAD_SE << 4);
01739 if ((tmp8 & (ROAD_SE << 4)) > 0) m_railroad[index] |= (ROAD_NW << 4);
01740
01741 if ((tmp8 & ROAD_Y) && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
01742 SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
01743 }
01744
01745 break;
01746
01747 case CP_TILE_TUNNELBRIDGE:
01748
01749 tmp8 = GB(m_railroad[index], 0, 2);
01750 if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01751 SB(m_railroad[index], 0, 2, tmp8);
01752 break;
01753 default: break;
01754 }
01755
01756 }
01757 }
01758
01759