Changeset - r13808:32b982f51e30
[Not reviewed]
master
0 2 0
rubidium - 15 years ago 2009-11-29 19:31:23
rubidium@openttd.org
(svn r18344) -Change [FS#2923]: do not split up articulated vehicles in the train details view. If an articulated vehicle it too 'wide' draw the information on the next line and if there are multiple cargos split that over multiple lines too. Based on work by frosch123.
2 files changed with 153 insertions and 62 deletions:
0 comments (0 inline, 0 general)
src/lang/english.txt
Show inline comments
 
@@ -2933,6 +2933,7 @@ STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_Y
 
STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS                         :{BLACK}Reliability: {LTBLUE}{COMMA}%  {BLACK}Breakdowns since last service: {LTBLUE}{COMMA}
 

	
 
STR_VEHICLE_INFO_BUILT_VALUE                                    :{LTBLUE}{ENGINE} {BLACK}Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY}
 
STR_VEHICLE_INFO_NO_CAPACITY                                    :{BLACK}Capacity: {LTBLUE}None
 
STR_VEHICLE_INFO_CAPACITY                                       :{BLACK}Capacity: {LTBLUE}{CARGO}{4:STRING}
 
STR_VEHICLE_INFO_CAPACITY_MULT                                  :{BLACK}Capacity: {LTBLUE}{CARGO}{4:STRING} (x{5:NUM})
 
STR_VEHICLE_INFO_CAPACITY_CAPACITY                              :{BLACK}Capacity: {LTBLUE}{CARGO}, {CARGO}{STRING}
src/train_gui.cpp
Show inline comments
 
@@ -122,28 +122,52 @@ void DrawTrainImage(const Train *v, int 
 
	_cur_dpi = old_dpi;
 
}
 

	
 
/** Helper struct for the cargo details information */
 
struct CargoSummaryItem {
 
	CargoID cargo;    ///< The cargo that is carried
 
	StringID subtype; ///< STR_EMPTY if none
 
	uint capacity;    ///< Amount that can be carried
 
	uint amount;      ///< Amount that is carried
 
	StationID source; ///< One of the source stations
 

	
 
	/** Used by CargoSummary::Find() and similiar functions */
 
	FORCEINLINE bool operator != (const CargoSummaryItem &other) const
 
	{
 
		return this->cargo != other.cargo || this->subtype != other.subtype;
 
	}
 
};
 

	
 
enum {
 
	TRAIN_DETAILS_MIN_INDENT = 32, ///< Minimum indent level in the train details window
 
	TRAIN_DETAILS_MAX_INDENT = 72, ///< Maximum indent level in the train details window; wider than this and we start on a new line
 
};
 

	
 
/** Container for the cargo summary information. */
 
typedef SmallVector<CargoSummaryItem, 2> CargoSummary;
 
/** Reused container of cargo details */
 
static CargoSummary _cargo_summary;
 

	
 
/**
 
 * Draw the details cargo tab for the given vehicle at the given position
 
 *
 
 * @param v     current vehicle
 
 * @param item  Data to draw
 
 * @param left  The left most coordinate to draw
 
 * @param right The right most coordinate to draw
 
 * @param y     The y coordinate
 
 */
 
static void TrainDetailsCargoTab(const Vehicle *v, int left, int right, int y)
 
static void TrainDetailsCargoTab(const CargoSummaryItem *item, int left, int right, int y)
 
