Fix #15439: Ride viewport is partially grey

The ride viewport does not work the same as other viewports due to the selection of views that it has. After refactoring the focus system to use a more streamlined approach the ride viewport lost its invalidation on resizing. If the ride window was to use the same viewport update code as say the guest window then the viewport focus still ends up incorrect due to it no longer centring the focus. Therefore the best approach was to lose the focus on resize and force a recalculation of it.

Also renamed Focus2 to Focus as Focus2 was meant to just be fill in whilst removing the original focus structs.
This commit is contained in:
Duncan 2021-09-21 10:06:04 +01:00 committed by GitHub
parent c56810e6a5
commit a268350615
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 51 additions and 56 deletions

View File

@ -274,7 +274,7 @@ rct_window* WindowCreate(
w->min_height = height;
w->max_height = height;
w->focus2 = std::nullopt;
w->focus = std::nullopt;
w->page = 0;
w->var_48C = 0;
w->var_492 = 0;

View File

@ -786,8 +786,7 @@ namespace OpenRCT2::Ui::Windows
auto wheight = viewportWidget->height() - 1;
if (viewport == nullptr)
{
const auto focus = Focus2(CoordsXYZ(0, 0, 0));
viewport_create(this, { left, top }, wwidth, wheight, focus);
viewport_create(this, { left, top }, wwidth, wheight, Focus(CoordsXYZ(0, 0, 0)));
flags |= WF_NO_SCROLLING;
Invalidate();
}

View File

@ -79,10 +79,9 @@ private:
void CreateViewport()
{
rct_widget* viewportWidget = &window_banner_widgets[WIDX_VIEWPORT];
const auto focus = Focus2(_bannerViewPos);
viewport_create(
this, windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 },
(viewportWidget->width()) - 1, (viewportWidget->height()) - 1, focus);
(viewportWidget->width()) - 1, (viewportWidget->height()) - 1, Focus(_bannerViewPos));
if (viewport != nullptr)
viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0;

View File

@ -40,8 +40,7 @@ rct_window* window_editor_main_open()
&window_editor_main_events, WC_MAIN_WINDOW, WF_STICK_TO_BACK);
window->widgets = window_editor_main_widgets;
const auto focus = Focus2(CoordsXYZ(0x0FFF, 0x0FFF, 0));
viewport_create(window, window->windowPos, window->width, window->height, focus);
viewport_create(window, window->windowPos, window->width, window->height, Focus(CoordsXYZ(0x0FFF, 0x0FFF, 0)));
window->viewport->flags |= 0x0400;
gCurrentRotation = 0;

View File

