mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-19 00:15:30 +00:00
STARK: Use the mouse cursor as a hitbox when testing small world items
Fixes #1506.
This commit is contained in:
parent
c5185ee753
commit
4edb8a7add
@ -127,7 +127,7 @@ bool RenderEntry::compare(const RenderEntry *x, const RenderEntry *y) {
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderEntry::containsPoint(const Common::Point &position, Common::Point &relativePosition) const {
|
||||
bool RenderEntry::containsPoint(const Common::Point &position, Common::Point &relativePosition, const Common::Rect &cursorRect) const {
|
||||
if (!_visual || !_clickable) {
|
||||
return false;
|
||||
}
|
||||
@ -143,6 +143,16 @@ bool RenderEntry::containsPoint(const Common::Point &position, Common::Point &re
|
||||
if (imageRect.contains(position) && image->isPointSolid(relativePosition)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (imageRect.width() < 32 && imageRect.height() < 32
|
||||
&& !cursorRect.isEmpty() && cursorRect.intersects(imageRect)) {
|
||||
// If the item in the scene is way smaller than the cursor,
|
||||
// use the whole cursor as a hit rectangle.
|
||||
relativePosition.x = 1 - image->getHotspot().x;
|
||||
relativePosition.y = 1 - image->getHotspot().y;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
VisualSmacker *smacker = _visual->get<VisualSmacker>();
|
||||
|
@ -95,9 +95,10 @@ public:
|
||||
*
|
||||
* @param position game window coordinates to test
|
||||
* @param relativePosition successful hit item relative coordinates
|
||||
* @param cursorRect cursor rectangle to be used to test small world items
|
||||
* @return successful hit
|
||||
*/
|
||||
bool containsPoint(const Common::Point &position, Common::Point &relativePosition) const;
|
||||
bool containsPoint(const Common::Point &position, Common::Point &relativePosition, const Common::Rect &cursorRect) const;
|
||||
|
||||
/** Mouse picking test for 3D items */
|
||||
bool intersectRay(const Math::Ray &ray) const;
|
||||
|
@ -159,4 +159,19 @@ void Cursor::setMouseHint(const Common::String &hint) {
|
||||
}
|
||||
}
|
||||
|
||||
Common::Rect Cursor::getHotRectangle() const {
|
||||
if (!_cursorImage) {
|
||||
return Common::Rect();
|
||||
} else {
|
||||
Common::Point hotSpot = _cursorImage->getHotspot();
|
||||
|
||||
Common::Rect hotRectangle;
|
||||
hotRectangle.setWidth(_cursorImage->getWidth());
|
||||
hotRectangle.setHeight(_cursorImage->getHeight());
|
||||
hotRectangle.translate(-hotSpot.x, -hotSpot.y);
|
||||
|
||||
return hotRectangle;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Stark
|
||||
|
@ -57,6 +57,9 @@ public:
|
||||
|
||||
Common::Point getMousePosition(bool unscaled = false) const;
|
||||
|
||||
/** Rectangle at the mouse position to consider to hit test small world items */
|
||||
Common::Rect getHotRectangle() const;
|
||||
|
||||
enum CursorType {
|
||||
kImage = -1,
|
||||
kDefault = 0,
|
||||
|
@ -176,7 +176,7 @@ bool StaticLocationWidget::isMouseInside(const Common::Point &mousePos) const {
|
||||
if (!_renderEntry) return false;
|
||||
|
||||
Common::Point relativePosition;
|
||||
return _renderEntry->containsPoint(mousePos, relativePosition);
|
||||
return _renderEntry->containsPoint(mousePos, relativePosition, Common::Rect());
|
||||
}
|
||||
|
||||
void StaticLocationWidget::onClick() {
|
||||
|
@ -220,17 +220,23 @@ void GameWindow::onDoubleClick(const Common::Point &pos) {
|
||||
}
|
||||
}
|
||||
|
||||
void GameWindow::checkObjectAtPos(Common::Point pos, int16 selectedInventoryItem, int16 &singlePossibleAction, bool &isDefaultAction) {
|
||||
void GameWindow::checkObjectAtPos(const Common::Point &pos, int16 selectedInventoryItem, int16 &singlePossibleAction, bool &isDefaultAction) {
|
||||
_objectUnderCursor = nullptr;
|
||||
singlePossibleAction = -1;
|
||||
isDefaultAction = false;
|
||||
|
||||
Math::Ray ray = StarkScene->makeRayFromMouse(_cursor->getMousePosition(true));
|
||||
|
||||
Common::Rect cursorRect;
|
||||
if (selectedInventoryItem != -1) {
|
||||
cursorRect = _cursor->getHotRectangle();
|
||||
cursorRect.translate(pos.x, pos.y);
|
||||
}
|
||||
|
||||
// Render entries are sorted from the farthest to the camera to the nearest
|
||||
// Loop in reverse order
|
||||
for (int i = _renderEntries.size() - 1; i >= 0; i--) {
|
||||
if (_renderEntries[i]->containsPoint(pos, _objectRelativePosition)
|
||||
if (_renderEntries[i]->containsPoint(pos, _objectRelativePosition, cursorRect)
|
||||
|| _renderEntries[i]->intersectRay(ray)) {
|
||||
_objectUnderCursor = _renderEntries[i]->getOwner();
|
||||
break;
|
||||
|
@ -58,7 +58,7 @@ protected:
|
||||
void onDoubleClick(const Common::Point &pos) override;
|
||||
void onRender() override;
|
||||
|
||||
void checkObjectAtPos(Common::Point pos, int16 selectedInventoryItem, int16 &singlePossibleAction, bool &isDefaultAction);
|
||||
void checkObjectAtPos(const Common::Point &pos, int16 selectedInventoryItem, int16 &singlePossibleAction, bool &isDefaultAction);
|
||||
|
||||
ActionMenu *_actionMenu;
|
||||
InventoryWindow *_inventory;
|
||||
|
Loading…
x
Reference in New Issue
Block a user