398 'B', |
398 'B', |
399 'T', |
399 'T', |
400 'R', |
400 'R', |
401 }; |
401 }; |
402 |
402 |
403 /** |
403 struct BuildRoadToolbarWindow : Window { |
404 * Update the remove button lowered state of the road toolbar |
404 BuildRoadToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) |
405 * |
405 { |
406 * @param w The toolbar window |
406 this->SetWidgetsDisabledState(true, |
407 * @param clicked_widget The widget which the player clicked just now |
407 RTW_REMOVE, |
408 */ |
408 RTW_ONE_WAY, |
409 static void UpdateOptionWidgetStatus(Window *w, RoadToolbarWidgets clicked_widget) |
409 WIDGET_LIST_END); |
410 { |
410 |
411 /* The remove and the one way button state is driven |
411 this->FindWindowPlacementAndResize(desc); |
412 * by the other buttons so they don't act on themselfs. |
412 if (_patches.link_terraform_toolbar) ShowTerraformToolbar(this); |
413 * Both are only valid if they are able to apply as options. */ |
413 } |
414 switch (clicked_widget) { |
414 |
415 case RTW_REMOVE: |
415 ~BuildRoadToolbarWindow() |
416 w->RaiseWidget(RTW_ONE_WAY); |
416 { |
417 w->InvalidateWidget(RTW_ONE_WAY); |
417 if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); |
418 break; |
418 } |
419 |
419 |
420 case RTW_ONE_WAY: |
420 /** |
421 w->RaiseWidget(RTW_REMOVE); |
421 * Update the remove button lowered state of the road toolbar |
422 w->InvalidateWidget(RTW_REMOVE); |
422 * |
423 break; |
423 * @param clicked_widget The widget which the player clicked just now |
424 |
424 */ |
425 case RTW_BUS_STATION: |
425 void UpdateOptionWidgetStatus(RoadToolbarWidgets clicked_widget) |
426 case RTW_TRUCK_STATION: |
426 { |
427 w->DisableWidget(RTW_ONE_WAY); |
427 /* The remove and the one way button state is driven |
428 w->SetWidgetDisabledState(RTW_REMOVE, !w->IsWidgetLowered(clicked_widget)); |
428 * by the other buttons so they don't act on themselfs. |
429 break; |
429 * Both are only valid if they are able to apply as options. */ |
430 |
430 switch (clicked_widget) { |
431 case RTW_ROAD_X: |
431 case RTW_REMOVE: |
432 case RTW_ROAD_Y: |
432 this->RaiseWidget(RTW_ONE_WAY); |
433 case RTW_AUTOROAD: |
433 this->InvalidateWidget(RTW_ONE_WAY); |
434 w->SetWidgetsDisabledState(!w->IsWidgetLowered(clicked_widget), |
434 break; |
435 RTW_REMOVE, |
435 |
436 RTW_ONE_WAY, |
436 case RTW_ONE_WAY: |
437 WIDGET_LIST_END); |
437 this->RaiseWidget(RTW_REMOVE); |
438 break; |
438 this->InvalidateWidget(RTW_REMOVE); |
439 |
439 break; |
440 default: |
440 |
441 /* When any other buttons than road/station, raise and |
441 case RTW_BUS_STATION: |
442 * disable the removal button */ |
442 case RTW_TRUCK_STATION: |
443 w->SetWidgetsDisabledState(true, |
443 this->DisableWidget(RTW_ONE_WAY); |
444 RTW_REMOVE, |
444 this->SetWidgetDisabledState(RTW_REMOVE, !this->IsWidgetLowered(clicked_widget)); |
445 RTW_ONE_WAY, |
445 break; |
446 WIDGET_LIST_END); |
446 |
447 w->SetWidgetsLoweredState (false, |
447 case RTW_ROAD_X: |
448 RTW_REMOVE, |
448 case RTW_ROAD_Y: |
449 RTW_ONE_WAY, |
449 case RTW_AUTOROAD: |
450 WIDGET_LIST_END); |
450 this->SetWidgetsDisabledState(!this->IsWidgetLowered(clicked_widget), |
451 break; |
451 RTW_REMOVE, |
452 } |
452 RTW_ONE_WAY, |
453 } |
453 WIDGET_LIST_END); |
454 |
454 break; |
455 static void BuildRoadToolbWndProc(Window *w, WindowEvent *e) |
455 |
456 { |
456 default: |
457 switch (e->event) { |
457 /* When any other buttons than road/station, raise and |
458 case WE_CREATE: |
458 * disable the removal button */ |
459 w->SetWidgetsDisabledState(true, |
459 this->SetWidgetsDisabledState(true, |
460 RTW_REMOVE, |
460 RTW_REMOVE, |
461 RTW_ONE_WAY, |
461 RTW_ONE_WAY, |
462 WIDGET_LIST_END); |
462 WIDGET_LIST_END); |
463 break; |
463 this->SetWidgetsLoweredState (false, |
464 |
464 RTW_REMOVE, |
465 case WE_PAINT: |
465 RTW_ONE_WAY, |
466 w->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD), |
466 WIDGET_LIST_END); |
467 RTW_DEPOT, |
467 break; |
468 RTW_BUS_STATION, |
468 } |
469 RTW_TRUCK_STATION, |
469 } |
470 WIDGET_LIST_END); |
470 |
471 w->DrawWidgets(); |
471 virtual void OnPaint() |
472 break; |
472 { |
473 |
473 this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD), |
474 case WE_CLICK: |
474 RTW_DEPOT, |
475 if (e->we.click.widget >= RTW_ROAD_X) { |
475 RTW_BUS_STATION, |
|
476 RTW_TRUCK_STATION, |
|
477 WIDGET_LIST_END); |
|
478 this->DrawWidgets(); |
|
479 } |
|
480 |
|
481 virtual void OnClick(Point pt, int widget) |
|
482 { |
|
483 if (widget >= RTW_ROAD_X) { |
|
484 _remove_button_clicked = false; |
|
485 _one_way_button_clicked = false; |
|
486 _build_road_button_proc[widget - RTW_ROAD_X](this); |
|
487 } |
|
488 this->UpdateOptionWidgetStatus((RoadToolbarWidgets)widget); |
|
489 if (_ctrl_pressed) RoadToolbar_CtrlChanged(this); |
|
490 } |
|
491 |
|
492 virtual EventState OnKeyPress(uint16 key, uint16 keycode) |
|
493 { |
|
494 EventState state = ES_NOT_HANDLED; |
|
495 for (uint i = 0; i != lengthof(_road_keycodes); i++) { |
|
496 if (keycode == _road_keycodes[i]) { |
476 _remove_button_clicked = false; |
497 _remove_button_clicked = false; |
477 _one_way_button_clicked = false; |
498 _one_way_button_clicked = false; |
478 _build_road_button_proc[e->we.click.widget - RTW_ROAD_X](w); |
499 _build_road_button_proc[i](this); |
|
500 this->UpdateOptionWidgetStatus((RoadToolbarWidgets)(i + RTW_ROAD_X)); |
|
501 if (_ctrl_pressed) RoadToolbar_CtrlChanged(this); |
|
502 state = ES_HANDLED; |
|
503 break; |
479 } |
504 } |
480 UpdateOptionWidgetStatus(w, (RoadToolbarWidgets)e->we.click.widget); |
505 } |
481 if (_ctrl_pressed) RoadToolbar_CtrlChanged(w); |
506 MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection |
482 break; |
507 return state; |
483 |
508 } |
484 case WE_KEYPRESS: |
509 |
485 for (uint i = 0; i != lengthof(_road_keycodes); i++) { |
510 virtual void OnPlaceObject(Point pt, TileIndex tile) |
486 if (e->we.keypress.keycode == _road_keycodes[i]) { |
511 { |
487 e->we.keypress.cont = false; |
512 _remove_button_clicked = this->IsWidgetLowered(RTW_REMOVE); |
488 _remove_button_clicked = false; |
513 _one_way_button_clicked = this->IsWidgetLowered(RTW_ONE_WAY); |
489 _one_way_button_clicked = false; |
514 _place_proc(tile); |
490 _build_road_button_proc[i](w); |
515 } |
491 UpdateOptionWidgetStatus(w, (RoadToolbarWidgets)(i + RTW_ROAD_X)); |
516 |
492 if (_ctrl_pressed) RoadToolbar_CtrlChanged(w); |
517 virtual void OnPlaceObjectAbort() |
|
518 { |
|
519 this->RaiseButtons(); |
|
520 this->SetWidgetsDisabledState(true, |
|
521 RTW_REMOVE, |
|
522 RTW_ONE_WAY, |
|
523 WIDGET_LIST_END); |
|
524 this->InvalidateWidget(RTW_REMOVE); |
|
525 this->InvalidateWidget(RTW_ONE_WAY); |
|
526 |
|
527 delete FindWindowById(WC_BUS_STATION, 0); |
|
528 delete FindWindowById(WC_TRUCK_STATION, 0); |
|
529 delete FindWindowById(WC_BUILD_DEPOT, 0); |
|
530 } |
|
531 |
|
532 virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) |
|
533 { |
|
534 /* Here we update the end tile flags |
|
535 * of the road placement actions. |
|
536 * At first we reset the end halfroad |
|
537 * bits and if needed we set them again. */ |
|
538 switch (select_proc) { |
|
539 case DDSP_PLACE_ROAD_X_DIR: |
|
540 _place_road_flag &= ~RF_END_HALFROAD_X; |
|
541 if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X; |
|
542 break; |
|
543 |
|
544 case DDSP_PLACE_ROAD_Y_DIR: |
|
545 _place_road_flag &= ~RF_END_HALFROAD_Y; |
|
546 if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y; |
|
547 break; |
|
548 |
|
549 case DDSP_PLACE_AUTOROAD: |
|
550 _place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X); |
|
551 if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y; |
|
552 if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X; |
|
553 |
|
554 /* For autoroad we need to update the |
|
555 * direction of the road */ |
|
556 if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y && |
|
557 ( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) || |
|
558 (_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) { |
|
559 /* Set dir = X */ |
|
560 _place_road_flag &= ~RF_DIR_Y; |
|
561 } else { |
|
562 /* Set dir = Y */ |
|
563 _place_road_flag |= RF_DIR_Y; |
|
564 } |
|
565 |
|
566 break; |
|
567 |
|
568 default: |
|
569 break; |
|
570 } |
|
571 |
|
572 VpSelectTilesWithMethod(pt.x, pt.y, select_method); |
|
573 } |
|
574 |
|
575 virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) |
|
576 { |
|
577 if (pt.x != -1) { |
|
578 switch (select_proc) { |
|
579 default: NOT_REACHED(); |
|
580 case DDSP_BUILD_BRIDGE: |
|
581 ResetObjectToPlace(); |
|
582 ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype)); |
493 break; |
583 break; |
494 } |
584 |
495 } |
585 case DDSP_DEMOLISH_AREA: |
496 MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection |
586 GUIPlaceProcDragXY(select_proc, start_tile, end_tile); |
497 break; |
587 break; |
498 |
588 |
499 case WE_PLACE_OBJ: |
|
500 _remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE); |
|
501 _one_way_button_clicked = w->IsWidgetLowered(RTW_ONE_WAY); |
|
502 _place_proc(e->we.place.tile); |
|
503 break; |
|
504 |
|
505 case WE_ABORT_PLACE_OBJ: |
|
506 w->RaiseButtons(); |
|
507 w->SetWidgetsDisabledState(true, |
|
508 RTW_REMOVE, |
|
509 RTW_ONE_WAY, |
|
510 WIDGET_LIST_END); |
|
511 w->InvalidateWidget(RTW_REMOVE); |
|
512 w->InvalidateWidget(RTW_ONE_WAY); |
|
513 |
|
514 delete FindWindowById(WC_BUS_STATION, 0); |
|
515 delete FindWindowById(WC_TRUCK_STATION, 0); |
|
516 delete FindWindowById(WC_BUILD_DEPOT, 0); |
|
517 break; |
|
518 |
|
519 case WE_PLACE_DRAG: |
|
520 /* Here we update the end tile flags |
|
521 * of the road placement actions. |
|
522 * At first we reset the end halfroad |
|
523 * bits and if needed we set them again. */ |
|
524 switch (e->we.place.select_proc) { |
|
525 case DDSP_PLACE_ROAD_X_DIR: |
589 case DDSP_PLACE_ROAD_X_DIR: |
526 _place_road_flag &= ~RF_END_HALFROAD_X; |
|
527 if (e->we.place.pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X; |
|
528 break; |
|
529 |
|
530 case DDSP_PLACE_ROAD_Y_DIR: |
590 case DDSP_PLACE_ROAD_Y_DIR: |
531 _place_road_flag &= ~RF_END_HALFROAD_Y; |
|
532 if (e->we.place.pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y; |
|
533 break; |
|
534 |
|
535 case DDSP_PLACE_AUTOROAD: |
591 case DDSP_PLACE_AUTOROAD: |
536 _place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X); |
592 /* Flag description: |
537 if (e->we.place.pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y; |
593 * Use the first three bits (0x07) if dir == Y |
538 if (e->we.place.pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X; |
594 * else use the last 2 bits (X dir has |
539 |
595 * not the 3rd bit set) */ |
540 /* For autoroad we need to update the |
596 _place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3)); |
541 * direction of the road */ |
597 |
542 if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y && |
598 DoCommandP(end_tile, start_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5), CcPlaySound1D, |
543 ( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) || |
599 (_ctrl_pressed || _remove_button_clicked) ? |
544 (_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) { |
600 CMD_REMOVE_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) : |
545 /* Set dir = X */ |
601 CMD_BUILD_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road)); |
546 _place_road_flag &= ~RF_DIR_Y; |
|
547 } else { |
|
548 /* Set dir = Y */ |
|
549 _place_road_flag |= RF_DIR_Y; |
|
550 } |
|
551 |
|
552 break; |
|
553 |
|
554 default: |
|
555 break; |
602 break; |
556 } |
603 } |
557 |
604 } |
558 VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method); |
605 } |
559 return; |
606 |
560 |
607 virtual void OnPlacePresize(Point pt, TileIndex tile) |
561 case WE_PLACE_MOUSEUP: |
608 { |
562 if (e->we.place.pt.x != -1) { |
609 DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL); |
563 TileIndex start_tile = e->we.place.starttile; |
610 VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); |
564 TileIndex end_tile = e->we.place.tile; |
611 } |
565 |
612 |
566 switch (e->we.place.select_proc) { |
613 virtual EventState OnCTRLStateChange() |
567 default: NOT_REACHED(); |
614 { |
568 case DDSP_BUILD_BRIDGE: |
615 if (RoadToolbar_CtrlChanged(this)) return ES_HANDLED; |
569 ResetObjectToPlace(); |
616 return ES_NOT_HANDLED; |
570 ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype)); |
617 } |
571 break; |
618 }; |
572 |
|
573 case DDSP_DEMOLISH_AREA: |
|
574 GUIPlaceProcDragXY(e->we.place.select_proc, e->we.place.starttile, e->we.place.tile); |
|
575 break; |
|
576 |
|
577 case DDSP_PLACE_ROAD_X_DIR: |
|
578 case DDSP_PLACE_ROAD_Y_DIR: |
|
579 case DDSP_PLACE_AUTOROAD: |
|
580 /* Flag description: |
|
581 * Use the first three bits (0x07) if dir == Y |
|
582 * else use the last 2 bits (X dir has |
|
583 * not the 3rd bit set) */ |
|
584 _place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3)); |
|
585 |
|
586 DoCommandP(end_tile, start_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5), CcPlaySound1D, |
|
587 (_ctrl_pressed || _remove_button_clicked) ? |
|
588 CMD_REMOVE_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) : |
|
589 CMD_BUILD_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road)); |
|
590 break; |
|
591 } |
|
592 } |
|
593 break; |
|
594 |
|
595 case WE_PLACE_PRESIZE: { |
|
596 TileIndex tile = e->we.place.tile; |
|
597 |
|
598 DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL); |
|
599 VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); |
|
600 } break; |
|
601 |
|
602 case WE_DESTROY: |
|
603 if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); |
|
604 break; |
|
605 |
|
606 case WE_CTRL_CHANGED: |
|
607 if (RoadToolbar_CtrlChanged(w)) e->we.ctrl.cont = false; |
|
608 break; |
|
609 |
|
610 default: |
|
611 break; |
|
612 } |
|
613 } |
|
614 |
619 |
615 /** Widget definition of the build road toolbar */ |
620 /** Widget definition of the build road toolbar */ |
616 static const Widget _build_road_widgets[] = { |
621 static const Widget _build_road_widgets[] = { |
617 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // RTW_CLOSEBOX |
622 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // RTW_CLOSEBOX |
618 { WWT_CAPTION, RESIZE_NONE, 7, 11, 250, 0, 13, STR_1802_ROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // RTW_CAPTION |
623 { WWT_CAPTION, RESIZE_NONE, 7, 11, 250, 0, 13, STR_1802_ROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // RTW_CAPTION |