Store tool handlers as shared pointers
This commit is contained in:
@@ -731,7 +731,7 @@ template <ImplementsRemoveHandler Handler>
|
||||
void RemoveAction<Handler>::HandleMouseRelease() {
|
||||
auto area = this->GetArea();
|
||||
if (!area.has_value()) return;
|
||||
this->handler.Execute(area.value());
|
||||
this->handler->Execute(area.value());
|
||||
this->start_tile = INVALID_TILE;
|
||||
}
|
||||
|
||||
@@ -750,7 +750,7 @@ ToolGUIInfo RemoveAction<Handler>::GetGUIInfo() {
|
||||
CommandCost cost;
|
||||
if (area.has_value()) {
|
||||
hlmap.AddTileAreaWithBorder(area.value(), CM_PALETTE_TINT_RED_DEEP);
|
||||
auto cmd = this->handler.GetCommand(area.value());
|
||||
auto cmd = this->handler->GetCommand(area.value());
|
||||
if (cmd) cost = cmd->test();
|
||||
}
|
||||
return {hlmap, data, cost};
|
||||
@@ -905,7 +905,7 @@ void SizedPlacementAction<Handler>::Update(Point, TileIndex tile) {
|
||||
|
||||
auto area = this->GetArea();
|
||||
if (!area.has_value()) return;
|
||||
auto cmdptr = this->handler.GetCommand(tile, INVALID_STATION);
|
||||
auto cmdptr = this->handler->GetCommand(tile, INVALID_STATION);
|
||||
auto cmd = dynamic_cast<cmd::BuildRailStation *>(cmdptr.get());
|
||||
if (cmd == nullptr) return;
|
||||
|
||||
@@ -960,16 +960,16 @@ bool SizedPlacementAction<Handler>::HandleMousePress() {
|
||||
template <ImplementsSizedPlacementHandler Handler>
|
||||
void SizedPlacementAction<Handler>::HandleMouseRelease() {
|
||||
if (!IsValidTile(this->cur_tile)) return;
|
||||
this->handler.Execute(this->cur_tile);
|
||||
this->handler->Execute(this->cur_tile);
|
||||
}
|
||||
|
||||
template <ImplementsSizedPlacementHandler Handler>
|
||||
ToolGUIInfo SizedPlacementAction<Handler>::GetGUIInfo() {
|
||||
if (!IsValidTile(this->cur_tile)) return {};
|
||||
auto [sct, rad] = this->handler.GetCatchmentParams();
|
||||
auto [sct, rad] = this->handler->GetCatchmentParams();
|
||||
return this->PrepareGUIInfo(
|
||||
this->handler.GetObjectHighlight(this->cur_tile),
|
||||
this->handler.GetCommand(this->cur_tile, INVALID_STATION),
|
||||
this->handler->GetObjectHighlight(this->cur_tile),
|
||||
this->handler->GetCommand(this->cur_tile, INVALID_STATION),
|
||||
sct,
|
||||
rad
|
||||
);
|
||||
@@ -1004,7 +1004,7 @@ template <ImplementsDragNDropPlacementHandler Handler>
|
||||
void DragNDropPlacementAction<Handler>::HandleMouseRelease() {
|
||||
auto area = this->GetArea();
|
||||
if (!area.has_value()) return;
|
||||
this->handler.Execute(area.value());
|
||||
this->handler->Execute(area.value());
|
||||
this->start_tile = INVALID_TILE;
|
||||
}
|
||||
|
||||
@@ -1012,11 +1012,11 @@ template <ImplementsDragNDropPlacementHandler Handler>
|
||||
ToolGUIInfo DragNDropPlacementAction<Handler>::GetGUIInfo() {
|
||||
auto area = this->GetArea();
|
||||
if (!area.has_value()) return {};
|
||||
auto ohl = this->handler.GetObjectHighlight(area.value());
|
||||
auto [sct, rad] = this->handler.GetCatchmentParams();
|
||||
auto ohl = this->handler->GetObjectHighlight(area.value());
|
||||
auto [sct, rad] = this->handler->GetCatchmentParams();
|
||||
return this->PrepareGUIInfo(
|
||||
this->handler.GetObjectHighlight(area.value()),
|
||||
this->handler.GetCommand(area.value(), INVALID_STATION),
|
||||
this->handler->GetObjectHighlight(area.value()),
|
||||
this->handler->GetCommand(area.value(), INVALID_STATION),
|
||||
sct,
|
||||
rad
|
||||
);
|
||||
@@ -1091,14 +1091,23 @@ StationBuildTool::StationBuildTool() {
|
||||
ResetHighlightCoverageStation();
|
||||
}
|
||||
|
||||
template<typename Thandler, typename Tcallback, typename Targ>
|
||||
bool StationBuildTool::ExecuteBuildCommand(Thandler *handler, Tcallback callback, Targ arg) {
|
||||
if (auto mode = std::get_if<StationAction::Join>(&_station_action)) {
|
||||
auto cmd = handler->GetCommand(arg, mode->station);
|
||||
return cmd ? cmd->post(callback) : false;
|
||||
}
|
||||
extern void ShowSelectStationWindow(TileArea ta, StationPickerCmdProc&& proc);
|
||||
|
||||
// Vanilla joining behaviour
|
||||
template<typename Thandler, typename Tcallback, typename Targ>
|
||||
bool ExecuteBuildCommand(Thandler *handler, Tcallback callback, Targ arg) {
|
||||
std::visit(Overload{
|
||||
[&](StationAction::Join &action) {
|
||||
Debug(misc, 0, "Join to {}", action.station);
|
||||
auto cmd = handler->GetCommand(arg, action.station);
|
||||
return cmd ? cmd->post(callback) : false;
|
||||
},
|
||||
[&](StationAction::Create &) {
|
||||
Debug(misc, 0, "Create new station");
|
||||
auto cmd = handler->GetCommand(arg, NEW_STATION);
|
||||
return cmd ? cmd->post(callback) : false;
|
||||
},
|
||||
[&](StationAction::Picker &) {
|
||||
Debug(misc, 0, "Show picker");
|
||||
auto cmd = handler->GetCommand(arg, INVALID_STATION);
|
||||
auto proc = [cmd=sp<Command>{std::move(cmd)}, callback](bool test, StationID to_join) -> bool {
|
||||
if (!cmd) return false;
|
||||
@@ -1117,8 +1126,12 @@ bool StationBuildTool::ExecuteBuildCommand(Thandler *handler, Tcallback callback
|
||||
if (!ohl.has_value()) return false;
|
||||
auto area = ohl->GetArea();
|
||||
if (!area.has_value()) return false;
|
||||
SetActiveHighlightObject(ohl);
|
||||
ShowSelectStationIfNeeded(area.value(), proc);
|
||||
// SetActiveHighlightObject(ohl);
|
||||
ShowSelectStationWindow(*area, std::move(proc));
|
||||
return true;
|
||||
}
|
||||
}, _station_action);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1159,14 +1172,14 @@ up<Command> RailStationBuildTool::SizedPlacementHandler::GetCommand(TileIndex ti
|
||||
_railstation.station_class,
|
||||
_railstation.station_type,
|
||||
to_join,
|
||||
_fn_mod
|
||||
true
|
||||
);
|
||||
cmd->with_error(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
bool RailStationBuildTool::SizedPlacementHandler::Execute(TileIndex tile) {
|
||||
return this->tool.ExecuteBuildCommand(this, &CcStation, tile);
|
||||
return ExecuteBuildCommand(this, &CcStation, tile);
|
||||
}
|
||||
|
||||
up<Command> RailStationBuildTool::DragNDropPlacementHandler::GetCommand(TileArea area, StationID to_join) {
|
||||
@@ -1184,14 +1197,14 @@ up<Command> RailStationBuildTool::DragNDropPlacementHandler::GetCommand(TileArea
|
||||
_railstation.station_class,
|
||||
_railstation.station_type,
|
||||
to_join,
|
||||
_fn_mod
|
||||
true
|
||||
);
|
||||
cmd->with_error(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
bool RailStationBuildTool::DragNDropPlacementHandler::Execute(TileArea area) {
|
||||
return this->tool.ExecuteBuildCommand(this, &CcStation, area);
|
||||
return ExecuteBuildCommand(this, &CcStation, area);
|
||||
}
|
||||
|
||||
std::optional<ObjectHighlight> RailStationBuildTool::DragNDropPlacementHandler::GetObjectHighlight(TileArea area) {
|
||||
@@ -1203,7 +1216,7 @@ std::optional<ObjectHighlight> RailStationBuildTool::SizedPlacementHandler::GetO
|
||||
}
|
||||
|
||||
RailStationBuildTool::RailStationBuildTool() : mode(Mode::SIZED) {
|
||||
this->action = make_up<SizedPlacementAction<SizedPlacementHandler>>(SizedPlacementHandler(*this));
|
||||
this->action = make_up<SizedPlacementAction<SizedPlacementHandler>>(*this);
|
||||
}
|
||||
|
||||
void RailStationBuildTool::Update(Point pt, TileIndex tile) {
|
||||
@@ -1292,14 +1305,14 @@ up<Command> RoadStopBuildTool::DragNDropPlacementHandler::GetCommand(TileArea ar
|
||||
_roadstop_gui_settings.roadstop_class,
|
||||
_roadstop_gui_settings.roadstop_type,
|
||||
to_join,
|
||||
_fn_mod
|
||||
true
|
||||
);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool RoadStopBuildTool::DragNDropPlacementHandler::Execute(TileArea area) {
|
||||
return this->tool.ExecuteBuildCommand(this, &CcRoadStop, area);
|
||||
return ExecuteBuildCommand(this, &CcRoadStop, area);
|
||||
}
|
||||
|
||||
std::optional<ObjectHighlight> RoadStopBuildTool::DragNDropPlacementHandler::GetObjectHighlight(TileArea area) {
|
||||
@@ -1400,13 +1413,13 @@ up<Command> DockBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, Sta
|
||||
return make_up<cmd::BuildDock>(
|
||||
tile,
|
||||
to_join,
|
||||
_fn_mod
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool DockBuildTool::SizedPlacementHandler::Execute(TileIndex tile) {
|
||||
return this->tool.ExecuteBuildCommand(this, &CcBuildDocks, tile);
|
||||
return ExecuteBuildCommand(this, &CcBuildDocks, tile);
|
||||
}
|
||||
|
||||
std::optional<ObjectHighlight> DockBuildTool::SizedPlacementHandler::GetObjectHighlight(TileIndex tile) {
|
||||
@@ -1489,14 +1502,14 @@ up<Command> AirportBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile,
|
||||
airport_type,
|
||||
layout,
|
||||
to_join,
|
||||
_fn_mod
|
||||
true
|
||||
);
|
||||
cmd->with_error(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
bool AirportBuildTool::SizedPlacementHandler::Execute(TileIndex tile) {
|
||||
this->tool.ExecuteBuildCommand(this, &CcBuildAirport, tile);
|
||||
ExecuteBuildCommand(this, &CcBuildAirport, tile);
|
||||
}
|
||||
|
||||
std::optional<ObjectHighlight> AirportBuildTool::SizedPlacementHandler::GetObjectHighlight(TileIndex tile) {
|
||||
|
||||
@@ -76,11 +76,12 @@ concept ImplementsRemoveHandler = std::derived_from<Handler, RemoveHandler>;
|
||||
template<ImplementsRemoveHandler Handler>
|
||||
class RemoveAction : public Action {
|
||||
private:
|
||||
Handler handler;
|
||||
sp<Handler> handler;
|
||||
TileIndex start_tile = INVALID_TILE;
|
||||
TileIndex cur_tile = INVALID_TILE;
|
||||
public:
|
||||
RemoveAction(const Handler &handler) : handler{handler} {}
|
||||
template<typename T>
|
||||
RemoveAction(T &tool) { this->handler = make_sp<Handler>(tool); };
|
||||
~RemoveAction() override = default;
|
||||
void Update(Point pt, TileIndex tile) override;
|
||||
std::optional<TileArea> GetArea() const override;
|
||||
@@ -102,10 +103,11 @@ concept ImplementsStationSelectHandler = std::derived_from<Handler, StationSelec
|
||||
template<ImplementsStationSelectHandler Handler>
|
||||
class StationSelectAction : public Action {
|
||||
private:
|
||||
Handler handler;
|
||||
sp<Handler> handler;
|
||||
TileIndex cur_tile = INVALID_TILE;
|
||||
public:
|
||||
StationSelectAction(const Handler &handler) : handler{handler} {}
|
||||
template<typename T>
|
||||
StationSelectAction(T &tool) { this->handler = make_sp<Handler>(tool); };
|
||||
~StationSelectAction() override = default;
|
||||
void Update(Point pt, TileIndex tile) override;
|
||||
bool HandleMousePress() override;
|
||||
@@ -137,13 +139,14 @@ concept ImplementsSizedPlacementHandler = std::derived_from<Handler, SizedPlacem
|
||||
template<ImplementsSizedPlacementHandler Handler>
|
||||
class SizedPlacementAction : public PlacementAction {
|
||||
private:
|
||||
Handler handler;
|
||||
sp<Handler> handler;
|
||||
TileIndex cur_tile = INVALID_TILE;
|
||||
public:
|
||||
SizedPlacementAction(const Handler &handler) : handler{handler} {}
|
||||
template<typename T>
|
||||
SizedPlacementAction(T &tool) { this->handler = make_sp<Handler>(tool); };
|
||||
~SizedPlacementAction() override = default;
|
||||
void Update(Point pt, TileIndex tile) override;
|
||||
std::optional<TileArea> GetArea() const override { return this->handler.GetArea(this->cur_tile); }
|
||||
std::optional<TileArea> GetArea() const override { return this->handler->GetArea(this->cur_tile); }
|
||||
bool HandleMousePress() override;
|
||||
void HandleMouseRelease() override;
|
||||
ToolGUIInfo GetGUIInfo() override;
|
||||
@@ -167,9 +170,10 @@ class DragNDropPlacementAction : public PlacementAction {
|
||||
private:
|
||||
TileIndex start_tile = INVALID_TILE;
|
||||
TileIndex cur_tile = INVALID_TILE;
|
||||
Handler handler;
|
||||
sp<Handler> handler;
|
||||
public:
|
||||
DragNDropPlacementAction(const Handler &handler) :handler{handler} {};
|
||||
template<typename T>
|
||||
DragNDropPlacementAction(T &tool) { this->handler = make_sp<Handler>(tool); };
|
||||
~DragNDropPlacementAction() override = default;
|
||||
void Update(Point pt, TileIndex tile) override;
|
||||
std::optional<TileArea> GetArea() const override;
|
||||
@@ -201,8 +205,6 @@ public:
|
||||
if (this->action) this->action->OnStationRemoved(station);
|
||||
}
|
||||
protected:
|
||||
template<typename Thandler, typename Tcallback, typename Targ>
|
||||
bool ExecuteBuildCommand(Thandler *handler, Tcallback callback, Targ arg);
|
||||
};
|
||||
|
||||
// RailStationBuildTool
|
||||
@@ -211,6 +213,7 @@ private:
|
||||
class RemoveHandler : public citymania::RemoveHandler {
|
||||
public:
|
||||
RailStationBuildTool &tool;
|
||||
// TODO storing tools in handlers isn't safe because of shared pointers
|
||||
RemoveHandler(RailStationBuildTool &tool) : tool(tool) {}
|
||||
~RemoveHandler() override = default;
|
||||
up<Command> GetCommand(TileArea area) override;
|
||||
|
||||
@@ -17,39 +17,17 @@ template<class T> using up=std::unique_ptr<T>;
|
||||
template<class T> using sp=std::shared_ptr<T>;
|
||||
template<class T> using wp=std::weak_ptr<T>;
|
||||
|
||||
/* C++14 implementation of make_unique */
|
||||
template<class T> struct _Unique_if {
|
||||
typedef std::unique_ptr<T> _Single_object;
|
||||
};
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto make_up(Args&&... args) {
|
||||
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class T> struct _Unique_if<T[]> {
|
||||
typedef std::unique_ptr<T[]> _Unknown_bound;
|
||||
};
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto make_sp(Args&&... args) {
|
||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class T, size_t N> struct _Unique_if<T[N]> {
|
||||
typedef void _Known_bound;
|
||||
};
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Single_object
|
||||
make_up(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename _Unique_if<T>::_Unknown_bound
|
||||
make_up(size_t n) {
|
||||
typedef typename std::remove_extent<T>::type U;
|
||||
return std::unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
make_up(Args&&...) = delete;
|
||||
|
||||
// template<typename T> const auto make_up = std::make_unique<T>;
|
||||
// template<typename T> const auto make_sp = std::make_shared<T>;
|
||||
template<typename T, class... Args> const auto make_sp = std::make_shared<T, Args...>;
|
||||
// template<typename T, class... Args> constexpr auto make_sp = std::make_shared<T, Args...>;
|
||||
|
||||
|
||||
enum class GameType: uint8_t {
|
||||
@@ -73,6 +51,15 @@ enum class ControllerType: uint8_t {
|
||||
TOWN_DEFENCE = 6,
|
||||
};
|
||||
|
||||
|
||||
// For use with std::visit
|
||||
template<typename ... Ts>
|
||||
struct Overload : Ts ... {
|
||||
using Ts::operator() ...;
|
||||
};
|
||||
template<class... Ts> Overload(Ts...) -> Overload<Ts...>;
|
||||
|
||||
|
||||
// Some utility funcitons for strings
|
||||
namespace string {
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
/** @file rail_gui.cpp %File for dealing with rail construction user interface */
|
||||
|
||||
#include "citymania/cm_highlight_type.hpp"
|
||||
#include "stdafx.h"
|
||||
#include "gui.h"
|
||||
#include "window_gui.h"
|
||||
@@ -52,6 +51,7 @@
|
||||
#include "debug.h"
|
||||
#include "citymania/cm_blueprint.hpp"
|
||||
#include "citymania/cm_commands.hpp"
|
||||
#include "citymania/cm_highlight_type.hpp"
|
||||
#include "citymania/cm_hotkeys.hpp"
|
||||
#include "citymania/cm_highlight.hpp"
|
||||
#include "citymania/cm_station_gui.hpp"
|
||||
|
||||
@@ -2520,3 +2520,10 @@ void ShowSelectWaypointIfNeeded(TileArea ta, StationPickerCmdProc proc)
|
||||
{
|
||||
ShowSelectBaseStationIfNeeded<Waypoint>(ta, std::move(proc));
|
||||
}
|
||||
|
||||
namespace citymania {
|
||||
void ShowSelectStationWindow(TileArea ta, StationPickerCmdProc&& proc) {
|
||||
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
|
||||
new SelectStationWindow<Station>(&_select_station_desc, ta, std::move(proc));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user