mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-13 09:17:28 +07:00
Added dialogs for saving/loading maps directly, work on web support
This commit is contained in:
@ -164,6 +164,8 @@ text.editor.generate=Generate
|
|||||||
text.editor.resize=Resize
|
text.editor.resize=Resize
|
||||||
text.editor.loadmap=Load Map
|
text.editor.loadmap=Load Map
|
||||||
text.editor.savemap=Save Map
|
text.editor.savemap=Save Map
|
||||||
|
text.editor.importmap=Import Map
|
||||||
|
text.editor.exportmap=Export Map
|
||||||
text.editor.loadimage=Import Terrain
|
text.editor.loadimage=Import Terrain
|
||||||
text.editor.saveimage=Export Terrain
|
text.editor.saveimage=Export Terrain
|
||||||
text.editor.unsaved=[scarlet]You have unsaved changes![]\nAre you sure you want to exit?
|
text.editor.unsaved=[scarlet]You have unsaved changes![]\nAre you sure you want to exit?
|
||||||
|
@ -16,6 +16,7 @@ import io.anuke.ucore.core.Core;
|
|||||||
import io.anuke.ucore.core.Graphics;
|
import io.anuke.ucore.core.Graphics;
|
||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.function.Callable;
|
||||||
import io.anuke.ucore.function.Consumer;
|
import io.anuke.ucore.function.Consumer;
|
||||||
import io.anuke.ucore.function.Listenable;
|
import io.anuke.ucore.function.Listenable;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
@ -211,6 +212,14 @@ public class UI extends SceneModule{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadAnd(Callable call){
|
||||||
|
loadfrag.show();
|
||||||
|
Timers.run(6f, () -> {
|
||||||
|
call.run();
|
||||||
|
loadfrag.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void showTextInput(String title, String text, String def, TextFieldFilter filter, Consumer<String> confirmed){
|
public void showTextInput(String title, String text, String def, TextFieldFilter filter, Consumer<String> confirmed){
|
||||||
new Dialog(title, "dialog"){{
|
new Dialog(title, "dialog"){{
|
||||||
content().margin(30).add(text).padRight(6f);
|
content().margin(30).add(text).padRight(6f);
|
||||||
|
@ -8,10 +8,7 @@ import com.badlogic.gdx.utils.Align;
|
|||||||
import com.badlogic.gdx.utils.ObjectMap;
|
import com.badlogic.gdx.utils.ObjectMap;
|
||||||
import io.anuke.mindustry.content.blocks.Blocks;
|
import io.anuke.mindustry.content.blocks.Blocks;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.io.MapIO;
|
import io.anuke.mindustry.io.*;
|
||||||
import io.anuke.mindustry.io.MapMeta;
|
|
||||||
import io.anuke.mindustry.io.MapTileData;
|
|
||||||
import io.anuke.mindustry.io.Platform;
|
|
||||||
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
||||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
@ -38,6 +35,7 @@ import io.anuke.ucore.util.Mathf;
|
|||||||
import io.anuke.ucore.util.Strings;
|
import io.anuke.ucore.util.Strings;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
@ -68,8 +66,7 @@ public class MapEditorDialog extends Dialog{
|
|||||||
saveFile = new FileChooser("$text.saveimage", false, file -> {
|
saveFile = new FileChooser("$text.saveimage", false, file -> {
|
||||||
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
|
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
|
||||||
FileHandle result = file;
|
FileHandle result = file;
|
||||||
ui.loadfrag.show();
|
ui.loadAnd(() -> {
|
||||||
Timers.run(3f, () -> {
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
if(!editor.getTags().containsKey("name")){
|
if(!editor.getTags().containsKey("name")){
|
||||||
@ -80,13 +77,11 @@ public class MapEditorDialog extends Dialog{
|
|||||||
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
ui.loadfrag.hide();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
openFile = new FileChooser("$text.loadimage", FileChooser.mapFilter, true, file -> {
|
openFile = new FileChooser("$text.loadimage", FileChooser.mapFilter, true, file -> {
|
||||||
ui.loadfrag.show();
|
ui.loadAnd(() -> {
|
||||||
Timers.run(3f, () -> {
|
|
||||||
try{
|
try{
|
||||||
DataInputStream stream = new DataInputStream(file.read());
|
DataInputStream stream = new DataInputStream(file.read());
|
||||||
|
|
||||||
@ -99,28 +94,24 @@ public class MapEditorDialog extends Dialog{
|
|||||||
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
|
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
ui.loadfrag.hide();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
saveImage = new FileChooser("$text.saveimage", false, file -> {
|
saveImage = new FileChooser("$text.saveimage", false, file -> {
|
||||||
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
||||||
FileHandle result = file;
|
FileHandle result = file;
|
||||||
ui.loadfrag.show();
|
ui.loadAnd(() -> {
|
||||||
Timers.run(3f, () -> {
|
|
||||||
try{
|
try{
|
||||||
Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result);
|
Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result);
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
ui.loadfrag.hide();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
openImage = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> {
|
openImage = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> {
|
||||||
ui.loadfrag.show();
|
ui.loadAnd(() -> {
|
||||||
Timers.run(3f, () -> {
|
|
||||||
try{
|
try{
|
||||||
MapTileData data = MapIO.readPixmap(new Pixmap(file));
|
MapTileData data = MapIO.readPixmap(new Pixmap(file));
|
||||||
|
|
||||||
@ -130,7 +121,6 @@ public class MapEditorDialog extends Dialog{
|
|||||||
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
|
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
ui.loadfrag.hide();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -155,11 +145,23 @@ public class MapEditorDialog extends Dialog{
|
|||||||
t.row();
|
t.row();
|
||||||
|
|
||||||
t.addImageTextButton("$text.editor.savemap", "icon-save-map", isize, () -> {
|
t.addImageTextButton("$text.editor.savemap", "icon-save-map", isize, () -> {
|
||||||
saveFile.show();
|
saveDialog.show();
|
||||||
menu.hide();
|
menu.hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
t.addImageTextButton("$text.editor.loadmap", "icon-load-map", isize, () -> {
|
t.addImageTextButton("$text.editor.loadmap", "icon-load-map", isize, () -> {
|
||||||
|
loadDialog.show();
|
||||||
|
menu.hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
t.row();
|
||||||
|
|
||||||
|
t.addImageTextButton("$text.editor.importmap", "icon-save-map", isize, () -> {
|
||||||
|
saveFile.show();
|
||||||
|
menu.hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
t.addImageTextButton("$text.editor.exportmap", "icon-load-map", isize, () -> {
|
||||||
openFile.show();
|
openFile.show();
|
||||||
menu.hide();
|
menu.hide();
|
||||||
});
|
});
|
||||||
@ -190,64 +192,40 @@ public class MapEditorDialog extends Dialog{
|
|||||||
menu.hide();
|
menu.hide();
|
||||||
}).size(470f, 60f);
|
}).size(470f, 60f);
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
loadDialog = new MapLoadDialog(map -> {
|
|
||||||
saveDialog.setFieldText(map.name);
|
|
||||||
ui.loadfrag.show();
|
|
||||||
|
|
||||||
Timers.run(3f, () -> {
|
|
||||||
Map copy = new Map();
|
|
||||||
copy.name = map.name;
|
|
||||||
copy.id = -1;
|
|
||||||
copy.pixmap = Pixmaps.copy(map.pixmap);
|
|
||||||
copy.texture = new Texture(copy.pixmap);
|
|
||||||
copy.oreGen = map.oreGen;
|
|
||||||
editor.beginEdit(copy);
|
|
||||||
ui.loadfrag.hide();
|
|
||||||
view.clearStack();
|
|
||||||
});
|
|
||||||
});*/
|
|
||||||
|
|
||||||
resizeDialog = new MapResizeDialog(editor, (x, y) -> {
|
resizeDialog = new MapResizeDialog(editor, (x, y) -> {
|
||||||
if(!(editor.getMap().width() == x && editor.getMap().height() == y)){
|
if(!(editor.getMap().width() == x && editor.getMap().height() == y)){
|
||||||
ui.loadfrag.show();
|
ui.loadAnd(() -> {
|
||||||
Timers.run(10f, () -> {
|
|
||||||
editor.resize(x, y);
|
editor.resize(x, y);
|
||||||
view.clearStack();
|
view.clearStack();
|
||||||
ui.loadfrag.hide();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
loadDialog = new MapLoadDialog(map -> {
|
||||||
saveDialog = new MapSaveDialog(name -> {
|
saveDialog.setFieldText(map.name);
|
||||||
ui.loadfrag.show();
|
|
||||||
if(verifyMap()){
|
ui.loadAnd(() -> {
|
||||||
saved = true;
|
try (DataInputStream stream = new DataInputStream(map.stream.get())){
|
||||||
String before = editor.getMap().name;
|
MapMeta meta = MapIO.readMapMeta(stream);
|
||||||
editor.getMap().name = name;
|
MapTileData data = MapIO.readTileData(stream, meta, false);
|
||||||
Timers.run(10f, () -> {
|
|
||||||
world.maps().saveAndReload(editor.getMap(), editor.pixmap());
|
editor.beginEdit(data, meta.tags);
|
||||||
loadDialog.rebuild();
|
|
||||||
ui.loadfrag.hide();
|
|
||||||
view.clearStack();
|
view.clearStack();
|
||||||
|
}catch (IOException e){
|
||||||
|
ui.showError(Bundles.format("text.editor.errormapload", Strings.parseException(e, false)));
|
||||||
|
Log.err(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if(!name.equals(before)) {
|
|
||||||
Map map = new Map();
|
|
||||||
map.name = editor.getMap().name;
|
|
||||||
map.oreGen = editor.getMap().oreGen;
|
|
||||||
map.pixmap = Pixmaps.copy(editor.getMap().pixmap);
|
|
||||||
map.texture = new Texture(map.pixmap);
|
|
||||||
map.custom = true;
|
|
||||||
editor.beginEdit(map);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}else{
|
saveDialog = new MapSaveDialog(name -> {
|
||||||
ui.loadfrag.hide();
|
ui.loadAnd(() -> {
|
||||||
}
|
saved = true;
|
||||||
});*/
|
world.maps().saveAndReload(editor.getTags().get("name", name), editor.getMap(), editor.getTags());
|
||||||
|
loadDialog.rebuild();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
setFillParent(true);
|
setFillParent(true);
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package io.anuke.mindustry.io;
|
package io.anuke.mindustry.io;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import io.anuke.ucore.function.Supplier;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class Map {
|
public class Map {
|
||||||
/**Internal map name. This is the filename, without any extensions.*/
|
/**Internal map name. This is the filename, without any extensions.*/
|
||||||
@ -9,12 +12,15 @@ public class Map {
|
|||||||
public final boolean custom;
|
public final boolean custom;
|
||||||
/**Metadata. Author description, display name, etc.*/
|
/**Metadata. Author description, display name, etc.*/
|
||||||
public final MapMeta meta;
|
public final MapMeta meta;
|
||||||
|
/**Supplies a new input stream with the data of this map.*/
|
||||||
|
public final Supplier<InputStream> stream;
|
||||||
/**Preview texture.*/
|
/**Preview texture.*/
|
||||||
public Texture texture;
|
public Texture texture;
|
||||||
|
|
||||||
public Map(String name, MapMeta meta, boolean custom){
|
public Map(String name, MapMeta meta, boolean custom, Supplier<InputStream> streamSupplier){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.custom = custom;
|
this.custom = custom;
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
|
this.stream = streamSupplier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,18 @@ import com.badlogic.gdx.files.FileHandle;
|
|||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.Disposable;
|
import com.badlogic.gdx.utils.Disposable;
|
||||||
|
import com.badlogic.gdx.utils.Json;
|
||||||
import com.badlogic.gdx.utils.ObjectMap;
|
import com.badlogic.gdx.utils.ObjectMap;
|
||||||
|
import io.anuke.ucore.core.Settings;
|
||||||
|
import io.anuke.ucore.function.Supplier;
|
||||||
import io.anuke.ucore.util.Log;
|
import io.anuke.ucore.util.Log;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.customMapDirectory;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
import static io.anuke.mindustry.Vars.headless;
|
|
||||||
import static io.anuke.mindustry.Vars.mapExtension;
|
|
||||||
|
|
||||||
public class Maps implements Disposable{
|
public class Maps implements Disposable{
|
||||||
/**List of all built-in maps.*/
|
/**List of all built-in maps.*/
|
||||||
@ -21,16 +24,25 @@ public class Maps implements Disposable{
|
|||||||
/**Tile format version.*/
|
/**Tile format version.*/
|
||||||
private static final int version = 0;
|
private static final int version = 0;
|
||||||
|
|
||||||
|
/**Maps map names to the real maps.*/
|
||||||
private ObjectMap<String, Map> maps = new ObjectMap<>();
|
private ObjectMap<String, Map> maps = new ObjectMap<>();
|
||||||
|
/**All maps stored in an ordered array.*/
|
||||||
private Array<Map> allMaps = new Array<>();
|
private Array<Map> allMaps = new Array<>();
|
||||||
|
/**Temporary array used for returning things.*/
|
||||||
private Array<Map> returnArray = new Array<>();
|
private Array<Map> returnArray = new Array<>();
|
||||||
|
/**Used for writing a list of custom map names on GWT.*/
|
||||||
|
private Json json = new Json();
|
||||||
|
|
||||||
|
public Maps(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**Returns a list of all maps, including custom ones.*/
|
/**Returns a list of all maps, including custom ones.*/
|
||||||
public Array<Map> all(){
|
public Array<Map> all(){
|
||||||
return allMaps;
|
return allMaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns a list of only custo maps.*/
|
/**Returns a list of only custom maps.*/
|
||||||
public Array<Map> customMaps(){
|
public Array<Map> customMaps(){
|
||||||
returnArray.clear();
|
returnArray.clear();
|
||||||
for(Map map : allMaps){
|
for(Map map : allMaps){
|
||||||
@ -57,32 +69,61 @@ public class Maps implements Disposable{
|
|||||||
public void load(){
|
public void load(){
|
||||||
try {
|
try {
|
||||||
for (String name : defaultMapNames) {
|
for (String name : defaultMapNames) {
|
||||||
loadMap(Gdx.files.internal("maps/" + name + "." + mapExtension), false);
|
FileHandle file = Gdx.files.internal("maps/" + name + "." + mapExtension);
|
||||||
|
loadMap(file.nameWithoutExtension(), file::read, false);
|
||||||
}
|
}
|
||||||
}catch (IOException e){
|
}catch (IOException e){
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(FileHandle file : customMapDirectory.list()){
|
loadCustomMaps();
|
||||||
try{
|
|
||||||
if(file.extension().toLowerCase().equals(mapExtension)) loadMap(file, true);
|
|
||||||
}catch (IOException e){
|
|
||||||
Log.err("Failed to load custom map file '{0}'!", file);
|
|
||||||
Log.err(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadMap(FileHandle file, boolean custom) throws IOException{
|
public void saveAndReload(String name, MapTileData data, ObjectMap<String, String> tags){
|
||||||
DataInputStream ds = new DataInputStream(file.read());
|
FileHandle file = customMapDirectory.child(name + "." + mapExtension);
|
||||||
MapMeta meta = MapIO.readMapMeta(ds);
|
//todo implement
|
||||||
Map map = new Map(file.nameWithoutExtension(), meta, custom);
|
|
||||||
if(!headless) map.texture = new Texture(MapIO.generatePixmap(MapIO.readTileData(ds, meta, true)));
|
|
||||||
|
|
||||||
maps.put(map.name, map);
|
|
||||||
allMaps.add(map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadMap(String name, Supplier<InputStream> supplier, boolean custom) throws IOException{
|
||||||
|
try(DataInputStream ds = new DataInputStream(supplier.get())) {
|
||||||
|
MapMeta meta = MapIO.readMapMeta(ds);
|
||||||
|
Map map = new Map(name, meta, custom, supplier);
|
||||||
|
if (!headless) map.texture = new Texture(MapIO.generatePixmap(MapIO.readTileData(ds, meta, true)));
|
||||||
|
|
||||||
|
maps.put(map.name, map);
|
||||||
|
allMaps.add(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadCustomMaps(){
|
||||||
|
if(!gwt){
|
||||||
|
for(FileHandle file : customMapDirectory.list()){
|
||||||
|
try{
|
||||||
|
if(file.extension().equalsIgnoreCase(mapExtension)){
|
||||||
|
loadMap(file.nameWithoutExtension(), file::read, true);
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
Log.err("Failed to load custom map file '{0}'!", file);
|
||||||
|
Log.err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
Array<String> maps = json.fromJson(Array.class, Settings.getString("custom-maps", "{}"));
|
||||||
|
|
||||||
|
for(String name : maps){
|
||||||
|
try{
|
||||||
|
String data = Settings.getString("map-data-" + name);
|
||||||
|
byte[] bytes = data.getBytes();
|
||||||
|
loadMap(name, () -> new ByteArrayInputStream(bytes), true);
|
||||||
|
}catch (Exception e){
|
||||||
|
Log.err("Failed to load custom map '{0}'!", name);
|
||||||
|
Log.err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public class DebugFragment implements Fragment {
|
|||||||
abottom().aleft();
|
abottom().aleft();
|
||||||
|
|
||||||
new table("pane"){{
|
new table("pane"){{
|
||||||
defaults().fillX();
|
defaults().fillX().width(100f);
|
||||||
|
|
||||||
new label("Debug");
|
new label("Debug");
|
||||||
row();
|
row();
|
||||||
|
Reference in New Issue
Block a user