Better item selection UI

This commit is contained in:
Anuken
2022-09-01 17:49:29 -04:00
parent 61295bc89c
commit b854b0ca22
11 changed files with 79 additions and 41 deletions

View File

@@ -36,6 +36,8 @@ public abstract class UnlockableContent extends MappableContent{
public boolean generateIcons = true; public boolean generateIcons = true;
/** Special logic icon ID. */ /** Special logic icon ID. */
public int iconId = 0; 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. */ /** Icon of the content to use in UI. */
public TextureRegion uiIcon; public TextureRegion uiIcon;
/** Icon of the full content. Unscaled.*/ /** Icon of the full content. Unscaled.*/

View File

@@ -423,6 +423,7 @@ public class UnitType extends UnlockableContent{
super(name); super(name);
constructor = EntityMapping.map(this.name); constructor = EntityMapping.map(this.name);
selectionSize = 30f;
} }
public UnitController createController(Unit unit){ public UnitController createController(Unit unit){

View File

@@ -211,6 +211,8 @@ public class Block extends UnlockableContent implements Senseable{
public boolean commandable; public boolean commandable;
/** If true, the building inventory can be shown with the config. */ /** If true, the building inventory can be shown with the config. */
public boolean allowConfigInventory = true; 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. */ /** If true, this block can be configured by logic. */
public boolean logicConfigurable = false; public boolean logicConfigurable = false;
/** Whether this block consumes touchDown events when tapped. */ /** Whether this block consumes touchDown events when tapped. */
@@ -365,6 +367,7 @@ public class Block extends UnlockableContent implements Senseable{
public Block(String name){ public Block(String name){
super(name); super(name);
initBuilding(); initBuilding();
selectionSize = 28f;
} }
public void drawBase(Tile tile){ public void drawBase(Tile tile){

View File

@@ -1,6 +1,7 @@
package mindustry.world.blocks; package mindustry.world.blocks;
import arc.func.*; import arc.func.*;
import arc.math.*;
import arc.scene.style.*; import arc.scene.style.*;
import arc.scene.ui.*; import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
@@ -15,49 +16,78 @@ import mindustry.world.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class ItemSelection{ public class ItemSelection{
private static TextField search;
private static int rowCount;
public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){ public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){
buildTable(table, items, holder, consumer, true); buildTable(table, items, holder, consumer, true);
} }
public static <T extends UnlockableContent> void buildTable(Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){
buildTable(block, table, items, holder, consumer, true);
}
public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){ public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){
buildTable(null, table, items, holder, consumer, closeSelect); buildTable(null, table, items, holder, consumer, closeSelect, 5, 4);
} }
public static <T extends UnlockableContent> void buildTable(@Nullable Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){
public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, int columns){
buildTable(null, table, items, holder, consumer, true, 5, columns);
}
public static <T extends UnlockableContent> void buildTable(Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){
buildTable(block, table, items, holder, consumer, true, 5, 4);
}
public static <T extends UnlockableContent> void buildTable(Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){
buildTable(block, table, items, holder, consumer, closeSelect, 5 ,4);
}
public static <T extends UnlockableContent> void buildTable(Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, int rows, int columns){
buildTable(block, table, items, holder, consumer, true, rows, columns);
}
public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, int rows, int columns){
buildTable(null, table, items, holder, consumer, true, rows, columns);
}
public static <T extends UnlockableContent> void buildTable(@Nullable Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect, int rows, int columns){
ButtonGroup<ImageButton> group = new ButtonGroup<>(); ButtonGroup<ImageButton> group = new ButtonGroup<>();
group.setMinCheckCount(0); group.setMinCheckCount(0);
Table cont = new Table(); Table cont = new Table().top();
cont.defaults().size(40); cont.defaults().size(40);
int i = 0; if(search != null) search.clearText();
for(T item : items){ Runnable rebuild = () -> {
if(!item.unlockedNow() || (item instanceof Item checkVisible && state.rules.hiddenBuildItems.contains(checkVisible)) || item.isHidden()) continue; group.clear();
cont.clearChildren();
ImageButton button = cont.button(Tex.whiteui, Styles.clearTogglei, 24, () -> { var text = search != null ? search.getText() : "";
if(closeSelect) control.input.config.hideConfig(); int i = 0;
}).group(group).tooltip(item.localizedName).get(); rowCount = 0;
button.changed(() -> consumer.get(button.isChecked() ? item : null));
button.getStyle().imageUp = new TextureRegionDrawable(item.uiIcon);
button.update(() -> button.setChecked(holder.get() == item));
if(i++ % 4 == 3){ Seq<T> list = items.select(u -> (text.isEmpty() || u.localizedName.toLowerCase().contains(text.toLowerCase())));
cont.row(); 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 rebuild.run();
if(i % 4 != 0){
int remaining = 4 - (i % 4); Table main = new Table().background(Styles.black6);
for(int j = 0; j < remaining; j++){ if(rowCount > rows * 1.5f){
cont.image(Styles.black6); 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); ScrollPane pane = new ScrollPane(cont, Styles.smallPane);
@@ -71,6 +101,7 @@ public class ItemSelection{
} }
pane.setOverscroll(false, false); pane.setOverscroll(false, false);
table.add(pane).maxHeight(Scl.scl(40 * 5)); main.add(pane).maxHeight(40 * rows);
table.top().add(main);
} }
} }

View File

@@ -126,7 +126,7 @@ public class Sorter extends Block{
@Override @Override
public void buildConfiguration(Table table){ 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 @Override
@@ -155,4 +155,4 @@ public class Sorter extends Block{
} }
} }
} }
} }

