Merge branch 'master' into port-field

This commit is contained in:
Summet
2020-09-24 21:03:06 +03:00
committed by GitHub
359 changed files with 26250 additions and 18402 deletions

View File

@@ -21,7 +21,7 @@ public class Bar extends Element{
public Bar(String name, Color color, Floatp fraction){
this.fraction = fraction;
this.name = Core.bundle.get(name);
this.name = Core.bundle.get(name, name);
this.blinkColor.set(color);
lastValue = value = fraction.get();
setColor(color);
@@ -80,11 +80,11 @@ public class Bar extends Element{
Drawable top = Tex.barTop;
float topWidth = width * value;
if(topWidth > Core.atlas.find("bar-top").getWidth()){
if(topWidth > Core.atlas.find("bar-top").width){
top.draw(x, y, topWidth, height);
}else{
if(ScissorStack.push(scissor.set(x, y, topWidth, height))){
top.draw(x, y, Core.atlas.find("bar-top").getWidth(), height);
top.draw(x, y, Core.atlas.find("bar-top").width, height);
ScissorStack.pop();
}
}

View File

@@ -5,6 +5,7 @@ import arc.struct.*;
import arc.graphics.*;
import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.world.*;
@@ -129,7 +130,7 @@ public class ContentDisplay{
public static void displayUnit(Table table, UnitType unit){
table.table(title -> {
title.image(unit.icon(Cicon.xlarge)).size(8 * 6);
title.image(unit.icon(Cicon.xlarge)).size(8 * 6).scaling(Scaling.fit);
title.add("[accent]" + unit.localizedName).padLeft(5);
});
@@ -149,10 +150,16 @@ public class ContentDisplay{
table.left().defaults().fillX();
table.add(Core.bundle.format("unit.health", unit.health));
table.row();
table.add(Core.bundle.format("unit.speed", Strings.fixed(unit.speed, 1)));
table.row();
Unit inst = unit.constructor.get();
//TODO more stats
table.add(Core.bundle.format("unit.health", unit.health)).row();
table.add(Core.bundle.format("unit.speed", Strings.fixed(unit.speed, 1))).row();
table.add(Core.bundle.format("unit.itemcapacity", unit.itemCapacity)).row();
if(inst instanceof Minerc) table.add(Core.bundle.format("unit.minespeed", (int)(unit.mineSpeed * 100f))).row();
if(inst instanceof Builderc) table.add(Core.bundle.format("unit.buildspeed", (int)(unit.buildSpeed * 100f))).row();
table.row();
}
}

View File

@@ -39,6 +39,7 @@ public class CoreItemsDisplay extends Table{
for(Item item : content.items()){
if(usedItems.contains(item)){
image(item.icon(Cicon.small)).padRight(3);
//TODO leaks garbage
label(() -> core == null ? "0" : UI.formatAmount(core.items.get(item))).padRight(3).left();
if(++i % 4 == 0){

View File

@@ -72,7 +72,7 @@ public class Fonts{
public static void loadContentIcons(){
Seq<Font> fonts = Seq.with(Fonts.chat, Fonts.def, Fonts.outline);
Texture uitex = Core.atlas.find("logo").getTexture();
Texture uitex = Core.atlas.find("logo").texture;
int size = (int)(Fonts.def.getData().lineHeight/Fonts.def.getData().scaleY);
try(Scanner scan = new Scanner(Core.files.internal("icons/icons.properties").read(512))){
@@ -84,7 +84,7 @@ public class Fonts{
int ch = Integer.parseInt(character);
TextureRegion region = Core.atlas.find(texture);
if(region.getTexture() != uitex){
if(region.texture != uitex){
continue;
//throw new IllegalArgumentException("Font icon '" + texture + "' is not in the UI texture.");
}
@@ -98,10 +98,10 @@ public class Fonts{
glyph.srcY = 0;
glyph.width = size;
glyph.height = size;
glyph.u = region.getU();
glyph.v = region.getV2();
glyph.u2 = region.getU2();
glyph.v2 = region.getV();
glyph.u = region.u;
glyph.v = region.v2;
glyph.u2 = region.u2;
glyph.v2 = region.v;
glyph.xoffset = 0;
glyph.yoffset = -size;
glyph.xadvance = size;
@@ -115,7 +115,9 @@ public class Fonts{
/** Called from a static context for use in the loading screen.*/
public static void loadDefaultFont(){
UI.packer = new PixmapPacker(2048, 2048, Format.rgba8888, 2, true);
int max = Gl.getInt(Gl.maxTextureSize);
UI.packer = new PixmapPacker(max >= 4096 ? 4096 : 2048, 2048, Format.rgba8888, 2, true);
FileHandleResolver resolver = new InternalFileHandleResolver();
Core.assets.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
Core.assets.setLoader(Font.class, null, new FreetypeFontLoader(resolver){
@@ -160,21 +162,21 @@ public class Fonts{
//grab all textures from the ui page, remove all the regions assigned to it, then copy them over to Fonts.packer and replace the texture in this atlas.
//grab old UI texture and regions...
Texture texture = atlas.find("logo").getTexture();
Texture texture = atlas.find("logo").texture;
Page page = UI.packer.getPages().first();
Seq<AtlasRegion> regions = atlas.getRegions().select(t -> t.getTexture() == texture);
Seq<AtlasRegion> regions = atlas.getRegions().select(t -> t.texture == texture);
for(AtlasRegion region : regions){
//get new pack rect
page.setDirty(false);
Rect rect = UI.packer.pack(region.name + (region.splits != null ? ".9" : ""), atlas.getPixmap(region));
//set new texture
region.setTexture(UI.packer.getPages().first().getTexture());
region.texture = UI.packer.getPages().first().getTexture();
//set its new position
region.set((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
//add old texture
atlas.getTextures().add(region.getTexture());
atlas.getTextures().add(region.texture);
}
//remove old texture, it will no longer be used
@@ -191,7 +193,7 @@ public class Fonts{
if(g == null) throw new IllegalArgumentException("No glyph: " + glyph + " (" + (int)glyph + ")");
float size = Math.max(g.width, g.height);
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().getTexture(), g.u, g.v2, g.u2, g.v)){
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().texture, g.u, g.v2, g.u2, g.v)){
@Override
public void draw(float x, float y, float width, float height){
Draw.color(Tmp.c1.set(tint).mul(Draw.getColor()).toFloatBits());

View File

@@ -14,7 +14,7 @@ public class ItemDisplay extends Table{
}
public ItemDisplay(Item item, int amount, boolean showName){
add(new ItemImage(new ItemStack(item, amount))).size(8 * 4).padRight(amount > 99 ? 12 : 0);
add(new ItemImage(new ItemStack(item, amount)));
if(showName) add(item.localizedName).padLeft(4 + amount > 99 ? 4 : 0);
this.item = item;

View File

@@ -8,15 +8,17 @@ import mindustry.type.*;
public class ItemImage extends Stack{
public ItemImage(TextureRegion region, int amount){
Table t = new Table().left().bottom();
t.add(amount + "").name("item-label");
t.pack();
add(new Table(o -> {
o.left();
o.add(new Image(region)).size(32f);
}));
add(t);
add(new Table(t -> {
t.left().bottom();
t.add(amount + "");
t.pack();
}));
}
public ItemImage(TextureRegion region){
@@ -27,12 +29,18 @@ public class ItemImage extends Stack{
}
public ItemImage(ItemStack stack){
add(new Image(stack.item.icon(Cicon.medium)));
add(new Table(o -> {
o.left();
o.add(new Image(stack.item.icon(Cicon.medium))).size(32f);
}));
if(stack.amount != 0){
Table t = new Table().left().bottom();
t.add(stack.amount + "").name("item-label").style(Styles.outlineLabel);
add(t);
add(new Table(t -> {
t.left().bottom();
t.add(stack.amount + "").style(Styles.outlineLabel);
t.pack();
}));
}
}
}

View File

@@ -54,9 +54,9 @@ public class Styles{
}};
waveb = new ButtonStyle(){{
up = buttonEdge4;
over = buttonEdgeOver4;
disabled = buttonEdge4;
up = wavepane;
over = wavepane; //TODO wrong
disabled = wavepane;
}};
defaultt = new TextButtonStyle(){{
@@ -183,6 +183,9 @@ public class Styles{
over = buttonRightOver;
down = buttonRightDown;
up = buttonRight;
disabled = buttonRightDisabled;
imageDisabledColor = Color.clear;
imageUpColor = Color.white;
}};
emptyi = new ImageButtonStyle(){{
imageDownColor = Pal.accent;

View File

@@ -3,19 +3,24 @@ package mindustry.ui.dialogs;
import arc.*;
import arc.func.*;
import arc.graphics.*;
import arc.math.*;
import arc.scene.style.*;
import arc.scene.ui.*;
import arc.scene.ui.ImageButton.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.type.Weather.*;
import mindustry.ui.*;
import mindustry.world.*;
import static arc.util.Time.*;
import static mindustry.Vars.*;
public class CustomRulesDialog extends BaseDialog{
@@ -135,6 +140,7 @@ public class CustomRulesDialog extends BaseDialog{
title("@rules.title.resourcesbuilding");
check("@rules.infiniteresources", b -> rules.infiniteResources = b, () -> rules.infiniteResources);
check("@rules.reactorexplosions", b -> rules.reactorExplosions = b, () -> rules.reactorExplosions);
check("@rules.schematic", b-> rules.schematicsAllowed = b, () -> rules.schematicsAllowed);
number("@rules.buildcostmultiplier", false, f -> rules.buildCostMultiplier = f, () -> rules.buildCostMultiplier, () -> !rules.infiniteResources);
number("@rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier);
number("@rules.deconstructrefundmultiplier", false, f -> rules.deconstructRefundMultiplier = f, () -> rules.deconstructRefundMultiplier, () -> !rules.infiniteResources);
@@ -160,6 +166,7 @@ public class CustomRulesDialog extends BaseDialog{
title("@rules.title.enemy");
check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
check("@rules.buildai", b -> rules.waveTeam.rules().ai = b, () -> rules.waveTeam.rules().ai);
number("@rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200));
title("@rules.title.environment");
@@ -175,8 +182,9 @@ public class CustomRulesDialog extends BaseDialog{
}}).grow();
}).margin(4).size(50f).padRight(10);
b.add("@rules.ambientlight");
}, () -> ui.picker.show(rules.ambientLight, rules.ambientLight::set)).left().width(250f);
main.row();
}, () -> ui.picker.show(rules.ambientLight, rules.ambientLight::set)).left().width(250f).row();
main.button("@rules.weather", this::weatherDialog).width(250f).left().row();
//TODO add weather patterns
}
@@ -213,4 +221,120 @@ public class CustomRulesDialog extends BaseDialog{
main.image().color(Pal.accent).height(3f).padRight(100f).padBottom(20);
main.row();
}
Cell<TextField> field(Table table, float value, Floatc setter){
return table.field(Strings.autoFixed(value, 2), v -> setter.get(Strings.parseFloat(v)))
.valid(Strings::canParsePositiveFloat)
.size(90f, 40f).pad(2f).addInputDialog();
}
void weatherDialog(){
BaseDialog dialog = new BaseDialog("@rules.weather");
Runnable[] rebuild = {null};
dialog.cont.pane(base -> {
rebuild[0] = () -> {
base.clearChildren();
int cols = Math.max(1, Core.graphics.getWidth() / 460);
int idx = 0;
for(WeatherEntry entry : rules.weather){
base.top();
//main container
base.table(Tex.pane, c -> {
c.margin(0);
//icons to perform actions
c.table(Tex.whiteui, t -> {
t.setColor(Pal.gray);
t.top().left();
t.add(entry.weather.localizedName).left().padLeft(6);
t.add().growX();
ImageButtonStyle style = Styles.geni;
t.defaults().size(42f);
t.button(Icon.cancel, style, () -> {
rules.weather.remove(entry);
rebuild[0].run();
});
}).growX();
c.row();
//all the options
c.table(f -> {
f.marginLeft(4);
f.left().top();
f.defaults().padRight(4).left();
f.add("@rules.weather.duration");
field(f, entry.minDuration / toMinutes, v -> entry.minDuration = v * toMinutes);
f.add("@waves.to");
field(f, entry.maxDuration / toMinutes, v -> entry.maxDuration = v * toMinutes);
f.add("@unit.minutes");
f.row();
f.add("@rules.weather.frequency");
field(f, entry.minFrequency / toMinutes, v -> entry.minFrequency = v * toMinutes);
f.add("@waves.to");
field(f, entry.maxFrequency / toMinutes, v -> entry.maxFrequency = v * toMinutes);
f.add("@unit.minutes");
//intensity can't currently be customized
}).grow().left().pad(6).top();
}).width(410f).pad(3).top().left().fillY();
if(++idx % cols == 0){
base.row();
}
}
};
rebuild[0].run();
}).grow();
dialog.addCloseButton();
dialog.buttons.button("@add", Icon.add, () -> {
BaseDialog addd = new BaseDialog("@add");
addd.cont.pane(t -> {
t.background(Tex.button);
int i = 0;
for(Weather weather : content.<Weather>getBy(ContentType.weather)){
t.button(weather.localizedName, Styles.cleart, () -> {
rules.weather.add(new WeatherEntry(weather));
rebuild[0].run();
addd.hide();
}).size(140f, 50f);
if(++i % 2 == 0) t.row();
}
});
addd.addCloseButton();
addd.show();
}).width(170f);
//reset cooldown to random number
dialog.hidden(() -> {
float sum = 0;
Seq<WeatherEntry> sh = rules.weather.copy();
sh.shuffle();
for(WeatherEntry w : sh){
//add the previous cooldowns to the sum so weather events are staggered and don't happen all at once.
w.cooldown = sum + Mathf.random(w.minFrequency, w.maxFrequency);
sum += w.cooldown;
}
});
dialog.show();
}
}

View File

@@ -56,7 +56,7 @@ public class DatabaseDialog extends BaseDialog{
for(int i = 0; i < array.size; i++){
UnlockableContent unlock = (UnlockableContent)array.get(i);
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)) : new Image(Icon.lock, Pal.gray);
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)).setScaling(Scaling.fit) : new Image(Icon.lock, Pal.gray);
list.add(image).size(8*4).pad(3);
ClickListener listener = new ClickListener();
image.addListener(listener);

View File

@@ -30,6 +30,7 @@ public class JoinDialog extends BaseDialog{
Table global = new Table();
Table hosts = new Table();
int totalHosts;
int refreshes;
public JoinDialog(){
super("@joingame");
@@ -95,6 +96,8 @@ public class JoinDialog extends BaseDialog{
}
void refreshAll(){
refreshes ++;
refreshLocal();
refreshRemote();
refreshGlobal();
@@ -327,12 +330,15 @@ public class JoinDialog extends BaseDialog{
}
void refreshGlobal(){
int cur = refreshes;
global.clear();
global.background(null);
for(String host : defaultServers){
String resaddress = host.contains(":") ? host.split(":")[0] : host;
int resport = host.contains(":") ? Strings.parseInt(host.split(":")[1]) : port;
net.pingHost(resaddress, resport, res -> {
if(refreshes != cur) return;
res.port = resport;
addGlobalHost(res);
}, e -> {});
@@ -406,7 +412,7 @@ public class JoinDialog extends BaseDialog{
void safeConnect(String ip, int port, int version){
if(version != Version.build && Version.build != -1 && version != -1){
ui.showInfo("[scarlet]" + (version > Version.build ? KickReason.clientOutdated : KickReason.serverOutdated).toString() + "\n[]" +
Core.bundle.format("server.versions", Version.build, version));
Core.bundle.format("server.versions", Version.build, version));
}else{
connect(ip, port);
}
@@ -427,7 +433,7 @@ public class JoinDialog extends BaseDialog{
}
//get servers
Core.net.httpGet(becontrol.active() ? serverJsonBeURL : serverJsonURL, result -> {
Core.net.httpGet(becontrol.active() ? serverJsonBeURL : serverJsonV6URL, result -> {
try{
Jval val = Jval.read(result.getResultAsString());
Core.app.post(() -> {

View File

@@ -18,10 +18,8 @@ import static mindustry.Vars.*;
/** Dialog for selecting loadout at sector launch. */
public class LaunchLoadoutDialog extends BaseDialog{
LoadoutDialog loadout = new LoadoutDialog();
//total as a map
ObjectIntMap<Item> totalMap = new ObjectIntMap<>();
//total required items
Seq<ItemStack> total = new Seq<>();
ItemSeq total = new ItemSeq();
//currently selected schematic
Schematic selected;
//validity of loadout items
@@ -34,21 +32,14 @@ public class LaunchLoadoutDialog extends BaseDialog{
public void show(CoreBlock core, Building build, Runnable confirm){
cont.clear();
buttons.clear();
totalMap.clear();
Seq<ItemStack> stacks = universe.getLaunchResources();
addCloseButton();
//updates sum requirements
Runnable update = () -> {
totalMap.clear();
total.clear();
selected.requirements().each(i -> totalMap.increment(i.item, i.amount));
universe.getLaunchResources().each(i -> totalMap.increment(i.item, i.amount));
for(Item item : content.items()){
if(totalMap.containsKey(item)) total.add(new ItemStack(item, totalMap.get(item)));
}
selected.requirements().each(total::add);
universe.getLaunchResources().each(total::add);
valid = build.items.has(total);
};
@@ -56,10 +47,18 @@ public class LaunchLoadoutDialog extends BaseDialog{
table.clearChildren();
int i = 0;
ItemSeq schems = selected.requirements();
ItemSeq launches = universe.getLaunchResources();
for(ItemStack s : total){
table.image(s.item.icon(Cicon.small)).left();
table.add((build.items.has(s.item, s.amount)) ? "[lightgray]" + s.amount + "" :
"[scarlet]" + (Math.min(build.items.get(s.item), s.amount) + "[lightgray]/" + s.amount)).padLeft(2).left().padRight(4);
int as = schems.get(s.item), al = launches.get(s.item);
String amountStr = "[lightgray]" + (al + " + [accent]" + as + "[lightgray]");
table.add(
build.items.has(s.item, s.amount) ? amountStr :
"[scarlet]" + (Math.min(build.items.get(s.item), s.amount) + "[lightgray]/" + amountStr)).padLeft(2).left().padRight(4);
if(++i % 4 == 0){
table.row();
@@ -72,8 +71,11 @@ public class LaunchLoadoutDialog extends BaseDialog{
Runnable rebuildItems = () -> rebuild.get(items);
buttons.button("@resources", Icon.terrain, () -> {
loadout.show(core.itemCapacity, stacks, UnlockableContent::unlocked, stacks::clear, () -> {}, () -> {
universe.updateLaunchResources(stacks);
ItemSeq stacks = universe.getLaunchResources();
Seq<ItemStack> out = stacks.toSeq();
loadout.show(core.itemCapacity, out, UnlockableContent::unlocked, out::clear, () -> {}, () -> {
universe.updateLaunchResources(new ItemSeq(out));
update.run();
rebuildItems.run();
});

View File

@@ -104,7 +104,7 @@ public class LoadDialog extends BaseDialog{
button.left().add(new BorderImage(def, 4f)).update(im -> {
TextureRegionDrawable draw = (TextureRegionDrawable)im.getDrawable();
if(draw.getRegion().getTexture().isDisposed()){
if(draw.getRegion().texture.isDisposed()){
draw.setRegion(def);
}

View File

@@ -16,6 +16,7 @@ public class LoadoutDialog extends BaseDialog{
private Runnable hider;
private Runnable resetter;
private Runnable updater;
//TODO use itemseqs
private Seq<ItemStack> stacks = new Seq<>();
private Seq<ItemStack> originalStacks = new Seq<>();
private Boolf<Item> validator = i -> true;

View File

@@ -54,7 +54,7 @@ public class MapsDialog extends BaseDialog{
Runnable show = () -> ui.loadAnd(() -> {
hide();
ui.editor.show();
ui.editor.editor.getTags().put("name", text);
ui.editor.editor.tags.put("name", text);
Events.fire(new MapMakeEvent());
});

View File

@@ -87,7 +87,7 @@ public class PausedDialog extends BaseDialog{
}else if(state.isCampaign()){
cont.buttonRow("@launchcore", Icon.up, () -> {
hide();
ui.planet.show(state.getSector(), player.team().core());
ui.planet.showLaunch(state.getSector(), player.team().core());
}).disabled(b -> player.team().core() == null);
cont.row();

View File

@@ -1,6 +1,7 @@
package mindustry.ui.dialogs;
import arc.*;
import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.graphics.gl.*;
@@ -29,17 +30,18 @@ import static mindustry.graphics.g3d.PlanetRenderer.*;
import static mindustry.ui.dialogs.PlanetDialog.Mode.*;
public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
private final FrameBuffer buffer = new FrameBuffer(2, 2, true);
final FrameBuffer buffer = new FrameBuffer(2, 2, true);
final PlanetRenderer planets = renderer.planets;
private final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog();
private final Table stable = new Table().background(Styles.black3);
final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog();
final Table stable = new Table().background(Styles.black3);
private int launchRange;
private float zoom = 1f, selectAlpha = 1f;
int launchRange;
float zoom = 1f, selectAlpha = 1f;
@Nullable Sector selected, hovered, launchSector;
private CoreBuild launcher;
CoreBuild launcher;
Mode mode = look;
private boolean launching;
boolean launching;
Cons<Sector> listener = s -> {};
public PlanetDialog(){
super("", Styles.fullDialog);
@@ -93,7 +95,25 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
return super.show();
}
public void show(Sector sector, CoreBuild launcher){
public void showSelect(Sector sector, Cons<Sector> listener){
selected = null;
hovered = null;
launching = false;
this.listener = listener;
//update view to sector
lookAt(sector);
zoom = 1f;
planets.zoom = 2f;
selectAlpha = 0f;
launchSector = sector;
mode = select;
super.show();
}
public void showLaunch(Sector sector, CoreBuild launcher){
if(launcher == null) return;
this.launcher = launcher;
@@ -118,7 +138,9 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
planets.camPos.set(Tmp.v33.set(sector.tile.v).rotate(Vec3.Y, -sector.planet.getRotation()));
}
boolean canLaunch(Sector sector){
boolean canSelect(Sector sector){
if(mode == select) return sector.hasBase();
return mode == launch &&
(sector.tile.v.within(launchSector.tile.v, (launchRange + 0.5f) * planets.planet.sectorApproxRadius*2) //within range
|| (sector.preset != null && sector.preset.unlocked())); //is an unlocked preset
@@ -131,7 +153,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
for(Sector sec : planet.sectors){
if(selectAlpha > 0.01f){
if(canLaunch(sec) || sec.unlocked()){
if(canSelect(sec) || sec.unlocked()){
if(sec.baseCoverage > 0){
planets.fill(sec, Tmp.c1.set(Team.crux.color).a(0.5f * sec.baseCoverage * selectAlpha), -0.002f);
}
@@ -169,8 +191,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
planets.batch.flush(Gl.triangles);
if(mode == launch){
if(hovered != launchSector && hovered != null && canLaunch(hovered)){
if(mode == launch || mode == select){
if(hovered != launchSector && hovered != null && canSelect(hovered)){
planets.drawArc(planet, launchSector.tile.v, hovered.tile.v);
}
}
@@ -193,7 +215,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
planets.drawPlane(hovered, () -> {
Draw.color(Color.white, Pal.accent, Mathf.absin(5f, 1f));
TextureRegion icon = hovered.locked() && !canLaunch(hovered) ? Icon.lock.getRegion() : null;
TextureRegion icon = hovered.locked() && !canSelect(hovered) ? Icon.lock.getRegion() : null;
if(icon != null){
Draw.rect(icon, 0, 0);
@@ -219,7 +241,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
addListener(new ElementGestureListener(){
@Override
public void tap(InputEvent event, float x, float y, int count, KeyCode button){
if(hovered != null && (mode == launch ? canLaunch(hovered) && hovered != launchSector : hovered.unlocked())){
if(hovered != null && (mode == launch ? canSelect(hovered) && hovered != launchSector : hovered.unlocked())){
selected = hovered;
}
@@ -239,7 +261,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
new Table(t -> {
//TODO localize
t.top();
t.label(() -> mode == launch ? "Select Launch Sector" : "Turn " + universe.turn()).style(Styles.outlineLabel).color(Pal.accent);
t.label(() -> mode == select ? "@sectors.select" : mode == launch ? "Select Launch Sector" : "Turn " + universe.turn()).style(Styles.outlineLabel).color(Pal.accent);
})).grow();
}
@@ -321,16 +343,25 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
stable.row();
}
stable.add("@sectors.resources").row();
stable.table(t -> {
t.left();
int idx = 0;
int max = 5;
for(UnlockableContent c : sector.data.resources){
t.image(c.icon(Cicon.small)).padRight(3);
if(++idx % max == 0) t.row();
}
}).fillX().row();
if(sector.save != null){
stable.add("@sectors.resources").row();
stable.table(t -> {
if(sector.save != null && sector.save.meta.secinfo != null && sector.save.meta.secinfo.resources.any()){
t.left();
int idx = 0;
int max = 5;
for(UnlockableContent c : sector.save.meta.secinfo.resources){
t.image(c.icon(Cicon.small)).padRight(3);
if(++idx % max == 0) t.row();
}
}else{
t.add("@unknown").color(Color.lightGray);
}
}).fillX().row();
}
//production
if(sector.hasBase() && sector.save.meta.hasProduction){
@@ -373,13 +404,13 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
stable.row();
if((sector.hasBase() && mode == look) || canLaunch(sector) || (sector.preset != null && sector.preset.alwaysUnlocked)){
stable.button(sector.hasBase() ? "@sectors.resume" : "@sectors.launch", Styles.transt, () -> {
if((sector.hasBase() && mode == look) || canSelect(sector) || (sector.preset != null && sector.preset.alwaysUnlocked)){
stable.button(mode == select ? "@sectors.select" : sector.hasBase() ? "@sectors.resume" : "@sectors.launch", Styles.transt, () -> {
boolean shouldHide = true;
//save before launch.
if(control.saves.getCurrent() != null && state.isGame()){
if(control.saves.getCurrent() != null && state.isGame() && mode != select){
try{
control.saves.getCurrent().save();
}catch(Throwable e){
@@ -399,12 +430,14 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
ui.hudfrag.showLaunchDirect();
Time.runTask(launchDuration, () -> control.playSector(current, sector));
});
}else if(mode == select){
listener.get(sector);
}else{
control.playSector(sector);
}
if(shouldHide) hide();
}).growX().padTop(2f).height(50f).minWidth(170f);
}).growX().padTop(2f).height(50f).minWidth(170f).disabled(b -> state.rules.sector == sector && !state.isMenu());
}
stable.pack();
@@ -435,6 +468,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
/** Look around for existing sectors. Can only deploy. */
look,
/** Launch to a new location. */
launch
launch,
/** Select a sector for some purpose. */
select
}
}

View File

@@ -340,7 +340,7 @@ public class ResearchDialog extends BaseDialog{
button.update(() -> {
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 = !locked(node.node) ? Tex.buttonOver : selectable(node.node) && !canSpend(node.node) ? Tex.buttonRed : Tex.button;
button.getStyle().up = !locked(node.node) ? Tex.buttonOver : !selectable(node.node) || !canSpend(node.node) ? Tex.buttonRed : Tex.button;
((TextureRegionDrawable)button.getStyle().imageUp).setRegion(node.selectable ? node.node.content.icon(Cicon.medium) : Icon.lock.getRegion());
button.getImage().setColor(!locked(node.node) ? Color.white : node.selectable ? Color.gray : Pal.gray);
@@ -377,8 +377,18 @@ public class ResearchDialog extends BaseDialog{
}
boolean canSpend(TechNode node){
//can spend when there's at least 1 item that can be spent
return selectable(node) && (node.requirements.length == 0 || Structs.contains(node.requirements, i -> items.has(i.item)));
if(!selectable(node)) return false;
if(node.requirements.length == 0) return true;
//can spend when there's at least 1 item that can be spent (non complete)
for(int i = 0; i < node.requirements.length; i++){
if(node.finishedRequirements[i].amount < node.requirements[i].amount && items.has(node.requirements[i].item)){
return true;
}
}
return false;
}
void spend(TechNode node){

View File

@@ -10,8 +10,8 @@ import arc.scene.ui.*;
import arc.scene.ui.ImageButton.*;
import arc.scene.ui.TextButton.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.Vars;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
@@ -64,8 +64,12 @@ public class SchematicsDialog extends BaseDialog{
t.update(() -> {
if(Core.input.keyTap(Binding.chat) && Core.scene.getKeyboardFocus() == searchField && firstSchematic != null){
control.input.useSchematic(firstSchematic);
hide();
if(!Vars.state.rules.schematicsAllowed){
ui.showInfo("@schematic.disabled");
}else{
control.input.useSchematic(firstSchematic);
hide();
}
}
});
@@ -146,8 +150,12 @@ public class SchematicsDialog extends BaseDialog{
if(state.isMenu()){
showInfo(s);
}else{
control.input.useSchematic(s);
hide();
if(!Vars.state.rules.schematicsAllowed){
ui.showInfo("@schematic.disabled");
}else{
control.input.useSchematic(s);
hide();
}
}
}).pad(4).style(Styles.cleari).get();
@@ -333,7 +341,7 @@ public class SchematicsDialog extends BaseDialog{
cont.add(new SchematicImage(schem)).maxSize(800f);
cont.row();
Seq<ItemStack> arr = schem.requirements();
ItemSeq arr = schem.requirements();
cont.table(r -> {
int i = 0;
for(ItemStack s : arr){

View File

@@ -86,14 +86,14 @@ public class SettingsMenuDialog extends SettingsDialog{
dataDialog.addCloseButton();
dataDialog.cont.table(Tex.button, t -> {
t.defaults().size(270f, 60f).left();
t.defaults().size(280f, 60f).left();
TextButtonStyle style = Styles.cleart;
t.button("@settings.cleardata", Icon.trash, style, () -> ui.showConfirm("@confirm", "@settings.clearall.confirm", () -> {
ObjectMap<String, Object> map = new ObjectMap<>();
for(String value : Core.settings.keys()){
if(value.contains("usid") || value.contains("uuid")){
map.put(value, Core.settings.getString(value));
map.put(value, Core.settings.get(value, null));
}
}
Core.settings.clear();
@@ -419,6 +419,9 @@ public class SettingsMenuDialog extends SettingsDialog{
zipped.walk(f -> f.copyTo(base.child(f.path())));
dest.delete();
//load data so it's saved on exit
settings.load();
}
private void back(){

View File

@@ -57,7 +57,7 @@ public class ChatFragment extends Table{
}
}
return net.active();
return net.active() && ui.hudfrag.shown();
});
update(() -> {
@@ -227,6 +227,7 @@ public class ChatFragment extends Table{
}
public void addMessage(String message, String sender){
if(sender == null && message == null) return;
messages.insert(0, new ChatMessage(message, sender));
fadetime += 1f;
@@ -244,7 +245,7 @@ public class ChatFragment extends Table{
this.message = message;
this.sender = sender;
if(sender == null){ //no sender, this is a server message?
formattedMessage = message;
formattedMessage = message == null ? "" : message;
}else{
formattedMessage = "[coral][[" + sender + "[coral]]:[white] " + message;
}

View File

@@ -1,7 +1,9 @@
package mindustry.ui.fragments;
import arc.*;
import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.input.*;
import arc.math.*;
import arc.scene.*;
@@ -29,10 +31,14 @@ import mindustry.ui.dialogs.*;
import static mindustry.Vars.*;
public class HudFragment extends Fragment{
private static final float dsize = 47f;
private static final float dsize = 65f;
public final PlacementFragment blockfrag = new PlacementFragment();
//TODO localize
public String sectorText = "Out of sector time.";
public Seq<Sector> attackedSectors = new Seq<>();
private ImageButton flip;
private Table lastUnlockTable;
private Table lastUnlockLayout;
@@ -64,16 +70,25 @@ public class HudFragment extends Fragment{
coreItems.clear();
});
Events.on(TurnEvent.class, e -> {
ui.announce("[accent][[ Turn " + universe.turn() + " ]");
});
//paused table
parent.fill(t -> {
t.top().visible(() -> state.isPaused() && !state.isOutOfTime()).touchable = Touchable.disabled;
t.table(Styles.black5, top -> top.add("@paused").style(Styles.outlineLabel).pad(8f)).growX();
});
//minimap + position
parent.fill(t -> {
t.visible(() -> Core.settings.getBool("minimap") && !state.rules.tutorial && shown);
//minimap
t.add(new Minimap());
t.row();
//position
t.label(() -> player.tileX() + "," + player.tileY())
.visible(() -> Core.settings.getBool("position") && !state.rules.tutorial)
.touchable(Touchable.disabled);
t.top().right();
});
//TODO tear this all down
//menu at top left
parent.fill(cont -> {
@@ -147,48 +162,54 @@ public class HudFragment extends Fragment{
cont.stack(wavesMain = new Table(), editorMain = new Table()).height(wavesMain.getPrefHeight());
{
wavesMain.visible(() -> shown && !state.isEditor());
wavesMain.top().left();
Stack stack = new Stack();
Button waves = new Button(Styles.waveb);
Table btable = new Table().margin(0);
wavesMain.visible(() -> shown && !state.isEditor());
wavesMain.top().left();
stack.add(waves);
stack.add(btable);
wavesMain.table(s -> {
//wave info button with text
s.add(makeStatusTable()).grow();
addWaveTable(waves);
addPlayButton(btable);
wavesMain.add(stack).width(dsize * 5 + 4f);
wavesMain.row();
wavesMain.table(Tex.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(() -> state.rules.waves && state.boss() != null).height(60f).get();
wavesMain.row();
}
//table with button to skip wave
s.button(Icon.play, Styles.righti, 30f, () -> {
if(net.client() && player.admin){
Call.adminRequest(player, AdminAction.wave);
}else if(inLaunchWave()){
ui.showConfirm("@confirm", "@launch.skip.confirm", () -> !canSkipWave(), () -> logic.skipWave());
}else{
logic.skipWave();
}
}).growY().fillX().right().width(40f).disabled(b -> !canSkipWave()).visible(() -> state.rules.waves);
}).width(dsize * 5 + 4f);
{
editorMain.table(Tex.buttonEdge4, t -> {
//t.margin(0f);
t.add("@editor.teams").growX().left();
t.row();
t.table(teams -> {
teams.left();
int i = 0;
for(Team team : Team.baseTeams){
ImageButton button = teams.button(Tex.whiteui, Styles.clearTogglePartiali, 40f, () -> Call.setPlayerTeamEditor(player, team))
.size(50f).margin(6f).get();
button.getImageCell().grow();
button.getStyle().imageUpColor = team.color;
button.update(() -> button.setChecked(player.team() == team));
wavesMain.row();
if(++i % 3 == 0){
teams.row();
}
wavesMain.table(Tex.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(() -> state.rules.waves && state.boss() != null).height(60f).get();
wavesMain.row();
editorMain.table(Tex.buttonEdge4, t -> {
//t.margin(0f);
t.add("@editor.teams").growX().left();
t.row();
t.table(teams -> {
teams.left();
int i = 0;
for(Team team : Team.baseTeams){
ImageButton button = teams.button(Tex.whiteui, Styles.clearTogglePartiali, 40f, () -> Call.setPlayerTeamEditor(player, team))
.size(50f).margin(6f).get();
button.getImageCell().grow();
button.getStyle().imageUpColor = team.color;
button.update(() -> button.setChecked(player.team() == team));
if(++i % 3 == 0){
teams.row();
}
}).left();
}).width(dsize * 5 + 4f);
editorMain.visible(() -> shown && state.isEditor());
}
}
}).left();
}).width(dsize * 5 + 4f);
editorMain.visible(() -> shown && state.isEditor());
//fps display
cont.table(info -> {
@@ -204,18 +225,6 @@ public class HudFragment extends Fragment{
}).top().left();
});
parent.fill(t -> {
t.visible(() -> Core.settings.getBool("minimap") && !state.rules.tutorial && shown);
//minimap
t.add(new Minimap());
t.row();
//position
t.label(() -> player.tileX() + "," + player.tileY())
.visible(() -> Core.settings.getBool("position") && !state.rules.tutorial)
.touchable(Touchable.disabled);
t.top().right();
});
//core items
parent.fill(t -> {
t.top().add(coreItems);
@@ -272,20 +281,30 @@ public class HudFragment extends Fragment{
parent.fill(t -> {
t.top().visible(() -> state.isOutOfTime());
t.table(Styles.black5, top -> {
//TODO localize when done
top.add("Out of sector time.").style(Styles.outlineLabel).color(Pal.accent).update(l -> l.color.a = Mathf.absin(Time.globalTime(), 7f, 1f)).colspan(2);
//TODO localize
top.add(sectorText).style(Styles.outlineLabel).color(Pal.accent).update(l -> {
l.color.a = Mathf.absin(Time.globalTime(), 7f, 1f);
l.setText(sectorText);
}).colspan(2);
top.row();
top.defaults().pad(2).size(150f, 54f);
top.button("Next Turn", () -> {
//TODO localize
top.button("Skip", () -> {
universe.runTurn();
state.set(State.playing);
//announce turn info only when something is skipped.
ui.announce("[accent][[ Turn " + universe.turn() + " ]\n[scarlet]" + attackedSectors.size + "[lightgray] sector(s) attacked.");
});
top.button("Back to Planet", () -> {
//TODO localize
top.button("Switch Sectors", () -> {
ui.paused.runExitSave();
ui.planet.show();
});
//switch to first attacked sector
control.playSector(attackedSectors.first());
}).disabled(b -> attackedSectors.isEmpty());
}).margin(8).growX();
});
@@ -331,6 +350,7 @@ public class HudFragment extends Fragment{
});
//TODO DEBUG: rate table
if(false)
parent.fill(t -> {
t.bottom().left();
t.table(Styles.black6, c -> {
@@ -598,7 +618,9 @@ public class HudFragment extends Fragment{
shown = !shown;
}
private void addWaveTable(Button table){
private Table makeStatusTable(){
Button table = new Button(Styles.waveb);
StringBuilder ibuild = new StringBuilder();
IntFormat wavef = new IntFormat("wave");
@@ -625,6 +647,106 @@ public class HudFragment extends Fragment{
StringBuilder builder = new StringBuilder();
table.name = "waves";
table.marginTop(0).marginBottom(4).marginLeft(4);
class SideBar extends Element{
public final Floatp amount;
public final boolean flip;
public final Boolp flash;
float last, blink, value;
public SideBar(Floatp amount, Boolp flash, boolean flip){
this.amount = amount;
this.flip = flip;
this.flash = flash;
setColor(Pal.health);
}
@Override
public void draw(){
float next = amount.get();
if(next < last && flash.get()){
blink = 1f;
}
blink = Mathf.lerpDelta(blink, 0f, 0.2f);
value = Mathf.lerpDelta(value, next, 0.15f);
last = next;
drawInner(Pal.darkishGray);
Draw.beginStencil();
Fill.crect(x, y, width, height * value);
Draw.beginStenciled();
drawInner(Tmp.c1.set(color).lerp(Color.white, blink));
Draw.endStencil();
}
void drawInner(Color color){
if(flip){
x += width;
width = -width;
}
float stroke = width * 0.35f;
float bh = height/2f;
Draw.color(color);
Fill.quad(
x, y,
x + stroke, y,
x + width, y + bh,
x + width - stroke, y + bh
);
Fill.quad(
x + width, y + bh,
x + width - stroke, y + bh,
x, y + height,
x + stroke, y + height
);
Draw.reset();
if(flip){
width = -width;
x -= width;
}
}
}
table.stack(
new Element(){
@Override
public void draw(){
Draw.color(Pal.darkerGray);
Fill.poly(x + width/2f, y + height/2f, 6, height / Mathf.sqrt3);
Draw.reset();
Drawf.shadow(x + width/2f, y + height/2f, height * 1.13f);
}
},
new Table(t -> {
float bw = 40f;
float pad = -20;
t.margin(0);
t.add(new SideBar(() -> player.unit().healthf(), () -> true, true)).width(bw).growY().padRight(pad);
t.image(() -> player.icon()).scaling(Scaling.bounded).grow().maxWidth(54f);
t.add(new SideBar(() -> player.dead() ? 0f : player.displayAmmo() ? player.unit().ammof() : player.unit().healthf(), () -> !player.displayAmmo(), false)).width(bw).growY().padLeft(pad).update(b -> {
b.color.set(player.displayAmmo() ? player.dead() ? Pal.ammo : player.unit().type().ammoType.color : Pal.health);
});
t.getChildren().get(1).toFront();
})).size(120f, 80).padRight(4);
table.labelWrap(() -> {
builder.setLength(0);
builder.append(wavef.get(state.wave));
@@ -671,22 +793,12 @@ public class HudFragment extends Fragment{
showLaunchConfirm();
}
});
return table;
}
private boolean canSkipWave(){
return state.rules.waves && ((net.server() || player.admin) || !net.active()) && state.enemies == 0 && !spawner.isSpawning() && !state.rules.tutorial;
}
private void addPlayButton(Table table){
table.right().button(Icon.play, Styles.righti, 30f, () -> {
if(net.client() && player.admin){
Call.adminRequest(player, AdminAction.wave);
}else if(inLaunchWave()){
ui.showConfirm("@confirm", "@launch.skip.confirm", () -> !canSkipWave(), () -> logic.skipWave());
}else{
logic.skipWave();
}
}).growY().fillX().right().width(40f)
.visible(this::canSkipWave);
}
}

View File

@@ -73,13 +73,12 @@ public class MenuFragment extends Fragment{
}));
}
String versionText = "[#ffffffba]" + ((Version.build == -1) ? "[#fc8140aa]custom build" : (Version.type.equals("official") ? Version.modifier : Version.type) + " build " + Version.build + (Version.revision == 0 ? "" : "." + Version.revision));
String versionText = ((Version.build == -1) ? "[#fc8140aa]" : "[#ffffffba]") + Version.combined();
parent.fill((x, y, w, h) -> {
TextureRegion logo = Core.atlas.find("logo");
float logoscl = Scl.scl(1);
float logow = Math.min(logo.getWidth() * logoscl, Core.graphics.getWidth() - Scl.scl(20));
float logoh = logow * (float)logo.getHeight() / logo.getWidth();
float logow = Math.min(logo.width * logoscl, Core.graphics.getWidth() - Scl.scl(20));
float logoh = logow * (float)logo.height / logo.width;
float fx = (int)(Core.graphics.getWidth() / 2f);
float fy = (int)(Core.graphics.getHeight() - 6 - logoh) + logoh / 2 - (Core.graphics.isPortrait() ? Scl.scl(30f) : 0f);

View File

@@ -32,7 +32,7 @@ public class MinimapFragment extends Fragment{
if(renderer.minimap.getTexture() != null){
Draw.color();
float ratio = (float)renderer.minimap.getTexture().getHeight() / renderer.minimap.getTexture().getWidth();
float ratio = (float)renderer.minimap.getTexture().height / renderer.minimap.getTexture().getWidth();
TextureRegion reg = Draw.wrap(renderer.minimap.getTexture());
Draw.rect(reg, w/2f + panx*zoom, h/2f + pany*zoom, size, size * ratio);
renderer.minimap.drawEntities(w/2f + panx*zoom - size/2f, h/2f + pany*zoom - size/2f * ratio, size, size * ratio, zoom, true);
@@ -113,7 +113,7 @@ public class MinimapFragment extends Fragment{
public void toggle(){
if(Core.settings.getBool("mapcenter")){
float size = baseSize * zoom * world.width();
float ratio = (float)renderer.minimap.getTexture().getHeight() / renderer.minimap.getTexture().getWidth();
float ratio = (float)renderer.minimap.getTexture().height / renderer.minimap.getTexture().getWidth();
panx = (size/2f - player.x() / (world.width() * tilesize) * size) / zoom;
pany = (size*ratio/2f - player.y() / (world.height() * tilesize) * size*ratio) / zoom;
}

View File

@@ -31,7 +31,7 @@ public class PlacementFragment extends Fragment{
final int rowWidth = 4;
public Category currentCategory = Category.distribution;
Seq<Block> returnArray = new Seq<>();
Seq<Block> returnArray = new Seq<>(), returnArray2 = new Seq<>();
Seq<Category> returnCatArray = new Seq<>();
boolean[] categoryEmpty = new boolean[Category.all.length];
ObjectMap<Category,Block> selectedBlocks = new ObjectMap<>();
@@ -422,7 +422,7 @@ public class PlacementFragment extends Fragment{
}
Seq<Block> getUnlockedByCategory(Category cat){
return returnArray.selectFrom(content.blocks(), block -> block.category == cat && block.isVisible() && unlocked(block)).sort((b1, b2) -> Boolean.compare(!b1.isPlaceable(), !b2.isPlaceable()));
return returnArray2.selectFrom(content.blocks(), block -> block.category == cat && block.isVisible() && unlocked(block)).sort((b1, b2) -> Boolean.compare(!b1.isPlaceable(), !b2.isPlaceable()));
}
Block getSelectedBlock(Category cat){