From 90b5c2d51adadf39f27b6da2f5f5da51fef362b4 Mon Sep 17 00:00:00 2001 From: MrTheShy <49885496+MrTheShy@users.noreply.github.com> Date: Fri, 6 Mar 2026 04:43:56 +0100 Subject: [PATCH] Add mouse click support to CraftingMenu (tab switching, slot selection, craft) The crafting screen's horizontal recipe slots and category tabs are custom-drawn via Iggy callbacks rather than regular Flash buttons, so the standard mouse hover system can't interact with them. This adds handleMouseClick to derive clickable regions from the H slot positions cached during customDraw. Tab clicking: tab hitboxes are computed relative to the H slot row since the Vita TouchPanel overlays (full-screen invisible rectangles) aren't suitable for direct hit-testing on Win64. The Y bounds were tuned empirically to match the SWF tab icon positions. Clicking a tab runs the same switch logic as LB/RB: hide old highlight, update group index, reset slot indices, recalculate recipes, and refresh the display. H slot clicking: clicking a different recipe slot selects it (updating V slots, highlight, and re-showing the previous slot). Clicking the already-selected slot crafts the item by dispatching ACTION_MENU_A through handleKeyDown, reusing the existing crafting path. Empty slots (iCount == 0) are ignored. All mouse clicks on the scene are consumed (return true) to prevent misses from falling through as ACTION_MENU_A and accidentally triggering a craft. This only suppresses mouse-originated A presses via m_mouseClickConsumedByScene; keyboard and controller A remain fully functional. Also enables GetMainPanel for Win64 (was Vita-only) so the mouse hover system can filter controls by active panel, same as other tabbed menus. --- .../Common/UI/UIScene_CraftingMenu.cpp | 82 +++++++++++++++---- .../Common/UI/UIScene_CraftingMenu.h | 6 +- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp index 369d4c51d..2d1b4302f 100644 --- a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp @@ -262,12 +262,14 @@ wstring UIScene_CraftingMenu::getMoviePath() } } -#ifdef __PSVITA__ +#if defined(__PSVITA__) || defined(_WINDOWS64) UIControl* UIScene_CraftingMenu::GetMainPanel() { return &m_controlMainPanel; } +#endif +#ifdef __PSVITA__ void UIScene_CraftingMenu::handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased) { // perform action on release @@ -394,33 +396,79 @@ void UIScene_CraftingMenu::handleTimerComplete(int id) #ifdef _WINDOWS64 bool UIScene_CraftingMenu::handleMouseClick(F32 x, F32 y) { - if (!m_hSlotBoundsValid) + if (!m_hSlotBoundsValid || m_hSlotSpacing <= 0) return false; - F32 rowWidth = m_hSlotSpacing * m_iCraftablesMaxHSlotC; + // Tab click — tabs sit directly above the H slot row. We derive their + // bounds from the H slot positions cached in customDraw, since the Vita + // TouchPanel controls are full-screen overlays with unusable bounds. + int maxTabs = (m_iContainerType == RECIPE_TYPE_3x3) ? m_iMaxGroup3x3 : m_iMaxGroup2x2; + F32 slotHeight = m_hSlotY1 - m_hSlotY0; + F32 tabRowY0 = (m_hSlotY0 * 0.75f) - slotHeight * 1.55f; + F32 tabRowY1 = tabRowY0 + (slotHeight * 1.7f); + F32 tabRowWidth = m_hSlotSpacing * m_iCraftablesMaxHSlotC; + F32 tabWidth = tabRowWidth / maxTabs; - if (m_hSlotSpacing > 0 && x >= m_hSlotX0 && x < m_hSlotX0 + rowWidth && + if (tabWidth > 0 && x >= m_hSlotX0 && x < m_hSlotX0 + tabRowWidth && + y >= tabRowY0 && y < tabRowY1) + { + int iTab = (int)((x - m_hSlotX0) / tabWidth); + if (iTab >= 0 && iTab < maxTabs && iTab != m_iGroupIndex) + { + showTabHighlight(m_iGroupIndex, false); + m_iGroupIndex = iTab; + showTabHighlight(m_iGroupIndex, true); + m_iCurrentSlotHIndex = 0; + m_iCurrentSlotVIndex = 1; + CheckRecipesAvailable(); + iVSlotIndexA[0] = CanBeMadeA[m_iCurrentSlotHIndex].iCount - 1; + iVSlotIndexA[1] = 0; + iVSlotIndexA[2] = 1; + ui.PlayUISFX(eSFX_Focus); + UpdateVerticalSlots(); + UpdateHighlight(); + setGroupText(GetGroupNameText(m_pGroupA[m_iGroupIndex])); + } + return true; + } + + // H slot click — select or craft + F32 rowWidth = m_hSlotSpacing * m_iCraftablesMaxHSlotC; + if (x >= m_hSlotX0 && x < m_hSlotX0 + rowWidth && y >= m_hSlotY0 && y < m_hSlotY1) { int iNewSlot = (int)((x - m_hSlotX0) / m_hSlotSpacing); if (iNewSlot >= 0 && iNewSlot < m_iCraftablesMaxHSlotC) { - int iOldHSlot = m_iCurrentSlotHIndex; - m_iCurrentSlotHIndex = iNewSlot; - m_iCurrentSlotVIndex = 1; - iVSlotIndexA[0] = CanBeMadeA[m_iCurrentSlotHIndex].iCount - 1; - iVSlotIndexA[1] = 0; - iVSlotIndexA[2] = 1; - UpdateVerticalSlots(); - UpdateHighlight(); - if (CanBeMadeA[iOldHSlot].iCount > 0) - setShowCraftHSlot(iOldHSlot, true); - ui.PlayUISFX(eSFX_Focus); + // Only interact with populated slots + if (CanBeMadeA[iNewSlot].iCount == 0) + return true; + + if (iNewSlot == m_iCurrentSlotHIndex) + { + // Click on already-selected slot — craft the item + handleKeyDown(m_iPad, ACTION_MENU_A, false); + } + else + { + int iOldHSlot = m_iCurrentSlotHIndex; + m_iCurrentSlotHIndex = iNewSlot; + m_iCurrentSlotVIndex = 1; + iVSlotIndexA[0] = CanBeMadeA[m_iCurrentSlotHIndex].iCount - 1; + iVSlotIndexA[1] = 0; + iVSlotIndexA[2] = 1; + UpdateVerticalSlots(); + UpdateHighlight(); + if (CanBeMadeA[iOldHSlot].iCount > 0) + setShowCraftHSlot(iOldHSlot, true); + ui.PlayUISFX(eSFX_Focus); + } return true; } } - - return false; + // Consume all mouse clicks so misses don't generate ACTION_MENU_A + // and accidentally craft. Only blocks mouse-originated presses. + return true; } #endif diff --git a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h index be3fe6c7d..2f52b8ba8 100644 --- a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h @@ -66,10 +66,12 @@ public: #ifdef __PSVITA__ virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased); - virtual UIControl* GetMainPanel(); virtual void handleTouchBoxRebuild(); virtual void handleTimerComplete(int id); #endif +#if defined(__PSVITA__) || defined(_WINDOWS64) + virtual UIControl* GetMainPanel(); +#endif #ifdef _WINDOWS64 virtual bool handleMouseClick(F32 x, F32 y); // Cached from customDraw — H slot bounding boxes in SWF space @@ -104,7 +106,7 @@ protected: ETouchInput_TouchPanel_5, ETouchInput_TouchPanel_6, ETouchInput_CraftingHSlots, - + ETouchInput_Count, }; UIControl_Touch m_TouchInput[ETouchInput_Count];