Merged Custom/editor maps implementation

This commit is contained in:
Anuken
2023-05-11 11:24:42 -04:00
parent 51daa82a1b
commit b3e111ebbb
5 changed files with 217 additions and 248 deletions

View File

@@ -50,8 +50,8 @@ public class UI implements ApplicationListener, Loadable{
public AboutDialog about;
public GameOverDialog restart;
public CustomGameDialog custom;
public MapsDialog maps;
public CustomMapsDialog custom;
public EditorMapsDialog maps;
public LoadDialog load;
public DiscordDialog discord;
public JoinDialog join;
@@ -185,7 +185,7 @@ public class UI implements ApplicationListener, Loadable{
join = new JoinDialog();
discord = new DiscordDialog();
load = new LoadDialog();
custom = new CustomGameDialog();
custom = new CustomMapsDialog();
language = new LanguageDialog();
database = new DatabaseDialog();
settings = new SettingsMenuDialog();
@@ -195,7 +195,7 @@ public class UI implements ApplicationListener, Loadable{
bans = new BansDialog();
admins = new AdminsDialog();
traces = new TraceDialog();
maps = new MapsDialog();
maps = new EditorMapsDialog();
content = new ContentInfoDialog();
planet = new PlanetDialog();
research = new ResearchDialog();

View File

@@ -1,98 +0,0 @@
package mindustry.ui.dialogs;
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.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.maps.*;
import mindustry.ui.*;
public class CustomGameDialog extends BaseDialog{
private MapPlayDialog dialog = new MapPlayDialog();
public CustomGameDialog(){
super("@customgame");
addCloseButton();
shown(this::setup);
onResize(this::setup);
}
void setup(){
clearChildren();
add(titleTable).growX().row();
stack(cont, buttons).grow();
buttons.bottom();
cont.clear();
Table maps = new Table();
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.grayPanel;
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()){
if(i % maxwidth == 0){
maps.row();
}
ImageButton image = new ImageButton(new TextureRegion(map.safeTexture()), style);
image.margin(5);
image.top();
Image img = image.getImage();
img.remove();
image.row();
image.table(t -> {
t.left();
for(Gamemode mode : Gamemode.all){
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()) + "Small");
if(mode.valid(map) && Core.atlas.isFound(icon.getRegion())){
t.image(icon).size(16f).pad(4f);
}
}
}).left();
image.row();
image.add(map.name()).pad(1f).growX().wrap().left().get().setEllipsis(true);
image.row();
image.image(Tex.whiteui, Pal.gray).growX().pad(3).height(4f);
image.row();
image.add(img).size(images);
BorderImage border = new BorderImage(map.safeTexture(), 3f);
border.setScaling(Scaling.fit);
image.replaceImage(border);
image.clicked(() -> dialog.show(map));
maps.add(image);
i++;
}
if(Vars.maps.all().size == 0){
maps.add("@maps.none").pad(50);
}
cont.add(pane).grow();
}
}

View File

@@ -0,0 +1,16 @@
package mindustry.ui.dialogs;
import mindustry.maps.*;
public class CustomMapsDialog extends MapListDialog{
private MapPlayDialog dialog = new MapPlayDialog();
public CustomMapsDialog(){
super("@customgame", false);
}
@Override
void showMap(Map map){
dialog.show(map);
}
}

View File

