Added new screen for managing and viewing maps, many editor fixes

This commit is contained in:
Anuken
2018-05-23 21:40:59 -04:00
parent d096a7ceb1
commit 9693de8885
13 changed files with 245 additions and 67 deletions

View File

@@ -9,7 +9,6 @@ import io.anuke.mindustry.Vars;
import io.anuke.mindustry.editor.MapEditorDialog;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.input.InputHandler;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.ui.dialogs.*;
import io.anuke.mindustry.ui.fragments.*;
import io.anuke.ucore.core.Core;
@@ -42,6 +41,7 @@ public class UI extends SceneModule{
public AboutDialog about;
public RestartDialog restart;
public LevelDialog levels;
public MapsDialog maps;
public LoadDialog load;
public DiscordDialog discord;
public JoinDialog join;
@@ -172,6 +172,7 @@ public class UI extends SceneModule{
bans = new BansDialog();
admins = new AdminsDialog();
traces = new TraceDialog();
maps = new MapsDialog();
localplayers = new LocalPlayerDialog();
build.begin(scene);
@@ -251,21 +252,22 @@ public class UI extends SceneModule{
public void showInfo(String info){
new Dialog("$text.info.title", "dialog"){{
content().margin(15).add(info).width(600f).get().setWrap(true);
getCell(content()).growX();
content().margin(15).add(info).width(400f).wrap();
buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
}}.show();
}
public void showError(String text){
new Dialog("$text.error.title", "dialog"){{
content().margin(15).add(text);
content().margin(15).add(text).width(400f).wrap();
buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
}}.show();
}
public void showConfirm(String title, String text, Listenable confirmed){
FloatingDialog dialog = new FloatingDialog(title);
dialog.content().add(text).pad(4f);
dialog.content().add(text).width(400f).wrap().pad(4f);
dialog.buttons().defaults().size(200f, 54f).pad(2f);
dialog.buttons().addButton("$text.cancel", dialog::hide);
dialog.buttons().addButton("$text.ok", () -> {

View File

@@ -39,6 +39,7 @@ import io.anuke.ucore.util.Strings;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import static io.anuke.mindustry.Vars.*;
@@ -47,19 +48,17 @@ public class MapEditorDialog extends Dialog implements Disposable{
private MapView view;
private MapInfoDialog infoDialog;
private MapLoadDialog loadDialog;
private MapSaveDialog saveDialog;
private MapResizeDialog resizeDialog;
private ScrollPane pane;
private FloatingDialog menu;
private FileChooser openFile, saveFile, openImage, saveImage;
private ObjectMap<String, String> tags = new ObjectMap<>();
private boolean saved = false;
private boolean shownWithMap = false;
private ButtonGroup<ImageButton> blockgroup;
public MapEditorDialog(){
super("$text.mapeditor", "dialog");
if(gwt) return;
editor = new MapEditor();
view = new MapView(editor);
@@ -73,7 +72,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
try{
if(!editor.getTags().containsKey("name")){
tags.put("name", result.nameWithoutExtension());
editor.getTags().put("name", result.nameWithoutExtension());
}
MapIO.writeMap(result.write(false), editor.getTags(), editor.getMap());
}catch (Exception e){
@@ -118,7 +117,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
try{
MapTileData data = MapIO.readPixmap(new Pixmap(file));
editor.beginEdit(data, new ObjectMap<>());
editor.beginEdit(data, editor.getTags());
view.clearStack();
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
@@ -136,23 +135,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
menu.content().table(t -> {
t.defaults().size(swidth, 60f).padBottom(5).padRight(5).padLeft(5);
t.addImageTextButton("$text.editor.savemap", "icon-floppy-16", isize, () -> {
String name = editor.getTags().get("name", "");
if(name.isEmpty()){
ui.showError("$text.editor.save.noname");
}else{
Map map = world.maps().getByName(name);
if(map != null && !map.custom){
ui.showError("$text.editor.save.overwrite");
}else{
world.maps().saveAndReload(name, editor.getMap(), editor.getTags());
ui.showInfoFade("$text.editor.saved");
}
}
menu.hide();
}).size(swidth*2f + 10, 60f).colspan(2);
t.addImageTextButton("$text.editor.savemap", "icon-floppy-16", isize, this::save).size(swidth*2f + 10, 60f).colspan(2);
t.row();
@@ -172,11 +155,23 @@ public class MapEditorDialog extends Dialog implements Disposable{
createDialog("$text.editor.import",
"$text.editor.importmap", "$text.editor.importmap.description", "icon-load-map", (Listenable)loadDialog::show,
"$text.editor.importfile", "$text.editor.importfile.description", "icon-file", (Listenable)openFile::show,
"$text.editor.importimage", "$text.editor.importimage.description", "icon-file-image", (Listenable)openImage::show));
"$text.editor.importimage", "$text.editor.importimage.description", "icon-file-image", (Listenable)() -> {
if(gwt){
ui.showError("text.web.unsupported");
}else {
openImage.show();
}
}));
t.addImageTextButton("$text.editor.export", "icon-save-map", isize, () -> createDialog("$text.editor.export",
"$text.editor.exportfile", "$text.editor.exportfile.description", "icon-file", (Listenable)saveFile::show,
"$text.editor.exportimage", "$text.editor.exportimage.description", "icon-file-image", (Listenable)saveImage::show));
"$text.editor.exportimage", "$text.editor.exportimage.description", "icon-file-image", (Listenable)() -> {
if(gwt){
ui.showError("text.web.unsupported");
}else {
saveImage.show();
}
}));
t.row();
@@ -204,7 +199,6 @@ public class MapEditorDialog extends Dialog implements Disposable{
});
loadDialog = new MapLoadDialog(map -> {
saveDialog.setFieldText(map.name);
ui.loadAnd(() -> {
try (DataInputStream stream = new DataInputStream(map.stream.get())){
@@ -219,15 +213,6 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
});
});
saveDialog = new MapSaveDialog(name -> {
ui.loadAnd(() -> {
saved = true;
world.maps().saveAndReload(editor.getTags().get("name", name), editor.getMap(), editor.getTags());
loadDialog.rebuild();
});
});
setFillParent(true);
@@ -250,10 +235,12 @@ public class MapEditorDialog extends Dialog implements Disposable{
shown(() -> {
saved = true;
editor.beginEdit(new MapTileData(256, 256), new ObjectMap<>());
blockgroup.getButtons().get(2).setChecked(true);
Core.scene.setScrollFocus(view);
view.clearStack();
Core.scene.setScrollFocus(view);
if(!shownWithMap){
editor.beginEdit(new MapTileData(256, 256), new ObjectMap<>());
}
shownWithMap = false;
Timers.runTask(10f, Platform.instance::updateRPC);
});
@@ -261,12 +248,30 @@ public class MapEditorDialog extends Dialog implements Disposable{
hidden(() -> Platform.instance.updateRPC());
}
private void save(){
String name = editor.getTags().get("name", "");
if(name.isEmpty()){
ui.showError("$text.editor.save.noname");
}else{
Map map = world.maps().getByName(name);
if(map != null && !map.custom){
ui.showError("$text.editor.save.overwrite");
}else{
world.maps().saveMap(name, editor.getMap(), editor.getTags());
ui.showInfoFade("$text.editor.saved");
}
}
menu.hide();
saved = true;
}
/**Argument format:
* 0) button name
* 1) description
* 2) icon name
* 3) listener
*/
* 3) listener */
private FloatingDialog createDialog(String title, Object... arguments){
FloatingDialog dialog = new FloatingDialog(title);
@@ -318,6 +323,22 @@ public class MapEditorDialog extends Dialog implements Disposable{
editor.renderer().dispose();
}
public void beginEditMap(InputStream is){
ui.loadAnd(() -> {
try {
shownWithMap = true;
DataInputStream stream = new DataInputStream(is);
MapMeta meta = MapIO.readMapMeta(stream);
editor.beginEdit(MapIO.readTileData(stream, meta, false), meta.tags);
is.close();
show();
}catch (Exception e){
Log.err(e);
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
}
});
}
public MapView getView() {
return view;
}
@@ -482,7 +503,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
if(Inputs.keyTap(Input.S)){
saveDialog.save();
save();
}
if(Inputs.keyTap(Input.G)){

View File

@@ -67,6 +67,10 @@ public class MapInfoDialog extends FloatingDialog{
tags.put("oregen", enabled ? "1" : "0");
}).left();
name.change();
description.change();
author.change();
Platform.instance.addDialog(name, 50);
Platform.instance.addDialog(author, 50);
Platform.instance.addDialog(description, 1000);

View File

@@ -36,6 +36,7 @@ public class MapLoadDialog extends FloatingDialog{
public void rebuild(){
content().clear();
selected = world.maps().all().first();
ButtonGroup<TextButton> group = new ButtonGroup<>();
@@ -52,7 +53,7 @@ public class MapLoadDialog extends FloatingDialog{
for (Map map : world.maps().all()) {
TextButton button = new TextButton(map.meta.name(), "toggle");
TextButton button = new TextButton(map.getDisplayName(), "toggle");
button.add(new BorderImage(map.texture, 2f)).size(16 * 4f);
button.getCells().reverse();
button.clicked(() -> selected = map);

View File

@@ -198,6 +198,9 @@ public class MapRenderer implements Disposable{
@Override
public void dispose() {
if(chunks == null){
return;
}
for(int x = 0; x < chunks.length; x ++){
for(int y = 0; y < chunks[0].length; y ++){
if(chunks[x][y] != null){

View File

@@ -23,4 +23,8 @@ public class Map {
this.meta = meta;
this.stream = streamSupplier;
}
public String getDisplayName(){
return meta.tags.get("name", name);
}
}

View File

@@ -75,7 +75,8 @@ public class Maps implements Disposable{
loadCustomMaps();
}
public void saveAndReload(String name, MapTileData data, ObjectMap<String, String> tags){
/**Save a map. This updates all values and stored data necessary.*/
public void saveMap(String name, MapTileData data, ObjectMap<String, String> tags){
try {
if (!gwt) {
FileHandle file = customMapDirectory.child(name + "." + mapExtension);
@@ -92,18 +93,43 @@ public class Maps implements Disposable{
}
if(maps.containsKey(name)){
maps.get(name).texture.dispose();
if(maps.get(name).texture != null) {
maps.get(name).texture.dispose();
maps.get(name).texture = null;
}
allMaps.removeValue(maps.get(name), true);
}
Map map = new Map(name, new MapMeta(version, tags, data.width(), data.height(), null), true, getStreamFor(name));
if (!headless){
map.texture = new Texture(MapIO.generatePixmap(data));
}
allMaps.add(map);
maps.put(name, map);
}catch (IOException e){
throw new RuntimeException(e);
}
//todo implement
}
/**Removes a map completely.*/
public void removeMap(Map map){
if(map.texture != null){
map.texture.dispose();
map.texture = null;
}
maps.remove(map.name);
allMaps.removeValue(map, true);
if (!gwt) {
customMapDirectory.child(map.name + "." + mapExtension).delete();
} else {
customMapNames.removeValue(map.name, false);
Settings.putString("map-data-" + map.name, "");
Settings.putString("custom-maps", json.toJson(customMapNames));
Settings.save();
}
}
private void loadMap(String name, Supplier<InputStream> supplier, boolean custom) throws IOException{

View File

@@ -19,9 +19,11 @@ import io.anuke.ucore.scene.ui.layout.Unit;
import java.util.Arrays;
import static io.anuke.mindustry.Vars.gwt;
public class FileChooser extends FloatingDialog {
private Table files;
private FileHandle homeDirectory = Gdx.files.absolute(Gdx.files.getExternalStoragePath());
private FileHandle homeDirectory = gwt ? Gdx.files.internal("") : Gdx.files.absolute(Gdx.files.getExternalStoragePath());
private FileHandle directory = homeDirectory;
private ScrollPane pane;
private TextField navigation, filefield;

View File

@@ -17,12 +17,9 @@ import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
public class LevelDialog extends FloatingDialog{
private ScrollPane pane;
public LevelDialog(){
super("$text.level.select");
getTitleTable().getCell(title()).growX().center();
getTitleTable().center();
addCloseButton();
shown(this::setup);
}
@@ -31,7 +28,7 @@ public class LevelDialog extends FloatingDialog{
content().clear();
Table maps = new Table();
pane = new ScrollPane(maps);
ScrollPane pane = new ScrollPane(maps);
pane.setFadeScrollBars(false);
int maxwidth = 4;

View File

@@ -0,0 +1,116 @@
package io.anuke.mindustry.ui.dialogs;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Scaling;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.io.Map;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.ScrollPane;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Bundles;
import static io.anuke.mindustry.Vars.ui;
import static io.anuke.mindustry.Vars.world;
public class MapsDialog extends FloatingDialog {
public MapsDialog() {
super("$text.maps");
addCloseButton();
shown(this::setup);
}
void setup(){
content().clear();
Table maps = new Table();
maps.marginRight(24);
ScrollPane pane = new ScrollPane(maps, "clear-black");
pane.setFadeScrollBars(false);
int maxwidth = 4;
float mapsize = 200f;
int i = 0;
for(Map map : world.maps().all()){
if(i % maxwidth == 0){
maps.row();
}
TextButton button = maps.addButton("", "clear", () -> showMapInfo(map)).width(mapsize).pad(8).get();
button.clearChildren();
button.margin(6);
button.add(map.meta.tags.get("name", map.name)).growX().center().get().setEllipsis(true);
button.row();
button.addImage("white").growX().pad(4).color(Color.GRAY);
button.row();
((Image)button.stack(new Image(map.texture), new BorderImage(map.texture)).size(mapsize-20f).get().getChildren().first()).setScaling(Scaling.fit);
button.row();
button.add(map.custom ? "$text.custom" : "$text.builtin").color(Color.GRAY).padTop(3);
i ++;
}
content().add(pane).uniformX();
}
void showMapInfo(Map map){
FloatingDialog dialog = new FloatingDialog("$text.editor.mapinfo");
dialog.addCloseButton();
float mapsize = 300f;
Table table = dialog.content();
((Image) table.stack(new Image(map.texture), new BorderImage(map.texture)).size(mapsize).get().getChildren().first()).setScaling(Scaling.fit);
table.table("clear", desc -> {
desc.top();
Table t = new Table();
ScrollPane pane = new ScrollPane(t, "clear-black");
desc.add(pane).grow();
t.top();
t.defaults().padTop(10).left();
t.add("$text.editor.name").padRight(10).color(Color.GRAY).padTop(0);
t.row();
t.add(map.meta.tags.get("name", map.name)).growX().wrap().padTop(2);
t.row();
t.add("$text.editor.author").padRight(10).color(Color.GRAY);
t.row();
t.add(map.meta.author()).growX().wrap().padTop(2);
t.row();
t.add("$text.editor.description").padRight(10).color(Color.GRAY).top();
t.row();
t.add(map.meta.description()).growX().wrap().padTop(2);
t.row();
t.add("$text.editor.oregen.info").padRight(10).color(Color.GRAY);
t.row();
t.add(map.meta.hasOreGen() ? "$text.on" : "$text.off").padTop(2);
}).height(mapsize).width(mapsize).margin(6);
table.row();
table.addImageTextButton("$text.editor.openin", "icon-load-map", "clear", 16*2, () -> {
Vars.ui.editor.beginEditMap(map.stream.get());
dialog.hide();
hide();
}).fillX().height(50f).marginLeft(6);
table.addImageTextButton("$text.delete", "icon-trash-16", "clear", 16*2, () -> {
ui.showConfirm("$text.confirm", Bundles.format("text.map.delete", map.name), () -> {
world.maps().removeMap(map);
dialog.hide();
setup();
});
}).fillX().height(50f).marginLeft(6).disabled(!map.custom).touchable(map.custom ? Touchable.enabled : Touchable.disabled);
dialog.show();
}
}

View File

@@ -31,21 +31,15 @@ public class MenuFragment implements Fragment{
row();
add(new MenuButton("icon-editor", "$text.editor", () -> {
if(gwt){
ui.showInfo("$text.editor.web");
}else{
ui.editor.show();
}
}));
add(new MenuButton("icon-tools", "$text.settings", ui.settings::show));
add(new MenuButton("icon-editor", "$text.editor", ui.editor::show));
add(new MenuButton("icon-menu", "$text.maps", ui.maps::show));
row();
add(new MenuButton("icon-info", "$text.about.button", ui.about::show));
add(new MenuButton("icon-menu", "$text.changelog.title", ui.changelog::show));
add(new MenuButton("icon-tools", "$text.settings", ui.settings::show));
row();