From b854b0ca227b0ed5d6905a78f839795cbd2547d6 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 1 Sep 2022 17:49:29 -0400 Subject: [PATCH] Better item selection UI --- .../mindustry/ctype/UnlockableContent.java | 2 + core/src/mindustry/type/UnitType.java | 1 + core/src/mindustry/world/Block.java | 3 + .../mindustry/world/blocks/ItemSelection.java | 87 +++++++++++++------ .../world/blocks/distribution/Sorter.java | 4 +- .../world/blocks/payloads/Constructor.java | 4 +- .../world/blocks/payloads/PayloadSource.java | 3 +- .../world/blocks/sandbox/ItemSource.java | 4 +- .../world/blocks/sandbox/LiquidSource.java | 4 +- .../world/blocks/storage/Unloader.java | 4 +- .../world/blocks/units/UnitFactory.java | 4 +- 11 files changed, 79 insertions(+), 41 deletions(-) diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java index 4471f7552c..566b625205 100644 --- a/core/src/mindustry/ctype/UnlockableContent.java +++ b/core/src/mindustry/ctype/UnlockableContent.java @@ -36,6 +36,8 @@ public abstract class UnlockableContent extends MappableContent{ public boolean generateIcons = true; /** Special logic icon ID. */ public int iconId = 0; + /** How big the content appears in certain selection menus */ + public float selectionSize = 24f; /** Icon of the content to use in UI. */ public TextureRegion uiIcon; /** Icon of the full content. Unscaled.*/ diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 3ffa005310..458b8f32d0 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -423,6 +423,7 @@ public class UnitType extends UnlockableContent{ super(name); constructor = EntityMapping.map(this.name); + selectionSize = 30f; } public UnitController createController(Unit unit){ diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index dd338b4f5e..c64718d56b 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -211,6 +211,8 @@ public class Block extends UnlockableContent implements Senseable{ public boolean commandable; /** If true, the building inventory can be shown with the config. */ public boolean allowConfigInventory = true; + /** Defines how large selection menus, such as that of sorters, should be. */ + public int selectionRows = 5, selectionColumns = 4; /** If true, this block can be configured by logic. */ public boolean logicConfigurable = false; /** Whether this block consumes touchDown events when tapped. */ @@ -365,6 +367,7 @@ public class Block extends UnlockableContent implements Senseable{ public Block(String name){ super(name); initBuilding(); + selectionSize = 28f; } public void drawBase(Tile tile){ diff --git a/core/src/mindustry/world/blocks/ItemSelection.java b/core/src/mindustry/world/blocks/ItemSelection.java index c444f2a4ac..1f833e6958 100644 --- a/core/src/mindustry/world/blocks/ItemSelection.java +++ b/core/src/mindustry/world/blocks/ItemSelection.java @@ -1,6 +1,7 @@ package mindustry.world.blocks; import arc.func.*; +import arc.math.*; import arc.scene.style.*; import arc.scene.ui.*; import arc.scene.ui.layout.*; @@ -15,49 +16,78 @@ import mindustry.world.*; import static mindustry.Vars.*; public class ItemSelection{ + private static TextField search; + private static int rowCount; public static void buildTable(Table table, Seq items, Prov holder, Cons consumer){ buildTable(table, items, holder, consumer, true); } - public static void buildTable(Block block, Table table, Seq items, Prov holder, Cons consumer){ - buildTable(block, table, items, holder, consumer, true); - } - public static void buildTable(Table table, Seq items, Prov holder, Cons consumer, boolean closeSelect){ - buildTable(null, table, items, holder, consumer, closeSelect); + buildTable(null, table, items, holder, consumer, closeSelect, 5, 4); } - - public static void buildTable(@Nullable Block block, Table table, Seq items, Prov holder, Cons consumer, boolean closeSelect){ + public static void buildTable(Table table, Seq items, Prov holder, Cons consumer, int columns){ + buildTable(null, table, items, holder, consumer, true, 5, columns); + } + + public static void buildTable(Block block, Table table, Seq items, Prov holder, Cons consumer){ + buildTable(block, table, items, holder, consumer, true, 5, 4); + } + + public static void buildTable(Block block, Table table, Seq items, Prov holder, Cons consumer, boolean closeSelect){ + buildTable(block, table, items, holder, consumer, closeSelect, 5 ,4); + } + + public static void buildTable(Block block, Table table, Seq items, Prov holder, Cons consumer, int rows, int columns){ + buildTable(block, table, items, holder, consumer, true, rows, columns); + } + + public static void buildTable(Table table, Seq items, Prov holder, Cons consumer, int rows, int columns){ + buildTable(null, table, items, holder, consumer, true, rows, columns); + } + + public static void buildTable(@Nullable Block block, Table table, Seq items, Prov holder, Cons consumer, boolean closeSelect, int rows, int columns){ ButtonGroup group = new ButtonGroup<>(); group.setMinCheckCount(0); - Table cont = new Table(); + Table cont = new Table().top(); cont.defaults().size(40); - int i = 0; + if(search != null) search.clearText(); - for(T item : items){ - if(!item.unlockedNow() || (item instanceof Item checkVisible && state.rules.hiddenBuildItems.contains(checkVisible)) || item.isHidden()) continue; + Runnable rebuild = () -> { + group.clear(); + cont.clearChildren(); - ImageButton button = cont.button(Tex.whiteui, Styles.clearTogglei, 24, () -> { - if(closeSelect) control.input.config.hideConfig(); - }).group(group).tooltip(item.localizedName).get(); - button.changed(() -> consumer.get(button.isChecked() ? item : null)); - button.getStyle().imageUp = new TextureRegionDrawable(item.uiIcon); - button.update(() -> button.setChecked(holder.get() == item)); + var text = search != null ? search.getText() : ""; + int i = 0; + rowCount = 0; - if(i++ % 4 == 3){ - cont.row(); + Seq list = items.select(u -> (text.isEmpty() || u.localizedName.toLowerCase().contains(text.toLowerCase()))); + for(T item : list){ + if(!item.unlockedNow() || (item instanceof Item checkVisible && state.rules.hiddenBuildItems.contains(checkVisible)) || item.isHidden()) continue; + + ImageButton button = cont.button(Tex.whiteui, Styles.clearNoneTogglei, Mathf.clamp(item.selectionSize, 0f, 40f), () -> { + if(closeSelect) control.input.config.hideConfig(); + }).tooltip(item.localizedName).group(group).get(); + button.changed(() -> consumer.get(button.isChecked() ? item : null)); + button.getStyle().imageUp = new TextureRegionDrawable(item.uiIcon); + button.update(() -> button.setChecked(holder.get() == item)); + + if(i++ % columns == (columns - 1)){ + cont.row(); + rowCount++; + } } - } + }; - //add extra blank spaces so it looks nice - if(i % 4 != 0){ - int remaining = 4 - (i % 4); - for(int j = 0; j < remaining; j++){ - cont.image(Styles.black6); - } + rebuild.run(); + + Table main = new Table().background(Styles.black6); + if(rowCount > rows * 1.5f){ + search = main.field(null, text -> rebuild.run()).width(40 * columns).padBottom(4).left().growX().get(); + search.setMessageText("@players.search"); + main.row(); } ScrollPane pane = new ScrollPane(cont, Styles.smallPane); @@ -71,6 +101,7 @@ public class ItemSelection{ } pane.setOverscroll(false, false); - table.add(pane).maxHeight(Scl.scl(40 * 5)); + main.add(pane).maxHeight(40 * rows); + table.top().add(main); } -} +} \ No newline at end of file diff --git a/core/src/mindustry/world/blocks/distribution/Sorter.java b/core/src/mindustry/world/blocks/distribution/Sorter.java index 5e19c65966..b37195173c 100644 --- a/core/src/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/mindustry/world/blocks/distribution/Sorter.java @@ -126,7 +126,7 @@ public class Sorter extends Block{ @Override public void buildConfiguration(Table table){ - ItemSelection.buildTable(Sorter.this, table, content.items(), () -> sortItem, this::configure); + ItemSelection.buildTable(Sorter.this, table, content.items(), () -> sortItem, this::configure, selectionRows, selectionColumns); } @Override @@ -155,4 +155,4 @@ public class Sorter extends Block{ } } } -} +} \ No newline at end of file diff --git a/core/src/mindustry/world/blocks/payloads/Constructor.java b/core/src/mindustry/world/blocks/payloads/Constructor.java index f27197e72e..bc13018691 100644 --- a/core/src/mindustry/world/blocks/payloads/Constructor.java +++ b/core/src/mindustry/world/blocks/payloads/Constructor.java @@ -58,7 +58,7 @@ public class Constructor extends BlockProducer{ @Override public void buildConfiguration(Table table){ - ItemSelection.buildTable(Constructor.this, table, filter.isEmpty() ? content.blocks().select(Constructor.this::canProduce) : filter, () -> recipe, this::configure); + ItemSelection.buildTable(Constructor.this, table, filter.isEmpty() ? content.blocks().select(Constructor.this::canProduce) : filter, () -> recipe, this::configure, selectionRows, selectionColumns); } @Override @@ -91,4 +91,4 @@ public class Constructor extends BlockProducer{ recipe = Vars.content.block(read.s()); } } -} +} \ No newline at end of file diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index 9a2012fc5e..b6f6de2380 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -29,6 +29,7 @@ public class PayloadSource extends PayloadBlock{ hasPower = false; rotate = true; configurable = true; + selectionRows = selectionColumns = 8; //make sure to display large units. clipSize = 120; noUpdateDisabled = true; @@ -103,7 +104,7 @@ public class PayloadSource extends PayloadBlock{ ItemSelection.buildTable(PayloadSource.this, table, content.blocks().select(PayloadSource.this::canProduce).as() .add(content.units().select(PayloadSource.this::canProduce).as()), - () -> (UnlockableContent)config(), this::configure); + () -> (UnlockableContent)config(), this::configure, selectionRows, selectionColumns); } @Override diff --git a/core/src/mindustry/world/blocks/sandbox/ItemSource.java b/core/src/mindustry/world/blocks/sandbox/ItemSource.java index c0d1aef175..06afbd3e66 100644 --- a/core/src/mindustry/world/blocks/sandbox/ItemSource.java +++ b/core/src/mindustry/world/blocks/sandbox/ItemSource.java @@ -89,7 +89,7 @@ public class ItemSource extends Block{ @Override public void buildConfiguration(Table table){ - ItemSelection.buildTable(ItemSource.this, table, content.items(), () -> outputItem, this::configure); + ItemSelection.buildTable(ItemSource.this, table, content.items(), () -> outputItem, this::configure, selectionRows, selectionColumns); } @Override @@ -114,4 +114,4 @@ public class ItemSource extends Block{ outputItem = content.item(read.s()); } } -} +} \ No newline at end of file diff --git a/core/src/mindustry/world/blocks/sandbox/LiquidSource.java b/core/src/mindustry/world/blocks/sandbox/LiquidSource.java index be5cf94619..56def6fd71 100644 --- a/core/src/mindustry/world/blocks/sandbox/LiquidSource.java +++ b/core/src/mindustry/world/blocks/sandbox/LiquidSource.java @@ -85,7 +85,7 @@ public class LiquidSource extends Block{ @Override public void buildConfiguration(Table table){ - ItemSelection.buildTable(LiquidSource.this, table, content.liquids(), () -> source, this::configure); + ItemSelection.buildTable(LiquidSource.this, table, content.liquids(), () -> source, this::configure, selectionRows, selectionColumns); } @Override @@ -111,4 +111,4 @@ public class LiquidSource extends Block{ source = id == -1 ? null : content.liquid(id); } } -} +} \ No newline at end of file diff --git a/core/src/mindustry/world/blocks/storage/Unloader.java b/core/src/mindustry/world/blocks/storage/Unloader.java index 2a4553b2ed..85b0ed8667 100644 --- a/core/src/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/mindustry/world/blocks/storage/Unloader.java @@ -224,7 +224,7 @@ public class Unloader extends Block{ @Override public void buildConfiguration(Table table){ - ItemSelection.buildTable(Unloader.this, table, content.items(), () -> sortItem, this::configure); + ItemSelection.buildTable(Unloader.this, table, content.items(), () -> sortItem, this::configure, selectionRows, selectionColumns); } @Override @@ -250,4 +250,4 @@ public class Unloader extends Block{ sortItem = id == -1 ? null : content.item(id); } } -} +} \ No newline at end of file diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java index 755633b8b6..bfbda241c5 100644 --- a/core/src/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/mindustry/world/blocks/units/UnitFactory.java @@ -211,7 +211,7 @@ public class UnitFactory extends UnitBlock{ Seq units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned()); if(units.any()){ - ItemSelection.buildTable(UnitFactory.this, table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit))); + ItemSelection.buildTable(UnitFactory.this, table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)), selectionRows, selectionColumns); }else{ table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray)); } @@ -357,4 +357,4 @@ public class UnitFactory extends UnitBlock{ } } } -} +} \ No newline at end of file