* Calculates height difference between one tile and another. * Multiplies the result to suit the standard given by #TILE_HEIGHT_STEP. * * To correctly get the height difference we need the direction we are dragging * in, as well as with what kind of tool we are dragging. For example a horizontal * autorail tool that starts in bottom and ends at the top of a tile will need the * maximum of SW
| 2957 | * @return Height difference between two tiles. The tile measurement tool utilizes this value in its tooltip. |
| 2958 | */ |
| 2959 | static int CalcHeightdiff(HighLightStyle style, uint distance, TileIndex start_tile, TileIndex end_tile) |
| 2960 | { |
| 2961 | bool swap = SwapDirection(style, start_tile, end_tile); |
| 2962 | uint h0, h1; // Start height and end height. |
| 2963 | |
| 2964 | if (start_tile == end_tile) return 0; |
| 2965 | if (swap) std::swap(start_tile, end_tile); |
| 2966 | |
| 2967 | switch (style & HT_DRAG_MASK) { |
| 2968 | case HT_RECT: |
| 2969 | /* In the case of an area we can determine whether we were dragging south or |
| 2970 | * east by checking the X-coordinates of the tiles */ |
| 2971 | if (TileX(end_tile) > TileX(start_tile)) { |
| 2972 | /* Dragging south does not need to change the start tile. */ |
| 2973 | end_tile = TileAddByDir(end_tile, DIR_S); |
| 2974 | } else { |
| 2975 | /* Dragging east. */ |
| 2976 | start_tile = TileAddByDir(start_tile, DIR_SW); |
| 2977 | end_tile = TileAddByDir(end_tile, DIR_SE); |
| 2978 | } |
| 2979 | [[fallthrough]]; |
| 2980 | |
| 2981 | case HT_POINT: |
| 2982 | h0 = TileHeight(start_tile); |
| 2983 | h1 = TileHeight(end_tile); |
| 2984 | break; |
| 2985 | default: { // All other types, this is mostly only line/autorail |
| 2986 | static const HighLightStyle flip_style_direction[] = { |
| 2987 | HT_DIR_X, HT_DIR_Y, HT_DIR_HL, HT_DIR_HU, HT_DIR_VR, HT_DIR_VL |
| 2988 | }; |
| 2989 | static const std::pair<TileIndexDiffC, TileIndexDiffC> start_heightdiff_line_by_dir[] = { |
| 2990 | { {1, 0}, {1, 1} }, // HT_DIR_X |
| 2991 | { {0, 1}, {1, 1} }, // HT_DIR_Y |
| 2992 | { {1, 0}, {0, 0} }, // HT_DIR_HU |
| 2993 | { {1, 0}, {1, 1} }, // HT_DIR_HL |
| 2994 | { {1, 0}, {1, 1} }, // HT_DIR_VL |
| 2995 | { {0, 1}, {1, 1} }, // HT_DIR_VR |
| 2996 | }; |
| 2997 | static const std::pair<TileIndexDiffC, TileIndexDiffC> end_heightdiff_line_by_dir[] = { |
| 2998 | { {0, 1}, {0, 0} }, // HT_DIR_X |
| 2999 | { {1, 0}, {0, 0} }, // HT_DIR_Y |
| 3000 | { {0, 1}, {0, 0} }, // HT_DIR_HU |
| 3001 | { {1, 1}, {0, 1} }, // HT_DIR_HL |
| 3002 | { {1, 0}, {0, 0} }, // HT_DIR_VL |
| 3003 | { {0, 0}, {0, 1} }, // HT_DIR_VR |
| 3004 | }; |
| 3005 | static_assert(std::size(start_heightdiff_line_by_dir) == HT_DIR_END); |
| 3006 | static_assert(std::size(end_heightdiff_line_by_dir) == HT_DIR_END); |
| 3007 | |
| 3008 | distance %= 2; // we're only interested if the distance is even or uneven |
| 3009 | style &= HT_DIR_MASK; |
| 3010 | assert(style < HT_DIR_END); |
| 3011 | |
| 3012 | /* To handle autorail, we do some magic to be able to use a lookup table. |
| 3013 | * Firstly if we drag the other way around, we switch start&end, and if needed |
| 3014 | * also flip the drag-position. Eg if it was on the left, and the distance is even |
| 3015 | * that means the end, which is now the start is on the right */ |
| 3016 | if (swap && distance == 0) style = flip_style_direction[style]; |
no test coverage detected