Files @ r25817:3f5c3838fe0a
Branch filter:

Location: cpp/openttd-patchpack/source/src/engine_gui.cpp - annotation

Patric Stout
Add: allow setting your server visibility to "invite-only" (#9434)

In this mode you do register to the Game Coordinator, but your
server will not show up in the public server listing. You can give
your friends the invite code of the server with which they can
join.
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r9111:983de9c5a848
r6125:eb40461cb765
r5584:545d748cc681
r8107:82461791b7a2
r9070:e059c65164f3
r8116:df67d3c5e4fd
r8114:866ed489ed98
r9380:6b24883f64de
r9567:b3592d86e408
r12037:7b4fedf64d47
r12037:7b4fedf64d47
r10000:91824eb4383b
r23698:1872cc5b7dd7
r13372:236fb191f6c2
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r5584:545d748cc681
r18670:f122c356353c
r18670:f122c356353c
r8264:d493cb51fe8a
r5584:545d748cc681
r21383:942c32fb8b0e
r21383:942c32fb8b0e
r15610:623a23fb6560
r15610:623a23fb6560
r12827:19af93950884
r12827:19af93950884
r12827:19af93950884
r9199:7d9724de3af0
r5584:545d748cc681
r13208:40382e8abf19
r13208:40382e8abf19
r6209:f315c4c30b43
r23698:1872cc5b7dd7
r23698:1872cc5b7dd7
r11725:57bc99fdc1bc
r11725:57bc99fdc1bc
r6259:e2dba394134b
r13208:40382e8abf19
r5584:545d748cc681
r5584:545d748cc681
r5584:545d748cc681
r11512:4e2f95d920fb
r11512:4e2f95d920fb
r13742:180ad925befc
r13742:180ad925befc
r11512:4e2f95d920fb
r13745:49505a0400d8
r18673:e5a4490b411b
r13490:0caa306cf3f9
r18673:e5a4490b411b
r18673:e5a4490b411b
r11512:4e2f95d920fb
r11512:4e2f95d920fb
r11512:4e2f95d920fb
r11512:4e2f95d920fb
r11512:4e2f95d920fb
r9302:115cfeb49cd5
r21789:7b1fbdc6dee7
r13490:0caa306cf3f9
r20280:ca1fc41725ff
r9302:115cfeb49cd5
r20280:ca1fc41725ff
r19854:d39ea9da77bb
r19854:d39ea9da77bb
r19854:d39ea9da77bb
r9302:115cfeb49cd5
r5584:545d748cc681
r23499:f9bf6ad58697
r13490:0caa306cf3f9
r18673:e5a4490b411b
r5584:545d748cc681
r21788:4129b833084f
r9302:115cfeb49cd5
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r21788:4129b833084f
r24597:afde5721a3b6
r21788:4129b833084f
r24597:afde5721a3b6
r5584:545d748cc681
r21788:4129b833084f
r13490:0caa306cf3f9
r13490:0caa306cf3f9
r13490:0caa306cf3f9
r13490:0caa306cf3f9
r23499:f9bf6ad58697
r13490:0caa306cf3f9
r18673:e5a4490b411b
r13490:0caa306cf3f9
r13490:0caa306cf3f9
r13490:0caa306cf3f9
r23229:d5166f55387e
r13490:0caa306cf3f9
r5584:545d748cc681
r7059:0c2dc932a6ae
r15390:44d506cb3529
r13490:0caa306cf3f9
r5584:545d748cc681
r21788:4129b833084f
r13490:0caa306cf3f9
r21788:4129b833084f
r13490:0caa306cf3f9
r5584:545d748cc681
r5584:545d748cc681
r23499:f9bf6ad58697
r9302:115cfeb49cd5
r9302:115cfeb49cd5
r18673:e5a4490b411b
r10499:570896340d7a
r22672:3473f7daf422
r18673:e5a4490b411b
r25564:c875d92c537a
r5584:545d748cc681
r5584:545d748cc681
r5584:545d748cc681
r19856:877797b48845
r23499:f9bf6ad58697
r19856:877797b48845
r19856:877797b48845
r19856:877797b48845
r19856:877797b48845
r25564:c875d92c537a
r19856:877797b48845
r9302:115cfeb49cd5
r5584:545d748cc681
r20280:ca1fc41725ff
r20283:2a199c78224c
r5893:6c4fd9987e0f
r13739:747ed1f003e3
r13554:d1964ead02ee
r11368:058349c3a02c
r5584:545d748cc681
r5584:545d748cc681
r5584:545d748cc681
r5584:545d748cc681
r9302:115cfeb49cd5
r5584:545d748cc681
r5584:545d748cc681
r17630:7d818445376d
r17630:7d818445376d
r17630:7d818445376d
r17630:7d818445376d
r17630:7d818445376d
r13211:4ba95564ba64
r9567:b3592d86e408
r13211:4ba95564ba64
r21705:f9ca7c863088
r9567:b3592d86e408
r9567:b3592d86e408
r12828:1411e13c41d0
r5584:545d748cc681
r10927:eb69eaf0227d
r10967:2c98940d6c64
r10967:2c98940d6c64
r10967:2c98940d6c64
r13372:236fb191f6c2
r5584:545d748cc681
r10927:eb69eaf0227d
r5584:545d748cc681
r13211:4ba95564ba64
r9567:b3592d86e408
r11188:143f3c64befd
r9720:6d491d07d0a8
r5584:545d748cc681
r5584:545d748cc681
r5584:545d748cc681
r14396:0e22f6ee524f
r5584:545d748cc681
r5584:545d748cc681
r12828:1411e13c41d0
r5584:545d748cc681
r11350:df593340eca2
r13407:428d181f586b
r13407:428d181f586b
r18646:67fc6c803d34
r11350:df593340eca2
r19170:2bf34ee1afd6
r19170:2bf34ee1afd6
r19170:2bf34ee1afd6
r22591:6e3880e55298
r19170:2bf34ee1afd6
r19170:2bf34ee1afd6
r19170:2bf34ee1afd6
r14191:bc6b1902e177
r13407:428d181f586b
r19170:2bf34ee1afd6
r19170:2bf34ee1afd6
r19170:2bf34ee1afd6
r22591:6e3880e55298
r11350:df593340eca2
r19170:2bf34ee1afd6
r22591:6e3880e55298
r11350:df593340eca2
r5584:545d748cc681
r5584:545d748cc681
r12828:1411e13c41d0
r5584:545d748cc681
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r22589:85fa73a4e73f
r11188:143f3c64befd
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r14749:107a1d25efe3
r11188:143f3c64befd
r5584:545d748cc681
r5584:545d748cc681
r12828:1411e13c41d0
r5584:545d748cc681
r10927:eb69eaf0227d
r10967:2c98940d6c64
r11188:143f3c64befd
r11403:ba31da6812eb
r10927:eb69eaf0227d
r22589:85fa73a4e73f
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r12828:1411e13c41d0
r5584:545d748cc681
r5584:545d748cc681
r12825:b76c82800d1a
r12825:b76c82800d1a
r13587:9ee7798ce808
r13587:9ee7798ce808
r13587:9ee7798ce808
r12825:b76c82800d1a
r12825:b76c82800d1a
r13060:e57594b0ca84
r12825:b76c82800d1a
r18234:0d83ef81cba4
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r18234:0d83ef81cba4
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r18234:0d83ef81cba4
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r18234:0d83ef81cba4
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r18234:0d83ef81cba4
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r12825:b76c82800d1a
r15610:623a23fb6560
r15610:623a23fb6560
r9380:6b24883f64de
r9380:6b24883f64de
r9380:6b24883f64de
r9403:e5bffa930a63
r9380:6b24883f64de
r23614:ccdf83295af6
r23614:ccdf83295af6
r9380:6b24883f64de
r9380:6b24883f64de
r15610:623a23fb6560
r15610:623a23fb6560
r9380:6b24883f64de
r9380:6b24883f64de
r9380:6b24883f64de
r9380:6b24883f64de
r9380:6b24883f64de
r9403:e5bffa930a63
r9380:6b24883f64de
r9404:f74e13f5c66e
r23520:20bbc807b0eb
r23520:20bbc807b0eb
r23614:ccdf83295af6
r9380:6b24883f64de
r9380:6b24883f64de
/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 */

/** @file engine_gui.cpp GUI to show engine related information. */

#include "stdafx.h"
#include "window_gui.h"
#include "engine_base.h"
#include "command_func.h"
#include "strings_func.h"
#include "engine_gui.h"
#include "articulated_vehicles.h"
#include "vehicle_func.h"
#include "company_func.h"
#include "rail.h"
#include "road.h"
#include "settings_type.h"
#include "train.h"
#include "roadveh.h"
#include "ship.h"
#include "aircraft.h"

#include "widgets/engine_widget.h"

#include "table/strings.h"

#include "safeguards.h"

/**
 * Return the category of an engine.
 * @param engine Engine to examine.
 * @return String describing the category ("road veh", "train". "airplane", or "ship") of the engine.
 */
StringID GetEngineCategoryName(EngineID engine)
{
	const Engine *e = Engine::Get(engine);
	switch (e->type) {
		default: NOT_REACHED();
		case VEH_ROAD:
			return GetRoadTypeInfo(e->u.road.roadtype)->strings.new_engine;
		case VEH_AIRCRAFT:          return STR_ENGINE_PREVIEW_AIRCRAFT;
		case VEH_SHIP:              return STR_ENGINE_PREVIEW_SHIP;
		case VEH_TRAIN:
			return GetRailTypeInfo(e->u.rail.railtype)->strings.new_loco;
	}
}

static const NWidgetPart _nested_engine_preview_widgets[] = {
	NWidget(NWID_HORIZONTAL),
		NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
		NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_ENGINE_PREVIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
	EndContainer(),
	NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
		NWidget(WWT_EMPTY, INVALID_COLOUR, WID_EP_QUESTION), SetMinimalSize(300, 0), SetPadding(8, 8, 8, 8), SetFill(1, 0),
		NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(85, 10, 85),
			NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_EP_NO), SetDataTip(STR_QUIT_NO, STR_NULL), SetFill(1, 0),
			NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_EP_YES), SetDataTip(STR_QUIT_YES, STR_NULL), SetFill(1, 0),
		EndContainer(),
		NWidget(NWID_SPACER), SetMinimalSize(0, 8),
	EndContainer(),
};

