diff --git a/core/assets-raw/sprites/ui/sideline-over.9.png b/core/assets-raw/sprites/ui/sideline-over.9.png new file mode 100644 index 0000000000..fec86b6d35 Binary files /dev/null and b/core/assets-raw/sprites/ui/sideline-over.9.png differ diff --git a/core/assets-raw/sprites/ui/sideline.9.png b/core/assets-raw/sprites/ui/sideline.9.png new file mode 100644 index 0000000000..4a5413a685 Binary files /dev/null and b/core/assets-raw/sprites/ui/sideline.9.png differ diff --git a/core/assets-raw/sprites/ui/underline-over.9.png b/core/assets-raw/sprites/ui/underline-over.9.png new file mode 100644 index 0000000000..d138927c1a Binary files /dev/null and b/core/assets-raw/sprites/ui/underline-over.9.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 1e359ee633..06c77ad450 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -564,6 +564,8 @@ weather.sandstorm.name = Sandstorm weather.sporestorm.name = Sporestorm weather.fog.name = Fog +sectorlist = Sectors +sectorlist.attacked = {0} under attack sectors.unexplored = [lightgray]Unexplored sectors.resources = Resources: sectors.production = Production: diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 0aa8f45175..bff3ae1f76 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -325,7 +325,7 @@ public class UnitType extends UnlockableContent{ singleTarget = weapons.size <= 1 && !forceMultiTarget; if(itemCapacity < 0){ - itemCapacity = Math.max(Mathf.round((int)(hitSize * 4.3), 10), 10); + itemCapacity = Math.max(Mathf.round((int)(hitSize * 4f), 10), 10); } //assume slight range margin diff --git a/core/src/mindustry/ui/Styles.java b/core/src/mindustry/ui/Styles.java index 36a3ace7d2..6a693b881c 100644 --- a/core/src/mindustry/ui/Styles.java +++ b/core/src/mindustry/ui/Styles.java @@ -26,8 +26,8 @@ import static mindustry.gen.Tex.*; public class Styles{ //TODO all these names are inconsistent and not descriptive public static Drawable black, black9, black8, black6, black3, black5, none, flatDown, flatOver, accentDrawable; - public static ButtonStyle defaultb, waveb, modsb; - public static TextButtonStyle defaultt, squaret, nodet, cleart, discordt, nonet, infot, clearPartialt, clearTogglet, logicTogglet, clearToggleMenut, togglet, transt, fullTogglet, logict; + public static ButtonStyle defaultb, waveb, modsb, underlineb; + public static TextButtonStyle defaultt, squaret, nodet, cleart, discordt, nonet, infot, clearPartialt, clearTogglet, logicTogglet, clearToggleMenut, togglet, transt, fullTogglet, squareTogglet, logict; public static ImageButtonStyle defaulti, nodei, righti, emptyi, emptytogglei, selecti, logici, geni, colori, accenti, cleari, clearFulli, clearPartiali, clearPartial2i, clearTogglei, clearTransi, clearToggleTransi, clearTogglePartiali; public static ScrollPaneStyle defaultPane, horizontalPane, smallPane, nonePane; public static KeybindDialog.KeybindDialogStyle defaultKeybindDialog; @@ -62,7 +62,14 @@ public class Styles{ modsb = new ButtonStyle(){{ down = flatOver; up = underline; - over = underlineWhite; + over = underline2; + }}; + + underlineb = new ButtonStyle(){{ + down = flatOver; + up = sideline; + over = sidelineOver; + checked = flatOver; }}; waveb = new ButtonStyle(){{ @@ -196,6 +203,16 @@ public class Styles{ disabled = black; disabledFontColor = Color.gray; }}; + squareTogglet = new TextButtonStyle(){{ + font = Fonts.def; + fontColor = Color.white; + checked = flatOver; + down = flatOver; + up = pane; + over = flatOver; + disabled = black; + disabledFontColor = Color.gray; + }}; defaulti = new ImageButtonStyle(){{ down = buttonDown; up = button; diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index a41428d6fc..7e1e68d2b7 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -61,9 +61,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ public Seq newPresets = new Seq<>(); public float presetShow = 0f; - public boolean showed = false; + public boolean showed = false, sectorsShown; + public String searchText = ""; - public Table sectorTop = new Table(); + public Table sectorTop = new Table(), notifs; public Label hoverLabel = new Label(""); public PlanetDialog(){ @@ -73,17 +74,22 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ planets.planet = content.getByName(ContentType.planet, Core.settings.getString("lastplanet", "serpulo")); if(planets.planet == null) planets.planet = Planets.serpulo; - keyDown(key -> { - if(key == KeyCode.escape || key == KeyCode.back || key == Core.keybinds.get(Binding.planet_map).key){ - if(showing() && newPresets.size > 1){ - //clear all except first, which is the last sector. - newPresets.truncate(1); - }else if(selected != null){ - selected = null; - updateSelected(); - }else{ - Core.app.post(this::hide); + addListener(new InputListener(){ + @Override + public boolean keyDown(InputEvent event, KeyCode key){ + if(event.targetActor == PlanetDialog.this && (key == KeyCode.escape || key == KeyCode.back || key == Core.keybinds.get(Binding.planet_map).key)){ + if(showing() && newPresets.size > 1){ + //clear all except first, which is the last sector. + newPresets.truncate(1); + }else if(selected != null){ + selected = null; + updateSelected(); + }else{ + Core.app.post(() -> hide()); + } + return true; } + return false; } }); @@ -120,8 +126,14 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ pos.rotate(Tmp.v31.set(planets.cam.up).rotate(planets.cam.direction, 90), amount); }); - scrolled(value -> { - zoom = Mathf.clamp(zoom + value / 10f, 0.5f, 2f); + addListener(new InputListener(){ + @Override + public boolean scrolled(InputEvent event, float x, float y, float amountX, float amountY){ + if(event.targetActor == PlanetDialog.this){ + zoom = Mathf.clamp(zoom + y / 10f, 0.5f, 2f); + } + return true; + } }); addCaptureListener(new ElementGestureListener(){ @@ -449,6 +461,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } void setup(){ + searchText = ""; zoom = planets.zoom = 1f; selectAlpha = 1f; ui.minimapfrag.hide(); @@ -481,13 +494,19 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ }); } + @Override + public void act(float delta){ + if(scene.getDialog() == PlanetDialog.this && !scene.hit(input.mouseX(), input.mouseY(), true).isDescendantOf(e -> e instanceof ScrollPane)){ + scene.setScrollFocus(PlanetDialog.this); + } + + super.act(delta); + } + @Override public void draw(){ planets.orbitAlpha = selectAlpha; planets.render(PlanetDialog.this); - if(Core.scene.getDialog() == PlanetDialog.this){ - Core.scene.setScrollFocus(PlanetDialog.this); - } } }, //info text @@ -513,7 +532,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ selected = null; launchSector = null; renderer.planets.planet = planet; - Core.settings.put("lastplanet", planet.name); + settings.put("lastplanet", planet.name); }).width(200).height(40).growX().update(bb -> bb.setChecked(renderer.planets.planet == planet)); pt.row(); } @@ -522,11 +541,95 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } }), - new Table(t -> { - t.top(); - //t.add(sectorTop); - })).grow(); + new Table(c -> { + if(!(graphics.isPortrait() && mobile) && planets.planet.sectors.contains(Sector::hasBase)){ + int attacked = planets.planet.sectors.count(Sector::isAttacked); + //sector notifications & search + c.top().right(); + c.defaults().width(280f); + + c.button(bundle.get("sectorlist") + + (attacked == 0 ? "" : "\n[red]⚠[lightgray] " + bundle.format("sectorlist.attacked", "[red]" + attacked + "[]")), + Icon.downOpen, Styles.squareTogglet, () -> sectorsShown = !sectorsShown) + .height(60f).checked(b -> { + Image image = (Image)b.getCells().first().get(); + image.setDrawable(sectorsShown ? Icon.upOpen : Icon.downOpen); + return sectorsShown; + }).with(t -> t.left().margin(7f)).with(t -> t.getLabelCell().grow().left()).row(); + + c.collapser(t -> { + t.background(Styles.black8); + + notifs = t; + rebuildList(); + }, false, () -> sectorsShown).padBottom(64f).row(); + } + })).grow(); + } + + //TODO + void rebuildList(){ + notifs.clear(); + + var all = planets.planet.sectors.select(Sector::hasBase); + all.sort(Structs.comps(Structs.comparingBool(s -> !s.isAttacked()), Structs.comparingInt(s -> s.save == null ? 0 : -(int)s.save.meta.timePlayed))); + + notifs.pane(p -> { + Runnable[] readd = {null}; + + p.table(s -> { + s.image(Icon.zoom).padRight(4); + s.field(searchText, t -> { + searchText = t; + readd[0].run(); + }).growX().height(50f).addInputDialog(); + }).growX().row(); + + Table con = p.table().growX().get(); + con.touchable = Touchable.enabled; + + readd[0] = () -> { + con.clearChildren(); + for(Sector sec : all){ + if(sec.hasBase() && (searchText.isEmpty() || sec.name().toLowerCase().contains(searchText.toLowerCase()))){ + con.button(t -> { + t.left(); + t.defaults().growX(); + + t.table(head -> { + head.left().defaults(); + + if(sec.isAttacked()){ + head.image(Icon.warningSmall).update(i -> { + i.color.set(Pal.accent).lerp(Pal.remove, Mathf.absin(Time.globalTime, 9f, 1f)); + }).padRight(4f); + } + + String ic = sec.iconChar() == null ? "" : sec.iconChar() + " "; + + head.add(ic + sec.name()).growX().wrap(); + }).growX().row(); + + if(sec.isAttacked()){ + addSurvivedInfo(sec, t, true); + } + }, Styles.underlineb, () -> { + lookAt(sec); + selected = sec; + updateSelected(); + }).margin(8f).marginLeft(13f).marginBottom(6f).marginTop(6f).padBottom(3f).padTop(3f).growX().checked(b -> selected == sec).row(); + //for resources: .tooltip(sec.info.resources.toString("", u -> u.emoji())) + } + } + + if(con.getChildren().isEmpty()){ + con.add("@none.found").pad(10f); + } + }; + + readd[0].run(); + }).grow().get().setScrollingDisabled(true, false); } @Override @@ -725,6 +828,19 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ dialog.show(); } + void addSurvivedInfo(Sector sector, Table table, boolean wrap){ + if(!wrap){ + table.add(Core.bundle.format("sectors.underattack", (int)(sector.info.damage * 100))).wrapLabel(wrap).row(); + } + + if(sector.info.wavesSurvived >= 0 && sector.info.wavesSurvived - sector.info.wavesPassed >= 0 && !sector.isBeingPlayed()){ + int toCapture = sector.info.attack || sector.info.winWave <= 1 ? -1 : sector.info.winWave - (sector.info.wave + sector.info.wavesPassed); + boolean plus = (sector.info.wavesSurvived - sector.info.wavesPassed) >= SectorDamage.maxRetWave - 1; + table.add(Core.bundle.format("sectors.survives", Math.min(sector.info.wavesSurvived - sector.info.wavesPassed, toCapture <= 0 ? 200 : toCapture) + + (plus ? "+" : "") + (toCapture < 0 ? "" : "/" + toCapture))).wrapLabel(wrap).row(); + } + } + void updateSelected(){ Sector sector = selected; Table stable = sectorTop; @@ -749,6 +865,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ ui.showTextInput("@sectors.rename", "@name", 20, sector.name(), v -> { sector.setName(v); updateSelected(); + rebuildList(); }); }).size(40f).padLeft(4); } @@ -761,6 +878,14 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ new Dialog(""){{ closeOnBack(); setFillParent(true); + + Runnable refresh = () -> { + sector.saveInfo(); + hide(); + updateSelected(); + rebuildList(); + }; + cont.pane(t -> { resized(true, () -> { t.clearChildren(); @@ -770,9 +895,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ t.button(Icon.none, Styles.clearTogglei, () -> { sector.info.icon = null; sector.info.contentIcon = null; - sector.saveInfo(); - hide(); - updateSelected(); + refresh.run(); }).checked(sector.info.icon == null && sector.info.contentIcon == null); int cols = (int)Math.min(20, Core.graphics.getWidth() / Scl.scl(52f)); @@ -784,9 +907,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ t.button(value, Styles.clearTogglei, () -> { sector.info.icon = key; sector.info.contentIcon = null; - sector.saveInfo(); - hide(); - updateSelected(); + refresh.run(); }).checked(key.equals(sector.info.icon)); if(++i % cols == 0) t.row(); @@ -803,9 +924,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ t.button(new TextureRegionDrawable(u.uiIcon), Styles.clearTogglei, iconMed, () -> { sector.info.icon = null; sector.info.contentIcon = u; - sector.saveInfo(); - hide(); - updateSelected(); + refresh.run(); }).checked(sector.info.contentIcon == u); if(++i % cols == 0) t.row(); @@ -840,16 +959,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } if(sector.isAttacked()){ - stable.add(Core.bundle.format("sectors.underattack", (int)(sector.info.damage * 100))); - stable.row(); - - if(sector.info.wavesSurvived >= 0 && sector.info.wavesSurvived - sector.info.wavesPassed >= 0 && !sector.isBeingPlayed()){ - int toCapture = sector.info.attack || sector.info.winWave <= 1 ? -1 : sector.info.winWave - (sector.info.wave + sector.info.wavesPassed); - boolean plus = (sector.info.wavesSurvived - sector.info.wavesPassed) >= SectorDamage.maxRetWave - 1; - stable.add(Core.bundle.format("sectors.survives", Math.min(sector.info.wavesSurvived - sector.info.wavesPassed, toCapture <= 0 ? 200 : toCapture) + - (plus ? "+" : "") + (toCapture < 0 ? "" : "/" + toCapture))); - stable.row(); - } + addSurvivedInfo(sector, stable, false); }else if(sector.hasBase() && sector.near().contains(Sector::hasEnemyBase)){ stable.add("@sectors.vulnerable"); stable.row(); @@ -886,6 +996,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ stable.pack(); stable.setPosition(x, y, Align.center); + //do not fade out for now, TODO remove? + /* stable.update(() -> { if(selected != null){ if(launching){ @@ -901,7 +1013,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } } } - }); + });*/ stable.act(0f); } diff --git a/core/src/mindustry/ui/dialogs/SchematicsDialog.java b/core/src/mindustry/ui/dialogs/SchematicsDialog.java index cdafcf0e80..e054772b62 100644 --- a/core/src/mindustry/ui/dialogs/SchematicsDialog.java +++ b/core/src/mindustry/ui/dialogs/SchematicsDialog.java @@ -69,7 +69,7 @@ public class SchematicsDialog extends BaseDialog{ searchField = s.field(search, res -> { search = res; rebuildPane.run(); - }).growX().get(); + }).growX().addInputDialog().get(); }).fillX().padBottom(4); cont.row(); diff --git a/core/src/mindustry/ui/fragments/HintsFragment.java b/core/src/mindustry/ui/fragments/HintsFragment.java index b548a5536c..059af19994 100644 --- a/core/src/mindustry/ui/fragments/HintsFragment.java +++ b/core/src/mindustry/ui/fragments/HintsFragment.java @@ -48,7 +48,7 @@ public class HintsFragment extends Fragment{ }else if(!current.show()){ //current became hidden hide(); } - }else if(hints.size > 0){ + }else if(hints.size > 0 && !renderer.isCutscene()){ //check one hint each frame to see if it should be shown. Hint hint = hints.find(Hint::show); if(hint != null && hint.complete()){ @@ -163,7 +163,7 @@ public class HintsFragment extends Fragment{ schematicSelect(visibleDesktop, () -> ui.hints.placedBlocks.contains(Blocks.router), () -> Core.input.keyRelease(Binding.schematic_select) || Core.input.keyTap(Binding.pick)), conveyorPathfind(() -> control.input.block == Blocks.titaniumConveyor, () -> Core.input.keyRelease(Binding.diagonal_placement) || (mobile && Core.settings.getBool("swapdiagonal"))), boost(visibleDesktop, () -> !player.dead() && player.unit().type.canBoost, () -> Core.input.keyDown(Binding.boost)), - blockInfo(() -> true, () -> ui.content.isShown()), + blockInfo(() -> !(state.isCampaign() && state.rules.sector == SectorPresets.groundZero.sector && state.wave < 3), () -> ui.content.isShown()), derelict(() -> ui.hints.events.contains("derelictmouse"), () -> false), command(() -> state.rules.defaultTeam.data().units.size > 3 && !net.active(), () -> player.unit().isCommanding()), payloadPickup(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().isEmpty(), () -> player.unit() instanceof Payloadc p && p.payloads().any()), diff --git a/gradle.properties b/gradle.properties index 6ce5f26d99..462317f276 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,4 +11,4 @@ android.useAndroidX=true #used for slow jitpack builds; TODO see if this actually works http.socketTimeout=80000 http.connectionTimeout=80000 -archash=de1df819aae54e4023718a07dabf794da9f5a4de +archash=98b38438ccb72669a73349bd5ffd60905ed231a7