diff --git a/core/src/main/assets/interfaces/toolbar.png b/core/src/main/assets/interfaces/toolbar.png index 45e6de4a4..e0871dbd7 100644 Binary files a/core/src/main/assets/interfaces/toolbar.png and b/core/src/main/assets/interfaces/toolbar.png differ diff --git a/core/src/main/assets/messages/windows/windows.properties b/core/src/main/assets/messages/windows/windows.properties index f74815306..c544f2363 100644 --- a/core/src/main/assets/messages/windows/windows.properties +++ b/core/src/main/assets/messages/windows/windows.properties @@ -225,7 +225,8 @@ windows.wndsettings$uitab.group=Group windows.wndsettings$uitab.center=Center windows.wndsettings$uitab.flip_toolbar=Flip Toolbar windows.wndsettings$uitab.flip_indicators=Flip Indicators -windows.wndsettings$uitab.quickslots=Quickslots +windows.wndsettings$uitab.quickslot_swapper=Quickslot Swapper +windows.wndsettings$uitab.swapper_desc=Shows 3 quickslots with a 'swapper' button if there isn't enough room to display all six quickslots. windows.wndsettings$uitab.system_font=System Font windows.wndsettings$uitab.key_bindings=Key Bindings windows.wndsettings$inputtab.title=Input Settings diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java index 28fc9e72d..79b8d229f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java @@ -67,6 +67,7 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; +import com.shatteredpixel.shatteredpixeldungeon.ui.Toolbar; import com.shatteredpixel.shatteredpixeldungeon.utils.BArray; import com.shatteredpixel.shatteredpixeldungeon.utils.DungeonSeed; import com.shatteredpixel.shatteredpixeldungeon.windows.WndResurrect; @@ -219,6 +220,7 @@ public class Dungeon { quickslot.reset(); QuickSlotButton.reset(); + Toolbar.swappedQuickslots = false; depth = 1; branch = 0; @@ -604,6 +606,7 @@ public class Dungeon { quickslot.reset(); QuickSlotButton.reset(); + Toolbar.swappedQuickslots = false; Dungeon.challenges = bundle.getInt( CHALLENGES ); Dungeon.mobsToChampion = bundle.getInt( MOBS_TO_CHAMPION ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/QuickSlot.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/QuickSlot.java index 2666bde38..264830220 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/QuickSlot.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/QuickSlot.java @@ -36,7 +36,7 @@ public class QuickSlot { * which can happen for a stackable item that has been 'used up', these are refered to a placeholders. */ - //note that the current max size is coded at 4, due to UI constraints, but it could be much much bigger with no issue. + //note that the current max size is coded at 6, due to UI constraints, but it could be much much bigger with no issue. public static int SIZE = 6; private Item[] slots = new Item[SIZE]; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Rankings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Rankings.java index 21edf1dae..bd40e5e4b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Rankings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Rankings.java @@ -36,6 +36,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll; import com.shatteredpixel.shatteredpixeldungeon.journal.Notes; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; +import com.shatteredpixel.shatteredpixeldungeon.ui.Toolbar; import com.watabou.noosa.Game; import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; @@ -250,6 +251,7 @@ public enum Rankings { Notes.reset(); Dungeon.quickslot.reset(); QuickSlotButton.reset(); + Toolbar.swappedQuickslots = false; Bundle handler = data.getBundle(HANDLERS); Scroll.restore(handler); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/SPDSettings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/SPDSettings.java index ea465f3af..2a6ae91cd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/SPDSettings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/SPDSettings.java @@ -152,9 +152,9 @@ public class SPDSettings extends GameSettings { return getInt( KEY_SCALE, 0 ); } - public static void quickSlots( int value ){ put( KEY_QUICKSLOTS, value ); } + public static void quickSlots( boolean value ){ put( KEY_QUICKSLOTS, value ); } - public static int quickSlots(){ return getInt( KEY_QUICKSLOTS, 4, 0, 4); } + public static boolean quickSlots(){ return getBoolean( KEY_QUICKSLOTS, false); } public static void flipToolbar( boolean value) { put(KEY_FLIPTOOLBAR, value ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/QuickSlotButton.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/QuickSlotButton.java index edd32ca68..567491821 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/QuickSlotButton.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/QuickSlotButton.java @@ -322,6 +322,9 @@ public class QuickSlotButton extends Button { instance[i].enable(instance[i].active); } } + if (Toolbar.SWAP_INSTANCE != null){ + Toolbar.SWAP_INSTANCE.updateVisuals(); + } } public static void target( Char target ) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Toolbar.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Toolbar.java index 1bb42a989..4e7b6a77d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Toolbar.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Toolbar.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.ui; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.QuickSlot; import com.shatteredpixel.shatteredpixeldungeon.SPDAction; import com.shatteredpixel.shatteredpixeldungeon.SPDSettings; import com.shatteredpixel.shatteredpixeldungeon.items.Item; @@ -51,6 +52,7 @@ public class Toolbar extends Component { private Tool btnSearch; private Tool btnInventory; private QuickslotTool[] btnQuick; + private SlotSwapTool btnSwap; private PickedUpItem pickedUp; @@ -76,13 +78,10 @@ public class Toolbar extends Component { @Override protected void createChildren() { - //TODO add a changer function to the 4th quickslot if there isn't room for 6? - int quickSlots = 4; - if (PixelScene.uiCamera.width > 152) quickSlots ++; - if (PixelScene.uiCamera.width > 170) quickSlots ++; + add(btnSwap = new SlotSwapTool(128, 0, 21, 23)); - btnQuick = new QuickslotTool[quickSlots]; - for (int i = 0; i < quickSlots; i++){ + btnQuick = new QuickslotTool[QuickSlot.SIZE]; + for (int i = 0; i < btnQuick.length; i++){ add( btnQuick[i] = new QuickslotTool(64, 0, 22, 24, i) ); } @@ -92,6 +91,8 @@ public class Toolbar extends Component { if (Dungeon.hero.ready && !GameScene.cancel()) { examining = false; Dungeon.hero.rest(false); + swappedQuickslots = !swappedQuickslots; + updateLayout(); } } @@ -227,14 +228,39 @@ public class Toolbar extends Component { float right = width; + int quickslotsToShow = 4; + if (PixelScene.uiCamera.width > 152) quickslotsToShow ++; + if (PixelScene.uiCamera.width > 170) quickslotsToShow ++; + + int startingSlot; + if (SPDSettings.quickSlots() && quickslotsToShow < 6){ + quickslotsToShow = 3; + startingSlot = swappedQuickslots ? 3 : 0; + btnSwap.visible = true; + btnSwap.active = lastEnabled; + } else { + startingSlot = 0; + btnSwap.visible = btnSwap.active = false; + btnSwap.setPos(0, PixelScene.uiCamera.height); + } + int endingSlot = startingSlot+quickslotsToShow-1; + + for (int i = 0; i < btnQuick.length; i++){ + btnQuick[i].visible = i >= startingSlot && i <= endingSlot; + btnQuick[i].enable(btnQuick[i].visible && lastEnabled); + if (i < startingSlot || i > endingSlot){ + btnQuick[i].setPos(btnQuick[i].left(), PixelScene.uiCamera.height); + } + } + if (SPDSettings.interfaceSize() > 0){ btnInventory.setPos(right - btnInventory.width(), y); btnWait.setPos(btnInventory.left() - btnWait.width(), y); btnSearch.setPos(btnWait.left() - btnSearch.width(), y); right = btnSearch.left(); - for(int i = btnQuick.length-1; i >= 0; i--) { - if (i == btnQuick.length-1){ + for(int i = endingSlot; i >= startingSlot; i--) { + if (i == endingSlot){ btnQuick[i].border(0, 2); btnQuick[i].frame(106, 0, 19, 24); } else if (i == 0){ @@ -248,16 +274,18 @@ public class Toolbar extends Component { right = btnQuick[i].left(); } + //swap button never appears on larger interface sizes + return; } - for(int i = 0; i < btnQuick.length; i++) { - if (i == 0 && !SPDSettings.flipToolbar() || - i == btnQuick.length-1 && SPDSettings.flipToolbar()){ + for(int i = startingSlot; i <= endingSlot; i++) { + if (i == startingSlot && !SPDSettings.flipToolbar() || + i == endingSlot && SPDSettings.flipToolbar()){ btnQuick[i].border(0, 2); btnQuick[i].frame(106, 0, 19, 24); - } else if (i == 0 && SPDSettings.flipToolbar() || - i == btnQuick.length-1 && !SPDSettings.flipToolbar()){ + } else if (i == startingSlot && SPDSettings.flipToolbar() || + i == endingSlot && !SPDSettings.flipToolbar()){ btnQuick[i].border(2, 1); btnQuick[i].frame(86, 0, 20, 24); } else { @@ -266,6 +294,7 @@ public class Toolbar extends Component { } } + float shift = 0; switch(Mode.valueOf(SPDSettings.toolbarMode())){ case SPLIT: btnWait.setPos(x, y); @@ -273,19 +302,19 @@ public class Toolbar extends Component { btnInventory.setPos(right - btnInventory.width(), y); - btnQuick[0].setPos(btnInventory.left() - btnQuick[0].width(), y + 2); - for (int i = 1; i < btnQuick.length; i++) { + float left = 0; + + btnQuick[startingSlot].setPos(btnInventory.left() - btnQuick[startingSlot].width(), y + 2); + for (int i = startingSlot+1; i <= endingSlot; i++) { btnQuick[i].setPos(btnQuick[i-1].left() - btnQuick[i].width(), y + 2); + shift = btnSearch.right() - btnQuick[i].left(); } - - //center the quickslots if they - if (btnQuick[btnQuick.length-1].left() < btnSearch.right()){ - float diff = Math.round(btnSearch.right() - btnQuick[btnQuick.length-1].left())/2; - for( int i = 0; i < btnQuick.length; i++){ - btnQuick[i].setPos( btnQuick[i].left()+diff, btnQuick[i].top() ); - } + + if (btnSwap.visible){ + btnSwap.setPos(btnQuick[endingSlot].left() - (btnSwap.width()-2), y+3); + shift = btnSearch.right() - btnSwap.left(); } - + break; //center = group but.. well.. centered, so all we need to do is pre-emptively set the right side further in. @@ -294,6 +323,7 @@ public class Toolbar extends Component { for(Button slot : btnQuick){ if (slot.visible) toolbarWidth += slot.width(); } + if (btnSwap.visible) toolbarWidth += btnSwap.width()-2; right = (width + toolbarWidth)/2; case GROUP: @@ -301,20 +331,30 @@ public class Toolbar extends Component { btnSearch.setPos(btnWait.left() - btnSearch.width(), y); btnInventory.setPos(btnSearch.left() - btnInventory.width(), y); - btnQuick[0].setPos(btnInventory.left() - btnQuick[0].width(), y + 2); - for (int i = 1; i < btnQuick.length; i++) { + btnQuick[startingSlot].setPos(btnInventory.left() - btnQuick[startingSlot].width(), y + 2); + for (int i = startingSlot+1; i <= endingSlot; i++) { btnQuick[i].setPos(btnQuick[i-1].left() - btnQuick[i].width(), y + 2); + shift = -btnQuick[i].left(); } - - if (btnQuick[btnQuick.length-1].left() < 0){ - float diff = -Math.round(btnQuick[btnQuick.length-1].left())/2; - for( int i = 0; i < btnQuick.length; i++){ - btnQuick[i].setPos( btnQuick[i].left()+diff, btnQuick[i].top() ); - } + + if (btnSwap.visible){ + btnSwap.setPos(btnQuick[endingSlot].left() - (btnSwap.width()-2), y+3); + shift = -btnSwap.left(); } break; } + + if (shift > 0){ + shift /= 2; //we want to center; + for (int i = startingSlot; i <= endingSlot; i++) { + btnQuick[i].setPos(btnQuick[i].left()+shift, btnQuick[i].top()); + } + if (btnSwap.visible){ + btnSwap.setPos(btnSwap.left()+shift, btnSwap.top()); + } + } + right = width; if (SPDSettings.flipToolbar()) { @@ -323,10 +363,14 @@ public class Toolbar extends Component { btnSearch.setPos( (right - btnSearch.right()), y); btnInventory.setPos( (right - btnInventory.right()), y); - for(int i = 0; i < btnQuick.length; i++) { + for(int i = startingSlot; i <= endingSlot; i++) { btnQuick[i].setPos( right - btnQuick[i].right(), y+2); } + if (btnSwap.visible){ + btnSwap.setPos( right - btnSwap.right(), y+3); + } + } } @@ -463,10 +507,118 @@ public class Toolbar extends Component { @Override public void enable( boolean value ) { - super.enable( value ); - slot.enable( value ); + super.enable( value && visible ); + slot.enable( value && visible ); } } + + public static boolean swappedQuickslots = false; + public static SlotSwapTool SWAP_INSTANCE; + + public static class SlotSwapTool extends Tool { + + private Image[] icons = new Image[4]; + private Item[] items = new Item[4]; + + public SlotSwapTool(int x, int y, int width, int height) { + super(x, y, width, height); + SWAP_INSTANCE = this; + updateVisuals(); + } + + @Override + public synchronized void destroy() { + super.destroy(); + SWAP_INSTANCE = null; + } + + @Override + protected void onClick() { + super.onClick(); + swappedQuickslots = !swappedQuickslots; + updateLayout(); + updateVisuals(); + } + + public void updateVisuals(){ + if (icons[0] == null){ + icons[0] = Icons.get(Icons.CHANGES); + icons[0].scale.set(PixelScene.align(0.45f)); + add(icons[0]); + } + + int slot; + int slotDir; + if (SPDSettings.flipToolbar()){ + slot = swappedQuickslots ? 0 : 3; + slotDir = +1; + } else { + slot = swappedQuickslots ? 2 : 5; + slotDir = -1; + } + + for (int i = 1; i < 4; i++){ + if (items[i] == Dungeon.quickslot.getItem(slot)){ + slot += slotDir; + continue; + } else { + items[i] = Dungeon.quickslot.getItem(slot); + } + if (icons[i] != null){ + icons[i].killAndErase(); + icons[i] = null; + } + if (items[i] != null){ + icons[i] = new ItemSprite(items[i]); + icons[i].scale.set(PixelScene.align(0.45f)); + if (Dungeon.quickslot.isPlaceholder(slot)) icons[i].alpha(0.29f); + add(icons[i]); + } + slot += slotDir; + } + + icons[0].x = x + 2 + (8 - icons[0].width())/2; + icons[0].y = y + 2 + (9 - icons[0].height())/2; + PixelScene.align(icons[0]); + + if (icons[1] != null){ + icons[1].x = x + 11 + (8 - icons[1].width())/2; + icons[1].y = y + 2 + (9 - icons[1].height())/2; + PixelScene.align(icons[1]); + } + + if (icons[2] != null){ + icons[2].x = x + 2 + (8 - icons[2].width())/2; + icons[2].y = y + 12 + (9 - icons[2].height())/2; + PixelScene.align(icons[2]); + } + + if (icons[3] != null){ + icons[3].x = x + 11 + (8 - icons[3].width())/2; + icons[3].y = y + 12 + (9 - icons[3].height())/2; + PixelScene.align(icons[3]); + } + } + + @Override + protected void layout() { + super.layout(); + updateVisuals(); + } + + @Override + public void enable(boolean value) { + super.enable(value); + for (Image ic : icons){ + if (ic != null && ic.alpha() >= 0.3f){ + ic.alpha( value ? 1 : 0.3f); + } + } + } + + //private + + } public static class PickedUpItem extends ItemSprite { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java index 5682cb928..9f0872ab7 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java @@ -462,9 +462,10 @@ public class WndSettings extends WndTabbed { RenderedTextBlock barDesc; RedButton btnSplit; RedButton btnGrouped; RedButton btnCentered; + CheckBox chkQuickSwapper; + RenderedTextBlock swapperDesc; CheckBox chkFlipToolbar; CheckBox chkFlipTags; - //TODO checkbox for forcing 6 quicksltos on mobile portrait { barDesc = PixelScene.renderTextBlock(Messages.get(WndSettings.UITab.this, "mode"), 9); @@ -515,6 +516,21 @@ public class WndSettings extends WndTabbed { } add(btnCentered); + chkQuickSwapper = new CheckBox(Messages.get(WndSettings.UITab.this, "quickslot_swapper")) { + @Override + protected void onClick() { + super.onClick(); + SPDSettings.quickSlots(checked()); + Toolbar.updateLayout(); + } + }; + chkQuickSwapper.checked(SPDSettings.quickSlots()); + add(chkQuickSwapper); + + swapperDesc = PixelScene.renderTextBlock(Messages.get(WndSettings.UITab.this, "swapper_desc"), 5); + swapperDesc.hardlight(0x888888); + add(swapperDesc); + chkFlipToolbar = new CheckBox(Messages.get(WndSettings.UITab.this, "flip_toolbar")) { @Override protected void onClick() { @@ -548,11 +564,16 @@ public class WndSettings extends WndTabbed { btnGrouped.setRect(btnSplit.right() + GAP, btnSplit.top(), btnWidth, BTN_HEIGHT-2); btnCentered.setRect(btnGrouped.right() + GAP, btnSplit.top(), btnWidth, BTN_HEIGHT-2); + chkQuickSwapper.setRect(0, btnGrouped.bottom() + GAP, width, BTN_HEIGHT); + + swapperDesc.maxWidth(width); + swapperDesc.setPos(0, chkQuickSwapper.bottom()+1); + if (width > 200) { - chkFlipToolbar.setRect(0, btnGrouped.bottom() + GAP, width / 2 - 1, BTN_HEIGHT); + chkFlipToolbar.setRect(0, swapperDesc.bottom() + GAP, width / 2 - 1, BTN_HEIGHT); chkFlipTags.setRect(chkFlipToolbar.right() + GAP, chkFlipToolbar.top(), width / 2 - 1, BTN_HEIGHT); } else { - chkFlipToolbar.setRect(0, btnGrouped.bottom() + GAP, width, BTN_HEIGHT); + chkFlipToolbar.setRect(0, swapperDesc.bottom() + GAP, width, BTN_HEIGHT); chkFlipTags.setRect(0, chkFlipToolbar.bottom() + GAP, width, BTN_HEIGHT); }