struct EnginePreviewWindow : Window {
	int vehicle_space; // The space to show the vehicle image

	EnginePreviewWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
	{
		this->InitNested(window_number);

		/* There is no way to recover the window; so disallow closure via DEL; unless SHIFT+DEL */
		this->flags |= WF_STICKY;
	}

	void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
	{
		if (widget != WID_EP_QUESTION) return;

		/* Get size of engine sprite, on loan from depot_gui.cpp */
		EngineID engine = this->window_number;
		EngineImageType image_type = EIT_PURCHASE;
		uint x, y;
		int x_offs, y_offs;

		const Engine *e = Engine::Get(engine);
		switch (e->type) {
			default: NOT_REACHED();
			case VEH_TRAIN:    GetTrainSpriteSize(   engine, x, y, x_offs, y_offs, image_type); break;
			case VEH_ROAD:     GetRoadVehSpriteSize( engine, x, y, x_offs, y_offs, image_type); break;
			case VEH_SHIP:     GetShipSpriteSize(    engine, x, y, x_offs, y_offs, image_type); break;
			case VEH_AIRCRAFT: GetAircraftSpriteSize(engine, x, y, x_offs, y_offs, image_type); break;
		}
		this->vehicle_space = std::max<int>(40, y - y_offs);

		size->width = std::max(size->width, x - x_offs);
		SetDParam(0, GetEngineCategoryName(engine));
		size->height = GetStringHeight(STR_ENGINE_PREVIEW_MESSAGE, size->width) + WD_PAR_VSEP_WIDE + FONT_HEIGHT_NORMAL + this->vehicle_space;
		SetDParam(0, engine);
		size->height += GetStringHeight(GetEngineInfoString(engine), size->width);
	}

