From c98e60f87a7c2ff2dab15b7b3be22389199f1120 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Fri, 11 Feb 2022 15:29:20 -0500 Subject: [PATCH] v1.2.0: added right and middle click functions to the inventory pane --- .../ui/InventoryPane.java | 176 ++++++++++-------- .../ui/RightClickMenu.java | 159 ++++++++++++++++ 2 files changed, 259 insertions(+), 76 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/RightClickMenu.java diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/InventoryPane.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/InventoryPane.java index a41a72754..1010f749e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/InventoryPane.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/InventoryPane.java @@ -49,6 +49,7 @@ import com.watabou.noosa.NinePatch; import com.watabou.noosa.PointerArea; import com.watabou.noosa.ui.Component; import com.watabou.utils.Point; +import com.watabou.utils.PointF; import java.util.ArrayList; @@ -130,44 +131,7 @@ public class InventoryPane extends Component { equipped = new ArrayList<>(); for (int i = 0; i < 5; i++){ - InventorySlot btn = new InventorySlot(null){ - @Override - protected void onClick() { - if (lastBag != item && !lastBag.contains(item) && !item.isEquipped(Dungeon.hero)){ - updateInventory(); - return; - } - - if (targeting){ - if (targetingSlot == this){ - int cell = QuickSlotButton.autoAim(lastTarget, item()); - - if (cell != -1){ - GameScene.handleCell(cell); - } else { - //couldn't auto-aim, just target the position and hope for the best. - GameScene.handleCell( lastTarget.pos ); - } - return; - } else { - cancelTargeting(); - } - } - - //any windows opened as a consequence of this button should be centered on the inventory - GameScene.lastOffset = new Point((int)InventoryPane.this.centerX() - camera.width/2, - (int)InventoryPane.this.centerY() - camera.height/2); - if (selector != null) { - WndBag.ItemSelector activating = selector; - selector = null; - activating.onSelect( item ); - updateInventory(); - } else { - targetingSlot = this; - GameScene.show(new WndUseItem( null, item )); - } - } - }; + InventorySlot btn = new InventoryPaneSlot(null); equipped.add(btn); add(btn); } @@ -190,44 +154,7 @@ public class InventoryPane extends Component { bagItems = new ArrayList<>(); for (int i = 0; i < 20; i++){ - InventorySlot btn = new InventorySlot(null){ - @Override - protected void onClick() { - if (lastBag != item && !lastBag.contains(item) && !item.isEquipped(Dungeon.hero)){ - updateInventory(); - return; - } - - if (targeting){ - if (targetingSlot == this){ - int cell = QuickSlotButton.autoAim(lastTarget, item()); - - if (cell != -1){ - GameScene.handleCell(cell); - } else { - //couldn't auto-aim, just target the position and hope for the best. - GameScene.handleCell( lastTarget.pos ); - } - return; - } else { - cancelTargeting(); - } - } - - //any windows opened as a consequence of this button should be centered on the inventory - GameScene.lastOffset = new Point((int)InventoryPane.this.centerX() - camera.width/2, - (int)InventoryPane.this.centerY() - camera.height/2); - if (selector != null) { - WndBag.ItemSelector activating = selector; - selector = null; - activating.onSelect( item ); - updateInventory(); - } else { - targetingSlot = this; - GameScene.show(new WndUseItem( null, item )); - } - } - }; + InventorySlot btn = new InventoryPaneSlot(null); bagItems.add(btn); add(btn); } @@ -491,6 +418,103 @@ public class InventoryPane extends Component { } } + private class InventoryPaneSlot extends InventorySlot { + + private InventoryPaneSlot( Item item ){ + super(item); + } + + @Override + protected void onClick() { + if (lastBag != item && !lastBag.contains(item) && !item.isEquipped(Dungeon.hero)){ + updateInventory(); + return; + } + + if (targeting){ + if (targetingSlot == this){ + int cell = QuickSlotButton.autoAim(lastTarget, item()); + + if (cell != -1){ + GameScene.handleCell(cell); + } else { + //couldn't auto-aim, just target the position and hope for the best. + GameScene.handleCell( lastTarget.pos ); + } + return; + } else { + cancelTargeting(); + } + } + + //any windows opened as a consequence of this button should be centered on the inventory + GameScene.lastOffset = new Point((int)InventoryPane.this.centerX() - camera.width/2, + (int)InventoryPane.this.centerY() - camera.height/2); + if (selector != null) { + WndBag.ItemSelector activating = selector; + selector = null; + activating.onSelect( item ); + updateInventory(); + } else { + targetingSlot = this; + GameScene.show(new WndUseItem( null, item )); + } + } + + @Override + protected void onMiddleClick() { + if (lastBag != item && !lastBag.contains(item) && !item.isEquipped(Dungeon.hero)){ + updateInventory(); + return; + } + + if (targeting){ + if (targetingSlot == this){ + onClick(); + } else{ + cancelTargeting(); + } + } + + if (selector == null && item.defaultAction != null){ + item.execute(Dungeon.hero); + if (item.usesTargeting) { + targetingSlot = this; + InventoryPane.useTargeting(); + } + } else { + super.onMiddleClick(); + } + } + + @Override + protected void onRightClick() { + if (lastBag != item && !lastBag.contains(item) && !item.isEquipped(Dungeon.hero)){ + updateInventory(); + return; + } + + if (targeting){ + if (targetingSlot == this){ + onClick(); + } else{ + cancelTargeting(); + } + } + + if (selector == null){ + RightClickMenu r = new RightClickMenu(item); + parent.addToFront(r); + r.camera = camera(); + PointF mousePos = PointerEvent.currentHoverPos(); + mousePos = camera.screenToCamera((int)mousePos.x, (int)mousePos.y); + r.setPos(mousePos.x-3, mousePos.y-3); + } else { + super.onRightClick(); + } + } + } + private class BagButton extends IconButton { private static final int ACTIVE = 0x9953564D; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/RightClickMenu.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/RightClickMenu.java new file mode 100644 index 000000000..5311ea878 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/RightClickMenu.java @@ -0,0 +1,159 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2022 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.ui; + +import com.shatteredpixel.shatteredpixeldungeon.Chrome; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; +import com.shatteredpixel.shatteredpixeldungeon.windows.IconTitle; +import com.watabou.input.PointerEvent; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Image; +import com.watabou.noosa.NinePatch; +import com.watabou.noosa.PointerArea; +import com.watabou.noosa.ui.Component; + +import java.util.ArrayList; + +public class RightClickMenu extends Component { + + private NinePatch bg; + private PointerArea blocker; + + private Image icon; + private RenderedTextBlock titleText; + private ColorBlock separator; + + private RedButton[] buttons; + + private Item item; + + public RightClickMenu(Item item){ + ArrayList actions = item.actions(Dungeon.hero); + if (actions.remove(item.defaultAction)) { + actions.add(0, item.defaultAction); + } + String[] options = actions.toArray(new String[0]); + this.item = item; + setup(new ItemSprite(item), Messages.titleCase(item.name()), options); + } + + public RightClickMenu(Image icon, String title, String... options){ + setup(icon, title, options); + } + + private void setup(Image icon, String title, String... options){ + bg = Chrome.get(Chrome.Type.TOAST_TR); + add(bg); + + this.icon = icon; + add(icon); + + titleText = PixelScene.renderTextBlock(title, 6); + titleText.maxWidth(50); + titleText.hardlight(Window.TITLE_COLOR); + add(titleText); + + separator = new ColorBlock(1, 1, 0xFF000000); + add(separator); + + buttons = new RedButton[options.length]; + for (int i = 0; i < options.length; i++){ + int finalI = i; + buttons[i] = new RedButton(options[finalI], 6){ + @Override + protected void onClick() { + super.onClick(); + if (item != null){ + item.execute(Dungeon.hero, options[finalI]); + } else { + onSelect(finalI); + } + RightClickMenu.this.destroy(); + RightClickMenu.this.killAndErase(); + } + }; + if (item != null && options[i].equals(item.defaultAction)){ + buttons[i].textColor(Window.TITLE_COLOR); + } + add(buttons[i]); + } + + blocker = new PointerArea(0, 0, 0, 0){ + @Override + protected void onHoverEnd(PointerEvent event) { + RightClickMenu.this.destroy(); + RightClickMenu.this.killAndErase(); + } + }; + blocker.blockLevel = PointerArea.NEVER_BLOCK; + blocker.target = bg; + add(blocker); + + } + + public void onSelect(int index){} + + @Override + protected void layout() { + super.layout(); + + height = 0; + height += bg.marginVer(); + height += Math.max(icon.height(), titleText.height()); + height += 2; + height += 13*buttons.length; + + width = icon.width + 2 + titleText.width()+bg.marginVer(); + + if (x + width > camera.width){ + x -= (x + width - camera.width); + } + if (y + height > camera.height){ + y -= (y + height - camera.height); + } + + bg.x = x; + bg.y = y; + + icon.x = x+bg.marginLeft(); + icon.y = y+bg.marginTop(); + + titleText.setPos(icon.x+icon.width()+2, icon.y + (icon.height()- titleText.height())/2); + + separator.x = x+bg.marginLeft(); + separator.y = Math.max(icon.y + icon.height(), titleText.bottom()) + 1; + separator.size(width - bg.marginHor(), 1); + + float top = separator.y + 2; + for (RedButton button : buttons){ + button.setRect(x + bg.marginLeft(), top, width-bg.marginHor(), 12); + top = button.bottom()+1; + } + + bg.size(width, height); + + } +}