From aedd047c6fdb879b817bb133937f636fdd3479e9 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 10 Apr 2020 11:49:22 -0400 Subject: [PATCH] Slightly improved mod dialog --- core/assets/bundles/bundle.properties | 6 +- core/src/mindustry/mod/Mods.java | 28 +- core/src/mindustry/ui/Styles.java | 4 +- .../mindustry/ui/dialogs/MapPlayDialog.java | 3 +- core/src/mindustry/ui/dialogs/MapsDialog.java | 2 +- core/src/mindustry/ui/dialogs/ModsDialog.java | 240 ++++++++++++------ .../world/blocks/storage/LaunchPad.java | 18 +- gradle.properties | 2 +- 8 files changed, 199 insertions(+), 104 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 5e1be3f6b2..7cc417fae4 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -105,7 +105,8 @@ mods = Mods mods.none = [LIGHT_GRAY]No mods found! mods.guide = Modding Guide mods.report = Report Bug -mods.openfolder = Open Mod Folder +mods.openfolder = Open Folder +mods.reload = Reload mod.display = [gray]Mod:[orange] {0} mod.enabled = [lightgray]Enabled mod.disabled = [scarlet]Disabled @@ -121,7 +122,8 @@ mod.enable = Enable mod.requiresrestart = The game will now close to apply the mod changes. mod.reloadrequired = [scarlet]Reload Required mod.import = Import Mod -mod.import.github = Import GitHub Mod +mod.import.file = Import File +mod.import.github = Import From GitHub mod.item.remove = This item is part of the[accent] '{0}'[] mod. To remove it, uninstall that mod. mod.remove.confirm = This mod will be deleted. mod.author = [LIGHT_GRAY]Author:[] {0} diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index 32a635b1b2..1b9d970609 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -114,6 +114,19 @@ public class Mods implements Loadable{ Log.debug("Time to pack textures: {0}", Time.elapsed()); } + private void loadIcons(){ + for(LoadedMod mod : mods){ + //try to load icon for each mod that can have one + if(mod.root.child("icon.png").exists()){ + try{ + mod.iconTexture = new Texture(mod.root.child("icon.png")); + }catch(Throwable t){ + Log.err("Failed to load icon for mod '" + mod.name + "'.", t); + } + } + } + } + private void packSprites(Array sprites, LoadedMod mod, boolean prefix){ for(Fi file : sprites){ try(InputStream stream = file.read()){ @@ -135,16 +148,7 @@ public class Mods implements Loadable{ @Override public void loadSync(){ - for(LoadedMod mod : mods){ - //try to load icon for each mod that can have one - if(mod.root.child("icon.png").exists()){ - try{ - mod.iconTexture = new Texture(mod.root.child("icon.png")); - }catch(Throwable t){ - Log.err("Failed to load icon for mod '" + mod.name + "'.", t); - } - } - } + loadIcons(); if(packer == null) return; Time.mark(); @@ -219,6 +223,7 @@ public class Mods implements Loadable{ return; } mods.remove(mod); + mod.dispose(); requiresReload = true; } @@ -452,6 +457,8 @@ public class Mods implements Loadable{ Core.atlas.getTextures().each(t -> t.setFilter(Core.settings.getBool("linear") ? TextureFilter.Linear : TextureFilter.Nearest)); requiresReload = false; + loadIcons(); + Events.fire(new ContentReloadEvent()); } @@ -728,6 +735,7 @@ public class Mods implements Loadable{ public void dispose(){ if(iconTexture != null){ iconTexture.dispose(); + iconTexture = null; } } diff --git a/core/src/mindustry/ui/Styles.java b/core/src/mindustry/ui/Styles.java index e28882397f..9e0fc1dcb5 100644 --- a/core/src/mindustry/ui/Styles.java +++ b/core/src/mindustry/ui/Styles.java @@ -103,9 +103,9 @@ public class Styles{ up = infoBanner; }}; clearPartialt = new TextButtonStyle(){{ - down = whiteui; + down = flatOver; up = pane; - over = flatDown; + over = flatDownBase; font = Fonts.def; fontColor = Color.white; disabledFontColor = Color.gray; diff --git a/core/src/mindustry/ui/dialogs/MapPlayDialog.java b/core/src/mindustry/ui/dialogs/MapPlayDialog.java index 9efcfd8e04..051757655e 100644 --- a/core/src/mindustry/ui/dialogs/MapPlayDialog.java +++ b/core/src/mindustry/ui/dialogs/MapPlayDialog.java @@ -15,8 +15,7 @@ import static mindustry.Vars.*; public class MapPlayDialog extends FloatingDialog{ CustomRulesDialog dialog = new CustomRulesDialog(); Rules rules; - @NonNull - Gamemode selectedGamemode = Gamemode.survival; + @NonNull Gamemode selectedGamemode = Gamemode.survival; Map lastMap; public MapPlayDialog(){ diff --git a/core/src/mindustry/ui/dialogs/MapsDialog.java b/core/src/mindustry/ui/dialogs/MapsDialog.java index 2f99b9a06b..b3c957d41e 100644 --- a/core/src/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/mindustry/ui/dialogs/MapsDialog.java @@ -183,7 +183,7 @@ public class MapsDialog extends FloatingDialog{ t.row(); t.add("$editor.author").padRight(10).color(Color.gray); t.row(); - t.add(map.custom && map.author().isEmpty() ? "Anuke" : map.author()).growX().wrap().padTop(2); + t.add(!map.custom && map.author().isEmpty() ? "Anuke" : map.author()).growX().wrap().padTop(2); t.row(); t.add("$editor.description").padRight(10).color(Color.gray).top(); t.row(); diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index 00d6e2351f..b57a8f5a88 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -3,6 +3,9 @@ package mindustry.ui.dialogs; import arc.*; import arc.Net.*; import arc.files.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.scene.ui.TextButton.*; import arc.util.*; import arc.util.io.*; import mindustry.gen.*; @@ -20,60 +23,14 @@ public class ModsDialog extends FloatingDialog{ super("$mods"); addCloseButton(); - buttons.addImageTextButton("$mods.openfolder", Icon.link, - () -> Core.app.openFolder(modDirectory.absolutePath())).size(250f, 64f); - - buttons.row(); - - buttons.addImageTextButton("$mods.guide", Icon.link, - () -> Core.net.openURI(modGuideURL)) - .size(210, 64f); - - buttons.addImageTextButton("$mod.import.github", Icon.github, () -> { - ui.showTextInput("$mod.import.github", "", 64, "Anuken/ExampleMod", text -> { - ui.loadfrag.show(); - Core.net.httpGet("http://api.github.com/repos/" + text + "/zipball/master", loc -> { - Core.net.httpGet(loc.getHeader("Location"), result -> { - if(result.getStatus() != HttpStatus.OK){ - ui.showErrorMessage(Core.bundle.format("connectfail", result.getStatus())); - ui.loadfrag.hide(); - }else{ - try{ - Fi file = tmpDirectory.child(text.replace("/", "") + ".zip"); - Streams.copy(result.getResultAsStream(), file.write(false)); - mods.importMod(file); - file.delete(); - Core.app.post(() -> { - try{ - mods.reloadContent(); - setup(); - ui.loadfrag.hide(); - }catch(Throwable e){ - ui.showException(e); - } - }); - }catch(Throwable e){ - modError(e); - } - } - }, t -> Core.app.post(() -> modError(t))); - }, t -> Core.app.post(() -> modError(t))); - }); - }).size(250f, 64f); + buttons.addImageTextButton("$mods.guide", Icon.link, () -> Core.net.openURI(modGuideURL)).size(210, 64f); shown(this::setup); hidden(() -> { if(mods.requiresReload()){ - ui.loadAnd("$reloading", () -> { - mods.eachEnabled(mod -> { - if(mod.hasUnmetDependencies()){ - ui.showErrorMessage(Core.bundle.format("mod.nowdisabled", mod.name, mod.missingDependencies.toString(", "))); - } - }); - mods.reloadContent(); - }); + reload(); } }); @@ -95,16 +52,102 @@ public class ModsDialog extends FloatingDialog{ } void setup(){ + float h = 120f; + float w = mobile ? 430f : 500f; + cont.clear(); cont.defaults().width(mobile ? 500 : 560f).pad(4); cont.add("$mod.reloadrequired").visible(mods::requiresReload).center().get().setAlignment(Align.center); cont.row(); + + cont.table(buttons -> { + buttons.left().defaults().growX().height(60f).uniformX(); + + TextButtonStyle style = Styles.clearPartialt; + float margin = 12f; + + buttons.addImageTextButton("$mod.import", Icon.add, style, () -> { + FloatingDialog dialog = new FloatingDialog("$mod.import"); + + TextButtonStyle bstyle = Styles.cleart; + + dialog.cont.table(Tex.button, t -> { + t.defaults().size(300f, 70f); + t.margin(12f); + + t.addImageTextButton("$mod.import.file", Icon.file, bstyle, () -> { + dialog.hide(); + + platform.showFileChooser(true, "zip", file -> { + try{ + mods.importMod(file); + setup(); + }catch(IOException e){ + ui.showException(e); + e.printStackTrace(); + } + }); + }).margin(12f); + + t.row(); + + t.addImageTextButton("$mod.import.github", Icon.github, bstyle, () -> { + dialog.hide(); + + ui.showTextInput("$mod.import.github", "", 64, "Anuken/ExampleMod", text -> { + ui.loadfrag.show(); + Core.net.httpGet("http://api.github.com/repos/" + text + "/zipball/master", loc -> { + Core.net.httpGet(loc.getHeader("Location"), result -> { + if(result.getStatus() != HttpStatus.OK){ + ui.showErrorMessage(Core.bundle.format("connectfail", result.getStatus())); + ui.loadfrag.hide(); + }else{ + try{ + Fi file = tmpDirectory.child(text.replace("/", "") + ".zip"); + Streams.copy(result.getResultAsStream(), file.write(false)); + mods.importMod(file); + file.delete(); + Core.app.post(() -> { + try{ + mods.reloadContent(); + setup(); + ui.loadfrag.hide(); + }catch(Throwable e){ + ui.showException(e); + } + }); + }catch(Throwable e){ + modError(e); + } + } + }, t2 -> Core.app.post(() -> modError(t2))); + }, t2 -> Core.app.post(() -> modError(t2))); + }); + }).margin(12f); + }); + + dialog.addCloseButton(); + + dialog.show(); + }).margin(margin); + + buttons.addImageTextButton("$mods.reload", Icon.refresh, style, this::reload).margin(margin); + + if(!mobile){ + buttons.addImageTextButton("$mods.openfolder", Icon.link, style, () -> Core.app.openFolder(modDirectory.absolutePath())).margin(margin); + } + }).width(w); + + cont.row(); + if(!mods.list().isEmpty()){ cont.pane(table -> { table.margin(10f).top(); boolean anyDisabled = false; for(LoadedMod mod : mods.list()){ + String letter = (Strings.stripColors(mod.name).charAt(0) + "").toUpperCase(); + if(!mod.enabled() && !anyDisabled && mods.list().size > 0){ anyDisabled = true; table.row(); @@ -112,26 +155,47 @@ public class ModsDialog extends FloatingDialog{ table.row(); } - table.table(Styles.black6, t -> { - t.defaults().pad(2).left().top(); - t.margin(14f).left(); + table.addButton(t -> { + t.top().left(); + t.margin(12f); + + t.add(new BorderImage(){ + { + if(mod.iconTexture != null){ + setDrawable(new TextureRegion(mod.iconTexture)); + }else{ + setDrawable(Tex.clear); + } + } + + @Override + public void draw(){ + super.draw(); + + if(mod.iconTexture == null){ + Fonts.def.draw(letter, x + width/2f, y + height/2f, Align.center); + } + } + }.border(Pal.accent)).size(h - 8f).padTop(-8f).padLeft(-8f).padRight(6f); + + t.defaults().left().top(); t.table(title -> { title.left(); - title.add("[accent]" + mod.meta.displayName() + "[lightgray] v" + mod.meta.version + (mod.enabled() ? "" : "\n" + Core.bundle.get("mod.disabled") + "")).width(200f).wrap(); + title.add("" + mod.meta.displayName() + "\n[lightgray]v" + mod.meta.version + (mod.enabled() ? "" : "\n" + Core.bundle.get("mod.disabled") + "")).growX(); title.add().growX(); - title.addImageTextButton(mod.enabled() ? "$mod.disable" : "$mod.enable", mod.enabled() ? Icon.downOpen : Icon.upOpen, Styles.cleart, () -> { + title.addImageTextButton(mod.enabled() ? "$mod.disable" : "$mod.enable", mod.enabled() ? Icon.downOpen : Icon.upOpen, Styles.transt, () -> { mods.setEnabled(mod, !mod.enabled()); setup(); }).height(50f).margin(8f).width(130f).disabled(!mod.isSupported()); if(steam && !mod.hasSteamID()){ - title.addImageButton(Icon.download, Styles.cleari, () -> { + title.addImageButton(Icon.download, Styles.clearTransi, () -> { platform.publish(mod); }).size(50f); } - title.addImageButton(mod.hasSteamID() ? Icon.link : Icon.trash, Styles.cleari, () -> { + title.addImageButton(mod.hasSteamID() ? Icon.link : Icon.trash, Styles.clearPartiali, () -> { if(!mod.hasSteamID()){ ui.showConfirm("$confirm", "$mod.remove.confirm", () -> { mods.removeMod(mod); @@ -141,17 +205,9 @@ public class ModsDialog extends FloatingDialog{ platform.viewListing(mod); } }).size(50f); - }).growX().left().padTop(-14f).padRight(-14f); + }).growX().left(); t.row(); - if(mod.meta.author != null){ - t.add(Core.bundle.format("mod.author", mod.meta.author)); - t.row(); - } - if(mod.meta.description != null){ - t.labelWrap("[lightgray]" + mod.meta.description).growX(); - t.row(); - } if(!mod.isSupported()){ t.labelWrap(Core.bundle.format("mod.requiresversion", mod.meta.minGameVersion)).growX(); t.row(); @@ -162,7 +218,7 @@ public class ModsDialog extends FloatingDialog{ t.labelWrap("$mod.erroredcontent").growX(); t.row(); } - }).width(mobile ? 430f : 500f); + }, Styles.clearPartialt, () -> showMod(mod)).size(w, h); table.row(); } }); @@ -173,16 +229,52 @@ public class ModsDialog extends FloatingDialog{ cont.row(); - cont.addImageTextButton("$mod.import", Icon.add, () -> { - platform.showFileChooser(true, "zip", file -> { - try{ - mods.importMod(file); - setup(); - }catch(IOException e){ - ui.showException(e); - e.printStackTrace(); + + } + + private void reload(){ + ui.loadAnd("$reloading", () -> { + mods.eachEnabled(mod -> { + if(mod.hasUnmetDependencies()){ + ui.showErrorMessage(Core.bundle.format("mod.nowdisabled", mod.name, mod.missingDependencies.toString(", "))); } }); - }).margin(12f).width(400f); + mods.reloadContent(); + setup(); + }); + } + + private void showMod(LoadedMod mod){ + FloatingDialog dialog = new FloatingDialog(mod.meta.displayName()); + + dialog.addCloseButton(); + + if(!mobile){ + dialog.buttons.addImageTextButton("$mods.openfolder", Icon.link, () -> Core.app.openFolder(mod.file.absolutePath())); + } + + //TODO improve this menu later + dialog.cont.pane(desc -> { + desc.center(); + desc.defaults().padTop(10).left(); + + desc.add("$editor.name").padRight(10).color(Color.gray).padTop(0); + desc.row(); + desc.add(mod.meta.displayName()).growX().wrap().padTop(2); + desc.row(); + if(mod.meta.author != null){ + desc.add("$editor.author").padRight(10).color(Color.gray); + desc.row(); + desc.add(mod.meta.author).growX().wrap().padTop(2); + desc.row(); + } + if(mod.meta.description != null){ + desc.add("$editor.description").padRight(10).color(Color.gray).top(); + desc.row(); + desc.add(mod.meta.description).growX().wrap().padTop(2); + } + }).width(400f); + + dialog.show(); } } diff --git a/core/src/mindustry/world/blocks/storage/LaunchPad.java b/core/src/mindustry/world/blocks/storage/LaunchPad.java index 6b577d4adc..c646c77cb7 100644 --- a/core/src/mindustry/world/blocks/storage/LaunchPad.java +++ b/core/src/mindustry/world/blocks/storage/LaunchPad.java @@ -1,19 +1,9 @@ package mindustry.world.blocks.storage; -import arc.*; -import arc.graphics.g2d.*; -import arc.math.*; -import arc.util.*; -import mindustry.*; -import mindustry.content.*; -import mindustry.game.EventType.*; import mindustry.gen.*; -import mindustry.graphics.*; import mindustry.type.*; import mindustry.world.meta.*; -import static mindustry.Vars.*; - public class LaunchPad extends StorageBlock{ public final int timerLaunch = timers++; /** Time inbetween launches. */ @@ -37,6 +27,8 @@ public class LaunchPad extends StorageBlock{ @Override public void draw(){ super.draw(); + //TODO + /* //TODO broken float progress = Mathf.clamp(Mathf.clamp((items.total() / (float)itemCapacity)) * ((timer().getTime(timerLaunch) / (launchTime / timeScale())))); @@ -57,7 +49,7 @@ public class LaunchPad extends StorageBlock{ } } - Draw.reset(); + Draw.reset();*/ } @Override @@ -67,6 +59,8 @@ public class LaunchPad extends StorageBlock{ @Override public void updateTile(){ + //TODO + /* if(state.isCampaign() && consValid() && items.total() >= itemCapacity && timer(timerLaunch, launchTime / timeScale())){ for(Item item : Vars.content.items()){ @@ -77,7 +71,7 @@ public class LaunchPad extends StorageBlock{ items.remove(item, used); Events.fire(new LaunchItemEvent(item, used)); } - } + }*/ } } } diff --git a/gradle.properties b/gradle.properties index da0c3966fa..cd20e76ae5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=7f42d930e71cad9bf0f461d0cc92c4963fcc8067 +archash=