From 03268009406794133ef8faee1ae31e483e6512c1 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 28 Apr 2024 13:15:41 +0200 Subject: [PATCH] fix broken scrolling in mod selector in vertical mode --- Aquaria/ModSelector.cpp | 43 +++++++++++++++++++++++++---------------- Aquaria/ModSelector.h | 2 ++ BBGE/Core.cpp | 20 ++++++++----------- BBGE/Core.h | 3 +++ BBGE/RenderObject.cpp | 35 +++++++++++++++++++++++++++------ BBGE/RenderObject.h | 4 +++- BBGE/SkeletalSprite.cpp | 2 +- 7 files changed, 72 insertions(+), 37 deletions(-) diff --git a/Aquaria/ModSelector.cpp b/Aquaria/ModSelector.cpp index 1b8a793..faa1dc0 100644 --- a/Aquaria/ModSelector.cpp +++ b/Aquaria/ModSelector.cpp @@ -100,6 +100,13 @@ void ModSelectorScreen::move(int ud, bool instant /* = false */) } } +bool ModSelectorScreen::isMoving() const +{ + const IconGridPanel *grid = panels[currentPanel]; + const InterpolatedVector& v = grid->position; + return v.isInterpolating(); +} + void ModSelectorScreen::onUpdate(float dt) { Quad::onUpdate(dt); @@ -431,23 +438,6 @@ void BasicIcon::onUpdate(float dt) { AquariaMenuItem::onUpdate(dt); - // Autoscroll if selecting icon outside of screen - if(hasFocus() && dsq->modSelectorScr && !_isRecCall) - { - Vector pos = getRealPosition(); - if(pos.y < 20 || pos.y > 580) - { - if(pos.y < 300) - dsq->modSelectorScr->move(5, true); - else - dsq->modSelectorScr->move(-5, true); - _isRecCall = true; - core->run(FRAME_TIME); // HACK: this is necessary to correctly position the mouse on the object after moving the panel - _isRecCall = false; - setFocus(true); // re-position mouse - } - } - if(!quad) return; @@ -506,6 +496,25 @@ ModIcon::ModIcon(): SubtitleIcon(), modId(-1) { } +void ModIcon::onUpdate(float dt) +{ + SubtitleIcon::onUpdate(dt); + + // Autoscroll if selecting icon outside of screen + if(hasFocus() && dsq->modSelectorScr && !_isRecCall && !dsq->modSelectorScr->isMoving() && !isCenterOnScreenWithMargin(Vector(0, 200))) + { + const Vector pos = getRealPosition(); + if(pos.y < 300) + dsq->modSelectorScr->move(5); + else + dsq->modSelectorScr->move(-5); + _isRecCall = true; + core->run(FRAME_TIME); // HACK: this is necessary to correctly position the mouse on the object after moving the panel + _isRecCall = false; + setFocus(true); // re-position mouse + } +} + void ModIcon::onClick() { dsq->sound->playSfx("click"); diff --git a/Aquaria/ModSelector.h b/Aquaria/ModSelector.h index baed439..b5bbc68 100644 --- a/Aquaria/ModSelector.h +++ b/Aquaria/ModSelector.h @@ -62,6 +62,7 @@ public: ModType modType; protected: + virtual void onUpdate(float dt); virtual void onClick(); }; @@ -158,6 +159,7 @@ public: void moveUp(); void moveDown(); void move(int ud, bool instant = false); + bool isMoving() const; std::vector panels; MenuIcon *globeIcon, *modsIcon; diff --git a/BBGE/Core.cpp b/BBGE/Core.cpp index 1155d79..74f3e8c 100644 --- a/BBGE/Core.cpp +++ b/BBGE/Core.cpp @@ -647,26 +647,22 @@ Vector Core::getWindowPosition(const Vector &worldpos) const bool Core::isRectInWindowCoordsPartiallyOnScreen(const Vector& center, const Vector& wh) const { - const float xo = getVirtualOffX(); - const float yo = getVirtualOffY(); - const Vector topleft(-xo, -yo); - const Vector bottomright(800 + xo, 600 + yo); - const Vector half = wh * 0.5f; - const Vector a = topleft - half; - const Vector b = bottomright + half; - return center.x >= a.x && center.x <= b.x - && center.y >= a.y && center.y <= b.y; + return isPointInWindowCoordsOnScreenWithMargin(center, wh * -0.5f); } bool Core::isRectInWindowCoordsFullyOnScreen(const Vector& center, const Vector& wh) const +{ + return isPointInWindowCoordsOnScreenWithMargin(center, wh * 0.5f); +} + +bool Core::isPointInWindowCoordsOnScreenWithMargin(const Vector& center, const Vector& margin) const { const float xo = getVirtualOffX(); const float yo = getVirtualOffY(); const Vector topleft(-xo, -yo); const Vector bottomright(800 + xo, 600 + yo); - const Vector half = wh * 0.5f; - const Vector a = topleft + half; - const Vector b = bottomright - half; + const Vector a = topleft + margin; + const Vector b = bottomright - margin; return center.x >= a.x && center.x <= b.x && center.y >= a.y && center.y <= b.y; } diff --git a/BBGE/Core.h b/BBGE/Core.h index a66a74e..d242641 100644 --- a/BBGE/Core.h +++ b/BBGE/Core.h @@ -282,6 +282,9 @@ public: bool isRectInWindowCoordsPartiallyOnScreen(const Vector& center, const Vector& wh) const; bool isRectInWindowCoordsFullyOnScreen(const Vector& center, const Vector& wh) const; + // positive margin makes the screen area narrower, negative margin makes it wider (accept slightly outside) + bool isPointInWindowCoordsOnScreenWithMargin(const Vector& center, const Vector& margin) const; + Vector screenCenter; diff --git a/BBGE/RenderObject.cpp b/BBGE/RenderObject.cpp index 112d3ac..89074a8 100644 --- a/BBGE/RenderObject.cpp +++ b/BBGE/RenderObject.cpp @@ -117,15 +117,29 @@ Vector RenderObject::getWorldPosition() const return getWorldCollidePosition(); } -RenderObject* RenderObject::getTopParent() const +RenderObject* RenderObject::getTopParent() { - RenderObject *p = parent; - RenderObject *lastp=0; - while (p) + RenderObject *p = this; + RenderObject *lastp; + do { lastp = p; p = p->parent; } + while(p); + return lastp; +} + +const RenderObject* RenderObject::getTopParent() const +{ + const RenderObject *p = this; + const RenderObject *lastp; + do + { + lastp = p; + p = p->parent; + } + while(p); return lastp; } @@ -942,14 +956,23 @@ Vector RenderObject::getFollowCameraPosition(const Vector& v) const bool RenderObject::isRectPartiallyOnScreen() const { - Vector p = core->getWindowPosition(getFollowCameraPosition(position + offset)); + Vector p = getTopParent()->getFollowCameraPosition(getWorldPosition()); + p = core->getWindowPosition(p); Vector sz = Vector(width, height) * getRealScale(); return core->isRectInWindowCoordsPartiallyOnScreen(p, sz); } bool RenderObject::isRectFullyOnScreen() const { - Vector p = core->getWindowPosition(getFollowCameraPosition(position + offset)); + Vector p = getTopParent()->getFollowCameraPosition(getWorldPosition()); + p = core->getWindowPosition(p); Vector sz = Vector(width, height) * getRealScale(); return core->isRectInWindowCoordsFullyOnScreen(p, sz); } + +bool RenderObject::isCenterOnScreenWithMargin(const Vector& margin) const +{ + Vector p = getTopParent()->getFollowCameraPosition(getWorldPosition()); + p = core->getWindowPosition(p); + return core->isPointInWindowCoordsOnScreenWithMargin(p, margin); +} diff --git a/BBGE/RenderObject.h b/BBGE/RenderObject.h index 2a730b1..267e7ac 100644 --- a/BBGE/RenderObject.h +++ b/BBGE/RenderObject.h @@ -179,6 +179,7 @@ public: inline bool isOnScreen() const; bool isRectPartiallyOnScreen() const; bool isRectFullyOnScreen() const; + bool isCenterOnScreenWithMargin(const Vector& margin) const; bool isCoordinateInRadius(const Vector &pos, float r) const; @@ -190,7 +191,8 @@ public: Vector getWorldPosition() const; Vector getWorldCollidePosition(const Vector &vec=Vector(0,0,0)) const; - RenderObject *getTopParent() const; + RenderObject *getTopParent(); + const RenderObject *getTopParent() const; virtual void onAnimationKeyPassed(int key){} diff --git a/BBGE/SkeletalSprite.cpp b/BBGE/SkeletalSprite.cpp index cd5e958..d6ada54 100644 --- a/BBGE/SkeletalSprite.cpp +++ b/BBGE/SkeletalSprite.cpp @@ -283,7 +283,7 @@ void Bone::renderCollision(const RenderState& rs) const glTranslatef(collide.x, collide.y, 0); - RenderObject *parent = this->getTopParent(); + const RenderObject *parent = this->getTopParent(); if (parent) drawCircle(collideRadius*parent->scale.x, 45); glTranslatef(-collide.x, -collide.y, 0);