private static void Input_ButtonPressed(object sender, ButtonPressedEventArgs e) { try { Point CursorPos = e.Cursor.ScreenPixels.AsAndroidCompatibleCursorPoint(); bool IsGamepadInput = e.Button.TryGetController(out Buttons GamepadButtons); if (Game1.activeClickableMenu != null && Game1.activeClickableMenu is ItemBagMenu IBM) { if (e.Button == SButton.MouseLeft || e.Button == SButton.MouseMiddle || e.Button == SButton.MouseRight) { try { IBM.OnMouseButtonPressed(e); } catch (Exception ex) { Monitor.Log(string.Format("Unhandled error while handling Mouse button pressed: {0}\n\n{1}", ex.Message, ex.ToString()), LogLevel.Error); } } else if (e.Button == SButton.LeftShift || e.Button == SButton.RightShift || e.Button == SButton.LeftControl || e.Button == SButton.RightControl) { try { IBM.OnModifierKeyPressed(e); } catch (Exception ex) { Monitor.Log(string.Format("Unhandled error while handling Modifier key pressed: {0}\n\n{1}", ex.Message, ex.ToString()), LogLevel.Error); } } else if (IsGamepadInput) { try { // Handle navigation buttons foreach (NavigationDirection Direction in Enum.GetValues(typeof(NavigationDirection)).Cast <NavigationDirection>()) { if (GamepadControls.IsMatch(GamepadButtons, GamepadControls.NavigateSingleButtons[Direction])) { NavigationButtonsPressedTime[Direction] = DateTime.Now; } } IBM.OnGamepadButtonsPressed(GamepadButtons); } catch (Exception ex) { Monitor.Log(string.Format("Unhandled error while handling Gamepad button pressed: {0}\n\n{1}", ex.Message, ex.ToString()), LogLevel.Error); } } } else if (Game1.activeClickableMenu != null && Game1.activeClickableMenu is GameMenu GM && GM.currentTab == GameMenu.inventoryTab) { InventoryPage InvPage = GM.pages.First(x => x is InventoryPage) as InventoryPage; InventoryMenu InvMenu = InvPage.inventory; int ClickedItemIndex = InvMenu.getInventoryPositionOfClick(CursorPos.X, CursorPos.Y); bool IsValidInventorySlot = ClickedItemIndex >= 0 && ClickedItemIndex < InvMenu.actualInventory.Count; if (IsValidInventorySlot) { Item ClickedItem = InvMenu.actualInventory[ClickedItemIndex]; // Double click an ItemBag to open it if (e.Button == SButton.MouseLeft) //SButtonExtensions.IsUseToolButton(e.Button)) { // The first time the user clicks an item in their inventory, Game1.player.CursorSlotItem is set to what they clicked (so it's like drag/drop, they're now holding the item to move it) // So to detect a double click, we can't just check if they clicked the bag twice in a row, since on the second click the item would no longer be in their inventory. // Instead, we need to check if they clicked the bag and then we need to check Game1.player.CursorSlotItem on the next click if (ClickedItem is ItemBag ClickedBag && Game1.player.CursorSlotItem == null) { LastClickedBagInventoryIndex = ClickedItemIndex; LastClickedBag = ClickedBag; LastClickedBagTime = DateTime.Now; } else if (ClickedItem == null && Game1.player.CursorSlotItem is ItemBag DraggedBag && LastClickedBag == DraggedBag && LastClickedBagInventoryIndex.HasValue && LastClickedBagInventoryIndex.Value == ClickedItemIndex && LastClickedBagTime.HasValue && DateTime.Now.Subtract(LastClickedBagTime.Value).TotalMilliseconds <= DoubleClickThresholdMS) { LastClickedBag = DraggedBag; LastClickedBagTime = DateTime.Now; // Put the item that's being dragged back into their inventory Game1.player.addItemToInventory(Game1.player.CursorSlotItem, ClickedItemIndex); Game1.player.CursorSlotItem = null; DraggedBag.OpenContents(Game1.player.Items, Game1.player.MaxItems); } } // Right-click an ItemBag to open it else if ((e.Button == SButton.MouseRight || (IsGamepadInput && GamepadControls.IsMatch(GamepadButtons, GamepadControls.Current.OpenBagFromInventory))) && ClickedItem is ItemBag ClickedBag && Game1.player.CursorSlotItem == null) { ClickedBag.OpenContents(Game1.player.Items, Game1.player.MaxItems); } // Handle dropping an item into a bag from the Inventory menu if (ClickedItem is ItemBag IB && Game1.player.CursorSlotItem != null && Game1.player.CursorSlotItem is Object Obj) { if (IB.IsValidBagItem(Obj) && (e.Button == SButton.MouseLeft || e.Button == SButton.MouseRight)) { int Qty = ItemBag.GetQuantityToTransfer(e, Obj); IB.MoveToBag(Obj, Qty, out int MovedQty, true, Game1.player.Items); if (e.Button == SButton.MouseLeft) // || (MovedQty > 0 && Obj.Stack == 0) // Handle moving the last quantity with a right-click { // Clicking the bag will have made it become the held CursorSlotItem, so queue up an action that will swap them back on next game tick QueueCursorSlotIndex = ClickedItemIndex; QueuePlaceCursorSlotItem = true; } } } } } else if (Game1.activeClickableMenu == null && (e.Button == SButton.MouseLeft || e.Button == SButton.MouseRight || (IsGamepadInput && GamepadControls.IsMatch(GamepadButtons, GamepadControls.Current.OpenBagFromToolbar)))) { // Check if they clicked a bag on the toolbar, open the bag if so Toolbar toolbar = Game1.onScreenMenus.FirstOrDefault(x => x is Toolbar) as Toolbar; if (toolbar != null) { try { List <ClickableComponent> toolbarButtons = typeof(Toolbar).GetField("buttons", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(toolbar) as List <ClickableComponent>; if (toolbarButtons != null) { // Find the slot on the toolbar that they clicked, if any for (int i = 0; i < toolbarButtons.Count; i++) { if (toolbarButtons[i].bounds.Contains(CursorPos) || (IsGamepadInput && toolbar.currentlySnappedComponent == toolbarButtons[i])) { int ActualIndex = i; if (Constants.TargetPlatform == GamePlatform.Android) { try { int StartIndex = Helper.Reflection.GetField <int>(toolbar, "_drawStartIndex").GetValue(); // This is completely untested ActualIndex = i + StartIndex; } catch (Exception) { } } // Get the corresponding Item from the player's inventory Item item = Game1.player.Items[ActualIndex]; if (item is ItemBag IB) { IB.OpenContents(Game1.player.Items, Game1.player.MaxItems); } break; } } } } catch (Exception) { } } } else if (Game1.activeClickableMenu is ItemGrabMenu IGM && IGM.context is Chest ChestSource && (e.Button == SButton.MouseRight || e.Button == SButton.MouseMiddle || (IsGamepadInput && GamepadControls.IsMatch(GamepadButtons, GamepadControls.Current.OpenBagFromChest)))) { // Check if they clicked a Bag in the inventory part of the chest interface bool Handled = false; for (int i = 0; i < IGM.inventory.inventory.Count; i++) { ClickableComponent Component = IGM.inventory.inventory[i]; if (Component != null && Component.bounds.Contains(CursorPos)) { Item ClickedInvItem = i < 0 || i >= IGM.inventory.actualInventory.Count ? null : IGM.inventory.actualInventory[i]; if (ClickedInvItem is ItemBag IB) { IB.OpenContents(IGM.inventory.actualInventory, Game1.player.MaxItems); } Handled = true; break; } } bool IsMegaStorageCompatibleWithCurrentChest = IGM.ItemsToGrabMenu.capacity == DefaultChestCapacity || MegaStorageInstalledVersion == null || MegaStorageInstalledVersion.IsNewerThan(new SemanticVersion(1, 4, 4)); if (!Handled && IsMegaStorageCompatibleWithCurrentChest) { // Check if they clicked a Bag in the chest part of the chest interface for (int i = 0; i < IGM.ItemsToGrabMenu.inventory.Count; i++) { ClickableComponent Component = IGM.ItemsToGrabMenu.inventory[i]; if (Component != null && Component.bounds.Contains(CursorPos)) { Item ClickedChestItem = i < 0 || i >= IGM.ItemsToGrabMenu.actualInventory.Count ? null : IGM.ItemsToGrabMenu.actualInventory[i]; if (ClickedChestItem is ItemBag IB) { IB.OpenContents(IGM.ItemsToGrabMenu.actualInventory, IGM.ItemsToGrabMenu.capacity); } Handled = true; break; } } } } }