Partial 7.0 merge - API preview
This commit is contained in:
@@ -8,6 +8,7 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.pooling.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
@@ -15,9 +16,9 @@ public class Bar extends Element{
|
||||
private static Rect scissor = new Rect();
|
||||
|
||||
private Floatp fraction;
|
||||
private String name = "";
|
||||
private float value, lastValue, blink;
|
||||
private Color blinkColor = new Color();
|
||||
private CharSequence name = "";
|
||||
private float value, lastValue, blink, outlineRadius;
|
||||
private Color blinkColor = new Color(), outlineColor = new Color();
|
||||
|
||||
public Bar(String name, Color color, Floatp fraction){
|
||||
this.fraction = fraction;
|
||||
@@ -27,7 +28,7 @@ public class Bar extends Element{
|
||||
setColor(color);
|
||||
}
|
||||
|
||||
public Bar(Prov<String> name, Prov<Color> color, Floatp fraction){
|
||||
public Bar(Prov<CharSequence> name, Prov<Color> color, Floatp fraction){
|
||||
this.fraction = fraction;
|
||||
try{
|
||||
lastValue = value = Mathf.clamp(fraction.get());
|
||||
@@ -61,6 +62,12 @@ public class Bar extends Element{
|
||||
update(() -> this.name = name.get());
|
||||
}
|
||||
|
||||
public Bar outline(Color color, float stroke){
|
||||
outlineColor.set(color);
|
||||
outlineRadius = Scl.scl(stroke);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Bar blink(Color color){
|
||||
blinkColor.set(color);
|
||||
return this;
|
||||
@@ -94,6 +101,11 @@ public class Bar extends Element{
|
||||
|
||||
Drawable bar = Tex.bar;
|
||||
|
||||
if(outlineRadius > 0){
|
||||
Draw.color(outlineColor);
|
||||
bar.draw(x - outlineRadius, y - outlineRadius, width + outlineRadius*2, height + outlineRadius*2);
|
||||
}
|
||||
|
||||
Draw.colorl(0.1f);
|
||||
bar.draw(x, y, width, height);
|
||||
Draw.color(color, blinkColor, blink);
|
||||
|
||||
@@ -1,23 +1,12 @@
|
||||
package mindustry.ui;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/** Defines sizes of a content's preview icon. */
|
||||
/** Use content icon fields directly instead. This will be removed. */
|
||||
@Deprecated
|
||||
public enum Cicon{
|
||||
/** Full size. */
|
||||
full(0),
|
||||
tiny(8 * 2),
|
||||
small(8 * 3),
|
||||
medium(8 * 4),
|
||||
large(8 * 5),
|
||||
xlarge(8 * 6);
|
||||
tiny, small, medium, large, xlarge, full;
|
||||
@Deprecated
|
||||
public final int size = 32;
|
||||
|
||||
public static final Cicon[] all = values();
|
||||
public static final Cicon[] scaled = Arrays.copyOfRange(all, 1, all.length);
|
||||
|
||||
public final int size;
|
||||
|
||||
Cicon(int size){
|
||||
this.size = size;
|
||||
}
|
||||
public static final Cicon[] scaled = values();
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ public class CoreItemsDisplay extends Table{
|
||||
|
||||
for(Item item : content.items()){
|
||||
if(usedItems.contains(item)){
|
||||
image(item.icon(Cicon.small)).padRight(3);
|
||||
image(item.uiIcon).size(iconSmall).padRight(3).tooltip(t -> t.background(Styles.black6).margin(4f).add(item.localizedName).style(Styles.outlineLabel));
|
||||
//TODO leaks garbage
|
||||
label(() -> core == null ? "0" : UI.formatAmount(core.items.get(item))).padRight(3).left();
|
||||
label(() -> core == null ? "0" : UI.formatAmount(core.items.get(item))).padRight(3).minWidth(52f).left();
|
||||
|
||||
if(++i % 4 == 0){
|
||||
row();
|
||||
|
||||
@@ -3,14 +3,11 @@ package mindustry.ui;
|
||||
import arc.*;
|
||||
import arc.Graphics.Cursor.*;
|
||||
import arc.assets.*;
|
||||
import arc.assets.loaders.*;
|
||||
import arc.assets.loaders.resolvers.*;
|
||||
import arc.files.*;
|
||||
import arc.freetype.*;
|
||||
import arc.freetype.FreeTypeFontGenerator.*;
|
||||
import arc.freetype.FreetypeFontLoader.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Pixmap.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.g2d.Font.*;
|
||||
@@ -56,6 +53,10 @@ public class Fonts{
|
||||
return stringIcons.get(content, "");
|
||||
}
|
||||
|
||||
public static boolean hasUnicodeStr(String content){
|
||||
return stringIcons.containsKey(content);
|
||||
}
|
||||
|
||||
/** Called from a static context to make the cursor appear immediately upon startup.*/
|
||||
public static void loadSystemCursors(){
|
||||
SystemCursor.arrow.set(Core.graphics.newCursor("cursor", cursorScale()));
|
||||
@@ -160,10 +161,9 @@ public class Fonts{
|
||||
public static void loadDefaultFont(){
|
||||
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){
|
||||
UI.packer = new PixmapPacker(max >= 4096 ? 4096 : 2048, 2048, 2, true);
|
||||
Core.assets.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(Core.files::internal));
|
||||
Core.assets.setLoader(Font.class, null, new FreetypeFontLoader(Core.files::internal){
|
||||
ObjectSet<FreeTypeFontParameter> scaled = new ObjectSet<>();
|
||||
|
||||
@Override
|
||||
@@ -197,7 +197,7 @@ public class Fonts{
|
||||
size = 18;
|
||||
}})).loaded = f -> {
|
||||
Fonts.tech = (Font)f;
|
||||
((Font)f).getData().down *= 1.5f;
|
||||
Fonts.tech.getData().down *= 1.5f;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -214,13 +214,16 @@ public class Fonts{
|
||||
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));
|
||||
Rect rect = UI.packer.pack(region.name, atlas.getPixmap(region), region.splits, region.pads);
|
||||
|
||||
//set new texture
|
||||
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.texture);
|
||||
//clear it
|
||||
region.pixmapRegion = null;
|
||||
}
|
||||
|
||||
//remove old texture, it will no longer be used
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package mindustry.ui;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
//TODO replace with static methods?
|
||||
/** An item image with text. */
|
||||
public class ItemDisplay extends Table{
|
||||
public final Item item;
|
||||
@@ -23,4 +27,14 @@ public class ItemDisplay extends Table{
|
||||
public ItemDisplay(Item item, int amount){
|
||||
this(item, amount, true);
|
||||
}
|
||||
|
||||
/** Displays the item with a "/sec" qualifier based on the time period, in ticks. */
|
||||
public ItemDisplay(Item item, int amount, float timePeriod, boolean showName){
|
||||
add(new ItemImage(item.uiIcon, amount));
|
||||
add(Strings.autoFixed(amount / (timePeriod / 60f), 2) + StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray).style(Styles.outlineLabel);
|
||||
if(showName) add(item.localizedName).padLeft(4 + amount > 99 ? 4 : 0);
|
||||
|
||||
this.item = item;
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class ItemImage extends Stack{
|
||||
|
||||
add(new Table(o -> {
|
||||
o.left();
|
||||
o.add(new Image(stack.item.icon(Cicon.medium))).size(32f);
|
||||
o.add(new Image(stack.item.uiIcon)).size(32f);
|
||||
}));
|
||||
|
||||
if(stack.amount != 0){
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ItemsDisplay extends Table{
|
||||
if(!items.has(item)) continue;
|
||||
|
||||
Label label = t.add(UI.formatAmount(items.get(item))).left().get();
|
||||
t.image(item.icon(Cicon.small)).size(8 * 3).padLeft(4).padRight(4);
|
||||
t.image(item.uiIcon).size(8 * 3).padLeft(4).padRight(4);
|
||||
t.add(item.localizedName).color(Color.lightGray).left();
|
||||
t.row();
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import arc.util.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
/** An ItemDisplay, but for liquids. */
|
||||
public class LiquidDisplay extends Table{
|
||||
public final Liquid liquid;
|
||||
@@ -19,14 +21,14 @@ public class LiquidDisplay extends Table{
|
||||
this.perSecond = perSecond;
|
||||
|
||||
add(new Stack(){{
|
||||
add(new Image(liquid.icon(Cicon.medium)));
|
||||
add(new Image(liquid.uiIcon));
|
||||
|
||||
if(amount != 0){
|
||||
Table t = new Table().left().bottom();
|
||||
t.add(Strings.autoFixed(amount, 2)).style(Styles.outlineLabel);
|
||||
add(t);
|
||||
}
|
||||
}}).size(8 * 4).padRight(3 + (amount != 0 && Strings.autoFixed(amount, 2).length() > 2 ? 8 : 0));
|
||||
}}).size(iconMed).padRight(3 + (amount != 0 && Strings.autoFixed(amount, 2).length() > 2 ? 8 : 0));
|
||||
|
||||
if(perSecond){
|
||||
add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray).style(Styles.outlineLabel);
|
||||
|
||||
@@ -9,15 +9,16 @@ import arc.scene.ui.Button.*;
|
||||
import arc.scene.ui.CheckBox.*;
|
||||
import arc.scene.ui.Dialog.*;
|
||||
import arc.scene.ui.ImageButton.*;
|
||||
import arc.scene.ui.KeybindDialog.*;
|
||||
import arc.scene.ui.Label.*;
|
||||
import arc.scene.ui.ScrollPane.*;
|
||||
import arc.scene.ui.Slider.*;
|
||||
import arc.scene.ui.TextButton.*;
|
||||
import arc.scene.ui.TextField.*;
|
||||
import arc.scene.ui.TreeElement.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.dialogs.*;
|
||||
|
||||
import static mindustry.gen.Tex.*;
|
||||
|
||||
@@ -28,13 +29,14 @@ public class Styles{
|
||||
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 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;
|
||||
public static KeybindDialogStyle defaultKeybindDialog;
|
||||
public static ScrollPaneStyle defaultPane, horizontalPane, smallPane, nonePane;
|
||||
public static KeybindDialog.KeybindDialogStyle defaultKeybindDialog;
|
||||
public static SliderStyle defaultSlider, vSlider;
|
||||
public static LabelStyle defaultLabel, outlineLabel, techLabel;
|
||||
public static TextFieldStyle defaultField, nodeField, areaField, nodeArea;
|
||||
public static CheckBoxStyle defaultCheck;
|
||||
public static DialogStyle defaultDialog, fullDialog;
|
||||
public static TreeStyle defaultTree;
|
||||
|
||||
public static void load(){
|
||||
black = whiteui.tint(0f, 0f, 0f, 1f);
|
||||
@@ -214,6 +216,7 @@ public class Styles{
|
||||
}};
|
||||
emptyi = new ImageButtonStyle(){{
|
||||
imageDownColor = Pal.accent;
|
||||
imageOverColor = Color.lightGray;
|
||||
imageUpColor = Color.white;
|
||||
}};
|
||||
emptytogglei = new ImageButtonStyle(){{
|
||||
@@ -306,8 +309,9 @@ public class Styles{
|
||||
vScroll = clear;
|
||||
vScrollKnob = scrollKnobVerticalThin;
|
||||
}};
|
||||
nonePane = new ScrollPaneStyle();
|
||||
|
||||
defaultKeybindDialog = new KeybindDialogStyle(){{
|
||||
defaultKeybindDialog = new KeybindDialog.KeybindDialogStyle(){{
|
||||
keyColor = Pal.accent;
|
||||
keyNameColor = Color.white;
|
||||
controllerColor = Color.lightGray;
|
||||
@@ -411,6 +415,13 @@ public class Styles{
|
||||
background = windowEmpty;
|
||||
titleFontColor = Pal.accent;
|
||||
}};
|
||||
|
||||
defaultTree = new TreeStyle(){{
|
||||
plus = Icon.downOpen;
|
||||
minus = Icon.upOpen;
|
||||
background = black5;
|
||||
over = flatOver;
|
||||
}};
|
||||
}
|
||||
|
||||
private static Drawable createFlatDown(){
|
||||
|
||||
@@ -4,7 +4,6 @@ import arc.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
@@ -44,12 +43,7 @@ public class BaseDialog extends Dialog{
|
||||
}
|
||||
|
||||
protected void onResize(Runnable run){
|
||||
Events.on(ResizeEvent.class, event -> {
|
||||
if(isShown() && Core.scene.getDialog() == this){
|
||||
run.run();
|
||||
updateScrollFocus();
|
||||
}
|
||||
});
|
||||
resized(run);
|
||||
}
|
||||
|
||||
public void addCloseListener(){
|
||||
|
||||
@@ -8,6 +8,8 @@ import mindustry.ctype.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ContentInfoDialog extends BaseDialog{
|
||||
|
||||
public ContentInfoDialog(){
|
||||
@@ -26,9 +28,7 @@ public class ContentInfoDialog extends BaseDialog{
|
||||
content.checkStats();
|
||||
|
||||
table.table(title1 -> {
|
||||
var size = content.prefDatabaseIcon();
|
||||
|
||||
title1.image(content.icon(size)).size(size.size).scaling(Scaling.fit);
|
||||
title1.image(content.uiIcon).size(iconXLarge).scaling(Scaling.fit);
|
||||
title1.add("[accent]" + content.localizedName).padLeft(5);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.input.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.util.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
public class ControlsDialog extends KeybindDialog{
|
||||
|
||||
public ControlsDialog(){
|
||||
setFillParent(true);
|
||||
title.setAlignment(Align.center);
|
||||
titleTable.row();
|
||||
titleTable.add(new Image()).growX().height(3f).pad(4f).get().setColor(Pal.accent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f, 64f);
|
||||
|
||||
keyDown(key -> {
|
||||
if(key == KeyCode.escape || key == KeyCode.back) hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.ImageButton.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
@@ -31,14 +32,20 @@ public class CustomGameDialog extends BaseDialog{
|
||||
cont.clear();
|
||||
|
||||
Table maps = new Table();
|
||||
maps.marginRight(14);
|
||||
maps.marginBottom(55f);
|
||||
maps.marginBottom(55f).marginRight(-20f);
|
||||
ScrollPane pane = new ScrollPane(maps);
|
||||
pane.setFadeScrollBars(false);
|
||||
|
||||
int maxwidth = Math.max((int)(Core.graphics.getWidth() / Scl.scl(210)), 1);
|
||||
float images = 146f;
|
||||
|
||||
ImageButtonStyle style = new ImageButtonStyle(){{
|
||||
up = Styles.none;
|
||||
down = Styles.flatOver;
|
||||
over = Styles.flatOver;
|
||||
disabled = Styles.none;
|
||||
}};
|
||||
|
||||
int i = 0;
|
||||
maps.defaults().width(170).fillY().top().pad(4f);
|
||||
for(Map map : Vars.maps.all()){
|
||||
@@ -47,7 +54,7 @@ public class CustomGameDialog extends BaseDialog{
|
||||
maps.row();
|
||||
}
|
||||
|
||||
ImageButton image = new ImageButton(new TextureRegion(map.safeTexture()), Styles.cleari);
|
||||
ImageButton image = new ImageButton(new TextureRegion(map.safeTexture()), style);
|
||||
image.margin(5);
|
||||
image.top();
|
||||
|
||||
@@ -86,6 +93,6 @@ public class CustomGameDialog extends BaseDialog{
|
||||
maps.add("@maps.none").pad(50);
|
||||
}
|
||||
|
||||
cont.add(pane).uniformX();
|
||||
cont.add(pane).grow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
for(Block block : array){
|
||||
t.table(Tex.underline, b -> {
|
||||
b.left().margin(4f);
|
||||
b.image(block.icon(Cicon.medium)).size(Cicon.medium.size).padRight(3);
|
||||
b.image(block.uiIcon).size(iconMed).padRight(3);
|
||||
b.add(block.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap();
|
||||
|
||||
b.button(Icon.cancel, Styles.clearPartiali, () -> {
|
||||
@@ -94,11 +94,11 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
int[] i = {0};
|
||||
content.blocks().each(b -> !rules.bannedBlocks.contains(b) && b.canBeBuilt(), b -> {
|
||||
int cols = mobile && Core.graphics.isPortrait() ? 4 : 12;
|
||||
t.button(new TextureRegionDrawable(b.icon(Cicon.medium)), Styles.cleari, () -> {
|
||||
t.button(new TextureRegionDrawable(b.uiIcon), Styles.cleari, iconMed, () -> {
|
||||
rules.bannedBlocks.add(b);
|
||||
rebuildBanned();
|
||||
dialog.hide();
|
||||
}).size(60f).get().resizeImage(Cicon.medium.size);
|
||||
}).size(60f);
|
||||
|
||||
if(++i[0] % cols == 0){
|
||||
t.row();
|
||||
@@ -149,7 +149,7 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
number("@rules.blockdamagemultiplier", f -> rules.blockDamageMultiplier = f, () -> rules.blockDamageMultiplier);
|
||||
|
||||
main.button("@configure",
|
||||
() -> loadoutDialog.show(Blocks.coreShard.itemCapacity, rules.loadout,
|
||||
() -> loadoutDialog.show(999999, rules.loadout,
|
||||
i -> true,
|
||||
() -> rules.loadout.clear().add(new ItemStack(Items.copper, 100)),
|
||||
() -> {}, () -> {}
|
||||
@@ -169,6 +169,7 @@ public class CustomRulesDialog extends BaseDialog{
|
||||
title("@rules.title.enemy");
|
||||
check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
|
||||
check("@rules.buildai", b -> rules.teams.get(rules.waveTeam).ai = rules.teams.get(rules.waveTeam).infiniteResources = b, () -> rules.teams.get(rules.waveTeam).ai);
|
||||
check("@rules.corecapture", b -> rules.coreCapture = b, () -> rules.coreCapture);
|
||||
number("@rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200));
|
||||
|
||||
title("@rules.title.environment");
|
||||
|
||||
@@ -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)).setScaling(Scaling.fit) : new Image(Icon.lock, Pal.gray);
|
||||
Image image = unlocked(unlock) ? new Image(unlock.uiIcon).setScaling(Scaling.fit) : new Image(Icon.lock, Pal.gray);
|
||||
list.add(image).size(8 * 4).pad(3);
|
||||
ClickListener listener = new ClickListener();
|
||||
image.addListener(listener);
|
||||
|
||||
@@ -66,7 +66,7 @@ public class GameOverDialog extends BaseDialog{
|
||||
if(state.stats.itemsDelivered.get(item, 0) > 0){
|
||||
t.table(items -> {
|
||||
items.add(" [lightgray]" + state.stats.itemsDelivered.get(item, 0));
|
||||
items.image(item.icon(Cicon.small)).size(8 * 3).pad(4);
|
||||
items.image(item.uiIcon).size(8 * 3).pad(4);
|
||||
}).left().row();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class HostDialog extends BaseDialog{
|
||||
Time.runTask(5f, () -> {
|
||||
try{
|
||||
net.host(Vars.port);
|
||||
player.admin(true);
|
||||
player.admin = true;
|
||||
|
||||
if(steam){
|
||||
Core.app.post(() -> Core.settings.getBoolOnce("steampublic3", () -> {
|
||||
|
||||
@@ -50,9 +50,7 @@ public class JoinDialog extends BaseDialog{
|
||||
addCloseButton();
|
||||
|
||||
buttons.add().growX().width(-1);
|
||||
if(!steam){
|
||||
buttons.button("?", () -> ui.showInfo("@join.info")).size(60f, 64f).width(-1);
|
||||
}
|
||||
if(!steam) buttons.button("?", () -> ui.showInfo("@join.info")).size(60f, 64f);
|
||||
|
||||
add = new BaseDialog("@joingame.title");
|
||||
add.cont.add("@joingame.ip").padRight(5f).left();
|
||||
@@ -97,8 +95,12 @@ public class JoinDialog extends BaseDialog{
|
||||
});
|
||||
|
||||
onResize(() -> {
|
||||
setup();
|
||||
refreshAll();
|
||||
//only refresh on resize when the minimum dimension is smaller than the maximum preferred width
|
||||
//this means that refreshes on resize will only happen for small phones that need the list to fit in portrait mode
|
||||
if(Math.min(Core.graphics.getWidth(), Core.graphics.getHeight()) / Scl.scl() * 0.9f < 500f){
|
||||
setup();
|
||||
refreshAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -402,6 +404,7 @@ public class JoinDialog extends BaseDialog{
|
||||
global.background(null);
|
||||
float w = targetWidth();
|
||||
|
||||
//TODO looks bad
|
||||
container.button(b -> buildServer(host, b), Styles.cleart, () -> {
|
||||
Events.fire(new ClientPreConnectEvent(host));
|
||||
if(!Core.settings.getBool("server-disclaimer", false)){
|
||||
|
||||
262
core/src/mindustry/ui/dialogs/KeybindDialog.java
Normal file
262
core/src/mindustry/ui/dialogs/KeybindDialog.java
Normal file
@@ -0,0 +1,262 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.KeyBinds.*;
|
||||
import arc.graphics.*;
|
||||
import arc.input.*;
|
||||
import arc.input.InputDevice.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
import static arc.Core.*;
|
||||
|
||||
public class KeybindDialog extends Dialog{
|
||||
protected KeybindDialogStyle style;
|
||||
protected Section section;
|
||||
protected KeyBind rebindKey = null;
|
||||
protected boolean rebindAxis = false;
|
||||
protected boolean rebindMin = true;
|
||||
protected KeyCode minKey = null;
|
||||
protected Dialog rebindDialog;
|
||||
protected ObjectIntMap<Section> sectionControls = new ObjectIntMap<>();
|
||||
|
||||
public KeybindDialog(){
|
||||
super(bundle.get("keybind.title", "Rebind Keys"));
|
||||
KeybindDialog.this.style = scene.getStyle(KeybindDialogStyle.class);
|
||||
KeybindDialog.this.setup();
|
||||
addCloseButton();
|
||||
setFillParent(true);
|
||||
title.setAlignment(Align.center);
|
||||
titleTable.row();
|
||||
titleTable.add(new Image()).growX().height(3f).pad(4f).get().setColor(Pal.accent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f, 64f);
|
||||
|
||||
keyDown(key -> {
|
||||
if(key == KeyCode.escape || key == KeyCode.back) hide();
|
||||
});
|
||||
}
|
||||
|
||||
public void setStyle(KeybindDialogStyle style){
|
||||
this.style = style;
|
||||
setup();
|
||||
}
|
||||
|
||||
private void setup(){
|
||||
cont.clear();
|
||||
|
||||
Section[] sections = Core.keybinds.getSections();
|
||||
|
||||
Stack stack = new Stack();
|
||||
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
||||
ScrollPane pane = new ScrollPane(stack);
|
||||
pane.setFadeScrollBars(false);
|
||||
this.section = sections[0];
|
||||
|
||||
for(Section section : sections){
|
||||
if(!sectionControls.containsKey(section))
|
||||
sectionControls.put(section, input.getDevices().indexOf(section.device, true));
|
||||
|
||||
if(sectionControls.get(section, 0) >= input.getDevices().size){
|
||||
sectionControls.put(section, 0);
|
||||
section.device = input.getDevices().get(0);
|
||||
}
|
||||
|
||||
if(sections.length != 1){
|
||||
//TODO toggle style
|
||||
TextButton button = new TextButton(bundle.get("section." + section.name + ".name", Strings.capitalize(section.name))/*, "toggle"*/);
|
||||
if(section.equals(this.section))
|
||||
button.toggle();
|
||||
|
||||
button.clicked(() -> this.section = section);
|
||||
|
||||
group.add(button);
|
||||
cont.add(button).fill();
|
||||
}
|
||||
|
||||
Table table = new Table();
|
||||
|
||||
Label device = new Label("Keyboard");
|
||||
//device.setColor(style.controllerColor);
|
||||
device.setAlignment(Align.center);
|
||||
|
||||
Seq<InputDevice> devices = input.getDevices();
|
||||
|
||||
Table stable = new Table();
|
||||
|
||||
stable.button("<", () -> {
|
||||
int i = sectionControls.get(section, 0);
|
||||
if(i - 1 >= 0){
|
||||
sectionControls.put(section, i - 1);
|
||||
section.device = devices.get(i - 1);
|
||||
setup();
|
||||
}
|
||||
}).disabled(sectionControls.get(section, 0) - 1 < 0).size(40);
|
||||
|
||||
stable.add(device).minWidth(device.getMinWidth() + 60);
|
||||
|
||||
device.setText(input.getDevices().get(sectionControls.get(section, 0)).name());
|
||||
|
||||
stable.button(">", () -> {
|
||||
int i = sectionControls.get(section, 0);
|
||||
|
||||
if(i + 1 < devices.size){
|
||||
sectionControls.put(section, i + 1);
|
||||
section.device = devices.get(i + 1);
|
||||
setup();
|
||||
}
|
||||
}).disabled(sectionControls.get(section, 0) + 1 >= devices.size).size(40);
|
||||
|
||||
table.add(stable).colspan(4);
|
||||
|
||||
table.row();
|
||||
table.add().height(10);
|
||||
table.row();
|
||||
if(section.device.type() == DeviceType.controller){
|
||||
table.table(info -> info.add("Controller Type: [#" + style.controllerColor.toString().toUpperCase() + "]" +
|
||||
Strings.capitalize(section.device.name())).left());
|
||||
}
|
||||
table.row();
|
||||
|
||||
String lastCategory = null;
|
||||
|
||||
for(KeyBind keybind : keybinds.getKeybinds()){
|
||||
if(lastCategory != keybind.category() && keybind.category() != null){
|
||||
table.add(bundle.get("category." + keybind.category() + ".name", Strings.capitalize(keybind.category()))).color(Color.gray).colspan(4).pad(10).padBottom(4).row();
|
||||
table.image().color(Color.gray).fillX().height(3).pad(6).colspan(4).padTop(0).padBottom(10).row();
|
||||
lastCategory = keybind.category();
|
||||
}
|
||||
|
||||
Axis axis = keybinds.get(section, keybind);
|
||||
|
||||
if(keybind.defaultValue(section.device.type()) instanceof Axis){
|
||||
table.add(bundle.get("keybind." + keybind.name() + ".name", Strings.capitalize(keybind.name())), style.keyNameColor).left().padRight(40).padLeft(8);
|
||||
|
||||
if(axis.key != null){
|
||||
table.add(axis.key.toString(), style.keyColor).left().minWidth(90).padRight(20);
|
||||
}else{
|
||||
Table axt = new Table();
|
||||
axt.left();
|
||||
axt.labelWrap(axis.min.toString() + " [red]/[] " + axis.max.toString()).color(style.keyColor).width(140f).padRight(5);
|
||||
table.add(axt).left().minWidth(90).padRight(20);
|
||||
}
|
||||
|
||||
table.button(bundle.get("settings.rebind", "Rebind"), () -> {
|
||||
rebindAxis = true;
|
||||
rebindMin = true;
|
||||
openDialog(section, keybind);
|
||||
}).width(130f);
|
||||
}else{
|
||||
table.add(bundle.get("keybind." + keybind.name() + ".name", Strings.capitalize(keybind.name())),
|
||||
style.keyNameColor).left().padRight(40).padLeft(8);
|
||||
table.add(keybinds.get(section, keybind).key.toString(),
|
||||
style.keyColor).left().minWidth(90).padRight(20);
|
||||
|
||||
table.button(bundle.get("settings.rebind", "Rebind"), () -> {
|
||||
rebindAxis = false;
|
||||
rebindMin = false;
|
||||
openDialog(section, keybind);
|
||||
}).width(130f);
|
||||
}
|
||||
table.button(bundle.get("settings.resetKey", "Reset"), () -> {
|
||||
keybinds.resetToDefault(section, keybind);
|
||||
setup();
|
||||
}).width(130f);
|
||||
table.row();
|
||||
}
|
||||
|
||||
table.visible(() -> this.section.equals(section));
|
||||
|
||||
table.button(bundle.get("settings.reset", "Reset to Defaults"), () -> {
|
||||
keybinds.resetToDefaults();
|
||||
setup();
|
||||
}).colspan(4).padTop(4).fill();
|
||||
|
||||
stack.add(table);
|
||||
}
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.add(pane).growX().colspan(sections.length);
|
||||
|
||||
}
|
||||
|
||||
void rebind(Section section, KeyBind bind, KeyCode newKey){
|
||||
if(rebindKey == null) return;
|
||||
rebindDialog.hide();
|
||||
boolean isAxis = bind.defaultValue(section.device.type()) instanceof Axis;
|
||||
|
||||
if(isAxis){
|
||||
if(newKey.axis || !rebindMin){
|
||||
section.binds.get(section.device.type(), OrderedMap::new).put(rebindKey, newKey.axis ? new Axis(newKey) : new Axis(minKey, newKey));
|
||||
}
|
||||
}else{
|
||||
section.binds.get(section.device.type(), OrderedMap::new).put(rebindKey, new Axis(newKey));
|
||||
}
|
||||
|
||||
if(rebindAxis && isAxis && rebindMin && !newKey.axis){
|
||||
rebindMin = false;
|
||||
minKey = newKey;
|
||||
openDialog(section, rebindKey);
|
||||
}else{
|
||||
rebindKey = null;
|
||||
rebindAxis = false;
|
||||
setup();
|
||||
}
|
||||
}
|
||||
|
||||
private void openDialog(Section section, KeyBind name){
|
||||
rebindDialog = new Dialog(rebindAxis ? bundle.get("keybind.press.axis", "Press an axis or key...") : bundle.get("keybind.press", "Press a key..."));
|
||||
|
||||
rebindKey = name;
|
||||
|
||||
rebindDialog.titleTable.getCells().first().pad(4);
|
||||
|
||||
if(section.device.type() == DeviceType.keyboard){
|
||||
rebindDialog.keyDown(i -> setup());
|
||||
|
||||
rebindDialog.addListener(new InputListener(){
|
||||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
|
||||
if(Core.app.isAndroid()) return false;
|
||||
rebind(section, name, button);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyDown(InputEvent event, KeyCode keycode){
|
||||
rebindDialog.hide();
|
||||
if(keycode == KeyCode.escape) return false;
|
||||
rebind(section, name, keycode);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean scrolled(InputEvent event, float x, float y, float amountX, float amountY){
|
||||
if(!rebindAxis) return false;
|
||||
rebindDialog.hide();
|
||||
rebind(section, name, KeyCode.scroll);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
rebindDialog.show();
|
||||
Time.runTask(1f, () -> getScene().setScrollFocus(rebindDialog));
|
||||
}
|
||||
|
||||
public static class KeybindDialogStyle extends Style{
|
||||
public Color keyColor = Color.white;
|
||||
public Color keyNameColor = Color.white;
|
||||
public Color controllerColor = Color.white;
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,41 @@ import static mindustry.Vars.*;
|
||||
|
||||
public class LanguageDialog extends BaseDialog{
|
||||
private Locale lastLocale;
|
||||
private ObjectMap<Locale, String> displayNames = ObjectMap.of(
|
||||
Locale.TRADITIONAL_CHINESE, "正體中文",
|
||||
Locale.SIMPLIFIED_CHINESE, "简体中文"
|
||||
private ObjectMap<String, String> displayNames = ObjectMap.of(
|
||||
"in_ID", "Bahasa Indonesia (Indonesia)",
|
||||
"da", "Dansk",
|
||||
"de", "Deutsch",
|
||||
"et", "Eesti",
|
||||
"en", "English",
|
||||
"es", "Español",
|
||||
"eu", "Euskara",
|
||||
"fil", "Filipino",
|
||||
"fr", "Français",
|
||||
"it", "Italiano",
|
||||
"lt", "Lietuvių",
|
||||
"hu", "Magyar",
|
||||
"nl", "Nederlands",
|
||||
"nl_BE", "Nederlands (België)",
|
||||
"pl", "Polski",
|
||||
"pt_BR", "Português (Brasil)",
|
||||
"pt_PT", "Português (Portugal)",
|
||||
"ro", "Română",
|
||||
"fi", "Suomi",
|
||||
"sv", "Svenska",
|
||||
"vi", "Tiếng Việt",
|
||||
"tk", "Türkmen dili",
|
||||
"tr", "Türkçe",
|
||||
"cs", "Čeština",
|
||||
"be", "Беларуская",
|
||||
"bg", "Български",
|
||||
"ru", "Русский",
|
||||
"uk_UA", "Українська (Україна)",
|
||||
"th", "ไทย",
|
||||
"zh_CN", "简体中文",
|
||||
"zh_TW", "正體中文",
|
||||
"ja", "日本語",
|
||||
"ko", "한국어",
|
||||
"router", "router"
|
||||
);
|
||||
|
||||
public LanguageDialog(){
|
||||
@@ -33,7 +65,7 @@ public class LanguageDialog extends BaseDialog{
|
||||
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
||||
|
||||
for(Locale loc : locales){
|
||||
TextButton button = new TextButton(Strings.capitalize(displayNames.get(loc, loc.getDisplayName(loc))), Styles.clearTogglet);
|
||||
TextButton button = new TextButton(displayNames.get(loc.toString(), loc.getDisplayName(Locale.ROOT)), Styles.clearTogglet);
|
||||
button.clicked(() -> {
|
||||
if(getLocale().equals(loc)) return;
|
||||
Core.settings.put("locale", loc.toString());
|
||||
|
||||
@@ -64,7 +64,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
|
||||
ItemSeq launches = universe.getLaunchResources();
|
||||
|
||||
for(ItemStack s : total){
|
||||
table.image(s.item.icon(Cicon.small)).left().size(Cicon.small.size);
|
||||
table.image(s.item.uiIcon).left().size(iconSmall);
|
||||
int as = schems.get(s.item), al = launches.get(s.item);
|
||||
|
||||
String amountStr = (al + as) + "[gray] (" + (al + " + " + as + ")");
|
||||
|
||||
@@ -111,7 +111,7 @@ public class LoadoutDialog extends BaseDialog{
|
||||
ui.showInfo(Core.bundle.format("configure.invalid", capacity));
|
||||
})).size(bsize);
|
||||
|
||||
t.image(stack.item.icon(Cicon.small)).size(8 * 3).padRight(4).padLeft(4);
|
||||
t.image(stack.item.uiIcon).size(8 * 3).padRight(4).padLeft(4);
|
||||
t.label(() -> stack.amount + "").left().width(90f);
|
||||
}).pad(2).left().fillX();
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public class MapsDialog extends BaseDialog{
|
||||
Runnable show = () -> ui.loadAnd(() -> {
|
||||
hide();
|
||||
ui.editor.show();
|
||||
ui.editor.editor.tags.put("name", text);
|
||||
editor.tags.put("name", text);
|
||||
Events.fire(new MapMakeEvent());
|
||||
});
|
||||
|
||||
|
||||
@@ -147,11 +147,12 @@ public class ModsDialog extends BaseDialog{
|
||||
}
|
||||
|
||||
void setup(){
|
||||
boolean squish = Core.graphics.isPortrait();
|
||||
float h = 110f;
|
||||
float w = mobile ? 440f : 524f;
|
||||
float w = squish ? 410f : 524f;
|
||||
|
||||
cont.clear();
|
||||
cont.defaults().width(mobile ? 500 : 560f).pad(4);
|
||||
cont.defaults().width(squish ? 480 : 560f).pad(4);
|
||||
cont.add("@mod.reloadrequired").visible(mods::requiresReload).center().get().setAlignment(Align.center);
|
||||
cont.row();
|
||||
|
||||
@@ -365,7 +366,7 @@ public class ModsDialog extends BaseDialog{
|
||||
d.cont.pane(cs -> {
|
||||
int i = 0;
|
||||
for(UnlockableContent c : all){
|
||||
cs.button(new TextureRegionDrawable(c.icon(Cicon.medium)), Styles.cleari, Cicon.medium.size, () -> {
|
||||
cs.button(new TextureRegionDrawable(c.uiIcon), Styles.cleari, iconMed, () -> {
|
||||
ui.content.show(c);
|
||||
}).size(50f).with(im -> {
|
||||
var click = im.getClickListener();
|
||||
|
||||
@@ -93,12 +93,19 @@ public class PausedDialog extends BaseDialog{
|
||||
}
|
||||
|
||||
void showQuitConfirm(){
|
||||
ui.showConfirm("@confirm", "@quit.confirm", () -> {
|
||||
Runnable quit = () -> {
|
||||
wasClient = net.client();
|
||||
if(net.client()) netClient.disconnectQuietly();
|
||||
runExitSave();
|
||||
hide();
|
||||
});
|
||||
};
|
||||
|
||||
if(confirmExit){
|
||||
ui.showConfirm("@confirm", "@quit.confirm", quit);
|
||||
}else{
|
||||
quit.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void runExitSave(){
|
||||
|
||||
@@ -10,6 +10,7 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
@@ -36,6 +37,13 @@ import static mindustry.graphics.g3d.PlanetRenderer.*;
|
||||
import static mindustry.ui.dialogs.PlanetDialog.Mode.*;
|
||||
|
||||
public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
static final String[] defaultIcons = {
|
||||
"effect", "power", "logic", "units", "liquid", "production", "defense", "turret", "distribution", "crafting",
|
||||
"settings", "cancel", "zoom", "ok", "star", "home", "pencil", "up", "down", "left", "right",
|
||||
"hammer", "warning", "tree", "admin", "map", "modePvp", "terrain",
|
||||
"modeSurvival", "commandRally", "commandAttack",
|
||||
};
|
||||
|
||||
//if true, enables launching anywhere for testing
|
||||
public static boolean debugSelect = false;
|
||||
public static float sectorShowDuration = 60f * 2.4f;
|
||||
@@ -61,6 +69,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
super("", Styles.fullDialog);
|
||||
|
||||
shouldPause = true;
|
||||
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){
|
||||
@@ -163,12 +173,13 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
launchSector = state.getSector();
|
||||
presetShow = 0f;
|
||||
showed = false;
|
||||
listener = s -> {};
|
||||
|
||||
newPresets.clear();
|
||||
|
||||
//announce new presets
|
||||
for(SectorPreset preset : content.sectors()){
|
||||
if(preset.unlocked() && !preset.alwaysUnlocked && !preset.sector.info.shown && !preset.sector.hasBase()){
|
||||
if(preset.unlocked() && !preset.alwaysUnlocked && !preset.sector.info.shown && !preset.sector.hasBase() && preset.planet == planets.planet){
|
||||
newPresets.add(preset.sector);
|
||||
preset.sector.info.shown = true;
|
||||
preset.sector.saveInfo();
|
||||
@@ -229,6 +240,24 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
dialog.add("@sectors.captured");
|
||||
}
|
||||
|
||||
//TODO
|
||||
public void showPlanetLaunch(Sector sector, Cons<Sector> listener){
|
||||
selected = null;
|
||||
hovered = null;
|
||||
launching = false;
|
||||
this.listener = listener;
|
||||
launchSector = sector;
|
||||
|
||||
//update view to sector
|
||||
zoom = 1f;
|
||||
planets.zoom = 1f;
|
||||
selectAlpha = 0f;
|
||||
|
||||
mode = planetLaunch;
|
||||
|
||||
super.show();
|
||||
}
|
||||
|
||||
public void showSelect(Sector sector, Cons<Sector> listener){
|
||||
selected = null;
|
||||
hovered = null;
|
||||
@@ -253,7 +282,9 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
|
||||
boolean canSelect(Sector sector){
|
||||
if(mode == select) return sector.hasBase();
|
||||
if(sector.hasBase()) return true;
|
||||
//cannot launch to existing sector w/ accelerator
|
||||
if(mode == planetLaunch) return !sector.hasBase();
|
||||
if(sector.hasBase() || sector.id == sector.planet.startSector) return true;
|
||||
//preset sectors can only be selected once unlocked
|
||||
if(sector.preset != null){
|
||||
TechNode node = sector.preset.node();
|
||||
@@ -369,7 +400,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
|
||||
if(icon != null){
|
||||
planets.drawPlane(sec, () -> {
|
||||
Draw.color(color, selectAlpha);
|
||||
//use white for content icons
|
||||
Draw.color(preficon == icon && sec.info.contentIcon != null ? Color.white : color, selectAlpha);
|
||||
Draw.rect(icon, 0, 0, iw, iw * icon.height / icon.width);
|
||||
});
|
||||
}
|
||||
@@ -395,6 +427,12 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
boolean selectable(Planet planet){
|
||||
//TODO what if any sector is selectable?
|
||||
if(mode == planetLaunch) return launchSector != null && planet != launchSector.planet;
|
||||
return planet == planets.planet || planet.alwaysUnlocked || planet.sectors.contains(Sector::hasBase);
|
||||
}
|
||||
|
||||
void setup(){
|
||||
zoom = planets.zoom = 1f;
|
||||
selectAlpha = 1f;
|
||||
@@ -447,7 +485,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
//planet selection
|
||||
new Table(t -> {
|
||||
t.right();
|
||||
if(content.planets().count(p -> p.accessible) > 1){
|
||||
if(content.planets().count(this::selectable) > 1){
|
||||
t.table(Styles.black6, pt -> {
|
||||
pt.add("@planets").color(Pal.accent);
|
||||
pt.row();
|
||||
@@ -455,11 +493,12 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
pt.row();
|
||||
for(int i = 0; i < content.planets().size; i++){
|
||||
Planet planet = content.planets().get(i);
|
||||
if(planet.accessible){
|
||||
if(selectable(planet)){
|
||||
pt.button(planet.localizedName, Styles.clearTogglet, () -> {
|
||||
selected = null;
|
||||
launchSector = null;
|
||||
renderer.planets.planet = planet;
|
||||
Core.settings.put("lastplanet", planet.name);
|
||||
}).width(200).height(40).growX().update(bb -> bb.setChecked(renderer.planets.planet == planet));
|
||||
pt.row();
|
||||
}
|
||||
@@ -516,7 +555,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
if(hovered != null){
|
||||
StringBuilder tx = hoverLabel.getText();
|
||||
if(!canSelect(hovered)){
|
||||
tx.append("[gray]").append(Iconc.lock).append(" ").append(Core.bundle.get("locked"));
|
||||
if(mode == planetLaunch){
|
||||
tx.append("[gray]").append(Iconc.cancel);
|
||||
}else{
|
||||
tx.append("[gray]").append(Iconc.lock).append(" ").append(Core.bundle.get("locked"));
|
||||
}
|
||||
}else{
|
||||
tx.append("[accent][[ [white]").append(hovered.name()).append("[accent] ]");
|
||||
}
|
||||
@@ -574,7 +617,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
stats.each((item, stat) -> {
|
||||
int total = (int)(stat.mean * 60 * scl);
|
||||
if(total > 1){
|
||||
t.image(item.icon(Cicon.small)).padRight(3);
|
||||
t.image(item.uiIcon).padRight(3);
|
||||
t.add(UI.formatAmount(total) + " " + Core.bundle.get("unit.perminute")).color(Color.lightGray).padRight(3);
|
||||
if(++i[0] % 3 == 0){
|
||||
t.row();
|
||||
@@ -604,7 +647,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
c.add("@sectors.resources").left().row();
|
||||
c.table(t -> {
|
||||
for(UnlockableContent uc : sector.info.resources){
|
||||
t.image(uc.icon(Cicon.small)).padRight(3).size(Cicon.small.size);
|
||||
t.image(uc.uiIcon).padRight(3).size(iconSmall);
|
||||
}
|
||||
}).padLeft(10f).left().row();
|
||||
}
|
||||
@@ -628,7 +671,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
|
||||
int i = 0;
|
||||
for(ItemStack stack : items){
|
||||
res.image(stack.item.icon(Cicon.small)).padRight(3);
|
||||
res.image(stack.item.uiIcon).padRight(3);
|
||||
res.add(UI.formatAmount(Math.max(stack.amount, 0))).color(Color.lightGray);
|
||||
if(++i % 4 == 0){
|
||||
res.row();
|
||||
@@ -671,41 +714,69 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
}).size(40f).padLeft(4);
|
||||
}
|
||||
|
||||
var icon = Icon.icons.get(sector.info.icon + "Small");
|
||||
var icon = sector.info.contentIcon != null ?
|
||||
new TextureRegionDrawable(sector.info.contentIcon.uiIcon) :
|
||||
Icon.icons.get(sector.info.icon + "Small");
|
||||
|
||||
title.button(icon == null ? Icon.noneSmall : icon, Styles.clearPartiali, () -> {
|
||||
title.button(icon == null ? Icon.noneSmall : icon, Styles.clearPartiali, iconSmall, () -> {
|
||||
new Dialog(""){{
|
||||
closeOnBack();
|
||||
setFillParent(true);
|
||||
cont.pane(t -> {
|
||||
t.marginRight(19f);
|
||||
t.defaults().size(48f);
|
||||
resized(true, () -> {
|
||||
t.clearChildren();
|
||||
t.marginRight(19f);
|
||||
t.defaults().size(48f);
|
||||
|
||||
t.button(Icon.none, Styles.clearTogglei, () -> {
|
||||
sector.info.icon = null;
|
||||
sector.saveInfo();
|
||||
hide();
|
||||
updateSelected();
|
||||
}).checked(sector.info.icon == null);
|
||||
|
||||
int i = 1;
|
||||
for(var entry : Icon.icons.entries()){
|
||||
if(entry.key.endsWith("Small") || entry.key.contains("none")) continue;
|
||||
String key = entry.key;
|
||||
|
||||
t.button(entry.value, Styles.cleari, () -> {
|
||||
sector.info.icon = key;
|
||||
t.button(Icon.none, Styles.clearTogglei, () -> {
|
||||
sector.info.icon = null;
|
||||
sector.saveInfo();
|
||||
hide();
|
||||
updateSelected();
|
||||
}).checked(entry.key.equals(sector.info.icon));
|
||||
}).checked(sector.info.icon == null);
|
||||
|
||||
if(++i % 8 == 0) t.row();
|
||||
}
|
||||
int cols = (int)Math.min(20, Core.graphics.getWidth() / 52f);
|
||||
|
||||
int i = 1;
|
||||
for(var key : defaultIcons){
|
||||
var value = Icon.icons.get(key);
|
||||
|
||||
t.button(value, Styles.cleari, () -> {
|
||||
sector.info.icon = key;
|
||||
sector.info.contentIcon = null;
|
||||
sector.saveInfo();
|
||||
hide();
|
||||
updateSelected();
|
||||
}).checked(key.equals(sector.info.icon));
|
||||
|
||||
if(++i % cols == 0) t.row();
|
||||
}
|
||||
|
||||
for(ContentType ctype : defaultContentIcons){
|
||||
t.row();
|
||||
t.image().colspan(cols).growX().width(Float.NEGATIVE_INFINITY).height(3f).color(Pal.accent);
|
||||
t.row();
|
||||
|
||||
i = 0;
|
||||
for(UnlockableContent u : content.getBy(ctype).<UnlockableContent>as()){
|
||||
if(!u.isHidden() && u.unlocked()){
|
||||
t.button(new TextureRegionDrawable(u.uiIcon), Styles.cleari, iconMed, () -> {
|
||||
sector.info.icon = null;
|
||||
sector.info.contentIcon = u;
|
||||
sector.saveInfo();
|
||||
hide();
|
||||
updateSelected();
|
||||
}).checked(sector.info.contentIcon == u);
|
||||
|
||||
if(++i % cols == 0) t.row();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f, 64f);
|
||||
}}.show();
|
||||
}).size(40f);
|
||||
}).size(40f).tooltip("@sector.changeicon");
|
||||
}).row();
|
||||
|
||||
stable.image().color(Pal.accent).fillX().height(3f).pad(3f).row();
|
||||
@@ -752,7 +823,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
t.add("@sectors.resources").padRight(4);
|
||||
for(UnlockableContent c : sector.info.resources){
|
||||
if(c == null) continue; //apparently this is possible.
|
||||
t.image(c.icon(Cicon.small)).padRight(3).size(Cicon.small.size);
|
||||
t.image(c.uiIcon).padRight(3).size(iconSmall);
|
||||
}
|
||||
}).padLeft(10f).fillX().row();
|
||||
}
|
||||
@@ -825,7 +896,12 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
if(mode == look && !sector.hasBase()){
|
||||
shouldHide = false;
|
||||
Sector from = findLauncher(sector);
|
||||
if(from == null){
|
||||
if(from == null || mode == planetLaunch){
|
||||
//TODO use the standard nucleus core schematic.
|
||||
if(mode == planetLaunch){
|
||||
listener.get(sector);
|
||||
}
|
||||
|
||||
//clear loadout information, so only the basic loadout gets used
|
||||
universe.clearLoadoutInfo();
|
||||
//free launch.
|
||||
@@ -857,6 +933,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
/** Look around for existing sectors. Can only deploy. */
|
||||
look,
|
||||
/** Select a sector for some purpose. */
|
||||
select
|
||||
select,
|
||||
/** Launch between planets. */
|
||||
planetLaunch
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ public class ResearchDialog extends BaseDialog{
|
||||
checkNodes(root);
|
||||
treeLayout();
|
||||
|
||||
view.hoverNode = null;
|
||||
view.infoTable.remove();
|
||||
view.infoTable.clear();
|
||||
});
|
||||
|
||||
hidden(ui.planet::setup);
|
||||
@@ -292,7 +295,7 @@ public class ResearchDialog extends BaseDialog{
|
||||
infoTable.touchable = Touchable.enabled;
|
||||
|
||||
for(TechTreeNode node : nodes){
|
||||
ImageButton button = new ImageButton(node.node.content.icon(Cicon.medium), Styles.nodei);
|
||||
ImageButton button = new ImageButton(node.node.content.uiIcon, Styles.nodei);
|
||||
button.visible(() -> node.visible);
|
||||
button.clicked(() -> {
|
||||
if(moved) return;
|
||||
@@ -339,7 +342,7 @@ public class ResearchDialog extends BaseDialog{
|
||||
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;
|
||||
|
||||
((TextureRegionDrawable)button.getStyle().imageUp).setRegion(node.selectable ? node.node.content.icon(Cicon.medium) : Icon.lock.getRegion());
|
||||
((TextureRegionDrawable)button.getStyle().imageUp).setRegion(node.selectable ? node.node.content.uiIcon : Icon.lock.getRegion());
|
||||
button.getImage().setColor(!locked(node.node) ? Color.white : node.selectable ? Color.gray : Pal.gray);
|
||||
button.getImage().setScaling(Scaling.bounded);
|
||||
});
|
||||
@@ -528,7 +531,7 @@ public class ResearchDialog extends BaseDialog{
|
||||
int reqAmount = req.amount - completed.amount;
|
||||
|
||||
list.left();
|
||||
list.image(req.item.icon(Cicon.small)).size(8 * 3).padRight(3);
|
||||
list.image(req.item.uiIcon).size(8 * 3).padRight(3);
|
||||
list.add(req.item.localizedName).color(Color.lightGray);
|
||||
Label label = list.label(() -> " " +
|
||||
UI.formatAmount(Math.min(items.get(req.item), reqAmount)) + " / "
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.graphics.g2d.*;
|
||||
@@ -11,8 +12,11 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.ImageButton.*;
|
||||
import arc.scene.ui.TextButton.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.scene.utils.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
@@ -20,18 +24,27 @@ import mindustry.input.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
import java.util.regex.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class SchematicsDialog extends BaseDialog{
|
||||
private static final float tagh = 42f;
|
||||
private SchematicInfoDialog info = new SchematicInfoDialog();
|
||||
private Schematic firstSchematic;
|
||||
private String search = "";
|
||||
private TextField searchField;
|
||||
private Runnable rebuildPane = () -> {}, rebuildTags = () -> {};
|
||||
private Pattern ignoreSymbols = Pattern.compile("[`~!@#$%^&*()-_=+{}|;:'\",<.>/?]");
|
||||
private Seq<String> tags, selectedTags = new Seq<>();
|
||||
private boolean checkedTags;
|
||||
|
||||
public SchematicsDialog(){
|
||||
super("@schematics");
|
||||
Core.assets.load("sprites/schematic-background.png", Texture.class).loaded = t -> ((Texture)t).setWrap(TextureWrap.repeat);
|
||||
|
||||
tags = Core.settings.getJson("schematic-tags", Seq.class, String.class, Seq::new);
|
||||
|
||||
shouldPause = true;
|
||||
addCloseButton();
|
||||
buttons.button("@schematic.import", Icon.download, this::showImport);
|
||||
@@ -40,8 +53,12 @@ public class SchematicsDialog extends BaseDialog{
|
||||
}
|
||||
|
||||
void setup(){
|
||||
if(!checkedTags){
|
||||
checkTags();
|
||||
checkedTags = true;
|
||||
}
|
||||
|
||||
search = "";
|
||||
Runnable[] rebuildPane = {null};
|
||||
|
||||
cont.top();
|
||||
cont.clear();
|
||||
@@ -51,15 +68,46 @@ public class SchematicsDialog extends BaseDialog{
|
||||
s.image(Icon.zoom);
|
||||
searchField = s.field(search, res -> {
|
||||
search = res;
|
||||
rebuildPane[0].run();
|
||||
rebuildPane.run();
|
||||
}).growX().get();
|
||||
}).fillX().padBottom(4);
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.table(in -> {
|
||||
in.left();
|
||||
in.add("@schematic.tags").padRight(4);
|
||||
|
||||
//tags (no scroll pane visible)
|
||||
in.pane(Styles.nonePane, t -> {
|
||||
rebuildTags = () -> {
|
||||
t.clearChildren();
|
||||
t.left();
|
||||
|
||||
t.defaults().pad(2).height(tagh);
|
||||
for(var tag : tags){
|
||||
t.button(tag, Styles.togglet, () -> {
|
||||
if(selectedTags.contains(tag)){
|
||||
selectedTags.remove(tag);
|
||||
}else{
|
||||
selectedTags.add(tag);
|
||||
}
|
||||
rebuildPane.run();
|
||||
}).checked(selectedTags.contains(tag)).with(c -> c.getLabel().setWrap(false));
|
||||
}
|
||||
};
|
||||
rebuildTags.run();
|
||||
}).fillX().height(tagh).get().setScrollingDisabled(false, true);
|
||||
|
||||
in.button(Icon.pencilSmall, () -> {
|
||||
showAllTags();
|
||||
}).size(tagh).pad(2).tooltip("@schematic.edittags");
|
||||
}).height(tagh).fillX();
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.pane(t -> {
|
||||
t.top();
|
||||
t.margin(20f);
|
||||
|
||||
t.update(() -> {
|
||||
if(Core.input.keyTap(Binding.chat) && Core.scene.getKeyboardFocus() == searchField && firstSchematic != null){
|
||||
@@ -72,18 +120,20 @@ public class SchematicsDialog extends BaseDialog{
|
||||
}
|
||||
});
|
||||
|
||||
rebuildPane[0] = () -> {
|
||||
rebuildPane = () -> {
|
||||
int cols = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1);
|
||||
|
||||
t.clear();
|
||||
int i = 0;
|
||||
String regex = "[`~!@#$%^&*()-_=+{}|;:'\",<.>/?]";
|
||||
String searchString = search.toLowerCase().replaceAll(regex, " ");
|
||||
String searchString = ignoreSymbols.matcher(search.toLowerCase()).replaceAll("");
|
||||
|
||||
firstSchematic = null;
|
||||
|
||||
for(Schematic s : schematics.all()){
|
||||
if(!search.isEmpty() && !s.name().toLowerCase().replaceAll(regex, " ").contains(searchString)) continue;
|
||||
//make sure *tags* fit
|
||||
if(selectedTags.any() && !s.labels.containsAll(selectedTags)) continue;
|
||||
//make sure search fits
|
||||
if(!search.isEmpty() && !ignoreSymbols.matcher(s.name().toLowerCase()).replaceAll("").contains(searchString)) continue;
|
||||
if(firstSchematic == null) firstSchematic = s;
|
||||
|
||||
Button[] sel = {null};
|
||||
@@ -106,20 +156,27 @@ public class SchematicsDialog extends BaseDialog{
|
||||
|
||||
buttons.button(Icon.pencil, style, () -> {
|
||||
new Dialog("@schematic.rename"){{
|
||||
setFillParent(true);
|
||||
|
||||
cont.margin(30);
|
||||
|
||||
cont.add("@schematic.tags").padRight(6f);
|
||||
cont.table(tags -> buildTags(s, tags, false)).maxWidth(400f).fillX().left().row();
|
||||
|
||||
cont.margin(30).add("@name").padRight(6f);
|
||||
TextField nameField = cont.field(s.name(), null).size(400f, 55f).addInputDialog().get();
|
||||
TextField nameField = cont.field(s.name(), null).size(400f, 55f).addInputDialog().left().get();
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.margin(30).add("@editor.description").padRight(6f);
|
||||
TextField descripionField = cont.area(s.description(), Styles.areaField, t -> {}).size(400f, 140f).addInputDialog().get();
|
||||
TextField descField = cont.area(s.description(), Styles.areaField, t -> {}).size(400f, 140f).left().addInputDialog().get();
|
||||
|
||||
Runnable accept = () -> {
|
||||
s.tags.put("name", nameField.getText());
|
||||
s.tags.put("description", descripionField.getText());
|
||||
s.tags.put("description", descField.getText());
|
||||
s.save();
|
||||
hide();
|
||||
rebuildPane[0].run();
|
||||
rebuildPane.run();
|
||||
};
|
||||
|
||||
buttons.defaults().size(120, 54).pad(4);
|
||||
@@ -127,7 +184,7 @@ public class SchematicsDialog extends BaseDialog{
|
||||
buttons.button("@cancel", this::hide);
|
||||
|
||||
keyDown(KeyCode.enter, () -> {
|
||||
if(!nameField.getText().isEmpty() && Core.scene.getKeyboardFocus() != descripionField){
|
||||
if(!nameField.getText().isEmpty() && Core.scene.getKeyboardFocus() != descField){
|
||||
accept.run();
|
||||
}
|
||||
});
|
||||
@@ -146,7 +203,7 @@ public class SchematicsDialog extends BaseDialog{
|
||||
}else{
|
||||
ui.showConfirm("@confirm", "@schematic.delete.confirm", () -> {
|
||||
schematics.remove(s);
|
||||
rebuildPane[0].run();
|
||||
rebuildPane.run();
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -188,8 +245,8 @@ public class SchematicsDialog extends BaseDialog{
|
||||
}
|
||||
};
|
||||
|
||||
rebuildPane[0].run();
|
||||
}).get().setScrollingDisabled(true, false);
|
||||
rebuildPane.run();
|
||||
}).grow().get().setScrollingDisabled(true, false);
|
||||
}
|
||||
|
||||
public void showInfo(Schematic schematic){
|
||||
@@ -212,6 +269,7 @@ public class SchematicsDialog extends BaseDialog{
|
||||
schematics.add(s);
|
||||
setup();
|
||||
ui.showInfoFade("@schematic.saved");
|
||||
checkTags(s);
|
||||
showInfo(s);
|
||||
}catch(Throwable e){
|
||||
ui.showException(e);
|
||||
@@ -227,6 +285,7 @@ public class SchematicsDialog extends BaseDialog{
|
||||
schematics.add(s);
|
||||
setup();
|
||||
showInfo(s);
|
||||
checkTags(s);
|
||||
}catch(Exception e){
|
||||
ui.showException(e);
|
||||
}
|
||||
@@ -281,6 +340,315 @@ public class SchematicsDialog extends BaseDialog{
|
||||
Core.scene.setKeyboardFocus(searchField);
|
||||
}
|
||||
|
||||
|
||||
//adds all new tags to the global list of tags
|
||||
//alternatively, unknown tags could be discarded on import?
|
||||
void checkTags(){
|
||||
ObjectSet<String> encountered = new ObjectSet<>();
|
||||
encountered.addAll(tags);
|
||||
for(Schematic s : schematics.all()){
|
||||
for(var tag : s.labels){
|
||||
if(encountered.add(tag)){
|
||||
tags.add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//adds any new tags found to the global tag list
|
||||
//TODO remove tags from it instead?
|
||||
void checkTags(Schematic s){
|
||||
boolean any = false;
|
||||
for(var tag : s.labels){
|
||||
if(!tags.contains(tag)){
|
||||
tags.add(tag);
|
||||
any = true;
|
||||
}
|
||||
}
|
||||
if(any){
|
||||
rebuildTags.run();
|
||||
}
|
||||
}
|
||||
|
||||
void tagsChanged(){
|
||||
rebuildTags.run();
|
||||
if(selectedTags.any()){
|
||||
rebuildPane.run();
|
||||
}
|
||||
|
||||
Core.settings.putJson("schematic-tags", String.class, tags);
|
||||
}
|
||||
|
||||
void addTag(Schematic s, String tag){
|
||||
s.labels.add(tag);
|
||||
s.save();
|
||||
tagsChanged();
|
||||
}
|
||||
|
||||
void removeTag(Schematic s, String tag){
|
||||
s.labels.remove(tag);
|
||||
s.save();
|
||||
tagsChanged();
|
||||
}
|
||||
|
||||
//shows a dialog for creating a new tag
|
||||
void showNewTag(Cons<String> result){
|
||||
ui.showTextInput("@schematic.addtag", "", "", out -> {
|
||||
if(tags.contains(out)){
|
||||
ui.showInfo("@schematic.tagexists");
|
||||
}else{
|
||||
tags.add(out);
|
||||
tagsChanged();
|
||||
result.get(out);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void showNewIconTag(Cons<String> cons){
|
||||
new Dialog(){{
|
||||
closeOnBack();
|
||||
setFillParent(true);
|
||||
|
||||
cont.pane(t -> {
|
||||
resized(true, () -> {
|
||||
t.clearChildren();
|
||||
t.marginRight(19f);
|
||||
t.defaults().size(48f);
|
||||
|
||||
int cols = (int)Math.min(20, Core.graphics.getWidth() / 52f);
|
||||
|
||||
/*
|
||||
int i = 0;
|
||||
for(var key : defaultIcons){
|
||||
var value = Icon.icons.get(key);
|
||||
|
||||
t.button(value, Styles.cleari, () -> {
|
||||
sector.info.icon = key;
|
||||
sector.info.contentIcon = null;
|
||||
sector.saveInfo();
|
||||
hide();
|
||||
updateSelected();
|
||||
}).checked(key.equals(sector.info.icon));
|
||||
|
||||
if(++i % cols == 0) t.row();
|
||||
}*/
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(ContentType ctype : defaultContentIcons){
|
||||
t.row();
|
||||
t.image().colspan(cols).growX().width(Float.NEGATIVE_INFINITY).height(3f).color(Pal.accent);
|
||||
t.row();
|
||||
|
||||
i = 0;
|
||||
for(UnlockableContent u : content.getBy(ctype).<UnlockableContent>as()){
|
||||
if(!u.isHidden() && u.unlockedNow() && u.hasEmoji() && !tags.contains(u.emoji())){
|
||||
t.button(new TextureRegionDrawable(u.uiIcon), Styles.cleari, iconMed, () -> {
|
||||
String out = u.emoji() + "";
|
||||
|
||||
tags.add(out);
|
||||
tagsChanged();
|
||||
cons.get(out);
|
||||
|
||||
hide();
|
||||
});
|
||||
|
||||
if(++i % cols == 0) t.row();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
buttons.button("@back", Icon.left, this::hide).size(210f, 64f);
|
||||
}}.show();
|
||||
}
|
||||
|
||||
void showAllTags(){
|
||||
var dialog = new BaseDialog("@schematic.edittags");
|
||||
dialog.addCloseButton();
|
||||
Runnable[] rebuild = {null};
|
||||
dialog.cont.pane(p -> {
|
||||
rebuild[0] = () -> {
|
||||
p.clearChildren();
|
||||
p.defaults().fillX().left();
|
||||
|
||||
float sum = 0f;
|
||||
Table current = new Table().left();
|
||||
|
||||
for(var tag : tags){
|
||||
|
||||
var next = new Table(Tex.button, n -> {
|
||||
n.add(tag).padRight(4);
|
||||
|
||||
n.add().growX();
|
||||
n.defaults().size(30f);
|
||||
|
||||
//delete
|
||||
n.button(Icon.cancelSmall, Styles.emptyi, () -> {
|
||||
ui.showConfirm("@schematic.tagdelconfirm", () -> {
|
||||
for(Schematic s : schematics.all()){
|
||||
if(s.labels.any()){
|
||||
s.labels.remove(tag);
|
||||
s.save();
|
||||
}
|
||||
}
|
||||
selectedTags.remove(tag);
|
||||
tags.remove(tag);
|
||||
tagsChanged();
|
||||
rebuildPane.run();
|
||||
rebuild[0].run();
|
||||
});
|
||||
});
|
||||
//rename
|
||||
n.button(Icon.pencilSmall, Styles.emptyi, () -> {
|
||||
ui.showTextInput("@schematic.renametag", "@name", tag, result -> {
|
||||
//same tag, nothing was renamed
|
||||
if(result.equals(tag)) return;
|
||||
|
||||
if(tags.contains(result)){
|
||||
ui.showInfo("@schematic.tagexists");
|
||||
}else{
|
||||
for(Schematic s : schematics.all()){
|
||||
if(s.labels.any()){
|
||||
s.labels.replace(tag, result);
|
||||
s.save();
|
||||
}
|
||||
}
|
||||
selectedTags.replace(tag, result);
|
||||
tags.replace(tag, result);
|
||||
tagsChanged();
|
||||
rebuild[0].run();
|
||||
}
|
||||
});
|
||||
});
|
||||
//move
|
||||
n.button(Icon.upSmall, Styles.emptyi, () -> {
|
||||
int idx = tags.indexOf(tag);
|
||||
if(idx > 0){
|
||||
tags.swap(idx, idx - 1);
|
||||
tagsChanged();
|
||||
rebuild[0].run();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
next.pack();
|
||||
float w = next.getPrefWidth() + Scl.scl(6f);
|
||||
|
||||
if(w + sum >= Core.graphics.getWidth() * (Core.graphics.isPortrait() ? 1f : 0.8f)){
|
||||
p.add(current).row();
|
||||
current = new Table();
|
||||
current.left();
|
||||
current.add(next).height(tagh).pad(2);
|
||||
sum = 0;
|
||||
}else{
|
||||
current.add(next).height(tagh).pad(2);
|
||||
}
|
||||
|
||||
sum += w;
|
||||
}
|
||||
|
||||
if(sum > 0){
|
||||
p.add(current).row();
|
||||
}
|
||||
|
||||
p.table(t -> {
|
||||
t.left().defaults().fillX().height(tagh).pad(2);
|
||||
|
||||
t.button("@schematic.texttag", Icon.add, () -> showNewTag(res -> rebuild[0].run())).wrapLabel(false).get().getLabelCell().padLeft(5);
|
||||
t.button("@schematic.icontag", Icon.add, () -> showNewIconTag(res -> rebuild[0].run())).wrapLabel(false).get().getLabelCell().padLeft(5);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
resized(true, rebuild[0]);
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
void buildTags(Schematic schem, Table t){
|
||||
buildTags(schem, t, true);
|
||||
}
|
||||
|
||||
void buildTags(Schematic schem, Table t, boolean name){
|
||||
t.clearChildren();
|
||||
t.left();
|
||||
|
||||
//sort by order in the main target array. the complexity of this is probably awful
|
||||
schem.labels.sort(s -> tags.indexOf(s));
|
||||
|
||||
if(name) t.add("@schematic.tags").padRight(4);
|
||||
t.pane(s -> {
|
||||
s.left();
|
||||
s.defaults().pad(3).height(tagh);
|
||||
for(var tag : schem.labels){
|
||||
s.table(Tex.button, i -> {
|
||||
i.add(tag).padRight(4).height(tagh).labelAlign(Align.center);
|
||||
i.button(Icon.cancelSmall, Styles.emptyi, () -> {
|
||||
removeTag(schem, tag);
|
||||
buildTags(schem, t, name);
|
||||
}).size(tagh).padRight(-9f).padLeft(-9f);
|
||||
});
|
||||
}
|
||||
|
||||
}).fillX().left().height(tagh).get().setScrollingDisabled(false, true);
|
||||
|
||||
t.button(Icon.addSmall, () -> {
|
||||
var dialog = new BaseDialog("@schematic.addtag");
|
||||
dialog.addCloseButton();
|
||||
dialog.cont.pane(p -> resized(true, () -> {
|
||||
p.clearChildren();
|
||||
|
||||
float sum = 0f;
|
||||
Table current = new Table().left();
|
||||
for(var tag : tags){
|
||||
if(schem.labels.contains(tag)) continue;
|
||||
|
||||
var next = Elem.newButton(tag, () -> {
|
||||
addTag(schem, tag);
|
||||
buildTags(schem, t, name);
|
||||
dialog.hide();
|
||||
});
|
||||
next.getLabel().setWrap(false);
|
||||
|
||||
next.pack();
|
||||
float w = next.getPrefWidth() + Scl.scl(6f);
|
||||
|
||||
if(w + sum >= Core.graphics.getWidth() * (Core.graphics.isPortrait() ? 1f : 0.8f)){
|
||||
p.add(current).row();
|
||||
current = new Table();
|
||||
current.left();
|
||||
current.add(next).height(tagh).pad(2);
|
||||
sum = 0;
|
||||
}else{
|
||||
current.add(next).height(tagh).pad(2);
|
||||
}
|
||||
|
||||
sum += w;
|
||||
}
|
||||
|
||||
if(sum > 0){
|
||||
p.add(current).row();
|
||||
}
|
||||
|
||||
Cons<String> handleTag = res -> {
|
||||
dialog.hide();
|
||||
addTag(schem, res);
|
||||
buildTags(schem, t, name);
|
||||
};
|
||||
|
||||
p.row();
|
||||
|
||||
p.table(v -> {
|
||||
v.left().defaults().fillX().height(tagh).pad(2);
|
||||
v.button("@schematic.texttag", Icon.add, () -> showNewTag(handleTag)).wrapLabel(false).get().getLabelCell().padLeft(4);
|
||||
v.button("@schematic.icontag", Icon.add, () -> showNewIconTag(handleTag)).wrapLabel(false).get().getLabelCell().padLeft(4);
|
||||
});
|
||||
}));
|
||||
dialog.show();
|
||||
}).size(tagh).tooltip("@schematic.addtag");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog show(){
|
||||
super.show();
|
||||
@@ -298,6 +666,7 @@ public class SchematicsDialog extends BaseDialog{
|
||||
public Color borderColor = Pal.gray;
|
||||
|
||||
private Schematic schematic;
|
||||
private Texture lastTexture;
|
||||
boolean set;
|
||||
|
||||
public SchematicImage(Schematic s){
|
||||
@@ -320,6 +689,8 @@ public class SchematicsDialog extends BaseDialog{
|
||||
if(!set){
|
||||
Core.app.post(this::setPreview);
|
||||
set = true;
|
||||
}else if(lastTexture != null && lastTexture.isDisposed()){
|
||||
set = wasSet = false;
|
||||
}
|
||||
|
||||
Texture background = Core.assets.get("sprites/schematic-background.png", Texture.class);
|
||||
@@ -346,13 +717,13 @@ public class SchematicsDialog extends BaseDialog{
|
||||
}
|
||||
|
||||
private void setPreview(){
|
||||
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(schematics.getPreview(schematic)));
|
||||
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(lastTexture = schematics.getPreview(schematic)));
|
||||
setDrawable(draw);
|
||||
setScaling(Scaling.fit);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SchematicInfoDialog extends BaseDialog{
|
||||
public class SchematicInfoDialog extends BaseDialog{
|
||||
|
||||
SchematicInfoDialog(){
|
||||
super("");
|
||||
@@ -366,6 +737,8 @@ public class SchematicsDialog extends BaseDialog{
|
||||
|
||||
cont.add(Core.bundle.format("schematic.info", schem.width, schem.height, schem.tiles.size)).color(Color.lightGray);
|
||||
cont.row();
|
||||
cont.table(tags -> buildTags(schem, tags)).fillX().left().row();
|
||||
cont.row();
|
||||
cont.add(new SchematicImage(schem)).maxSize(800f);
|
||||
cont.row();
|
||||
|
||||
@@ -373,7 +746,7 @@ public class SchematicsDialog extends BaseDialog{
|
||||
cont.table(r -> {
|
||||
int i = 0;
|
||||
for(ItemStack s : arr){
|
||||
r.image(s.item.icon(Cicon.small)).left();
|
||||
r.image(s.item.uiIcon).left().size(iconMed);
|
||||
r.label(() -> {
|
||||
Building core = player.core();
|
||||
if(core == null || state.rules.infiniteResources || core.items.has(s.item, s.amount)) return "[lightgray]" + s.amount + "";
|
||||
|
||||
@@ -2,11 +2,10 @@ package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.files.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.input.*;
|
||||
import arc.scene.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.TextButton.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
@@ -31,10 +30,11 @@ import static arc.Core.*;
|
||||
import static mindustry.Vars.net;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class SettingsMenuDialog extends SettingsDialog{
|
||||
public class SettingsMenuDialog extends Dialog{
|
||||
public SettingsTable graphics;
|
||||
public SettingsTable game;
|
||||
public SettingsTable sound;
|
||||
public SettingsTable main;
|
||||
|
||||
private Table prefs;
|
||||
private Table menu;
|
||||
@@ -42,6 +42,11 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
private boolean wasPaused;
|
||||
|
||||
public SettingsMenuDialog(){
|
||||
super(bundle.get("settings", "Settings"));
|
||||
addCloseButton();
|
||||
|
||||
cont.add(main = new SettingsTable());
|
||||
|
||||
hidden(() -> {
|
||||
Sounds.back.play();
|
||||
if(state.isGame()){
|
||||
@@ -60,6 +65,15 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
rebuildMenu();
|
||||
});
|
||||
|
||||
Events.on(ResizeEvent.class, event -> {
|
||||
if(isShown() && Core.scene.getDialog() == this){
|
||||
graphics.rebuild();
|
||||
sound.rebuild();
|
||||
game.rebuild();
|
||||
updateScrollFocus();
|
||||
}
|
||||
});
|
||||
|
||||
setFillParent(true);
|
||||
title.setAlignment(Align.center);
|
||||
titleTable.row();
|
||||
@@ -222,29 +236,8 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
}).marginLeft(4);
|
||||
});
|
||||
|
||||
ScrollPane pane = new ScrollPane(prefs);
|
||||
pane.addCaptureListener(new InputListener(){
|
||||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
|
||||
Element actor = pane.hit(x, y, true);
|
||||
if(actor instanceof Slider){
|
||||
pane.setFlickScroll(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.touchDown(event, x, y, pointer, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){
|
||||
pane.setFlickScroll(true);
|
||||
super.touchUp(event, x, y, pointer, button);
|
||||
}
|
||||
});
|
||||
pane.setFadeScrollBars(false);
|
||||
|
||||
row();
|
||||
add(pane).grow().top();
|
||||
pane(prefs).grow().top();
|
||||
row();
|
||||
add(buttons).fillX();
|
||||
|
||||
@@ -296,9 +289,13 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
game.screenshakePref();
|
||||
if(mobile){
|
||||
game.checkPref("autotarget", true);
|
||||
game.checkPref("keyboard", false, val -> control.setInput(val ? new DesktopInput() : new MobileInput()));
|
||||
game.checkPref("keyboard", false, val -> {
|
||||
control.setInput(val ? new DesktopInput() : new MobileInput());
|
||||
input.setUseKeyboard(val);
|
||||
});
|
||||
if(Core.settings.getBool("keyboard")){
|
||||
control.setInput(new DesktopInput());
|
||||
input.setUseKeyboard(true);
|
||||
}
|
||||
}
|
||||
//the issue with touchscreen support on desktop is that:
|
||||
@@ -346,10 +343,11 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
}
|
||||
}
|
||||
|
||||
int[] lastUiScale = {settings.getInt("uiscale", 100)};
|
||||
|
||||
graphics.sliderPref("uiscale", 100, 25, 300, 25, s -> {
|
||||
if(ui.settings != null){
|
||||
Core.settings.put("uiscalechanged", true);
|
||||
}
|
||||
//if the user changed their UI scale, but then put it back, don't consider it 'changed'
|
||||
Core.settings.put("uiscalechanged", s != lastUiScale[0]);
|
||||
return s + "%";
|
||||
});
|
||||
graphics.sliderPref("fpscap", 240, 15, 245, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s)));
|
||||
@@ -412,15 +410,12 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
graphics.checkPref("indicators", true);
|
||||
graphics.checkPref("showweather", true);
|
||||
graphics.checkPref("animatedwater", true);
|
||||
|
||||
if(Shaders.shield != null){
|
||||
graphics.checkPref("animatedshields", !mobile);
|
||||
}
|
||||
|
||||
//if(!ios){
|
||||
graphics.checkPref("bloom", true, val -> renderer.toggleBloom(val));
|
||||
//}else{
|
||||
// Core.settings.put("bloom", false);
|
||||
//}
|
||||
graphics.checkPref("bloom", true, val -> renderer.toggleBloom(val));
|
||||
|
||||
graphics.checkPref("pixelate", false, val -> {
|
||||
if(val){
|
||||
@@ -538,4 +533,174 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface StringProcessor{
|
||||
String get(int i);
|
||||
}
|
||||
|
||||
public static class SettingsTable extends Table{
|
||||
protected Seq<Setting> list = new Seq<>();
|
||||
|
||||
public SettingsTable(){
|
||||
left();
|
||||
}
|
||||
|
||||
public Seq<Setting> getSettings(){
|
||||
return list;
|
||||
}
|
||||
|
||||
public void pref(Setting setting){
|
||||
list.add(setting);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
public void screenshakePref(){
|
||||
sliderPref("screenshake", bundle.get("setting.screenshake.name", "Screen Shake"), 4, 0, 8, i -> (i / 4f) + "x");
|
||||
}
|
||||
|
||||
public SliderSetting sliderPref(String name, String title, int def, int min, int max, StringProcessor s){
|
||||
return sliderPref(name, title, def, min, max, 1, s);
|
||||
}
|
||||
|
||||
public SliderSetting sliderPref(String name, String title, int def, int min, int max, int step, StringProcessor s){
|
||||
SliderSetting res;
|
||||
list.add(res = new SliderSetting(name, title, def, min, max, step, s));
|
||||
settings.defaults(name, def);
|
||||
rebuild();
|
||||
return res;
|
||||
}
|
||||
|
||||
public SliderSetting sliderPref(String name, int def, int min, int max, StringProcessor s){
|
||||
return sliderPref(name, def, min, max, 1, s);
|
||||
}
|
||||
|
||||
public SliderSetting sliderPref(String name, int def, int min, int max, int step, StringProcessor s){
|
||||
SliderSetting res;
|
||||
list.add(res = new SliderSetting(name, bundle.get("setting." + name + ".name"), def, min, max, step, s));
|
||||
settings.defaults(name, def);
|
||||
rebuild();
|
||||
return res;
|
||||
}
|
||||
|
||||
public void checkPref(String name, String title, boolean def){
|
||||
list.add(new CheckSetting(name, title, def, null));
|
||||
settings.defaults(name, def);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
public void checkPref(String name, String title, boolean def, Boolc changed){
|
||||
list.add(new CheckSetting(name, title, def, changed));
|
||||
settings.defaults(name, def);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
/** Localized title. */
|
||||
public void checkPref(String name, boolean def){
|
||||
list.add(new CheckSetting(name, bundle.get("setting." + name + ".name"), def, null));
|
||||
settings.defaults(name, def);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
/** Localized title. */
|
||||
public void checkPref(String name, boolean def, Boolc changed){
|
||||
list.add(new CheckSetting(name, bundle.get("setting." + name + ".name"), def, changed));
|
||||
settings.defaults(name, def);
|
||||
rebuild();
|
||||
}
|
||||
|
||||
void rebuild(){
|
||||
clearChildren();
|
||||
|
||||
for(Setting setting : list){
|
||||
setting.add(this);
|
||||
}
|
||||
|
||||
button(bundle.get("settings.reset", "Reset to Defaults"), () -> {
|
||||
for(Setting setting : list){
|
||||
if(setting.name == null || setting.title == null) continue;
|
||||
settings.put(setting.name, settings.getDefault(setting.name));
|
||||
}
|
||||
rebuild();
|
||||
}).margin(14).width(240f).pad(6);
|
||||
}
|
||||
|
||||
public abstract static class Setting{
|
||||
public String name;
|
||||
public String title;
|
||||
|
||||
public abstract void add(SettingsTable table);
|
||||
}
|
||||
|
||||
public static class CheckSetting extends Setting{
|
||||
boolean def;
|
||||
Boolc changed;
|
||||
|
||||
CheckSetting(String name, String title, boolean def, Boolc changed){
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
this.def = def;
|
||||
this.changed = changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(SettingsTable table){
|
||||
CheckBox box = new CheckBox(title);
|
||||
|
||||
box.update(() -> box.setChecked(settings.getBool(name)));
|
||||
|
||||
box.changed(() -> {
|
||||
settings.put(name, box.isChecked());
|
||||
if(changed != null){
|
||||
changed.get(box.isChecked());
|
||||
}
|
||||
});
|
||||
|
||||
box.left();
|
||||
table.add(box).left().padTop(3f);
|
||||
table.row();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SliderSetting extends Setting{
|
||||
int def, min, max, step;
|
||||
StringProcessor sp;
|
||||
|
||||
SliderSetting(String name, String title, int def, int min, int max, int step, StringProcessor s){
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
this.def = def;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.step = step;
|
||||
this.sp = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(SettingsTable table){
|
||||
Slider slider = new Slider(min, max, step, false);
|
||||
|
||||
slider.setValue(settings.getInt(name));
|
||||
|
||||
Label label = new Label(title);
|
||||
slider.changed(() -> {
|
||||
settings.put(name, (int)slider.getValue());
|
||||
label.setText(title + ": " + sp.get((int)slider.getValue()));
|
||||
});
|
||||
|
||||
slider.change();
|
||||
|
||||
table.table(t -> {
|
||||
t.left().defaults().left();
|
||||
t.add(label).minWidth(label.getPrefWidth() / Scl.scl(1f) + 50);
|
||||
if(Core.graphics.isPortrait()){
|
||||
t.row();
|
||||
}
|
||||
t.add(slider).width(180);
|
||||
}).left().padTop(3);
|
||||
|
||||
table.row();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import arc.util.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -147,7 +146,7 @@ public class BlockInventoryFragment extends Fragment{
|
||||
HandCursorListener l = new HandCursorListener();
|
||||
l.enabled = canPick;
|
||||
|
||||
Element image = itemImage(item.icon(Cicon.xlarge), () -> {
|
||||
Element image = itemImage(item.uiIcon, () -> {
|
||||
if(tile == null || !tile.isValid()){
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -156,6 +156,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()),
|
||||
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()),
|
||||
payloadDrop(() -> !player.unit().dead && player.unit() instanceof Payloadc p && p.payloads().any(), () -> player.unit() instanceof Payloadc p && p.payloads().isEmpty()),
|
||||
|
||||
@@ -17,6 +17,7 @@ import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
@@ -30,7 +31,7 @@ import mindustry.ui.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class HudFragment extends Fragment{
|
||||
private static final float dsize = 65f;
|
||||
private static final float dsize = 65f, pauseHeight = 36f;
|
||||
|
||||
public final PlacementFragment blockfrag = new PlacementFragment();
|
||||
public boolean shown = true;
|
||||
@@ -60,7 +61,7 @@ public class HudFragment extends Fragment{
|
||||
|
||||
//increments at which to warn about incoming guardian
|
||||
if(diff == 1 || diff == 2 || diff == 5 || diff == 10){
|
||||
showToast(Icon.warning, Core.bundle.format("wave.guardianwarn" + (diff == 1 ? ".one" : ""), diff));
|
||||
showToast(Icon.warning, group.type.emoji() + " " + Core.bundle.format("wave.guardianwarn" + (diff == 1 ? ".one" : ""), diff));
|
||||
}
|
||||
|
||||
break outer;
|
||||
@@ -90,7 +91,9 @@ public class HudFragment extends Fragment{
|
||||
parent.fill(t -> {
|
||||
t.name = "paused";
|
||||
t.top().visible(() -> state.isPaused() && shown).touchable = Touchable.disabled;
|
||||
t.table(Styles.black5, top -> top.label(() -> state.gameOver && state.isCampaign() ? "@sector.curlost" : "@paused").style(Styles.outlineLabel).pad(8f)).growX();
|
||||
t.table(Styles.black6, top -> top.label(() -> netServer.isWaitingForPlayers() ? "@waiting.players" : state.gameOver && state.isCampaign() ? "@sector.curlost" : "@paused")
|
||||
.style(Styles.outlineLabel).pad(8f)).height(pauseHeight).growX();
|
||||
//.padLeft(dsize * 5 + 4f) to prevent alpha overlap on left
|
||||
});
|
||||
|
||||
//minimap + position
|
||||
@@ -208,10 +211,7 @@ public class HudFragment extends Fragment{
|
||||
|
||||
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).name("boss");
|
||||
|
||||
wavesMain.row();
|
||||
addInfoTable(wavesMain.table().width(dsize * 5f + 4f).left().get());
|
||||
|
||||
editorMain.name = "editor";
|
||||
editorMain.table(Tex.buttonEdge4, t -> {
|
||||
@@ -244,6 +244,7 @@ public class HudFragment extends Fragment{
|
||||
info.top().left().margin(4).visible(() -> Core.settings.getBool("fps") && shown);
|
||||
IntFormat fps = new IntFormat("fps");
|
||||
IntFormat ping = new IntFormat("ping");
|
||||
IntFormat tps = new IntFormat("tps");
|
||||
IntFormat mem = new IntFormat("memory");
|
||||
IntFormat memnative = new IntFormat("memory2");
|
||||
|
||||
@@ -257,68 +258,83 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
info.row();
|
||||
|
||||
info.label(() -> ping.get(netClient.getPing())).visible(net::client).left().style(Styles.outlineLabel).name("ping");
|
||||
info.label(() -> ping.get(netClient.getPing())).visible(net::client).left().style(Styles.outlineLabel).name("ping").row();
|
||||
info.label(() -> tps.get(state.serverTps == -1 ? 60 : state.serverTps)).visible(net::client).left().style(Styles.outlineLabel).name("tps").row();
|
||||
|
||||
}).top().left();
|
||||
});
|
||||
|
||||
//core items
|
||||
//core info
|
||||
parent.fill(t -> {
|
||||
t.name = "coreitems";
|
||||
t.top().add(coreItems);
|
||||
t.visible(() -> Core.settings.getBool("coreitems") && !mobile && !state.isPaused() && shown);
|
||||
t.top();
|
||||
|
||||
t.name = "coreinfo";
|
||||
|
||||
t.collapser(v -> v.add().height(pauseHeight), () -> state.isPaused()).row();
|
||||
|
||||
t.table(c -> {
|
||||
//core items
|
||||
c.top().collapser(coreItems, () -> Core.settings.getBool("coreitems") && !mobile && shown).fillX().row();
|
||||
|
||||
float notifDuration = 240f;
|
||||
float[] coreAttackTime = {0};
|
||||
|
||||
Events.run(Trigger.teamCoreDamage, () -> coreAttackTime[0] = notifDuration);
|
||||
|
||||
//'core is under attack' table
|
||||
c.collapser(top -> top.background(Styles.black6).add("@coreattack").pad(8)
|
||||
.update(label -> label.color.set(Color.orange).lerp(Color.scarlet, Mathf.absin(Time.time, 2f, 1f))), true,
|
||||
() -> {
|
||||
if(!shown || state.isPaused()) return false;
|
||||
if(state.isMenu() || !state.teams.get(player.team()).hasCore()){
|
||||
coreAttackTime[0] = 0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
return (coreAttackTime[0] -= Time.delta) > 0;
|
||||
})
|
||||
.touchable(Touchable.disabled)
|
||||
.fillX().row();
|
||||
}).row();
|
||||
|
||||
var bossb = new StringBuilder();
|
||||
var bossText = Core.bundle.get("guardian");
|
||||
int maxBosses = 6;
|
||||
|
||||
t.table(v -> v.margin(10f)
|
||||
.add(new Bar(() -> {
|
||||
bossb.setLength(0);
|
||||
for(int i = 0; i < Math.min(state.teams.bosses.size, maxBosses); i++){
|
||||
bossb.append(state.teams.bosses.get(i).type.emoji());
|
||||
}
|
||||
if(state.teams.bosses.size > maxBosses){
|
||||
bossb.append("[accent]+[]");
|
||||
}
|
||||
bossb.append(" ");
|
||||
bossb.append(bossText);
|
||||
return bossb;
|
||||
}, () -> Pal.health, () -> {
|
||||
if(state.boss() == null) return 0f;
|
||||
float max = 0f, val = 0f;
|
||||
for(var boss : state.teams.bosses){
|
||||
max += boss.maxHealth;
|
||||
val += boss.health;
|
||||
}
|
||||
return max == 0f ? 0f : val / max;
|
||||
}).blink(Color.white).outline(new Color(0, 0, 0, 0.6f), 7f)).grow())
|
||||
.fillX().width(320f).height(60f).name("boss").visible(() -> state.rules.waves && state.boss() != null).padTop(7);
|
||||
});
|
||||
|
||||
//spawner warning
|
||||
parent.fill(t -> {
|
||||
t.name = "nearpoint";
|
||||
t.touchable = Touchable.disabled;
|
||||
t.table(Styles.black, c -> c.add("@nearpoint")
|
||||
t.table(Styles.black6, 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))
|
||||
.labelAlign(Align.center, Align.center))
|
||||
.margin(6).update(u -> u.color.a = Mathf.lerpDelta(u.color.a, Mathf.num(spawner.playerNear()), 0.1f)).get().color.a = 0f;
|
||||
});
|
||||
|
||||
parent.fill(t -> {
|
||||
t.name = "waiting";
|
||||
t.visible(() -> netServer.isWaitingForPlayers());
|
||||
t.table(Tex.button, c -> c.add("@waiting.players"));
|
||||
});
|
||||
|
||||
//'core is under attack' table
|
||||
parent.fill(t -> {
|
||||
t.name = "coreattack";
|
||||
t.touchable = Touchable.disabled;
|
||||
float notifDuration = 240f;
|
||||
float[] coreAttackTime = {0};
|
||||
float[] coreAttackOpacity = {0};
|
||||
|
||||
Events.run(Trigger.teamCoreDamage, () -> {
|
||||
coreAttackTime[0] = notifDuration;
|
||||
});
|
||||
|
||||
t.top().visible(() -> {
|
||||
if(!shown) return false;
|
||||
if(state.isMenu() || !state.teams.get(player.team()).hasCore()){
|
||||
coreAttackTime[0] = 0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
t.color.a = coreAttackOpacity[0];
|
||||
if(coreAttackTime[0] > 0){
|
||||
coreAttackOpacity[0] = Mathf.lerpDelta(coreAttackOpacity[0], 1f, 0.1f);
|
||||
}else{
|
||||
coreAttackOpacity[0] = Mathf.lerpDelta(coreAttackOpacity[0], 0f, 0.1f);
|
||||
}
|
||||
|
||||
coreAttackTime[0] -= Time.delta;
|
||||
|
||||
return coreAttackOpacity[0] > 0;
|
||||
});
|
||||
t.table(Tex.button, top -> top.add("@coreattack").pad(2)
|
||||
.update(label -> label.color.set(Color.orange).lerp(Color.scarlet, Mathf.absin(Time.time, 2f, 1f)))).touchable(Touchable.disabled);
|
||||
});
|
||||
|
||||
//'saving' indicator
|
||||
parent.fill(t -> {
|
||||
t.name = "saving";
|
||||
@@ -343,7 +359,6 @@ public class HudFragment extends Fragment{
|
||||
//TODO DEBUG: rate table
|
||||
if(false)
|
||||
parent.fill(t -> {
|
||||
t.name = "rates";
|
||||
t.bottom().left();
|
||||
t.table(Styles.black6, c -> {
|
||||
Bits used = new Bits(content.items().size);
|
||||
@@ -353,7 +368,7 @@ public class HudFragment extends Fragment{
|
||||
|
||||
for(Item item : content.items()){
|
||||
if(state.rules.sector != null && state.rules.sector.info.getExport(item) >= 1){
|
||||
c.image(item.icon(Cicon.small));
|
||||
c.image(item.uiIcon);
|
||||
c.label(() -> (int)state.rules.sector.info.getExport(item) + " /s").color(Color.lightGray);
|
||||
c.row();
|
||||
}
|
||||
@@ -412,6 +427,10 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
|
||||
public void showToast(Drawable icon, String text){
|
||||
showToast(icon, -1, text);
|
||||
}
|
||||
|
||||
public void showToast(Drawable icon, float size, String text){
|
||||
if(state.isMenu()) return;
|
||||
|
||||
scheduleToast(() -> {
|
||||
@@ -424,7 +443,8 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
});
|
||||
table.margin(12);
|
||||
table.image(icon).pad(3);
|
||||
var cell = table.image(icon).pad(3);
|
||||
if(size > 0) cell.size(size);
|
||||
table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center);
|
||||
table.pack();
|
||||
|
||||
@@ -462,7 +482,7 @@ public class HudFragment extends Fragment{
|
||||
Table in = new Table();
|
||||
|
||||
//create texture stack for displaying
|
||||
Image image = new Image(content.icon(Cicon.xlarge));
|
||||
Image image = new Image(content.uiIcon);
|
||||
image.setScaling(Scaling.fit);
|
||||
|
||||
in.add(image).size(8 * 6).pad(2);
|
||||
@@ -516,7 +536,7 @@ public class HudFragment extends Fragment{
|
||||
//if there's space, add it
|
||||
if(esize < cap){
|
||||
|
||||
Image image = new Image(content.icon(Cicon.medium));
|
||||
Image image = new Image(content.uiIcon);
|
||||
image.setScaling(Scaling.fit);
|
||||
|
||||
lastUnlockLayout.add(image);
|
||||
@@ -758,6 +778,12 @@ public class HudFragment extends Fragment{
|
||||
|
||||
table.row();
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
private void addInfoTable(Table table){
|
||||
table.left();
|
||||
|
||||
var count = new float[]{-1};
|
||||
table.table().update(t -> {
|
||||
if(player.unit() instanceof Payloadc payload){
|
||||
@@ -770,8 +796,29 @@ public class HudFragment extends Fragment{
|
||||
t.clear();
|
||||
}
|
||||
}).growX().visible(() -> player.unit() instanceof Payloadc p && p.payloadUsed() > 0).colspan(2);
|
||||
table.row();
|
||||
|
||||
return table;
|
||||
Bits statuses = new Bits();
|
||||
|
||||
table.table().update(t -> {
|
||||
t.left();
|
||||
Bits applied = player.unit().statusBits();
|
||||
if(!statuses.equals(applied)){
|
||||
t.clear();
|
||||
|
||||
if(applied != null){
|
||||
for(StatusEffect effect : content.statusEffects()){
|
||||
if(applied.get(effect.id) && !effect.isHidden()){
|
||||
t.image(effect.uiIcon).size(iconMed).get()
|
||||
.addListener(new Tooltip(l -> l.label(() ->
|
||||
effect.localizedName + " [lightgray]" + UI.formatTime(player.unit().getDuration(effect))).style(Styles.outlineLabel)));
|
||||
}
|
||||
}
|
||||
|
||||
statuses.set(applied);
|
||||
}
|
||||
}
|
||||
}).left();
|
||||
}
|
||||
|
||||
private boolean canSkipWave(){
|
||||
|
||||
@@ -98,7 +98,7 @@ public class PlacementFragment extends Fragment{
|
||||
|
||||
if(Core.input.keyTap(Binding.pick) && player.isBuilder()){ //mouse eyedropper select
|
||||
var build = world.buildWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
|
||||
Block tryRecipe = build == null ? null : build instanceof ConstructBuild c ? c.cblock : build.block;
|
||||
Block tryRecipe = build == null ? null : build instanceof ConstructBuild c ? c.current : build.block;
|
||||
Object tryConfig = build == null || !build.block.copyConfig ? null : build.config();
|
||||
|
||||
for(BuildPlan req : player.unit().plans()){
|
||||
@@ -224,7 +224,7 @@ public class PlacementFragment extends Fragment{
|
||||
blockTable.row();
|
||||
}
|
||||
|
||||
ImageButton button = blockTable.button(new TextureRegionDrawable(block.icon(Cicon.medium)), Styles.selecti, () -> {
|
||||
ImageButton button = blockTable.button(new TextureRegionDrawable(block.uiIcon), Styles.selecti, () -> {
|
||||
if(unlocked(block)){
|
||||
if(Core.input.keyDown(KeyCode.shiftLeft) && Fonts.getUnicode(block.name) != 0){
|
||||
Core.app.setClipboardText((char)Fonts.getUnicode(block.name) + "");
|
||||
@@ -235,7 +235,7 @@ public class PlacementFragment extends Fragment{
|
||||
}
|
||||
}
|
||||
}).size(46f).group(group).name("block-" + block.name).get();
|
||||
button.resizeImage(Cicon.medium.size);
|
||||
button.resizeImage(iconMed);
|
||||
|
||||
button.update(() -> { //color unplacable things gray
|
||||
Building core = player.core();
|
||||
@@ -309,7 +309,7 @@ public class PlacementFragment extends Fragment{
|
||||
}
|
||||
final String keyComboFinal = keyCombo;
|
||||
header.left();
|
||||
header.add(new Image(displayBlock.icon(Cicon.medium))).size(8 * 4);
|
||||
header.add(new Image(displayBlock.uiIcon)).size(8 * 4);
|
||||
header.labelWrap(() -> !unlocked(displayBlock) ? Core.bundle.get("block.unknown") : displayBlock.localizedName + keyComboFinal)
|
||||
.left().width(190f).padLeft(5);
|
||||
header.add().growX();
|
||||
@@ -328,7 +328,7 @@ public class PlacementFragment extends Fragment{
|
||||
for(ItemStack stack : displayBlock.requirements){
|
||||
req.table(line -> {
|
||||
line.left();
|
||||
line.image(stack.item.icon(Cicon.small)).size(8 * 2);
|
||||
line.image(stack.item.uiIcon).size(8 * 2);
|
||||
line.add(stack.item.localizedName).maxWidth(140f).fillX().color(Color.lightGray).padLeft(2).left().get().setEllipsis(true);
|
||||
line.labelWrap(() -> {
|
||||
Building core = player.core();
|
||||
@@ -349,7 +349,7 @@ public class PlacementFragment extends Fragment{
|
||||
topTable.row();
|
||||
topTable.table(b -> {
|
||||
b.image(Icon.cancel).padRight(2).color(Color.scarlet);
|
||||
b.add(!player.isBuilder() ? "@unit.nobuild" : "@banned").width(190f).wrap();
|
||||
b.add(!player.isBuilder() ? "@unit.nobuild" : !displayBlock.supportsEnv(state.rules.environment) ? "@unsupported.environment" : "@banned").width(190f).wrap();
|
||||
b.left();
|
||||
}).padTop(2).left();
|
||||
}
|
||||
@@ -471,7 +471,7 @@ public class PlacementFragment extends Fragment{
|
||||
}
|
||||
|
||||
//if the tile has a drop, display the drop
|
||||
if(hoverTile.drop() != null){
|
||||
if(hoverTile.drop() != null || hoverTile.wallDrop() != null){
|
||||
return hoverTile;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user