@@ -0,0 +1,155 @@
package mindustry.ui.dialogs;
import arc.*;
import arc.graphics.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.*;
import mindustry.game.EventType.*;
import mindustry.gen.*;
import mindustry.io.*;
import mindustry.maps.*;
import mindustry.ui.*;
import static mindustry.Vars.*;
public class EditorMapsDialog extends MapListDialog{
public EditorMapsDialog(){
super("@maps", true);
}
@Override
void buildButtons(){
buttons.button("@editor.newmap", Icon.add, () -> {
ui.showTextInput("@editor.newmap", "@editor.mapname", "", text -> {
Runnable show = () -> ui.loadAnd(() -> {
hide();
ui.editor.show();
editor.tags.put("name", text);
Events.fire(new MapMakeEvent());
});
if(maps.byName(text) != null){
ui.showErrorMessage("@editor.exists");
}else{
show.run();
}
});
}).size(210f, 64f);
buttons.button("@editor.importmap", Icon.upload, () -> {
platform.showFileChooser(true, mapExtension, file -> {
ui.loadAnd(() -> {
maps.tryCatchMapError(() -> {
if(MapIO.isImage(file)){
ui.showErrorMessage("@editor.errorimage");
return;
}
Map map = MapIO.createMap(file, true);
//when you attempt to import a save, it will have no name, so generate one
String name = map.tags.get("name", () -> {
String result = "unknown";
int number = 0;
while(maps.byName(result + number++) != null) ;
return result + number;
});
//this will never actually get called, but it remains just in case
if(name == null){
ui.showErrorMessage("@editor.errorname");
return;
}
Map conflict = maps.all().find(m -> m.name().equals(name));
if(conflict != null && !conflict.custom){
ui.showInfo(Core.bundle.format("editor.import.exists", name));
}else if(conflict != null){
ui.showConfirm("@confirm", Core.bundle.format("editor.overwrite.confirm", map.name()), () -> {
maps.tryCatchMapError(() -> {
maps.removeMap(conflict);
maps.importMap(map.file);
setup();
});
});
}else{
maps.importMap(map.file);
setup();
}
});
});
});
}).size(210f, 64f);
}
@Override
void showMap(Map map){
BaseDialog dialog = activeDialog = new BaseDialog("@editor.mapinfo");
dialog.addCloseButton();
float mapsize = Core.graphics.isPortrait() ? 160f : 300f;
Table table = dialog.cont;
table.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize);
table.table(Styles.black, desc -> {
desc.top();
Table t = new Table();
t.margin(6);
ScrollPane pane = new ScrollPane(t);
desc.add(pane).grow();
t.top();
t.defaults().padTop(10).left();
t.add("@editor.mapname").padRight(10).color(Color.gray).padTop(0);
t.row();
t.add(map.name()).growX().wrap().padTop(2);
t.row();
t.add("@editor.author").padRight(10).color(Color.gray);
t.row();
t.add(!map.custom && map.tags.get("author", "").isEmpty() ? "Anuke" : map.author()).growX().wrap().padTop(2);
t.row();
if(!map.tags.get("description", "").isEmpty()){
t.add("@editor.description").padRight(10).color(Color.gray).top();
t.row();
t.add(map.description()).growX().wrap().padTop(2);
}
}).height(mapsize).width(mapsize);
table.row();
table.button("@editor.openin", Icon.export, () -> {
try{
Vars.ui.editor.beginEditMap(map.file);
dialog.hide();
hide();
}catch(Exception e){
Log.err(e);
ui.showErrorMessage("@error.mapnotfound");
}
}).fillX().height(54f).marginLeft(10);
table.button(map.workshop && steam ? "@view.workshop" : "@delete", map.workshop && steam ? Icon.link : Icon.trash, () -> {
if(map.workshop && steam){
platform.viewListing(map);
}else{
ui.showConfirm("@confirm", Core.bundle.format("map.delete", map.name()), () -> {
maps.removeMap(map);
dialog.hide();
setup();
});
}
}).fillX().height(54f).marginLeft(10).disabled(!map.workshop && !map.custom);
dialog.show();
}
}

View File

