This commit is contained in:
Anuken
2019-03-10 22:51:04 -04:00
880 changed files with 19481 additions and 12588 deletions

View File

@@ -32,8 +32,10 @@ public class Bar extends Element{
public Bar(Supplier<String> name, Supplier<Color> color, FloatProvider fraction){
this.fraction = fraction;
lastValue = value = Mathf.clamp(fraction.get());
update(() -> {
this.name = name.get();
this.blinkColor.set(color.get());
setColor(color.get());
});
}
@@ -45,13 +47,14 @@ public class Bar extends Element{
@Override
public void draw(){
if(!Mathf.isEqual(lastValue, fraction.get())){
float computed = Mathf.clamp(fraction.get());
if(!Mathf.isEqual(lastValue, computed)){
blink = 1f;
lastValue = fraction.get();
lastValue = computed;
}
blink = Mathf.lerpDelta(blink, 0f, 0.2f);
value = Mathf.lerpDelta(value, fraction.get(), 0.15f);
value = Mathf.lerpDelta(value, computed, 0.15f);
Draw.colorl(0.1f);
Draw.drawable("bar", x, y, width, height);
@@ -75,6 +78,7 @@ public class Bar extends Element{
GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new);
lay.setText(font, name);
font.setColor(Color.WHITE);
font.draw(name, x + width/2f - lay.width/2f, y + height/2f + lay.height/2f + 1);
Pools.free(lay);

View File

@@ -2,7 +2,7 @@ package io.anuke.mindustry.ui;
import io.anuke.arc.graphics.Texture;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Lines;
import io.anuke.arc.scene.ui.Image;
@@ -36,7 +36,7 @@ public class BorderImage extends Image{
float scaleX = getScaleX();
float scaleY = getScaleY();
Draw.color(Palette.accent);
Draw.color(Pal.accent);
Lines.stroke(Unit.dp.scl(thickness));
Lines.rect(x + imageX, y + imageY, imageWidth * scaleX, imageHeight * scaleY);
Draw.reset();

View File

@@ -5,8 +5,8 @@ import io.anuke.arc.collection.OrderedMap;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.util.Strings;
import io.anuke.mindustry.entities.units.UnitType;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.type.UnitType;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Liquid;
import io.anuke.mindustry.type.Mech;
@@ -25,7 +25,7 @@ public class ContentDisplay{
int size = 8 * 6;
title.addImage(block.icon(Icon.large)).size(size);
title.add("[accent]" + block.formalName).padLeft(5);
title.add("[accent]" + block.localizedName).padLeft(5);
});
table.row();
@@ -34,8 +34,8 @@ public class ContentDisplay{
table.row();
if(block.fullDescription != null){
table.add(block.fullDescription).padLeft(5).padRight(5).width(400f).wrap().fillX();
if(block.description != null){
table.add(block.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.row();
table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(8).padLeft(0).padRight(0).fillX();
@@ -49,7 +49,7 @@ public class ContentDisplay{
if(map.size == 0) continue;
table.add("$category." + cat.name()).color(Palette.accent).fillX();
table.add("$category." + cat.name()).color(Pal.accent).fillX();
table.row();
for(BlockStat stat : map.keys()){
@@ -86,13 +86,11 @@ public class ContentDisplay{
table.left().defaults().fillX();
table.add(Core.bundle.format("item.explosiveness", (int) (item.explosiveness * 100 * 2f)));
table.add(Core.bundle.format("item.explosiveness", (int) (item.explosiveness * 100)));
table.row();
table.add(Core.bundle.format("item.flammability", (int) (item.flammability * 100 * 2f)));
table.add(Core.bundle.format("item.flammability", (int) (item.flammability * 100)));
table.row();
table.add(Core.bundle.format("item.radioactivity", (int) (item.radioactivity * 100 * 2f)));
table.row();
table.add(Core.bundle.format("item.fluxiness", (int) (item.fluxiness * 100 * 2f)));
table.add(Core.bundle.format("item.radioactivity", (int) (item.radioactivity * 100)));
table.row();
}
@@ -119,9 +117,9 @@ public class ContentDisplay{
table.left().defaults().fillX();
table.add(Core.bundle.format("item.explosiveness", (int) (liquid.explosiveness * 100 * 2f)));
table.add(Core.bundle.format("item.explosiveness", (int) (liquid.explosiveness * 100)));
table.row();
table.add(Core.bundle.format("item.flammability", (int) (liquid.flammability * 100 * 2f)));
table.add(Core.bundle.format("item.flammability", (int) (liquid.flammability * 100)));
table.row();
table.add(Core.bundle.format("liquid.heatcapacity", (int) (liquid.heatCapacity * 100)));
table.row();
@@ -161,7 +159,7 @@ public class ContentDisplay{
table.add(Core.bundle.format("mech.ability", Core.bundle.get("mech." + mech.name + ".ability")));
table.row();
}
table.add(Core.bundle.format("mech.armor", mech.armor));
table.add(Core.bundle.format("mech.health", (int)mech.health));
table.row();
table.add(Core.bundle.format("mech.itemcapacity", mech.itemCapacity));
table.row();

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.ui;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.mindustry.type.Item.Icon;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.arc.function.Supplier;
import io.anuke.arc.scene.ui.Image;
@@ -9,6 +10,14 @@ import io.anuke.arc.scene.ui.layout.Table;
public class ItemImage extends Stack{
public ItemImage(TextureRegion region, int amount){
Table t = new Table().left().bottom();
t.add(amount + "").name("item-label");
add(new Image(region));
add(t);
}
public ItemImage(TextureRegion region, Supplier<CharSequence> text){
Table t = new Table().left().bottom();
t.label(text).name("item-label");
@@ -18,7 +27,7 @@ public class ItemImage extends Stack{
}
public ItemImage(ItemStack stack){
add(new Image(stack.item.region));
add(new Image(stack.item.icon(Icon.medium)));
if(stack.amount != 0){
Table t = new Table().left().bottom();

View File

@@ -0,0 +1,41 @@
package io.anuke.mindustry.ui;
import io.anuke.arc.collection.ObjectIntMap;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Item.Icon;
import io.anuke.mindustry.type.ItemType;
import java.text.NumberFormat;
import java.util.Locale;
import static io.anuke.mindustry.Vars.content;
import static io.anuke.mindustry.Vars.data;
public class ItemsDisplay extends Table{
private static final NumberFormat format = NumberFormat.getNumberInstance(Locale.getDefault());
public ItemsDisplay(){
rebuild();
}
public void rebuild(){
clear();
top().left();
margin(0);
table("flat", t -> {
t.margin(10).marginLeft(15).marginTop(15f);
ObjectIntMap<Item> items = data.items();
for(Item item : content.items()){
if(item.type == ItemType.material && data.isUnlocked(item)){
t.label(() -> format.format(items.get(item, 0))).left();
t.addImage(item.icon(Icon.medium)).size(8*3).padLeft(4).padRight(4);
t.add(item.localizedName()).color(Color.LIGHT_GRAY).left();
t.row();
}
}
});
}
}

View File

@@ -8,7 +8,7 @@ public class Links{
private static void createLinks(){
links = new LinkEntry[]{
new LinkEntry("discord", "https://discord.gg/BKADYds", Color.valueOf("7289da")),
new LinkEntry("discord", "https://discord.gg/mindustry", Color.valueOf("7289da")),
new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Color.valueOf("026aa7")),
new LinkEntry("wiki", "http://mindustry.wikia.com/wiki/Mindustry_Wiki", Color.valueOf("0f142f")),
new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Color.valueOf("fa5c5c")),

View File

@@ -0,0 +1,31 @@
package io.anuke.mindustry.ui;
import io.anuke.arc.collection.Array;
import io.anuke.arc.scene.ui.layout.Stack;
import io.anuke.arc.util.Time;
public class MultiReqImage extends Stack{
private Array<ReqImage> displays = new Array<>();
private float time;
public void add(ReqImage display){
displays.add(display);
super.add(display);
}
@Override
public void act(float delta){
super.act(delta);
time += Time.delta() / 60f;
displays.each(req -> req.visible(false));
ReqImage valid = displays.find(ReqImage::valid);
if(valid != null){
valid.visible(true);
}else{
displays.get((int)(time) % displays.size).visible(true);
}
}
}

View File

@@ -0,0 +1,42 @@
package io.anuke.mindustry.ui;
import io.anuke.arc.function.BooleanProvider;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Lines;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.scene.Element;
import io.anuke.arc.scene.ui.Image;
import io.anuke.arc.scene.ui.layout.Stack;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.mindustry.graphics.Pal;
public class ReqImage extends Stack{
private final BooleanProvider valid;
public ReqImage(Element image, BooleanProvider valid){
this.valid = valid;
add(image);
add(new Element(){
{
visible(() -> !valid.get());
}
@Override
public void draw(){
Lines.stroke(Unit.dp.scl(2f), Pal.removeBack);
Lines.line(x, y - 2f + height, x + width, y - 2f);
Draw.color(Pal.remove);
Lines.line(x, y + height, x + width, y);
Draw.reset();
}
});
}
public ReqImage(TextureRegion region, BooleanProvider valid){
this(new Image(region), valid);
}
public boolean valid(){
return valid.get();
}
}

View File

@@ -292,12 +292,12 @@ public class TreeLayout{
center, towardsRoot, awayFromRoot
}
public static class TreeNode{
public static class TreeNode<T extends TreeNode>{
public float width, height, x, y;
//should be initialized by user
public TreeNode[] children;
public TreeNode parent;
public T[] children;
public T parent;
private float mode, prelim, change, shift;
private int number = -1;

View File

@@ -4,7 +4,7 @@ import io.anuke.arc.Core;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.ObjectSet;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.io.Contributors;
import io.anuke.mindustry.io.Contributors.Contributor;
import io.anuke.mindustry.ui.Links;
@@ -103,7 +103,7 @@ public class AboutDialog extends FloatingDialog{
dialog.cont.add("$credits.text");
dialog.cont.row();
if(!contributors.isEmpty()){
dialog.cont.addImage("blank").color(Palette.accent).fillX().height(3f).pad(3f);
dialog.cont.addImage("blank").color(Pal.accent).fillX().height(3f).pad(3f);
dialog.cont.row();
dialog.cont.add("$contributors");
dialog.cont.row();

View File

@@ -5,7 +5,7 @@ import io.anuke.arc.input.KeyCode;
import io.anuke.arc.scene.ui.Image;
import io.anuke.arc.scene.ui.KeybindDialog;
import io.anuke.arc.util.Align;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
public class ControlsDialog extends KeybindDialog{
@@ -16,7 +16,7 @@ public class ControlsDialog extends KeybindDialog{
title.setAlignment(Align.center);
titleTable.row();
titleTable.add(new Image("white"))
.growX().height(3f).pad(4f).get().setColor(Palette.accent);
.growX().height(3f).pad(4f).get().setColor(Pal.accent);
}
@Override

View File

@@ -20,6 +20,7 @@ import static io.anuke.mindustry.Vars.*;
public class CustomGameDialog extends FloatingDialog{
Difficulty difficulty = Difficulty.normal;
RulePreset lastPreset = RulePreset.survival;
public CustomGameDialog(){
super("$customgame");
@@ -30,6 +31,7 @@ public class CustomGameDialog extends FloatingDialog{
}
void setup(){
state.rules = lastPreset.get();
cont.clear();
Table maps = new Table();
@@ -48,10 +50,10 @@ public class CustomGameDialog extends FloatingDialog{
modes.marginBottom(5);
for(RulePreset mode : RulePreset.values()){
//todo fix presets
modes.addButton(mode.toString(), "toggle", () -> state.rules = mode.get())/*
.update(b -> b.setChecked(state.rules == mode))*/.group(group).size(140f, 54f);
modes.addButton(mode.toString(), "toggle", () -> {
state.rules = mode.get();
lastPreset = mode;
}).update(b -> b.setChecked(lastPreset == mode)).group(group).size(140f, 54f);
if(i++ % 2 == 1) modes.row();
}
selmode.add(modes);
@@ -112,7 +114,7 @@ public class CustomGameDialog extends FloatingDialog{
image.clicked(() -> {
hide();
control.playMap(map);
control.playMap(map, lastPreset.get());
});
maps.add(image);
@@ -120,14 +122,6 @@ public class CustomGameDialog extends FloatingDialog{
i++;
}
/*
ImageButton gen = maps.addImageButton("icon-editor", "clear", 16*4, () -> {
hide();
world.generator.playRandomMap();
}).growY().get();
gen.row();
gen.add("$map.random");*/
if(world.maps.all().size == 0){
maps.add("$maps.none").pad(50);
}
@@ -136,7 +130,7 @@ public class CustomGameDialog extends FloatingDialog{
}
private void displayGameModeHelp(){
FloatingDialog d = new FloatingDialog(Core.bundle.get("mode.text.help.title"));
FloatingDialog d = new FloatingDialog(Core.bundle.get("mode.help.title"));
d.setFillParent(false);
Table table = new Table();
table.defaults().pad(1f);

View File

@@ -1,24 +1,23 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.collection.Array;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.game.Content;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.type.ContentType;
import io.anuke.arc.scene.event.HandCursorListener;
import io.anuke.arc.scene.ui.Image;
import io.anuke.arc.scene.ui.ScrollPane;
import io.anuke.arc.scene.ui.Tooltip;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.utils.UIUtils;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.Content;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.ContentType;
public class DatabaseDialog extends FloatingDialog{
public DatabaseDialog(){
super("database");
super("$database");
shouldPause = true;
addCloseButton();
@@ -38,31 +37,29 @@ public class DatabaseDialog extends FloatingDialog{
for(int j = 0; j < allContent.length; j ++){
ContentType type = ContentType.values()[j];
Array<Content> array = allContent[j];
if(array.size == 0 || !(array.first() instanceof UnlockableContent)) continue;
Array<Content> array = allContent[j].select(c -> c instanceof UnlockableContent && !((UnlockableContent)c).isHidden());
if(array.size == 0) continue;
table.add("$content." + type.name() + ".name").growX().left().color(Palette.accent);
table.add("$content." + type.name() + ".name").growX().left().color(Pal.accent);
table.row();
table.addImage("white").growX().pad(5).padLeft(0).padRight(0).height(3).color(Palette.accent);
table.addImage("white").growX().pad(5).padLeft(0).padRight(0).height(3).color(Pal.accent);
table.row();
table.table(list -> {
list.left();
int maxWidth = UIUtils.portrait() ? 7 : 13;
int size = 8 * 6;
int size = 8 * 4;
int count = 0;
for(int i = 0; i < array.size; i++){
UnlockableContent unlock = (UnlockableContent) array.get(i);
if(unlock.isHidden()) continue;
Image image = data.isUnlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-tree-locked");
Image image = unlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-tree-locked");
image.addListener(new HandCursorListener());
list.add(image).size(size).pad(3);
if(data.isUnlocked(unlock)){
if(unlocked(unlock)){
image.clicked(() -> Vars.ui.content.show(unlock));
image.addListener(new Tooltip<>(new Table("button"){{
add(unlock.localizedName());
@@ -79,4 +76,8 @@ public class DatabaseDialog extends FloatingDialog{
cont.add(pane);
}
boolean unlocked(UnlockableContent content){
return (!Vars.world.isZone() && !Vars.state.is(State.menu)) || content.unlocked();
}
}

View File

@@ -1,198 +1,102 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core;
import io.anuke.arc.collection.ObjectIntMap;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.scene.ui.ScrollPane;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.ObjectSet;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Lines;
import io.anuke.arc.scene.Group;
import io.anuke.arc.scene.ui.TextButton;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.util.Align;
import io.anuke.arc.util.Structs;
import io.anuke.mindustry.content.Zones;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.Saves.SaveSlot;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.io.SaveIO.SaveException;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.ItemType;
import io.anuke.mindustry.type.Zone;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Block.Icon;
import io.anuke.mindustry.ui.ItemsDisplay;
import io.anuke.mindustry.ui.TreeLayout;
import io.anuke.mindustry.ui.TreeLayout.TreeNode;
import static io.anuke.mindustry.Vars.*;
public class DeployDialog extends FloatingDialog{
private final float nodeSize = Unit.dp.scl(210f);
private ObjectSet<ZoneNode> nodes = new ObjectSet<>();
private ZoneInfoDialog info = new ZoneInfoDialog();
public DeployDialog(){
super("$play");
super("");
shown(this::setup);
}
ZoneNode root = new ZoneNode(Zones.groundZero, null);
void setup(){
buttons.clear();
cont.clear();
TreeLayout layout = new TreeLayout();
layout.gapBetweenLevels = layout.gapBetweenNodes = Unit.dp.scl(50f);
layout.layout(root);
addCloseButton();
buttons.addImageTextButton("$techtree", "icon-tree", 16 * 2, () -> ui.tech.show()).size(230f, 64f);
cont.stack(new Table(){{
top().left().margin(10);
shown(this::setup);
}
ObjectIntMap<Item> items = data.items();
for(Item item : content.items()){
if(item.type == ItemType.material && data.isUnlocked(item)){
label(() -> items.get(item, 0) + "").left();
addImage(item.region).size(8*4).pad(4);
add("[LIGHT_GRAY]" + item.localizedName()).left();
row();
}
}
public void setup(){
cont.clear();
titleTable.remove();
margin(0f).marginBottom(8);
}}, new ScrollPane(new Table(){{
if(!Core.settings.getBool("zone-info", false)){
Core.app.post(() -> ui.showInfoText("TEMPORARY GUIDE ON HOW TO PLAY ZONES", "- deploy to zones by selecting them here\n- most zones require items to deploy\n- once you survive a set amount of waves, you can launch all the resources in your core\n- use these items to research in the tech tree or uncover new zones"));
if(control.saves.getZoneSlot() == null){
Core.settings.put("zone-info", true);
Core.settings.save();
}
int i = 0;
for(Zone zone : content.zones()){
table(t -> {
TextButton button = t.addButton("", () -> {
if(!data.isUnlocked(zone)){
data.removeItems(zone.itemRequirements);
data.unlockContent(zone);
setup();
}else{
data.removeItems(zone.deployCost);
hide();
world.playZone(zone);
}
}).size(250f).disabled(b -> !canUnlock(zone)).get();
cont.stack(control.saves.getZoneSlot() == null ? new View() : new Table(){{
SaveSlot slot = control.saves.getZoneSlot();
button.clearChildren();
TextButton[] b = {null};
if(data.isUnlocked(zone)){
button.table(title -> {
title.addImage("icon-zone").padRight(3);
title.add(zone.localizedName());
});
button.row();
TextButton button = addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> {
if(b[0].childrenPressed()) return;
if(data.getWaveScore(zone) > 0){
button.add(Core.bundle.format("bestwave", data.getWaveScore(zone)));
}
button.row();
button.add("$launch").color(Color.LIGHT_GRAY).pad(4);
button.row();
button.table(req -> {
for(ItemStack stack : zone.deployCost){
req.addImage(stack.item.region).size(8 * 3);
req.add(stack.amount + "").left();
}
}).pad(3).growX();
}else{
button.addImage("icon-zone-locked");
button.row();
button.add("$locked").padBottom(6);
if(!hidden(zone)){
button.row();
button.table(req -> {
req.defaults().left();
if(zone.zoneRequirements.length > 0){
req.table(r -> {
r.add("$complete").colspan(2).left();
r.row();
for(Zone other : zone.zoneRequirements){
r.addImage("icon-zone").padRight(4);
r.add(other.localizedName()).color(Color.LIGHT_GRAY);
r.addImage(data.isCompleted(zone) ? "icon-check-2" : "icon-cancel-2")
.color(data.isCompleted(zone) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3);
r.row();
}
});
}
req.row();
if(zone.itemRequirements.length > 0){
req.table(r -> {
for(ItemStack stack : zone.itemRequirements){
r.addImage(stack.item.region).size(8 * 3).padRight(4);
r.add(Math.min(data.getItem(stack.item), stack.amount) + "/" + stack.amount)
.color(stack.amount > data.getItem(stack.item) ? Color.SCARLET : Color.LIGHT_GRAY).left();
r.row();
}
}).padTop(10);
}
req.row();
if(zone.blockRequirements.length > 0){
req.table(r -> {
r.add("$research.list").colspan(2).left();
r.row();
for(Block block : zone.blockRequirements){
r.addImage(block.icon(Icon.small)).size(8 * 3).padRight(4);
r.add(block.formalName).color(Color.LIGHT_GRAY);
r.addImage(data.isUnlocked(block) ? "icon-check-2" : "icon-cancel-2")
.color(data.isUnlocked(block) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3);
r.row();
}
}).padTop(10);
}
}).growX();
}
}
}).pad(4);
if(++i % 2 == 0){
row();
hide();
ui.loadAnd(() -> {
try{
control.saves.getZoneSlot().load();
state.set(State.playing);
}catch(SaveException e){ //make sure to handle any save load errors!
e.printStackTrace();
if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete();
Core.app.post(() -> ui.showInfo("$save.corrupted"));
show();
}
}
}else{
SaveSlot slot = control.saves.getZoneSlot();
});
}).size(230f).get();
b[0] = button;
TextButton b[] = {null};
String color = "[lightgray]";
TextButton button = addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> {
if(b[0].childrenPressed()) return;
button.defaults().colspan(2);
button.row();
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
button.row();
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
button.row();
button.add().grow();
button.row();
hide();
ui.loadAnd(() -> {
try{
control.saves.getZoneSlot().load();
state.set(State.playing);
}catch(SaveException e){ //make sure to handle any save load errors!
e.printStackTrace();
if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete();
ui.showInfo("$save.corrupted");
show();
}
});
}).size(200f).get();
b[0] = button;
button.addButton("$abandon", () -> {
ui.showConfirm("$warning", "$abandon.text", () -> {
slot.delete();
setup();
});
}).growX().height(50f).pad(-12).padTop(10);
String color = "[lightgray]";
button.defaults().colspan(2);
button.row();
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
button.row();
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
button.row();
button.add().grow();
button.row();
button.addButton("$abandon", () -> {
ui.showConfirm("$warning", "$abandon.text", () -> {
slot.delete();
setup();
});
}).growX().height(50f).pad(-12).padTop(10);
}
}})).grow();
}}, new ItemsDisplay()).grow();
}
boolean hidden(Zone zone){
@@ -204,19 +108,81 @@ public class DeployDialog extends FloatingDialog{
return false;
}
boolean canUnlock(Zone zone){
for(Zone other : zone.zoneRequirements){
if(!data.isCompleted(other)){
return false;
@Override
protected void drawBackground(float x, float y){
drawDefaultBackground(x, y);
}
void buildButton(Zone zone, TextButton button){
button.setDisabled(() -> hidden(zone));
button.clicked(() -> info.show(zone));
if(zone.unlocked()){
button.addImage("icon-zone").padRight(3);
button.labelWrap(zone.localizedName()).width(140).growX();
}else{
button.addImage("icon-zone-locked");
button.row();
button.add("$locked");
}
}
//should be static variables of View, but that's impossible
static float panX = 0, panY = -200;
class View extends Group{
{
for(ZoneNode node : nodes){
TextButton button = new TextButton("", "node");
button.setSize(node.width, node.height);
button.update(() -> {
button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f, Align.center);
});
button.clearChildren();
buildButton(node.zone, button);
addChild(button);
}
dragged((x, y) -> {
panX += x;
panY += y;
});
}
for(Block other : zone.blockRequirements){
if(!data.isUnlocked(other)){
return false;
@Override
public void draw(){
float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y;
for(ZoneNode node : nodes){
for(ZoneNode child : node.children){
Lines.stroke(Unit.dp.scl(3f), node.zone.locked() || child.zone.locked() ? Pal.locked : Pal.accent);
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}
}
Draw.reset();
super.draw();
}
}
class ZoneNode extends TreeNode<ZoneNode>{
final Array<Zone> arr = new Array<>();
final Zone zone;
ZoneNode(Zone zone, ZoneNode parent){
this.zone = zone;
this.parent = parent;
this.width = this.height = nodeSize;
this.height /= 2f;
nodes.add(this);
arr.selectFrom(content.zones(), other -> Structs.contains(other.zoneRequirements, zone));
children = new ZoneNode[arr.size];
for(int i = 0; i < children.length; i++){
children[i] = new ZoneNode(arr.get(i), this);
}
}
return data.hasItems(zone.itemRequirements);
}
}

View File

@@ -2,7 +2,7 @@ package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core;
import io.anuke.arc.graphics.Color;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.arc.scene.ui.Dialog;
import static io.anuke.mindustry.Vars.discordURL;
@@ -33,7 +33,7 @@ public class DiscordDialog extends Dialog{
i.addImage("icon-discord").size(14 * 3);
}).size(h).left();
t.add("$discord").color(Palette.accent).growX().padLeft(10f);
t.add("$discord").color(Pal.accent).growX().padLeft(10f);
}).size(470f, h).pad(10f);
buttons.defaults().size(170f, 50);

View File

@@ -5,7 +5,7 @@ import io.anuke.arc.input.KeyCode;
import io.anuke.arc.util.Align;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.EventType.ResizeEvent;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.net.Net;
import io.anuke.arc.Events;
import io.anuke.arc.scene.ui.Dialog;
@@ -22,7 +22,7 @@ public class FloatingDialog extends Dialog{
setFillParent(true);
this.title.setAlignment(Align.center);
titleTable.row();
titleTable.addImage("white", Palette.accent)
titleTable.addImage("white", Pal.accent)
.growX().height(3f).pad(4f);
hidden(() -> {
@@ -63,7 +63,7 @@ public class FloatingDialog extends Dialog{
@Override
public void addCloseButton(){
buttons.addImageTextButton("$back", "icon-arrow-left", 30f, this::hide).size(230f, 64f);
buttons.addImageTextButton("$back", "icon-arrow-left", 30f, this::hide).size(210f, 64f);
keyDown(key -> {
if(key == KeyCode.ESCAPE || key == KeyCode.BACK) {

View File

@@ -2,8 +2,10 @@ package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.Stats.RankResult;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Item.Icon;
import static io.anuke.mindustry.Vars.*;
@@ -60,12 +62,18 @@ public class GameOverDialog extends FloatingDialog{
if(state.stats.itemsDelivered.get(item, 0) > 0){
cont.table(items -> {
items.add(" [LIGHT_GRAY]" + state.stats.itemsDelivered.get(item, 0));
items.addImage(item.region).size(8 *3).pad(4);
items.addImage(item.icon(Icon.medium)).size(8 *3).pad(4);
}).left();
cont.row();
}
}
}
if(world.isZone()){
RankResult result = state.stats.calculateRank(world.getZone(), state.launched);
cont.add(Core.bundle.format("stat.rank", result.rank + result.modifier));
cont.row();
}
}).pad(12);
if(world.isZone()){

View File

@@ -6,7 +6,7 @@ import io.anuke.arc.scene.ui.ImageButton;
import io.anuke.arc.util.Strings;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.net.Net;
import java.io.IOException;

View File

@@ -14,7 +14,7 @@ import io.anuke.arc.util.Strings;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.game.Version;
import io.anuke.mindustry.net.Host;
import io.anuke.mindustry.net.Net;

View File

@@ -5,7 +5,7 @@ import io.anuke.arc.scene.ui.Image;
import io.anuke.arc.scene.ui.layout.Stack;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.util.Scaling;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.type.Player;
import static io.anuke.mindustry.Vars.control;
import static io.anuke.mindustry.Vars.players;

View File

@@ -87,7 +87,7 @@ public class MapsDialog extends FloatingDialog{
TextButton button = maps.addButton("", "clear", () -> showMapInfo(map)).width(mapsize).pad(8).get();
button.clearChildren();
button.margin(9);
button.add(map.meta.tags.get("name", map.name)).growX().center().get().setEllipsis(true);
button.add(map.meta.tags.get("name", map.name)).width(mapsize - 18f).center().get().setEllipsis(true);
button.row();
button.addImage("white").growX().pad(4).color(Color.GRAY);
button.row();
@@ -138,8 +138,6 @@ public class MapsDialog extends FloatingDialog{
t.add(map.meta.description()).growX().wrap().padTop(2);
t.row();
t.add("$editor.oregen.info").padRight(10).color(Color.GRAY);
t.row();
t.add(map.meta.hasOreGen() ? "$on" : "$off").padTop(2);
}).height(mapsize).width(mapsize);
table.row();

View File

@@ -40,7 +40,11 @@ public class PausedDialog extends FloatingDialog{
cont.addButton("$back", this::hide).colspan(2).width(dw*2 + 20f);
cont.row();
cont.addButton("database", ui.database::show);
if(world.isZone()){
cont.addButton("$techtree", ui.tech::show);
}else{
cont.addButton("$database", ui.database::show);
}
cont.addButton("$settings", ui.settings::show);
if(!world.isZone()){
@@ -76,6 +80,8 @@ public class PausedDialog extends FloatingDialog{
cont.row();
cont.addRowImageTextButton("$load", "icon-load", isize, load::show).disabled(b -> Net.active());
}else{
cont.row();
}
cont.addRowImageTextButton("$hostserver.mobile", "icon-host", isize, ui.host::show).disabled(b -> Net.active());

View File

@@ -14,7 +14,7 @@ import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.util.Align;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.net.Net;
import static io.anuke.mindustry.Vars.*;
@@ -49,7 +49,7 @@ public class SettingsMenuDialog extends SettingsDialog{
title.setAlignment(Align.center);
titleTable.row();
titleTable.add(new Image("white"))
.growX().height(3f).pad(4f).get().setColor(Palette.accent);
.growX().height(3f).pad(4f).get().setColor(Pal.accent);
cont.clearChildren();
cont.remove();
@@ -120,6 +120,7 @@ public class SettingsMenuDialog extends SettingsDialog{
void addSettings(){
//TODO add when sound works again
//sound.volumePrefs();
sound.add("[LIGHT_GRAY]there is no sound implemented in v4 yet");
game.screenshakePref();
game.checkPref("effects", true);
@@ -194,8 +195,8 @@ public class SettingsMenuDialog extends SettingsDialog{
graphics.checkPref("fps", false);
graphics.checkPref("indicators", true);
graphics.checkPref("animatedwater", !mobile);
graphics.checkPref("lasers", true);
graphics.checkPref("minimap", !mobile); //minimap is disabled by default on mobile devices
}
private void back(){

View File

@@ -4,67 +4,52 @@ import io.anuke.arc.Core;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.ObjectSet;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Lines;
import io.anuke.arc.input.KeyCode;
import io.anuke.arc.math.Interpolation;
import io.anuke.arc.math.geom.Rectangle;
import io.anuke.arc.scene.Element;
import io.anuke.arc.scene.Group;
import io.anuke.arc.scene.actions.Actions;
import io.anuke.arc.scene.event.InputEvent;
import io.anuke.arc.scene.event.InputListener;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.style.TextureRegionDrawable;
import io.anuke.arc.scene.ui.ImageButton;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.util.Align;
import io.anuke.arc.util.Log;
import io.anuke.arc.util.Structs;
import io.anuke.mindustry.content.TechTree;
import io.anuke.mindustry.content.TechTree.TechNode;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.ui.ItemsDisplay;
import io.anuke.mindustry.ui.TreeLayout;
import io.anuke.mindustry.ui.TreeLayout.TreeNode;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Block.Icon;
import static io.anuke.mindustry.Vars.*;
public class TechTreeDialog extends FloatingDialog{
private final float nodeSize = Unit.dp.scl(60f);
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
private TechTreeNode root = new TechTreeNode(TechTree.root, null);
private static final float nodeSize = 60f;
private ItemsDisplay items;
public TechTreeDialog(){
super("");
cont.setFillParent(true);
titleTable.remove();
margin(0f).marginBottom(8);
cont.stack(new View(), items = new ItemsDisplay()).grow();
TreeLayout layout = new TreeLayout();
layout.gapBetweenLevels = 60f;
layout.gapBetweenNodes = 40f;
layout.layout(root);
cont.add(new View()).grow();
{ //debug code; TODO remove
ObjectSet<Block> used = new ObjectSet<Block>().select(t -> true);
for(TechTreeNode node : nodes){
used.add(node.node.block);
}
Array<Block> recipes = content.blocks().select(r -> r.isVisible() && !used.contains(r));
recipes.sort(Structs.comparing(r -> r.buildCost));
if(recipes.size > 0){
Log.info("Recipe tree coverage: {0}%", (int)((float)nodes.size / content.blocks().select(Block::isVisible).size * 100));
Log.info("Missing items: ");
recipes.forEach(r -> Log.info(" {0}", r));
}
}
shown(() -> checkNodes(root));
shown(() -> {
checkNodes(root);
treeLayout();
});
hidden(ui.deploy::setup);
addCloseButton();
buttons.addImageTextButton("$database", "icon-database", 14*2, () -> {
hide();
ui.database.show();
}).size(210f, 64f);
}
@Override
@@ -72,52 +57,70 @@ public class TechTreeDialog extends FloatingDialog{
drawDefaultBackground(x, y);
}
void checkNodes(TechTreeNode node){
boolean locked = locked(node);
if(!locked) node.visible = true;
for(TreeNode child : node.children){
TechTreeNode l = (TechTreeNode)child;
l.visible = !locked && l.node.block.isVisible();
checkNodes(l);
void treeLayout(){
TreeLayout layout = new TreeLayout();
layout.gapBetweenLevels = Unit.dp.scl(60f);
layout.gapBetweenNodes = Unit.dp.scl(40f);
LayoutNode node = new LayoutNode(root, null);
layout.layout(node);
copyInfo(node);
}
void copyInfo(LayoutNode node){
node.node.x = node.x;
node.node.y = node.y;
if(node.children != null){
for(LayoutNode child : node.children){
copyInfo(child);
}
}
}
void showToast(String info){
int maxIndex = 0;
for(Element e : Core.scene.root.getChildren()){
if("toast".equals(e.getName())){
maxIndex = Math.max(maxIndex, (Integer)e.getUserObject() + 1);
}
void checkNodes(TechTreeNode node){
boolean locked = locked(node.node);
if(!locked) node.visible = true;
for(TechTreeNode l : node.children){
l.visible = !locked;
checkNodes(l);
}
int m = maxIndex;
items.rebuild();
}
void showToast(String info){
Table table = new Table();
table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor());
table.actions(Actions.fadeOut(0.5f, Interpolation.fade), Actions.removeActor());
table.top().add(info);
table.setName("toast");
table.setUserObject(maxIndex);
table.update(() -> {
table.toFront();
table.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight() - 21 - m*20f, Align.top);
table.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight() - 21, Align.top);
});
Core.scene.add(table);
}
boolean locked(TreeNode node){
return locked(((TechTreeNode)node).node);
}
boolean locked(TechNode node){
return !data.isUnlocked(node.block);
return node.block.locked();
}
class TechTreeNode extends TreeNode{
class LayoutNode extends TreeNode<LayoutNode>{
final TechTreeNode node;
LayoutNode(TechTreeNode node, LayoutNode parent){
this.node = node;
this.parent = parent;
this.width = this.height = nodeSize;
if(node.children != null){
children = Array.with(node.children).select(n -> n.visible).map(t -> new LayoutNode(t, this)).toArray(LayoutNode.class);
}
}
}
class TechTreeNode extends TreeNode<TechTreeNode>{
final TechNode node;
boolean visible = true;
public TechTreeNode(TechNode node, TreeNode parent){
TechTreeNode(TechNode node, TechTreeNode parent){
this.node = node;
this.parent = parent;
this.width = this.height = nodeSize;
@@ -134,7 +137,6 @@ public class TechTreeDialog extends FloatingDialog{
class View extends Group{
float panX = 0, panY = -200;
boolean moved = false;
Rectangle clip = new Rectangle();
ImageButton hoverNode;
Table infoTable = new Table();
@@ -143,11 +145,12 @@ public class TechTreeDialog extends FloatingDialog{
for(TechTreeNode node : nodes){
ImageButton button = new ImageButton(node.node.block.icon(Icon.medium), "node");
button.visible(() -> node.visible);
button.clicked(() -> {
if(mobile){
hoverNode = button;
rebuild();
}else if(data.hasItems(node.node.requirements) && locked(node)){
}else if(data.hasItems(node.node.requirements) && locked(node.node)){
unlock(node.node);
}
});
@@ -158,7 +161,7 @@ public class TechTreeDialog extends FloatingDialog{
}
});
button.exited(() -> {
if(hoverNode == button && !infoTable.hasMouse() && !hoverNode.hasMouse()){
if(!mobile && hoverNode == button && !infoTable.hasMouse() && !hoverNode.hasMouse()){
hoverNode = null;
rebuild();
}
@@ -166,44 +169,34 @@ public class TechTreeDialog extends FloatingDialog{
button.touchable(() -> !node.visible ? Touchable.disabled : Touchable.enabled);
button.setUserObject(node.node);
button.tapped(() -> moved = false);
button.setSize(nodeSize, nodeSize);
button.setSize(nodeSize);
button.update(() -> {
button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f, Align.center);
button.getStyle().up = Core.scene.skin.getDrawable(!locked(node) ? "content-background" : "content-background-locked");
float offset = (Core.graphics.getHeight() % 2) / 2f;
button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f + offset, Align.center);
button.getStyle().up = Core.scene.skin.getDrawable(!locked(node.node) ? "content-background" : "content-background-locked");
((TextureRegionDrawable)button.getStyle().imageUp)
.setRegion(node.visible ? node.node.block.icon(Icon.medium) : Core.atlas.find("icon-tree-locked"));
button.getImage().setColor(!locked(node) ? Color.WHITE : Color.GRAY);
button.getImage().setColor(!locked(node.node) ? Color.WHITE : Color.GRAY);
});
addChild(button);
}
addListener(new InputListener(){
float lastX, lastY;
@Override
public void touchDragged(InputEvent event, float mx, float my, int pointer){
panX -= lastX - mx;
panY -= lastY - my;
lastX = mx;
lastY = my;
moved = true;
}
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
lastX = x;
lastY = y;
return true;
}
dragged((x, y) -> {
moved = true;
panX += x;
panY += y;
});
}
void unlock(TechNode node){
data.unlockContent(node.block);
data.removeItems(node.requirements);
showToast(Core.bundle.format("researched", node.block.formalName));
showToast(Core.bundle.format("researched", node.block.localizedName));
checkNodes(root);
hoverNode = null;
treeLayout();
rebuild();
Core.scene.act();
}
void rebuild(){
@@ -235,7 +228,7 @@ public class TechTreeDialog extends FloatingDialog{
infoTable.table(desc -> {
desc.left().defaults().left();
desc.add(node.block.formalName);
desc.add(node.block.localizedName);
desc.row();
if(locked(node)){
desc.table(t -> {
@@ -245,8 +238,8 @@ public class TechTreeDialog extends FloatingDialog{
list.left();
list.addImage(req.item.getContentIcon()).size(8 * 3).padRight(3);
list.add(req.item.localizedName()).color(Color.LIGHT_GRAY);
list.add(" " + Math.min(data.items().get(req.item, 0), req.amount) + " / " + req.amount)
.color(data.has(req.item, req.amount) ? Color.LIGHT_GRAY : Color.SCARLET);
list.label(() -> " " + Math.min(data.getItem(req.item), req.amount) + " / " + req.amount)
.update(l -> l.setColor(data.has(req.item, req.amount) ? Color.LIGHT_GRAY : Color.SCARLET));
}).fillX().left();
t.row();
}
@@ -270,14 +263,17 @@ public class TechTreeDialog extends FloatingDialog{
public void draw(){
float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y;
for(TreeNode node : nodes){
for(TreeNode child : node.children){
Lines.stroke(3f, locked(node) || locked(child) ? Palette.locked : Palette.accent);
for(TechTreeNode node : nodes){
if(!node.visible) continue;
for(TechTreeNode child : node.children){
if(!child.visible) continue;
Lines.stroke(Unit.dp.scl(3f), locked(node.node) || locked(child.node) ? Pal.locked : Pal.accent);
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}
}
Draw.reset();
super.draw();
}
}

View File

@@ -37,7 +37,7 @@ public class TraceDialog extends FloatingDialog{
table.row();
table.add(Core.bundle.format("trace.structureblocksbroken", info.structureBlocksBroken));
table.row();
table.add(Core.bundle.format("trace.lastblockbroken", info.lastBlockBroken.formalName));
table.add(Core.bundle.format("trace.lastblockbroken", info.lastBlockBroken.localizedName));
table.row();
table.add().pad(5);
@@ -45,7 +45,7 @@ public class TraceDialog extends FloatingDialog{
table.add(Core.bundle.format("trace.totalblocksplaced", info.totalBlocksPlaced));
table.row();
table.add(Core.bundle.format("trace.lastblockplaced", info.lastBlockPlaced.formalName));
table.add(Core.bundle.format("trace.lastblockplaced", info.lastBlockPlaced.localizedName));
table.row();
cont.add(table);

View File

@@ -0,0 +1,221 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.scene.ui.Button;
import io.anuke.arc.scene.ui.TextButton;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.ItemType;
import io.anuke.mindustry.type.Zone;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Block.Icon;
import static io.anuke.mindustry.Vars.*;
public class ZoneInfoDialog extends FloatingDialog{
public ZoneInfoDialog(){
super("");
titleTable.remove();
addCloseButton();
}
@Override
protected void drawBackground(float x, float y){
drawDefaultBackground(x, y);
}
public void show(Zone zone){
setup(zone);
show();
}
private void setup(Zone zone){
cont.clear();
Table iteminfo = new Table();
Runnable rebuildItems = () -> {
int i = 0;
iteminfo.clear();
ItemStack[] stacks = zone.unlocked() ? zone.getLaunchCost() : zone.itemRequirements;
for(ItemStack stack : stacks){
if(stack.amount == 0) continue;
if(i++ % 2 == 0){
iteminfo.row();
}
iteminfo.addImage(stack.item.icon(Item.Icon.medium)).size(8*3).padRight(1);
iteminfo.add(stack.amount + "").color(Color.LIGHT_GRAY).padRight(5);
}
};
rebuildItems.run();
cont.table(cont -> {
if(zone.locked()){
cont.addImage("icon-zone-locked");
cont.row();
cont.add("$locked").padBottom(6);
cont.row();
cont.table(req -> {
req.defaults().left();
if(zone.zoneRequirements.length > 0){
req.table(r -> {
r.add("$complete").colspan(2).left();
r.row();
for(Zone other : zone.zoneRequirements){
r.addImage("icon-zone").padRight(4);
r.add(other.localizedName()).color(Color.LIGHT_GRAY);
r.addImage(other.isCompleted() ? "icon-check-2" : "icon-cancel-2")
.color(other.isCompleted() ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3);
r.row();
}
});
}
req.row();
if(zone.blockRequirements.length > 0){
req.table(r -> {
r.add("$research.list").colspan(2).left();
r.row();
for(Block block : zone.blockRequirements){
r.addImage(block.icon(Icon.small)).size(8 * 3).padRight(4);
r.add(block.localizedName).color(Color.LIGHT_GRAY);
r.addImage(data.isUnlocked(block) ? "icon-check-2" : "icon-cancel-2")
.color(data.isUnlocked(block) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3);
r.row();
}
}).padTop(10);
}
}).growX();
}else{
cont.add(zone.localizedName()).color(Pal.accent).growX().center();
cont.row();
cont.addImage("white").color(Pal.accent).height(3).pad(6).growX();
cont.row();
cont.table(res -> {
res.add("$zone.resources").padRight(6);
if(zone.resources.length > 0){
for(Item item : zone.resources){
res.addImage(item.icon(Item.Icon.medium)).size(8 * 3);
}
}else{
res.add("$none");
}
});
if(zone.bestWave() > 0){
cont.row();
cont.add(Core.bundle.format("bestwave", zone.bestWave()));
}
Table load = new Table();
//thanks java, absolutely brilliant syntax here
Runnable[] rebuildLoadout = {null};
rebuildLoadout[0] = () -> {
load.clear();
float bsize = 40f;
int step = 100;
load.left();
for(ItemStack stack : zone.getStartingItems()){
load.addButton("-", () -> {
stack.amount = Math.max(stack.amount - step, 0);
zone.updateLaunchCost();
rebuildItems.run();
}).size(bsize).pad(2);
load.addButton("+", () -> {
stack.amount = Math.min(stack.amount + step, zone.loadout.core().itemCapacity);
zone.updateLaunchCost();
rebuildItems.run();
}).size(bsize).pad(2);
load.addImage(stack.item.icon(Item.Icon.medium)).size(8 * 3).padRight(4);
load.label(() -> stack.amount + "").left();
load.row();
}
load.addButton("$add", () -> {
FloatingDialog dialog = new FloatingDialog("");
dialog.setFillParent(false);
for(Item item : content.items().select(item -> data.getItem(item) > 0 && item.type == ItemType.material && zone.getStartingItems().find(stack -> stack.item == item) == null)){
TextButton button = dialog.cont.addButton("", () -> {
zone.getStartingItems().add(new ItemStack(item, 0));
zone.updateLaunchCost();
rebuildLoadout[0].run();
dialog.hide();
}).size(300f, 35f).pad(1).get();
button.clearChildren();
button.left();
button.addImage(item.icon(Item.Icon.medium)).size(8*3).pad(4);
button.add(item.localizedName);
dialog.cont.row();
}
dialog.show();
}).colspan(4).size(100f, bsize).left().disabled(b -> !content.items().contains(item -> data.getItem(item) > 0 && item.type == ItemType.material && !zone.getStartingItems().contains(stack -> stack.item == item)));
};
rebuildLoadout[0].run();
cont.row();
cont.table(zone.canConfigure() ? "button" : "button-disabled", t -> {
t.left();
t.add(!zone.canConfigure() ? Core.bundle.format("configure.locked", zone.configureWave) : "$configure").growX().wrap();
if(zone.canConfigure()){
t.row();
t.pane(load).pad(2).growX().left();
}
}).width(300f).pad(4).left();
}
});
cont.row();
Button button = cont.addButton(zone.locked() ? "$uncover" : "$launch", () -> {
if(!data.isUnlocked(zone)){
data.removeItems(zone.itemRequirements);
data.unlockContent(zone);
ui.deploy.setup();
setup(zone);
}else{
ui.deploy.hide();
data.removeItems(zone.getLaunchCost());
hide();
world.playZone(zone);
}
}).minWidth(150f).margin(13f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.getLaunchCost())).get();
button.row();
button.add(iteminfo);
}
private boolean canUnlock(Zone zone){
if(data.isUnlocked(zone)){
return true;
}
for(Zone other : zone.zoneRequirements){
if(!other.isCompleted()){
return false;
}
}
for(Block other : zone.blockRequirements){
if(!data.isUnlocked(other)){
return false;
}
}
return data.hasItems(zone.itemRequirements);
}
}

View File

@@ -29,6 +29,7 @@ public class BlockConfigFragment extends Fragment{
@Override
public void build(Group parent){
table.visible(false);
parent.addChild(table);
}

View File

@@ -20,10 +20,11 @@ import io.anuke.arc.util.Align;
import io.anuke.arc.util.Strings;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.input.InputHandler;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Item.Icon;
import io.anuke.mindustry.ui.ItemImage;
import io.anuke.mindustry.world.Tile;
@@ -49,7 +50,7 @@ public class BlockInventoryFragment extends Fragment{
int removed = tile.block().removeStack(tile, item, amount);
player.inventory.addItem(item, removed);
player.addItem(item, removed);
for(int j = 0; j < Mathf.clamp(removed / 3, 1, 8); j++){
Time.run(j * 3f, () -> Call.transferItemEffect(item, tile.drawx(), tile.drawy(), player));
}
@@ -65,6 +66,10 @@ public class BlockInventoryFragment extends Fragment{
}
public void showFor(Tile t){
if(this.tile == t.target()){
hide();
return;
}
this.tile = t.target();
if(tile == null || tile.entity == null || !tile.block().isAccessible() || tile.entity.items.total() == 0)
return;
@@ -97,7 +102,7 @@ public class BlockInventoryFragment extends Fragment{
holdTime += Time.delta();
if(holdTime >= holdWithdraw){
int amount = Math.min(tile.entity.items.get(lastItem), player.inventory.itemCapacityUsed(lastItem));
int amount = Math.min(tile.entity.items.get(lastItem), player.maxAccepted(lastItem));
Call.requestItem(player, tile, lastItem, amount);
holding = false;
holdTime = 0f;
@@ -120,7 +125,7 @@ public class BlockInventoryFragment extends Fragment{
int row = 0;
table.margin(6f);
table.defaults().size(16 * 2.5f).space(6f);
table.defaults().size(8 * 5).space(6f);
if(tile.block().hasItems){
@@ -130,12 +135,12 @@ public class BlockInventoryFragment extends Fragment{
container.add(i);
BooleanProvider canPick = () -> player.inventory.canAcceptItem(item);
BooleanProvider canPick = () -> player.acceptsItem(item) && !state.isPaused();
HandCursorListener l = new HandCursorListener();
l.setEnabled(canPick);
ItemImage image = new ItemImage(item.region, () -> {
ItemImage image = new ItemImage(item.icon(Icon.xlarge), () -> {
if(tile == null || tile.entity == null){
return "";
}
@@ -147,11 +152,13 @@ public class BlockInventoryFragment extends Fragment{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
if(!canPick.get() || !tile.entity.items.has(item)) return false;
int amount = Math.min(1, player.inventory.itemCapacityUsed(item));
Call.requestItem(player, tile, item, amount);
lastItem = item;
holding = true;
holdTime = 0f;
int amount = Math.min(1, player.maxAccepted(item));
if(amount > 0){
Call.requestItem(player, tile, item, amount);
lastItem = item;
holding = true;
holdTime = 0f;
}
return true;
}

View File

@@ -15,34 +15,32 @@ import io.anuke.arc.scene.ui.ImageButton;
import io.anuke.arc.scene.ui.TextButton;
import io.anuke.arc.scene.ui.layout.Stack;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.scene.utils.Elements;
import io.anuke.arc.util.Align;
import io.anuke.arc.util.Scaling;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.Tmp;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.EventType.StateChangeEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.input.Binding;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Packets.AdminAction;
import io.anuke.mindustry.ui.Bar;
import io.anuke.mindustry.ui.IntFormat;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import static io.anuke.mindustry.Vars.*;
public class HudFragment extends Fragment{
public final PlacementFragment blockfrag = new PlacementFragment();
private ImageButton menu, flip;
private Stack wavetable;
private Table infolabel;
private ImageButton flip;
private Table lastUnlockTable;
private Table lastUnlockLayout;
private boolean shown = true;
private float dsize = 58;
private float dsize = 59;
private float isize = 40;
private float coreAttackTime;
@@ -53,7 +51,6 @@ public class HudFragment extends Fragment{
//menu at top left
parent.fill(cont -> {
cont.top().left().visible(() -> !state.is(State.menu));
if(mobile){
@@ -61,7 +58,7 @@ public class HudFragment extends Fragment{
select.left();
select.defaults().size(dsize).left();
menu = select.addImageButton("icon-menu", "clear", isize, ui.paused::show).get();
select.addImageButton("icon-menu", "clear", isize, ui.paused::show);
flip = select.addImageButton("icon-arrow-up", "clear", isize, this::toggleMenus).get();
select.addImageButton("icon-pause", "clear", isize, () -> {
@@ -86,6 +83,8 @@ public class HudFragment extends Fragment{
}else{
ui.chatfrag.toggle();
}
}else if(world.isZone()){
ui.tech.show();
}else{
ui.database.show();
}
@@ -93,15 +92,15 @@ public class HudFragment extends Fragment{
if(Net.active() && mobile){
i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-chat");
}else{
i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-unlocks");
i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-database-small");
}
}).get();
select.addImage("blank").color(Palette.accent).width(6f).fillY();
});
select.addImage("blank").color(Pal.accent).width(3f).fillY();
}).left();
cont.row();
cont.addImage("blank").height(6f).color(Palette.accent).fillX();
cont.addImage("blank").height(3f).color(Pal.accent).fillX();
cont.row();
}
@@ -111,45 +110,57 @@ public class HudFragment extends Fragment{
}
});
Stack stack = new Stack();
TextButton waves = new TextButton("", "wave");
Table btable = new Table().margin(0);
cont.table(stuff -> {
stuff.left();
Stack stack = new Stack();
TextButton waves = new TextButton("", "wave");
Table btable = new Table().margin(0);
stack.add(waves);
stack.add(btable);
stack.add(waves);
stack.add(btable);
wavetable = stack;
addWaveTable(waves);
addPlayButton(btable);
cont.add(stack).width(dsize * 4 + 6f);
cont.row();
//fps display
infolabel = cont.table(t -> {
IntFormat fps = new IntFormat("fps");
IntFormat ping = new IntFormat("ping");
t.label(() -> fps.get(Core.graphics.getFramesPerSecond())).padRight(10);
t.row();
if(Net.hasClient()){
t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2);
}
}).size(-1).visible(() -> Core.settings.getBool("fps")).update(t -> t.setTranslation(0, (!waves.isVisible() ? wavetable.getHeight() : Math.min(wavetable.getTranslation().y, wavetable.getHeight())))).get();
//make wave box appear below rest of menu
if(mobile){
cont.swapActor(wavetable, menu.getParent());
}
addWaveTable(waves);
addPlayButton(btable);
stuff.add(stack).width(dsize * 4 + 3f);
stuff.row();
stuff.table("button", t -> t.margin(10f).add(new Bar("boss.health", Pal.health, () -> state.boss() == null ? 0f : state.boss().healthf()).blink(Color.WHITE))
.grow()).fillX().visible(() -> world.isZone() && state.boss() != null).height(60f).get();
stuff.row();
}).visible(() -> shown);
});
//minimap
//parent.fill(t -> t.top().right().add(new Minimap()).visible(() -> !state.is(State.menu) && Core.settings.getBool("minimap")));
//paused table
//fps display
parent.fill(info -> {
info.top().right().margin(4).visible(() -> Core.settings.getBool("fps") && !state.is(State.menu));
IntFormat fps = new IntFormat("fps");
IntFormat ping = new IntFormat("ping");
info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).right();
info.row();
info.label(() -> ping.get(Net.getPing())).visible(Net::client).right();
});
//spawner warning
parent.fill(t -> {
t.top().visible(() -> state.is(State.paused) && !Net.active());
t.table("button", top -> top.add("$paused").pad(6f));
t.touchable(Touchable.disabled);
t.visible(() -> !state.is(State.menu));
t.table("flat", c -> c.add("$nearpoint")
.update(l -> l.setColor(Tmp.c1.set(Color.WHITE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 10f, 1f))))
.get().setAlignment(Align.center, Align.center))
.margin(6).update(u -> u.color.a = Mathf.lerpDelta(u.color.a, Mathf.num(world.spawner.playerNear()), 0.1f)).get().color.a = 0f;
});
//out of bounds warning
parent.fill(t -> {
t.touchable(Touchable.disabled);
t.visible(() -> !state.is(State.menu));
t.table("flat", c -> c.add("")
.update(l ->{
l.setColor(Tmp.c1.set(Color.WHITE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 10f, 1f)));
l.setText(Core.bundle.format("outofbounds", (int)((boundsCountdown - players[0].destructTime) / 60f)));
}).get().setAlignment(Align.center, Align.center)).margin(6).update(u -> {
u.color.a = Mathf.lerpDelta(u.color.a, Mathf.num(players[0].isOutOfBounds()), 0.1f);
}).get().color.a = 0f;
});
parent.fill(t -> {
@@ -196,8 +207,45 @@ public class HudFragment extends Fragment{
.update(label -> label.getColor().set(Color.ORANGE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 2f, 1f))));
});
parent.fill(t -> t.top().right().addRowImageTextButton("$launch", "icon-arrow-up", 8*3, () -> world.launchZone())
.size(94f, 70f).visible(() -> world.isZone() && world.getZone().metCondition()));
//launch button
parent.fill(t -> {
t.top().visible(() -> !state.is(State.menu));
TextButton button = Elements.newButton("$launch", () -> ui.showConfirm("$launch", "$launch.confirm", Call::launchZone));
button.getStyle().disabledFontColor = Color.WHITE;
button.visible(() ->
world.isZone() &&
world.getZone().metCondition() &&
!Net.client() &&
state.wave % world.getZone().launchPeriod == 0 &&
state.wavetime < state.rules.waveSpacing * launchWaveMultiplier - 70);
button.update(() -> {
if(world.getZone() == null){
button.setText("");
return;
}
button.setText(state.enemies() > 0 ? Core.bundle.format("launch.unable", state.enemies()) : Core.bundle.get("launch") + "\n" +
Core.bundle.format("launch.next", state.wave + world.getZone().launchPeriod));
button.getLabel().setColor(Tmp.c1.set(Color.WHITE).lerp(state.enemies() > 0 ? Color.WHITE : Pal.accent,
Mathf.absin(Time.time(), 7f, 1f)));
});
button.setDisabled(() -> state.enemies() > 0);
button.getLabelCell().left().get().setAlignment(Align.left, Align.left);
t.add(button).size(350f, 80f);
});
//paused table
parent.fill(t -> {
t.top().visible(() -> state.is(State.paused) && !Net.active());
t.table("button", top -> top.add("$paused").pad(6f));
});
//'saving' indicator
parent.fill(t -> {
@@ -229,6 +277,10 @@ public class HudFragment extends Fragment{
Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.removeActor())));
}
public boolean shown(){
return shown;
}
/** Show unlock notification for a new recipe. */
public void showUnlock(UnlockableContent content){
//some content may not have icons... yet
@@ -314,38 +366,25 @@ public class HudFragment extends Fragment{
}
}
public void showTextDialog(String str){
new FloatingDialog("$mission.info"){{
shouldPause = true;
setFillParent(false);
getCell(cont).growX();
cont.margin(15).add(str).width(400f).wrap().get().setAlignment(Align.left, Align.left);
buttons.addButton("$continue", this::hide).size(140, 60).pad(4);
}}.show();
public void showLaunch(){
Image image = new Image("white");
image.getColor().a = 0f;
image.setFillParent(true);
image.actions(Actions.fadeIn(40f / 60f));
image.update(() -> {
if(state.is(State.menu)){
image.remove();
}
});
Core.scene.add(image);
}
private void toggleMenus(){
wavetable.clearActions();
infolabel.clearActions();
float dur = 0.3f;
Interpolation in = Interpolation.pow3Out;
if(flip != null){
flip.getStyle().imageUp = Core.scene.skin.getDrawable(shown ? "icon-arrow-down" : "icon-arrow-up");
}
if(shown){
shown = false;
blockfrag.toggle(dur, in);
wavetable.actions(Actions.translateBy(0, (wavetable.getHeight() + Unit.dp.scl(dsize) + Unit.dp.scl(6)) - wavetable.getTranslation().y, dur, in));
infolabel.actions(Actions.translateBy(0, (wavetable.getHeight()) - wavetable.getTranslation().y, dur, in));
}else{
shown = true;
blockfrag.toggle(dur, in);
wavetable.actions(Actions.translateBy(0, -wavetable.getTranslation().y, dur, in));
infolabel.actions(Actions.translateBy(0, -infolabel.getTranslation().y, dur, in));
}
shown = !shown;
}
private void addWaveTable(TextButton table){
@@ -391,12 +430,8 @@ public class HudFragment extends Fragment{
}else{
state.wavetime = 0f;
}
}).growY().fillX().right().width(40f).update(l -> {
boolean vis = !state.rules.waveTimer && ((Net.server() || players[0].isAdmin) || !Net.active());
boolean paused = state.is(State.paused) || !vis;
l.getStyle().imageUp = Core.scene.skin.getDrawable(vis ? "icon-play" : "clear");
l.touchable(!paused ? Touchable.enabled : Touchable.disabled);
}).visible(() -> !state.rules.waveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()) && unitGroups[Team.red.ordinal()].size() == 0);
}).growY().fillX().right().width(40f)
.visible(() -> state.rules.waves && ((Net.server() || players[0].isAdmin) || !Net.active()) && state.enemies() == 0
&& (state.wavetime < state.rules.waveSpacing - 60 || !state.rules.waveTimer));
}
}

View File

@@ -1,6 +1,6 @@
package io.anuke.mindustry.ui.fragments;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.arc.scene.Group;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.ui.Label;
@@ -18,11 +18,11 @@ public class LoadingFragment extends Fragment{
t.touchable(Touchable.enabled);
t.add().height(70f).row();
t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Palette.accent);
t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent);
t.row();
t.add("$loading").name("namelabel").pad(10f);
t.row();
t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Palette.accent);
t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent);
t.row();
button = t.addButton("$cancel", () -> {}).pad(20).size(250f, 70f).visible(false).get();

View File

@@ -11,6 +11,7 @@ import io.anuke.mindustry.game.EventType.ResizeEvent;
import io.anuke.mindustry.game.Version;
import io.anuke.mindustry.ui.MenuButton;
import io.anuke.mindustry.ui.MobileButton;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import static io.anuke.mindustry.Vars.*;
@@ -42,7 +43,7 @@ public class MenuFragment extends Fragment{
}
//version info
parent.fill(c -> c.bottom().left().add(Strings.formatArgs("Mindustry v{0} {1}-{2} {3}{4}", Version.number, Version.modifier, Version.type,
parent.fill(c -> c.bottom().left().add(Strings.format("Mindustry v{0} {1}-{2} {3}{4}", Version.number, Version.modifier, Version.type,
(Version.build == -1 ? "custom build" : "build " + Version.build), Version.revision == 0 ? "" : "." + Version.revision))
.visible(() -> state.is(State.menu)));
}
@@ -56,19 +57,18 @@ public class MenuFragment extends Fragment{
container.defaults().size(size).pad(5).padTop(4f);
MobileButton
play = new MobileButton("icon-play-2", isize, "$play", this::showPlaySelect),
play = new MobileButton("icon-play-2", isize, "$play", ui.deploy::show),
maps = new MobileButton("icon-map", isize, "$maps", ui.maps::show),
load = new MobileButton("icon-load", isize, "$load", ui.load::show),
custom = new MobileButton("icon-play-custom", isize, "$customgame", this::showCustomSelect),
join = new MobileButton("icon-add", isize, "$joingame", ui.join::show),
editor = new MobileButton("icon-editor", isize, "$editor", () -> ui.loadAnd(ui.editor::show)),
tools = new MobileButton("icon-tools", isize, "$settings", ui.settings::show),
unlocks = new MobileButton("icon-unlocks", isize, "database", ui.database::show),
donate = new MobileButton("icon-donate", isize, "$donate", Platform.instance::openDonations);
if(Core.graphics.getWidth() > Core.graphics.getHeight()){
container.add(play);
container.add(join);
container.add(load);
container.add(custom);
container.add(maps);
container.row();
@@ -77,7 +77,6 @@ public class MenuFragment extends Fragment{
table.add(editor);
table.add(tools);
table.add(unlocks);
if(Platform.instance.canDonate()) table.add(donate);
}).colspan(4);
@@ -85,7 +84,7 @@ public class MenuFragment extends Fragment{
container.add(play);
container.add(maps);
container.row();
container.add(load);
container.add(custom);
container.add(join);
container.row();
container.add(editor);
@@ -95,8 +94,6 @@ public class MenuFragment extends Fragment{
container.table(table -> {
table.defaults().set(container.defaults());
table.add(unlocks);
if(Platform.instance.canDonate()) table.add(donate);
}).colspan(2);
}
@@ -111,7 +108,13 @@ public class MenuFragment extends Fragment{
out.margin(16);
out.defaults().size(w, 66f).padTop(5).padRight(5);
out.add(new MenuButton("icon-play-2", "$play", MenuFragment.this::showPlaySelect)).width(bw).colspan(2);
out.add(new MenuButton("icon-play-2", "$play", ui.deploy::show)).width(bw).colspan(2);
out.row();
out.add(new MenuButton("icon-add", "$joingame", ui.join::show));
out.add(new MenuButton("icon-play-custom", "$customgame", this::showCustomSelect));
out.row();
@@ -131,40 +134,20 @@ public class MenuFragment extends Fragment{
});
}
private void showPlaySelect(){
ui.deploy.show();
/*
float w = 220f;
float bw = w * 2f + 10f;
private void showCustomSelect(){
FloatingDialog dialog = new FloatingDialog("$play");
dialog.setFillParent(false);
dialog.addCloseButton();
dialog.cont.defaults().height(66f).width(w).padRight(5f);
dialog.cont.add(new MenuButton("icon-play-2", "$map.random", () -> {
dialog.hide();
world.generator.playRandomMap();
})).width(bw).colspan(2);
dialog.cont.row();
dialog.cont.add(new MenuButton("icon-add", "$joingame", () -> {
ui.join.show();
dialog.cont.defaults().size(230f, 64f);
dialog.cont.add(new MenuButton("icon-editor", "$newgame", () -> {
dialog.hide();
ui.custom.show();
}));
dialog.cont.add(new MenuButton("icon-editor", "$customgame", () -> {
dialog.hide();
ui.levels.show();
}));
dialog.cont.row();
dialog.cont.add(new MenuButton("icon-load", "$loadgame", () -> {
ui.load.show();
dialog.hide();
})).width(bw).colspan(2);
dialog.show();*/
}));
dialog.show();
}
}

View File

@@ -5,22 +5,23 @@ import io.anuke.arc.Events;
import io.anuke.arc.collection.Array;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.input.KeyCode;
import io.anuke.arc.math.Interpolation;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.scene.Group;
import io.anuke.arc.scene.actions.Actions;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.style.TextureRegionDrawable;
import io.anuke.arc.scene.ui.ButtonGroup;
import io.anuke.arc.scene.ui.Image;
import io.anuke.arc.scene.ui.ImageButton;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.game.EventType.UnlockEvent;
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.input.Binding;
import io.anuke.mindustry.input.InputHandler;
import io.anuke.mindustry.type.Category;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Block.Icon;
@@ -33,12 +34,13 @@ public class PlacementFragment extends Fragment{
final int rowWidth = 4;
Array<Block> returnArray = new Array<>();
Array<Category> returnCatArray = new Array<>();
boolean[] categoryEmpty = new boolean[Category.values().length];
Category currentCategory = Category.distribution;
Block hovered, lastDisplay;
Tile lastHover;
Tile hoverTile;
Table blockTable, toggler, topTable;
boolean shown = true;
boolean lastGround;
//TODO make this configurable
@@ -56,14 +58,41 @@ public class PlacementFragment extends Fragment{
public PlacementFragment(){
Events.on(WorldLoadEvent.class, event -> {
currentCategory = Category.turret;
Group group = toggler.getParent();
toggler.remove();
build(group);
control.input(0).block = null;
rebuild();
});
Events.on(UnlockEvent.class, event -> {
if(event.content instanceof Block){
rebuild();
}
});
}
void rebuild(){
currentCategory = Category.turret;
Group group = toggler.getParent();
int index = toggler.getZIndex();
toggler.remove();
build(group);
toggler.setZIndex(index);
}
boolean gridUpdate(InputHandler input){
if(Core.input.keyDown(Binding.pick)){ //mouse eyedropper select
Tile tile = world.tileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
if(tile != null){
tile = tile.target();
Block tryRecipe = tile.block();
if(tryRecipe.isVisible() && unlocked(tryRecipe)){
input.block = tryRecipe;
currentCategory = input.block.buildCategory;
return true;
}
}
}
if(!Core.input.keyDown(Binding.gridMode) || ui.chatfrag.chatOpen()) return false;
if(Core.input.keyDown(Binding.gridModeShift)){ //select category
int i = 0;
@@ -75,24 +104,12 @@ public class PlacementFragment extends Fragment{
i++;
}
return true;
}else if(Core.input.keyDown(Binding.select)){ //mouse eyedropper select
Tile tile = world.tileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
if(tile != null){
tile = tile.target();
Block tryRecipe = tile.block();
if(tryRecipe.isVisible() && data.isUnlocked(tryRecipe)){
input.block = tryRecipe;
currentCategory = input.block.buildCategory;
return true;
}
}
}else{ //select block
int i = 0;
Array<Block> recipes = getByCategory(currentCategory);
for(KeyCode key : inputGrid){
if(Core.input.keyDown(key))
input.block = (i < recipes.size && data.isUnlocked(recipes.get(i))) ? recipes.get(i) : null;
input.block = (i < recipes.size && unlocked(recipes.get(i))) ? recipes.get(i) : null;
i++;
}
}
@@ -103,7 +120,7 @@ public class PlacementFragment extends Fragment{
public void build(Group parent){
parent.fill(full -> {
toggler = full;
full.bottom().right().visible(() -> !state.is(State.menu));
full.bottom().right().visible(() -> !state.is(State.menu) && ui.hudfrag.shown());
full.table(frame -> {
InputHandler input = control.input(0);
@@ -119,34 +136,28 @@ public class PlacementFragment extends Fragment{
group.setMinCheckCount(0);
for(Block block : getByCategory(currentCategory)){
if(index++ % rowWidth == 0){
blockTable.row();
}
boolean[] unlocked = {false};
if(!unlocked(block)){
blockTable.add().size(46);
continue;
}
ImageButton button = blockTable.addImageButton("icon-locked", "select", 8 * 4, () -> {
if(data.isUnlocked(block)){
if(unlocked(block)){
input.block = input.block == block ? null : block;
}
}).size(46f).group(group).get();
button.getStyle().imageUp = new TextureRegionDrawable(block.icon(Icon.medium));
button.update(() -> { //color unplacable things gray
boolean ulock = data.isUnlocked(block);
TileEntity core = players[0].getClosestCore();
Color color = core != null && (core.items.has(block.buildRequirements) || state.rules.infiniteResources) ? Color.WHITE : ulock ? Color.GRAY : Color.WHITE;
Color color = core != null && (core.items.has(block.buildRequirements) || state.rules.infiniteResources) ? Color.WHITE : Color.GRAY;
button.forEach(elem -> elem.setColor(color));
button.setChecked(input.block == block);
if(ulock == unlocked[0]) return;
unlocked[0] = ulock;
if(!ulock){
button.replaceImage(new Image("icon-locked"));
}else{
button.replaceImage(new Image(block.icon(Icon.medium)));
}
});
button.hovered(() -> hovered = block);
@@ -165,7 +176,7 @@ public class PlacementFragment extends Fragment{
top.add(new Table()).growX().update(topTable -> {
//don't refresh unnecessarily
if((tileDisplayBlock() == null && lastDisplay == getSelected() && !lastGround)
|| (tileDisplayBlock() != null && lastHover == hoverTile && lastGround))
|| (tileDisplayBlock() != null && lastHover == hoverTile && lastDisplay == tileDisplayBlock() && lastGround))
return;
topTable.clear();
@@ -181,10 +192,10 @@ public class PlacementFragment extends Fragment{
topTable.table(header -> {
header.left();
header.add(new Image(lastDisplay.icon(Icon.medium))).size(8 * 4);
header.labelWrap(() -> !data.isUnlocked(lastDisplay) ? Core.bundle.get("blocks.unknown") : lastDisplay.formalName)
header.labelWrap(() -> !unlocked(lastDisplay) ? Core.bundle.get("blocks.unknown") : lastDisplay.localizedName)
.left().width(190f).padLeft(5);
header.add().growX();
if(data.isUnlocked(lastDisplay)){
if(unlocked(lastDisplay)){
header.addButton("?", "clear-partial", () -> ui.content.show(lastDisplay))
.size(8 * 5).padTop(-5).padRight(-5).right().grow();
}
@@ -197,7 +208,7 @@ public class PlacementFragment extends Fragment{
for(ItemStack stack : lastDisplay.buildRequirements){
req.table(line -> {
line.left();
line.addImage(stack.item.region).size(8 * 2);
line.addImage(stack.item.icon(Item.Icon.small)).size(8 * 2);
line.add(stack.item.localizedName()).color(Color.LIGHT_GRAY).padLeft(2).left();
line.labelWrap(() -> {
TileEntity core = players[0].getClosestCore();
@@ -231,7 +242,7 @@ public class PlacementFragment extends Fragment{
});
}).colspan(3).fillX().visible(() -> getSelected() != null || tileDisplayBlock() != null).touchable(Touchable.enabled);
frame.row();
frame.addImage("blank").color(Palette.accent).colspan(3).height(3).growX();
frame.addImage("blank").color(Pal.accent).colspan(3).height(3).growX();
frame.row();
frame.table("pane-2", blocksSelect -> {
blocksSelect.margin(4).marginTop(0);
@@ -244,15 +255,25 @@ public class PlacementFragment extends Fragment{
ButtonGroup<ImageButton> group = new ButtonGroup<>();
//update category empty values
for(Category cat : Category.values()){
if(getByCategory(cat).isEmpty()) continue;
Array<Block> blocks = getByCategory(cat);
categoryEmpty[cat.ordinal()] = blocks.isEmpty() || !unlocked(blocks.first());
}
int f = 0;
for(Category cat : getCategories()){
if(f++ % 2 == 0) categories.row();
if(categoryEmpty[cat.ordinal()]){
categories.addImage("flat");
continue;
}
categories.addImageButton("icon-" + cat.name(), "clear-toggle", 16 * 2, () -> {
currentCategory = cat;
rebuildCategory.run();
}).group(group).update(i -> i.setChecked(currentCategory == cat));
if(cat.ordinal() % 2 == 1) categories.row();
}
}).touchable(Touchable.enabled);
@@ -263,6 +284,13 @@ public class PlacementFragment extends Fragment{
});
});
}
Array<Category> getCategories(){
returnCatArray.clear();
returnCatArray.addAll(Category.values());
returnCatArray.sort((c1, c2) -> Boolean.compare(categoryEmpty[c1.ordinal()], categoryEmpty[c2.ordinal()]));
return returnCatArray;
}
Array<Block> getByCategory(Category cat){
returnArray.clear();
@@ -271,9 +299,14 @@ public class PlacementFragment extends Fragment{
returnArray.add(block);
}
}
returnArray.sort((b1, b2) -> -Boolean.compare(unlocked(b1), unlocked(b2)));
return returnArray;
}
boolean unlocked(Block block){
return !world.isZone() || data.isUnlocked(block);
}
/** Returns the currently displayed block in the top box. */
Block getSelected(){
Block toDisplay = null;
@@ -309,16 +342,4 @@ public class PlacementFragment extends Fragment{
Block tileDisplayBlock(){
return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.floor() instanceof OreBlock ? hoverTile.floor() : null;
}
/** Show or hide the placement menu. */
void toggle(float t, Interpolation ip){
toggler.clearActions();
if(shown){
shown = false;
toggler.actions(Actions.translateBy(toggler.getTranslation().x + toggler.getWidth(), 0, t, ip));
}else{
shown = true;
toggler.actions(Actions.translateBy(-toggler.getTranslation().x, 0, t, ip));
}
}
}

View File

@@ -11,7 +11,7 @@ import io.anuke.arc.scene.ui.layout.Unit;
import io.anuke.arc.util.Interval;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetConnection;
import io.anuke.mindustry.net.Packets.AdminAction;
@@ -82,7 +82,7 @@ public class PlayerListFragment extends Fragment{
@Override
public void draw(){
super.draw();
Draw.color(Palette.accent);
Draw.color(Pal.accent);
Draw.alpha(parentAlpha);
Lines.stroke(Unit.dp.scl(3f));
Lines.rect(x, y, width, height);
@@ -136,7 +136,7 @@ public class PlayerListFragment extends Fragment{
content.add(button).padBottom(-6).width(350f).maxHeight(h + 14);
content.row();
content.addImage("blank").height(3f).color(state.rules.pvp ? player.getTeam().color : Palette.accent).growX();
content.addImage("blank").height(3f).color(state.rules.pvp ? player.getTeam().color : Pal.accent).growX();
content.row();
});