Пример #1
0
void ShipInfoPanel::DrawShipStats(const Rectangle &bounds)
{
	// Check that the specified area is big enough.
	if(bounds.Width() < WIDTH)
		return;
	
	// Colors to draw with.
	Color dim = *GameData::Colors().Get("medium");
	Color bright = *GameData::Colors().Get("bright");
	const Ship &ship = **shipIt;
	const Font &font = FontSet::Get(14);
	
	// Table attributes.
	Table table;
	table.AddColumn(0, Table::LEFT);
	table.AddColumn(WIDTH - 20, Table::RIGHT);
	table.SetUnderline(0, WIDTH - 20);
	table.DrawAt(bounds.TopLeft() + Point(10., 8.));
	
	// Draw the ship information.
	table.Draw("ship:", dim);
	table.Draw(font.TruncateMiddle(ship.Name(), WIDTH - 50), bright);
	
	table.Draw("model:", dim);
	table.Draw(ship.ModelName(), bright);
	
	info.DrawAttributes(table.GetRowBounds().TopLeft() - Point(10., 10.));
}
Пример #2
0
void ShipInfoDisplay::DrawAttributes(const Point &topLeft) const
{
	Point point = Draw(topLeft, attributeLabels, attributeValues);
	
	// Get standard colors to draw with.
	Color labelColor = *GameData::Colors().Get("medium");
	Color valueColor = *GameData::Colors().Get("bright");
	
	Table table;
	table.AddColumn(10, Table::LEFT);
	table.AddColumn(WIDTH - 90, Table::RIGHT);
	table.AddColumn(WIDTH - 10, Table::RIGHT);
	table.DrawAt(point);
	table.DrawGap(10.);
	
	table.Advance();
	table.Draw("energy", labelColor);
	table.Draw("heat", labelColor);
	
	for(unsigned i = 0; i < tableLabels.size(); ++i)
	{
		table.Draw(tableLabels[i], labelColor);
		table.Draw(energyTable[i], valueColor);
		table.Draw(heatTable[i], valueColor);
	}
}
Пример #3
0
Point ItemInfoDisplay::Draw(Point point, const vector<string> &labels, const vector<string> &values)
{
	// Add ten pixels of padding at the top.
	point.Y() += 10.;
	
	// Get standard colors to draw with.
	Color labelColor = *GameData::Colors().Get("medium");
	Color valueColor = *GameData::Colors().Get("bright");
	
	Table table;
	// Use 10-pixel margins on both sides.
	table.AddColumn(10, Table::LEFT);
	table.AddColumn(WIDTH - 10, Table::RIGHT);
	table.DrawAt(point);
	
	for(unsigned i = 0; i < labels.size() && i < values.size(); ++i)
	{
		if(labels[i].empty())
		{
			table.DrawGap(10);
			continue;
		}
		
		table.Draw(labels[i], values[i].empty() ? valueColor : labelColor);
		table.Draw(values[i], valueColor);
	}
	return table.GetPoint();
}
Пример #4
0
void VfkStream::ScanHeader(const char *b, Table& table)
{
	int colid = 0;
	while(*b && *b != '\n') {
		if(IsAlpha(*b)) {
			const char *id = b;
			while(IsIdent(*++b))
				;
			Column col;
			col.name = String(id, b);
			try {
				while(*b == ' ')
					b++;
				col.vtype = ERROR_V;
				col.width = Null;
				switch(*b++) {
					case 'N': {
						col.vtype = DOUBLE_V;
						break;
					}
					case 'T': {
						col.vtype = STRING_V;
						if(!IsDigit(*b))
							throw Exc("missing string width");
						col.width = ScanInt(b, &b);
						break;
					}
					case 'D': {
						col.vtype = TIME_V;
						break;
					}
					default: {
						throw Exc(NFormat("invalid data type '%c'", *--b));
					}
				}
				if(colid < table.columns.GetCount()) {
					const Column& old = table.columns[colid];
					if(old.name != col.name)
						throw Exc(NFormat("column name mismatch (%s / %s)", old.name, col.name));
					if(old.vtype != col.vtype)
						throw Exc(NFormat("column type mismatch (%d / %d)", old.vtype, col.vtype));
					if(old.width != col.width)
						throw Exc(NFormat("column width mismatch (%~d / %~d)", old.width, col.width));
				}
				else
					table.AddColumn(col);
				colid++;
			}
			catch(Exc e) {
				throw Exc(NFormat("column '%s': %s", colid, e));
			}
		}
		else
			b++;
	}
}
Пример #5
0
void PreferencesPanel::DrawPlugins()
{
	const Color &back = *GameData::Colors().Get("faint");
	const Color &medium = *GameData::Colors().Get("medium");
	const Color &bright = *GameData::Colors().Get("bright");
	
	Table table;
	table.AddColumn(-115, Table::LEFT);
	table.SetUnderline(-120, 120);
	
	int firstY = -238;
	table.DrawAt(Point(-130, firstY));
	table.DrawUnderline(medium);
	table.Draw("Installed plugins:", bright);
	table.DrawGap(5);
	
	const int MAX_TEXT_WIDTH = 230;
	const Font &font = FontSet::Get(14);
	for(const pair<string, string> &plugin : GameData::PluginAboutText())
	{
		pluginZones.emplace_back(table.GetCenterPoint(), table.GetRowSize(), plugin.first);
		
		bool isSelected = (plugin.first == selectedPlugin);
		if(isSelected || plugin.first == hoverPlugin)
			table.DrawHighlight(back);
		table.Draw(font.TruncateMiddle(plugin.first, MAX_TEXT_WIDTH), isSelected ? bright : medium);
		
		if(isSelected)
		{
			const Sprite *sprite = SpriteSet::Get(plugin.first);
			Point top(15., firstY);
			if(sprite)
			{
				Point center(130., top.Y() + .5 * sprite->Height());
				SpriteShader::Draw(sprite, center);
				top.Y() += sprite->Height() + 10.;
			}
			
			WrappedText wrap(font);
			wrap.SetWrapWidth(MAX_TEXT_WIDTH);
			static const string EMPTY = "(No description given.)";
			wrap.Wrap(plugin.second.empty() ? EMPTY : plugin.second);
			wrap.Draw(top, medium);
		}
	}
}
Пример #6
0
void BankPanel::Draw() const
{
	Table table;
	table.AddColumn(TYPE_X, Table::LEFT);
	table.AddColumn(PRINCIPAL_X, Table::LEFT);
	table.AddColumn(INTEREST_X, Table::LEFT);
	table.AddColumn(TERM_X, Table::LEFT);
	table.AddColumn(PAYMENT_X, Table::LEFT);
	table.AddColumn(170, Table::RIGHT);
	table.SetHighlight(-300, 180);
	table.DrawAt(Point(0., FIRST_Y));
	
	Color back = *GameData::Colors().Get("faint");
	Color unselected = *GameData::Colors().Get("medium");
	Color selected = *GameData::Colors().Get("bright");
	table.DrawUnderline(unselected);
	table.SetColor(selected);
	for(int i = 0; i < 6; ++i)
		table.Draw(HEADING[i]);
	table.DrawGap(5);
	
	// Figure out the total payments and principal (other than salaries). This
	// is in case there are more mortgages than can be displayed.
	int otherPrincipal = 0;
	int otherPayment = 0;
	for(const Mortgage &mortgage : player.Accounts().Mortgages())
	{
		otherPrincipal += mortgage.Principal();
		otherPayment += mortgage.Payment();
	}
	int totalPayment = otherPayment;
	
	// Check if salaries need to be drawn.
	int salaries = player.Salaries();
	
	int row = 0;
	for(const Mortgage &mortgage : player.Accounts().Mortgages())
	{
		if(row == selectedRow)
		{
			table.DrawHighlight(back);
			table.SetColor(selected);
		}
		else
			table.SetColor(unselected);
		
		// There is room for seven rows if including salaries, or 8 if not.
		if(row == (6 + !salaries) && otherPrincipal != mortgage.Principal())
		{
			table.Draw("Other", unselected);
			table.Draw(otherPrincipal);
			table.Advance(2);
			table.Draw(otherPayment);
		}
		else
		{
			table.Draw(mortgage.Type());
			table.Draw(mortgage.Principal());
			table.Draw(mortgage.Interest());
			table.Draw(mortgage.Term());
			table.Draw(mortgage.Payment());
			
			otherPrincipal -= mortgage.Principal();
			otherPayment -= mortgage.Payment();
		}
		table.Draw("[pay extra]");
		++row;
		
		// Draw no more than 8 rows, counting the salaries row if any.
		if(row == 7 + !salaries)
			break;
	}
	table.SetColor(unselected);
	// Draw the salaries, if necessary.
	if(salaries)
	{
		totalPayment += salaries;
		
		table.Draw("Crew Salaries", unselected);
		table.Advance(3);
		table.Draw(salaries);
		table.Advance();
	}
	
	table.Advance(3);
	table.Draw("total:", selected);
	table.Draw(totalPayment, unselected);
	table.Advance();
	
	table.DrawAt(Point(0., FIRST_Y + 210.));
	string credit = "Your credit score is " + to_string(player.Accounts().CreditScore()) + ".";
	table.Draw(credit);
	table.Advance(5);
	
	string amount;
	if(!qualify)
		amount = "You do not qualify for further loans at this time.";
	else
		amount = "You qualify for a new loan of up to " + Format::Number(qualify) + " credits.";
	bool isSelected = qualify && (selectedRow > (6 + !salaries)
		|| static_cast<unsigned>(selectedRow) >= player.Accounts().Mortgages().size());
	if(isSelected)
		table.DrawHighlight(back);
	table.Draw(amount, unselected);
	if(qualify)
	{
		table.Advance(4);
		table.Draw("[apply]", selected);
	}
	
	const Interface *interface = GameData::Interfaces().Get("bank");
	Information info;
	for(const Mortgage &mortgage : player.Accounts().Mortgages())
		if(mortgage.Principal() <= player.Accounts().Credits())
			info.SetCondition("can pay");
	interface->Draw(info);
}
Пример #7
0
void InfoPanel::DrawInfo() const
{
	Color dim = *GameData::Colors().Get("medium");
	Color bright = *GameData::Colors().Get("bright");
	Color elsewhere = *GameData::Colors().Get("dim");
	Color dead(.4, 0., 0., 0.);
	const Font &font = FontSet::Get(14);
	
	// Player info.
	Table table;
	table.AddColumn(0, Table::LEFT);
	table.AddColumn(230, Table::RIGHT);
	table.SetUnderline(0, 230);
	table.DrawAt(Point(-490., -282.));
	
	table.Draw("player:", dim);
	table.Draw(player.FirstName() + " " + player.LastName(), bright);
	table.Draw("net worth:", dim);
	table.Draw(Format::Number(player.Accounts().NetWorth()) + " credits", bright);
	
	// Determine the player's combat rating.
	table.DrawGap(10);
	size_t ratingLevel = 0;
	auto it = player.Conditions().find("combat rating");
	if(it != player.Conditions().end() && it->second > 0)
	{
		ratingLevel = log(it->second);
		ratingLevel = min(ratingLevel, RATINGS.size() - 1);
	}
	table.DrawUnderline(dim);
	table.Draw("combat rating:", bright);
	table.Advance();
	table.DrawGap(5);
	table.Draw(RATINGS[ratingLevel], dim);
	table.Draw("(" + to_string(ratingLevel) + ")", dim);
	
	auto salary = Match(player, "salary: ", "");
	sort(salary.begin(), salary.end());
	DrawList(salary, table, "salary:", 4);
	
	auto tribute = Match(player, "tribute: ", "");
	sort(tribute.begin(), tribute.end());
	DrawList(tribute, table, "tribute:", 4);
	
	int maxRows = static_cast<int>(250. - 30. - table.GetPoint().Y()) / 20;
	auto licenses = Match(player, "license: ", " License");
	DrawList(licenses, table, "licenses:", maxRows, false);
	
	// Fleet listing.
	Point pos = Point(-240., -280.);
	font.Draw("ship", pos + Point(0., 0.), bright);
	font.Draw("model", pos + Point(220., 0.), bright);
	font.Draw("system", pos + Point(350., 0.), bright);
	font.Draw("shields", pos + Point(550. - font.Width("shields"), 0.), bright);
	font.Draw("hull", pos + Point(610. - font.Width("hull"), 0.), bright);
	font.Draw("fuel", pos + Point(670. - font.Width("fuel"), 0.), bright);
	font.Draw("crew", pos + Point(730. - font.Width("crew"), 0.), bright);
	FillShader::Fill(pos + Point(365., 15.), Point(730., 1.), dim);
	
	if(!player.Ships().size())
		return;
	int lastIndex = player.Ships().size() - 1;
	const Ship *flagship = player.Flagship();
	
	pos.Y() += 5.;
	int index = scroll;
	auto sit = player.Ships().begin() + scroll;
	for( ; sit < player.Ships().end(); ++sit)
	{
		const shared_ptr<Ship> &ship = *sit;
		pos.Y() += 20.;
		if(pos.Y() >= 260.)
			break;
		
		bool isElsewhere = (ship->GetSystem() != player.GetSystem());
		isElsewhere |= (ship->CanBeCarried() && player.GetSystem());
		bool isDead = ship->IsDestroyed() || ship->IsDisabled();
		bool isHovered = (index == hover);
		const Color &color = isDead ? dead : isElsewhere ? elsewhere : isHovered ? bright : dim;
		font.Draw(ship->Name(), pos + Point(10. * ship->CanBeCarried(), 0.), color);
		font.Draw(ship->ModelName(), pos + Point(220., 0.), color);
		
		const System *system = ship->GetSystem();
		if(system)
			font.Draw(system->Name(), pos + Point(350., 0.), color);
		
		string shields = to_string(static_cast<int>(100. * max(0., ship->Shields()))) + "%";
		font.Draw(shields, pos + Point(550. - font.Width(shields), 0.), color);
		
		string hull = to_string(static_cast<int>(100. * max(0., ship->Hull()))) + "%";
		font.Draw(hull, pos + Point(610. - font.Width(hull), 0.), color);
		
		string fuel = to_string(static_cast<int>(
			ship->Attributes().Get("fuel capacity") * ship->Fuel()));
		font.Draw(fuel, pos + Point(670. - font.Width(fuel), 0.), color);
		
		string crew = ship->IsParked() ? "Parked" :
			to_string(ship.get() == flagship ? ship->Crew() : ship->RequiredCrew());
		font.Draw(crew, pos + Point(730. - font.Width(crew), 0.), color);
		
		if(index < lastIndex || selected < 0)
			zones.emplace_back(pos + Point(365, font.Height() / 2), Point(730, 20), index);
		else
		{
			int height = 280. - pos.Y();
			zones.emplace_back(pos + Point(365, height / 2), Point(730, height), index);
		}
		++index;
	}
	
	// Re-ordering ships in your fleet.
	if(selected >= 0)
	{
		const string &name = player.Ships()[selected]->Name();
		Point pos(hoverPoint.X() - .5 * font.Width(name), hoverPoint.Y());
		font.Draw(name, pos + Point(1., 1.), Color(0., 1.));
		font.Draw(name, pos, bright);
	}
}
Пример #8
0
void PreferencesPanel::DrawSettings()
{
	const Color &back = *GameData::Colors().Get("faint");
	const Color &dim = *GameData::Colors().Get("dim");
	const Color &medium = *GameData::Colors().Get("medium");
	const Color &bright = *GameData::Colors().Get("bright");
	
	Table table;
	table.AddColumn(-115, Table::LEFT);
	table.AddColumn(115, Table::RIGHT);
	table.SetUnderline(-120, 120);
	
	int firstY = -248;
	table.DrawAt(Point(-130, firstY));
	
	static const string SETTINGS[] = {
		"Display",
		ZOOM_FACTOR,
		VIEW_ZOOM_FACTOR,
		"Show status overlays",
		"Highlight player's flagship",
		"Rotate flagship in HUD",
		"Show planet labels",
		"Show mini-map",
		"",
		"AI",
		"Automatic aiming",
		"Automatic firing",
		EXPEND_AMMO,
		TURRET_TRACKING,
		"",
		"Performance",
		"Show CPU / GPU load",
		"Render motion blur",
		"Reduce large graphics",
		"Draw background haze",
		"Show hyperspace flash",
		"\n",
		"Other",
		"Clickable radar display",
		"Hide unexplored map regions",
		REACTIVATE_HELP,
		"Rehire extra crew when lost",
		SCROLL_SPEED,
		"Show escort systems on map",
		"Warning siren"
	};
	bool isCategory = true;
	for(const string &setting : SETTINGS)
	{
		// Check if this is a category break or column break.
		if(setting.empty() || setting == "\n")
		{
			isCategory = true;
			if(!setting.empty())
				table.DrawAt(Point(130, firstY));
			continue;
		}
		
		if(isCategory)
		{
			isCategory = false;
			table.DrawGap(10);
			table.DrawUnderline(medium);
			table.Draw(setting, bright);
			table.Advance();
			table.DrawGap(5);
			continue;
		}
		
		// Record where this setting is displayed, so the user can click on it.
		prefZones.emplace_back(table.GetCenterPoint(), table.GetRowSize(), setting);
		
		// Get the "on / off" text for this setting.
		bool isOn = Preferences::Has(setting);
		string text;
		if(setting == ZOOM_FACTOR)
		{
			isOn = true;
			text = to_string(Screen::Zoom());
		}
		else if(setting == VIEW_ZOOM_FACTOR)
		{
			isOn = true;
			text = to_string(static_cast<int>(100. * Preferences::ViewZoom()));
		}
		else if(setting == EXPEND_AMMO)
			text = Preferences::AmmoUsage();
		else if(setting == TURRET_TRACKING)
		{
			isOn = true;
			text = Preferences::Has(FOCUS_PREFERENCE) ? "focused" : "opportunistic";
		}
		else if(setting == REACTIVATE_HELP)
		{
			// Check how many help messages have been displayed.
			const map<string, string> &help = GameData::HelpTemplates();
			int shown = 0;
			for(const auto &it : help)
				shown += Preferences::Has("help: " + it.first);
			
			// Don't count the "basic help" messages in the total.
			if(shown)
				text = to_string(shown) + " / " + to_string(help.size() - 2);
			else
			{
				isOn = true;
				text = "done";
			}
		}
		else if(setting == SCROLL_SPEED)
		{
			isOn = true;
			text = to_string(Preferences::ScrollSpeed());
		}
		else
			text = isOn ? "on" : "off";
		
		if(setting == hoverPreference)
			table.DrawHighlight(back);
		table.Draw(setting, isOn ? medium : dim);
		table.Draw(text, isOn ? bright : medium);
	}
}
Пример #9
0
void PreferencesPanel::DrawControls()
{
	const Color &back = *GameData::Colors().Get("faint");
	const Color &dim = *GameData::Colors().Get("dim");
	const Color &medium = *GameData::Colors().Get("medium");
	const Color &bright = *GameData::Colors().Get("bright");
	
	// Check for conflicts.
	Color red(.3, 0., 0., .3);
	
	Table table;
	table.AddColumn(-115, Table::LEFT);
	table.AddColumn(115, Table::RIGHT);
	table.SetUnderline(-120, 120);
	
	int firstY = -248;
	table.DrawAt(Point(-130, firstY));
	
	static const string CATEGORIES[] = {
		"Navigation",
		"Weapons",
		"Targeting",
		"Menus",
		"Fleet"
	};
	const string *category = CATEGORIES;
	static const Command COMMANDS[] = {
		Command::NONE,
		Command::FORWARD,
		Command::LEFT,
		Command::RIGHT,
		Command::BACK,
		Command::AFTERBURNER,
		Command::LAND,
		Command::JUMP,
		Command::NONE,
		Command::PRIMARY,
		Command::SELECT,
		Command::SECONDARY,
		Command::CLOAK,
		Command::NONE,
		Command::NEAREST,
		Command::TARGET,
		Command::HAIL,
		Command::BOARD,
		Command::SCAN,
		Command::NONE,
		Command::MENU,
		Command::MAP,
		Command::INFO,
		Command::FULLSCREEN,
		Command::NONE,
		Command::DEPLOY,
		Command::FIGHT,
		Command::GATHER,
		Command::HOLD,
		Command::AMMO
	};
	static const Command *BREAK = &COMMANDS[19];
	for(const Command &command : COMMANDS)
	{
		// The "BREAK" line is where to go to the next column.
		if(&command == BREAK)
			table.DrawAt(Point(130, firstY));
		
		if(!command)
		{
			table.DrawGap(10);
			table.DrawUnderline(medium);
			if(category != end(CATEGORIES))
				table.Draw(*category++, bright);
			else
				table.Advance();
			table.Draw("Key", bright);
			table.DrawGap(5);
		}
		else
		{
			int index = zones.size();
			// Mark conflicts.
			bool isConflicted = command.HasConflict();
			bool isEditing = (index == editing);
			if(isConflicted || isEditing)
			{
				table.SetHighlight(66, 120);
				table.DrawHighlight(isEditing ? dim: red);
			}
			
			// Mark the selected row.
			bool isHovering = (index == hover && !isEditing);
			if(!isHovering && index == selected)
			{
				table.SetHighlight(-120, 64);
				table.DrawHighlight(back);
			}
			
			// Highlight whichever row the mouse hovers over.
			table.SetHighlight(-120, 120);
			if(isHovering)
				table.DrawHighlight(back);
			
			zones.emplace_back(table.GetCenterPoint(), table.GetRowSize(), command);
			
			table.Draw(command.Description(), medium);
			table.Draw(command.KeyName(), isEditing ? bright : medium);
		}
	}
	
	Table shiftTable;
	shiftTable.AddColumn(125, Table::RIGHT);
	shiftTable.SetUnderline(0, 130);
	shiftTable.DrawAt(Point(-400, 52));
	
	shiftTable.DrawUnderline(medium);
	shiftTable.Draw("With <shift> key", bright);
	shiftTable.DrawGap(5);
	shiftTable.Draw("Select nearest ship", medium);
	shiftTable.Draw("Select next escort", medium);
	shiftTable.Draw("Talk to planet", medium);
	shiftTable.Draw("Board disabled escort", medium);
}
Пример #10
0
void ShipInfoPanel::DrawCargo(const Rectangle &bounds)
{
	Color dim = *GameData::Colors().Get("medium");
	Color bright = *GameData::Colors().Get("bright");
	Color backColor = *GameData::Colors().Get("faint");
	const Ship &ship = **shipIt;

	// Cargo list.
	const CargoHold &cargo = (player.Cargo().Used() ? player.Cargo() : ship.Cargo());
	Table table;
	table.AddColumn(0, Table::LEFT);
	table.AddColumn(WIDTH - 20, Table::RIGHT);
	table.SetUnderline(-5, WIDTH - 15);
	table.DrawAt(bounds.TopLeft() + Point(10., 8.));
	
	double endY = bounds.Bottom() - 30. * (cargo.Passengers() != 0);
	bool hasSpace = (table.GetRowBounds().Bottom() < endY);
	if((cargo.CommoditiesSize() || cargo.HasOutfits() || cargo.MissionCargoSize()) && hasSpace)
	{
		table.Draw("Cargo", bright);
		table.Advance();
		hasSpace = (table.GetRowBounds().Bottom() < endY);
	}
	if(cargo.CommoditiesSize() && hasSpace)
	{
		for(const auto &it : cargo.Commodities())
		{
			if(!it.second)
				continue;
			
			commodityZones.emplace_back(table.GetCenterPoint(), table.GetRowSize(), it.first);
			if(it.first == selectedCommodity)
				table.DrawHighlight(backColor);
			
			table.Draw(it.first, dim);
			table.Draw(to_string(it.second), bright);
			
			// Truncate the list if there is not enough space.
			if(table.GetRowBounds().Bottom() >= endY)
			{
				hasSpace = false;
				break;
			}
		}
		table.DrawGap(10.);
	}
	if(cargo.HasOutfits() && hasSpace)
	{
		for(const auto &it : cargo.Outfits())
		{
			if(!it.second)
				continue;
			
			plunderZones.emplace_back(table.GetCenterPoint(), table.GetRowSize(), it.first);
			if(it.first == selectedPlunder)
				table.DrawHighlight(backColor);
			
			// For outfits, show how many of them you have and their total mass.
			bool isSingular = (it.second == 1 || it.first->Get("installable") < 0.);
			string name = (isSingular ? it.first->Name() : it.first->PluralName());
			if(!isSingular)
				name += " (" + to_string(it.second) + "x)";
			table.Draw(name, dim);
			
			double mass = it.first->Mass() * it.second;
			table.Draw(Format::Number(mass), bright);
			
			// Truncate the list if there is not enough space.
			if(table.GetRowBounds().Bottom() >= endY)
			{
				hasSpace = false;
				break;
			}
		}
		table.DrawGap(10.);
	}
	if(cargo.HasMissionCargo() && hasSpace)
	{
		for(const auto &it : cargo.MissionCargo())
		{
			// Capitalize the name of the cargo.
			table.Draw(Format::Capitalize(it.first->Cargo()), dim);
			table.Draw(to_string(it.second), bright);
			
			// Truncate the list if there is not enough space.
			if(table.GetRowBounds().Bottom() >= endY)
				break;
		}
		table.DrawGap(10.);
	}
	if(cargo.Passengers() && endY >= bounds.Top())
	{
		table.DrawAt(Point(bounds.Left(), endY) + Point(10., 8.));
		table.Draw("passengers:", dim);
		table.Draw(to_string(cargo.Passengers()), bright);
	}
}
Пример #11
0
void ShipInfoPanel::DrawOutfits(const Rectangle &bounds, Rectangle &cargoBounds)
{
	// Check that the specified area is big enough.
	if(bounds.Width() < WIDTH)
		return;
	
	// Colors to draw with.
	Color dim = *GameData::Colors().Get("medium");
	Color bright = *GameData::Colors().Get("bright");
	const Ship &ship = **shipIt;
	
	// Table attributes.
	Table table;
	table.AddColumn(0, Table::LEFT);
	table.AddColumn(WIDTH - 20, Table::RIGHT);
	table.SetUnderline(0, WIDTH - 20);
	Point start = bounds.TopLeft() + Point(10., 8.);
	table.DrawAt(start);
	
	// Draw the outfits in the same order used in the outfitter.
	for(const string &category : Outfit::CATEGORIES)
	{
		auto it = outfits.find(category);
		if(it == outfits.end())
			continue;
		
		// Skip to the next column if there is not space for this category label
		// plus at least one outfit.
		if(table.GetRowBounds().Bottom() + 40. > bounds.Bottom())
		{
			start += Point(WIDTH, 0.);
			if(start.X() + WIDTH - 20 > bounds.Right())
				break;
			table.DrawAt(start);
		}
		
		// Draw the category label.
		table.Draw(category, bright);
		table.Advance();
		for(const Outfit *outfit : it->second)
		{
			// Check if we've gone below the bottom of the bounds.
			if(table.GetRowBounds().Bottom() > bounds.Bottom())
			{
				start += Point(WIDTH, 0.);
				if(start.X() + WIDTH - 20 > bounds.Right())
					break;
				table.DrawAt(start);
				table.Draw(category, bright);
				table.Advance();
			}
			
			// Draw the outfit name and count.
			table.Draw(outfit->Name(), dim);
			string number = to_string(ship.OutfitCount(outfit));
			table.Draw(number, bright);
		}
		// Add an extra gap in between categories.
		table.DrawGap(10.);
	}
	
	// Check if this information spilled over into the cargo column.
	if(table.GetPoint().X() >= cargoBounds.Left())
	{
		double startY = table.GetRowBounds().Top() - 8.;
		cargoBounds = Rectangle::WithCorners(
			Point(cargoBounds.Left(), startY),
			Point(cargoBounds.Right(), max(startY, cargoBounds.Bottom())));
	}
}