@@ -8,30 +8,33 @@ import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.io.*;
import mindustry.maps.*;
import mindustry.ui.*;
import static mindustry.Vars.*;
public class MapsDialog extends BaseDialog{
private BaseDialog dialog;
public abstract class MapListDialog extends BaseDialog{
BaseDialog activeDialog;
private String searchString;
private Seq<Gamemode> modes = new Seq<>();
private Table mapTable = new Table();
private TextField searchField;
private boolean showBuiltIn = Core.settings.getBool("editorshowbuiltinmaps", true);
private boolean showCustom = Core.settings.getBool("editorshowcustommaps", true);
private boolean searchAuthor = Core.settings.getBool("editorsearchauthor", false);
private boolean searchDescription = Core.settings.getBool("editorsearchdescription", false);
private boolean
showBuiltIn = Core.settings.getBool("editorshowbuiltinmaps", true),
showCustom = Core.settings.getBool("editorshowcustommaps", true),
searchAuthor = Core.settings.getBool("editorsearchauthor", false),
searchDescription = Core.settings.getBool("editorsearchdescription", false),
displayType;
public MapsDialog(){
super("@maps");
public MapListDialog(String title, boolean displayType){
super(title);
this.displayType = displayType;
buttons.remove();
@@ -39,13 +42,17 @@ public class MapsDialog extends BaseDialog{
shown(this::setup);
onResize(() -> {
if(dialog != null){
dialog.hide();
if(activeDialog != null){
activeDialog.hide();
}
setup();
});
}
void buildButtons(){}
abstract void showMap(Map map);
void setup(){
buttons.clearChildren();
@@ -58,69 +65,7 @@ public class MapsDialog extends BaseDialog{
buttons.button("@back", Icon.left, this::hide).size(210f, 64f);
}
buttons.button("@editor.newmap", Icon.add, () -> {
ui.showTextInput("@editor.newmap", "@editor.mapname", "", text -> {
Runnable show = () -> ui.loadAnd(() -> {
hide();
ui.editor.show();
editor.tags.put("name", text);
Events.fire(new MapMakeEvent());
});
if(maps.byName(text) != null){
ui.showErrorMessage("@editor.exists");
}else{
show.run();
}
});
}).size(210f, 64f);
buttons.button("@editor.importmap", Icon.upload, () -> {
platform.showFileChooser(true, mapExtension, file -> {
ui.loadAnd(() -> {
maps.tryCatchMapError(() -> {
if(MapIO.isImage(file)){
ui.showErrorMessage("@editor.errorimage");
return;
}
Map map = MapIO.createMap(file, true);
//when you attempt to import a save, it will have no name, so generate one
String name = map.tags.get("name", () -> {
String result = "unknown";
int number = 0;
while(maps.byName(result + number++) != null) ;
return result + number;
});
//this will never actually get called, but it remains just in case
if(name == null){
ui.showErrorMessage("@editor.errorname");
return;
}
Map conflict = maps.all().find(m -> m.name().equals(name));
if(conflict != null && !conflict.custom){
ui.showInfo(Core.bundle.format("editor.import.exists", name));
}else if(conflict != null){
ui.showConfirm("@confirm", Core.bundle.format("editor.overwrite.confirm", map.name()), () -> {
maps.tryCatchMapError(() -> {
maps.removeMap(conflict);
maps.importMap(map.file);
setup();
});
});
}else{
maps.importMap(map.file);
setup();
}
});
});
});
}).size(210f, 64f);
buildButtons();
cont.clear();
@@ -180,16 +125,31 @@ public class MapsDialog extends BaseDialog{
mapTable.row();
}
TextButton button = mapTable.button("", Styles.grayt, () -> showMapInfo(map)).width(mapsize).pad(8).get();
TextButton button = mapTable.button("", Styles.grayt, () -> showMap(map)).width(mapsize).pad(8).get();
button.clearChildren();
button.margin(9);
//TODO hide in editor?
button.table(t -> {
t.left();
for(Gamemode mode : Gamemode.all){
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()) + "Small");
if(mode.valid(map) && Core.atlas.isFound(icon.getRegion())){
t.image(icon).size(16f).pad(4f);
}
}
}).left().row();
button.add(map.name()).width(mapsize - 18f).center().get().setEllipsis(true);
button.row();
button.image().growX().pad(4).color(Pal.gray);
button.row();
button.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize - 20f);
button.row();
button.add(map.custom ? "@custom" : map.workshop ? "@workshop" : map.mod != null ? "[lightgray]" + map.mod.meta.displayName() : "@builtin").color(Color.gray).padTop(3);
if(displayType){
button.row();
button.add(map.custom ? "@custom" : map.workshop ? "@workshop" : map.mod != null ? "[lightgray]" + map.mod.meta.displayName() : "@builtin").color(Color.gray).padTop(3);
}
i++;
}
@@ -201,9 +161,9 @@ public class MapsDialog extends BaseDialog{
}
void showMapFilters(){
dialog = new BaseDialog("@editor.filters");
dialog.addCloseButton();
dialog.cont.table(menu -> {
activeDialog = new BaseDialog("@editor.filters");
activeDialog.addCloseButton();
activeDialog.cont.table(menu -> {
menu.add("@editor.filters.mode").width(150f).left();
menu.table(t -> {
for(Gamemode mode : Gamemode.all){
@@ -252,71 +212,7 @@ public class MapsDialog extends BaseDialog{
});
});
dialog.show();
}
void showMapInfo(Map map){
dialog = new BaseDialog("@editor.mapinfo");
dialog.addCloseButton();
float mapsize = Core.graphics.isPortrait() ? 160f : 300f;
Table table = dialog.cont;
table.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize);
table.table(Styles.black, desc -> {
desc.top();
Table t = new Table();
t.margin(6);
ScrollPane pane = new ScrollPane(t);
desc.add(pane).grow();
t.top();
t.defaults().padTop(10).left();
t.add("@editor.mapname").padRight(10).color(Color.gray).padTop(0);
t.row();
t.add(map.name()).growX().wrap().padTop(2);
t.row();
t.add("@editor.author").padRight(10).color(Color.gray);
t.row();
t.add(!map.custom && map.tags.get("author", "").isEmpty() ? "Anuke" : map.author()).growX().wrap().padTop(2);
t.row();
if(!map.tags.get("description", "").isEmpty()){
t.add("@editor.description").padRight(10).color(Color.gray).top();
t.row();
t.add(map.description()).growX().wrap().padTop(2);
}
}).height(mapsize).width(mapsize);
table.row();
table.button("@editor.openin", Icon.export, () -> {
try{
Vars.ui.editor.beginEditMap(map.file);
dialog.hide();
hide();
}catch(Exception e){
e.printStackTrace();
ui.showErrorMessage("@error.mapnotfound");
}
}).fillX().height(54f).marginLeft(10);
table.button(map.workshop && steam ? "@view.workshop" : "@delete", map.workshop && steam ? Icon.link : Icon.trash, () -> {
if(map.workshop && steam){
platform.viewListing(map);
}else{
ui.showConfirm("@confirm", Core.bundle.format("map.delete", map.name()), () -> {
maps.removeMap(map);
dialog.hide();
setup();
});
}
}).fillX().height(54f).marginLeft(10).disabled(!map.workshop && !map.custom);
dialog.show();
activeDialog.show();
}
@Override