Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Item Selection UI #5921

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/src/mindustry/ctype/UnlockableContent.java
Expand Up @@ -31,6 +31,8 @@ public abstract class UnlockableContent extends MappableContent{
public boolean hideDetails = 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.*/
Expand Down
1 change: 1 addition & 0 deletions core/src/mindustry/type/UnitType.java
Expand Up @@ -148,6 +148,7 @@ public UnitType(String name){
super(name);

constructor = EntityMapping.map(this.name);
selectionSize = 36f;
}

public UnitController createController(){
Expand Down
3 changes: 3 additions & 0 deletions core/src/mindustry/world/Block.java
Expand Up @@ -167,6 +167,8 @@ public class Block extends UnlockableContent{
public boolean configurable;
/** 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. */
Expand Down Expand Up @@ -290,6 +292,7 @@ public class Block extends UnlockableContent{
public Block(String name){
super(name);
initBuilding();
selectionSize = 36f;
}

public void drawBase(Tile tile){
Expand Down
90 changes: 65 additions & 25 deletions core/src/mindustry/world/blocks/ItemSelection.java
@@ -1,6 +1,8 @@
package mindustry.world.blocks;

import arc.*;
import arc.func.*;
import arc.math.*;
import arc.scene.style.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
Expand All @@ -14,49 +16,86 @@
import static mindustry.Vars.*;

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){
buildTable(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){
buildTable(null, table, items, holder, consumer, closeSelect, 5, 4);
}

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);
buildTable(block, table, items, holder, consumer, true, 5, 4);
}

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);
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(@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 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<>();
group.setMinCheckCount(0);
Table cont = new Table();
Table cont = new Table().top();
cont.defaults().size(40);

int i = 0;
if(search != null) search.clearText();

Runnable rebuild = () -> {
group.clear();
cont.clearChildren();

for(T item : items){
if(!item.unlockedNow()) continue;
var text = search != null ? search.getText() : "";
int i = 0;
rowCount = 0;

ImageButton button = cont.button(Tex.whiteui, Styles.clearToggleTransi, 24, () -> {
if(closeSelect) control.input.frag.config.hideConfig();
}).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));
Seq<T> list = items.select(u -> (text.isEmpty() || u.localizedName.toLowerCase().contains(text.toLowerCase())));
for(T item : list){
if(!item.unlockedNow()) continue;

if(i++ % 4 == 3){
cont.row();
ImageButton button = cont.button(Tex.whiteui, Styles.clearTogglePartiali, Mathf.clamp(item.selectionSize, 0f, 40f), () -> {
if(closeSelect) control.input.frag.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);
//add extra blank spaces so it looks nice
if(i % columns != 0){
int remaining = columns - (i % columns);
for(int j = 0; j < remaining; j++){
cont.image(Styles.none);
}
}
};

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);
Expand All @@ -70,6 +109,7 @@ public static <T extends UnlockableContent> void buildTable(@Nullable Block bloc
}

pane.setOverscroll(false, false);
table.add(pane).maxHeight(Scl.scl(40 * 5));
main.add(pane).maxHeight(40 * rows);
table.top().add(main);
}
}
}
4 changes: 2 additions & 2 deletions core/src/mindustry/world/blocks/distribution/Sorter.java
Expand Up @@ -124,7 +124,7 @@ public Building getTileTarget(Item item, Building source, boolean flip){

@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
Expand Down Expand Up @@ -164,4 +164,4 @@ public void read(Reads read, byte revision){
}
}
}
}
}
4 changes: 2 additions & 2 deletions core/src/mindustry/world/blocks/payloads/Constructor.java
Expand Up @@ -55,7 +55,7 @@ public class ConstructorBuild extends BlockProducerBuild{

@Override
public void buildConfiguration(Table table){
ItemSelection.buildTable(Constructor.this, table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure);
ItemSelection.buildTable(Constructor.this, table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure, selectionRows, selectionColumns);
}

@Override
Expand Down Expand Up @@ -99,4 +99,4 @@ public void read(Reads read, byte revision){
recipe = Vars.content.block(read.s());
}
}
}
}
3 changes: 2 additions & 1 deletion core/src/mindustry/world/blocks/payloads/PayloadSource.java
Expand Up @@ -28,6 +28,7 @@ public PayloadSource(String name){
hasPower = false;
rotate = true;
configurable = true;
selectionRows = selectionColumns = 8;
//make sure to display large units.
clipSize = 120;
noUpdateDisabled = true;
Expand Down Expand Up @@ -88,7 +89,7 @@ public void buildConfiguration(Table table){
ItemSelection.buildTable(PayloadSource.this, table,
content.blocks().select(PayloadSource.this::canProduce).<UnlockableContent>as()
.and(content.units().select(PayloadSource.this::canProduce).as()),
() -> (UnlockableContent)config(), this::configure);
() -> (UnlockableContent)config(), this::configure, selectionRows, selectionColumns);
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions core/src/mindustry/world/blocks/sandbox/ItemSource.java
Expand Up @@ -73,7 +73,7 @@ public void updateTile(){

@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
Expand Down Expand Up @@ -109,4 +109,4 @@ public void read(Reads read, byte revision){
outputItem = content.item(read.s());
}
}
}
}
4 changes: 2 additions & 2 deletions core/src/mindustry/world/blocks/sandbox/LiquidSource.java
Expand Up @@ -73,7 +73,7 @@ public void draw(){

@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
Expand Down Expand Up @@ -110,4 +110,4 @@ public void read(Reads read, byte revision){
source = id == -1 ? null : content.liquid(id);
}
}
}
}
4 changes: 2 additions & 2 deletions core/src/mindustry/world/blocks/storage/Unloader.java
Expand Up @@ -194,7 +194,7 @@ public void draw(){

@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
Expand Down Expand Up @@ -231,4 +231,4 @@ public void read(Reads read, byte revision){
sortItem = id == -1 ? null : content.items().get(id);
}
}
}
}
4 changes: 2 additions & 2 deletions core/src/mindustry/world/blocks/units/UnitFactory.java
Expand Up @@ -160,7 +160,7 @@ public void buildConfiguration(Table table){
Seq<UnitType> 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));
}
Expand Down Expand Up @@ -305,4 +305,4 @@ public void read(Reads read, byte revision){
currentPlan = read.s();
}
}
}
}