train_gui.c
changeset 5199 9a75b853ad22
parent 5198 7046e5b0b5bc
child 5200 dfd31d4f2410
equal deleted inserted replaced
5198:7046e5b0b5bc 5199:9a75b853ad22
    72 	EngineID vb = *(const EngineID*)b;
    72 	EngineID vb = *(const EngineID*)b;
    73 	int val_a = ((RailVehInfo(va)->flags & RVI_WAGON) != 0) ? 1 : 0;
    73 	int val_a = ((RailVehInfo(va)->flags & RVI_WAGON) != 0) ? 1 : 0;
    74 	int val_b = ((RailVehInfo(vb)->flags & RVI_WAGON) != 0) ? 1 : 0;
    74 	int val_b = ((RailVehInfo(vb)->flags & RVI_WAGON) != 0) ? 1 : 0;
    75 	int r = val_a - val_b;
    75 	int r = val_a - val_b;
    76 
    76 
    77 	if (r == 0) {
    77 	/* Use EngineID to sort instead since we want consistent sorting */
    78 		/* Use EngineID to sort instead since we want consistent sorting */
    78 	if (r == 0) return TrainEngineNumberSorter(a, b);
    79 		return TrainEngineNumberSorter(a, b);
    79 
    80 	}
       
    81 	return _internal_sort_order ? -r : r;
    80 	return _internal_sort_order ? -r : r;
    82 }
    81 }
    83 
    82 
    84 static int CDECL TrainEngineCostSorter(const void *a, const void *b)
    83 static int CDECL TrainEngineCostSorter(const void *a, const void *b)
    85 {
    84 {
    86 	const int va = RailVehInfo(*(const EngineID*)a)->base_cost;
    85 	int va = RailVehInfo(*(const EngineID*)a)->base_cost;
    87 	const int vb = RailVehInfo(*(const EngineID*)b)->base_cost;
    86 	int vb = RailVehInfo(*(const EngineID*)b)->base_cost;
    88 	int r = va - vb;
    87 	int r = va - vb;
    89 
    88 
    90 	return _internal_sort_order ? -r : r;
    89 	return _internal_sort_order ? -r : r;
    91 }
    90 }
    92 
    91 
    93 static int CDECL TrainEngineSpeedSorter(const void *a, const void *b)
    92 static int CDECL TrainEngineSpeedSorter(const void *a, const void *b)
    94 {
    93 {
    95 	const int va = RailVehInfo(*(const EngineID*)a)->max_speed;
    94 	int va = RailVehInfo(*(const EngineID*)a)->max_speed;
    96 	const int vb = RailVehInfo(*(const EngineID*)b)->max_speed;
    95 	int vb = RailVehInfo(*(const EngineID*)b)->max_speed;
    97 	const int r = va - vb;
    96 	int r = va - vb;
    98 
    97 
    99 	return _internal_sort_order ? -r : r;
    98 	return _internal_sort_order ? -r : r;
   100 }
    99 }
   101 
   100 
   102 static int CDECL TrainEnginePowerSorter(const void *a, const void *b)
   101 static int CDECL TrainEnginePowerSorter(const void *a, const void *b)
   103 {
   102 {
   104 	const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
   103 	const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
   105 	const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
   104 	const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
   106 
   105 
   107 	const int va = rvi_a->power << (rvi_a->flags & RVI_MULTIHEAD ? 1 : 0);
   106 	int va = rvi_a->power << (rvi_a->flags & RVI_MULTIHEAD ? 1 : 0);
   108 	const int vb = rvi_b->power << (rvi_b->flags & RVI_MULTIHEAD ? 1 : 0);
   107 	int vb = rvi_b->power << (rvi_b->flags & RVI_MULTIHEAD ? 1 : 0);
   109 	const int r = va - vb;
   108 	int r = va - vb;
   110 
   109 
   111 	return _internal_sort_order ? -r : r;
   110 	return _internal_sort_order ? -r : r;
   112 }
   111 }
   113 
   112 
   114 static int CDECL TrainEngineIntroDateSorter(const void *a, const void *b)
   113 static int CDECL TrainEngineIntroDateSorter(const void *a, const void *b)
   115 {
   114 {
   116 	const int va = GetEngine(*(const EngineID*)a)->intro_date;
   115 	int va = GetEngine(*(const EngineID*)a)->intro_date;
   117 	const int vb = GetEngine(*(const EngineID*)b)->intro_date;
   116 	int vb = GetEngine(*(const EngineID*)b)->intro_date;
   118 	const int r = va - vb;
   117 	int r = va - vb;
   119 
   118 
   120 	return _internal_sort_order ? -r : r;
   119 	return _internal_sort_order ? -r : r;
   121 }
   120 }
   122 
   121 
   123 static EngineID _last_engine; // cached vehicle to hopefully speed up name-sorting
   122 static EngineID _last_engine; // cached vehicle to hopefully speed up name-sorting
   147 static int CDECL TrainEngineRunningCostSorter(const void *a, const void *b)
   146 static int CDECL TrainEngineRunningCostSorter(const void *a, const void *b)
   148 {
   147 {
   149 	const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
   148 	const RailVehicleInfo *rvi_a = RailVehInfo(*(const EngineID*)a);
   150 	const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
   149 	const RailVehicleInfo *rvi_b = RailVehInfo(*(const EngineID*)b);
   151 
   150 
   152 	const int va = rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class] * (rvi_a->flags & RVI_MULTIHEAD ? 2 : 1);
   151 	int va = rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class] * (rvi_a->flags & RVI_MULTIHEAD ? 2 : 1);
   153 	const int vb = rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class] * (rvi_b->flags & RVI_MULTIHEAD ? 2 : 1);
   152 	int vb = rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class] * (rvi_b->flags & RVI_MULTIHEAD ? 2 : 1);
   154 	const int r = va - vb;
   153 	int r = va - vb;
   155 
   154 
   156 	return _internal_sort_order ? -r : r;
   155 	return _internal_sort_order ? -r : r;
   157 }
   156 }
   158 
   157 
   159 static int CDECL TrainEnginePowerVsRunningCostSorter(const void *a, const void *b)
   158 static int CDECL TrainEnginePowerVsRunningCostSorter(const void *a, const void *b)
   165 	 * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int,
   164 	 * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int,
   166 	 * we will actually calculate cunning cost/power (to make it more than 1).
   165 	 * we will actually calculate cunning cost/power (to make it more than 1).
   167 	 * Because of this, the return value have to be reversed as well and we return b - a instead of a - b.
   166 	 * Because of this, the return value have to be reversed as well and we return b - a instead of a - b.
   168 	 * Another thing is that both power and running costs should be doubled for multiheaded engines.
   167 	 * Another thing is that both power and running costs should be doubled for multiheaded engines.
   169 	 * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */
   168 	 * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */
   170 	const int va = (rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class]) / max(1, rvi_a->power);
   169 	int va = (rvi_a->running_cost_base * _price.running_rail[rvi_a->running_cost_class]) / max(1, rvi_a->power);
   171 	const int vb = (rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class]) / max(1, rvi_b->power);
   170 	int vb = (rvi_b->running_cost_base * _price.running_rail[rvi_b->running_cost_class]) / max(1, rvi_b->power);
   172 	const int r = vb - va;
   171 	int r = vb - va;
   173 
   172 
   174 	return _internal_sort_order ? -r : r;
   173 	return _internal_sort_order ? -r : r;
   175 }
   174 }
   176 
   175 
   177 static int CDECL TrainEngineReliabilitySorter(const void *a, const void *b)
   176 static int CDECL TrainEngineReliabilitySorter(const void *a, const void *b)
   178 {
   177 {
   179 	const int va = GetEngine(*(const EngineID*)a)->reliability;
   178 	int va = GetEngine(*(const EngineID*)a)->reliability;
   180 	const int vb = GetEngine(*(const EngineID*)b)->reliability;
   179 	int vb = GetEngine(*(const EngineID*)b)->reliability;
   181 	const int r = va - vb;
   180 	int r = va - vb;
   182 
   181 
   183 	return _internal_sort_order ? -r : r;
   182 	return _internal_sort_order ? -r : r;
   184 }
   183 }
   185 
   184 
   186 static EngList_SortTypeFunction * const _engine_sorter[] = {
   185 static EngList_SortTypeFunction * const _engine_sorter[] = {
   374 	}
   373 	}
   375 }
   374 }
   376 
   375 
   377 static void GenerateBuildList(Window *w)
   376 static void GenerateBuildList(Window *w)
   378 {
   377 {
   379 	EngineID id;
   378 	EngineID eid;
   380 	int num_engines = 0;
   379 	int num_engines = 0;
   381 	int num_wagons  = 0;
   380 	int num_wagons  = 0;
   382 	buildvehicle_d *bv = &WP(w, buildvehicle_d);
   381 	buildvehicle_d *bv = &WP(w, buildvehicle_d);
   383 
   382 
   384 	bv->filter.railtype = w->window_number == 0 ? RAILTYPE_END : GetRailType(w->window_number);
   383 	bv->filter.railtype = (w->window_number == 0) ? RAILTYPE_END : GetRailType(w->window_number);
   385 
   384 
   386 	EngList_RemoveAll(&bv->eng_list);
   385 	EngList_RemoveAll(&bv->eng_list);
   387 	// make list of all available cars
   386 
   388 	for (id = 0; id < NUM_TRAIN_ENGINES; id++) {
   387 	// make a list of all available cars
   389 		const Engine *e = GetEngine(id);
   388 	for (eid = 0; eid < NUM_TRAIN_ENGINES; eid++) {
   390 		const RailVehicleInfo *rvi = RailVehInfo(id);
   389 		const Engine *e = GetEngine(eid);
       
   390 		const RailVehicleInfo *rvi = RailVehInfo(eid);
   391 
   391 
   392 		if (bv->filter.railtype != RAILTYPE_END && !HasPowerOnRail(e->railtype, bv->filter.railtype)) continue;
   392 		if (bv->filter.railtype != RAILTYPE_END && !HasPowerOnRail(e->railtype, bv->filter.railtype)) continue;
   393 		if (!IsEngineBuildable(id, VEH_Train)) continue;
   393 		if (!IsEngineBuildable(eid, VEH_Train)) continue;
   394 
   394 
   395 		EngList_Add(&bv->eng_list, id);
   395 		EngList_Add(&bv->eng_list, eid);
   396 		if ((rvi->flags & RVI_WAGON) == 0) {
   396 		if ((rvi->flags & RVI_WAGON) == 0) {
   397 			num_engines++;
   397 			num_engines++;
   398 		} else {
   398 		} else {
   399 			num_wagons++;
   399 			num_wagons++;
   400 		}
   400 		}
   403 	// make engines first, and then wagons, sorted by ListPositionOfEngine()
   403 	// make engines first, and then wagons, sorted by ListPositionOfEngine()
   404 	_internal_sort_order = false;
   404 	_internal_sort_order = false;
   405 	EngList_Sort(&bv->eng_list, TrainEnginesThenWagonsSorter);
   405 	EngList_Sort(&bv->eng_list, TrainEnginesThenWagonsSorter);
   406 
   406 
   407 	// and then sort engines
   407 	// and then sort engines
   408 	_internal_sort_order = WP(w,buildvehicle_d).descending_sort_order;
   408 	_internal_sort_order = bv->descending_sort_order;
   409 	EngList_SortPartial(&bv->eng_list, _engine_sorter[bv->sort_criteria], 0, num_engines);
   409 	EngList_SortPartial(&bv->eng_list, _engine_sorter[bv->sort_criteria], 0, num_engines);
   410 
   410 
   411 	// and finally sort wagons
   411 	// and finally sort wagons
   412 	EngList_SortPartial(&bv->eng_list, _engine_sorter[bv->sort_criteria], num_engines, num_wagons);
   412 	EngList_SortPartial(&bv->eng_list, _engine_sorter[bv->sort_criteria], num_engines, num_wagons);
   413 }
   413 }
   414 
   414 
   415 static void DrawTrainBuildWindow(Window *w)
   415 static void DrawTrainBuildWindow(Window *w)
   416 {
   416 {
   417 	buildvehicle_d *bv = &WP(w,buildvehicle_d);
   417 	const buildvehicle_d *bv = &WP(w, buildvehicle_d);
   418 	int num_engines = EngList_Count(&bv->eng_list);
   418 	int num_engines = EngList_Count(&bv->eng_list);
   419 	int x = 1;
   419 	int x = 1;
   420 	int y = 27;
   420 	int y = 27;
   421 	EngineID selected_id = bv->sel_engine;
   421 	EngineID selected_id = bv->sel_engine;
   422 	int max = w->vscroll.pos + w->vscroll.cap;
   422 	int max = w->vscroll.pos + w->vscroll.cap;
   459 	DoDrawString(bv->descending_sort_order ? DOWNARROW : UPARROW, 69, 15, 0x10);
   459 	DoDrawString(bv->descending_sort_order ? DOWNARROW : UPARROW, 69, 15, 0x10);
   460 }
   460 }
   461 
   461 
   462 static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
   462 static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
   463 {
   463 {
   464 	buildvehicle_d *bv = &WP(w,buildvehicle_d);
   464 	buildvehicle_d *bv = &WP(w, buildvehicle_d);
   465 	switch (e->event) {
   465 	switch (e->event) {
   466 		case WE_CREATE:
   466 		case WE_CREATE:
   467 			EngList_Create(&bv->eng_list);
   467 			EngList_Create(&bv->eng_list);
   468 			bv->sel_engine            = INVALID_ENGINE;
   468 			bv->sel_engine            = INVALID_ENGINE;
   469 			bv->sort_criteria         = _last_sort_criteria;
   469 			bv->sort_criteria         = _last_sort_criteria;
   484 			break;
   484 			break;
   485 
   485 
   486 		case WE_CLICK: {
   486 		case WE_CLICK: {
   487 			switch (e->we.click.widget) {
   487 			switch (e->we.click.widget) {
   488 				case BUILD_TRAIN_WIDGET_SORT_ASCENDING_DESCENDING:
   488 				case BUILD_TRAIN_WIDGET_SORT_ASCENDING_DESCENDING:
   489 					_last_sort_order = bv->descending_sort_order = !bv->descending_sort_order;
   489 					bv->descending_sort_order ^= true;
       
   490 					_last_sort_order = bv->descending_sort_order;
   490 					GenerateBuildList(w);
   491 					GenerateBuildList(w);
   491 					SetWindowDirty(w);
   492 					SetWindowDirty(w);
   492 					break;
   493 					break;
   493 
   494 
   494 				case BUILD_TRAIN_WIDGET_SORT_TEXT: case BUILD_TRAIN_WIDGET_SORT_DROPDOWN:/* Select sorting criteria dropdown menu */
   495 				case BUILD_TRAIN_WIDGET_SORT_TEXT: case BUILD_TRAIN_WIDGET_SORT_DROPDOWN:/* Select sorting criteria dropdown menu */
   530 			break;
   531 			break;
   531 		}
   532 		}
   532 
   533 
   533 		case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
   534 		case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
   534 			if (bv->sort_criteria != e->we.dropdown.index) {
   535 			if (bv->sort_criteria != e->we.dropdown.index) {
   535 				bv->sort_criteria = e->we.dropdown.index;
   536 				bv->sort_criteria = _last_sort_criteria = e->we.dropdown.index;
   536 				_last_sort_criteria = e->we.dropdown.index;
       
   537 				GenerateBuildList(w);
   537 				GenerateBuildList(w);
   538 				SetWindowDirty(w);
   538 				SetWindowDirty(w);
   539 			}
   539 			}
   540 			break;
   540 			break;
   541 
   541