	void DrawWidget(const Rect &r, int widget) const override
	{
		if (widget != WID_EP_QUESTION) return;

		EngineID engine = this->window_number;
		SetDParam(0, GetEngineCategoryName(engine));
		int y = r.top + GetStringHeight(STR_ENGINE_PREVIEW_MESSAGE, r.right - r.left + 1);
		y = DrawStringMultiLine(r.left, r.right, r.top, y, STR_ENGINE_PREVIEW_MESSAGE, TC_FROMSTRING, SA_CENTER) + WD_PAR_VSEP_WIDE;

		SetDParam(0, engine);
		DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_ENGINE_NAME, TC_BLACK, SA_HOR_CENTER);
		y += FONT_HEIGHT_NORMAL;

		DrawVehicleEngine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, this->width >> 1, y + this->vehicle_space / 2, engine, GetEnginePalette(engine, _local_company), EIT_PREVIEW);

		y += this->vehicle_space;
		DrawStringMultiLine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, r.bottom, GetEngineInfoString(engine), TC_FROMSTRING, SA_CENTER);
	}

	void OnClick(Point pt, int widget, int click_count) override
	{
		switch (widget) {
			case WID_EP_YES:
				DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW);
				FALLTHROUGH;
			case WID_EP_NO:
				if (!_shift_pressed) this->Close();
				break;
		}
	}

	void OnInvalidateData(int data = 0, bool gui_scope = true) override
	{
		if (!gui_scope) return;

		EngineID engine = this->window_number;
		if (Engine::Get(engine)->preview_company != _local_company) this->Close();
	}
};

