diff --git a/src/client/gui/Screen.cpp b/src/client/gui/Screen.cpp index cc6c0c7..a888cd6 100755 --- a/src/client/gui/Screen.cpp +++ b/src/client/gui/Screen.cpp @@ -78,6 +78,14 @@ void Screen::updateEvents() void Screen::mouseEvent() { const MouseAction& e = Mouse::getEvent(); + // forward wheel events to subclasses + if (e.action == MouseAction::ACTION_WHEEL) { + int xm = e.x * width / minecraft->width; + int ym = e.y * height / minecraft->height - 1; + mouseWheel(e.dx, e.dy, xm, ym); + return; + } + if (!e.isButton()) return; diff --git a/src/client/gui/Screen.h b/src/client/gui/Screen.h index eebe588..3c8c5a9 100755 --- a/src/client/gui/Screen.h +++ b/src/client/gui/Screen.h @@ -57,6 +57,9 @@ protected: virtual void mouseClicked(int x, int y, int buttonNum); virtual void mouseReleased(int x, int y, int buttonNum); + // mouse wheel movement (dx/dy are wheel deltas, xm/ym are GUI coords) + virtual void mouseWheel(int dx, int dy, int xm, int ym) {} + virtual void keyPressed(int eventKey); virtual void keyboardNewChar(char inputChar) {} public: diff --git a/src/client/gui/components/ScrollingPane.cpp b/src/client/gui/components/ScrollingPane.cpp index 78c0187..6ee7744 100755 --- a/src/client/gui/components/ScrollingPane.cpp +++ b/src/client/gui/components/ScrollingPane.cpp @@ -548,6 +548,14 @@ void ScrollingPane::stepThroughDecelerationAnimation(bool noAnimation) { } } +void ScrollingPane::scrollBy(float dx, float dy) { + // adjust the translation offsets fpx/fpy by the requested amount + float nfpx = fpx + dx; + float nfpy = fpy + dy; + // convert back to content offset (fpx = -contentOffset.x) + setContentOffset(Vec3(-nfpx, -nfpy, 0)); +} + void ScrollingPane::setContentOffset(float x, float y) { this->setContentOffsetWithAnimation(Vec3(x, y, 0), false); } diff --git a/src/client/gui/components/ScrollingPane.h b/src/client/gui/components/ScrollingPane.h index ff31e7c..0a2c321 100755 --- a/src/client/gui/components/ScrollingPane.h +++ b/src/client/gui/components/ScrollingPane.h @@ -51,6 +51,10 @@ public: void tick(); void render(int xm, int ym, float alpha); + // scroll the content by the given amount (dx horizontal, dy vertical) + // positive values move content downward/rightward + void scrollBy(float dx, float dy); + bool getGridItemFor_slow(int itemIndex, GridItem& out); void setSelected(int id, bool selected); diff --git a/src/client/gui/screens/IngameBlockSelectionScreen.cpp b/src/client/gui/screens/IngameBlockSelectionScreen.cpp index bc6fc64..1ab5b77 100755 --- a/src/client/gui/screens/IngameBlockSelectionScreen.cpp +++ b/src/client/gui/screens/IngameBlockSelectionScreen.cpp @@ -202,6 +202,25 @@ void IngameBlockSelectionScreen::keyPressed(int eventKey) #endif } +//------------------------------------------------------------------------------ +// wheel support for creative inventory; scroll moves selection vertically +void IngameBlockSelectionScreen::mouseWheel(int dx, int dy, int xm, int ym) +{ + if (dy == 0) return; + // just move selection up/down one row; desktop UI doesn't have a pane + int cols = InventoryCols; + int maxIndex = InventorySize - 1; + int idx = selectedItem; + if (dy > 0) { + // wheel up -> previous row + if (idx >= cols) idx -= cols; + } else { + // wheel down -> next row + if (idx + cols <= maxIndex) idx += cols; + } + selectedItem = idx; +} + int IngameBlockSelectionScreen::getSelectedSlot(int x, int y) { int left = width / 2 - InventoryCols * 10; diff --git a/src/client/gui/screens/IngameBlockSelectionScreen.h b/src/client/gui/screens/IngameBlockSelectionScreen.h index df8bacf..8c3c82b 100755 --- a/src/client/gui/screens/IngameBlockSelectionScreen.h +++ b/src/client/gui/screens/IngameBlockSelectionScreen.h @@ -23,6 +23,9 @@ protected: virtual void buttonClicked(Button* button); + // wheel input for creative inventory scrolling + virtual void mouseWheel(int dx, int dy, int xm, int ym) override; + virtual void keyPressed(int eventKey); private: void renderSlots(); diff --git a/src/client/gui/screens/SelectWorldScreen.cpp b/src/client/gui/screens/SelectWorldScreen.cpp index 8ec3f3c..9d8148b 100755 --- a/src/client/gui/screens/SelectWorldScreen.cpp +++ b/src/client/gui/screens/SelectWorldScreen.cpp @@ -356,7 +356,7 @@ void SelectWorldScreen::render( int xm, int ym, float a ) worldsList->setComponentSelected(bWorldView.selected); // #ifdef PLATFORM_DESKTOP - // We should add scrolling with mouse wheel but currently i dont know how to implement it + // desktop: render the list normally (mouse wheel handled separately below) if (_mouseHasBeenUp) worldsList->render(xm, ym, a); else { @@ -412,6 +412,28 @@ std::string SelectWorldScreen::getUniqueLevelName( const std::string& level ) bool SelectWorldScreen::isInGameScreen() { return true; } +void SelectWorldScreen::mouseWheel(int dx, int dy, int xm, int ym) +{ + if (!worldsList) + return; + if (dy == 0) + return; + int num = worldsList->getNumberOfItems(); + int idx = worldsList->selectedItem; + if (dy > 0) { + if (idx > 0) { + idx--; + worldsList->stepLeft(); + } + } else { + if (idx < num - 1) { + idx++; + worldsList->stepRight(); + } + } + worldsList->selectedItem = idx; +} + void SelectWorldScreen::keyPressed( int eventKey ) { if (bWorldView.selected) { diff --git a/src/client/gui/screens/SelectWorldScreen.h b/src/client/gui/screens/SelectWorldScreen.h index 8b45bb2..7dd3f18 100755 --- a/src/client/gui/screens/SelectWorldScreen.h +++ b/src/client/gui/screens/SelectWorldScreen.h @@ -90,6 +90,9 @@ public: void render(int xm, int ym, float a); + // mouse wheel scroll (new in desktop implementation) + virtual void mouseWheel(int dx, int dy, int xm, int ym); + bool isInGameScreen(); private: void loadLevelSource(); diff --git a/src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.cpp b/src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.cpp index db0b3ef..d88025d 100755 --- a/src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.cpp +++ b/src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.cpp @@ -153,6 +153,11 @@ int IngameBlockSelectionScreen::getSlotPosY(int slotY) { return height - 16 - 3 - 22 * 2 - 22 * slotY; } +int IngameBlockSelectionScreen::getSlotHeight() { + // same as non-touch implementation + return 22; +} + void IngameBlockSelectionScreen::mouseClicked(int x, int y, int buttonNum) { _pendingClose = _blockList->_clickArea->isInside((float)x, (float)y); if (!_pendingClose) @@ -166,6 +171,24 @@ void IngameBlockSelectionScreen::mouseReleased(int x, int y, int buttonNum) { super::mouseReleased(x, y, buttonNum); } +void IngameBlockSelectionScreen::mouseWheel(int dx, int dy, int xm, int ym) +{ + if (dy == 0) return; + if (_blockList) { + float amount = -dy * getSlotHeight(); + _blockList->scrollBy(0, amount); + } + int cols = InventoryColumns; + int maxIndex = InventorySize - 1; + int idx = selectedItem; + if (dy > 0) { + if (idx >= cols) idx -= cols; + } else { + if (idx + cols <= maxIndex) idx += cols; + } + selectedItem = idx; +} + bool IngameBlockSelectionScreen::addItem(const InventoryPane* pane, int itemId) { Inventory* inventory = minecraft->player->inventory; diff --git a/src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.h b/src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.h index 1bfa25b..ed05c0b 100755 --- a/src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.h +++ b/src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.h @@ -39,12 +39,16 @@ public: protected: virtual void mouseClicked(int x, int y, int buttonNum); virtual void mouseReleased(int x, int y, int buttonNum); + + // also support wheel scrolling + virtual void mouseWheel(int dx, int dy, int xm, int ym) override; private: void renderDemoOverlay(); //int getLinearSlotId(int x, int y); int getSlotPosX(int slotX); int getSlotPosY(int slotY); + int getSlotHeight(); private: int selectedItem; diff --git a/src/client/gui/screens/touch/TouchSelectWorldScreen.cpp b/src/client/gui/screens/touch/TouchSelectWorldScreen.cpp index e294a6d..93fc3f8 100755 --- a/src/client/gui/screens/touch/TouchSelectWorldScreen.cpp +++ b/src/client/gui/screens/touch/TouchSelectWorldScreen.cpp @@ -389,6 +389,26 @@ static char ILLEGAL_FILE_CHARACTERS[] = { '/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':' }; +void SelectWorldScreen::mouseWheel(int dx, int dy, int xm, int ym) +{ + if (!worldsList) return; + if (dy == 0) return; + int num = worldsList->getNumberOfItems(); + int idx = worldsList->selectedItem; + if (dy > 0) { + if (idx > 0) { + idx--; + worldsList->stepLeft(); + } + } else { + if (idx < num - 1) { + idx++; + worldsList->stepRight(); + } + } + worldsList->selectedItem = idx; +} + void SelectWorldScreen::tick() { #if 0 diff --git a/src/client/gui/screens/touch/TouchSelectWorldScreen.h b/src/client/gui/screens/touch/TouchSelectWorldScreen.h index 1f62139..f02f5e0 100755 --- a/src/client/gui/screens/touch/TouchSelectWorldScreen.h +++ b/src/client/gui/screens/touch/TouchSelectWorldScreen.h @@ -97,6 +97,9 @@ public: virtual void buttonClicked(Button* button); virtual void keyPressed(int eventKey); + // support for mouse wheel when desktop code uses touch variant + virtual void mouseWheel(int dx, int dy, int xm, int ym) override; + bool isInGameScreen(); private: void loadLevelSource(); diff --git a/src/main_win32.h b/src/main_win32.h index 931ae64..a008a07 100755 --- a/src/main_win32.h +++ b/src/main_win32.h @@ -113,6 +113,14 @@ LRESULT WINAPI windowProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) Multitouch::feed(0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0); break; } + case WM_MOUSEWHEEL: { + // wheel delta is multiples of WHEEL_DELTA (120); convert to +/-1 + int delta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA; + short x = GET_X_LPARAM(lParam); + short y = GET_Y_LPARAM(lParam); + Mouse::feed(MouseAction::ACTION_WHEEL, 0, x, y, 0, delta); + break; + } default: if (uMsg == WM_NCDESTROY) g_running = false; else {