27 BUILD_TRAIN_WIDGET_CLOSEBOX = 0, |
27 BUILD_TRAIN_WIDGET_CLOSEBOX = 0, |
28 BUILD_TRAIN_WIDGET_CAPTION, |
28 BUILD_TRAIN_WIDGET_CAPTION, |
29 BUILD_TRAIN_WIDGET_LIST, |
29 BUILD_TRAIN_WIDGET_LIST, |
30 BUILD_TRAIN_WIDGET_SCROLLBAR, |
30 BUILD_TRAIN_WIDGET_SCROLLBAR, |
31 BUILD_TRAIN_WIDGET_PANEL, |
31 BUILD_TRAIN_WIDGET_PANEL, |
|
32 BUILD_TRAIN_WIDGET_ENGINES, |
|
33 BUILD_TRAIN_WIDGET_WAGONS, |
|
34 BUILD_TRAIN_WIDGET_BOTH, |
32 BUILD_TRAIN_WIDGET_BUILD, |
35 BUILD_TRAIN_WIDGET_BUILD, |
33 BUILD_TRAIN_WIDGET_RENAME, |
36 BUILD_TRAIN_WIDGET_RENAME, |
34 BUILD_TRAIN_WIDGET_RESIZE, |
37 BUILD_TRAIN_WIDGET_RESIZE, |
35 } BuildTrainWidget; |
38 } BuildTrainWidget; |
|
39 |
|
40 static const Widget _new_rail_vehicle_widgets[] = { |
|
41 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
42 { WWT_CAPTION, RESIZE_NONE, 14, 11, 227, 0, 13, STR_JUST_STRING, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
43 { WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 215, 14, 125, 0x801, STR_8843_TRAIN_VEHICLE_SELECTION}, |
|
44 { WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 216, 227, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, |
|
45 { WWT_PANEL, RESIZE_TB, 14, 0, 227, 126, 197, 0x0, STR_NULL}, |
|
46 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 76, 198, 209, STR_BLACK_ENGINES, STR_BUILD_TRAIN_ENGINES_TIP}, |
|
47 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 77, 151, 198, 209, STR_BLACK_WAGONS, STR_BUILD_TRAIN_WAGONS_TIP}, |
|
48 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 152, 227, 198, 209, STR_BLACK_BOTH, STR_BUILD_TRAIN_BOTH_TIP}, |
|
49 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 107, 210, 221, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN}, |
|
50 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 108, 215, 210, 221, STR_8820_RENAME, STR_8845_RENAME_TRAIN_VEHICLE_TYPE}, |
|
51 { WWT_RESIZEBOX, RESIZE_TB, 14, 216, 227, 210, 221, 0x0, STR_RESIZE_BUTTON}, |
|
52 { WIDGETS_END}, |
|
53 }; |
36 |
54 |
37 |
55 |
38 /** |
56 /** |
39 * Draw the purchase info details of train engine at a given location. |
57 * Draw the purchase info details of train engine at a given location. |
40 * @param x,y location where to draw the info |
58 * @param x,y location where to draw the info |
185 |
203 |
186 void CcCloneTrain(bool success, TileIndex tile, uint32 p1, uint32 p2) |
204 void CcCloneTrain(bool success, TileIndex tile, uint32 p1, uint32 p2) |
187 { |
205 { |
188 if (success) ShowTrainViewWindow(GetVehicle(_new_vehicle_id)); |
206 if (success) ShowTrainViewWindow(GetVehicle(_new_vehicle_id)); |
189 } |
207 } |
190 |
208 static void engine_drawing_loop(const EngineID *engines, const uint16 engine_count, |
191 static void engine_drawing_loop(int *x, int *y, int *pos, int *sel, |
209 const int x, int *y, const EngineID sel, EngineID *position, const int16 show_max) |
192 EngineID *selected_id, RailType railtype, byte show_max, bool is_engine) |
210 { |
193 { |
211 for (; (*position) < min(engine_count, show_max); (*position)++) { |
|
212 EngineID i = engines[*position]; |
|
213 |
|
214 DrawString(x + 59, *y + 2, GetCustomEngineName(i), sel == i ? 0xC : 0x10); |
|
215 DrawTrainEngine(x + 29, *y + 6, i, GetEnginePalette(i, _local_player)); |
|
216 *y += 14; |
|
217 } |
|
218 } |
|
219 |
|
220 static inline void ExtendEngineListSize(const EngineID **engine_list, uint16 *engine_list_length, uint16 step_size) |
|
221 { |
|
222 *engine_list_length = min(*engine_list_length + step_size, NUM_TRAIN_ENGINES); |
|
223 *engine_list = realloc((void*)*engine_list, (*engine_list_length) * sizeof((*engine_list)[0])); |
|
224 } |
|
225 |
|
226 static void GenerateBuildList(EngineID **engines, uint16 *num_engines, EngineID **wagons, uint16 *num_wagons, RailType railtype) |
|
227 { |
|
228 uint16 engine_length = *num_engines; |
|
229 uint16 wagon_length = *num_wagons; |
194 EngineID j; |
230 EngineID j; |
|
231 |
|
232 (*num_engines) = 0; |
|
233 (*num_wagons) = 0; |
|
234 |
|
235 if (engines == NULL) ExtendEngineListSize((const EngineID**)engines, &engine_length, 25); |
|
236 if (wagons == NULL) ExtendEngineListSize((const EngineID**)wagons, &wagon_length, 25); |
195 |
237 |
196 for (j = 0; j < NUM_TRAIN_ENGINES; j++) { |
238 for (j = 0; j < NUM_TRAIN_ENGINES; j++) { |
197 EngineID i = GetRailVehAtPosition(j); |
239 EngineID i = GetRailVehAtPosition(j); |
198 const Engine *e = GetEngine(i); |
240 const Engine *e = GetEngine(i); |
199 const RailVehicleInfo *rvi = RailVehInfo(i); |
241 const RailVehicleInfo *rvi = RailVehInfo(i); |
200 |
242 |
201 if (!HasPowerOnRail(e->railtype, railtype) || !(rvi->flags & RVI_WAGON) != is_engine || |
243 if (!HasPowerOnRail(e->railtype, railtype)) continue; |
202 !HASBIT(e->player_avail, _local_player)) |
244 if (!IsEngineBuildable(i, VEH_Train)) continue; |
203 continue; |
245 |
204 |
246 if (rvi->flags & RVI_WAGON) { |
205 if (*sel == 0) *selected_id = i; |
247 if (*num_wagons == wagon_length) ExtendEngineListSize((const EngineID**)wagons, &wagon_length, 5); |
206 |
248 (*wagons)[(*num_wagons)++] = i; |
207 if (IS_INT_INSIDE(--*pos, -show_max, 0)) { |
249 } else { |
208 DrawString(*x + 59, *y + 2, GetCustomEngineName(i), *sel == 0 ? 0xC : 0x10); |
250 if (*num_engines == engine_length) ExtendEngineListSize((const EngineID**)engines, &engine_length, 5); |
209 DrawTrainEngine(*x + 29, *y + 6, i, GetEnginePalette(i, _local_player)); |
251 (*engines)[(*num_engines)++] = i; |
210 *y += 14; |
252 } |
211 } |
253 } |
212 --*sel; |
254 |
|
255 /* Reduce array sizes if they are too big */ |
|
256 if (*num_engines == engine_length) *engines = realloc((void*)*engines, (*num_engines) * sizeof((*engines)[0])); |
|
257 if (*num_wagons == wagon_length) *wagons = realloc((void*)*wagons, (*num_wagons) * sizeof((*wagons)[0])); |
|
258 } |
|
259 |
|
260 static void DrawTrainBuildWindow(Window *w) |
|
261 { |
|
262 int x = 1; |
|
263 int y = 15; |
|
264 EngineID position = w->vscroll.pos; |
|
265 EngineID selected_id = WP(w,buildtrain_d).sel_engine; |
|
266 int max = w->vscroll.pos + w->vscroll.cap; |
|
267 uint16 scrollcount = 0; |
|
268 |
|
269 SetWindowWidgetDisabledState(w, BUILD_TRAIN_WIDGET_BUILD, w->window_number == 0); // Disable unless we got a depot to build in |
|
270 |
|
271 /* Draw the clicked engine/wagon/both button pressed and unpress the other two */ |
|
272 SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_ENGINES, WP(w,buildtrain_d).show_engine_wagon == 1); |
|
273 SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_WAGONS, WP(w,buildtrain_d).show_engine_wagon == 2); |
|
274 SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_BOTH, WP(w,buildtrain_d).show_engine_wagon == 3); |
|
275 |
|
276 GenerateBuildList(&WP(w,buildtrain_d).engines, &WP(w,buildtrain_d).num_engines, &WP(w,buildtrain_d).wagons, &WP(w,buildtrain_d).num_wagons, WP(w,buildtrain_d).railtype); |
|
277 |
|
278 if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) scrollcount += WP(w,buildtrain_d).num_engines; |
|
279 if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 1)) scrollcount += WP(w,buildtrain_d).num_wagons; |
|
280 |
|
281 SetVScrollCount(w, scrollcount); |
|
282 SetDParam(0, WP(w,buildtrain_d).railtype + STR_881C_NEW_RAIL_VEHICLES); |
|
283 DrawWindowWidgets(w); |
|
284 |
|
285 if (selected_id == INVALID_ENGINE && scrollcount != 0) { |
|
286 if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0) && WP(w,buildtrain_d).num_engines != 0) { |
|
287 selected_id = WP(w,buildtrain_d).engines[0]; |
|
288 } else { |
|
289 selected_id = WP(w,buildtrain_d).wagons[0]; |
|
290 } |
|
291 WP(w,buildtrain_d).sel_engine = selected_id; |
|
292 } |
|
293 |
|
294 /* Draw the engines */ |
|
295 if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) { |
|
296 engine_drawing_loop(WP(w,buildtrain_d).engines, WP(w,buildtrain_d).num_engines, x, &y, selected_id, &position, max); |
|
297 |
|
298 /* Magically set the number 0 line to the one right after the last engine |
|
299 * This way the line numbers fit the indexes in the wagon array */ |
|
300 position -= WP(w,buildtrain_d).num_engines; |
|
301 max -= WP(w,buildtrain_d).num_engines; |
|
302 } |
|
303 |
|
304 /* Draw the wagons */ |
|
305 if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 1)) { |
|
306 engine_drawing_loop(WP(w,buildtrain_d).wagons, WP(w,buildtrain_d).num_wagons, x, &y, selected_id, &position, max); |
|
307 } |
|
308 |
|
309 if (selected_id != INVALID_ENGINE) { |
|
310 const RailVehicleInfo *rvi = RailVehInfo(selected_id); |
|
311 |
|
312 if (rvi->flags & RVI_WAGON) { |
|
313 DrawTrainWagonPurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id); |
|
314 } else { |
|
315 DrawTrainEnginePurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id); |
|
316 } |
213 } |
317 } |
214 } |
318 } |
215 |
319 |
216 static void NewRailVehicleWndProc(Window *w, WindowEvent *e) |
320 static void NewRailVehicleWndProc(Window *w, WindowEvent *e) |
217 { |
321 { |
218 switch (e->event) { |
322 switch (e->event) { |
|
323 case WE_CREATE: |
|
324 WP(w,buildtrain_d).num_engines = 0; |
|
325 WP(w,buildtrain_d).num_wagons = 0; |
|
326 WP(w,buildtrain_d).engines = NULL; |
|
327 WP(w,buildtrain_d).wagons = NULL; |
|
328 WP(w,buildtrain_d).show_engine_wagon = 3; |
|
329 break; |
|
330 |
|
331 case WE_DESTROY: |
|
332 free((void*)WP(w,buildtrain_d).engines); |
|
333 free((void*)WP(w,buildtrain_d).wagons); |
|
334 break; |
|
335 |
219 case WE_PAINT: |
336 case WE_PAINT: |
220 |
337 DrawTrainBuildWindow(w); |
221 SetWindowWidgetDisabledState(w, BUILD_TRAIN_WIDGET_BUILD, w->window_number == 0); |
338 break; |
222 |
339 |
223 { |
|
224 int count = 0; |
|
225 RailType railtype = WP(w,buildtrain_d).railtype; |
|
226 EngineID i; |
|
227 |
|
228 for (i = 0; i < NUM_TRAIN_ENGINES; i++) { |
|
229 const Engine *e = GetEngine(i); |
|
230 if (HasPowerOnRail(e->railtype, railtype) && |
|
231 HASBIT(e->player_avail, _local_player)) { |
|
232 count++; |
|
233 } |
|
234 } |
|
235 SetVScrollCount(w, count); |
|
236 } |
|
237 |
|
238 SetDParam(0, WP(w,buildtrain_d).railtype + STR_881C_NEW_RAIL_VEHICLES); |
|
239 DrawWindowWidgets(w); |
|
240 |
|
241 { |
|
242 RailType railtype = WP(w,buildtrain_d).railtype; |
|
243 int sel = WP(w,buildtrain_d).sel_index; |
|
244 int pos = w->vscroll.pos; |
|
245 int x = 1; |
|
246 int y = 15; |
|
247 EngineID selected_id = INVALID_ENGINE; |
|
248 |
|
249 /* Ensure that custom engines which substituted wagons |
|
250 * are sorted correctly. |
|
251 * XXX - DO NOT EVER DO THIS EVER AGAIN! GRRR hacking in wagons as |
|
252 * engines to get more types.. Stays here until we have our own format |
|
253 * then it is exit!!! */ |
|
254 engine_drawing_loop(&x, &y, &pos, &sel, &selected_id, railtype, w->vscroll.cap, true); // True engines |
|
255 engine_drawing_loop(&x, &y, &pos, &sel, &selected_id, railtype, w->vscroll.cap, false); // Feeble wagons |
|
256 |
|
257 WP(w,buildtrain_d).sel_engine = selected_id; |
|
258 |
|
259 if (selected_id != INVALID_ENGINE) { |
|
260 const RailVehicleInfo *rvi = RailVehInfo(selected_id); |
|
261 |
|
262 if (!(rvi->flags & RVI_WAGON)) { |
|
263 /* it's an engine */ |
|
264 DrawTrainEnginePurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1,selected_id); |
|
265 } else { |
|
266 /* it's a wagon */ |
|
267 DrawTrainWagonPurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id); |
|
268 } |
|
269 } |
|
270 } |
|
271 break; |
|
272 |
340 |
273 case WE_CLICK: { |
341 case WE_CLICK: { |
274 switch (e->we.click.widget) { |
342 switch (e->we.click.widget) { |
275 case BUILD_TRAIN_WIDGET_LIST: { |
343 case BUILD_TRAIN_WIDGET_LIST: { |
276 uint i = (e->we.click.pt.y - 14) / 14; |
344 uint i = ((e->we.click.pt.y - 14) / 14) + w->vscroll.pos; |
277 if (i < w->vscroll.cap) { |
345 if (i < WP(w,buildtrain_d).num_engines + WP(w,buildtrain_d).num_wagons) { |
278 WP(w,buildtrain_d).sel_index = i + w->vscroll.pos; |
346 if (i < WP(w,buildtrain_d).num_engines && HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) { |
|
347 WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).engines[i]; |
|
348 } else { |
|
349 WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).wagons[i - (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0) ? WP(w,buildtrain_d).num_engines : 0)]; |
|
350 } |
279 SetWindowDirty(w); |
351 SetWindowDirty(w); |
280 } |
352 } |
281 } break; |
353 } break; |
|
354 |
|
355 case BUILD_TRAIN_WIDGET_ENGINES: |
|
356 case BUILD_TRAIN_WIDGET_WAGONS: |
|
357 case BUILD_TRAIN_WIDGET_BOTH: { |
|
358 /* First we need to figure out the new show_engine_wagon setting |
|
359 * Because the button widgets are ordered as they are (in a row), we can calculate as following: |
|
360 * engines = bit 0 (1 for set), wagons bit 1 (2 for set), both (2 | 1 = 3) |
|
361 * Those numbers are the same as the clicked button - BUILD_TRAIN_WIDGET_ENGINES + 1 */ |
|
362 |
|
363 byte click_state = e->we.click.widget - BUILD_TRAIN_WIDGET_ENGINES + 1; |
|
364 if (WP(w,buildtrain_d).show_engine_wagon == click_state) break; // We clicked the pressed button |
|
365 WP(w,buildtrain_d).sel_engine = INVALID_ENGINE; |
|
366 WP(w,buildtrain_d).show_engine_wagon = click_state; |
|
367 w->vscroll.pos = 0; |
|
368 SetWindowDirty(w); |
|
369 } |
|
370 break; |
282 |
371 |
283 case BUILD_TRAIN_WIDGET_BUILD: { |
372 case BUILD_TRAIN_WIDGET_BUILD: { |
284 EngineID sel_eng = WP(w,buildtrain_d).sel_engine; |
373 EngineID sel_eng = WP(w,buildtrain_d).sel_engine; |
285 if (sel_eng != INVALID_ENGINE) |
374 if (sel_eng != INVALID_ENGINE) |
286 DoCommandP(w->window_number, sel_eng, 0, (RailVehInfo(sel_eng)->flags & RVI_WAGON) ? CcBuildWagon : CcBuildLoco, CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE)); |
375 DoCommandP(w->window_number, sel_eng, 0, (RailVehInfo(sel_eng)->flags & RVI_WAGON) ? CcBuildWagon : CcBuildLoco, CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE)); |
312 w->widget[BUILD_TRAIN_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1; |
401 w->widget[BUILD_TRAIN_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1; |
313 } break; |
402 } break; |
314 } |
403 } |
315 } |
404 } |
316 |
405 |
317 static const Widget _new_rail_vehicle_widgets[] = { |
|
318 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
|
319 { WWT_CAPTION, RESIZE_NONE, 14, 11, 227, 0, 13, STR_JUST_STRING, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
|
320 { WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 215, 14, 125, 0x801, STR_8843_TRAIN_VEHICLE_SELECTION}, |
|
321 { WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 216, 227, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, |
|
322 { WWT_PANEL, RESIZE_TB, 14, 0, 227, 126, 197, 0x0, STR_NULL}, |
|
323 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 107, 198, 209, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN}, |
|
324 { WWT_PUSHTXTBTN, RESIZE_TB, 14, 108, 215, 198, 209, STR_8820_RENAME, STR_8845_RENAME_TRAIN_VEHICLE_TYPE}, |
|
325 { WWT_RESIZEBOX, RESIZE_TB, 14, 216, 227, 198, 209, 0x0, STR_RESIZE_BUTTON}, |
|
326 { WIDGETS_END}, |
|
327 }; |
|
328 |
|
329 static const WindowDesc _new_rail_vehicle_desc = { |
406 static const WindowDesc _new_rail_vehicle_desc = { |
330 -1, -1, 228, 210, |
407 -1, -1, 228, 222, |
331 WC_BUILD_VEHICLE,0, |
408 WC_BUILD_VEHICLE,0, |
332 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, |
409 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, |
333 _new_rail_vehicle_widgets, |
410 _new_rail_vehicle_widgets, |
334 NewRailVehicleWndProc |
411 NewRailVehicleWndProc |
335 }; |
412 }; |