mirror of https://github.com/OpenRCT2/OpenRCT2.git
Update the UI at screen refresh rate (#20214)
* Update the UI at screen refresh rate * Decouple input from ticks, fix scroll at high frame rates * Fix holding down mouse button on buttons causing too many events * Subtract the initial delay to keep the same behavior as before * Guard against the rare case where the value might be 0 * Fix right click not working correctly * Fix odd behavior when using right click to scroll lists * Make touch work again, fix mouse panning in fullscreen (borderless) * Update changelog.txt
This commit is contained in:
parent
0b18bc0923
commit
6bd5f75330
|
@ -3,6 +3,7 @@
|
|||
- Feature: [OpenMusic#41] Official Title Theme by Allister Brimble.
|
||||
- Improved: [#20200] Allow audio files to play to up to 44100hz sample rate (from 22050hz).
|
||||
- Change: [#20110] Fix a few RCT1 build height parity discrepancies.
|
||||
- Fix: [#6152] Camera and UI are no longer locked at 40hz providing a smoother experience.
|
||||
- Fix: [#19823] Parkobj, disallow overriding objects of different object types.
|
||||
- Fix: [#20111] All coaster types can access the new diagonal slope pieces.
|
||||
- Fix: [#20155] Fairground organ style 2 shows up as regular song, rather than for the merry-go-round.
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <openrct2/world/Banner.h>
|
||||
#include <openrct2/world/Map.h>
|
||||
#include <openrct2/world/Scenery.h>
|
||||
#include <optional>
|
||||
|
||||
struct RCTMouseData
|
||||
{
|
||||
|
@ -44,7 +45,7 @@ static RCTMouseData _mouseInputQueue[64];
|
|||
static uint8_t _mouseInputQueueReadIndex = 0;
|
||||
static uint8_t _mouseInputQueueWriteIndex = 0;
|
||||
|
||||
static uint32_t _ticksSinceDragStart;
|
||||
static std::optional<uint32_t> _ticksSinceDragStart;
|
||||
static WidgetRef _dragWidget;
|
||||
static uint8_t _dragScrollIndex;
|
||||
static int32_t _originalWindowWidth;
|
||||
|
@ -59,7 +60,7 @@ uint16_t gTooltipTimeout;
|
|||
WidgetRef gTooltipWidget;
|
||||
ScreenCoordsXY gTooltipCursor;
|
||||
|
||||
static int16_t _clickRepeatTicks;
|
||||
static std::optional<uint32_t> _clickRepeatTicks;
|
||||
|
||||
static MouseState GameGetNextInput(ScreenCoordsXY& screenCoords);
|
||||
static void InputWidgetOver(const ScreenCoordsXY& screenCoords, WindowBase* w, WidgetIndex widgetIndex);
|
||||
|
@ -178,7 +179,7 @@ static void InputScrollDragBegin(const ScreenCoordsXY& screenCoords, WindowBase*
|
|||
_dragWidget.window_classification = w->classification;
|
||||
_dragWidget.window_number = w->number;
|
||||
_dragWidget.widget_index = widgetIndex;
|
||||
_ticksSinceDragStart = 0;
|
||||
_ticksSinceDragStart = gCurrentRealTimeTicks;
|
||||
|
||||
_dragScrollIndex = WindowGetScrollDataIndex(*w, widgetIndex);
|
||||
ContextHideCursor();
|
||||
|
@ -197,6 +198,8 @@ static void InputScrollDragContinue(const ScreenCoordsXY& screenCoords, WindowBa
|
|||
auto& scroll = w->scrolls[scrollIndex];
|
||||
|
||||
ScreenCoordsXY differentialCoords = screenCoords - gInputDragLast;
|
||||
if (differentialCoords.x == 0 && differentialCoords.y == 0)
|
||||
return;
|
||||
|
||||
if (scroll.flags & HSCROLLBAR_VISIBLE)
|
||||
{
|
||||
|
@ -242,10 +245,9 @@ static void InputScrollRight(const ScreenCoordsXY& screenCoords, MouseState stat
|
|||
switch (state)
|
||||
{
|
||||
case MouseState::Released:
|
||||
_ticksSinceDragStart += gCurrentDeltaTime;
|
||||
if (screenCoords.x != 0 || screenCoords.y != 0)
|
||||
{
|
||||
_ticksSinceDragStart = 1000;
|
||||
_ticksSinceDragStart = std::nullopt;
|
||||
InputScrollDragContinue(screenCoords, w);
|
||||
}
|
||||
break;
|
||||
|
@ -348,7 +350,7 @@ static void GameHandleInputMouse(const ScreenCoordsXY& screenCoords, MouseState
|
|||
else if (state == MouseState::RightRelease)
|
||||
{
|
||||
InputViewportDragEnd();
|
||||
if (_ticksSinceDragStart < 500)
|
||||
if (_ticksSinceDragStart.has_value() && gCurrentRealTimeTicks - _ticksSinceDragStart.value() < 500)
|
||||
{
|
||||
// If the user pressed the right mouse button for less than 500 ticks, interpret as right click
|
||||
ViewportInteractionRightClick(screenCoords);
|
||||
|
@ -525,7 +527,7 @@ static void InputViewportDragBegin(WindowBase& w)
|
|||
_inputState = InputState::ViewportRight;
|
||||
_dragWidget.window_classification = w.classification;
|
||||
_dragWidget.window_number = w.number;
|
||||
_ticksSinceDragStart = 0;
|
||||
_ticksSinceDragStart = gCurrentRealTimeTicks;
|
||||
auto cursorPosition = ContextGetCursorPosition();
|
||||
gInputDragLast = cursorPosition;
|
||||
if (!gConfigGeneral.InvertViewportDrag)
|
||||
|
@ -543,9 +545,11 @@ static void InputViewportDragContinue()
|
|||
Viewport* viewport;
|
||||
|
||||
auto newDragCoords = ContextGetCursorPosition();
|
||||
const CursorState* cursorState = ContextGetCursorState();
|
||||
|
||||
auto differentialCoords = newDragCoords - gInputDragLast;
|
||||
if (differentialCoords.x == 0 && differentialCoords.y == 0)
|
||||
return;
|
||||
|
||||
w = WindowFindByNumber(_dragWidget.window_classification, _dragWidget.window_number);
|
||||
|
||||
// #3294: Window can be closed during a drag session, so just finish
|
||||
|
@ -557,7 +561,6 @@ static void InputViewportDragContinue()
|
|||
}
|
||||
|
||||
viewport = w->viewport;
|
||||
_ticksSinceDragStart += gCurrentDeltaTime;
|
||||
if (viewport == nullptr)
|
||||
{
|
||||
ContextShowCursor();
|
||||
|
@ -571,7 +574,7 @@ static void InputViewportDragContinue()
|
|||
|
||||
// If the drag time is less than 500 the "drag" is usually interpreted as a right click.
|
||||
// As the user moved the mouse, don't interpret it as right click in any case.
|
||||
_ticksSinceDragStart = 1000;
|
||||
_ticksSinceDragStart = std::nullopt;
|
||||
|
||||
differentialCoords.x = (viewport->zoom + 1).ApplyTo(differentialCoords.x);
|
||||
differentialCoords.y = (viewport->zoom + 1).ApplyTo(differentialCoords.y);
|
||||
|
@ -586,6 +589,7 @@ static void InputViewportDragContinue()
|
|||
}
|
||||
}
|
||||
|
||||
const CursorState* cursorState = ContextGetCursorState();
|
||||
if (cursorState->touch || gConfigGeneral.InvertViewportDrag)
|
||||
{
|
||||
gInputDragLast = newDragCoords;
|
||||
|
@ -1086,7 +1090,7 @@ static void InputWidgetLeft(const ScreenCoordsXY& screenCoords, WindowBase* w, W
|
|||
gPressedWidget.widget_index = widgetIndex;
|
||||
_inputFlags |= INPUT_FLAG_WIDGET_PRESSED;
|
||||
_inputState = InputState::WidgetPressed;
|
||||
_clickRepeatTicks = 1;
|
||||
_clickRepeatTicks = gCurrentRealTimeTicks;
|
||||
|
||||
WidgetInvalidateByNumber(windowClass, windowNumber, widgetIndex);
|
||||
WindowEventMouseDownCall(w, widgetIndex);
|
||||
|
@ -1304,17 +1308,28 @@ void InputStateWidgetPressed(
|
|||
if (WidgetIsDisabled(*w, widgetIndex))
|
||||
break;
|
||||
|
||||
if (_clickRepeatTicks != 0)
|
||||
// If this variable is non-zero then its the last tick the mouse down event was fired.
|
||||
if (_clickRepeatTicks.has_value())
|
||||
{
|
||||
_clickRepeatTicks++;
|
||||
// The initial amount of time in ticks to wait until the first click repeat.
|
||||
constexpr auto ticksUntilRepeats = 16U;
|
||||
|
||||
// Handle click repeat
|
||||
if (_clickRepeatTicks >= 16 && (_clickRepeatTicks & 3) == 0)
|
||||
// The amount of ticks between each click repeat.
|
||||
constexpr auto eventDelayInTicks = 3U;
|
||||
|
||||
// The amount of ticks since the last click repeat.
|
||||
const auto clickRepeatsDelta = gCurrentRealTimeTicks - _clickRepeatTicks.value();
|
||||
|
||||
// Handle click repeat, only start this when at least 16 ticks elapsed.
|
||||
if (clickRepeatsDelta >= ticksUntilRepeats && (clickRepeatsDelta & eventDelayInTicks) == 0)
|
||||
{
|
||||
if (WidgetIsHoldable(*w, widgetIndex))
|
||||
{
|
||||
WindowEventMouseDownCall(w, widgetIndex);
|
||||
}
|
||||
|
||||
// Subtract initial delay from here on we want the event each third tick.
|
||||
_clickRepeatTicks = gCurrentRealTimeTicks - ticksUntilRepeats;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1439,7 +1454,7 @@ void InputStateWidgetPressed(
|
|||
return;
|
||||
}
|
||||
|
||||
_clickRepeatTicks = 0;
|
||||
_clickRepeatTicks = std::nullopt;
|
||||
if (_inputState != InputState::DropdownActive)
|
||||
{
|
||||
// Hold down widget and drag outside of area??
|
||||
|
|
|
@ -1112,12 +1112,12 @@ namespace OpenRCT2
|
|||
{
|
||||
Tick();
|
||||
|
||||
// Always run this at a fixed rate, Update can cause multiple ticks if the game is speed up.
|
||||
WindowUpdateAll();
|
||||
|
||||
_ticksAccumulator -= GAME_UPDATE_TIME_MS;
|
||||
}
|
||||
|
||||
ContextHandleInput();
|
||||
WindowUpdateAll();
|
||||
|
||||
if (ShouldDraw())
|
||||
{
|
||||
Draw();
|
||||
|
@ -1141,9 +1141,6 @@ namespace OpenRCT2
|
|||
|
||||
Tick();
|
||||
|
||||
// Always run this at a fixed rate, Update can cause multiple ticks if the game is speed up.
|
||||
WindowUpdateAll();
|
||||
|
||||
_ticksAccumulator -= GAME_UPDATE_TIME_MS;
|
||||
|
||||
// Get the next position of each sprite
|
||||
|
@ -1151,6 +1148,9 @@ namespace OpenRCT2
|
|||
tweener.PostTick();
|
||||
}
|
||||
|
||||
ContextHandleInput();
|
||||
WindowUpdateAll();
|
||||
|
||||
if (shouldDraw)
|
||||
{
|
||||
const float alpha = std::min(_ticksAccumulator / GAME_UPDATE_TIME_MS, 1.0f);
|
||||
|
|
|
@ -230,8 +230,6 @@ void GameState::Tick()
|
|||
gWindowMapFlashingFlags &= ~MapFlashingFlags::StaffListOpen;
|
||||
|
||||
ContextUpdateMapTooltip();
|
||||
|
||||
ContextHandleInput();
|
||||
}
|
||||
|
||||
// Always perform autosave check, even when paused
|
||||
|
|
Loading…
Reference in New Issue