* Draws an image of a whole train * @param v Front vehicle * @param r Rect to draw at * @param selection Selected vehicle to draw a frame around * @param skip Number of pixels to skip at the front (for scrolling) * @param drag_dest The vehicle another one is dragged over, \c VehicleID::Invalid() if none. */
| 96 | * @param drag_dest The vehicle another one is dragged over, \c VehicleID::Invalid() if none. |
| 97 | */ |
| 98 | void DrawTrainImage(const Train *v, const Rect &r, VehicleID selection, EngineImageType image_type, int skip, VehicleID drag_dest) |
| 99 | { |
| 100 | bool rtl = _current_text_dir == TD_RTL; |
| 101 | Direction dir = rtl ? DIR_E : DIR_W; |
| 102 | |
| 103 | DrawPixelInfo tmp_dpi; |
| 104 | /* Position of highlight box */ |
| 105 | int highlight_l = 0; |
| 106 | int highlight_r = 0; |
| 107 | int max_width = r.Width(); |
| 108 | |
| 109 | if (!FillDrawPixelInfo(&tmp_dpi, r)) return; |
| 110 | |
| 111 | { |
| 112 | AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); |
| 113 | |
| 114 | bool do_overlays = ShowCargoIconOverlay(); |
| 115 | /* List of overlays, only used if cargo icon overlays are enabled. */ |
| 116 | static std::vector<CargoIconOverlay> overlays; |
| 117 | |
| 118 | int px = rtl ? max_width + skip : -skip; |
| 119 | int y = r.Height() / 2; |
| 120 | bool sel_articulated = false; |
| 121 | bool dragging = (drag_dest != VehicleID::Invalid()); |
| 122 | bool drag_at_end_of_train = (drag_dest == v->index); // Head index is used to mark dragging at end of train. |
| 123 | for (; v != nullptr && (rtl ? px > 0 : px < max_width); v = v->Next()) { |
| 124 | if (dragging && !drag_at_end_of_train && drag_dest == v->index) { |
| 125 | /* Highlight the drag-and-drop destination inside the train. */ |
| 126 | int drag_hlight_width = HighlightDragPosition(px, max_width, y, selection, _cursor.vehchain); |
| 127 | px += rtl ? -drag_hlight_width : drag_hlight_width; |
| 128 | } |
| 129 | |
| 130 | Point offset; |
| 131 | int width = Train::From(v)->GetDisplayImageWidth(&offset); |
| 132 | |
| 133 | if (rtl ? px + width > 0 : px - width < max_width) { |
| 134 | PaletteID pal = v->vehstatus.Test(VehState::Crashed) ? PALETTE_CRASH : GetVehiclePalette(v); |
| 135 | VehicleSpriteSeq seq; |
| 136 | v->GetImage(dir, image_type, &seq); |
| 137 | seq.Draw(px + (rtl ? -offset.x : offset.x), y + offset.y, pal, v->vehstatus.Test(VehState::Crashed)); |
| 138 | } |
| 139 | |
| 140 | if (!v->IsArticulatedPart()) sel_articulated = false; |
| 141 | |
| 142 | if (v->index == selection) { |
| 143 | /* Set the highlight position */ |
| 144 | highlight_l = rtl ? px - width : px; |
| 145 | highlight_r = rtl ? px - 1 : px + width - 1; |
| 146 | sel_articulated = true; |
| 147 | } else if ((_cursor.vehchain && highlight_r != 0) || sel_articulated) { |
| 148 | if (rtl) { |
| 149 | highlight_l -= width; |
| 150 | } else { |
| 151 | highlight_r += width; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | if (do_overlays) AddCargoIconOverlay(overlays, px, width, v); |
no test coverage detected