View File

@@ -58,7 +58,7 @@ public class Constructor extends BlockProducer{
@Override @Override
public void buildConfiguration(Table table){ 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 @Override
@@ -91,4 +91,4 @@ public class Constructor extends BlockProducer{
recipe = Vars.content.block(read.s()); recipe = Vars.content.block(read.s());
} }
} }
} }

View File

@@ -29,6 +29,7 @@ public class PayloadSource extends PayloadBlock{
hasPower = false; hasPower = false;
rotate = true; rotate = true;
configurable = true; configurable = true;
selectionRows = selectionColumns = 8;
//make sure to display large units. //make sure to display large units.
clipSize = 120; clipSize = 120;
noUpdateDisabled = true; noUpdateDisabled = true;
@@ -103,7 +104,7 @@ public class PayloadSource extends PayloadBlock{
ItemSelection.buildTable(PayloadSource.this, table, ItemSelection.buildTable(PayloadSource.this, table,
content.blocks().select(PayloadSource.this::canProduce).<UnlockableContent>as() content.blocks().select(PayloadSource.this::canProduce).<UnlockableContent>as()
.add(content.units().select(PayloadSource.this::canProduce).as()), .add(content.units().select(PayloadSource.this::canProduce).as()),
() -> (UnlockableContent)config(), this::configure); () -> (UnlockableContent)config(), this::configure, selectionRows, selectionColumns);
} }
@Override @Override

View File

@@ -89,7 +89,7 @@ public class ItemSource extends Block{
@Override @Override
public void buildConfiguration(Table table){ 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 @Override
@@ -114,4 +114,4 @@ public class ItemSource extends Block{
outputItem = content.item(read.s()); outputItem = content.item(read.s());
} }
} }
} }

View File

@@ -85,7 +85,7 @@ public class LiquidSource extends Block{
@Override @Override
public void buildConfiguration(Table table){ 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 @Override
@@ -111,4 +111,4 @@ public class LiquidSource extends Block{
source = id == -1 ? null : content.liquid(id); source = id == -1 ? null : content.liquid(id);
} }
} }
} }

View File

@@ -224,7 +224,7 @@ public class Unloader extends Block{
@Override @Override
public void buildConfiguration(Table table){ 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 @Override
@@ -250,4 +250,4 @@ public class Unloader extends Block{
sortItem = id == -1 ? null : content.item(id); sortItem = id == -1 ? null : content.item(id);
} }
} }
} }

View File

@@ -211,7 +211,7 @@ public class UnitFactory extends UnitBlock{
Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned()); Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned());
if(units.any()){ 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{ }else{
table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray)); table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray));
} }
@@ -357,4 +357,4 @@ public class UnitFactory extends UnitBlock{
} }
} }
} }
} }