912 lines
34 KiB
C++
912 lines
34 KiB
C++
#include "../Audio/Audio.h"
|
|
#include "../Config.h"
|
|
#include "../Date.h"
|
|
#include "../GameCommands/GameCommands.h"
|
|
#include "../Graphics/Colour.h"
|
|
#include "../Graphics/Gfx.h"
|
|
#include "../Graphics/ImageIds.h"
|
|
#include "../IndustryManager.h"
|
|
#include "../Input.h"
|
|
#include "../Interop/Interop.hpp"
|
|
#include "../Localisation/FormatArguments.hpp"
|
|
#include "../Localisation/StringIds.h"
|
|
#include "../Map/Map.hpp"
|
|
#include "../Map/TileManager.h"
|
|
#include "../Objects/CargoObject.h"
|
|
#include "../Objects/IndustryObject.h"
|
|
#include "../Objects/InterfaceSkinObject.h"
|
|
#include "../Objects/ObjectManager.h"
|
|
#include "../Ui/WindowManager.h"
|
|
#include "../ViewportManager.h"
|
|
#include "../Widget.h"
|
|
|
|
using namespace OpenLoco::Interop;
|
|
using namespace OpenLoco::GameCommands;
|
|
|
|
namespace OpenLoco::Ui::Windows::Industry
|
|
{
|
|
namespace Common
|
|
{
|
|
enum widx
|
|
{
|
|
frame,
|
|
caption,
|
|
close_button,
|
|
panel,
|
|
tab_industry,
|
|
tab_production,
|
|
tab_production_2,
|
|
tab_transported,
|
|
};
|
|
|
|
const uint64_t enabledWidgets = (1 << widx::caption) | (1 << widx::close_button) | (1 << widx::tab_industry) | (1 << widx::tab_production) | (1 << widx::tab_production_2) | (1 << widx::tab_transported);
|
|
|
|
#define commonWidgets(frameWidth, frameHeight, windowCaptionId) \
|
|
makeWidget({ 0, 0 }, { frameWidth, frameHeight }, WidgetType::frame, WindowColour::primary), \
|
|
makeWidget({ 1, 1 }, { frameWidth - 2, 13 }, WidgetType::caption_25, WindowColour::primary, windowCaptionId), \
|
|
makeWidget({ frameWidth - 15, 2 }, { 13, 13 }, WidgetType::wt_9, WindowColour::primary, ImageIds::close_button, StringIds::tooltip_close_window), \
|
|
makeWidget({ 0, 41 }, { frameWidth, 95 }, WidgetType::panel, WindowColour::secondary), \
|
|
makeRemapWidget({ 3, 15 }, { 31, 27 }, WidgetType::wt_8, WindowColour::secondary, ImageIds::tab, StringIds::tooltip_industry), \
|
|
makeRemapWidget({ 34, 15 }, { 31, 27 }, WidgetType::wt_8, WindowColour::secondary, ImageIds::tab, StringIds::tooltip_production_graph), \
|
|
makeRemapWidget({ 65, 15 }, { 31, 27 }, WidgetType::wt_8, WindowColour::secondary, ImageIds::tab, StringIds::tooltip_production_graph), \
|
|
makeRemapWidget({ 96, 15 }, { 31, 27 }, WidgetType::wt_8, WindowColour::secondary, ImageIds::tab, StringIds::tooltip_statistics)
|
|
|
|
// Defined at the bottom of this file.
|
|
static void prepareDraw(Window* self);
|
|
static void textInput(Window* self, WidgetIndex_t callingWidget, const char* input);
|
|
static void update(Window* self);
|
|
static void renameIndustryPrompt(Window* self, WidgetIndex_t widgetIndex);
|
|
static void repositionTabs(Window* self);
|
|
static void switchTab(Window* self, WidgetIndex_t widgetIndex);
|
|
static void drawTabs(Window* self, Gfx::Context* context);
|
|
static void setDisabledWidgets(Window* self);
|
|
static void draw(Window* self, Gfx::Context* context);
|
|
static void onMouseUp(Window* self, WidgetIndex_t widgetIndex);
|
|
static void initEvents();
|
|
}
|
|
|
|
namespace Industry
|
|
{
|
|
static const Ui::Size windowSize = { 223, 137 };
|
|
|
|
static const Ui::Size minWindowSize = { 192, 137 };
|
|
|
|
static const Ui::Size maxWindowSize = { 600, 440 };
|
|
|
|
enum widx
|
|
{
|
|
viewport = 8,
|
|
status_bar,
|
|
centre_on_viewport,
|
|
demolish_industry,
|
|
};
|
|
|
|
static Widget widgets[] = {
|
|
commonWidgets(223, 137, StringIds::title_town),
|
|
makeWidget({ 3, 44 }, { 195, 80 }, WidgetType::viewport, WindowColour::secondary, 0xFFFFFFFE),
|
|
makeWidget({ 3, 115 }, { 195, 21 }, WidgetType::wt_13, WindowColour::secondary),
|
|
makeWidget({ 0, 0 }, { 24, 24 }, WidgetType::wt_9, WindowColour::secondary, ImageIds::null, StringIds::move_main_view_to_show_this),
|
|
makeWidget({ 198, 44 }, { 24, 24 }, WidgetType::wt_9, WindowColour::secondary, ImageIds::rubbish_bin, StringIds::demolish_this_industry),
|
|
widgetEnd(),
|
|
};
|
|
|
|
const uint64_t enabledWidgets = Common::enabledWidgets | (1 << centre_on_viewport) | (1 << demolish_industry);
|
|
|
|
static WindowEventList events;
|
|
|
|
// 0x00455ADD
|
|
static void prepareDraw(Window* self)
|
|
{
|
|
Common::prepareDraw(self);
|
|
|
|
self->widgets[widx::viewport].right = self->width - 26;
|
|
self->widgets[widx::viewport].bottom = self->height - 14;
|
|
|
|
self->widgets[widx::status_bar].top = self->height - 12;
|
|
self->widgets[widx::status_bar].bottom = self->height - 3;
|
|
self->widgets[widx::status_bar].right = self->width - 14;
|
|
|
|
self->widgets[widx::demolish_industry].right = self->width - 2;
|
|
self->widgets[widx::demolish_industry].left = self->width - 25;
|
|
|
|
if (isEditorMode() || isSandboxMode())
|
|
{
|
|
self->widgets[widx::demolish_industry].type = WidgetType::wt_9;
|
|
}
|
|
else
|
|
{
|
|
self->widgets[widx::demolish_industry].type = WidgetType::none;
|
|
self->widgets[widx::viewport].right += 22;
|
|
}
|
|
|
|
self->widgets[widx::centre_on_viewport].right = self->widgets[widx::viewport].right - 1;
|
|
self->widgets[widx::centre_on_viewport].bottom = self->widgets[widx::viewport].bottom - 1;
|
|
self->widgets[widx::centre_on_viewport].left = self->widgets[widx::viewport].right - 24;
|
|
self->widgets[widx::centre_on_viewport].top = self->widgets[widx::viewport].bottom - 24;
|
|
|
|
Common::repositionTabs(self);
|
|
}
|
|
|
|
// 0x00455C22
|
|
static void draw(Window* self, Gfx::Context* context)
|
|
{
|
|
self->draw(context);
|
|
Common::drawTabs(self, context);
|
|
self->drawViewports(context);
|
|
Widget::drawViewportCentreButton(context, self, widx::centre_on_viewport);
|
|
|
|
const char* buffer = StringManager::getString(StringIds::buffer_1250);
|
|
auto industry = IndustryManager::get(self->number);
|
|
industry->getStatusString(const_cast<char*>(buffer));
|
|
|
|
auto args = FormatArguments();
|
|
args.push(StringIds::buffer_1250);
|
|
|
|
auto widget = &self->widgets[widx::status_bar];
|
|
auto x = self->x + widget->left - 1;
|
|
auto y = self->y + widget->top - 1;
|
|
auto width = widget->width();
|
|
Gfx::drawString_494BBF(*context, x, y, width, Colour::black, StringIds::black_stringid, &args);
|
|
}
|
|
|
|
// 0x00455C86
|
|
static void onMouseUp(Window* self, WidgetIndex_t widgetIndex)
|
|
{
|
|
switch (widgetIndex)
|
|
{
|
|
case Common::widx::caption:
|
|
Common::renameIndustryPrompt(self, widgetIndex);
|
|
break;
|
|
|
|
case Common::widx::close_button:
|
|
WindowManager::close(self);
|
|
break;
|
|
|
|
case Common::widx::tab_industry:
|
|
case Common::widx::tab_production:
|
|
case Common::widx::tab_production_2:
|
|
case Common::widx::tab_transported:
|
|
Common::switchTab(self, widgetIndex);
|
|
break;
|
|
|
|
// 0x00455EA2
|
|
case widx::centre_on_viewport:
|
|
self->viewportCentreMain();
|
|
break;
|
|
|
|
// 0x00455E59
|
|
case widx::demolish_industry:
|
|
{
|
|
bool success = GameCommands::do_48(GameCommands::Flags::apply, self->number);
|
|
if (!success)
|
|
break;
|
|
|
|
Audio::playSound(Audio::SoundId::demolish, GameCommands::getPosition());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void initViewport(Window* self);
|
|
|
|
// 0x00455F1A
|
|
static void onResize(Window* self)
|
|
{
|
|
self->setSize(minWindowSize, maxWindowSize);
|
|
|
|
if (self->viewports[0] != nullptr)
|
|
{
|
|
uint16_t newWidth = self->width - 30;
|
|
if (!isEditorMode() && !isSandboxMode())
|
|
newWidth += 22;
|
|
|
|
uint16_t newHeight = self->height - 59;
|
|
|
|
auto& viewport = self->viewports[0];
|
|
if (newWidth != viewport->width || newHeight != viewport->height)
|
|
{
|
|
viewport->width = newWidth;
|
|
viewport->height = newHeight;
|
|
viewport->view_width = newWidth << viewport->zoom;
|
|
viewport->view_height = newHeight << viewport->zoom;
|
|
self->saved_view.clear();
|
|
}
|
|
}
|
|
|
|
initViewport(self);
|
|
}
|
|
|
|
// 0x00456C36
|
|
static void initViewport(Window* self)
|
|
{
|
|
if (self->current_tab != Common::widx::tab_industry - Common::widx::tab_industry)
|
|
return;
|
|
|
|
self->callPrepareDraw();
|
|
|
|
// Figure out the industry's position on the map.
|
|
auto industry = IndustryManager::get(self->number);
|
|
int16_t tileZ = TileManager::getHeight({ industry->x, industry->y }).landHeight;
|
|
|
|
// Compute views.
|
|
SavedView view = {
|
|
industry->x,
|
|
industry->y,
|
|
ZoomLevel::quarter,
|
|
static_cast<int8_t>(self->viewports[0]->getRotation()),
|
|
tileZ,
|
|
};
|
|
//view.flags |= (1 << 14);
|
|
|
|
uint16_t flags = 0;
|
|
if (self->viewports[0] != nullptr)
|
|
{
|
|
if (self->saved_view == view)
|
|
return;
|
|
|
|
flags = self->viewports[0]->flags;
|
|
self->viewportRemove(0);
|
|
ViewportManager::collectGarbage();
|
|
}
|
|
else
|
|
{
|
|
if ((Config::get().flags & Config::Flags::gridlinesOnLandscape) != 0)
|
|
flags |= ViewportFlags::gridlines_on_landscape;
|
|
}
|
|
|
|
self->saved_view = view;
|
|
|
|
if (self->viewports[0] == nullptr)
|
|
{
|
|
auto widget = &self->widgets[widx::viewport];
|
|
auto tile = Map::Pos3({ industry->x, industry->y, tileZ });
|
|
auto origin = Ui::Point(widget->left + self->x + 1, widget->top + self->y + 1);
|
|
auto size = Ui::Size(widget->width() - 2, widget->height() - 2);
|
|
ViewportManager::create(self, 0, origin, size, self->saved_view.zoomLevel, tile);
|
|
self->invalidate();
|
|
self->flags |= WindowFlags::viewport_no_scrolling;
|
|
}
|
|
|
|
if (self->viewports[0] != nullptr)
|
|
{
|
|
self->viewports[0]->flags = flags;
|
|
self->invalidate();
|
|
}
|
|
}
|
|
|
|
static void initEvents()
|
|
{
|
|
events.draw = draw;
|
|
events.on_mouse_up = onMouseUp;
|
|
events.on_resize = onResize;
|
|
events.on_update = Common::update;
|
|
events.prepare_draw = prepareDraw;
|
|
events.text_input = Common::textInput;
|
|
events.viewport_rotate = initViewport;
|
|
}
|
|
}
|
|
|
|
// 0x00456D2D
|
|
Window* open(IndustryId_t industryId)
|
|
{
|
|
auto window = WindowManager::bringToFront(WindowType::industry, industryId);
|
|
if (window != nullptr)
|
|
{
|
|
if (Input::isToolActive(window->type, window->number))
|
|
Input::toolCancel();
|
|
|
|
window = WindowManager::bringToFront(WindowType::industry, industryId);
|
|
}
|
|
|
|
if (window == nullptr)
|
|
{
|
|
// 0x00456DBC start
|
|
const uint32_t newFlags = WindowFlags::flag_8 | WindowFlags::resizable;
|
|
window = WindowManager::createWindow(WindowType::industry, Industry::windowSize, newFlags, &Industry::events);
|
|
window->number = industryId;
|
|
window->min_width = 192;
|
|
window->min_height = 137;
|
|
window->max_width = 600;
|
|
window->max_height = 440;
|
|
|
|
auto skin = ObjectManager::get<InterfaceSkinObject>();
|
|
if (skin != nullptr)
|
|
{
|
|
window->setColour(WindowColour::primary, skin->colour_0B);
|
|
window->setColour(WindowColour::secondary, skin->colour_0C);
|
|
}
|
|
// 0x00456DBC end
|
|
|
|
window->saved_view.clear();
|
|
}
|
|
|
|
// TODO: only needs to be called once.
|
|
Common::initEvents();
|
|
|
|
window->current_tab = Common::widx::tab_industry - Common::widx::tab_industry;
|
|
window->invalidate();
|
|
|
|
window->widgets = Industry::widgets;
|
|
window->enabled_widgets = Industry::enabledWidgets;
|
|
window->holdable_widgets = 0;
|
|
window->event_handlers = &Industry::events;
|
|
window->activated_widgets = 0;
|
|
|
|
Common::setDisabledWidgets(window);
|
|
|
|
window->initScrollWidgets();
|
|
Industry::initViewport(window);
|
|
|
|
return window;
|
|
}
|
|
|
|
namespace Production
|
|
{
|
|
|
|
static const Ui::Size minWindowSize = { 299, 282 };
|
|
|
|
static const Ui::Size maxWindowSize = { 299, 337 };
|
|
|
|
static WindowEventList events;
|
|
|
|
// 0x00455FD9
|
|
static void prepareDraw(Window* self)
|
|
{
|
|
Common::prepareDraw(self);
|
|
|
|
Common::repositionTabs(self);
|
|
}
|
|
|
|
// 0x0045654F
|
|
static void onResize(Window* self)
|
|
{
|
|
{
|
|
self->setSize(minWindowSize, maxWindowSize);
|
|
}
|
|
}
|
|
|
|
static void initEvents()
|
|
{
|
|
events.draw = Common::draw;
|
|
events.on_mouse_up = Common::onMouseUp;
|
|
events.on_resize = onResize;
|
|
events.on_update = Common::update;
|
|
events.prepare_draw = prepareDraw;
|
|
events.text_input = Common::textInput;
|
|
}
|
|
}
|
|
|
|
namespace Production2
|
|
{
|
|
static const Ui::Size minWindowSize = { 299, 282 };
|
|
|
|
static const Ui::Size maxWindowSize = { 299, 337 };
|
|
|
|
static Widget widgets[] = {
|
|
commonWidgets(222, 136, StringIds::title_industry_monthly_production),
|
|
widgetEnd(),
|
|
};
|
|
|
|
static WindowEventList events;
|
|
|
|
// 0x0045626F
|
|
static void prepareDraw(Window* self)
|
|
{
|
|
Common::prepareDraw(self);
|
|
|
|
Common::repositionTabs(self);
|
|
}
|
|
|
|
// 0x004565FF
|
|
static void onResize(Window* self)
|
|
{
|
|
{
|
|
self->setSize(minWindowSize, maxWindowSize);
|
|
}
|
|
}
|
|
|
|
static void initEvents()
|
|
{
|
|
events.draw = Common::draw;
|
|
events.on_mouse_up = Common::onMouseUp;
|
|
events.on_resize = onResize;
|
|
events.on_update = Common::update;
|
|
events.prepare_draw = prepareDraw;
|
|
events.text_input = Common::textInput;
|
|
}
|
|
}
|
|
|
|
namespace Transported
|
|
{
|
|
static const Ui::Size windowSize = { 300, 127 };
|
|
|
|
static Widget widgets[] = {
|
|
commonWidgets(300, 126, StringIds::title_statistics),
|
|
widgetEnd(),
|
|
};
|
|
|
|
static WindowEventList events;
|
|
|
|
// 0x00456665
|
|
static void prepareDraw(Window* self)
|
|
{
|
|
Common::prepareDraw(self);
|
|
|
|
Common::repositionTabs(self);
|
|
}
|
|
|
|
// 0x00456705
|
|
static void draw(Window* self, Gfx::Context* context)
|
|
{
|
|
self->draw(context);
|
|
Common::drawTabs(self, context);
|
|
|
|
auto industry = IndustryManager::get(self->number);
|
|
auto industryObj = industry->object();
|
|
int16_t xPos = self->x + 3;
|
|
int16_t yPos = self->y + 45;
|
|
Ui::Point origin = { xPos, yPos };
|
|
|
|
// Draw Last Months received cargo stats
|
|
if (industry->canReceiveCargo())
|
|
{
|
|
origin.x += 4;
|
|
origin.y += 10;
|
|
Gfx::drawString_494B3F(*context, xPos, yPos, Colour::black, StringIds::received_cargo);
|
|
|
|
auto cargoNumber = 0;
|
|
for (const auto& receivedCargoType : industryObj->required_cargo_type)
|
|
{
|
|
if (receivedCargoType != 0xFF)
|
|
{
|
|
auto cargoObj = ObjectManager::get<CargoObject>(receivedCargoType);
|
|
auto args = FormatArguments();
|
|
|
|
if (industry->required_cargo_quantity[cargoNumber] == 1)
|
|
{
|
|
args.push(cargoObj->unit_name_singular);
|
|
}
|
|
else
|
|
{
|
|
args.push(cargoObj->unit_name_plural);
|
|
}
|
|
args.push<uint32_t>(industry->required_cargo_quantity[cargoNumber]);
|
|
|
|
origin.y = Gfx::drawString_495224(*context, origin.x, origin.y, 290, Colour::black, StringIds::black_stringid, &args);
|
|
}
|
|
cargoNumber++;
|
|
}
|
|
origin.y += 4;
|
|
origin.x -= 4;
|
|
}
|
|
|
|
// Draw Last Months produced cargo stats
|
|
if (industry->canProduceCargo())
|
|
{
|
|
Gfx::drawString_494B3F(*context, origin.x, origin.y, Colour::black, StringIds::produced_cargo);
|
|
origin.y += 10;
|
|
origin.x += 4;
|
|
|
|
auto cargoNumber = 0;
|
|
for (const auto& producedCargoType : industryObj->produced_cargo_type)
|
|
{
|
|
if (producedCargoType != 0xFF)
|
|
{
|
|
auto cargoObj = ObjectManager::get<CargoObject>(producedCargoType);
|
|
auto args = FormatArguments();
|
|
|
|
if (industry->produced_cargo_quantity[cargoNumber] == 1)
|
|
{
|
|
args.push(cargoObj->unit_name_singular);
|
|
}
|
|
else
|
|
{
|
|
args.push(cargoObj->unit_name_plural);
|
|
}
|
|
args.push<uint32_t>(industry->produced_cargo_quantity[cargoNumber]);
|
|
args.push<uint16_t>(industry->produced_cargo_transported[cargoNumber]);
|
|
|
|
origin.y = Gfx::drawString_495224(*context, origin.x, origin.y, 290, Colour::black, StringIds::transported_cargo, &args);
|
|
}
|
|
cargoNumber++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 0x004569C2
|
|
static void onResize(Window* self)
|
|
{
|
|
{
|
|
self->setSize(windowSize, windowSize);
|
|
}
|
|
}
|
|
|
|
static void initEvents()
|
|
{
|
|
events.draw = draw;
|
|
events.on_mouse_up = Common::onMouseUp;
|
|
events.on_resize = onResize;
|
|
events.on_update = Common::update;
|
|
events.prepare_draw = prepareDraw;
|
|
events.text_input = Common::textInput;
|
|
}
|
|
}
|
|
|
|
namespace Common
|
|
{
|
|
struct TabInformation
|
|
{
|
|
Widget* widgets;
|
|
const widx widgetIndex;
|
|
WindowEventList* events;
|
|
const uint64_t* enabledWidgets;
|
|
};
|
|
|
|
static TabInformation tabInformationByTabOffset[] = {
|
|
{ Industry::widgets, widx::tab_industry, &Industry::events, &Industry::enabledWidgets },
|
|
{ Production2::widgets, widx::tab_production, &Production::events, &Common::enabledWidgets },
|
|
{ Production2::widgets, widx::tab_production_2, &Production2::events, &Common::enabledWidgets },
|
|
{ Transported::widgets, widx::tab_transported, &Transported::events, &Common::enabledWidgets }
|
|
};
|
|
|
|
static void setDisabledWidgets(Window* self)
|
|
{
|
|
auto industryObj = ObjectManager::get<IndustryObject>(IndustryManager::get(self->number)->object_id);
|
|
auto disabledWidgets = 0;
|
|
|
|
if (industryObj->produced_cargo_type[0] == 0xFF)
|
|
disabledWidgets |= (1 << Common::widx::tab_production);
|
|
|
|
if (industryObj->produced_cargo_type[1] == 0xFF)
|
|
disabledWidgets |= (1 << Common::widx::tab_production_2);
|
|
|
|
self->disabled_widgets = disabledWidgets;
|
|
}
|
|
|
|
// 0x00456079
|
|
static void draw(Window* self, Gfx::Context* context)
|
|
{
|
|
self->draw(context);
|
|
Common::drawTabs(self, context);
|
|
|
|
// Draw Units of Cargo sub title
|
|
const auto industry = IndustryManager::get(self->number);
|
|
const auto industryObj = ObjectManager::get<IndustryObject>(industry->object_id);
|
|
const auto cargoObj = ObjectManager::get<CargoObject>(industryObj->produced_cargo_type[0]);
|
|
|
|
{
|
|
auto args = FormatArguments();
|
|
args.push(cargoObj->units_and_cargo_name);
|
|
|
|
int16_t x = self->x + 2;
|
|
int16_t y = self->y - 24 + 68;
|
|
|
|
Gfx::drawString_494B3F(*context, x, y, Colour::black, StringIds::production_graph_label, &args);
|
|
}
|
|
|
|
// Draw Y label and grid lines.
|
|
const uint16_t graphBottom = self->y + self->height - 7;
|
|
int32_t yTick = 0;
|
|
for (int16_t yPos = graphBottom; yPos >= self->y + 68; yPos -= 20)
|
|
{
|
|
auto args = FormatArguments();
|
|
args.push(yTick);
|
|
|
|
Gfx::drawRect(context, self->x + 41, yPos, 239, 1, Colour::getShade(self->getColour(WindowColour::secondary), 4));
|
|
|
|
Gfx::drawString_494C78(*context, self->x + 39, yPos - 6, Colour::black, StringIds::population_graph_people, &args);
|
|
|
|
yTick += 1000;
|
|
}
|
|
|
|
month_id month = getCurrentMonth();
|
|
int16_t year = getCurrentYear();
|
|
int8_t yearSkip = 0;
|
|
// This is either 0 or 1 depending on selected tab
|
|
// used to select the correct history
|
|
const uint8_t productionTabWidx = self->current_tab + widx::tab_industry;
|
|
const uint8_t productionNum = productionTabWidx - widx::tab_production;
|
|
for (uint8_t i = industry->history_size[productionNum] - 1; i > 0; i--)
|
|
{
|
|
const uint16_t xPos = self->x + 41 + i;
|
|
const uint16_t yPos = self->y + 56;
|
|
|
|
// Draw horizontal year and vertical grid lines.
|
|
if (month == month_id::january)
|
|
{
|
|
if (yearSkip == 0)
|
|
{
|
|
auto args = FormatArguments();
|
|
args.push(year);
|
|
|
|
Gfx::drawStringCentred(*context, xPos, yPos, Colour::black, StringIds::population_graph_year, &args);
|
|
}
|
|
|
|
Gfx::drawRect(context, xPos, yPos + 11, 1, self->height - 74, Colour::getShade(self->getColour(WindowColour::secondary), 4));
|
|
}
|
|
|
|
const auto history = productionTabWidx == widx::tab_production ? industry->history_1 : industry->history_2;
|
|
// Draw production graph
|
|
const uint16_t yPos1 = graphBottom - history[i];
|
|
const uint16_t yPos2 = graphBottom - history[i + 1];
|
|
|
|
// Do not draw current segment yet; it may be zeroed.
|
|
if (i < industry->history_size[productionNum] - 1)
|
|
{
|
|
if (yPos1 <= graphBottom)
|
|
{
|
|
if (yPos2 <= graphBottom)
|
|
{
|
|
Gfx::drawLine(context, xPos, yPos1, xPos + 1, yPos2, Colour::getShade(self->getColour(WindowColour::secondary), 7));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (month == month_id::january)
|
|
{
|
|
month = month_id::december;
|
|
year--;
|
|
|
|
yearSkip++;
|
|
if (yearSkip >= 3)
|
|
yearSkip = 0;
|
|
}
|
|
else
|
|
{
|
|
month = month_id(static_cast<int8_t>(month) - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 0x004565B5, 0x00456505
|
|
static void onMouseUp(Window* self, WidgetIndex_t widgetIndex)
|
|
{
|
|
switch (widgetIndex)
|
|
{
|
|
case Common::widx::caption:
|
|
Common::renameIndustryPrompt(self, widgetIndex);
|
|
break;
|
|
|
|
case Common::widx::close_button:
|
|
WindowManager::close(self);
|
|
break;
|
|
|
|
case Common::widx::tab_industry:
|
|
case Common::widx::tab_production:
|
|
case Common::widx::tab_production_2:
|
|
case Common::widx::tab_transported:
|
|
Common::switchTab(self, widgetIndex);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void prepareDraw(Window* self)
|
|
{
|
|
// Reset tab widgets if needed.
|
|
auto tabWidgets = tabInformationByTabOffset[self->current_tab].widgets;
|
|
if (self->widgets != tabWidgets)
|
|
{
|
|
self->widgets = tabWidgets;
|
|
self->initScrollWidgets();
|
|
}
|
|
|
|
// Activate the current tab.
|
|
self->activated_widgets &= ~((1ULL << widx::tab_industry) | (1ULL << widx::tab_production) | (1ULL << widx::tab_production_2) | (1ULL << widx::tab_transported));
|
|
widx widgetIndex = tabInformationByTabOffset[self->current_tab].widgetIndex;
|
|
self->activated_widgets |= (1ULL << widgetIndex);
|
|
|
|
// Put industry name in place.
|
|
auto industry = IndustryManager::get(self->number);
|
|
auto args = FormatArguments();
|
|
args.push(industry->name);
|
|
args.push(industry->town);
|
|
|
|
// Resize common widgets.
|
|
self->widgets[Common::widx::frame].right = self->width - 1;
|
|
self->widgets[Common::widx::frame].bottom = self->height - 1;
|
|
|
|
self->widgets[Common::widx::caption].right = self->width - 2;
|
|
|
|
self->widgets[Common::widx::close_button].left = self->width - 15;
|
|
self->widgets[Common::widx::close_button].right = self->width - 3;
|
|
|
|
self->widgets[Common::widx::panel].right = self->width - 1;
|
|
self->widgets[Common::widx::panel].bottom = self->height - 1;
|
|
}
|
|
|
|
// 0x00455CBC
|
|
static void textInput(Window* self, WidgetIndex_t callingWidget, const char* input)
|
|
{
|
|
if (callingWidget != Common::widx::caption)
|
|
return;
|
|
|
|
if (strlen(input) == 0)
|
|
return;
|
|
|
|
GameCommands::setErrorTitle(StringIds::error_cant_rename_industry);
|
|
|
|
uint32_t* buffer = (uint32_t*)input;
|
|
GameCommands::do_79(self->number, 1, buffer[0], buffer[1], buffer[2]);
|
|
GameCommands::do_79(0, 2, buffer[3], buffer[4], buffer[5]);
|
|
GameCommands::do_79(0, 0, buffer[6], buffer[7], buffer[8]);
|
|
}
|
|
|
|
static void update(Window* self)
|
|
{
|
|
self->frame_no++;
|
|
self->callPrepareDraw();
|
|
WindowManager::invalidate(WindowType::industry, self->number);
|
|
}
|
|
|
|
//0x00455D81
|
|
static void renameIndustryPrompt(Window* self, WidgetIndex_t widgetIndex)
|
|
{
|
|
auto industry = IndustryManager::get(self->number);
|
|
if (!isEditorMode() && !isSandboxMode())
|
|
{
|
|
if ((industry->flags & IndustryFlags::flag_04) == 0)
|
|
return;
|
|
if (!isPlayerCompany(industry->owner))
|
|
return;
|
|
}
|
|
|
|
auto args = FormatArguments();
|
|
args.push<int64_t>(0);
|
|
args.push(industry->name);
|
|
args.push(industry->town);
|
|
|
|
TextInput::openTextInput(self, StringIds::title_industry_name, StringIds::prompt_enter_new_industry_name, industry->name, widgetIndex, &industry->town);
|
|
}
|
|
|
|
// 0x00456A5E, 0x00456A64
|
|
static void repositionTabs(Window* self)
|
|
{
|
|
int16_t xPos = self->widgets[widx::tab_industry].left;
|
|
const int16_t tabWidth = self->widgets[widx::tab_industry].right - xPos;
|
|
|
|
for (uint8_t i = widx::tab_industry; i <= widx::tab_transported; i++)
|
|
{
|
|
if (self->isDisabled(i))
|
|
continue;
|
|
|
|
self->widgets[i].left = xPos;
|
|
self->widgets[i].right = xPos + tabWidth;
|
|
xPos = self->widgets[i].right + 1;
|
|
}
|
|
}
|
|
|
|
// 0x00455CC7
|
|
static void switchTab(Window* self, WidgetIndex_t widgetIndex)
|
|
{
|
|
if (Input::isToolActive(self->type, self->number))
|
|
Input::toolCancel();
|
|
|
|
TextInput::sub_4CE6C9(self->type, self->number);
|
|
|
|
self->current_tab = widgetIndex - widx::tab_industry;
|
|
self->frame_no = 0;
|
|
self->flags &= ~(WindowFlags::flag_16);
|
|
self->var_85C = -1;
|
|
|
|
self->viewportRemove(0);
|
|
|
|
auto tabInfo = tabInformationByTabOffset[widgetIndex - widx::tab_industry];
|
|
|
|
self->enabled_widgets = *tabInfo.enabledWidgets;
|
|
self->holdable_widgets = 0;
|
|
self->event_handlers = tabInfo.events;
|
|
self->activated_widgets = 0;
|
|
self->widgets = tabInfo.widgets;
|
|
|
|
Common::setDisabledWidgets(self);
|
|
|
|
self->invalidate();
|
|
|
|
self->setSize(Industry::windowSize);
|
|
self->callOnResize();
|
|
self->callPrepareDraw();
|
|
self->initScrollWidgets();
|
|
self->invalidate();
|
|
self->moveInsideScreenEdges();
|
|
}
|
|
|
|
static void drawProductionTab(Window* self, Gfx::Context* context, uint8_t productionTabNumber)
|
|
{
|
|
static const uint32_t productionTabImageIds[] = {
|
|
InterfaceSkin::ImageIds::tab_production_frame0,
|
|
InterfaceSkin::ImageIds::tab_production_frame1,
|
|
InterfaceSkin::ImageIds::tab_production_frame2,
|
|
InterfaceSkin::ImageIds::tab_production_frame3,
|
|
InterfaceSkin::ImageIds::tab_production_frame4,
|
|
InterfaceSkin::ImageIds::tab_production_frame5,
|
|
InterfaceSkin::ImageIds::tab_production_frame6,
|
|
InterfaceSkin::ImageIds::tab_production_frame7,
|
|
};
|
|
|
|
auto industry = IndustryManager::get(self->number);
|
|
auto industryObj = ObjectManager::get<IndustryObject>(industry->object_id);
|
|
auto skin = ObjectManager::get<InterfaceSkinObject>();
|
|
|
|
static const uint32_t productionTabIds[] = {
|
|
widx::tab_production,
|
|
widx::tab_production_2,
|
|
};
|
|
|
|
auto tab = productionTabIds[productionTabNumber];
|
|
|
|
uint32_t imageId = 0xFFFFFFFF;
|
|
auto widget = self->widgets[tab];
|
|
|
|
if (industryObj->produced_cargo_type[productionTabNumber] != 0xFF)
|
|
{
|
|
imageId = Gfx::recolour(skin->img, self->getColour(WindowColour::secondary));
|
|
|
|
if (self->current_tab == tab - widx::tab_industry)
|
|
imageId += productionTabImageIds[(self->frame_no / 4) % std::size(productionTabImageIds)];
|
|
else
|
|
imageId += productionTabImageIds[0];
|
|
|
|
auto xPos = widget.left + self->x;
|
|
auto yPos = widget.top + self->y;
|
|
Gfx::drawImage(context, xPos, yPos, imageId);
|
|
|
|
auto caroObj = ObjectManager::get<CargoObject>(industryObj->produced_cargo_type[productionTabNumber]);
|
|
Gfx::drawImage(context, xPos + 18, yPos + 14, caroObj->unit_inline_sprite);
|
|
|
|
Widget::drawTab(self, context, -2, tab);
|
|
}
|
|
}
|
|
|
|
// 0x00456A98
|
|
static void drawTabs(Window* self, Gfx::Context* context)
|
|
{
|
|
auto skin = ObjectManager::get<InterfaceSkinObject>();
|
|
|
|
// Industry tab
|
|
{
|
|
uint32_t imageId = skin->img;
|
|
imageId += InterfaceSkin::ImageIds::toolbar_menu_industries;
|
|
Widget::drawTab(self, context, imageId, widx::tab_industry);
|
|
}
|
|
|
|
// Production Tab
|
|
{
|
|
drawProductionTab(self, context, 0);
|
|
}
|
|
|
|
// 2nd Production Tab
|
|
{
|
|
drawProductionTab(self, context, 1);
|
|
}
|
|
|
|
// Transported Tab
|
|
{
|
|
static const uint32_t transportedTabImageIds[] = {
|
|
InterfaceSkin::ImageIds::tab_transported_frame0,
|
|
InterfaceSkin::ImageIds::tab_transported_frame1,
|
|
InterfaceSkin::ImageIds::tab_transported_frame2,
|
|
InterfaceSkin::ImageIds::tab_transported_frame3,
|
|
InterfaceSkin::ImageIds::tab_transported_frame4,
|
|
InterfaceSkin::ImageIds::tab_transported_frame5,
|
|
InterfaceSkin::ImageIds::tab_transported_frame6,
|
|
};
|
|
|
|
uint32_t imageId = skin->img;
|
|
if (self->current_tab == widx::tab_transported - widx::tab_industry)
|
|
imageId += transportedTabImageIds[(self->frame_no / 4) % std::size(transportedTabImageIds)];
|
|
else
|
|
imageId += transportedTabImageIds[0];
|
|
Widget::drawTab(self, context, imageId, widx::tab_transported);
|
|
}
|
|
}
|
|
|
|
static void initEvents()
|
|
{
|
|
Industry::initEvents();
|
|
Production::initEvents();
|
|
Production2::initEvents();
|
|
Transported::initEvents();
|
|
}
|
|
}
|
|
}
|