{
 
	if (v->cargo_cap != 0) {
 
		StringID str = STR_VEHICLE_DETAILS_CARGO_EMPTY;
 
	StringID str = STR_VEHICLE_DETAILS_CARGO_EMPTY;
 

	
 
		if (!v->cargo.Empty()) {
 
			SetDParam(0, v->cargo_type);
 
			SetDParam(1, v->cargo.Count());
 
			SetDParam(2, v->cargo.Source());
 
			SetDParam(3, _settings_game.vehicle.freight_trains);
 
			str = FreightWagonMult(v->cargo_type) > 1 ? STR_VEHICLE_DETAILS_CARGO_FROM_MULT : STR_VEHICLE_DETAILS_CARGO_FROM;
 
		}
 
		DrawString(left, right, y, str);
 
	if (item->amount > 0) {
 
		SetDParam(0, item->cargo);
 
		SetDParam(1, item->amount);
 
		SetDParam(2, item->source);
 
		SetDParam(3, _settings_game.vehicle.freight_trains);
 
		str = FreightWagonMult(item->cargo) > 1 ? STR_VEHICLE_DETAILS_CARGO_FROM_MULT : STR_VEHICLE_DETAILS_CARGO_FROM;
 
	}
 

	
 
	DrawString(left, right, y, str);
 
}
 

	
 
/**
 
@@ -171,20 +195,65 @@ static void TrainDetailsInfoTab(const Ve
 
/**
 
 * Draw the details capacity tab for the given vehicle at the given position
 
 *
 
 * @param v     current vehicle
 
 * @param item  Data to draw
 
 * @param left  The left most coordinate to draw
 
 * @param right The right most coordinate to draw
 
 * @param y     The y coordinate
 
 */
 
static void TrainDetailsCapacityTab(const Vehicle *v, int left, int right, int y)
 
static void TrainDetailsCapacityTab(const CargoSummaryItem *item, int left, int right, int y)
 
{
 
	SetDParam(0, item->cargo);
 
	SetDParam(1, item->capacity);
 
	SetDParam(4, item->subtype);
 
	SetDParam(5, _settings_game.vehicle.freight_trains);
 
	DrawString(left, right, y, FreightWagonMult(item->cargo) > 1 ? STR_VEHICLE_INFO_CAPACITY_MULT : STR_VEHICLE_INFO_CAPACITY);
 
}
 

	
 
/**
 
 * Collects the cargo transportet
 
 * @param v Vehicle to process
 
 * @param summary Space for the result
 
 */
 
static void GetCargoSummaryOfArticulatedVehicle(const Train *v, CargoSummary *summary)
 
{
 
	if (v->cargo_cap != 0) {
 
		SetDParam(0, v->cargo_type);
 
		SetDParam(1, v->cargo_cap);
 
		SetDParam(4, GetCargoSubtypeText(v));
 
		SetDParam(5, _settings_game.vehicle.freight_trains);
 
		DrawString(left, right, y, FreightWagonMult(v->cargo_type) > 1 ? STR_VEHICLE_INFO_CAPACITY_MULT : STR_VEHICLE_INFO_CAPACITY);
 
	}
 
	summary->Clear();
 
	do {
 
		if (v->cargo_cap == 0) continue;
 

	
 
		CargoSummaryItem new_item;
 
		new_item.cargo = v->cargo_type;
 
		new_item.subtype = GetCargoSubtypeText(v);
 

	
 
		CargoSummaryItem *item = summary->Find(new_item);
 
		if (item == summary->End()) {
 
			item = summary->Append();
 
			item->cargo = new_item.cargo;
 
			item->subtype = new_item.subtype;
 
			item->capacity = 0;
 
			item->amount = 0;
 
			item->source = INVALID_STATION;
 
		}
 

	
 
		item->capacity += v->cargo_cap;
 
		item->amount += v->cargo.Count();
 
		if (item->source == INVALID_STATION) item->source = v->cargo.Source();
 
	} while ((v = v->Next()) != NULL && v->IsArticulatedPart());
 
}
 

	
 
/**
 
 * Get the length of an articulated vehicle.
 
 * @param v the vehicle to get the length of.
 
 * @return the length in pixels.
 
 */
 
static uint GetLengthOfArticulatedVehicle(const Train *v)
 
{
 
	uint length = 0;
 

	
 
	do {
 
		length += v->GetDisplayImageWidth();
 
	} while ((v = v->Next()) != NULL && v->IsArticulatedPart());
 

	
 
	return length;
 
}
 

	
 
/**
 
@@ -213,8 +282,12 @@ int GetTrainDetailsWndVScroll(VehicleID 
 
		}
 
		num++; // needs one more because first line is description string
 
	} else {
 
		for (const Train *v = Train::Get(veh_id); v != NULL; v = v->Next()) {
 
			if (!v->IsArticulatedPart() || v->cargo_cap != 0) num++;
 
		for (const Train *v = Train::Get(veh_id); v != NULL; v = v->GetNextVehicle()) {
 
			GetCargoSummaryOfArticulatedVehicle(v, &_cargo_summary);
 
			num += max(1u, _cargo_summary.Length());
 

	
 
			uint length = GetLengthOfArticulatedVehicle(v);
 
			if (length > TRAIN_DETAILS_MAX_INDENT) num++;
 
		}
 
	}
 

	
 
@@ -238,53 +311,70 @@ void DrawTrainDetails(const Train *v, in
 
	if (det_tab != TDW_TAB_TOTALS) {
 
		bool rtl = _dynlang.text_dir == TD_RTL;
 
		Direction dir = rtl ? DIR_E : DIR_W;
 
		const Train *u = v;
 
		int x = rtl ? right : left;
 
		int sprite_y_offset = 4 + (FONT_HEIGHT_NORMAL - 10) / 2;
 
		for (;;) {
 
			if (--vscroll_pos < 0 && vscroll_pos >= -vscroll_cap) {
 
				int px = x;
 
		int line_height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
 
		for (; v != NULL && vscroll_pos > -vscroll_cap; v = v->GetNextVehicle()) {
 
			GetCargoSummaryOfArticulatedVehicle(v, &_cargo_summary);
 

	
 
				u = v;
 
				do {
 
					Point offset;
 
					int width = u->GetDisplayImageWidth(&offset);
 
					SpriteID pal = (u->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(u);
 
					DrawSprite(u->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), y + sprite_y_offset + offset.y);
 
					px += rtl ? -width : width;
 
					u = u->Next();
 
				} while (u != NULL && u->IsArticulatedPart() && u->cargo_cap == 0);
 
			/* Draw sprites */
 
			int dx = 0;
 
			int px = x;
 
			const Train *u = v;
 
			do {
 
				Point offset;
 
				int width = u->GetDisplayImageWidth(&offset);
 
				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
 
					SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
 
					DrawSprite(u->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + offset.y);
 
				}
 
				px += rtl ? -width : width;
 
				dx += width;
 
				u = u->Next();
 
			} while (u != NULL && u->IsArticulatedPart());
 

	
 
				px += rtl ? -2 : 2;
 
				int py = y;
 
				switch (det_tab) {
 
					default: NOT_REACHED();
 
			bool separate_sprite_row = (dx > TRAIN_DETAILS_MAX_INDENT);
 
			if (separate_sprite_row) {
 
				vscroll_pos--;
 
				dx = 0;
 
			}
 

	
 
					case TDW_TAB_CARGO:
 
						TrainDetailsCargoTab(v, rtl ? left : px, rtl ? px : right, py);
 
						break;
 

	
 
					case TDW_TAB_INFO:
 
						/* Only show name and value for the 'real' part */
 
						if (!v->IsArticulatedPart()) {
 
							TrainDetailsInfoTab(v, rtl ? left : px, rtl ? px : right, py);
 
						}
 
						break;
 
			uint num_lines = max(1u, _cargo_summary.Length());
 
			for (uint i = 0; i < num_lines; i++) {
 
				int sprite_width = max<int>(dx, TRAIN_DETAILS_MIN_INDENT) + 3;
 
				int data_left  = left + (rtl ? 0 : sprite_width);
 
				int data_right = right - (rtl ? sprite_width : 0);
 
				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
 
					int py = y - line_height * vscroll_pos;
 
					if (i > 0 || separate_sprite_row) {
 
						if (vscroll_pos != 0) GfxFillRect(left, py - WD_MATRIX_TOP - 1, right, py - WD_MATRIX_TOP, _colour_gradient[COLOUR_GREY][5]);
 
					}
 
					switch (det_tab) {
 
						case TDW_TAB_CARGO:
 
							if (i < _cargo_summary.Length()) {
 
								TrainDetailsCargoTab(&_cargo_summary[i], data_left, data_right, py);
 
							} else {
 
								DrawString(data_left, data_right, py, STR_QUANTITY_N_A, TC_LIGHT_BLUE);
 
							}
 
							break;
 

	
 
					case TDW_TAB_CAPACITY:
 
						TrainDetailsCapacityTab(v, rtl ? left : px, rtl ? px : right, py);
 
						break;
 
				}
 
				y += WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
 
						case TDW_TAB_INFO:
 
							if (i == 0) TrainDetailsInfoTab(v, data_left, data_right, py);
 
							break;
 

	
 
				v = u;
 
			} else {
 
				/* Move to the next line */
 
				do {
 
					v = v->Next();
 
				} while (v != NULL && v->IsArticulatedPart() && v->cargo_cap == 0);
 
						case TDW_TAB_CAPACITY:
 
							if (i < _cargo_summary.Length()) {
 
								TrainDetailsCapacityTab(&_cargo_summary[i], data_left, data_right, py);
 
							} else {
 
								DrawString(data_left, data_right, py, STR_VEHICLE_INFO_NO_CAPACITY);
 
							}
 
							break;
 

	
 
						default: NOT_REACHED();
 
					}
 
				}
 
				vscroll_pos--;
 
			}
 
			if (v == NULL) return;
 
		}
 
	} else {
 
		CargoArray act_cargo;
0 comments (0 inline, 0 general)