@ -732,7 +732,7 @@ void window_guest_viewport_init(rct_window* w)
uint16_t origViewportFlags{};
if (w->viewport != nullptr)
{
if (w->focus2.has_value())
if (w->focus.has_value())
return;
origViewportFlags = w->viewport->flags;
@ -750,7 +750,7 @@ void window_guest_viewport_init(rct_window* w)
int32_t width = view_widget->width() - 1;
int32_t height = view_widget->height() - 1;
viewport_create(w, screenPos, width, height, w->focus2.value());
viewport_create(w, screenPos, width, height, w->focus.value());
if (w->viewport != nullptr && reCreateViewport)
{
w->viewport->flags = origViewportFlags;

View File

@ -41,8 +41,7 @@ rct_window* window_main_open()
WF_STICK_TO_BACK);
window->widgets = window_main_widgets;
const auto focus = Focus2(CoordsXYZ(0x0FFF, 0x0FFF, 0));
viewport_create(window, window->windowPos, window->width, window->height, focus);
viewport_create(window, window->windowPos, window->width, window->height, Focus(CoordsXYZ(0x0FFF, 0x0FFF, 0)));
window->viewport->flags |= VIEWPORT_FLAG_SOUND_ON;
gCurrentRotation = 0;
gShowGridLinesRefCount = 0;

View File

@ -740,11 +740,11 @@ static void window_park_init_viewport(rct_window* w)
if (w->page != WINDOW_PARK_PAGE_ENTRANCE)
return;
std::optional<Focus2> focus = std::nullopt;
std::optional<Focus> focus = std::nullopt;
if (!gParkEntrances.empty())
{
const auto& entrance = gParkEntrances[0];
focus = Focus2(CoordsXYZ{ entrance.x + 16, entrance.y + 16, entrance.z + 32 });
focus = Focus(CoordsXYZ{ entrance.x + 16, entrance.y + 16, entrance.z + 32 });
}
if (w->viewport == nullptr)
@ -760,7 +760,7 @@ static void window_park_init_viewport(rct_window* w)
// Call invalidate event
window_event_invalidate_call(w);
w->focus2 = focus;
w->focus = focus;
if (focus.has_value())
{

View File

@ -547,7 +547,7 @@ static void window_player_set_page(rct_window* w, int32_t page)
{
if (w->viewport == nullptr)
{
const auto focus = Focus2(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ());
const auto focus = Focus(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ());
viewport_create(w, w->windowPos, w->width, w->height, focus);
w->flags |= WF_NO_SCROLLING;
window_event_invalidate_call(w);

View File

@ -1589,7 +1589,7 @@ static void window_ride_init_viewport(rct_window* w)
int32_t viewSelectionIndex = w->ride.view - 1;
std::optional<Focus2> focus;
std::optional<Focus> focus;
if (viewSelectionIndex >= 0 && viewSelectionIndex < ride->num_vehicles && ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)
{
@ -1609,7 +1609,7 @@ static void window_ride_init_viewport(rct_window* w)
}
if (vehId != SPRITE_INDEX_NULL)
{
focus = Focus2(vehId);
focus = Focus(vehId);
}
}
else if (viewSelectionIndex >= ride->num_vehicles && viewSelectionIndex < (ride->num_vehicles + ride->num_stations))
@ -1618,7 +1618,7 @@ static void window_ride_init_viewport(rct_window* w)
if (stationIndex)
{
const auto location = ride->stations[*stationIndex].GetStart();
focus = Focus2(location);
focus = Focus(location);
}
}
else
@ -1630,14 +1630,14 @@ static void window_ride_init_viewport(rct_window* w)
if (w->number < ride_overall_views.size())
{
const auto& view = ride_overall_views[w->number];
focus = Focus2(view.loc, view.zoom);
focus = Focus(view.loc, view.zoom);
}
}
uint16_t viewport_flags = 0;
if (w->viewport != nullptr)
{
if (focus == w->focus2)
if (focus == w->focus)
{
return;
}
@ -1651,7 +1651,7 @@ static void window_ride_init_viewport(rct_window* w)
window_event_invalidate_call(w);
w->focus2 = focus;
w->focus = focus;
// rct2: 0x006aec9c only used here so brought it into the function
if (!w->viewport && !ride->overall_view.IsNull())
@ -1662,7 +1662,7 @@ static void window_ride_init_viewport(rct_window* w)
int32_t width = view_widget->width() - 1;
int32_t height = view_widget->height() - 1;
viewport_create(w, screenPos, width, height, w->focus2.value());
viewport_create(w, screenPos, width, height, w->focus.value());
w->flags |= WF_NO_SCROLLING;
w->Invalidate();
@ -1796,6 +1796,8 @@ static void window_ride_main_resize(rct_window* w)
w->flags |= WF_RESIZABLE;
window_set_resize(w, 316, minHeight, 500, 450);
// Unlike with other windows, the focus needs to be recentred so its best to just reset it.
w->focus = std::nullopt;
window_ride_init_viewport(w);
}

View File

@ -127,10 +127,9 @@ public:
// Create viewport
rct_widget& viewportWidget = window_sign_widgets[WIDX_VIEWPORT];
const auto focus = Focus2(CoordsXYZ{ signViewPosition, viewZ });
viewport_create(
this, windowPos + ScreenCoordsXY{ viewportWidget.left + 1, viewportWidget.top + 1 }, viewportWidget.width() - 1,
viewportWidget.height() - 1, focus);
viewportWidget.height() - 1, Focus(CoordsXYZ{ signViewPosition, viewZ }));
viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0;
Invalidate();
@ -300,10 +299,9 @@ public:
// Create viewport
rct_widget* viewportWidget = &window_sign_widgets[WIDX_VIEWPORT];
const auto focus = Focus2(CoordsXYZ{ signViewPos });
viewport_create(
this, windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, viewportWidget->width() - 1,
viewportWidget->height() - 1, focus);
viewportWidget->height() - 1, Focus(CoordsXYZ{ signViewPos }));
if (viewport != nullptr)
viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0;
Invalidate();

