OpenLoco/src/OpenLoco/Windows/Construction/OverheadTab.cpp

313 lines
11 KiB
C++

#include "../../CompanyManager.h"
#include "../../Graphics/ImageIds.h"
#include "../../Input.h"
#include "../../Localisation/FormatArguments.hpp"
#include "../../Objects/ObjectManager.h"
#include "../../Objects/RoadExtraObject.h"
#include "../../Objects/RoadObject.h"
#include "../../Objects/TrackExtraObject.h"
#include "../../Objects/TrackObject.h"
#include "../../Ui/Dropdown.h"
#include "../../Widget.h"
#include "Construction.h"
using namespace OpenLoco::Interop;
using namespace OpenLoco::Map;
using namespace OpenLoco::Map::TileManager;
namespace OpenLoco::Ui::Windows::Construction::Overhead
{
static loco_global<int32_t, 0x00E3F0B8> gCurrentRotation;
Widget widgets[] = {
commonWidgets(138, 192, StringIds::stringid_2),
makeWidget({ 3, 45 }, { 132, 12 }, WidgetType::checkbox, WindowColour::secondary, StringIds::empty, StringIds::tooltip_select_track_mod),
makeWidget({ 3, 57 }, { 132, 12 }, WidgetType::checkbox, WindowColour::secondary, StringIds::empty, StringIds::tooltip_select_track_mod),
makeWidget({ 3, 69 }, { 132, 12 }, WidgetType::checkbox, WindowColour::secondary, StringIds::empty, StringIds::tooltip_select_track_mod),
makeWidget({ 3, 81 }, { 132, 12 }, WidgetType::checkbox, WindowColour::secondary, StringIds::empty, StringIds::tooltip_select_track_mod),
makeWidget({ 35, 110 }, { 66, 66 }, WidgetType::wt_3, WindowColour::secondary),
makeWidget({ 3, 95 }, { 132, 12 }, WidgetType::wt_18, WindowColour::secondary, 0xFFFFFFFF, StringIds::tooltip_select_track_to_upgrade),
makeWidget({ 123, 96 }, { 11, 10 }, WidgetType::wt_11, WindowColour::secondary, StringIds::dropdown, StringIds::tooltip_select_track_to_upgrade),
widgetEnd(),
};
WindowEventList events;
// 0x0049EBD1
static void onMouseUp(Window* self, WidgetIndex_t widgetIndex)
{
switch (widgetIndex)
{
case Common::widx::close_button:
WindowManager::close(self);
break;
case Common::widx::tab_construction:
case Common::widx::tab_overhead:
case Common::widx::tab_signal:
case Common::widx::tab_station:
Common::switchTab(self, widgetIndex);
break;
case widx::checkbox_1:
case widx::checkbox_2:
case widx::checkbox_3:
case widx::checkbox_4:
{
auto checkboxIndex = widgetIndex - widx::checkbox_1;
_lastSelectedMods = _lastSelectedMods ^ (1 << checkboxIndex);
// TODO: & ~(1 << 7) added to prevent crashing when selecting/deselecting overhead wires for trams
_scenarioTrackMods[_trackType & ~(1 << 7)] = _lastSelectedMods;
self->invalidate();
break;
}
}
}
// 0x0049EBFC
static void onMouseDown(Window* self, WidgetIndex_t widgetIndex)
{
switch (widgetIndex)
{
case widx::track_dropdown:
{
uint8_t modCount = 3;
auto widget = self->widgets[widx::track];
auto xPos = widget.left + self->x;
auto yPos = widget.top + self->y;
auto width = widget.width() + 2;
auto height = widget.height();
Dropdown::show(xPos, yPos, width, height, self->getColour(WindowColour::secondary), modCount, (1 << 7));
Dropdown::add(0, StringIds::single_section);
Dropdown::add(1, StringIds::block_section);
Dropdown::add(2, StringIds::all_connected_track);
Dropdown::setHighlightedItem(_lastSelectedTrackModSection);
break;
}
case widx::image:
{
Input::toolCancel();
Input::toolSet(self, widgetIndex, 12);
break;
}
}
}
// 0x0049EC09
static void onDropdown(Window* self, WidgetIndex_t widgetIndex, int16_t itemIndex)
{
if (widgetIndex != widx::track_dropdown)
return;
if (itemIndex != -1)
{
_lastSelectedTrackModSection = itemIndex;
self->invalidate();
}
}
// 0x0049ECD1
static void onUpdate(Window* self)
{
Common::onUpdate(self, (1 << 5));
}
// 0x0049EC15
static void onToolUpdate(Window& self, const WidgetIndex_t widgetIndex, const int16_t x, const int16_t y)
{
registers regs;
regs.esi = (int32_t)&self;
regs.dx = widgetIndex;
regs.ax = x;
regs.bx = y;
call(0x0049EC15, regs);
}
// 0x0049EC20
static void onToolDown(Window& self, const WidgetIndex_t widgetIndex, const int16_t x, const int16_t y)
{
registers regs;
regs.esi = (int32_t)&self;
regs.dx = widgetIndex;
regs.ax = x;
regs.bx = y;
call(0x0049EC20, regs);
}
static void setCheckbox(Window* self, WidgetIndex_t checkboxIndex, string_id name)
{
auto widgetIndex = checkboxIndex + widx::checkbox_1;
self->widgets[widgetIndex].type = WidgetType::checkbox;
self->widgets[widgetIndex].text = name;
if (_lastSelectedMods & (1 << checkboxIndex))
self->activated_widgets |= (1ULL << widgetIndex);
}
// 0x0049E7D3
static void prepareDraw(Window* self)
{
Common::prepareDraw(self);
self->activated_widgets &= ~(1 << widx::checkbox_1 | 1 << widx::checkbox_2 | 1 << widx::checkbox_3 | 1 << widx::checkbox_4);
self->widgets[widx::checkbox_1].type = WidgetType::none;
self->widgets[widx::checkbox_2].type = WidgetType::none;
self->widgets[widx::checkbox_3].type = WidgetType::none;
self->widgets[widx::checkbox_4].type = WidgetType::none;
if (_trackType & (1 << 7))
{
auto trackType = _trackType & ~(1 << 7);
auto roadObj = ObjectManager::get<RoadObject>(trackType);
auto args = FormatArguments();
args.push(roadObj->name);
for (auto i = 0; i < 2; i++)
{
if (_modList[i] != 0xFF)
{
auto extraName = ObjectManager::get<RoadExtraObject>(_modList[i])->name;
setCheckbox(self, i, extraName);
}
}
}
else
{
auto trackObj = ObjectManager::get<TrackObject>(_trackType);
auto args = FormatArguments();
args.push(trackObj->name);
for (auto i = 0; i < 4; i++)
{
if (_modList[i] != 0xFF)
{
auto extraName = ObjectManager::get<TrackExtraObject>(_modList[i])->name;
setCheckbox(self, i, extraName);
}
}
}
//self->activated_widgets = activatedWidgets;
self->widgets[widx::image].type = WidgetType::none;
self->widgets[widx::track].type = WidgetType::none;
self->widgets[widx::track_dropdown].type = WidgetType::none;
self->widgets[widx::image].tooltip = StringIds::null;
if (_lastSelectedMods & 0xF)
{
self->widgets[widx::image].type = WidgetType::wt_3;
self->widgets[widx::track].type = WidgetType::wt_18;
self->widgets[widx::track_dropdown].type = WidgetType::wt_11;
self->widgets[widx::image].tooltip = StringIds::upgrade_track_with_mods;
if (isNetworkHost())
{
if (_toolWindowType == WindowType::construction)
self->widgets[widx::image].tooltip = StringIds::click_track_to_upgrade;
}
}
static string_id modString[] = {
StringIds::single_section,
StringIds::block_section,
StringIds::all_connected_track,
};
self->widgets[widx::track].text = modString[_lastSelectedTrackModSection];
Common::repositionTabs(self);
}
// 0x0049EA3E
static void draw(Window* self, Gfx::Context* context)
{
self->draw(context);
Common::drawTabs(self, context);
if (_lastSelectedMods & 0xF)
{
Gfx::Context* clipped = nullptr;
auto xPos = self->x + self->widgets[widx::image].left + 1;
auto yPos = self->y + self->widgets[widx::image].top + 1;
auto width = self->widgets[widx::image].width();
auto height = self->widgets[widx::image].height();
if (Gfx::clipContext(&clipped, context, xPos, yPos, width, height))
{
coord_t x = 0x2010;
coord_t y = 0x2010;
auto rotCoord = rotate2dCoordinate({ x, y }, gCurrentRotation);
Gfx::point_t screenPos = { static_cast<int16_t>(rotCoord.y - rotCoord.x), static_cast<int16_t>(((rotCoord.x + rotCoord.y) >> 1) - 460) };
screenPos.x -= (self->widgets[widx::image].width() / 2);
screenPos.y -= ((self->widgets[widx::image].width() / 2) + 16);
clipped->x += screenPos.x;
clipped->y += screenPos.y;
_dword_E0C3E0 = clipped;
x = 0x2000;
y = 0x2000;
auto company = CompanyManager::get(_playerCompany);
auto companyColour = company->mainColours.primary;
_byte_522095 = _byte_522095 | (1 << 0);
if (_trackType & (1 << 7))
{
uint8_t trackType = _trackType & ~(1 << 7);
Construction::drawRoad(x, y, _lastSelectedMods, 0x1D0, trackType, 0, companyColour, gCurrentRotation);
}
else
{
Construction::drawTrack(x, y, _lastSelectedMods, 0x1D0, _trackType, 0, companyColour, gCurrentRotation);
}
_byte_522095 = _byte_522095 & ~(1 << 0);
}
}
auto xPos = self->x + 69;
auto yPos = self->widgets[widx::image].bottom + self->y + 4;
if (_modCost != 0x80000000 && _modCost != 0)
{
auto args = FormatArguments();
args.push<uint32_t>(_modCost);
Gfx::drawStringCentred(*context, xPos, yPos, Colour::black, StringIds::build_cost, &args);
}
}
void tabReset(Window* self)
{
self->callOnMouseDown(Overhead::widx::image);
}
void initEvents()
{
events.on_close = Common::onClose;
events.on_mouse_up = onMouseUp;
events.on_mouse_down = onMouseDown;
events.on_dropdown = onDropdown;
events.on_update = onUpdate;
events.on_tool_update = onToolUpdate;
events.on_tool_down = onToolDown;
events.prepare_draw = prepareDraw;
events.draw = draw;
}
}