static WindowDesc _engine_preview_desc(
	WDP_CENTER, "engine_preview", 0, 0,
	WC_ENGINE_PREVIEW, WC_NONE,
	WDF_CONSTRUCTION,
	_nested_engine_preview_widgets, lengthof(_nested_engine_preview_widgets)
);


void ShowEnginePreviewWindow(EngineID engine)
{
	AllocateWindowDescFront<EnginePreviewWindow>(&_engine_preview_desc, engine);
}

/**
 * Get the capacity of an engine with articulated parts.
 * @param engine The engine to get the capacity of.
 * @return The capacity.
 */
uint GetTotalCapacityOfArticulatedParts(EngineID engine)
{
	CargoArray cap = GetCapacityOfArticulatedParts(engine);
	return cap.GetSum<uint>();
}

static StringID GetTrainEngineInfoString(const Engine *e)
{
	SetDParam(0, e->GetCost());
	SetDParam(2, e->GetDisplayMaxSpeed());
	SetDParam(3, e->GetPower());
	SetDParam(1, e->GetDisplayWeight());
	SetDParam(7, e->GetDisplayMaxTractiveEffort());

	SetDParam(4, e->GetRunningCost());

	uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
	if (capacity != 0) {
		SetDParam(5, e->GetDefaultCargoType());
		SetDParam(6, capacity);
	} else {
		SetDParam(5, CT_INVALID);
	}
	return (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && GetRailTypeInfo(e->u.rail.railtype)->acceleration_type != 2) ? STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE : STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER;
}

static StringID GetAircraftEngineInfoString(const Engine *e)
{
	CargoID cargo = e->GetDefaultCargoType();
	uint16 mail_capacity;
	uint capacity = e->GetDisplayDefaultCapacity(&mail_capacity);
	uint16 range = e->GetRange();

	uint i = 0;
	SetDParam(i++, e->GetCost());
	SetDParam(i++, e->GetDisplayMaxSpeed());
	SetDParam(i++, e->GetAircraftTypeText());
	if (range > 0) SetDParam(i++, range);
	SetDParam(i++, cargo);
	SetDParam(i++, capacity);

	if (mail_capacity > 0) {
		SetDParam(i++, CT_MAIL);
		SetDParam(i++, mail_capacity);
		SetDParam(i++, e->GetRunningCost());
		return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST;
	} else {
		SetDParam(i++, e->GetRunningCost());
		return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST;
	}
}