View File

@ -1346,7 +1346,7 @@ void window_staff_viewport_init(rct_window* w)
if (w->page != WINDOW_STAFF_OVERVIEW)
return;
std::optional<Focus2> focus;
std::optional<Focus> focus;
const auto peep = GetStaff(w);
if (peep == nullptr)
@ -1356,14 +1356,14 @@ void window_staff_viewport_init(rct_window* w)
if (peep->State != PeepState::Picked)
{
focus = Focus2(peep->sprite_index);
focus = Focus(peep->sprite_index);
}
uint16_t viewport_flags;
if (w->viewport)
{
if (focus == w->focus2)
if (focus == w->focus)
return;
viewport_flags = w->viewport->flags;
@ -1378,7 +1378,7 @@ void window_staff_viewport_init(rct_window* w)
window_event_invalidate_call(w);
w->focus2 = focus;
w->focus = focus;
if (peep->State != PeepState::Picked)
{

View File

@ -227,7 +227,7 @@ void window_title_command_editor_open(TitleSequence* sequence, int32_t index, bo
WindowInitScrollWidgets(window);
rct_widget* const viewportWidget = &window_title_command_editor_widgets[WIDX_VIEWPORT];
const auto focus = Focus2(CoordsXYZ{ 0, 0, 0 });
const auto focus = Focus(CoordsXYZ{ 0, 0, 0 });
viewport_create(
window, window->windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 },
viewportWidget->width() - 1, viewportWidget->height() - 1, focus);

View File

@ -76,8 +76,7 @@ public:
enabled_widgets = (1ULL << WIDX_CLOSE) | (1ULL << WIDX_ZOOM_IN) | (1ULL << WIDX_ZOOM_OUT) | (1ULL << WIDX_LOCATE);
// Create viewport
const auto focus = Focus2(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ());
viewport_create(this, windowPos, width, height, focus);
viewport_create(this, windowPos, width, height, Focus(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ()));
if (viewport == nullptr)
{
Close();

View File

@ -117,14 +117,14 @@ std::optional<ScreenCoordsXY> centre_2d_coordinates(const CoordsXYZ& loc, rct_vi
return { screenCoord };
}
CoordsXYZ Focus2::GetPos() const
CoordsXYZ Focus::GetPos() const
{
return std::visit(
[](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, Focus2::CoordinateFocus>)
if constexpr (std::is_same_v<T, Focus::CoordinateFocus>)
return arg;
else if constexpr (std::is_same_v<T, Focus2::EntityFocus>)
else if constexpr (std::is_same_v<T, Focus::EntityFocus>)
{
auto* centreEntity = GetEntity(arg);
if (centreEntity != nullptr)
@ -158,7 +158,7 @@ CoordsXYZ Focus2::GetPos() const
* flags: edx top most 2 bits 0b_X1 for zoom clear see below for 2nd bit.
* w: esi
*/
void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus2& focus)
void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus)
{
rct_viewport* viewport = nullptr;
if (_viewports.size() >= MAX_VIEWPORT_COUNT)
@ -188,9 +188,9 @@ void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t
w->viewport_target_sprite = std::visit(
[](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, Focus2::CoordinateFocus>)
if constexpr (std::is_same_v<T, Focus::CoordinateFocus>)
return SPRITE_INDEX_NULL;
else if constexpr (std::is_same_v<T, Focus2::EntityFocus>)
else if constexpr (std::is_same_v<T, Focus::EntityFocus>)
return arg;
},
focus.data);
@ -702,7 +702,7 @@ void viewport_update_smart_sprite_follow(rct_window* window)
break;
default: // All other types don't need any "smart" following; steam particle, duck, money effect, etc.
window->focus2 = Focus2(window->viewport_smart_follow_sprite);
window->focus = Focus(window->viewport_smart_follow_sprite);
window->viewport_target_sprite = window->viewport_smart_follow_sprite;
break;
}
@ -710,14 +710,14 @@ void viewport_update_smart_sprite_follow(rct_window* window)
void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep)
{
Focus2 focus = Focus2(peep->sprite_index);
Focus focus = Focus(peep->sprite_index);
window->viewport_target_sprite = peep->sprite_index;
if (peep->State == PeepState::Picked)
{
window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL;
window->viewport_target_sprite = SPRITE_INDEX_NULL;
window->focus2 = std::nullopt; // No focus
window->focus = std::nullopt; // No focus
return;
}
@ -734,7 +734,7 @@ void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep)
const auto car = train->GetCar(peep->CurrentCar);
if (car != nullptr)
{
focus = Focus2(car->sprite_index);
focus = Focus(car->sprite_index);
overallFocus = false;
window->viewport_target_sprite = car->sprite_index;
}
@ -752,12 +752,12 @@ void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep)
coordFocus.x = xy.x;
coordFocus.y = xy.y;
coordFocus.z = tile_element_height(xy) + (4 * COORDS_Z_STEP);
focus = Focus2(coordFocus);
focus = Focus(coordFocus);
window->viewport_target_sprite = SPRITE_INDEX_NULL;
}
}
window->focus2 = focus;
window->focus = focus;
}
void viewport_update_smart_staff_follow(rct_window* window, const Staff* peep)
@ -766,17 +766,17 @@ void viewport_update_smart_staff_follow(rct_window* window, const Staff* peep)
{
window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL;
window->viewport_target_sprite = SPRITE_INDEX_NULL;
window->focus2 = std::nullopt;
window->focus = std::nullopt;
return;
}
window->focus2 = Focus2(window->viewport_smart_follow_sprite);
window->focus = Focus(window->viewport_smart_follow_sprite);
window->viewport_target_sprite = window->viewport_smart_follow_sprite;
}
void viewport_update_smart_vehicle_follow(rct_window* window)
{
window->focus2 = Focus2(window->viewport_smart_follow_sprite);
window->focus = Focus(window->viewport_smart_follow_sprite);
window->viewport_target_sprite = window->viewport_smart_follow_sprite;
}

