Merge
This commit is contained in:
@@ -1,9 +1,195 @@
|
||||
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.BitmapFont.*;
|
||||
import arc.graphics.g2d.PixmapPacker.*;
|
||||
import arc.graphics.g2d.TextureAtlas.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Fonts{
|
||||
private static ObjectIntMap<String> unicodeIcons = new ObjectIntMap<>();
|
||||
|
||||
public static BitmapFont def;
|
||||
public static BitmapFont outline;
|
||||
public static BitmapFont chat;
|
||||
public static BitmapFont icon;
|
||||
|
||||
public static int getUnicode(String content){
|
||||
return unicodeIcons.get(content, 0);
|
||||
}
|
||||
|
||||
/** Called from a static context to make the cursor appear immediately upon startup.*/
|
||||
public static void loadSystemCursors(){
|
||||
SystemCursor.arrow.set(Core.graphics.newCursor("cursor"));
|
||||
SystemCursor.hand.set(Core.graphics.newCursor("hand"));
|
||||
SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam"));
|
||||
|
||||
Core.graphics.restoreCursor();
|
||||
}
|
||||
|
||||
public static void loadFonts(){
|
||||
String fontName = "fonts/font.ttf";
|
||||
|
||||
FreeTypeFontParameter param = fontParameter();
|
||||
|
||||
Core.assets.load("default", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.def = (BitmapFont)f;
|
||||
Core.assets.load("chat", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.chat = (BitmapFont)f;
|
||||
Core.assets.load("icon", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/icon.ttf", new FreeTypeFontParameter(){{
|
||||
size = (int)(Scl.scl(30f));
|
||||
incremental = true;
|
||||
}})).loaded = f -> Fonts.icon = (BitmapFont)f;
|
||||
}
|
||||
|
||||
public static void loadContentIcons(){
|
||||
Array<BitmapFont> fonts = Array.with(Fonts.chat, Fonts.def, Fonts.outline);
|
||||
Texture uitex = Core.atlas.find("logo").getTexture();
|
||||
int size = (int)(Fonts.def.getData().lineHeight/Fonts.def.getData().scaleY);
|
||||
|
||||
try(Scanner scan = new Scanner(Core.files.internal("icons/icons.properties").read(512))){
|
||||
while(scan.hasNextLine()){
|
||||
String line = scan.nextLine();
|
||||
String[] split = line.split("=");
|
||||
String[] nametex = split[1].split("\\|");
|
||||
String character = split[0], texture = nametex[1];
|
||||
int ch = Integer.parseInt(character);
|
||||
TextureRegion region = Core.atlas.find(texture);
|
||||
|
||||
if(region.getTexture() != uitex) throw new IllegalArgumentException("Font icon '" + texture + "' is not in the UI texture.");
|
||||
|
||||
unicodeIcons.put(nametex[0], ch);
|
||||
|
||||
Glyph glyph = new Glyph();
|
||||
glyph.id = ch;
|
||||
glyph.srcX = 0;
|
||||
glyph.srcY = 0;
|
||||
glyph.width = size;
|
||||
glyph.height = size;
|
||||
glyph.u = region.getU();
|
||||
glyph.v = region.getV2();
|
||||
glyph.u2 = region.getU2();
|
||||
glyph.v2 = region.getV();
|
||||
glyph.xoffset = 0;
|
||||
glyph.yoffset = -size;
|
||||
glyph.xadvance = size;
|
||||
glyph.kerning = null;
|
||||
glyph.fixedWidth = true;
|
||||
glyph.page = 0;
|
||||
fonts.each(f -> f.getData().setGlyph(ch, glyph));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Called from a static context for use in the loading screen.*/
|
||||
public static void loadDefaultFont(){
|
||||
UI.packer = new PixmapPacker(2048, 2048, Format.RGBA8888, 2, true);
|
||||
FileHandleResolver resolver = new InternalFileHandleResolver();
|
||||
Core.assets.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
|
||||
Core.assets.setLoader(BitmapFont.class, null, new FreetypeFontLoader(resolver){
|
||||
@Override
|
||||
public BitmapFont loadSync(AssetManager manager, String fileName, Fi file, FreeTypeFontLoaderParameter parameter){
|
||||
if(fileName.equals("outline")){
|
||||
parameter.fontParameters.borderWidth = Scl.scl(2f);
|
||||
parameter.fontParameters.spaceX -= parameter.fontParameters.borderWidth;
|
||||
}
|
||||
parameter.fontParameters.magFilter = TextureFilter.Linear;
|
||||
parameter.fontParameters.minFilter = TextureFilter.Linear;
|
||||
parameter.fontParameters.packer = UI.packer;
|
||||
return super.loadSync(manager, fileName, file, parameter);
|
||||
}
|
||||
});
|
||||
|
||||
FreeTypeFontParameter param = new FreeTypeFontParameter(){{
|
||||
borderColor = Color.darkGray;
|
||||
size = (int)(Scl.scl(18f));
|
||||
incremental = true;
|
||||
}};
|
||||
|
||||
Core.assets.load("outline", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/font.ttf", param)).loaded = t -> Fonts.outline = (BitmapFont)t;
|
||||
}
|
||||
|
||||
/** Merges the UI and font atlas together for better performance. */
|
||||
public static void mergeFontAtlas(TextureAtlas atlas){
|
||||
//grab all textures from the ui page, remove all the regions assigned to it, then copy them over to Fonts.packer and replace the texture in this atlas.
|
||||
|
||||
//grab old UI texture and regions...
|
||||
Texture texture = atlas.find("logo").getTexture();
|
||||
|
||||
Page page = UI.packer.getPages().first();
|
||||
|
||||
Array<AtlasRegion> regions = atlas.getRegions().select(t -> t.getTexture() == texture);
|
||||
for(AtlasRegion region : regions){
|
||||
//get new pack rect
|
||||
page.setDirty(false);
|
||||
Rect rect = UI.packer.pack(region.name + (region.splits != null ? ".9" : ""), atlas.getPixmap(region));
|
||||
//set new texture
|
||||
region.setTexture(UI.packer.getPages().first().getTexture());
|
||||
//set its new position
|
||||
region.set((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
||||
//add old texture
|
||||
atlas.getTextures().add(region.getTexture());
|
||||
}
|
||||
|
||||
//remove old texture, it will no longer be used
|
||||
atlas.getTextures().remove(texture);
|
||||
texture.dispose();
|
||||
atlas.disposePixmap(texture);
|
||||
|
||||
page.setDirty(true);
|
||||
page.updateTexture(TextureFilter.Linear, TextureFilter.Linear, false);
|
||||
}
|
||||
|
||||
public static TextureRegionDrawable getGlyph(BitmapFont font, char glyph){
|
||||
Glyph g = font.getData().getGlyph(glyph);
|
||||
if(g == null) throw new IllegalArgumentException("No glyph: " + glyph + " (" + (int)glyph + ")");
|
||||
|
||||
float size = Math.max(g.width, g.height);
|
||||
float aspect = (float)g.height / g.width;
|
||||
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().getTexture(), g.u, g.v2, g.u2, g.v)){
|
||||
@Override
|
||||
public void draw(float x, float y, float width, float height){
|
||||
Draw.color(Tmp.c1.set(tint).mul(Draw.getColor()).toFloatBits());
|
||||
float cx = x + width/2f - g.width/2f, cy = y + height/2f - g.height/2f;
|
||||
cx = (int)cx;
|
||||
cy = (int)cy;
|
||||
Draw.rect(region, cx + g.width/2f, cy + g.height/2f, g.width, g.height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float imageSize(){
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
draw.setMinWidth(size);
|
||||
draw.setMinHeight(size);
|
||||
return draw;
|
||||
}
|
||||
|
||||
static FreeTypeFontParameter fontParameter(){
|
||||
return new FreeTypeFontParameter(){{
|
||||
size = (int)(Scl.scl(18f));
|
||||
shadowColor = Color.darkGray;
|
||||
shadowOffsetY = 2;
|
||||
incremental = true;
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public class ItemImage extends Stack{
|
||||
|
||||
if(stack.amount != 0){
|
||||
Table t = new Table().left().bottom();
|
||||
t.add(stack.amount + "").name("item-label");
|
||||
t.add(stack.amount + "").name("item-label").style(Styles.outlineLabel);
|
||||
add(t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package mindustry.ui;
|
||||
|
||||
import arc.Core;
|
||||
import arc.scene.style.*;
|
||||
import arc.util.Strings;
|
||||
import arc.graphics.Color;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.Pal;
|
||||
|
||||
public class Links{
|
||||
@@ -10,17 +12,17 @@ public class Links{
|
||||
|
||||
private static void createLinks(){
|
||||
links = new LinkEntry[]{
|
||||
new LinkEntry("discord", "https://discord.gg/mindustry", Color.valueOf("7289da")),
|
||||
new LinkEntry("changelog", "https://github.com/Anuken/Mindustry/releases", Pal.accent.cpy()),
|
||||
new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Color.valueOf("026aa7")),
|
||||
new LinkEntry("wiki", "https://mindustrygame.github.io/wiki/", Color.valueOf("0f142f")),
|
||||
new LinkEntry("feathub", "https://feathub.com/Anuken/Mindustry/", Color.valueOf("ebebeb")),
|
||||
new LinkEntry("reddit", "https://www.reddit.com/r/Mindustry/", Color.valueOf("ee593b")),
|
||||
new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Color.valueOf("fa5c5c")),
|
||||
new LinkEntry("google-play", "https://play.google.com/store/apps/details?id=io.anuke.mindustry", Color.valueOf("689f38")),
|
||||
new LinkEntry("f-droid", "https://f-droid.org/packages/io.anuke.mindustry/", Color.valueOf("026aa7")),
|
||||
new LinkEntry("github", "https://github.com/Anuken/Mindustry/", Color.valueOf("24292e")),
|
||||
new LinkEntry("dev-builds", "https://github.com/Anuken/MindustryBuilds", Color.valueOf("fafbfc"))
|
||||
new LinkEntry("discord", "https://discord.gg/mindustry", Icon.discord, Color.valueOf("7289da")),
|
||||
new LinkEntry("changelog", "https://github.com/Anuken/Mindustry/releases", Icon.list, Pal.accent.cpy()),
|
||||
new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Icon.trello, Color.valueOf("026aa7")),
|
||||
new LinkEntry("wiki", "https://mindustrygame.github.io/wiki/", Icon.book, Color.valueOf("0f142f")),
|
||||
new LinkEntry("feathub", "https://feathub.com/Anuken/Mindustry/", Icon.add, Color.valueOf("ebebeb")),
|
||||
new LinkEntry("reddit", "https://www.reddit.com/r/Mindustry/", Icon.redditAlien, Color.valueOf("ee593b")),
|
||||
new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Icon.itchio, Color.valueOf("fa5c5c")),
|
||||
new LinkEntry("google-play", "https://play.google.com/store/apps/details?id=io.anuke.mindustry", Icon.googleplay, Color.valueOf("689f38")),
|
||||
new LinkEntry("f-droid", "https://f-droid.org/packages/io.anuke.mindustry/", Icon.android, Color.valueOf("026aa7")),
|
||||
new LinkEntry("github", "https://github.com/Anuken/Mindustry/", Icon.github, Color.valueOf("24292e")),
|
||||
new LinkEntry("dev-builds", "https://github.com/Anuken/MindustryBuilds", Icon.githubSquare, Color.valueOf("fafbfc"))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -35,12 +37,14 @@ public class Links{
|
||||
public static class LinkEntry{
|
||||
public final String name, title, description, link;
|
||||
public final Color color;
|
||||
public final Drawable icon;
|
||||
|
||||
public LinkEntry(String name, String link, Color color){
|
||||
public LinkEntry(String name, String link, Drawable icon, Color color){
|
||||
this.name = name;
|
||||
this.color = color;
|
||||
this.description = Core.bundle.getNotNull("link." + name + ".description");
|
||||
this.link = link;
|
||||
this.icon = icon;
|
||||
|
||||
String title = Core.bundle.getOrNull("link." + name + ".title");
|
||||
this.title = title != null ? title : Strings.capitalize(name.replace("-", " "));
|
||||
|
||||
@@ -24,13 +24,13 @@ public class LiquidDisplay extends Table{
|
||||
|
||||
if(amount != 0){
|
||||
Table t = new Table().left().bottom();
|
||||
t.add(Strings.autoFixed(amount, 1));
|
||||
t.add(Strings.autoFixed(amount, 1)).style(Styles.outlineLabel);
|
||||
add(t);
|
||||
}
|
||||
}}).size(8 * 4).padRight(3 + (amount != 0 && Strings.autoFixed(amount, 1).length() > 2 ? 8 : 0));
|
||||
|
||||
if(perSecond){
|
||||
add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray);
|
||||
add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray).style(Styles.outlineLabel);
|
||||
}
|
||||
|
||||
add(liquid.localizedName);
|
||||
|
||||
@@ -55,7 +55,7 @@ public class AboutDialog extends FloatingDialog{
|
||||
|
||||
table.table(i -> {
|
||||
i.background(Tex.buttonEdge3);
|
||||
i.addImage(Core.atlas.drawable("icon-" + link.name));
|
||||
i.addImage(link.icon);
|
||||
}).size(h - 5, h);
|
||||
|
||||
table.table(inset -> {
|
||||
|
||||
@@ -55,7 +55,7 @@ public class ColorPicker extends FloatingDialog{
|
||||
|
||||
buttons.clear();
|
||||
addCloseButton();
|
||||
buttons.addImageTextButton("$ok", Icon.checkSmall, () -> {
|
||||
buttons.addImageTextButton("$ok", Icon.ok, () -> {
|
||||
cons.get(current);
|
||||
hide();
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ public class ControlsDialog extends KeybindDialog{
|
||||
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeftSmall, this::hide).size(230f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(230f, 64f);
|
||||
|
||||
keyDown(key -> {
|
||||
if(key == KeyCode.ESCAPE || key == KeyCode.BACK)
|
||||
|
||||
@@ -35,12 +35,12 @@ public class CustomRulesDialog extends FloatingDialog{
|
||||
banDialog.addCloseButton();
|
||||
|
||||
banDialog.shown(this::rebuildBanned);
|
||||
banDialog.buttons.addImageTextButton("$addall", Icon.arrow16Small, () -> {
|
||||
banDialog.buttons.addImageTextButton("$addall", Icon.add, () -> {
|
||||
rules.bannedBlocks.addAll(content.blocks().select(Block::isBuildable));
|
||||
rebuildBanned();
|
||||
}).size(180, 64f);
|
||||
|
||||
banDialog.buttons.addImageTextButton("$clear", Icon.trash16Small, () -> {
|
||||
banDialog.buttons.addImageTextButton("$clear", Icon.trash, () -> {
|
||||
rules.bannedBlocks.clear();
|
||||
rebuildBanned();
|
||||
}).size(180, 64f);
|
||||
@@ -72,7 +72,7 @@ public class CustomRulesDialog extends FloatingDialog{
|
||||
b.addImage(block.icon(Cicon.medium)).size(Cicon.medium.size).padRight(3);
|
||||
b.add(block.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap();
|
||||
|
||||
b.addImageButton(Icon.cancelSmall, Styles.clearPartiali, () -> {
|
||||
b.addImageButton(Icon.cancel, Styles.clearPartiali, () -> {
|
||||
rules.bannedBlocks.remove(block);
|
||||
rebuildBanned();
|
||||
}).size(70f).pad(-4f).padLeft(0f);
|
||||
@@ -84,7 +84,7 @@ public class CustomRulesDialog extends FloatingDialog{
|
||||
}
|
||||
}).get().setScrollYForce(previousScroll);
|
||||
banDialog.cont.row();
|
||||
banDialog.cont.addImageTextButton("$add", Icon.addSmall, () -> {
|
||||
banDialog.cont.addImageTextButton("$add", Icon.add, () -> {
|
||||
FloatingDialog dialog = new FloatingDialog("$add");
|
||||
dialog.cont.pane(t -> {
|
||||
t.left().margin(14f);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.input.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.scene.event.*;
|
||||
@@ -15,6 +16,8 @@ import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
import static mindustry.Vars.ui;
|
||||
|
||||
public class DatabaseDialog extends FloatingDialog{
|
||||
|
||||
public DatabaseDialog(){
|
||||
@@ -55,7 +58,7 @@ public class DatabaseDialog extends FloatingDialog{
|
||||
for(int i = 0; i < array.size; i++){
|
||||
UnlockableContent unlock = (UnlockableContent)array.get(i);
|
||||
|
||||
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)) : new Image(Icon.lockedSmall, Pal.gray);
|
||||
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)) : new Image(Icon.lockOpen, Pal.gray);
|
||||
list.add(image).size(8*4).pad(3);
|
||||
ClickListener listener = new ClickListener();
|
||||
image.addListener(listener);
|
||||
@@ -65,7 +68,14 @@ public class DatabaseDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
if(unlocked(unlock)){
|
||||
image.clicked(() -> Vars.ui.content.show(unlock));
|
||||
image.clicked(() -> {
|
||||
if(Core.input.keyDown(KeyCode.SHIFT_LEFT) && Fonts.getUnicode(unlock.name) != 0){
|
||||
Core.app.setClipboardText((char)Fonts.getUnicode(unlock.name) + "");
|
||||
ui.showInfoFade("$copied");
|
||||
}else{
|
||||
Vars.ui.content.show(unlock);
|
||||
}
|
||||
});
|
||||
image.addListener(new Tooltip(t -> t.background(Tex.button).add(unlock.localizedName)));
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
setFilter(TextureFilter.Linear);
|
||||
}}){{
|
||||
float[] time = {0};
|
||||
setColor(Color.fromGray(0.3f));
|
||||
setColor(Color.gray(0.3f));
|
||||
setScale(1.5f);
|
||||
update(() -> {
|
||||
setOrigin(Align.center);
|
||||
@@ -140,7 +140,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
Stack sub = new Stack();
|
||||
|
||||
if(slot.getZone() != null){
|
||||
sub.add(new Table(f -> f.margin(4f).add(new Image()).color(Color.fromGray(0.1f)).grow()));
|
||||
sub.add(new Table(f -> f.margin(4f).add(new Image()).color(Color.gray(0.1f)).grow()));
|
||||
|
||||
sub.add(new Table(f -> f.margin(4f).add(new Image(slot.getZone().preview).setScaling(Scaling.fit)).update(img -> {
|
||||
TextureRegionDrawable draw = (TextureRegionDrawable)img.getDrawable();
|
||||
@@ -235,7 +235,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
button.labelWrap(zone.localizedName).style(Styles.outlineLabel).width(140).growX().get().setAlignment(Align.center);
|
||||
}else{
|
||||
Cons<Element> flasher = zone.canUnlock() && !hidden(zone) ? e -> e.update(() -> e.getColor().set(Color.white).lerp(Pal.accent, Mathf.absin(3f, 1f))) : e -> {};
|
||||
flasher.get(button.addImage(Icon.locked).get());
|
||||
flasher.get(button.addImage(Icon.lock).get());
|
||||
button.row();
|
||||
flasher.get(button.add("$locked").get());
|
||||
}
|
||||
@@ -254,7 +254,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
stack.setSize(Tmp.v1.x, Tmp.v1.y);
|
||||
stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview).setScaling(Scaling.stretch)).color(node.zone.unlocked() ? Color.darkGray : Color.fromGray(0.2f)).grow()));
|
||||
stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview).setScaling(Scaling.stretch)).color(node.zone.unlocked() ? Color.darkGray : Color.gray(0.2f)).grow()));
|
||||
stack.update(() -> stack.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center));
|
||||
|
||||
Button button = new Button(Styles.squaret);
|
||||
|
||||
@@ -92,15 +92,15 @@ public class FileChooser extends FloatingDialog{
|
||||
|
||||
Table icontable = new Table();
|
||||
|
||||
ImageButton up = new ImageButton(Icon.folderParent);
|
||||
ImageButton up = new ImageButton(Icon.upOpen);
|
||||
up.clicked(() -> {
|
||||
directory = directory.parent();
|
||||
updateFiles(true);
|
||||
});
|
||||
|
||||
|
||||
ImageButton back = new ImageButton(Icon.arrowLeft);
|
||||
ImageButton forward = new ImageButton(Icon.arrowRight);
|
||||
ImageButton back = new ImageButton(Icon.left);
|
||||
ImageButton forward = new ImageButton(Icon.right);
|
||||
|
||||
forward.clicked(() -> stack.forward());
|
||||
back.clicked(() -> stack.back());
|
||||
@@ -185,7 +185,7 @@ public class FileChooser extends FloatingDialog{
|
||||
files.top().left();
|
||||
Fi[] names = getFileNames();
|
||||
|
||||
Image upimage = new Image(Icon.folderParentSmall);
|
||||
Image upimage = new Image(Icon.upOpen);
|
||||
TextButton upbutton = new TextButton(".." + directory.toString(), Styles.clearTogglet);
|
||||
upbutton.clicked(() -> {
|
||||
directory = directory.parent();
|
||||
@@ -229,7 +229,7 @@ public class FileChooser extends FloatingDialog{
|
||||
button.setChecked(filename.equals(filefield.getText()));
|
||||
});
|
||||
|
||||
Image image = new Image(file.isDirectory() ? Icon.folderSmall : Icon.fileTextSmall);
|
||||
Image image = new Image(file.isDirectory() ? Icon.folder : Icon.fileText);
|
||||
|
||||
button.add(image).padRight(4f).padLeft(4);
|
||||
button.getCells().reverse();
|
||||
|
||||
@@ -56,7 +56,7 @@ public class FloatingDialog extends Dialog{
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.defaults().size(210f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(210f, 64f);
|
||||
|
||||
keyDown(key -> {
|
||||
if(key == KeyCode.ESCAPE || key == KeyCode.BACK){
|
||||
|
||||
@@ -122,7 +122,7 @@ public class JoinDialog extends FloatingDialog{
|
||||
|
||||
inner.add(button.getLabel()).growX();
|
||||
|
||||
inner.addImageButton(Icon.arrowUpSmall, Styles.emptyi, () -> {
|
||||
inner.addImageButton(Icon.upOpen, Styles.emptyi, () -> {
|
||||
int index = servers.indexOf(server);
|
||||
if(index > 0){
|
||||
servers.remove(index);
|
||||
@@ -139,25 +139,25 @@ public class JoinDialog extends FloatingDialog{
|
||||
}
|
||||
}
|
||||
|
||||
}).margin(3f).padTop(6f).top().right();
|
||||
}).margin(3f).pad(2).padTop(6f).top().right();
|
||||
|
||||
inner.addImageButton(Icon.loadingSmall, Styles.emptyi, () -> {
|
||||
inner.addImageButton(Icon.refresh, Styles.emptyi, () -> {
|
||||
refreshServer(server);
|
||||
}).margin(3f).padTop(6f).top().right();
|
||||
}).margin(3f).pad(2).padTop(6f).top().right();
|
||||
|
||||
inner.addImageButton(Icon.pencilSmall, Styles.emptyi, () -> {
|
||||
inner.addImageButton(Icon.pencil, Styles.emptyi, () -> {
|
||||
renaming = server;
|
||||
add.show();
|
||||
}).margin(3f).padTop(6f).top().right();
|
||||
}).margin(3f).pad(2).padTop(6f).top().right();
|
||||
|
||||
inner.addImageButton(Icon.trash16Small, Styles.emptyi, () -> {
|
||||
inner.addImageButton(Icon.trash, Styles.emptyi, () -> {
|
||||
ui.showConfirm("$confirm", "$server.delete", () -> {
|
||||
servers.removeValue(server, true);
|
||||
saveServers();
|
||||
setupRemote();
|
||||
refreshRemote();
|
||||
});
|
||||
}).margin(3f).pad(6).top().right();
|
||||
}).margin(3f).pad(2).pad(6).top().right();
|
||||
|
||||
button.row();
|
||||
|
||||
@@ -179,7 +179,7 @@ public class JoinDialog extends FloatingDialog{
|
||||
|
||||
net.pingHost(server.ip, server.port, host -> setupServer(server, host), e -> {
|
||||
server.content.clear();
|
||||
server.content.add("$host.invalid");
|
||||
server.content.add("$host.invalid").padBottom(4);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -212,6 +212,10 @@ public class JoinDialog extends FloatingDialog{
|
||||
content.table(t -> {
|
||||
t.add("[lightgray]" + host.name + " " + versionString).width(targetWidth() - 10f).left().get().setEllipsis(true);
|
||||
t.row();
|
||||
if(!host.description.isEmpty()){
|
||||
t.add("[gray]" + host.description).width(targetWidth() - 10f).left().wrap();
|
||||
t.row();
|
||||
}
|
||||
t.add("[lightgray]" + (Core.bundle.format("players" + (host.players == 1 && host.playerLimit <= 0 ? ".single" : ""), (host.players == 0 ? "[lightgray]" : "[accent]") + host.players + (host.playerLimit > 0 ? "[lightgray]/[accent]" + host.playerLimit : "")+ "[lightgray]"))).left();
|
||||
t.row();
|
||||
t.add("[lightgray]" + Core.bundle.format("save.map", host.mapname) + "[lightgray] / " + host.mode.toString()).width(targetWidth() - 10f).left().get().setEllipsis(true);
|
||||
@@ -303,7 +307,7 @@ public class JoinDialog extends FloatingDialog{
|
||||
local.background(Tex.button);
|
||||
local.add("$hosts.none").pad(10f);
|
||||
local.add().growX();
|
||||
local.addImageButton(Icon.loading, this::refreshLocal).pad(-12f).padLeft(0).size(70f);
|
||||
local.addImageButton(Icon.refresh, this::refreshLocal).pad(-12f).padLeft(0).size(70f);
|
||||
}else{
|
||||
local.background(null);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class LoadDialog extends FloatingDialog{
|
||||
title.table(t -> {
|
||||
t.right();
|
||||
|
||||
t.addImageButton(Icon.floppy, Styles.emptytogglei, () -> {
|
||||
t.addImageButton(Icon.save, Styles.emptytogglei, () -> {
|
||||
slot.setAutosave(!slot.isAutosave());
|
||||
}).checked(slot.isAutosave()).right();
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ public class LoadoutDialog extends FloatingDialog{
|
||||
}
|
||||
});
|
||||
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(210f, 64f);
|
||||
|
||||
buttons.addImageTextButton("$settings.reset", Icon.refreshSmall, () -> {
|
||||
buttons.addImageTextButton("$settings.reset", Icon.refresh, () -> {
|
||||
resetter.run();
|
||||
reseed();
|
||||
updater.run();
|
||||
@@ -83,7 +83,7 @@ public class LoadoutDialog extends FloatingDialog{
|
||||
updater.run();
|
||||
}).size(bsize);
|
||||
|
||||
t.addImageButton(Icon.pencilSmaller, Styles.cleari, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
|
||||
t.addImageButton(Icon.pencil, Styles.cleari, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
|
||||
if(Strings.canParsePostiveInt(str)){
|
||||
int amount = Strings.parseInt(str);
|
||||
if(amount >= 0 && amount <= capacity){
|
||||
|
||||
@@ -68,7 +68,7 @@ public class MapPlayDialog extends FloatingDialog{
|
||||
|
||||
cont.add(selmode);
|
||||
cont.row();
|
||||
cont.addImageTextButton("$customize", Icon.toolsSmall, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).width(230);
|
||||
cont.addImageTextButton("$customize", Icon.settings, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).width(230);
|
||||
cont.row();
|
||||
cont.add(new BorderImage(map.safeTexture(), 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit);
|
||||
//only maps with survival are valid for high scores
|
||||
|
||||
@@ -44,10 +44,10 @@ public class MapsDialog extends FloatingDialog{
|
||||
buttons.clearChildren();
|
||||
|
||||
if(Core.graphics.isPortrait()){
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f*2f, 64f).colspan(2);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(210f*2f, 64f).colspan(2);
|
||||
buttons.row();
|
||||
}else{
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(210f, 64f);
|
||||
}
|
||||
|
||||
buttons.addImageTextButton("$editor.newmap", Icon.add, () -> {
|
||||
@@ -67,7 +67,7 @@ public class MapsDialog extends FloatingDialog{
|
||||
});
|
||||
}).size(210f, 64f);
|
||||
|
||||
buttons.addImageTextButton("$editor.importmap", Icon.load, () -> {
|
||||
buttons.addImageTextButton("$editor.importmap", Icon.upload, () -> {
|
||||
platform.showFileChooser(true, mapExtension, file -> {
|
||||
ui.loadAnd(() -> {
|
||||
maps.tryCatchMapError(() -> {
|
||||
@@ -192,7 +192,7 @@ public class MapsDialog extends FloatingDialog{
|
||||
|
||||
table.row();
|
||||
|
||||
table.addImageTextButton("$editor.openin", Icon.loadMapSmall, () -> {
|
||||
table.addImageTextButton("$editor.openin", Icon.export, () -> {
|
||||
try{
|
||||
Vars.ui.editor.beginEditMap(map.file);
|
||||
dialog.hide();
|
||||
@@ -203,7 +203,7 @@ public class MapsDialog extends FloatingDialog{
|
||||
}
|
||||
}).fillX().height(54f).marginLeft(10);
|
||||
|
||||
table.addImageTextButton(map.workshop && steam ? "$view.workshop" : "$delete", map.workshop && steam ? Icon.linkSmall : Icon.trash16Small, () -> {
|
||||
table.addImageTextButton(map.workshop && steam ? "$view.workshop" : "$delete", map.workshop && steam ? Icon.link : Icon.trash, () -> {
|
||||
if(map.workshop && steam){
|
||||
platform.viewListing(map);
|
||||
}else{
|
||||
|
||||
@@ -20,15 +20,8 @@ public class ModsDialog extends FloatingDialog{
|
||||
super("$mods");
|
||||
addCloseButton();
|
||||
|
||||
buttons.addImageTextButton(mobile ? "$mods.report" : "$mods.openfolder", Icon.link,
|
||||
() -> {
|
||||
if(mobile){
|
||||
Core.net.openURI(reportIssueURL);
|
||||
}else{
|
||||
Core.net.openFolder(modDirectory.absolutePath());
|
||||
}
|
||||
})
|
||||
.size(250f, 64f);
|
||||
buttons.addImageTextButton("$mods.openfolder", Icon.link,
|
||||
() -> Core.app.openFolder(modDirectory.absolutePath())).size(250f, 64f);
|
||||
|
||||
buttons.row();
|
||||
|
||||
@@ -127,18 +120,18 @@ public class ModsDialog extends FloatingDialog{
|
||||
title.add("[accent]" + mod.meta.displayName() + "[lightgray] v" + mod.meta.version + (mod.enabled() ? "" : "\n" + Core.bundle.get("mod.disabled") + "")).width(200f).wrap();
|
||||
title.add().growX();
|
||||
|
||||
title.addImageTextButton(mod.enabled() ? "$mod.disable" : "$mod.enable", mod.enabled() ? Icon.arrowDownSmall : Icon.arrowUpSmall, Styles.cleart, () -> {
|
||||
title.addImageTextButton(mod.enabled() ? "$mod.disable" : "$mod.enable", mod.enabled() ? Icon.downOpen : Icon.upOpen, Styles.cleart, () -> {
|
||||
mods.setEnabled(mod, !mod.enabled());
|
||||
setup();
|
||||
}).height(50f).margin(8f).width(130f).disabled(!mod.isSupported());
|
||||
|
||||
if(steam && !mod.hasSteamID()){
|
||||
title.addImageButton(Icon.loadMapSmall, Styles.cleari, () -> {
|
||||
title.addImageButton(Icon.download, Styles.cleari, () -> {
|
||||
platform.publish(mod);
|
||||
}).size(50f);
|
||||
}
|
||||
|
||||
title.addImageButton(mod.hasSteamID() ? Icon.linkSmall : Icon.trash16Small, Styles.cleari, () -> {
|
||||
title.addImageButton(mod.hasSteamID() ? Icon.link : Icon.trash, Styles.cleari, () -> {
|
||||
if(!mod.hasSteamID()){
|
||||
ui.showConfirm("$confirm", "$mod.remove.confirm", () -> {
|
||||
mods.removeMod(mod);
|
||||
|
||||
@@ -35,29 +35,29 @@ public class PausedDialog extends FloatingDialog{
|
||||
});
|
||||
|
||||
if(!mobile){
|
||||
float dw = 210f;
|
||||
cont.defaults().width(dw).height(50).pad(5f);
|
||||
float dw = 220f;
|
||||
cont.defaults().width(dw).height(55).pad(5f);
|
||||
|
||||
cont.addButton("$back", this::hide).colspan(2).width(dw * 2 + 20f);
|
||||
cont.addImageTextButton("$back", Icon.left, this::hide).colspan(2).width(dw * 2 + 20f);
|
||||
|
||||
cont.row();
|
||||
if(world.isZone()){
|
||||
cont.addButton("$techtree", ui.tech::show);
|
||||
cont.addImageTextButton("$techtree", Icon.tree, ui.tech::show);
|
||||
}else{
|
||||
cont.addButton("$database", ui.database::show);
|
||||
cont.addImageTextButton("$database", Icon.book, ui.database::show);
|
||||
}
|
||||
cont.addButton("$settings", ui.settings::show);
|
||||
cont.addImageTextButton("$settings", Icon.settings, ui.settings::show);
|
||||
|
||||
if(!state.rules.tutorial){
|
||||
if(!world.isZone() && !state.isEditor()){
|
||||
cont.row();
|
||||
cont.addButton("$savegame", save::show);
|
||||
cont.addButton("$loadgame", load::show).disabled(b -> net.active());
|
||||
cont.addImageTextButton("$savegame", Icon.save, save::show);
|
||||
cont.addImageTextButton("$loadgame", Icon.upload, load::show).disabled(b -> net.active());
|
||||
}
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.addButton("$hostserver", () -> {
|
||||
cont.addImageTextButton("$hostserver", Icon.host, () -> {
|
||||
if(net.server() && steam){
|
||||
platform.inviteFriends();
|
||||
}else{
|
||||
@@ -72,26 +72,29 @@ public class PausedDialog extends FloatingDialog{
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.addButton("$quit", this::showQuitConfirm).colspan(2).width(dw + 10f).update(s -> s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "$save.quit" : "$quit"));
|
||||
cont.addImageTextButton("$quit", Icon.exit, this::showQuitConfirm).colspan(2).width(dw + 20f).update(s -> s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "$save.quit" : "$quit"));
|
||||
|
||||
}else{
|
||||
cont.defaults().size(130f).pad(5);
|
||||
cont.addRowImageTextButton("$back", Icon.play2, this::hide);
|
||||
cont.addRowImageTextButton("$settings", Icon.tools, ui.settings::show);
|
||||
cont.addRowImageTextButton("$back", Icon.play, this::hide);
|
||||
cont.addRowImageTextButton("$settings", Icon.settings, ui.settings::show);
|
||||
|
||||
if(!world.isZone() && !state.isEditor()){
|
||||
cont.addRowImageTextButton("$save", Icon.save, save::show);
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.addRowImageTextButton("$load", Icon.load, load::show).disabled(b -> net.active());
|
||||
cont.addRowImageTextButton("$load", Icon.download, load::show).disabled(b -> net.active());
|
||||
}else{
|
||||
cont.row();
|
||||
}
|
||||
|
||||
cont.addRowImageTextButton("$hostserver.mobile", Icon.host, ui.host::show).disabled(b -> net.active());
|
||||
|
||||
cont.addRowImageTextButton("$quit", Icon.quit, this::showQuitConfirm).update(s -> s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "$save.quit" : "$quit"));
|
||||
cont.addRowImageTextButton("$quit", Icon.exit, this::showQuitConfirm).update(s -> {
|
||||
s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "$save.quit" : "$quit");
|
||||
s.getLabelCell().growX().wrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
|
||||
shouldPause = true;
|
||||
addCloseButton();
|
||||
buttons.addImageTextButton("$schematic.import", Icon.loadMapSmall, this::showImport);
|
||||
buttons.addImageTextButton("$schematic.import", Icon.download, this::showImport);
|
||||
shown(this::setup);
|
||||
onResize(this::setup);
|
||||
}
|
||||
@@ -79,15 +79,15 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
|
||||
ImageButtonStyle style = Styles.clearPartiali;
|
||||
|
||||
buttons.addImageButton(Icon.infoSmall, style, () -> {
|
||||
buttons.addImageButton(Icon.info, style, () -> {
|
||||
showInfo(s);
|
||||
});
|
||||
|
||||
buttons.addImageButton(Icon.loadMapSmall, style, () -> {
|
||||
buttons.addImageButton(Icon.download, style, () -> {
|
||||
showExport(s);
|
||||
});
|
||||
|
||||
buttons.addImageButton(Icon.pencilSmall, style, () -> {
|
||||
buttons.addImageButton(Icon.pencil, style, () -> {
|
||||
ui.showTextInput("$schematic.rename", "$name", s.name(), res -> {
|
||||
s.tags.put("name", res);
|
||||
s.save();
|
||||
@@ -96,9 +96,9 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
});
|
||||
|
||||
if(s.hasSteamID()){
|
||||
buttons.addImageButton(Icon.linkSmall, style, () -> platform.viewListing(s));
|
||||
buttons.addImageButton(Icon.link, style, () -> platform.viewListing(s));
|
||||
}else{
|
||||
buttons.addImageButton(Icon.trash16Small, style, () -> {
|
||||
buttons.addImageButton(Icon.trash, style, () -> {
|
||||
if(s.mod != null){
|
||||
ui.showInfo(Core.bundle.format("mod.item.remove", s.mod.meta.displayName()));
|
||||
}else{
|
||||
@@ -154,7 +154,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
TextButtonStyle style = Styles.cleart;
|
||||
t.defaults().size(280f, 60f).left();
|
||||
t.row();
|
||||
t.addImageTextButton("$schematic.copy.import", Icon.copySmall, style, () -> {
|
||||
t.addImageTextButton("$schematic.copy.import", Icon.copy, style, () -> {
|
||||
dialog.hide();
|
||||
try{
|
||||
Schematic s = Schematics.readBase64(Core.app.getClipboardText());
|
||||
@@ -168,7 +168,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
}
|
||||
}).marginLeft(12f).disabled(b -> Core.app.getClipboardText() == null || !Core.app.getClipboardText().startsWith(schematicBaseStart));
|
||||
t.row();
|
||||
t.addImageTextButton("$schematic.importfile", Icon.saveMapSmall, style, () -> platform.showFileChooser(true, schematicExtension, file -> {
|
||||
t.addImageTextButton("$schematic.importfile", Icon.download, style, () -> platform.showFileChooser(true, schematicExtension, file -> {
|
||||
dialog.hide();
|
||||
|
||||
try{
|
||||
@@ -183,7 +183,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
})).marginLeft(12f);
|
||||
t.row();
|
||||
if(steam){
|
||||
t.addImageTextButton("$schematic.browseworkshop", Icon.wikiSmall, style, () -> {
|
||||
t.addImageTextButton("$schematic.browseworkshop", Icon.book, style, () -> {
|
||||
dialog.hide();
|
||||
platform.openWorkshop();
|
||||
}).marginLeft(12f);
|
||||
@@ -203,18 +203,18 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
TextButtonStyle style = Styles.cleart;
|
||||
t.defaults().size(280f, 60f).left();
|
||||
if(steam && !s.hasSteamID()){
|
||||
t.addImageTextButton("$schematic.shareworkshop", Icon.wikiSmall, style,
|
||||
t.addImageTextButton("$schematic.shareworkshop", Icon.book, style,
|
||||
() -> platform.publish(s)).marginLeft(12f);
|
||||
t.row();
|
||||
dialog.hide();
|
||||
}
|
||||
t.addImageTextButton("$schematic.copy", Icon.copySmall, style, () -> {
|
||||
t.addImageTextButton("$schematic.copy", Icon.copy, style, () -> {
|
||||
dialog.hide();
|
||||
ui.showInfoFade("$copied");
|
||||
Core.app.setClipboardText(schematics.writeBase64(s));
|
||||
}).marginLeft(12f);
|
||||
t.row();
|
||||
t.addImageTextButton("$schematic.exportfile", Icon.saveMapSmall, style, () -> platform.showFileChooser(false, schematicExtension, file -> {
|
||||
t.addImageTextButton("$schematic.exportfile", Icon.export, style, () -> platform.showFileChooser(false, schematicExtension, file -> {
|
||||
dialog.hide();
|
||||
try{
|
||||
Schematics.write(s, file);
|
||||
@@ -272,7 +272,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
if(wasSet){
|
||||
super.draw();
|
||||
}else{
|
||||
Draw.rect(Icon.loading.getRegion(), x + width/2f, y + height/2f, width/4f, height/4f);
|
||||
Draw.rect(Icon.refresh.getRegion(), x + width/2f, y + height/2f, width/4f, height/4f);
|
||||
}
|
||||
|
||||
Draw.color(checked ? Pal.accent : borderColor);
|
||||
|
||||
@@ -81,10 +81,10 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
dataDialog.addCloseButton();
|
||||
|
||||
dataDialog.cont.table(Tex.button, t -> {
|
||||
t.defaults().size(240f, 60f).left();
|
||||
t.defaults().size(270f, 60f).left();
|
||||
TextButtonStyle style = Styles.cleart;
|
||||
|
||||
t.addButton("$settings.cleardata", style, () -> ui.showConfirm("$confirm", "$settings.clearall.confirm", () -> {
|
||||
t.addImageTextButton("$settings.cleardata", Icon.trash, style, () -> ui.showConfirm("$confirm", "$settings.clearall.confirm", () -> {
|
||||
ObjectMap<String, Object> map = new ObjectMap<>();
|
||||
for(String value : Core.settings.keys()){
|
||||
if(value.contains("usid") || value.contains("uuid")){
|
||||
@@ -104,7 +104,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
|
||||
t.row();
|
||||
|
||||
t.addButton("$data.export", style, () -> {
|
||||
t.addImageTextButton("$data.export", Icon.download, style, () -> {
|
||||
if(ios){
|
||||
Fi file = Core.files.local("mindustry-data-export.zip");
|
||||
try{
|
||||
@@ -128,7 +128,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
|
||||
t.row();
|
||||
|
||||
t.addButton("$data.import", style, () -> ui.showConfirm("$confirm", "$data.import.confirm", () -> platform.showFileChooser(true, "zip", file -> {
|
||||
t.addImageTextButton("$data.import", Icon.download, style, () -> ui.showConfirm("$confirm", "$data.import.confirm", () -> platform.showFileChooser(true, "zip", file -> {
|
||||
try{
|
||||
data.importData(file);
|
||||
Core.app.exit();
|
||||
@@ -143,6 +143,11 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
}
|
||||
}
|
||||
})));
|
||||
|
||||
if(!ios){
|
||||
t.row();
|
||||
t.addImageTextButton("$data.openfolder", Icon.folder, style, () -> Core.app.openFolder(Core.settings.getDataDirectory().absolutePath()));
|
||||
}
|
||||
});
|
||||
|
||||
ScrollPane pane = new ScrollPane(prefs);
|
||||
@@ -290,7 +295,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
if(Core.settings.getBool("borderlesswindow")){
|
||||
Core.app.post(() -> Core.graphics.setUndecorated(true));
|
||||
}
|
||||
}else{
|
||||
}else if(!ios){
|
||||
graphics.checkPref("landscape", false, b -> {
|
||||
if(b){
|
||||
platform.beginForceLandscape();
|
||||
@@ -357,7 +362,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeftSmaller, () -> {
|
||||
buttons.addImageTextButton("$back", Icon.leftOpen, () -> {
|
||||
if(prefs.getChildren().first() != menu){
|
||||
back();
|
||||
}else{
|
||||
|
||||
@@ -60,7 +60,7 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
|
||||
addCloseButton();
|
||||
|
||||
buttons.addImageTextButton("$database", Icon.database, () -> {
|
||||
buttons.addImageTextButton("$database", Icon.book, () -> {
|
||||
hide();
|
||||
ui.database.show();
|
||||
}).size(210f, 64f);
|
||||
@@ -324,7 +324,7 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
infoTable.table(b -> {
|
||||
b.margin(0).left().defaults().left();
|
||||
|
||||
b.addImageButton(Icon.infoSmall, Styles.cleari, () -> ui.content.show(node.block)).growY().width(50f);
|
||||
b.addImageButton(Icon.info, Styles.cleari, () -> ui.content.show(node.block)).growY().width(50f);
|
||||
b.add().grow();
|
||||
b.table(desc -> {
|
||||
desc.left().defaults().left();
|
||||
@@ -351,7 +351,7 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
|
||||
if(mobile && locked(node)){
|
||||
b.row();
|
||||
b.addImageTextButton("$research", Icon.checkSmall, Styles.nodet, () -> unlock(node))
|
||||
b.addImageTextButton("$research", Icon.ok, Styles.nodet, () -> unlock(node))
|
||||
.disabled(i -> !data.hasItems(node.requirements)).growX().height(44f).colspan(3);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ZoneInfoDialog extends FloatingDialog{
|
||||
if(i++ % 2 == 0){
|
||||
iteminfo.row();
|
||||
}
|
||||
iteminfo.addImage(stack.item.icon(mindustry.ui.Cicon.small)).size(8 * 3).padRight(1);
|
||||
iteminfo.addImage(stack.item.icon(Cicon.small)).size(8 * 3).padRight(1);
|
||||
iteminfo.add(stack.amount + "").color(Color.lightGray).padRight(5);
|
||||
}
|
||||
};
|
||||
@@ -54,7 +54,7 @@ public class ZoneInfoDialog extends FloatingDialog{
|
||||
|
||||
cont.pane(cont -> {
|
||||
if(zone.locked()){
|
||||
cont.addImage(Icon.locked);
|
||||
cont.addImage(Icon.lock);
|
||||
cont.row();
|
||||
cont.add("$locked").padBottom(6);
|
||||
cont.row();
|
||||
@@ -71,7 +71,7 @@ public class ZoneInfoDialog extends FloatingDialog{
|
||||
for(Objective o : zones){
|
||||
r.addImage(Icon.terrain).padRight(4);
|
||||
r.add(o.display()).color(Color.lightGray);
|
||||
r.addImage(o.complete() ? Icon.checkSmall : Icon.cancelSmall, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||
r.addImage(o.complete() ? Icon.ok : Icon.cancel, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||
r.row();
|
||||
}
|
||||
});
|
||||
@@ -85,9 +85,9 @@ public class ZoneInfoDialog extends FloatingDialog{
|
||||
r.add("$research.list").colspan(2).left();
|
||||
r.row();
|
||||
for(Unlock blocko : blocks){
|
||||
r.addImage(blocko.block.icon(mindustry.ui.Cicon.small)).size(8 * 3).padRight(5);
|
||||
r.addImage(blocko.block.icon(Cicon.small)).size(8 * 3).padRight(5);
|
||||
r.add(blocko.block.localizedName).color(Color.lightGray).left();
|
||||
r.addImage(blocko.block.unlocked() ? Icon.checkSmall : Icon.cancelSmall, blocko.block.unlocked() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||
r.addImage(blocko.block.unlocked() ? Icon.ok : Icon.cancel, blocko.block.unlocked() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||
r.row();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package mindustry.ui.fragments;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.struct.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.input.*;
|
||||
@@ -13,14 +11,18 @@ import arc.scene.actions.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.net.Administration.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
@@ -37,7 +39,14 @@ public class BlockInventoryFragment extends Fragment{
|
||||
@Remote(called = Loc.server, targets = Loc.both, forward = true)
|
||||
public static void requestItem(Player player, Tile tile, Item item, int amount){
|
||||
if(player == null || tile == null || !tile.interactable(player.getTeam())) return;
|
||||
if(!Units.canInteract(player, tile)) return;
|
||||
amount = Mathf.clamp(amount, 0, player.getItemCapacity());
|
||||
int fa = amount;
|
||||
|
||||
if(net.server() && (!Units.canInteract(player, tile) ||
|
||||
!netServer.admins.allowAction(player, ActionType.withdrawItem, tile, action -> {
|
||||
action.item = item;
|
||||
action.itemAmount = fa;
|
||||
}))) throw new ValidateException(player, "Player cannot request items.");
|
||||
|
||||
int removed = tile.block().removeStack(tile, item, amount);
|
||||
|
||||
|
||||
@@ -62,12 +62,12 @@ public class HudFragment extends Fragment{
|
||||
|
||||
ImageButtonStyle style = Styles.clearTransi;
|
||||
|
||||
select.addImageButton(Icon.menuLargeSmall, style, ui.paused::show);
|
||||
flip = select.addImageButton(Icon.arrowUpSmall, style, this::toggleMenus).get();
|
||||
select.addImageButton(Icon.menu, style, ui.paused::show);
|
||||
flip = select.addImageButton(Icon.upOpen, style, this::toggleMenus).get();
|
||||
|
||||
select.addImageButton(Icon.pasteSmall, style, ui.schematics::show);
|
||||
select.addImageButton(Icon.paste, style, ui.schematics::show);
|
||||
|
||||
select.addImageButton(Icon.pauseSmall, style, () -> {
|
||||
select.addImageButton(Icon.pause, style, () -> {
|
||||
if(net.active()){
|
||||
ui.listfrag.toggle();
|
||||
}else{
|
||||
@@ -75,14 +75,14 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
}).name("pause").update(i -> {
|
||||
if(net.active()){
|
||||
i.getStyle().imageUp = Icon.playersSmall;
|
||||
i.getStyle().imageUp = Icon.user;
|
||||
}else{
|
||||
i.setDisabled(false);
|
||||
i.getStyle().imageUp = state.is(State.paused) ? Icon.playSmall : Icon.pauseSmall;
|
||||
i.getStyle().imageUp = state.is(State.paused) ? Icon.play : Icon.pause;
|
||||
}
|
||||
});
|
||||
|
||||
select.addImageButton(Icon.chatSmall, style,() -> {
|
||||
select.addImageButton(Icon.chat, style,() -> {
|
||||
if(net.active() && mobile){
|
||||
if(ui.chatfrag.shown()){
|
||||
ui.chatfrag.hide();
|
||||
@@ -96,9 +96,9 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
}).update(i -> {
|
||||
if(net.active() && mobile){
|
||||
i.getStyle().imageUp = Icon.chatSmall;
|
||||
i.getStyle().imageUp = Icon.chat;
|
||||
}else{
|
||||
i.getStyle().imageUp = Icon.databaseSmall;
|
||||
i.getStyle().imageUp = Icon.book;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -203,7 +203,7 @@ public class HudFragment extends Fragment{
|
||||
float[] position = {0, 0};
|
||||
|
||||
t.row();
|
||||
t.addImageTextButton("$editor.removeunit", Icon.quit, Styles.togglet, () -> {}).fillX().update(b -> {
|
||||
t.addImageTextButton("$editor.removeunit", Icon.cancel, Styles.togglet, () -> {}).fillX().update(b -> {
|
||||
boolean[] found = {false};
|
||||
if(b.isChecked()){
|
||||
Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
|
||||
@@ -319,7 +319,7 @@ public class HudFragment extends Fragment{
|
||||
setDisabled(() -> !control.tutorial.canNext());
|
||||
}},
|
||||
new Table(f -> {
|
||||
f.left().addImageButton(Icon.arrowLeftSmall, Styles.emptyi, () -> {
|
||||
f.left().addImageButton(Icon.left, Styles.emptyi, () -> {
|
||||
control.tutorial.prevSentence();
|
||||
}).width(44f).growY().visible(() -> control.tutorial.canPrev());
|
||||
}));
|
||||
@@ -393,7 +393,7 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
});
|
||||
table.margin(12);
|
||||
table.addImage(Icon.check).pad(3);
|
||||
table.addImage(Icon.ok).pad(3);
|
||||
table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center);
|
||||
table.pack();
|
||||
|
||||
@@ -562,7 +562,7 @@ public class HudFragment extends Fragment{
|
||||
|
||||
private void toggleMenus(){
|
||||
if(flip != null){
|
||||
flip.getStyle().imageUp = shown ? Icon.arrowDownSmall : Icon.arrowUpSmall;
|
||||
flip.getStyle().imageUp = shown ? Icon.downOpen : Icon.upOpen;
|
||||
}
|
||||
|
||||
shown = !shown;
|
||||
@@ -650,7 +650,7 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
|
||||
private void addPlayButton(Table table){
|
||||
table.right().addImageButton(Icon.playSmaller, Styles.righti, 30f, () -> {
|
||||
table.right().addImageButton(Icon.play, Styles.righti, 30f, () -> {
|
||||
if(net.client() && player.isAdmin){
|
||||
Call.onAdminRequest(player, AdminAction.wave);
|
||||
}else if(inLaunchWave()){
|
||||
|
||||
@@ -60,7 +60,7 @@ public class MenuFragment extends Fragment{
|
||||
parent.fill(c -> c.bottom().left().addButton("", Styles.infot, ui.about::show).size(84, 45));
|
||||
parent.fill(c -> c.bottom().right().addButton("", Styles.discordt, ui.discord::show).size(84, 45));
|
||||
}else if(becontrol.active()){
|
||||
parent.fill(c -> c.bottom().right().addImageTextButton("$be.check", Icon.refreshSmall, () -> {
|
||||
parent.fill(c -> c.bottom().right().addImageTextButton("$be.check", Icon.refresh, () -> {
|
||||
ui.loadfrag.show();
|
||||
becontrol.checkUpdate(result -> {
|
||||
ui.loadfrag.hide();
|
||||
@@ -100,13 +100,13 @@ public class MenuFragment extends Fragment{
|
||||
container.defaults().size(size).pad(5).padTop(4f);
|
||||
|
||||
MobileButton
|
||||
play = new MobileButton(Icon.play2, "$campaign", () -> checkPlay(ui.deploy::show)),
|
||||
custom = new MobileButton(Icon.playCustom, "$customgame", () -> checkPlay(ui.custom::show)),
|
||||
maps = new MobileButton(Icon.load, "$loadgame", () -> checkPlay(ui.load::show)),
|
||||
play = new MobileButton(Icon.play, "$campaign", () -> checkPlay(ui.deploy::show)),
|
||||
custom = new MobileButton(Icon.rightOpenOut, "$customgame", () -> checkPlay(ui.custom::show)),
|
||||
maps = new MobileButton(Icon.download, "$loadgame", () -> checkPlay(ui.load::show)),
|
||||
join = new MobileButton(Icon.add, "$joingame", () -> checkPlay(ui.join::show)),
|
||||
editor = new MobileButton(Icon.editor, "$editor", () -> checkPlay(ui.maps::show)),
|
||||
tools = new MobileButton(Icon.tools, "$settings", ui.settings::show),
|
||||
mods = new MobileButton(Icon.wiki, "$mods", ui.mods::show),
|
||||
editor = new MobileButton(Icon.terrain, "$editor", () -> checkPlay(ui.maps::show)),
|
||||
tools = new MobileButton(Icon.settings, "$settings", ui.settings::show),
|
||||
mods = new MobileButton(Icon.book, "$mods", ui.mods::show),
|
||||
donate = new MobileButton(Icon.link, "$website", () -> Core.net.openURI("https://anuke.itch.io/mindustry")),
|
||||
exit = new MobileButton(Icon.exit, "$quit", () -> Core.app.exit());
|
||||
|
||||
@@ -164,20 +164,20 @@ public class MenuFragment extends Fragment{
|
||||
t.defaults().width(width).height(70f);
|
||||
|
||||
buttons(t,
|
||||
new Buttoni("$play", Icon.play2Small,
|
||||
new Buttoni("$campaign", Icon.play2Small, () -> checkPlay(ui.deploy::show)),
|
||||
new Buttoni("$joingame", Icon.addSmall, () -> checkPlay(ui.join::show)),
|
||||
new Buttoni("$customgame", Icon.editorSmall, () -> checkPlay(ui.custom::show)),
|
||||
new Buttoni("$loadgame", Icon.loadSmall, () -> checkPlay(ui.load::show)),
|
||||
new Buttoni("$tutorial", Icon.infoSmall, () -> checkPlay(control::playTutorial))
|
||||
new Buttoni("$play", Icon.play,
|
||||
new Buttoni("$campaign", Icon.play, () -> checkPlay(ui.deploy::show)),
|
||||
new Buttoni("$joingame", Icon.add, () -> checkPlay(ui.join::show)),
|
||||
new Buttoni("$customgame", Icon.terrain, () -> checkPlay(ui.custom::show)),
|
||||
new Buttoni("$loadgame", Icon.download, () -> checkPlay(ui.load::show)),
|
||||
new Buttoni("$tutorial", Icon.info, () -> checkPlay(control::playTutorial))
|
||||
),
|
||||
new Buttoni("$editor", Icon.editorSmall, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.saveSmall, platform::openWorkshop) : null,
|
||||
new Buttoni(Core.bundle.get("mods") + "\n" + Core.bundle.get("mods.alpha"), Icon.wikiSmall, ui.mods::show),
|
||||
new Buttoni("$editor", Icon.terrain, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.save, platform::openWorkshop) : null,
|
||||
new Buttoni(Core.bundle.get("mods"), Icon.bookOpen, ui.mods::show),
|
||||
//not enough space for this button
|
||||
//new Buttoni("$schematics", Icon.pasteSmall, ui.schematics::show),
|
||||
new Buttoni("$settings", Icon.toolsSmall, ui.settings::show),
|
||||
new Buttoni("$about.button", Icon.infoSmall, ui.about::show),
|
||||
new Buttoni("$quit", Icon.exitSmall, Core.app::exit)
|
||||
//new Buttoni("$schematics", Icon.paste, ui.schematics::show),
|
||||
new Buttoni("$settings", Icon.settings, ui.settings::show),
|
||||
new Buttoni("$about.button", Icon.info, ui.about::show),
|
||||
new Buttoni("$quit", Icon.exit, Core.app::exit)
|
||||
);
|
||||
|
||||
}).width(width).growY();
|
||||
|
||||
@@ -100,7 +100,7 @@ public class MinimapFragment extends Fragment{
|
||||
t.row();
|
||||
t.add().growY();
|
||||
t.row();
|
||||
t.addImageTextButton("$back", Icon.backSmall, () -> shown = false).size(220f, 60f).pad(10f);
|
||||
t.addImageTextButton("$back", Icon.leftOpen, () -> shown = false).size(220f, 60f).pad(10f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package mindustry.ui.fragments;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.input.*;
|
||||
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.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
@@ -19,7 +20,6 @@ import mindustry.graphics.*;
|
||||
import mindustry.input.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
@@ -202,14 +202,18 @@ public class PlacementFragment extends Fragment{
|
||||
blockTable.row();
|
||||
}
|
||||
|
||||
ImageButton button = blockTable.addImageButton(Icon.lockedSmall, Styles.selecti, () -> {
|
||||
ImageButton button = blockTable.addImageButton(new TextureRegionDrawable(block.icon(Cicon.medium)), Styles.selecti, () -> {
|
||||
if(unlocked(block)){
|
||||
control.input.block = control.input.block == block ? null : block;
|
||||
selectedBlocks.put(currentCategory, control.input.block);
|
||||
if(Core.input.keyDown(KeyCode.SHIFT_LEFT) && Fonts.getUnicode(block.name) != 0){
|
||||
Core.app.setClipboardText((char)Fonts.getUnicode(block.name) + "");
|
||||
ui.showInfoFade("$copied");
|
||||
}else{
|
||||
control.input.block = control.input.block == block ? null : block;
|
||||
selectedBlocks.put(currentCategory, control.input.block);
|
||||
}
|
||||
}
|
||||
}).size(46f).group(group).name("block-" + block.name).get();
|
||||
|
||||
button.getStyle().imageUp = new TextureRegionDrawable(block.icon(Cicon.medium));
|
||||
button.resizeImage(Cicon.medium.size);
|
||||
|
||||
button.update(() -> { //color unplacable things gray
|
||||
TileEntity core = player.getClosestCore();
|
||||
@@ -311,7 +315,7 @@ public class PlacementFragment extends Fragment{
|
||||
if(state.rules.bannedBlocks.contains(lastDisplay)){
|
||||
topTable.row();
|
||||
topTable.table(b -> {
|
||||
b.addImage(Icon.cancelSmall).padRight(2).color(Color.scarlet);
|
||||
b.addImage(Icon.cancel).padRight(2).color(Color.scarlet);
|
||||
b.add("$banned");
|
||||
b.left();
|
||||
}).padTop(2).left();
|
||||
@@ -378,7 +382,7 @@ public class PlacementFragment extends Fragment{
|
||||
continue;
|
||||
}
|
||||
|
||||
categories.addImageButton(Core.atlas.drawable("icon-" + cat.name() + "-smaller"), Styles.clearToggleTransi, () -> {
|
||||
categories.addImageButton(ui.getIcon(cat.name()), Styles.clearToggleTransi, () -> {
|
||||
currentCategory = cat;
|
||||
if(control.input.block != null){
|
||||
control.input.block = getSelectedBlock(currentCategory);
|
||||
|
||||
@@ -104,14 +104,14 @@ public class PlayerListFragment extends Fragment{
|
||||
button.table(t -> {
|
||||
t.defaults().size(bs);
|
||||
|
||||
t.addImageButton(Icon.banSmall, Styles.clearPartiali,
|
||||
t.addImageButton(Icon.hammer, Styles.clearPartiali,
|
||||
() -> ui.showConfirm("$confirm", "$confirmban", () -> Call.onAdminRequest(user, AdminAction.ban)));
|
||||
t.addImageButton(Icon.cancelSmall, Styles.clearPartiali,
|
||||
t.addImageButton(Icon.cancel, Styles.clearPartiali,
|
||||
() -> ui.showConfirm("$confirm", "$confirmkick", () -> Call.onAdminRequest(user, AdminAction.kick)));
|
||||
|
||||
t.row();
|
||||
|
||||
t.addImageButton(Icon.adminSmall, Styles.clearTogglePartiali, () -> {
|
||||
t.addImageButton(Icon.admin, Styles.clearTogglePartiali, () -> {
|
||||
if(net.client()) return;
|
||||
|
||||
String id = user.uuid;
|
||||
@@ -127,13 +127,13 @@ public class PlayerListFragment extends Fragment{
|
||||
.touchable(() -> net.client() ? Touchable.disabled : Touchable.enabled)
|
||||
.checked(user.isAdmin);
|
||||
|
||||
t.addImageButton(Icon.zoomSmall, Styles.clearPartiali, () -> Call.onAdminRequest(user, AdminAction.trace));
|
||||
t.addImageButton(Icon.zoom, Styles.clearPartiali, () -> Call.onAdminRequest(user, AdminAction.trace));
|
||||
|
||||
}).padRight(12).size(bs + 10f, bs);
|
||||
}else if((!user.isLocal && !user.isAdmin) && net.client() && playerGroup.size() >= 3 && player.getTeam() != user.getTeam()){ //votekick
|
||||
}else if(!user.isLocal && !user.isAdmin && net.client() && playerGroup.size() >= 3 && player.getTeam() == user.getTeam()){ //votekick
|
||||
button.add().growY();
|
||||
|
||||
button.addImageButton(Icon.banSmall, Styles.clearPartiali,
|
||||
button.addImageButton(Icon.hammer, Styles.clearPartiali,
|
||||
() -> ui.showConfirm("$confirm", "$confirmvotekick", () -> Call.sendChatMessage("/votekick " + user.name))).size(h);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ScriptConsoleFragment extends Table{
|
||||
clearChatInput();
|
||||
}
|
||||
|
||||
return shown && Vars.net.active();
|
||||
return shown && !Vars.net.active();
|
||||
});
|
||||
|
||||
update(() -> {
|
||||
|
||||
Reference in New Issue
Block a user