-
-
Notifications
You must be signed in to change notification settings - Fork 400
Fix scroll cursor ("arrow") position on screen edges for software rendered cursor #9852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -217,40 +217,45 @@ namespace | |
return palette.data(); | ||
} | ||
|
||
// Updates `roi` to be only inside {0, 0, width, height} rectangle. | ||
// Returns false if `roi` is out of such rectangle. | ||
bool getActiveArea( fheroes2::Rect & roi, const int32_t width, const int32_t height ) | ||
{ | ||
if ( roi.width <= 0 || roi.height <= 0 || roi.x >= width || roi.y >= height ) | ||
if ( roi.width <= 0 || roi.height <= 0 || roi.x >= width || roi.y >= height ) { | ||
return false; | ||
} | ||
|
||
if ( roi.x < 0 ) { | ||
const int32_t offsetX = -roi.x; | ||
if ( offsetX >= roi.width ) | ||
if ( -roi.x >= roi.width ) { | ||
return false; | ||
} | ||
|
||
roi.width += roi.x; | ||
roi.x = 0; | ||
roi.width -= offsetX; | ||
} | ||
|
||
if ( roi.y < 0 ) { | ||
const int32_t offsetY = -roi.y; | ||
if ( offsetY >= roi.height ) | ||
if ( -roi.y >= roi.height ) { | ||
return false; | ||
} | ||
|
||
roi.height += roi.y; | ||
roi.y = 0; | ||
roi.height -= offsetY; | ||
} | ||
|
||
if ( roi.x + roi.width > width ) { | ||
const int32_t offsetX = roi.x + roi.width - width; | ||
if ( offsetX >= roi.width ) | ||
if ( const int32_t offsetX = roi.x + roi.width - width; offsetX > 0 ) { | ||
if ( offsetX >= roi.width ) { | ||
return false; | ||
} | ||
|
||
roi.width -= offsetX; | ||
} | ||
|
||
if ( roi.y + roi.height > height ) { | ||
const int32_t offsetY = roi.y + roi.height - height; | ||
if ( offsetY >= roi.height ) | ||
if ( const int32_t offsetY = roi.y + roi.height - height; offsetY > 0 ) { | ||
if ( offsetY >= roi.height ) { | ||
return false; | ||
} | ||
|
||
roi.height -= offsetY; | ||
} | ||
|
||
|
@@ -448,10 +453,12 @@ namespace | |
|
||
bool isVisible() const override | ||
{ | ||
if ( _emulation ) | ||
if ( _emulation ) { | ||
return fheroes2::Cursor::isVisible(); | ||
else | ||
} | ||
else { | ||
return fheroes2::Cursor::isVisible() && ( SDL_ShowCursor( SDL_QUERY ) == SDL_ENABLE ); | ||
} | ||
} | ||
|
||
void update( const fheroes2::Image & image, int32_t offsetX, int32_t offsetY ) override | ||
|
@@ -1319,9 +1326,6 @@ namespace fheroes2 | |
Display::Display() | ||
: _engine( RenderEngine::create() ) | ||
, _cursor( RenderCursor::create() ) | ||
, _preprocessing( nullptr ) | ||
, _postprocessing( nullptr ) | ||
, _renderSurface( nullptr ) | ||
{ | ||
_disableTransformLayer(); | ||
} | ||
|
@@ -1369,22 +1373,25 @@ namespace fheroes2 | |
void Display::render( const Rect & roi ) | ||
{ | ||
Rect temp( roi ); | ||
if ( !getActiveArea( temp, width(), height() ) ) | ||
if ( !getActiveArea( temp, width(), height() ) ) { | ||
return; | ||
|
||
getActiveArea( _prevRoi, width(), height() ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no need to call |
||
} | ||
|
||
if ( _cursor->isVisible() && _cursor->isSoftwareEmulation() && !_cursor->_image.empty() ) { | ||
const Sprite & cursorImage = _cursor->_image; | ||
const Sprite backup = Crop( *this, cursorImage.x(), cursorImage.y(), cursorImage.width(), cursorImage.height() ); | ||
Blit( cursorImage, *this, cursorImage.x(), cursorImage.y() ); | ||
|
||
if ( !backup.empty() ) { | ||
// ROI must include cursor's area as well, otherwise cursor won't be rendered. | ||
Rect cursorROI( cursorImage.x(), cursorImage.y(), cursorImage.width(), cursorImage.height() ); | ||
if ( getActiveArea( cursorROI, width(), height() ) ) { | ||
temp = getBoundaryRect( temp, cursorROI ); | ||
} | ||
Rect cursorROI( cursorImage.x(), cursorImage.y(), cursorImage.width(), cursorImage.height() ); | ||
|
||
if ( _cursor->_keepInScreenArea ) { | ||
cursorROI.x = std::clamp( cursorROI.x, 0, width() - cursorROI.width ); | ||
cursorROI.y = std::clamp( cursorROI.y, 0, height() - cursorROI.height ); | ||
} | ||
|
||
const Sprite backup = Crop( *this, cursorROI.x, cursorROI.y, cursorROI.width, cursorROI.height ); | ||
Blit( cursorImage, 0, 0, *this, cursorROI.x, cursorROI.y, cursorROI.width, cursorROI.height ); | ||
|
||
// ROI must include cursor's area as well, otherwise cursor won't be rendered. | ||
if ( !backup.empty() && getActiveArea( cursorROI, width(), height() ) ) { | ||
temp = getBoundaryRect( temp, cursorROI ); | ||
} | ||
|
||
// Previous position of cursor must be updated as well to avoid ghost effect. | ||
|
@@ -1404,12 +1411,13 @@ namespace fheroes2 | |
} | ||
} | ||
|
||
_prevRoi = temp; | ||
_prevRoi = std::move( temp ); | ||
Districh-ru marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
void Display::updateNextRenderRoi( const Rect & roi ) | ||
{ | ||
_prevRoi = getBoundaryRect( _prevRoi, roi ); | ||
getActiveArea( _prevRoi, width(), height() ); | ||
} | ||
|
||
void Display::_renderFrame( const Rect & roi ) const | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
/*************************************************************************** | ||
* fheroes2: https://github.com/ihhub/fheroes2 * | ||
* Copyright (C) 2019 - 2024 * | ||
* Copyright (C) 2019 - 2025 * | ||
* * | ||
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * | ||
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> * | ||
|
@@ -59,7 +59,11 @@ void Cursor::SetThemes( const int theme, const bool force /* = false */ ) | |
} | ||
const fheroes2::Sprite & spr = fheroes2::AGG::GetICN( icnID, 0xFF & theme ); | ||
SetOffset( theme, { ( spr.width() - spr.x() ) / 2, ( spr.height() - spr.y() ) / 2 } ); | ||
fheroes2::cursor().update( spr, -_offset.x, -_offset.y ); | ||
|
||
fheroes2::Cursor & cursor = fheroes2::cursor(); | ||
cursor.update( spr, -_offset.x, -_offset.y ); | ||
// Force the scroll cursor to stay in screen boundaries. | ||
cursor.keepInScreenArea( theme >= SCROLL_TOP && theme <= SCROLL_TOPLEFT ); | ||
|
||
// Apply new offset. | ||
const fheroes2::Point & currentPos = LocalEvent::Get().getMouseCursorPos(); | ||
|
@@ -70,7 +74,9 @@ void Cursor::setCustomImage( const fheroes2::Image & image, const fheroes2::Poin | |
{ | ||
_theme = NONE; | ||
|
||
fheroes2::cursor().update( image, -offset.x, -offset.y ); | ||
fheroes2::Cursor & cursor = fheroes2::cursor(); | ||
cursor.update( image, -offset.x, -offset.y ); | ||
cursor.keepInScreenArea( false ); | ||
|
||
// Immediately apply new mouse offset. | ||
const fheroes2::Point & currentPos = LocalEvent::Get().getMouseCursorPos(); | ||
|
Uh oh!
There was an error while loading. Please reload this page.