diff --git a/src/openrct2-ui/WindowManager.cpp b/src/openrct2-ui/WindowManager.cpp index 8163f5e09a..2f58bf9d37 100644 --- a/src/openrct2-ui/WindowManager.cpp +++ b/src/openrct2-ui/WindowManager.cpp @@ -488,7 +488,7 @@ public: return std::string(buffer); } - void SetMainView(const ScreenCoordsXY& viewPos, int32_t zoom, int32_t rotation) override + void SetMainView(const ScreenCoordsXY& viewPos, ZoomLevel zoom, int32_t rotation) override { auto mainWindow = window_get_main(); if (mainWindow != nullptr) @@ -503,8 +503,8 @@ public: if (zoomDifference != 0) { - viewport->view_width <<= zoomDifference; - viewport->view_height <<= zoomDifference; + viewport->view_width = viewport->view_width * zoomDifference; + viewport->view_height = viewport->view_height * zoomDifference; } mainWindow->savedViewPos.x -= viewport->view_width >> 1; mainWindow->savedViewPos.y -= viewport->view_height >> 1; diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index 85623819a4..aef53c9769 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -623,9 +623,9 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint return; } - if (_dpi->zoom_level != 0) + if (_dpi->zoom_level > 0) { - if (g1Element->flags & (1 << 4)) + if (g1Element->flags & G1_FLAG_HAS_ZOOM_SPRITE) { rct_drawpixelinfo zoomedDPI; zoomedDPI.bits = _dpi->bits; @@ -639,19 +639,22 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint DrawSprite((image & 0xFFF80000) | (g1Id - g1Element->zoomed_offset), x >> 1, y >> 1, tertiaryColour); return; } - if (g1Element->flags & (1 << 5)) + if (g1Element->flags & G1_FLAG_NO_ZOOM_DRAW) { return; } } - uint8_t zoomLevel = (1 << _dpi->zoom_level); int32_t left = x + g1Element->x_offset; int32_t top = y + g1Element->y_offset; - int32_t zoom_mask = 0xFFFFFFFF << _dpi->zoom_level; - if (_dpi->zoom_level && g1Element->flags & G1_FLAG_RLE_COMPRESSION) + int32_t zoom_mask; + if (_dpi->zoom_level >= 0) + zoom_mask = 0xFFFFFFFF * _dpi->zoom_level; + else + zoom_mask = 0xFFFFFFFF; + if (_dpi->zoom_level != 0 && (g1Element->flags & G1_FLAG_RLE_COMPRESSION)) { top -= ~zoom_mask; } @@ -667,7 +670,7 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint int32_t right = left + g1Element->width; int32_t bottom = top + g1Element->height; - if (_dpi->zoom_level && g1Element->flags & G1_FLAG_RLE_COMPRESSION) + if (_dpi->zoom_level != 0 && (g1Element->flags & G1_FLAG_RLE_COMPRESSION)) { bottom += top & ~zoom_mask; } @@ -686,10 +689,10 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint right -= _dpi->x; bottom -= _dpi->y; - left /= zoomLevel; - top /= zoomLevel; - right /= zoomLevel; - bottom /= zoomLevel; + left = left / _dpi->zoom_level; + top = top / _dpi->zoom_level; + right = right / _dpi->zoom_level; + bottom = bottom / _dpi->zoom_level; left += _clipLeft; top += _clipTop; @@ -774,8 +777,6 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t ma const auto textureMask = _textureCache->GetOrLoadImageTexture(maskImage); const auto textureColour = _textureCache->GetOrLoadImageTexture(colourImage); - uint8_t zoomLevel = (1 << _dpi->zoom_level); - int32_t drawOffsetX = g1ElementMask->x_offset; int32_t drawOffsetY = g1ElementMask->y_offset; int32_t drawWidth = std::min(g1ElementMask->width, g1ElementColour->width); @@ -800,10 +801,10 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t ma right -= _dpi->x; bottom -= _dpi->y; - left /= zoomLevel; - top /= zoomLevel; - right /= zoomLevel; - bottom /= zoomLevel; + left = left * _dpi->zoom_level; + top = top * _dpi->zoom_level; + right = right * _dpi->zoom_level; + bottom = bottom * _dpi->zoom_level; left += _clipLeft; top += _clipTop; @@ -1011,9 +1012,8 @@ void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo* dpi) _clipLeft = (int32_t)(bitsOffset % (screenDPI->width + screenDPI->pitch)); _clipTop = (int32_t)(bitsOffset / (screenDPI->width + screenDPI->pitch)); - - _clipRight = _clipLeft + (dpi->width >> dpi->zoom_level); - _clipBottom = _clipTop + (dpi->height >> dpi->zoom_level); + _clipRight = _clipLeft + (dpi->width / dpi->zoom_level); + _clipBottom = _clipTop + (dpi->height / dpi->zoom_level); _offsetX = _clipLeft - dpi->x; _offsetY = _clipTop - dpi->y; diff --git a/src/openrct2-ui/input/MouseInput.cpp b/src/openrct2-ui/input/MouseInput.cpp index f19031b828..ac4f10c18c 100644 --- a/src/openrct2-ui/input/MouseInput.cpp +++ b/src/openrct2-ui/input/MouseInput.cpp @@ -555,8 +555,8 @@ static void input_viewport_drag_continue() // As the user moved the mouse, don't interpret it as right click in any case. _ticksSinceDragStart = 1000; - differentialCoords.x *= 1 << (viewport->zoom + 1); - differentialCoords.y *= 1 << (viewport->zoom + 1); + differentialCoords.x = differentialCoords.x * (viewport->zoom + 1); + differentialCoords.y = differentialCoords.y * (viewport->zoom + 1); if (gConfigGeneral.invert_viewport_drag) { w->savedViewPos -= differentialCoords; @@ -1591,8 +1591,9 @@ void input_scroll_viewport(const ScreenCoordsXY& scrollScreenCoords) const int32_t speed = gConfigGeneral.edge_scrolling_speed; - int32_t dx = scrollScreenCoords.x * (speed << viewport->zoom); - int32_t dy = scrollScreenCoords.y * (speed << viewport->zoom); + int32_t multiplier = speed * viewport->zoom; + int32_t dx = scrollScreenCoords.x * multiplier; + int32_t dy = scrollScreenCoords.y * multiplier; if (scrollScreenCoords.x != 0) { diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 269249b475..736c611b21 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -627,8 +627,8 @@ static Peep* viewport_interaction_get_closest_peep(ScreenCoordsXY screenCoords, if (viewport == nullptr || viewport->zoom >= 2) return nullptr; - screenCoords.x = ((screenCoords.x - viewport->pos.x) << viewport->zoom) + viewport->viewPos.x; - screenCoords.y = ((screenCoords.y - viewport->pos.y) << viewport->zoom) + viewport->viewPos.y; + screenCoords.x = ((screenCoords.x - viewport->pos.x) * viewport->zoom) + viewport->viewPos.x; + screenCoords.y = ((screenCoords.y - viewport->pos.y) * viewport->zoom) + viewport->viewPos.y; closestPeep = nullptr; closestDistance = 0xFFFF; diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index 0c9dd30433..74ce9bc819 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -660,11 +660,10 @@ void window_guest_overview_resize(rct_window* w) auto reqViewportHeight = w->height - 72; if (viewport->width != reqViewportWidth || viewport->height != reqViewportHeight) { - uint8_t zoom_amount = 1 << viewport->zoom; viewport->width = reqViewportWidth; viewport->height = reqViewportHeight; - viewport->view_width = viewport->width / zoom_amount; - viewport->view_height = viewport->height / zoom_amount; + viewport->view_width = viewport->width / viewport->zoom; + viewport->view_height = viewport->height / viewport->zoom; } } window_guest_viewport_init(w); diff --git a/src/openrct2-ui/windows/Player.cpp b/src/openrct2-ui/windows/Player.cpp index 82572b0f16..ef2547491b 100644 --- a/src/openrct2-ui/windows/Player.cpp +++ b/src/openrct2-ui/windows/Player.cpp @@ -459,8 +459,8 @@ void window_player_overview_invalidate(rct_window* w) viewport->pos = w->windowPos + ScreenCoordsXY{ viewportWidget->left, viewportWidget->top }; viewport->width = viewportWidget->right - viewportWidget->left; viewport->height = viewportWidget->bottom - viewportWidget->top; - viewport->view_width = viewport->width << viewport->zoom; - viewport->view_height = viewport->height << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; + viewport->view_height = viewport->height * viewport->zoom; } // Only enable kick button for other players diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index c55be231d0..bcda34399c 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -2148,15 +2148,14 @@ static std::optional ride_get_place_position_from_screen_position(Scre { if (gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_SHIFT_Z) { - constexpr uint16_t maxHeight = (std::numeric_limits::max() - 32) - << MAX_ZOOM_LEVEL; + uint16_t maxHeight = (std::numeric_limits::max() - 32) * ZoomLevel::max(); _trackPlaceShiftZ = _trackPlaceShiftStart.y - screenCoords.y + 4; // Scale delta by zoom to match mouse position. auto* mainWnd = window_get_main(); if (mainWnd && mainWnd->viewport) { - _trackPlaceShiftZ <<= mainWnd->viewport->zoom; + _trackPlaceShiftZ = _trackPlaceShiftZ * mainWnd->viewport->zoom; } _trackPlaceShiftZ = floor2(_trackPlaceShiftZ, 8); diff --git a/src/openrct2-ui/windows/Staff.cpp b/src/openrct2-ui/windows/Staff.cpp index 4a03812c14..fa10c35f64 100644 --- a/src/openrct2-ui/windows/Staff.cpp +++ b/src/openrct2-ui/windows/Staff.cpp @@ -544,8 +544,8 @@ void window_staff_overview_resize(rct_window* w) { viewport->width = new_width; viewport->height = new_height; - viewport->view_width = new_width << viewport->zoom; - viewport->view_height = new_height << viewport->zoom; + viewport->view_width = new_width * viewport->zoom; + viewport->view_height = new_height * viewport->zoom; } } diff --git a/src/openrct2-ui/windows/TitleCommandEditor.cpp b/src/openrct2-ui/windows/TitleCommandEditor.cpp index c43ef4e58a..2da1db442f 100644 --- a/src/openrct2-ui/windows/TitleCommandEditor.cpp +++ b/src/openrct2-ui/windows/TitleCommandEditor.cpp @@ -214,7 +214,7 @@ static uint8_t get_zoom() rct_window* w = window_get_main(); if (w != nullptr) { - zoom = w->viewport->zoom; + zoom = static_cast(w->viewport->zoom); } return zoom; } diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index ae353f344e..c9adba89e5 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -870,11 +870,11 @@ static void window_top_toolbar_invalidate(rct_window* w) } // Zoomed out/in disable. Not sure where this code is in the original. - if (window_get_main()->viewport->zoom == 0) + if (window_get_main()->viewport->zoom == ZoomLevel::min()) { w->disabled_widgets |= (1 << WIDX_ZOOM_IN); } - else if (window_get_main()->viewport->zoom >= MAX_ZOOM_LEVEL) + else if (window_get_main()->viewport->zoom >= ZoomLevel::max()) { w->disabled_widgets |= (1 << WIDX_ZOOM_OUT); } @@ -1217,7 +1217,7 @@ static void sub_6E1F34( return; } - uint16_t maxPossibleHeight = (std::numeric_limits::max() - 32) << MAX_ZOOM_LEVEL; + uint16_t maxPossibleHeight = (std::numeric_limits::max() - 32) * ZoomLevel::max(); bool can_raise_item = false; if (selection.SceneryType == SCENERY_TYPE_SMALL) @@ -1310,7 +1310,7 @@ static void sub_6E1F34( auto* mainWnd = window_get_main(); if (mainWnd && mainWnd->viewport) { - gSceneryShiftPressZOffset <<= mainWnd->viewport->zoom; + gSceneryShiftPressZOffset = gSceneryShiftPressZOffset * mainWnd->viewport->zoom; } gSceneryShiftPressZOffset = floor2(gSceneryShiftPressZOffset, 8); @@ -3106,7 +3106,7 @@ static void window_top_toolbar_land_tool_drag(int16_t x, int16_t y) if (!viewport) return; - int16_t tile_height = -16 / (1 << viewport->zoom); + int16_t tile_height = -16 / viewport->zoom; int32_t y_diff = y - gInputDragLast.y; @@ -3149,8 +3149,7 @@ static void window_top_toolbar_water_tool_drag(int16_t x, int16_t y) if (!viewport) return; - int16_t dx = -16; - dx >>= viewport->zoom; + int16_t dx = -16 / viewport->zoom; y -= gInputDragLast.y; diff --git a/src/openrct2-ui/windows/Viewport.cpp b/src/openrct2-ui/windows/Viewport.cpp index 5efd7ef8da..f0d6f86171 100644 --- a/src/openrct2-ui/windows/Viewport.cpp +++ b/src/openrct2-ui/windows/Viewport.cpp @@ -130,14 +130,14 @@ static void window_viewport_mouseup(rct_window* w, rct_widgetindex widgetIndex) window_close(w); break; case WIDX_ZOOM_IN: - if (w->viewport != nullptr && w->viewport->zoom > 0) + if (w->viewport != nullptr && w->viewport->zoom > ZoomLevel::min()) { w->viewport->zoom--; w->Invalidate(); } break; case WIDX_ZOOM_OUT: - if (w->viewport != nullptr && w->viewport->zoom < 3) + if (w->viewport != nullptr && w->viewport->zoom < ZoomLevel::max()) { w->viewport->zoom++; w->Invalidate(); @@ -205,16 +205,16 @@ static void window_viewport_invalidate(rct_window* w) // Set disabled widgets w->disabled_widgets = 0; - if (viewport->zoom == 0) + if (viewport->zoom == ZoomLevel::min()) w->disabled_widgets |= 1 << WIDX_ZOOM_IN; - if (viewport->zoom >= 3) + if (viewport->zoom >= ZoomLevel::max()) w->disabled_widgets |= 1 << WIDX_ZOOM_OUT; viewport->pos = w->windowPos + ScreenCoordsXY{ viewportWidget->left, viewportWidget->top }; viewport->width = viewportWidget->right - viewportWidget->left; viewport->height = viewportWidget->bottom - viewportWidget->top; - viewport->view_width = viewport->width << viewport->zoom; - viewport->view_height = viewport->height << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; + viewport->view_height = viewport->height * viewport->zoom; } static void window_viewport_paint(rct_window* w, rct_drawpixelinfo* dpi) diff --git a/src/openrct2/audio/Audio.cpp b/src/openrct2/audio/Audio.cpp index b473e12db4..5900822465 100644 --- a/src/openrct2/audio/Audio.cpp +++ b/src/openrct2/audio/Audio.cpp @@ -220,7 +220,7 @@ static AudioParams audio_get_params_from_location(SoundId soundId, const CoordsX { int16_t vx = pos2.x - viewport->viewPos.x; int16_t vy = pos2.y - viewport->viewPos.y; - params.pan = viewport->pos.x + (vx >> viewport->zoom); + params.pan = viewport->pos.x + (vx / viewport->zoom); params.volume = SoundVolumeAdjust[static_cast(soundId)] + ((-1024 * viewport->zoom - 1) * (1 << volumeDown)) + 1; diff --git a/src/openrct2/drawing/Drawing.Sprite.cpp b/src/openrct2/drawing/Drawing.Sprite.cpp index 1fcd112c33..3c2ddc4113 100644 --- a/src/openrct2/drawing/Drawing.Sprite.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.cpp @@ -408,10 +408,10 @@ void FASTCALL gfx_bmp_sprite_to_buffer( const uint8_t* palette_pointer, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image, rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId) { - uint16_t zoom_level = dest_dpi->zoom_level; - uint8_t zoom_amount = 1 << zoom_level; - uint32_t dest_line_width = (dest_dpi->width / zoom_amount) + dest_dpi->pitch; - uint32_t source_line_width = source_image->width * zoom_amount; + auto zoom_level = dest_dpi->zoom_level; + uint8_t zoom_amount = 1 * zoom_level; + uint32_t dest_line_width = (dest_dpi->width / zoom_level) + dest_dpi->pitch; + uint32_t source_line_width = source_image->width * zoom_level; // Image uses the palette pointer to remap the colours of the image if (imageId.HasPrimary()) @@ -612,10 +612,10 @@ void FASTCALL gfx_draw_sprite_palette_set_software( } // Its used super often so we will define it to a separate variable. - int32_t zoom_level = dpi->zoom_level; - int32_t zoom_mask = 0xFFFFFFFF << zoom_level; + auto zoom_level = dpi->zoom_level; + int32_t zoom_mask = 0xFFFFFFFF * zoom_level; - if (zoom_level && g1->flags & G1_FLAG_RLE_COMPRESSION) + if (zoom_level != 0 && g1->flags & G1_FLAG_RLE_COMPRESSION) { x -= ~zoom_mask; y -= ~zoom_mask; @@ -656,7 +656,7 @@ void FASTCALL gfx_draw_sprite_palette_set_software( } else { - if (g1->flags & G1_FLAG_RLE_COMPRESSION && zoom_level) + if ((g1->flags & G1_FLAG_RLE_COMPRESSION) && zoom_level != 0) { source_start_y -= dest_start_y & ~zoom_mask; height += dest_start_y & ~zoom_mask; @@ -675,7 +675,7 @@ void FASTCALL gfx_draw_sprite_palette_set_software( if (height <= 0) return; - dest_start_y >>= zoom_level; + dest_start_y = dest_start_y / zoom_level; // This will be the width of the drawn image int32_t width = g1->width; @@ -701,7 +701,7 @@ void FASTCALL gfx_draw_sprite_palette_set_software( } else { - if (g1->flags & G1_FLAG_RLE_COMPRESSION && zoom_level) + if ((g1->flags & G1_FLAG_RLE_COMPRESSION) && zoom_level != 0) { source_start_x -= dest_start_x & ~zoom_mask; } @@ -719,11 +719,11 @@ void FASTCALL gfx_draw_sprite_palette_set_software( return; } - dest_start_x >>= zoom_level; + dest_start_x = dest_start_x / zoom_level; uint8_t* dest_pointer = dpi->bits; // Move the pointer to the start point of the destination - dest_pointer += ((dpi->width >> zoom_level) + dpi->pitch) * dest_start_y + dest_start_x; + dest_pointer += ((dpi->width / zoom_level) + dpi->pitch) * dest_start_y + dest_start_x; if (g1->flags & G1_FLAG_RLE_COMPRESSION) { diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index 2f6f642fdc..133d8efb7a 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -12,6 +12,7 @@ #include "../common.h" #include "../interface/Colour.h" +#include "../interface/ZoomLevel.hpp" namespace OpenRCT2 { @@ -42,7 +43,7 @@ struct rct_drawpixelinfo int16_t width{}; int16_t height{}; int16_t pitch{}; // note: this is actually (pitch - width) - uint16_t zoom_level{}; + ZoomLevel zoom_level{}; OpenRCT2::Drawing::IDrawingEngine* DrawingEngine{}; }; diff --git a/src/openrct2/drawing/DrawingFast.cpp b/src/openrct2/drawing/DrawingFast.cpp index 9db5e4fbe0..e24470cfac 100644 --- a/src/openrct2/drawing/DrawingFast.cpp +++ b/src/openrct2/drawing/DrawingFast.cpp @@ -147,7 +147,7 @@ static void FASTCALL DrawRLESprite1( const uint8_t* source_bits_pointer, uint8_t* dest_bits_pointer, const uint8_t* palette_pointer, const rct_drawpixelinfo* dpi, int32_t source_y_start, int32_t height, int32_t source_x_start, int32_t width) { - int32_t zoom_level = dpi->zoom_level; + auto zoom_level = static_cast(dpi->zoom_level); switch (zoom_level) { case 0: diff --git a/src/openrct2/drawing/LightFX.cpp b/src/openrct2/drawing/LightFX.cpp index 28b25d272e..b76465aa50 100644 --- a/src/openrct2/drawing/LightFX.cpp +++ b/src/openrct2/drawing/LightFX.cpp @@ -70,12 +70,12 @@ static uint32_t LightListCurrentCountFront; static int16_t _current_view_x_front = 0; static int16_t _current_view_y_front = 0; static uint8_t _current_view_rotation_front = 0; -static uint8_t _current_view_zoom_front = 0; +static ZoomLevel _current_view_zoom_front = 0; static int16_t _current_view_x_back = 0; static int16_t _current_view_y_back = 0; static uint8_t _current_view_rotation_back = 0; -static uint8_t _current_view_zoom_back = 0; -static uint8_t _current_view_zoom_back_delay = 0; +static ZoomLevel _current_view_zoom_back = 0; +static ZoomLevel _current_view_zoom_back_delay = 0; static rct_palette gPalette_light; @@ -202,8 +202,8 @@ void lightfx_prepare_light_list() int32_t posOnScreenX = entry->viewCoords.x - _current_view_x_front; int32_t posOnScreenY = entry->viewCoords.y - _current_view_y_front; - posOnScreenX >>= _current_view_zoom_front; - posOnScreenY >>= _current_view_zoom_front; + posOnScreenX = posOnScreenX / _current_view_zoom_front; + posOnScreenY = posOnScreenY / _current_view_zoom_front; if ((posOnScreenX < -128) || (posOnScreenY < -128) || (posOnScreenX > _pixelInfo.width + 128) || (posOnScreenY > _pixelInfo.height + 128)) @@ -263,7 +263,7 @@ void lightfx_prepare_light_list() break; } - int32_t mapFrontDiv = 1 << _current_view_zoom_front; + int32_t mapFrontDiv = 1 * _current_view_zoom_front; // clang-format off static int16_t offsetPattern[26] = { @@ -397,17 +397,18 @@ void lightfx_prepare_light_list() entry->lightIntensity = std::min( 0xFF, (entry->lightIntensity * lightIntensityOccluded) / (totalSamplePoints * 100)); } - entry->lightIntensity = std::max(0x00, entry->lightIntensity - _current_view_zoom_front * 5); + entry->lightIntensity = std::max( + 0x00, entry->lightIntensity - static_cast(_current_view_zoom_front) * 5); if (_current_view_zoom_front > 0) { - if ((entry->lightType & 0x3) < _current_view_zoom_front) + if ((entry->lightType & 0x3) < static_cast(_current_view_zoom_front)) { entry->lightType = LIGHTFX_LIGHT_TYPE_NONE; continue; } - entry->lightType -= _current_view_zoom_front; + entry->lightType -= static_cast(_current_view_zoom_front); } } } @@ -484,8 +485,8 @@ void lightfx_render_lights_to_frontbuffer() { inRectCentreX -= _current_view_x_front; inRectCentreY -= _current_view_y_front; - inRectCentreX >>= _current_view_zoom_front; - inRectCentreY >>= _current_view_zoom_front; + inRectCentreX = inRectCentreX / _current_view_zoom_front; + inRectCentreY = inRectCentreY / _current_view_zoom_front; } switch (entry->lightType) diff --git a/src/openrct2/drawing/ScrollingText.cpp b/src/openrct2/drawing/ScrollingText.cpp index d06dd64f2e..b9c8a37c88 100644 --- a/src/openrct2/drawing/ScrollingText.cpp +++ b/src/openrct2/drawing/ScrollingText.cpp @@ -1450,7 +1450,7 @@ int32_t scrolling_text_setup( rct_drawpixelinfo* dpi = &session->DPI; - if (dpi->zoom_level != 0) + if (dpi->zoom_level > 0) return SPR_SCROLLING_TEXT_DEFAULT; _drawSCrollNextIndex++; diff --git a/src/openrct2/drawing/X8DrawingEngine.cpp b/src/openrct2/drawing/X8DrawingEngine.cpp index 269717d35e..b6e411cb29 100644 --- a/src/openrct2/drawing/X8DrawingEngine.cpp +++ b/src/openrct2/drawing/X8DrawingEngine.cpp @@ -471,8 +471,8 @@ void X8DrawingContext::Clear(uint8_t paletteIndex) { rct_drawpixelinfo* dpi = _dpi; - int32_t w = dpi->width >> dpi->zoom_level; - int32_t h = dpi->height >> dpi->zoom_level; + int32_t w = dpi->width / dpi->zoom_level; + int32_t h = dpi->height / dpi->zoom_level; uint8_t* ptr = dpi->bits; for (int32_t y = 0; y < h; y++) @@ -699,8 +699,7 @@ void X8DrawingContext::FilterRect(FILTER_PALETTE_ID palette, int32_t left, int32 // 00678B7E 00678C83 // Location in screen buffer? uint8_t* dst = dpi->bits - + (uint32_t)((startY >> (dpi->zoom_level)) * ((dpi->width >> dpi->zoom_level) + dpi->pitch) - + (startX >> dpi->zoom_level)); + + (uint32_t)((startY / dpi->zoom_level) * ((dpi->width / dpi->zoom_level) + dpi->pitch) + (startX / dpi->zoom_level)); // Find colour in colour table? uint16_t g1Index = palette_to_g1_offset[palette]; @@ -708,11 +707,12 @@ void X8DrawingContext::FilterRect(FILTER_PALETTE_ID palette, int32_t left, int32 if (g1Element != nullptr) { auto g1Bits = g1Element->offset; - const int32_t scaled_width = width >> dpi->zoom_level; - const int32_t step = ((dpi->width >> dpi->zoom_level) + dpi->pitch); + const int32_t scaled_width = width / dpi->zoom_level; + const int32_t step = ((dpi->width / dpi->zoom_level) + dpi->pitch); // Fill the rectangle with the colours from the colour table - for (int32_t i = 0; i < (height >> dpi->zoom_level); i++) + auto c = height / dpi->zoom_level; + for (int32_t i = 0; i < c; i++) { uint8_t* nextdst = dst + step * i; for (int32_t j = 0; j < scaled_width; j++) diff --git a/src/openrct2/interface/Screenshot.cpp b/src/openrct2/interface/Screenshot.cpp index b9ea7a2331..5ecd6dba48 100644 --- a/src/openrct2/interface/Screenshot.cpp +++ b/src/openrct2/interface/Screenshot.cpp @@ -348,7 +348,7 @@ static void ReleaseDPI(rct_drawpixelinfo& dpi) dpi.height = 0; } -static rct_viewport GetGiantViewport(int32_t mapSize, int32_t rotation, int32_t zoom) +static rct_viewport GetGiantViewport(int32_t mapSize, int32_t rotation, ZoomLevel zoom) { // Get the tile coordinates of each corner auto leftTileCoords = GetEdgeTile(mapSize, rotation, EdgeType::LEFT, false); @@ -370,8 +370,8 @@ static rct_viewport GetGiantViewport(int32_t mapSize, int32_t rotation, int32_t viewport.viewPos = { left, top }; viewport.view_width = right - left; viewport.view_height = bottom - top; - viewport.width = viewport.view_width >> zoom; - viewport.height = viewport.view_height >> zoom; + viewport.width = viewport.view_width / zoom; + viewport.height = viewport.view_height / zoom; viewport.zoom = zoom; return viewport; } @@ -403,7 +403,7 @@ void screenshot_giant() } int32_t rotation = get_current_rotation(); - int32_t zoom = 0; + ZoomLevel zoom = 0; auto mainWindow = window_get_main(); auto vp = window_get_viewport(mainWindow); @@ -463,7 +463,7 @@ static void benchgfx_render_screenshots(const char* inputPath, std::unique_ptr dpis; std::array viewports; diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 05b8491cce..26b900a238 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -46,7 +46,7 @@ rct_viewport* g_music_tracking_viewport; static std::unique_ptr _paintJobs; ScreenCoordsXY gSavedView; -uint8_t gSavedViewZoom; +ZoomLevel gSavedViewZoom; uint8_t gSavedViewRotation; paint_entry* gNextFreePaintStruct; @@ -253,49 +253,49 @@ static void viewport_redraw_after_shift( if (viewport->pos.x < window->windowPos.x) { viewport->width = window->windowPos.x - viewport->pos.x; - viewport->view_width = viewport->width << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; viewport_redraw_after_shift(dpi, window, viewport, x, y); viewport->pos.x += viewport->width; - viewport->viewPos.x += viewport->width << viewport->zoom; + viewport->viewPos.x += viewport->width * viewport->zoom; viewport->width = view_copy.width - viewport->width; - viewport->view_width = viewport->width << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; viewport_redraw_after_shift(dpi, window, viewport, x, y); } else if (viewport->pos.x + viewport->width > window->windowPos.x + window->width) { viewport->width = window->windowPos.x + window->width - viewport->pos.x; - viewport->view_width = viewport->width << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; viewport_redraw_after_shift(dpi, window, viewport, x, y); viewport->pos.x += viewport->width; - viewport->viewPos.x += viewport->width << viewport->zoom; + viewport->viewPos.x += viewport->width * viewport->zoom; viewport->width = view_copy.width - viewport->width; - viewport->view_width = viewport->width << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; viewport_redraw_after_shift(dpi, window, viewport, x, y); } else if (viewport->pos.y < window->windowPos.y) { viewport->height = window->windowPos.y - viewport->pos.y; - viewport->view_width = viewport->width << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; viewport_redraw_after_shift(dpi, window, viewport, x, y); viewport->pos.y += viewport->height; - viewport->viewPos.y += viewport->height << viewport->zoom; + viewport->viewPos.y += viewport->height * viewport->zoom; viewport->height = view_copy.height - viewport->height; - viewport->view_width = viewport->width << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; viewport_redraw_after_shift(dpi, window, viewport, x, y); } else if (viewport->pos.y + viewport->height > window->windowPos.y + window->height) { viewport->height = window->windowPos.y + window->height - viewport->pos.y; - viewport->view_width = viewport->width << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; viewport_redraw_after_shift(dpi, window, viewport, x, y); viewport->pos.y += viewport->height; - viewport->viewPos.y += viewport->height << viewport->zoom; + viewport->viewPos.y += viewport->height * viewport->zoom; viewport->height = view_copy.height - viewport->height; - viewport->view_width = viewport->width << viewport->zoom; + viewport->view_width = viewport->width * viewport->zoom; viewport_redraw_after_shift(dpi, window, viewport, x, y); } @@ -401,13 +401,13 @@ static void viewport_shift_pixels( static void viewport_move(int16_t x, int16_t y, rct_window* w, rct_viewport* viewport) { - uint8_t zoom = (1 << viewport->zoom); + auto zoom = viewport->zoom; // Note: do not do the subtraction and then divide! // Note: Due to arithmetic shift != /zoom a shift will have to be used // hopefully when 0x006E7FF3 is finished this can be converted to /zoom. - int16_t x_diff = (viewport->viewPos.x >> viewport->zoom) - (x >> viewport->zoom); - int16_t y_diff = (viewport->viewPos.y >> viewport->zoom) - (y >> viewport->zoom); + int16_t x_diff = (viewport->viewPos.x / viewport->zoom) - (x / viewport->zoom); + int16_t y_diff = (viewport->viewPos.y / viewport->zoom) - (y / viewport->zoom); viewport->viewPos = { x, y }; @@ -797,10 +797,10 @@ void viewport_render( top = std::max(top - viewport->pos.y, 0); bottom = std::min(bottom - viewport->pos.y, viewport->height); - left <<= viewport->zoom; - right <<= viewport->zoom; - top <<= viewport->zoom; - bottom <<= viewport->zoom; + left = left * viewport->zoom; + right = right * viewport->zoom; + top = top * viewport->zoom; + bottom = bottom * viewport->zoom; left += viewport->viewPos.x; right += viewport->viewPos.x; @@ -896,7 +896,7 @@ void viewport_paint( uint32_t viewFlags = viewport->flags; uint16_t width = right - left; uint16_t height = bottom - top; - uint16_t bitmask = 0xFFFF & (0xFFFF << viewport->zoom); + uint16_t bitmask = viewport->zoom >= 0 ? 0xFFFF & (0xFFFF * viewport->zoom) : 0xFFFF; width &= bitmask; height &= bitmask; @@ -906,11 +906,11 @@ void viewport_paint( bottom = top + height; int16_t x = (int16_t)(left - (int16_t)(viewport->viewPos.x & bitmask)); - x >>= viewport->zoom; + x = x / viewport->zoom; x += viewport->pos.x; int16_t y = (int16_t)(top - (int16_t)(viewport->viewPos.y & bitmask)); - y >>= viewport->zoom; + y = y / viewport->zoom; y += viewport->pos.y; rct_drawpixelinfo dpi1 = *dpi; @@ -919,7 +919,7 @@ void viewport_paint( dpi1.y = top; dpi1.width = width; dpi1.height = height; - dpi1.pitch = (dpi->width + dpi->pitch) - (width >> viewport->zoom); + dpi1.pitch = (dpi->width + dpi->pitch) - (width / viewport->zoom); dpi1.zoom_level = viewport->zoom; // make sure, the compare operation is done in int16_t to avoid the loop becoming an infiniteloop. @@ -959,8 +959,8 @@ void viewport_paint( { int16_t leftPitch = x - dpi2.x; dpi2.width -= leftPitch; - dpi2.bits += leftPitch >> dpi2.zoom_level; - dpi2.pitch += leftPitch >> dpi2.zoom_level; + dpi2.bits += leftPitch / dpi2.zoom_level; + dpi2.pitch += leftPitch / dpi2.zoom_level; dpi2.x = x; } @@ -969,7 +969,7 @@ void viewport_paint( { int16_t rightPitch = paintRight - x - 32; paintRight -= rightPitch; - dpi2.pitch += rightPitch >> dpi2.zoom_level; + dpi2.pitch += rightPitch / dpi2.zoom_level; } dpi2.width = paintRight - dpi2.x; @@ -1057,8 +1057,8 @@ std::optional screen_pos_to_map_pos(const ScreenCoordsXY& screenCoords ScreenCoordsXY screen_coord_to_viewport_coord(rct_viewport* viewport, const ScreenCoordsXY& screenCoords) { ScreenCoordsXY ret; - ret.x = ((screenCoords.x - viewport->pos.x) << viewport->zoom) + viewport->viewPos.x; - ret.y = ((screenCoords.y - viewport->pos.y) << viewport->zoom) + viewport->viewPos.y; + ret.x = ((screenCoords.x - viewport->pos.x) * viewport->zoom) + viewport->viewPos.x; + ret.y = ((screenCoords.y - viewport->pos.y) * viewport->zoom) + viewport->viewPos.y; return ret; } @@ -1415,7 +1415,7 @@ static bool is_sprite_interacted_with_palette_set( return false; } - if (dpi->zoom_level != 0) + if (dpi->zoom_level > 0) { if (g1->flags & G1_FLAG_NO_ZOOM_DRAW) { @@ -1432,14 +1432,14 @@ static bool is_sprite_interacted_with_palette_set( /* .height = */ dpi->height, /* .width = */ dpi->width, /* .pitch = */ dpi->pitch, - /* .zoom_level = */ (uint16_t)(dpi->zoom_level - 1), + /* .zoom_level = */ dpi->zoom_level - 1, }; return is_sprite_interacted_with_palette_set(&zoomed_dpi, imageId - g1->zoomed_offset, x / 2, y / 2, palette); } } - int32_t round = 1 << dpi->zoom_level; + int32_t round = std::max(1, 1 * dpi->zoom_level); if (g1->flags & G1_FLAG_RLE_COMPRESSION) { @@ -1650,11 +1650,11 @@ void get_map_coordinates_from_pos_window( if (screenCoords.x >= 0 && screenCoords.x < (int32_t)myviewport->width && screenCoords.y >= 0 && screenCoords.y < (int32_t)myviewport->height) { - screenCoords.x <<= myviewport->zoom; - screenCoords.y <<= myviewport->zoom; + screenCoords.x = screenCoords.x * myviewport->zoom; + screenCoords.y = screenCoords.y * myviewport->zoom; screenCoords += myviewport->viewPos; - screenCoords.x &= (0xFFFF << myviewport->zoom) & 0xFFFF; - screenCoords.y &= (0xFFFF << myviewport->zoom) & 0xFFFF; + screenCoords.x &= (0xFFFF * myviewport->zoom) & 0xFFFF; + screenCoords.y &= (0xFFFF * myviewport->zoom) & 0xFFFF; rct_drawpixelinfo dpi; dpi.x = screenCoords.x; dpi.y = screenCoords.y; @@ -1714,15 +1714,14 @@ void viewport_invalidate(rct_viewport* viewport, int32_t left, int32_t top, int3 right = std::min(right, viewportRight); bottom = std::min(bottom, viewportBottom); - uint8_t zoom = 1 << viewport->zoom; left -= viewportLeft; top -= viewportTop; right -= viewportLeft; bottom -= viewportTop; - left /= zoom; - top /= zoom; - right /= zoom; - bottom /= zoom; + left = left / viewport->zoom; + top = top / viewport->zoom; + right = right / viewport->zoom; + bottom = bottom / viewport->zoom; left += viewport->pos.x; top += viewport->pos.y; right += viewport->pos.x; diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index 4e5e84998f..9d110852fe 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -108,7 +108,6 @@ struct InteractionInfo }; #define MAX_VIEWPORT_COUNT WINDOW_LIMIT_MAX -#define MAX_ZOOM_LEVEL 3 /** * A reference counter for whether something is forcing the grid lines to show. When the counter @@ -122,7 +121,7 @@ extern uint8_t gShowConstuctionRightsRefCount; extern rct_viewport g_viewport_list[MAX_VIEWPORT_COUNT]; extern rct_viewport* g_music_tracking_viewport; extern ScreenCoordsXY gSavedView; -extern uint8_t gSavedViewZoom; +extern ZoomLevel gSavedViewZoom; extern uint8_t gSavedViewRotation; extern paint_entry* gNextFreePaintStruct; diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index 2366c27b9b..7999d783e9 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -974,12 +974,12 @@ void window_viewport_get_map_coords_by_cursor( } // Rebase mouse position onto centre of window, and compensate for zoom level. - int32_t rebased_x = ((w->width >> 1) - mouseCoords.x) * (1 << w->viewport->zoom), - rebased_y = ((w->height >> 1) - mouseCoords.y) * (1 << w->viewport->zoom); + int32_t rebased_x = ((w->width / 2) - mouseCoords.x) * w->viewport->zoom; + int32_t rebased_y = ((w->height / 2) - mouseCoords.y) * w->viewport->zoom; // Compute cursor offset relative to tile. - *offset_x = (w->savedViewPos.x - (centreLoc->x + rebased_x)) * (1 << w->viewport->zoom); - *offset_y = (w->savedViewPos.y - (centreLoc->y + rebased_y)) * (1 << w->viewport->zoom); + *offset_x = (w->savedViewPos.x - (centreLoc->x + rebased_x)) * w->viewport->zoom; + *offset_y = (w->savedViewPos.y - (centreLoc->y + rebased_y)) * w->viewport->zoom; } void window_viewport_centre_tile_around_cursor(rct_window* w, int16_t map_x, int16_t map_y, int16_t offset_x, int16_t offset_y) @@ -998,19 +998,19 @@ void window_viewport_centre_tile_around_cursor(rct_window* w, int16_t map_x, int auto mouseCoords = context_get_cursor_position_scaled(); // Rebase mouse position onto centre of window, and compensate for zoom level. - int32_t rebased_x = ((w->width >> 1) - mouseCoords.x) * (1 << w->viewport->zoom), - rebased_y = ((w->height >> 1) - mouseCoords.y) * (1 << w->viewport->zoom); + int32_t rebased_x = ((w->width >> 1) - mouseCoords.x) * w->viewport->zoom; + int32_t rebased_y = ((w->height >> 1) - mouseCoords.y) * w->viewport->zoom; // Apply offset to the viewport. - w->savedViewPos = { centreLoc->x + rebased_x + (offset_x / (1 << w->viewport->zoom)), - centreLoc->y + rebased_y + (offset_y / (1 << w->viewport->zoom)) }; + w->savedViewPos = { centreLoc->x + rebased_x + (offset_x / w->viewport->zoom), + centreLoc->y + rebased_y + (offset_y / w->viewport->zoom) }; } -void window_zoom_set(rct_window* w, int32_t zoomLevel, bool atCursor) +void window_zoom_set(rct_window* w, ZoomLevel zoomLevel, bool atCursor) { rct_viewport* v = w->viewport; - zoomLevel = std::clamp(zoomLevel, 0, MAX_ZOOM_LEVEL); + zoomLevel = std::clamp(zoomLevel, ZoomLevel::min(), ZoomLevel::max()); if (v->zoom == zoomLevel) return; @@ -1663,8 +1663,8 @@ void window_resize_gui_scenario_editor(int32_t width, int32_t height) mainWind->height = height; viewport->width = width; viewport->height = height; - viewport->view_width = width << viewport->zoom; - viewport->view_height = height << viewport->zoom; + viewport->view_width = width * viewport->zoom; + viewport->view_height = height * viewport->zoom; if (mainWind->widgets != nullptr && mainWind->widgets[WC_MAIN_WINDOW__0].type == WWT_VIEWPORT) { mainWind->widgets[WC_MAIN_WINDOW__0].right = width; @@ -1734,18 +1734,12 @@ void window_update_viewport_ride_music() g_music_tracking_viewport = viewport; gWindowAudioExclusive = w; - switch (viewport->zoom) - { - case 0: - gVolumeAdjustZoom = 0; - break; - case 1: - gVolumeAdjustZoom = 30; - break; - default: - gVolumeAdjustZoom = 60; - break; - } + if (viewport->zoom <= 0) + gVolumeAdjustZoom = 0; + else if (viewport->zoom == 1) + gVolumeAdjustZoom = 30; + else + gVolumeAdjustZoom = 60; break; } } diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index 5f955b2e58..251f1c3612 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -14,6 +14,7 @@ #include "../ride/RideTypes.h" #include "../world/Location.hpp" #include "../world/ScenerySelection.h" +#include "ZoomLevel.hpp" #include #include @@ -97,7 +98,7 @@ struct rct_viewport int16_t view_width; int16_t view_height; uint32_t flags; - uint8_t zoom; + ZoomLevel zoom; uint8_t var_11; uint8_t visibility; // VISIBILITY_CACHE }; @@ -674,7 +675,7 @@ void window_rotate_camera(rct_window* w, int32_t direction); void window_viewport_get_map_coords_by_cursor( rct_window* w, int16_t* map_x, int16_t* map_y, int16_t* offset_x, int16_t* offset_y); void window_viewport_centre_tile_around_cursor(rct_window* w, int16_t map_x, int16_t map_y, int16_t offset_x, int16_t offset_y); -void window_zoom_set(rct_window* w, int32_t zoomLevel, bool atCursor); +void window_zoom_set(rct_window* w, ZoomLevel zoomLevel, bool atCursor); void window_zoom_in(rct_window* w, bool atCursor); void window_zoom_out(rct_window* w, bool atCursor); void main_window_zoom(bool zoomIn, bool atCursor); diff --git a/src/openrct2/interface/ZoomLevel.hpp b/src/openrct2/interface/ZoomLevel.hpp new file mode 100644 index 0000000000..0b2bde6819 --- /dev/null +++ b/src/openrct2/interface/ZoomLevel.hpp @@ -0,0 +1,151 @@ +/***************************************************************************** + * Copyright (c) 2020 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include + +struct ZoomLevel +{ +private: + int8_t _level{}; + +public: + constexpr ZoomLevel() + : _level() + { + } + + constexpr ZoomLevel(int8_t level) + : _level(level) + { + } + + constexpr ZoomLevel(const ZoomLevel& rhs) + : _level(rhs._level) + { + } + + explicit operator int8_t() const + { + return _level; + } + + ZoomLevel operator++(int) + { + ZoomLevel tmp(*this); + operator++(); + return tmp; + } + + ZoomLevel& operator++() + { + _level++; + return *this; + } + + ZoomLevel operator--(int) + { + ZoomLevel tmp(*this); + operator--(); + return tmp; + } + + ZoomLevel& operator--() + { + _level--; + return *this; + } + + ZoomLevel& operator=(const ZoomLevel& other) + { + _level = other._level; + return *this; + } + + ZoomLevel& operator+=(const ZoomLevel& rhs) + { + _level += rhs._level; + return *this; + } + + ZoomLevel& operator-=(const ZoomLevel& rhs) + { + _level -= rhs._level; + return *this; + } + + friend ZoomLevel operator+(ZoomLevel lhs, const ZoomLevel& rhs) + { + lhs += rhs; + return lhs; + } + + friend ZoomLevel operator-(ZoomLevel lhs, const ZoomLevel& rhs) + { + lhs -= rhs; + return lhs; + } + + friend bool operator==(const ZoomLevel& lhs, const ZoomLevel& rhs) + { + return lhs._level == rhs._level; + } + + friend bool operator!=(const ZoomLevel& lhs, const ZoomLevel& rhs) + { + return lhs._level != rhs._level; + } + + friend bool operator>=(const ZoomLevel& lhs, const ZoomLevel& rhs) + { + return lhs._level >= rhs._level; + } + + friend bool operator<=(const ZoomLevel& lhs, const ZoomLevel& rhs) + { + return lhs._level <= rhs._level; + } + + friend bool operator>(const ZoomLevel& lhs, const ZoomLevel& rhs) + { + return lhs._level > rhs._level; + } + + friend bool operator<(const ZoomLevel& lhs, const ZoomLevel& rhs) + { + return lhs._level < rhs._level; + } + + template friend T operator*(const T& lhs, const ZoomLevel& rhs) + { + if (rhs._level < 0) + return lhs >> -rhs._level; + else + return lhs << rhs._level; + } + + template friend T operator/(const T& lhs, const ZoomLevel& rhs) + { + if (rhs._level < 0) + return lhs << -rhs._level; + else + return lhs >> rhs._level; + } + + static constexpr ZoomLevel min() + { + return -2; + } + + static constexpr ZoomLevel max() + { + return 3; + } +}; diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index df8c133e04..068c942b66 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -690,12 +690,11 @@ static uint32_t paint_ps_colourify_image(uint32_t imageId, uint8_t spriteType, u static void draw_pixel_info_crop_by_zoom(rct_drawpixelinfo* dpi) { - int32_t zoom = dpi->zoom_level; + dpi->x = dpi->x / dpi->zoom_level; + dpi->y = dpi->y / dpi->zoom_level; + dpi->width = dpi->width / dpi->zoom_level; + dpi->height = dpi->height / dpi->zoom_level; dpi->zoom_level = 0; - dpi->x >>= zoom; - dpi->y >>= zoom; - dpi->width >>= zoom; - dpi->height >>= zoom; } paint_session* paint_session_alloc(rct_drawpixelinfo* dpi, uint32_t viewFlags) diff --git a/src/openrct2/paint/sprite/Paint.Litter.cpp b/src/openrct2/paint/sprite/Paint.Litter.cpp index 214565b394..c1968844fb 100644 --- a/src/openrct2/paint/sprite/Paint.Litter.cpp +++ b/src/openrct2/paint/sprite/Paint.Litter.cpp @@ -70,7 +70,7 @@ void litter_paint(paint_session* session, const Litter* litter, int32_t imageDir rct_drawpixelinfo* dpi; dpi = &session->DPI; - if (dpi->zoom_level != 0) + if (dpi->zoom_level > 0) return; // If zoomed at all no litter drawn // litter has no sprite direction so remove that diff --git a/src/openrct2/paint/sprite/Paint.Misc.cpp b/src/openrct2/paint/sprite/Paint.Misc.cpp index c4cc074c30..718cb33235 100644 --- a/src/openrct2/paint/sprite/Paint.Misc.cpp +++ b/src/openrct2/paint/sprite/Paint.Misc.cpp @@ -44,7 +44,7 @@ void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDir case SPRITE_MISC_MONEY_EFFECT: // 1 { - if (dpi->zoom_level != 0) + if (dpi->zoom_level > 0) { return; } @@ -59,7 +59,7 @@ void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDir case SPRITE_MISC_CRASHED_VEHICLE_PARTICLE: // 2 { - if (dpi->zoom_level != 0) + if (dpi->zoom_level > 0) { return; } @@ -98,7 +98,7 @@ void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDir case SPRITE_MISC_JUMPING_FOUNTAIN_WATER: // 6 case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW: // 9 { - if (dpi->zoom_level != 0) + if (dpi->zoom_level > 0) { return; } diff --git a/src/openrct2/paint/tile_element/Paint.Entrance.cpp b/src/openrct2/paint/tile_element/Paint.Entrance.cpp index d9d0d28186..ed704d2b3f 100644 --- a/src/openrct2/paint/tile_element/Paint.Entrance.cpp +++ b/src/openrct2/paint/tile_element/Paint.Entrance.cpp @@ -343,7 +343,7 @@ void entrance_paint(paint_session* session, uint8_t direction, int32_t height, c rct_drawpixelinfo* dpi = &session->DPI; - if (session->ViewFlags & VIEWPORT_FLAG_PATH_HEIGHTS && dpi->zoom_level == 0) + if (session->ViewFlags & VIEWPORT_FLAG_PATH_HEIGHTS && dpi->zoom_level <= 0) { if (entrance_get_directions(tile_element) & 0xF) { diff --git a/src/openrct2/paint/tile_element/Paint.Path.cpp b/src/openrct2/paint/tile_element/Paint.Path.cpp index 20cbca549e..b5fe6531ee 100644 --- a/src/openrct2/paint/tile_element/Paint.Path.cpp +++ b/src/openrct2/paint/tile_element/Paint.Path.cpp @@ -304,7 +304,7 @@ static void path_bit_benches_paint( static void path_bit_jumping_fountains_paint( paint_session* session, rct_scenery_entry* pathBitEntry, int32_t height, uint32_t pathBitImageFlags, rct_drawpixelinfo* dpi) { - if (dpi->zoom_level != 0) + if (dpi->zoom_level > 0) return; uint32_t imageId = pathBitEntry->image; diff --git a/src/openrct2/paint/tile_element/Paint.Surface.cpp b/src/openrct2/paint/tile_element/Paint.Surface.cpp index 754a8754f4..988a37d2d6 100644 --- a/src/openrct2/paint/tile_element/Paint.Surface.cpp +++ b/src/openrct2/paint/tile_element/Paint.Surface.cpp @@ -942,7 +942,7 @@ void surface_paint(paint_session* session, uint8_t direction, uint16_t height, c session->DidPassSurface = true; session->SurfaceElement = tileElement; - const uint16_t zoomLevel = dpi->zoom_level; + const auto zoomLevel = dpi->zoom_level; const uint8_t rotation = session->CurrentRotation; const uint32_t terrain_type = tileElement->AsSurface()->GetSurfaceStyle(); const uint8_t surfaceShape = viewport_surface_paint_setup_get_relative_slope(tileElement, rotation); diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index edd4d9a409..0b4ad80d75 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -1411,7 +1411,7 @@ void peep_update_crowd_noise() // 207360000 maybe related to DSBVOLUME_MIN which is -10,000 (dB/100) volume = 120 - std::min(visiblePeeps, 120); volume = volume * volume * volume * volume; - volume = (((207360000 - volume) >> viewport->zoom) - 207360000) / 65536 - 150; + volume = (((207360000 - volume) / viewport->zoom) - 207360000) / 65536 - 150; // Load and play crowd noise if needed and set volume if (_crowdSoundChannel == nullptr) diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index 2c35de2bfa..6833e754e1 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -363,7 +363,7 @@ void S6Exporter::Export() _s6.saved_age = gSavedAge; _s6.saved_view_x = gSavedView.x; _s6.saved_view_y = gSavedView.y; - _s6.saved_view_zoom = gSavedViewZoom; + _s6.saved_view_zoom = static_cast(std::clamp(gSavedViewZoom, 0, 3)); _s6.saved_view_rotation = gSavedViewRotation; ExportMapAnimations(); diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 1999ccbfff..38dd70587b 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -3491,7 +3491,7 @@ int32_t ride_music_params_update( return ride_music_params_update_label_58(position, tuneId); } - int32_t x2 = viewport->pos.x + ((rotatedCoords.x - viewport->viewPos.x) >> viewport->zoom); + int32_t x2 = viewport->pos.x + ((rotatedCoords.x - viewport->viewPos.x) / viewport->zoom); x2 *= 0x10000; uint16_t screenwidth = context_get_width(); if (screenwidth < 64) @@ -3500,7 +3500,7 @@ int32_t ride_music_params_update( } int32_t pan_x = ((x2 / screenwidth) - 0x8000) >> 4; - int32_t y2 = viewport->pos.y + ((rotatedCoords.y - viewport->viewPos.y) >> viewport->zoom); + int32_t y2 = viewport->pos.y + ((rotatedCoords.y - viewport->viewPos.y) / viewport->zoom); y2 *= 0x10000; uint16_t screenheight = context_get_height(); if (screenheight < 64) diff --git a/src/openrct2/ride/TrackPaint.cpp b/src/openrct2/ride/TrackPaint.cpp index 1344a43603..9f64dc714c 100644 --- a/src/openrct2/ride/TrackPaint.cpp +++ b/src/openrct2/ride/TrackPaint.cpp @@ -2169,7 +2169,7 @@ void track_paint(paint_session* session, uint8_t direction, int32_t height, cons int32_t trackSequence = tileElement->AsTrack()->GetSequenceIndex(); int32_t trackColourScheme = tileElement->AsTrack()->GetColourScheme(); - if ((session->ViewFlags & VIEWPORT_FLAG_TRACK_HEIGHTS) && dpi->zoom_level == 0) + if ((session->ViewFlags & VIEWPORT_FLAG_TRACK_HEIGHTS) && dpi->zoom_level <= 0) { session->InteractionType = VIEWPORT_INTERACTION_ITEM_NONE; if (TrackHeightMarkerPositions[trackType] & (1 << trackSequence)) diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index fb139a8f6e..98e11b1006 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -939,7 +939,7 @@ rct_vehicle_sound_params Vehicle::CreateSoundParam(uint16_t priority) const rct_vehicle_sound_params param; param.priority = priority; int32_t panX = (sprite_left / 2) + (sprite_right / 2) - g_music_tracking_viewport->viewPos.x; - panX >>= g_music_tracking_viewport->zoom; + panX = panX / g_music_tracking_viewport->zoom; panX += g_music_tracking_viewport->pos.x; uint16_t screenWidth = context_get_width(); @@ -950,7 +950,7 @@ rct_vehicle_sound_params Vehicle::CreateSoundParam(uint16_t priority) const param.pan_x = ((((panX * 65536) / screenWidth) - 0x8000) >> 4); int32_t panY = (sprite_top / 2) + (sprite_bottom / 2) - g_music_tracking_viewport->viewPos.y; - panY >>= g_music_tracking_viewport->zoom; + panY = panY / g_music_tracking_viewport->zoom; panY += g_music_tracking_viewport->pos.y; uint16_t screenHeight = context_get_height(); @@ -1049,8 +1049,12 @@ static void vehicle_sounds_update_window_setup() g_music_tracking_viewport = viewport; gWindowAudioExclusive = window; - const uint8_t ZoomToVolume[MAX_ZOOM_LEVEL + 1] = { 0, 35, 70, 70 }; - gVolumeAdjustZoom = ZoomToVolume[viewport->zoom]; + if (viewport->zoom <= 0) + gVolumeAdjustZoom = 0; + else if (viewport->zoom == 1) + gVolumeAdjustZoom = 35; + else + gVolumeAdjustZoom = 70; } static uint8_t vehicle_sounds_update_get_pan_volume(rct_vehicle_sound_params* sound_params) diff --git a/src/openrct2/ride/gentle/HauntedHouse.cpp b/src/openrct2/ride/gentle/HauntedHouse.cpp index 899cff6bbd..46aeab14b1 100644 --- a/src/openrct2/ride/gentle/HauntedHouse.cpp +++ b/src/openrct2/ride/gentle/HauntedHouse.cpp @@ -63,7 +63,7 @@ static void paint_haunted_house_structure( boundBox.offset_y, height); rct_drawpixelinfo* dpi = &session->DPI; - if (dpi->zoom_level == 0 && frameNum != 0) + if (dpi->zoom_level <= 0 && frameNum != 0) { switch (direction) { diff --git a/src/openrct2/ui/DummyWindowManager.cpp b/src/openrct2/ui/DummyWindowManager.cpp index 2ad857c880..8d1c6ab0a7 100644 --- a/src/openrct2/ui/DummyWindowManager.cpp +++ b/src/openrct2/ui/DummyWindowManager.cpp @@ -53,7 +53,7 @@ namespace OpenRCT2::Ui { return std::string(); } - void SetMainView(const ScreenCoordsXY& viewPos, int32_t zoom, int32_t rotation) override + void SetMainView(const ScreenCoordsXY& viewPos, ZoomLevel zoom, int32_t rotation) override { } void UpdateMouseWheel() override diff --git a/src/openrct2/ui/WindowManager.h b/src/openrct2/ui/WindowManager.h index 17afce589a..1392b68db9 100644 --- a/src/openrct2/ui/WindowManager.h +++ b/src/openrct2/ui/WindowManager.h @@ -35,7 +35,7 @@ namespace OpenRCT2::Ui virtual void HandleInput() abstract; virtual void HandleKeyboard(bool isTitle) abstract; virtual std::string GetKeyboardShortcutString(int32_t shortcut) abstract; - virtual void SetMainView(const ScreenCoordsXY& viewPos, int32_t zoom, int32_t rotation) abstract; + virtual void SetMainView(const ScreenCoordsXY& viewPos, ZoomLevel zoom, int32_t rotation) abstract; virtual void UpdateMouseWheel() abstract; virtual rct_window* GetOwner(const rct_viewport* viewport) abstract; };