Added scroll with wheel on PC and touch scroll on Android/IOS
This commit is contained in:
@@ -35,6 +35,17 @@ void GuiElementContainer::removeChild( GuiElement* element ) {
|
|||||||
children.erase(it);
|
children.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GuiElementContainer::containsPointInChildren(int x, int y) const {
|
||||||
|
for (std::vector<GuiElement*>::const_iterator it = children.begin(); it != children.end(); ++it) {
|
||||||
|
GuiElement* child = *it;
|
||||||
|
if (child == NULL || !child->visible) continue;
|
||||||
|
if (child->pointInside(x, y)) return true;
|
||||||
|
const GuiElementContainer* container = dynamic_cast<const GuiElementContainer*>(child);
|
||||||
|
if (container != NULL && container->containsPointInChildren(x, y)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void GuiElementContainer::tick( Minecraft* minecraft ) {
|
void GuiElementContainer::tick( Minecraft* minecraft ) {
|
||||||
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
|
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
|
||||||
(*it)->tick(minecraft);
|
(*it)->tick(minecraft);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public:
|
|||||||
virtual void setupPositions();
|
virtual void setupPositions();
|
||||||
virtual void addChild(GuiElement* element);
|
virtual void addChild(GuiElement* element);
|
||||||
virtual void removeChild(GuiElement* element);
|
virtual void removeChild(GuiElement* element);
|
||||||
|
bool containsPointInChildren(int x, int y) const;
|
||||||
|
|
||||||
virtual void tick( Minecraft* minecraft );
|
virtual void tick( Minecraft* minecraft );
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,34 @@
|
|||||||
#include "../../../locale/I18n.h"
|
#include "../../../locale/I18n.h"
|
||||||
#include "TextOption.h"
|
#include "TextOption.h"
|
||||||
#include "KeyOption.h"
|
#include "KeyOption.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include "../Screen.h"
|
||||||
|
#include "../../../platform/input/Mouse.h"
|
||||||
|
#include "../../../util/Mth.h"
|
||||||
|
|
||||||
OptionsGroup::OptionsGroup( std::string labelID ) {
|
OptionsGroup::OptionsGroup( std::string labelID )
|
||||||
|
: contentHeight(0),
|
||||||
|
scrollOffsetY(0.0f),
|
||||||
|
maxScrollOffsetY(0.0f),
|
||||||
|
trackingScrollGesture(false),
|
||||||
|
scrollingGesture(false),
|
||||||
|
touchDispatched(false),
|
||||||
|
dragStartX(0),
|
||||||
|
dragStartY(0),
|
||||||
|
lastDragY(0),
|
||||||
|
touchStartX(0),
|
||||||
|
touchStartY(0) {
|
||||||
label = I18n::get(labelID);
|
label = I18n::get(labelID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionsGroup::setupPositions() {
|
void OptionsGroup::setupPositions() {
|
||||||
|
const int labelHeight = 18;
|
||||||
|
const float requestedScroll = scrollOffsetY;
|
||||||
|
const int scrollOffset = (int)requestedScroll;
|
||||||
|
int curY = y + labelHeight - scrollOffset;
|
||||||
|
const int contentStartY = y + labelHeight;
|
||||||
|
|
||||||
// First we write the header and then we add the items
|
// First we write the header and then we add the items
|
||||||
int curY = y + 18;
|
|
||||||
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
|
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
|
||||||
(*it)->width = width - 5;
|
(*it)->width = width - 5;
|
||||||
|
|
||||||
@@ -22,7 +42,13 @@ void OptionsGroup::setupPositions() {
|
|||||||
(*it)->setupPositions();
|
(*it)->setupPositions();
|
||||||
curY += (*it)->height + 3;
|
curY += (*it)->height + 3;
|
||||||
}
|
}
|
||||||
height = curY;
|
contentHeight = std::max(0, curY - contentStartY + scrollOffset);
|
||||||
|
maxScrollOffsetY = std::max(0, contentHeight - (height - labelHeight));
|
||||||
|
const float clampedScroll = Mth::clamp(requestedScroll, 0.0f, maxScrollOffsetY);
|
||||||
|
if (clampedScroll != requestedScroll) {
|
||||||
|
scrollOffsetY = clampedScroll;
|
||||||
|
setupPositions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionsGroup::render( Minecraft* minecraft, int xm, int ym ) {
|
void OptionsGroup::render( Minecraft* minecraft, int xm, int ym ) {
|
||||||
@@ -34,6 +60,82 @@ void OptionsGroup::render( Minecraft* minecraft, int xm, int ym ) {
|
|||||||
super::render(minecraft, xm, ym);
|
super::render(minecraft, xm, ym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OptionsGroup::tick(Minecraft* minecraft) {
|
||||||
|
int xm = Mouse::getX();
|
||||||
|
int ym = Mouse::getY();
|
||||||
|
if (minecraft->screen != NULL) {
|
||||||
|
minecraft->screen->toGUICoordinate(xm, ym);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool leftDown = Mouse::isButtonDown(MouseAction::ACTION_LEFT);
|
||||||
|
|
||||||
|
if (trackingScrollGesture && leftDown) {
|
||||||
|
int dy = ym - lastDragY;
|
||||||
|
int dx = xm - dragStartX;
|
||||||
|
if (!scrollingGesture) {
|
||||||
|
int totalDx = xm - dragStartX;
|
||||||
|
int totalDy = ym - dragStartY;
|
||||||
|
if (std::abs(totalDx) >= ScrollStartThreshold || std::abs(totalDy) >= ScrollStartThreshold) {
|
||||||
|
if (std::abs(totalDy) >= std::abs(totalDx)) {
|
||||||
|
scrollingGesture = true;
|
||||||
|
} else if (!touchDispatched) {
|
||||||
|
super::mouseClicked(minecraft, touchStartX, touchStartY, MouseAction::ACTION_LEFT);
|
||||||
|
touchDispatched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scrollingGesture && dy != 0) {
|
||||||
|
scrollByPixels((float)dy);
|
||||||
|
}
|
||||||
|
lastDragY = ym;
|
||||||
|
}
|
||||||
|
super::tick(minecraft);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsGroup::mouseClicked(Minecraft* minecraft, int x, int y, int buttonNum) {
|
||||||
|
trackingScrollGesture = false;
|
||||||
|
scrollingGesture = false;
|
||||||
|
touchDispatched = false;
|
||||||
|
|
||||||
|
if (buttonNum == MouseAction::ACTION_LEFT && pointInside(x, y)) {
|
||||||
|
trackingScrollGesture = true;
|
||||||
|
dragStartX = x;
|
||||||
|
dragStartY = y;
|
||||||
|
lastDragY = y;
|
||||||
|
touchStartX = x;
|
||||||
|
touchStartY = y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super::mouseClicked(minecraft, x, y, buttonNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsGroup::mouseReleased(Minecraft* minecraft, int x, int y, int buttonNum) {
|
||||||
|
bool wasScrolling = scrollingGesture;
|
||||||
|
bool wasTracking = trackingScrollGesture;
|
||||||
|
trackingScrollGesture = false;
|
||||||
|
scrollingGesture = false;
|
||||||
|
if (buttonNum == MouseAction::ACTION_LEFT && wasTracking && !touchDispatched && pointInside(touchStartX, touchStartY)) {
|
||||||
|
super::mouseClicked(minecraft, touchStartX, touchStartY, buttonNum);
|
||||||
|
touchDispatched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasScrolling) {
|
||||||
|
super::mouseReleased(minecraft, x, y, buttonNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsGroup::scrollByPixels(float deltaY) {
|
||||||
|
if (deltaY == 0.0f || maxScrollOffsetY <= 0.0f) return;
|
||||||
|
|
||||||
|
scrollOffsetY = Mth::clamp(scrollOffsetY - deltaY, 0.0f, maxScrollOffsetY);
|
||||||
|
setupPositions();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OptionsGroup::isScrollingGestureActive() const {
|
||||||
|
return trackingScrollGesture || scrollingGesture;
|
||||||
|
}
|
||||||
|
|
||||||
OptionsGroup& OptionsGroup::addOptionItem(OptionId optId, Minecraft* minecraft ) {
|
OptionsGroup& OptionsGroup::addOptionItem(OptionId optId, Minecraft* minecraft ) {
|
||||||
auto option = minecraft->options.getOpt(optId);
|
auto option = minecraft->options.getOpt(optId);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ public:
|
|||||||
OptionsGroup(std::string labelID);
|
OptionsGroup(std::string labelID);
|
||||||
virtual void setupPositions();
|
virtual void setupPositions();
|
||||||
virtual void render(Minecraft* minecraft, int xm, int ym);
|
virtual void render(Minecraft* minecraft, int xm, int ym);
|
||||||
|
virtual void tick(Minecraft* minecraft);
|
||||||
|
virtual void mouseClicked(Minecraft* minecraft, int x, int y, int buttonNum);
|
||||||
|
virtual void mouseReleased(Minecraft* minecraft, int x, int y, int buttonNum);
|
||||||
OptionsGroup& addOptionItem(OptionId optId, Minecraft* minecraft);
|
OptionsGroup& addOptionItem(OptionId optId, Minecraft* minecraft);
|
||||||
|
void scrollByPixels(float deltaY);
|
||||||
|
bool isScrollingGestureActive() const;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void createToggle(OptionId optId, Minecraft* minecraft);
|
void createToggle(OptionId optId, Minecraft* minecraft);
|
||||||
@@ -27,6 +32,18 @@ protected:
|
|||||||
void createKey(OptionId optId, Minecraft* minecraft);
|
void createKey(OptionId optId, Minecraft* minecraft);
|
||||||
|
|
||||||
std::string label;
|
std::string label;
|
||||||
|
int contentHeight;
|
||||||
|
float scrollOffsetY;
|
||||||
|
float maxScrollOffsetY;
|
||||||
|
bool trackingScrollGesture;
|
||||||
|
bool scrollingGesture;
|
||||||
|
bool touchDispatched;
|
||||||
|
int dragStartX;
|
||||||
|
int dragStartY;
|
||||||
|
int lastDragY;
|
||||||
|
int touchStartX;
|
||||||
|
int touchStartY;
|
||||||
|
static const int ScrollStartThreshold = 5;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__OptionsGroup_H__*/
|
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__OptionsGroup_H__*/
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ void OptionsScreen::setupPositions() {
|
|||||||
(*it)->x = categoryButtons[0]->width;
|
(*it)->x = categoryButtons[0]->width;
|
||||||
(*it)->y = bHeader->height;
|
(*it)->y = bHeader->height;
|
||||||
(*it)->width = width - categoryButtons[0]->width;
|
(*it)->width = width - categoryButtons[0]->width;
|
||||||
|
(*it)->height = height - bHeader->height;
|
||||||
|
|
||||||
(*it)->setupPositions();
|
(*it)->setupPositions();
|
||||||
}
|
}
|
||||||
@@ -253,6 +254,12 @@ void OptionsScreen::mouseReleased(int x, int y, int buttonNum) {
|
|||||||
super::mouseReleased(x, y, buttonNum);
|
super::mouseReleased(x, y, buttonNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OptionsScreen::mouseWheel(int dx, int dy, int xm, int ym) {
|
||||||
|
if (currentOptionsGroup != NULL && currentOptionsGroup->pointInside(xm, ym) && dy != 0) {
|
||||||
|
currentOptionsGroup->scrollByPixels((float)dy * 18.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OptionsScreen::keyPressed(int eventKey) {
|
void OptionsScreen::keyPressed(int eventKey) {
|
||||||
if (currentOptionsGroup != NULL)
|
if (currentOptionsGroup != NULL)
|
||||||
currentOptionsGroup->keyPressed(minecraft, eventKey);
|
currentOptionsGroup->keyPressed(minecraft, eventKey);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public:
|
|||||||
|
|
||||||
virtual void mouseClicked(int x, int y, int buttonNum);
|
virtual void mouseClicked(int x, int y, int buttonNum);
|
||||||
virtual void mouseReleased(int x, int y, int buttonNum);
|
virtual void mouseReleased(int x, int y, int buttonNum);
|
||||||
|
virtual void mouseWheel(int dx, int dy, int xm, int ym);
|
||||||
virtual void keyPressed(int eventKey);
|
virtual void keyPressed(int eventKey);
|
||||||
virtual void charPressed(char inputChar);
|
virtual void charPressed(char inputChar);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user