View File

@ -104,7 +104,7 @@ extern uint8_t gCurrentRotation;
void viewport_init_all();
std::optional<ScreenCoordsXY> centre_2d_coordinates(const CoordsXYZ& loc, rct_viewport* viewport);
void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus2& focus);
void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus);
void viewport_remove(rct_viewport* viewport);
void viewports_invalidate(int32_t left, int32_t top, int32_t right, int32_t bottom, int32_t maxZoom = -1);
void viewport_update_position(rct_window* window);

View File

@ -195,7 +195,7 @@ struct rct_scroll
constexpr auto WINDOW_SCROLL_UNDEFINED = std::numeric_limits<uint16_t>::max();
struct Focus2
struct Focus
{
using CoordinateFocus = CoordsXYZ;
using EntityFocus = uint16_t;
@ -203,7 +203,7 @@ struct Focus2
uint8_t zoom = 0;
std::variant<CoordinateFocus, EntityFocus> data;
template<typename T> constexpr explicit Focus2(T newValue, uint8_t newZoom = 0)
template<typename T> constexpr explicit Focus(T newValue, uint8_t newZoom = 0)
{
data = newValue;
zoom = newZoom;
@ -211,7 +211,7 @@ struct Focus2
CoordsXYZ GetPos() const;
constexpr bool operator==(const Focus2& other) const
constexpr bool operator==(const Focus& other) const
{
if (zoom != other.zoom)
{
@ -219,7 +219,7 @@ struct Focus2
}
return data == other.data;
}
constexpr bool operator!=(const Focus2& other) const
constexpr bool operator!=(const Focus& other) const
{
return !(*this == other);
}

View File

@ -12,10 +12,10 @@ void rct_window::SetLocation(const CoordsXYZ& coords)
void rct_window::ScrollToViewport()
{
if (viewport == nullptr || !focus2.has_value())
if (viewport == nullptr || !focus.has_value())
return;
CoordsXYZ newCoords = focus2.value().GetPos();
CoordsXYZ newCoords = focus.value().GetPos();
auto mainWindow = window_get_main();
if (mainWindow != nullptr)

View File

@ -55,7 +55,7 @@ struct rct_window
uint32_t list_item_positions[1024]{};
uint16_t no_list_items{}; // 0 for no items
int16_t selected_list_item{}; // -1 for none selected
std::optional<Focus2> focus2;
std::optional<Focus> focus;
union
{
campaign_variables campaign;