static StringID GetRoadVehEngineInfoString(const Engine *e)
{
	if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) {
		SetDParam(0, e->GetCost());
		SetDParam(1, e->GetDisplayMaxSpeed());
		uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
		if (capacity != 0) {
			SetDParam(2, e->GetDefaultCargoType());
			SetDParam(3, capacity);
		} else {
			SetDParam(2, CT_INVALID);
		}
		SetDParam(4, e->GetRunningCost());
		return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST;
	} else {
		SetDParam(0, e->GetCost());
		SetDParam(2, e->GetDisplayMaxSpeed());
		SetDParam(3, e->GetPower());
		SetDParam(1, e->GetDisplayWeight());
		SetDParam(7, e->GetDisplayMaxTractiveEffort());

		SetDParam(4, e->GetRunningCost());

		uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
		if (capacity != 0) {
			SetDParam(5, e->GetDefaultCargoType());
			SetDParam(6, capacity);
		} else {
			SetDParam(5, CT_INVALID);
		}
		return STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE;
	}
}

static StringID GetShipEngineInfoString(const Engine *e)
{
	SetDParam(0, e->GetCost());
	SetDParam(1, e->GetDisplayMaxSpeed());
	SetDParam(2, e->GetDefaultCargoType());
	SetDParam(3, e->GetDisplayDefaultCapacity());
	SetDParam(4, e->GetRunningCost());
	return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST;
}


/**
 * Get a multi-line string with some technical data, describing the engine.
 * @param engine Engine to describe.
 * @return String describing the engine.
 * @post \c DParam array is set up for printing the string.
 */
StringID GetEngineInfoString(EngineID engine)
{
	const Engine *e = Engine::Get(engine);

	switch (e->type) {
		case VEH_TRAIN:
			return GetTrainEngineInfoString(e);

		case VEH_ROAD:
			return GetRoadVehEngineInfoString(e);

		case VEH_SHIP:
			return GetShipEngineInfoString(e);

		case VEH_AIRCRAFT:
			return GetAircraftEngineInfoString(e);

		default: NOT_REACHED();
	}
}

/**
 * Draw an engine.
 * @param left   Minimum horizontal position to use for drawing the engine
 * @param right  Maximum horizontal position to use for drawing the engine
 * @param preferred_x Horizontal position to use for drawing the engine.
 * @param y      Vertical position to use for drawing the engine.
 * @param engine Engine to draw.
 * @param pal    Palette to use for drawing.
 */
void DrawVehicleEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
{
	const Engine *e = Engine::Get(engine);

	switch (e->type) {
		case VEH_TRAIN:
			DrawTrainEngine(left, right, preferred_x, y, engine, pal, image_type);
			break;

		case VEH_ROAD:
			DrawRoadVehEngine(left, right, preferred_x, y, engine, pal, image_type);
			break;

		case VEH_SHIP:
			DrawShipEngine(left, right, preferred_x, y, engine, pal, image_type);
			break;

		case VEH_AIRCRAFT:
			DrawAircraftEngine(left, right, preferred_x, y, engine, pal, image_type);
			break;

		default: NOT_REACHED();
	}
}

/**
 * Sort all items using quick sort and given 'CompareItems' function
 * @param el list to be sorted
 * @param compare function for evaluation of the quicksort
 */
void EngList_Sort(GUIEngineList *el, EngList_SortTypeFunction compare)
{
	if (el->size() < 2) return;
	std::sort(el->begin(), el->end(), compare);
}

/**
 * Sort selected range of items (on indices @ <begin, begin+num_items-1>)
 * @param el list to be sorted
 * @param compare function for evaluation of the quicksort
 * @param begin start of sorting
 * @param num_items count of items to be sorted
 */
void EngList_SortPartial(GUIEngineList *el, EngList_SortTypeFunction compare, uint begin, uint num_items)
{
	if (num_items < 2) return;
	assert(begin < el->size());
	assert(begin + num_items <= el->size());
	std::sort(el->begin() + begin, el->begin() + begin + num_items, compare);
}