Removed old maps, re-added map editor, broke compilation again

This commit is contained in:
Anuken 2018-03-18 22:30:33 -04:00
parent 172ac78466
commit 0f8168324f
42 changed files with 1770 additions and 130 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -1,95 +0,0 @@
{
"maps": [
{
"id": 0,
"name": "maze",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 1,
"name": "fortress",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 2,
"name": "sinkhole",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 3,
"name": "caves",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 4,
"name": "volcano",
"visible": true,
"flipBase": true,
"backgroundColor": "646464"
},
{
"id": 5,
"name": "caldera",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 6,
"name": "scorch",
"visible": true,
"flipBase": false,
"backgroundColor": "e5d8bb"
},
{
"id": 7,
"name": "desert",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 8,
"name": "island",
"visible": true,
"flipBase": false,
"backgroundColor": "e5d8bb"
},
{
"id": 9,
"name": "grassland",
"visible": true,
"flipBase": false,
"backgroundColor": "5ab464"
},
{
"id": 10,
"name": "tundra",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 11,
"name": "spiral",
"visible": true,
"flipBase": false,
"backgroundColor": "f7feff"
},
{
"id": 12,
"name": "tutorial",
"visible": false,
"flipBase": false,
"backgroundColor": "646464"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -1,5 +1,5 @@
#Autogenerated file. Do not modify. #Autogenerated file. Do not modify.
#Sat Mar 17 21:20:30 EDT 2018 #Sat Mar 17 21:49:13 EDT 2018
version=release version=release
androidBuildCode=538 androidBuildCode=538
name=Mindustry name=Mindustry

View File

@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.Colors;
import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Align;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.editor.MapEditorDialog;
import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.ui.dialogs.*; import io.anuke.mindustry.ui.dialogs.*;
import io.anuke.mindustry.ui.fragments.*; import io.anuke.mindustry.ui.fragments.*;
@ -43,7 +44,7 @@ public class UI extends SceneModule{
public PausedDialog paused; public PausedDialog paused;
public SettingsMenuDialog settings; public SettingsMenuDialog settings;
public ControlsDialog controls; public ControlsDialog controls;
public FloatingDialog editor; //TODO change back to map editor dialog public MapEditorDialog editor;
public LanguageDialog language; public LanguageDialog language;
public BansDialog bans; public BansDialog bans;
public AdminsDialog admins; public AdminsDialog admins;
@ -143,7 +144,7 @@ public class UI extends SceneModule{
@Override @Override
public void init(){ public void init(){
(editor = new FloatingDialog("The editor is currently broken.")).addCloseButton(); editor = new MapEditorDialog();
controls = new ControlsDialog(); controls = new ControlsDialog();
restart = new RestartDialog(); restart = new RestartDialog();
join = new JoinDialog(); join = new JoinDialog();

View File

@ -0,0 +1,39 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.utils.Disposable;
import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import java.nio.ByteBuffer;
public class DrawOperation implements Disposable{
/**Data to apply operation to.*/
MapTileData data;
/**Format:
* position (int)
* packed data FROM (use TileDataWriter's read/write methods)
* packed data TO (use TileDataWriter's read/write methods)
*/
ByteBuffer operation;
TileDataWriter writer = new TileDataWriter();
public DrawOperation(MapTileData data){
this.data = data;
}
public void set(ByteBuffer operation) {
this.operation = operation;
}
public void undo() {
//TODO implement
}
public void redo() {
//TODO implement
}
@Override
public void dispose() {}
}

View File

@ -0,0 +1,94 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntSet;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.types.Floor;
import static io.anuke.mindustry.Vars.ui;
public enum EditorTool{
pick{
public void touched(MapEditor editor, int x, int y){
TileDataWriter writer = editor.getMap().readAt(x, y);
Block block = Block.getByID(writer.wall == 0 ? writer.floor : writer.wall);
editor.setDrawBlock(block);
ui.editor.updateSelectedBlock();
}
},
pencil{
{
edit = true;
}
public void touched(MapEditor editor, int x, int y){
editor.draw(x, y);
}
},
line{
{
}
},
fill{
{
edit = true;
}
public void touched(MapEditor editor, int x, int y){
//TODO select floor/block properly instead of using this method!
boolean floor = editor.getDrawBlock() instanceof Floor;
TileDataWriter writer = editor.getMap().readAt(x, y);
byte dest = floor ? writer.floor : writer.wall;
int width = editor.getMap().width();
int height = editor.getMap().height();
IntSet set = new IntSet();
IntArray points = new IntArray();
points.add(asInt(x, y, editor.getMap().width()));
while(points.size != 0){
int pos = points.pop();
int px = pos % width;
int py = pos / width;
set.add(pos);
writer = editor.getMap().readAt(px, py);
if((floor ? writer.floor : writer.wall) == dest){
if(floor)
writer.floor = dest;
else
writer.wall = dest;
editor.getMap().write(px, py, writer);
editor.renderer().updatePoint(px, py);
if(px > 0 && !set.contains(asInt(px - 1, py, width))) points.add(asInt(px - 1, py, width));
if(py > 0 && !set.contains(asInt(px, py - 1, width))) points.add(asInt(px, py - 1, width));
if(px < width - 1 && !set.contains(asInt(px + 1, py, width))) points.add(asInt(px + 1, py, width));
if(py < height - 1 && !set.contains(asInt(px, py + 1, width))) points.add(asInt(px, py + 1, width));
}
}
}
int asInt(int x, int y, int width){
return x+y*width;
}
boolean colorEquals(int a, int b){
return a == b;
}
},
zoom;
boolean edit;
public void touched(MapEditor editor, int x, int y){
}
}

View File

@ -0,0 +1,81 @@
package io.anuke.mindustry.editor;
import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.types.Floor;
import io.anuke.ucore.util.Mathf;
public class MapEditor{
public static final int minMapSize = 128, maxMapSize = 512;
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15};
private MapTileData map;
private MapRenderer renderer = new MapRenderer(this);
private int brushSize = 1;
private Block drawBlock = Blocks.stone;
public MapEditor(){
}
public MapTileData getMap(){
return map;
}
public void beginEdit(MapTileData map){
drawBlock = Blocks.stone;
this.map = map;
this.brushSize = 1;
}
public Block getDrawBlock(){
return drawBlock;
}
public void setDrawBlock(Block block){
this.drawBlock = block;
}
public void setBrushSize(int size){
this.brushSize = size;
}
public int getBrushSize() {
return brushSize;
}
public void draw(int dx, int dy){
if(dx < 0 || dy < 0 || dx >= map.width() || dy >= map.height()){
return;
}
TileDataWriter writer = map.readAt(dx, dy);
if(drawBlock instanceof Floor){
writer.floor = (byte)drawBlock.id;
}else{
writer.wall = (byte)drawBlock.id;
}
for(int rx = -brushSize + 1; rx <= brushSize - 1; rx ++){
for(int ry = -brushSize + 1; ry <= brushSize - 1; ry ++){
if(Mathf.dst(rx, ry) < brushSize){
map.write(dx + rx, dy + ry, writer);
renderer.updatePoint(dx + rx, dy + ry);
}
}
}
}
public MapRenderer renderer() {
return renderer;
}
public void resize(int width, int height){
map = new MapTileData(width, height);
renderer.resize(width, height);
}
}

View File

@ -0,0 +1,421 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.ColorMapper.BlockPair;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.builders.build;
import io.anuke.ucore.scene.builders.imagebutton;
import io.anuke.ucore.scene.builders.label;
import io.anuke.ucore.scene.builders.table;
import io.anuke.ucore.scene.ui.*;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Bundles;
import static io.anuke.mindustry.Vars.gwt;
import static io.anuke.mindustry.Vars.ui;
public class MapEditorDialog extends Dialog{
private MapEditor editor;
private MapView view;
private MapGenerateDialog dialog;
private MapLoadDialog loadDialog;
private MapSaveDialog saveDialog;
private MapResizeDialog resizeDialog;
private ScrollPane pane;
//private FileChooser openFile, saveFile;
private boolean saved = false;
private ButtonGroup<ImageButton> blockgroup;
public MapEditorDialog(){
super("$text.mapeditor", "dialog");
if(gwt) return;
editor = new MapEditor();
dialog = new MapGenerateDialog(editor);
view = new MapView(editor);
/*
openFile = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> {
ui.loadfrag.show();
Timers.run(3f, () -> {
try{
Pixmap pixmap = new Pixmap(file);
if(verifySize(pixmap)){
editor.setPixmap(pixmap);
view.clearStack();
}else{
ui.showError(Bundles.format("text.editor.badsize", Arrays.toString(MapEditor.validMapSizes)));
}
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
Log.err(e);
}
ui.loadfrag.hide();
});
});
saveFile = new FileChooser("$saveimage", false, file -> {
if(!file.extension().toLowerCase().equals(".png")){
file = file.parent().child(file.nameWithoutExtension() + ".png");
}
FileHandle result = file;
ui.loadfrag.show();
Timers.run(3f, () -> {
try{
Pixmaps.write(editor.pixmap(), result);
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
if(!android) Log.err(e);
}
ui.loadfrag.hide();
});
});*/
/*
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) -> {
if(!(editor.getMap().width() == x && editor.getMap().height() == y)){
ui.loadfrag.show();
Timers.run(10f, () -> {
editor.resize(x, y);
view.clearStack();
ui.loadfrag.hide();
});
}
});
/*
saveDialog = new MapSaveDialog(name -> {
ui.loadfrag.show();
if(verifyMap()){
saved = true;
String before = editor.getMap().name;
editor.getMap().name = name;
Timers.run(10f, () -> {
world.maps().saveAndReload(editor.getMap(), editor.pixmap());
loadDialog.rebuild();
ui.loadfrag.hide();
view.clearStack();
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{
ui.loadfrag.hide();
}
});*/
setFillParent(true);
clearChildren();
margin(0);
build.begin(this);
build();
build.end();
tapped(() -> {
Element e = Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true);
if(e == null || !e.isDescendantOf(pane)) Core.scene.setScrollFocus(null);
});
update(() -> {
if(Core.scene != null && Core.scene.getKeyboardFocus() == this){
doInput();
}
});
shown(() -> {
saved = true;
editor.beginEdit(new MapTileData(256, 256));
blockgroup.getButtons().get(2).setChecked(true);
Core.scene.setScrollFocus(view);
view.clearStack();
Timers.runTask(10f, Platform.instance::updateRPC);
});
hidden(() -> Platform.instance.updateRPC());
}
public MapView getView() {
return view;
}
public void resetSaved(){
saved = false;
}
public void updateSelectedBlock(){
Block block = editor.getDrawBlock();
int i = 0;
for(BlockPair pair : ColorMapper.getPairs()){
if(pair.wall == block || (pair.wall == Blocks.air && pair.floor == block)){
blockgroup.getButtons().get(i).setChecked(true);
break;
}
i++;
}
}
public boolean hasPane(){
return Core.scene.getScrollFocus() == pane;
}
public void build(){
new table(){{
float isize = 16*2f;
aleft();
new table(){{
defaults().growY().width(130f).padBottom(-6);
new imagebutton("icon-terrain", isize, () ->
dialog.show()
).text("$text.editor.generate");
row();
new imagebutton("icon-resize", isize, () ->
resizeDialog.show()
).text("$text.editor.resize").padTop(4f);
row();
new imagebutton("icon-load-map", isize, () ->
loadDialog.show()
).text("$text.editor.loadmap");
row();
new imagebutton("icon-save-map", isize, ()->
saveDialog.show()
).text("$text.editor.savemap");
row();
/*
new imagebutton("icon-load-image", isize, () ->
openFile.show()
).text("$text.editor.loadimage");
row();
new imagebutton("icon-save-image", isize, () ->
saveFile.show()
).text("$text.editor.saveimage");*/
row();
new imagebutton("icon-back", isize, () -> {
if(!saved){
ui.showConfirm("$text.confirm", "$text.editor.unsaved",
MapEditorDialog.this::hide);
}else{
hide();
}
}).padBottom(0).text("$text.back");
}}.left().growY().end();
new table("button"){{
add(view).grow();
}}.grow().end();
new table(){{
Table tools = new Table("button");
tools.top();
tools.marginTop(0).marginBottom(6);
ButtonGroup<ImageButton> group = new ButtonGroup<>();
int i = 1;
tools.defaults().size(53f, 58f).padBottom(-6);
ImageButton undo = tools.addImageButton("icon-undo", 16*2f, () -> view.undo()).get();
ImageButton redo = tools.addImageButton("icon-redo", 16*2f, () -> view.redo()).get();
ImageButton grid = tools.addImageButton("icon-grid", "toggle", 16*2f, () -> view.setGrid(!view.isGrid())).get();
undo.setDisabled(() -> !view.getStack().canUndo());
redo.setDisabled(() -> !view.getStack().canRedo());
undo.update(() -> undo.getImage().setColor(undo.isDisabled() ? Color.GRAY : Color.WHITE));
redo.update(() -> redo.getImage().setColor(redo.isDisabled() ? Color.GRAY : Color.WHITE));
grid.update(() -> grid.setChecked(view.isGrid()));
for(EditorTool tool : EditorTool.values()){
ImageButton button = new ImageButton("icon-" + tool.name(), "toggle");
button.clicked(() -> view.setTool(tool));
button.resizeImage(16*2f);
button.update(() -> button.setChecked(view.getTool() == tool));
group.add(button);
if (tool == EditorTool.pencil)
button.setChecked(true);
tools.add(button).padBottom(-6f);
if(i++ % 4 == 1) tools.row();
}
add(tools).width(53*4).padBottom(-6);
row();
new table("button"){{
margin(10f);
Slider slider = new Slider(0, MapEditor.brushSizes.length-1, 1, false);
slider.moved(f -> editor.setBrushSize(MapEditor.brushSizes[(int)(float)f]));
new label(() -> Bundles.format("text.editor.brushsize", MapEditor.brushSizes[(int)slider.getValue()])).left();
row();
add(slider).growX().padTop(4f);
}}.growX().padBottom(-6).end();
row();
/*
new table("button"){{
get().addCheck("$text.oregen", b -> editor.getMap().oreGen = b)
.update(c -> c.setChecked(editor.getMap().oreGen)).padTop(3).padBottom(3);
}}.growX().padBottom(-6).end();*/
row();
addBlockSelection(get());
row();
}}.right().growY().end();
}}.grow().end();
}
private void doInput(){
//tool select
for(int i = 0; i < EditorTool.values().length; i ++){
int code = i == 0 ? 5 : i;
if(Inputs.keyTap("weapon_" + code)){
view.setTool(EditorTool.values()[i]);
break;
}
}
//ctrl keys (undo, redo, save)
if(Inputs.keyDown(Keys.CONTROL_LEFT)){
if(Inputs.keyTap(Keys.Z)){
view.undo();
}
if(Inputs.keyTap(Keys.Y)){
view.redo();
}
if(Inputs.keyTap(Keys.S)){
saveDialog.save();
}
if(Inputs.keyTap(Keys.G)){
view.setGrid(!view.isGrid());
}
}
}
private boolean verifyMap(){
//TODO make sure both teams have cores or something
/*
int psc = ColorMapper.getColor(SpecialBlocks.playerSpawn);
int esc = ColorMapper.getColor(SpecialBlocks.enemySpawn);
int playerSpawns = 0;
int enemySpawns = 0;
Pixmap pix = editor.pixmap();
for(int x = 0; x < pix.getWidth(); x ++){
for(int y = 0; y < pix.getHeight(); y ++){
int i = pix.getPixel(x, y);
if(i == psc) playerSpawns ++;
if(i == esc) enemySpawns ++;
}
}
if(playerSpawns == 0){
ui.showError("$text.editor.noplayerspawn");
return false;
}else if(playerSpawns > 1){
ui.showError("$text.editor.manyplayerspawns");
return false;
}
if(enemySpawns > MapEditor.maxSpawnpoints){
ui.showError(Bundles.format("text.editor.manyenemyspawns", MapEditor.maxSpawnpoints));
return false;
}*/
return true;
}
private void addBlockSelection(Table table){
Table content = new Table();
pane = new ScrollPane(content, "volume");
pane.setScrollingDisabled(true, false);
pane.setFadeScrollBars(false);
pane.setOverscroll(true, false);
ButtonGroup<ImageButton> group = new ButtonGroup<>();
blockgroup = group;
int i = 0;
for(BlockPair pair : ColorMapper.getPairs()){
Block block = pair.wall == Blocks.air ? pair.floor : pair.wall;
ImageButton button = new ImageButton(Draw.hasRegion(block.name) ? Draw.region(block.name) : Draw.region(block.name + "1"), "toggle");
button.clicked(() -> editor.setDrawBlock(block));
button.resizeImage(8*4f);
group.add(button);
content.add(button).pad(4f).size(53f, 58f);
if(i++ % 2 == 1){
content.row();
}
}
group.getButtons().get(2).setChecked(true);
Table extra = new Table("button");
extra.labelWrap(() -> editor.getDrawBlock().formalName).width(180f).center();
table.add(extra).padBottom(-6).growX();
table.row();
table.add(pane).growY().fillX();
}
}

View File

@ -0,0 +1,244 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.OrderedMap;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.ColorMapper.BlockPair;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.types.Floor;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.noise.RidgedPerlin;
import io.anuke.ucore.noise.Simplex;
import io.anuke.ucore.util.Mathf;
public class MapFilter{
private ObjectMap<String, GenPref> prefs = map(
pref("replace", "whether to replace blocks"),
pref("terrain", "generate new terrain"),
pref("circle", "generate terrain in a circle"),
pref("distort", "distort the map image"),
pref("sand", "add patches of sand"),
pref("grass", "add patches of grass"),
pref("stone", "add patches of stone"),
pref("blackstone", "add patches of black stone"),
pref("allgrass", "fill map with grass"),
pref("allsnow", "fill map with snow"),
pref("allsand", "fill map with sand"),
pref("water", "add lakes"),
pref("oil", "add oil lakes"),
pref("lavariver", "add lava rivers"),
pref("slavariver", "ad small lava rivers"),
pref("river", "add rivers"),
pref("iceriver", "add frozen rivers"),
pref("oilriver", "add oil rivers")
);
private Simplex sim = new Simplex();
private RidgedPerlin rid = new RidgedPerlin(1, 10, 20f);
private RidgedPerlin rid2 = new RidgedPerlin(1, 6, 1f);
private RidgedPerlin rid3 = new RidgedPerlin(1, 6, 1f);
public MapFilter(){
prefs.get("replace").enabled = true;
prefs.get("terrain").enabled = true;
randomize();
}
public void randomize(){
sim.setSeed(Mathf.random(999999));
rid.setSeed(Mathf.random(999999));
rid2.setSeed(Mathf.random(999999));
rid3.setSeed(Mathf.random(999999));
}
public ObjectMap<String, GenPref> getPrefs(){
return prefs;
}
public Pixmap process(Pixmap pixmap){
if(prefs.get("terrain").enabled){
for(int x = 0; x < pixmap.getWidth(); x++){
for(int y = 0; y < pixmap.getHeight(); y++){
float dist = Vector2.dst((float) x / pixmap.getWidth(), (float) y / pixmap.getHeight(), 0.5f, 0.5f) * 2f;
double noise = sim.octaveNoise2D(6, 0.6, 1 / 180.0, x, y + 9999) / (prefs.get("circle").enabled ? 1.7 : 1f) + dist / 10f;
if(dist > 0.8){
noise += 2 * (dist - 0.8);
}
Block block = noise > 0.6 ? Blocks.stoneblock : Blocks.stone;
pixmap.drawPixel(x, y, ColorMapper.getColor(block));
}
}
}
Pixmap src = Pixmaps.copy(pixmap);
for(int x = 0; x < pixmap.getWidth(); x++){
for(int y = 0; y < pixmap.getHeight(); y++){
int dx = 0, dy = 0;
if(prefs.get("distort").enabled){
double intensity = 12;
double scale = 80;
double octaves = 4;
double falloff = 0.6;
double nx = (sim.octaveNoise2D(octaves, falloff, 1 / scale, x, y) - 0.5f) * intensity;
double ny = (sim.octaveNoise2D(octaves, falloff, 1 / scale, x, y + 99999) - 0.5f) * intensity;
dx = (int) nx;
dy = (int) ny;
}
int pix = src.getPixel(x + dx, y + dy);
BlockPair pair = ColorMapper.get(pix);
Block block = pair == null ? null : pair.wall == Blocks.air ? pair.floor : pair.wall;
if(block == null)
continue;
boolean floor = block instanceof Floor;
double noise = sim.octaveNoise2D(4, 0.6, 1 / 170.0, x, y) + sim.octaveNoise2D(1, 1.0, 1 / 5.0, x, y) / 18.0;
double nwater = sim.octaveNoise2D(1, 1.0, 1 / 130.0, x, y);
noise += nwater / 5.0;
double noil = sim.octaveNoise2D(1, 1.0, 1 / 150.0, x + 9999, y) + sim.octaveNoise2D(1, 1.0, 1 / 2.0, x, y) / 290.0;
if(!floor || prefs.get("replace").enabled){
if(prefs.get("allgrass").enabled){
block = floor ? Blocks.grass : Blocks.grassblock;
}else if(prefs.get("allsnow").enabled){
block = floor ? Blocks.snow : Blocks.snowblock;
}else if(prefs.get("allsand").enabled){
block = floor ? Blocks.sand : Blocks.sandblock;
}else if(prefs.get("replace").enabled){
block = floor ? Blocks.stone : Blocks.stoneblock;
}
if(noise > 0.7 && prefs.get("grass").enabled){
block = floor ? Blocks.grass : Blocks.grassblock;
}
if(noise > 0.7 && prefs.get("blackstone").enabled){
block = floor ? Blocks.blackstone : Blocks.blackstoneblock;
}
if(noise > 0.7 && prefs.get("sand").enabled){
block = floor ? Blocks.sand : Blocks.sandblock;
}
if(noise > 0.8 && prefs.get("stone").enabled){
block = floor ? Blocks.stone : Blocks.stoneblock;
}
}
if(floor){
if(nwater > 0.93 && prefs.get("water").enabled){
block = Blocks.water;
if(nwater > 0.943){
block = Blocks.deepwater;
}
}
if(noil > 0.95 && prefs.get("oil").enabled){
block = Blocks.dirt;
if(noil > 0.955){
block = Blocks.oil;
}
}
}
if(floor && prefs.get("lavariver").enabled){
double lava = rid.getValue(x, y, 1 / 100f);
double t = 0.6;
if(lava > t){
block = Blocks.lava;
}else if(lava > t - 0.2){
block = Blocks.blackstone;
}
}
if(floor && prefs.get("slavariver").enabled){
double lava = rid.getValue(x, y, 1 / 40f);
double t = 0.7;
if(lava > t){
block = Blocks.lava;
}else if(lava > t - 0.3){
block = Blocks.blackstone;
}
}
if(floor && prefs.get("oilriver").enabled){
double lava = rid3.getValue(x, y, 1 / 100f);
double t = 0.9;
if(lava > t){
block = Blocks.oil;
}else if(lava > t - 0.2){
block = Blocks.dirt;
}
}
if(floor && prefs.get("river").enabled){
double riv = rid2.getValue(x, y, 1 / 140f);
double t = 0.4;
if(riv > t + 0.1){
block = Blocks.deepwater;
}else if(riv > t){
block = Blocks.water;
}else if(riv > t - 0.2){
block = Blocks.grass;
}
}
if(floor && prefs.get("iceriver").enabled){
double riv = rid2.getValue(x, y, 1 / 140f);
double t = 0.4;
if(riv > t + 0.1){
block = Blocks.ice;
}else if(riv > t){
block = Blocks.ice;
}else if(riv > t - 0.2){
block = Blocks.snow;
}
}
pixmap.drawPixel(x, y, ColorMapper.getColor(block));
}
}
src.dispose();
return pixmap;
}
private static OrderedMap<String, GenPref> map(GenPref...objects){
OrderedMap<String, GenPref> prefs = new OrderedMap<>();
for(int i = 0; i < objects.length; i ++){
GenPref pref = (GenPref)objects[i];
prefs.put(pref.name, pref);
}
return prefs;
}
private GenPref pref(String name, String desc){
return new GenPref(name, desc);
}
class GenPref{
public final String name;
public final String description;
public boolean enabled;
GenPref(String name, String description){
this.name = name;
this.description = description;
}
}
}

View File

@ -0,0 +1,105 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Scaling;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.editor.MapFilter.GenPref;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.scene.style.TextureRegionDrawable;
import io.anuke.ucore.scene.ui.CheckBox;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.ScrollPane;
import io.anuke.ucore.scene.ui.layout.Stack;
import io.anuke.ucore.scene.ui.layout.Table;
public class MapGenerateDialog extends FloatingDialog{
private MapEditor editor;
private Image image;
private boolean loading;
public MapGenerateDialog(MapEditor editor) {
super("$text.editor.generate");
this.editor = editor;
Stack stack = new Stack();
stack.add(image = new BorderImage());
Image loadImage = new Image("icon-loading");
loadImage.setScaling(Scaling.none);
loadImage.setScale(3f);
loadImage.update(() -> loadImage.setOrigin(Align.center));
loadImage.setVisible(() -> loading);
Image next = new Image("white");
next.setScaling(Scaling.fit);
next.setColor(0, 0, 0, 0.6f);
next.setVisible(() -> loading);
stack.add(next);
stack.add(loadImage);
content().add(stack).grow();
image.setScaling(Scaling.fit);
Table preft = new Table();
preft.left();
preft.margin(4f).marginRight(25f);
for(GenPref pref : editor.getFilter().getPrefs().values()){
CheckBox box = new CheckBox(pref.name);
box.setChecked(pref.enabled);
box.changed(() -> pref.enabled = box.isChecked());
preft.add(box).pad(4f).left();
preft.row();
}
ScrollPane pane = new ScrollPane(preft, "volume");
pane.setFadeScrollBars(false);
pane.setScrollingDisabled(true, false);
content().add(pane).fillY();
buttons().defaults().size(170f, 50f).pad(4f);
buttons().addButton("$text.back", this::hide);
buttons().addButton("$text.randomize", () ->{
editor.getFilter().randomize();
apply();
});
buttons().addButton("$text.update", this::apply);
buttons().addButton("$text.apply", () ->{
ui.loadfrag.show();
Timers.run(3f, () ->{
Pixmap copy = Pixmaps.copy(editor.pixmap());
editor.applyFilter();
ui.editor.getView().push(copy, Pixmaps.copy(editor.pixmap()));
ui.loadfrag.hide();
ui.editor.resetSaved();
hide();
});
});
shown(() ->{
loading = true;
Timers.run(30f, () -> {
editor.applyFilterPreview();
image.setDrawable(new TextureRegionDrawable(new TextureRegion(editor.getFilterTexture())));
loading = false;
});
});
}
private void apply(){
loading = true;
Timers.run(3f, () -> {
editor.applyFilterPreview();
loading = false;
});
}
}

View File

@ -0,0 +1,73 @@
package io.anuke.mindustry.editor;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.scene.ui.ButtonGroup;
import io.anuke.ucore.scene.ui.ScrollPane;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.layout.Table;
import static io.anuke.mindustry.Vars.world;
public class MapLoadDialog extends FloatingDialog{
private Map selected = world.maps().getMap(0);
public MapLoadDialog(Consumer<Map> loader) {
super("$text.editor.loadmap");
shown(this::rebuild);
rebuild();
TextButton button = new TextButton("$text.load");
button.setDisabled(() -> selected == null);
button.clicked(() -> {
if (selected != null) {
loader.accept(selected);
hide();
}
});
buttons().defaults().size(200f, 50f);
buttons().addButton("$text.cancel", this::hide);
buttons().add(button);
}
public void rebuild(){
content().clear();
selected = world.maps().getMap(0);
ButtonGroup<TextButton> group = new ButtonGroup<>();
int maxcol = 3;
int i = 0;
Table table = new Table();
table.defaults().size(200f, 90f).pad(4f);
table.margin(10f);
ScrollPane pane = new ScrollPane(table, "horizontal");
pane.setFadeScrollBars(false);
for (Map map : world.maps().list()) {
if (!map.visible) continue;
TextButton button = new TextButton(map.localized(), "toggle");
button.add(new BorderImage(map.texture, 2f)).size(16 * 4f);
button.getCells().reverse();
button.clicked(() -> selected = map);
button.getLabelCell().grow().left().padLeft(5f);
group.add(button);
table.add(button);
if (++i % maxcol == 0) table.row();
}
content().add("$text.editor.loadmap");
content().row();
content().add(pane);
}
}

View File

@ -0,0 +1,103 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.utils.IntSet;
import com.badlogic.gdx.utils.IntSet.IntSetIterator;
import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.graphics.CacheBatch;
import io.anuke.ucore.graphics.Draw;
import static io.anuke.mindustry.Vars.tilesize;
public class MapRenderer {
private static final int chunksize = 32;
private CacheBatch batch;
private int[][] chunks;
private IntSet updates = new IntSet();
private MapEditor editor;
public MapRenderer(MapEditor editor){
this.editor = editor;
}
public void resize(int width, int height){
batch = new CacheBatch(width * height * 3);
chunks = new int[width / chunksize][height / chunksize];
updates.clear();
updateAll();
}
public void draw(){
Graphics.end();
Graphics.useBatch(batch);
IntSetIterator it = updates.iterator();
int i = it.next();
for(; it.hasNext; i = it.next()){
int x = i % chunks.length;
int y = i / chunks.length;
render(x, y, chunks[x][y]);
}
updates.clear();
Graphics.popBatch();
Gdx.gl.glEnable(GL20.GL_BLEND);
batch.beginDraw();
for(int x = 0; x < chunks.length; x ++){
for(int y = 0; y < chunks[0].length; y ++){
int id = chunks[x][y];
batch.drawCache(id);
}
}
batch.endDraw();
Graphics.begin();
}
public void updatePoint(int x, int y){
x /= chunksize;
y /= chunksize;
updates.add(x + y * chunks.length);
}
public void updateAll(){
for(int x = 0; x < chunks.length; x ++){
for(int y = 0; y < chunks[0].length; y ++){
render(x, y, chunks[x][y]);
}
}
}
private void render(int chunkx, int chunky, int previousID){
if(previousID == -1){
batch.begin();
}else{
batch.begin(previousID);
}
for(int x = 0; x < chunkx; x ++){
for(int y = 0; y < chunky; y ++){
int wx = chunkx*chunksize + x;
int wy = chunky*chunksize + y;
TileDataWriter data = editor.getMap().readAt(wx, wy);
Block floor = Block.getByID(data.floor);
Block wall = Block.getByID(data.wall);
if(floor != Blocks.air) Draw.rect(floor.name, wx * tilesize, wy * tilesize);
if(floor != Blocks.air) Draw.rect(wall.name, wx * tilesize, wy * tilesize);
}
}
batch.end();
chunks[chunkx][chunky] = batch.getLastCache();
}
}

View File

@ -0,0 +1,67 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.utils.Align;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.ucore.function.BiConsumer;
import io.anuke.ucore.scene.ui.ButtonGroup;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.layout.Table;
public class MapResizeDialog extends FloatingDialog{
int width, height;
public MapResizeDialog(MapEditor editor, BiConsumer<Integer, Integer> cons){
super("$text.editor.resizemap");
shown(() -> {
content().clear();
Pixmap pix = editor.pixmap();
width = pix.getWidth();
height = pix.getHeight();
Table table = new Table();
for(int d = 0; d < 2; d ++){
boolean w = d == 0;
int curr = d == 0 ? pix.getWidth() : pix.getHeight();
int idx = 0;
for(int i = 0; i < MapEditor.validMapSizes.length; i ++)
if(MapEditor.validMapSizes[i] == curr) idx = i;
table.add(d == 0 ? "$text.width": "$text.height").padRight(8f);
ButtonGroup<TextButton> group = new ButtonGroup<>();
for(int i = 0; i < MapEditor.validMapSizes.length; i ++){
int size = MapEditor.validMapSizes[i];
TextButton button = new TextButton(size + "", "toggle");
button.clicked(() -> {
if(w)
width = size;
else
height = size;
});
group.add(button);
if(i == idx) button.setChecked(true);
table.add(button).size(100f, 54f).pad(2f);
}
table.row();
}
content().label(() ->
width + height > 512 ? "$text.editor.resizebig" : ""
).get().setAlignment(Align.center, Align.center);
content().row();
content().add(table);
});
buttons().defaults().size(200f, 50f);
buttons().addButton("$text.cancel", this::hide);
buttons().addButton("$text.editor.resize", () -> {
cons.accept(width, height);
hide();
});
}
}

View File

@ -0,0 +1,75 @@
package io.anuke.mindustry.editor;
import io.anuke.mindustry.io.Map;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.TextField;
import static io.anuke.mindustry.Vars.ui;
import static io.anuke.mindustry.Vars.world;
public class MapSaveDialog extends FloatingDialog{
private TextField field;
private Consumer<String> listener;
public MapSaveDialog(Consumer<String> cons){
super("$text.editor.savemap");
field = new TextField();
listener = cons;
Platform.instance.addDialog(field);
shown(() -> {
content().clear();
content().label(() ->{
Map map = world.maps().getByName(field.getText());
if(map != null){
if(map.custom){
return "$text.editor.overwrite";
}else{
return "$text.editor.failoverwrite";
}
}
return "";
}).colspan(2);
content().row();
content().add("$text.editor.mapname").padRight(14f);
content().add(field).size(220f, 48f);
});
buttons().defaults().size(200f, 50f).pad(2f);
buttons().addButton("$text.cancel", this::hide);
TextButton button = new TextButton("$text.save");
button.clicked(() -> {
if(!invalid()){
cons.accept(field.getText());
hide();
}
});
button.setDisabled(this::invalid);
buttons().add(button);
}
public void save(){
if(!invalid()){
listener.accept(field.getText());
}else{
ui.showError("$text.editor.failoverwrite");
}
}
public void setFieldText(String text){
field.setText(text);
}
private boolean invalid(){
if(field.getText().isEmpty()){
return true;
}
Map map = world.maps().getByName(field.getText());
return map != null && !map.custom;
}
}

View File

@ -0,0 +1,328 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Colors;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.math.Bresenham2;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.ui.GridImage;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.event.InputEvent;
import io.anuke.ucore.scene.event.InputListener;
import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.ui.TextField;
import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Tmp;
import static io.anuke.mindustry.Vars.ui;
public class MapView extends Element implements GestureListener{
private MapEditor editor;
private EditorTool tool = EditorTool.pencil;
private OperationStack stack = new OperationStack();
private DrawOperation op;
private Pixmap current;
private Bresenham2 br = new Bresenham2();
private boolean updated = false;
private float offsetx, offsety;
private float zoom = 1f;
private boolean grid = false;
private GridImage image = new GridImage(0, 0);
private Vector2 vec = new Vector2();
private Rectangle rect = new Rectangle();
private boolean drawing;
private int lastx, lasty;
private int startx, starty;
public void setTool(EditorTool tool){
this.tool = tool;
}
public EditorTool getTool() {
return tool;
}
public void clearStack(){
stack.clear();
current = null;
}
public OperationStack getStack() {
return stack;
}
public void setGrid(boolean grid) {
this.grid = grid;
}
public boolean isGrid() {
return grid;
}
public void push(Pixmap previous, Pixmap add){
DrawOperation op = new DrawOperation(editor.pixmap());
op.add(previous, add);
stack.add(op);
this.current = add;
}
public void undo(){
if(stack.canUndo()){
stack.undo();
editor.updateTexture();
}
}
public void redo(){
if(stack.canRedo()){
stack.redo();
editor.updateTexture();
}
}
public MapView(MapEditor editor){
this.editor = editor;
Inputs.addProcessor(0, new GestureDetector(20, 0.5f, 2, 0.15f, this));
setTouchable(Touchable.enabled);
addListener(new InputListener(){
@Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
if(pointer != 0){
return false;
}
if(current == null){
current = Pixmaps.copy(editor.pixmap());
}
updated = false;
GridPoint2 p = project(x, y);
lastx = p.x;
lasty = p.y;
startx = p.x;
starty = p.y;
tool.touched(editor, p.x, p.y);
if(tool.edit){
updated = true;
ui.editor.resetSaved();
}
op = new DrawOperation(editor.pixmap());
drawing = true;
return true;
}
@Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
drawing = false;
GridPoint2 p = project(x, y);
if(tool == EditorTool.line){
ui.editor.resetSaved();
Array<GridPoint2> points = br.line(startx, starty, p.x, p.y);
for(GridPoint2 point : points){
editor.draw(point.x, point.y);
}
updated = true;
}
if(updated){
if(op == null) op = new DrawOperation(editor.pixmap());
Pixmap next = Pixmaps.copy(editor.pixmap());
op.add(current, next);
current = null;
stack.add(op);
op = null;
}
}
@Override
public void touchDragged (InputEvent event, float x, float y, int pointer) {
GridPoint2 p = project(x, y);
if(drawing && tool == EditorTool.pencil){
ui.editor.resetSaved();
Array<GridPoint2> points = br.line(lastx, lasty, p.x, p.y);
for(GridPoint2 point : points){
editor.draw(point.x, point.y);
}
updated = true;
}
lastx = p.x;
lasty = p.y;
}
});
}
@Override
public void act(float delta){
super.act(delta);
if(Core.scene.getKeyboardFocus() == null || !(Core.scene.getKeyboardFocus() instanceof TextField) &&
!Inputs.keyDown(Keys.CONTROL_LEFT)) {
float ax = Inputs.getAxis("move_x");
float ay = Inputs.getAxis("move_y");
offsetx -= ax * 15f / zoom;
offsety -= ay * 15f / zoom;
}
if(ui.editor.hasPane()) return;
zoom += Inputs.scroll()/10f * zoom;
clampZoom();
}
private void clampZoom(){
zoom = Mathf.clamp(zoom, 0.2f, 12f);
}
private GridPoint2 project(float x, float y){
float ratio = 1f / ((float)editor.pixmap().getWidth() / editor.pixmap().getHeight());
float size = Math.min(width, height);
float sclwidth = size * zoom;
float sclheight = size * zoom * ratio;
x = (x - getWidth()/2 + sclwidth/2 - offsetx*zoom) / sclwidth * editor.texture().getWidth();
y = (y - getHeight()/2 + sclheight/2 - offsety*zoom) / sclheight * editor.texture().getHeight();
return Tmp.g1.set((int)x, editor.texture().getHeight() - 1 - (int)y);
}
private Vector2 unproject(int x, int y){
float ratio = 1f / ((float)editor.pixmap().getWidth() / editor.pixmap().getHeight());
float size = Math.min(width, height);
float sclwidth = size * zoom;
float sclheight = size * zoom * ratio;
float px = ((float)x / editor.texture().getWidth()) * sclwidth + offsetx*zoom - sclwidth/2 + getWidth()/2;
float py = (float)((float)(editor.texture().getHeight() - 1 - y) / editor.texture().getHeight()) * sclheight
+ offsety*zoom - sclheight/2 + getHeight()/2;
return vec.set(px, py);
}
@Override
public void draw(Batch batch, float alpha){
float ratio = 1f / ((float)editor.pixmap().getWidth() / editor.pixmap().getHeight());
float size = Math.min(width, height);
float sclwidth = size * zoom;
float sclheight = size * zoom * ratio;
float centerx = x + width/2 + offsetx * zoom;
float centery = y + height/2 + offsety * zoom;
image.setImageSize(editor.pixmap().getWidth(), editor.pixmap().getHeight());
batch.flush();
boolean pop = ScissorStack.pushScissors(rect.set(x + width/2 - size/2, y + height/2 - size/2, size, size));
batch.draw(editor.texture(), centerx - sclwidth/2, centery - sclheight/2, sclwidth, sclheight);
if(grid){
Draw.color(Color.GRAY);
image.setBounds(centerx - sclwidth/2, centery - sclheight/2, sclwidth, sclheight);
image.draw(batch, alpha);
Draw.color();
}
if(tool == EditorTool.line && drawing){
Vector2 v1 = unproject(startx, starty).add(x, y);
float sx = v1.x, sy = v1.y;
Vector2 v2 = unproject(lastx, lasty).add(x, y);
Draw.color(Tmp.c1.set(ColorMapper.getColor(editor.getDrawBlock())));
Lines.stroke(Unit.dp.scl(3f * zoom));
Lines.line(sx, sy, v2.x, v2.y);
Lines.poly(sx, sy, 40, editor.getBrushSize() * zoom * 3);
Lines.poly(v2.x, v2.y, 40, editor.getBrushSize() * zoom * 3);
}
batch.flush();
if(pop) ScissorStack.popScissors();
Draw.color(Colors.get("accent"));
Lines.stroke(Unit.dp.scl(3f));
Lines.rect(x + width/2 - size/2, y + height/2 - size/2, size, size);
Draw.reset();
}
private boolean active(){
return Core.scene.getKeyboardFocus() != null
&& Core.scene.getKeyboardFocus().isDescendantOf(ui.editor)
&& ui.editor.isShown() && tool == EditorTool.zoom &&
Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true) == this;
}
@Override
public boolean touchDown(float x, float y, int pointer, int button){
return false;
}
@Override
public boolean tap(float x, float y, int count, int button){
return false;
}
@Override
public boolean longPress(float x, float y){
return false;
}
@Override
public boolean fling(float velocityX, float velocityY, int button){
return false;
}
@Override
public boolean pan(float x, float y, float deltaX, float deltaY){
if(!active()) return false;
offsetx += deltaX / zoom;
offsety -= deltaY / zoom;
return false;
}
@Override
public boolean panStop(float x, float y, int pointer, int button){
return false;
}
@Override
public boolean zoom(float initialDistance, float distance){
if(!active()) return false;
float nzoom = distance - initialDistance;
zoom += nzoom / 10000f / Unit.dp.scl(1f) * zoom;
clampZoom();
return false;
}
@Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2){
return false;
}
@Override
public void pinchStop(){
}
}

View File

@ -0,0 +1,54 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.utils.Array;
public class OperationStack{
private final static int maxSize = 10;
private Array<DrawOperation> stack = new Array<>();
private int index = 0;
public OperationStack(){
}
public void clear(){
for(DrawOperation op : stack){
op.dispose();
}
stack.clear();
index = 0;
}
public void add(DrawOperation action){
stack.truncate(stack.size + index);
index = 0;
stack.add(action);
if(stack.size > maxSize){
stack.removeIndex(0);
}
}
public boolean canUndo(){
return !(stack.size - 1 + index < 0);
}
public boolean canRedo(){
return !(index > -1 || stack.size + index < 0);
}
public void undo(){
if(!canUndo()) return;
stack.get(stack.size - 1 + index).undo();
index --;
}
public void redo(){
if(!canRedo()) return;
index ++;
stack.get(stack.size - 1 + index).redo();
}
}

View File

@ -12,7 +12,7 @@ public class MapTileData {
private final static int TILE_SIZE = 3; private final static int TILE_SIZE = 3;
private final ByteBuffer buffer; private final ByteBuffer buffer;
private final TileData tile = new TileData(); private final TileDataWriter tile = new TileDataWriter();
private final int width, height; private final int width, height;
public MapTileData(int width, int height){ public MapTileData(int width, int height){
@ -36,15 +36,22 @@ public class MapTileData {
} }
/**Reads and returns the next tile data.*/ /**Reads and returns the next tile data.*/
public TileData read(){ public TileDataWriter read(){
tile.read(); tile.read(buffer);
return tile; return tile;
} }
/**Writes tile data at a specified position. Uses the tile data returned by read().*/ /**Reads and returns the next tile data.*/
public void write(int x, int y){ public TileDataWriter readAt(int x, int y){
position(x, y); position(x, y);
tile.write(); tile.read(buffer);
return tile;
}
/**Writes tile data at a specified position.*/
public void write(int x, int y, TileDataWriter writer){
position(x, y);
writer.write(buffer);
} }
/**Sets read position to the specified coordinates*/ /**Sets read position to the specified coordinates*/
@ -52,12 +59,12 @@ public class MapTileData {
buffer.position((x + width * y) * TILE_SIZE); buffer.position((x + width * y) * TILE_SIZE);
} }
public class TileData{ public static class TileDataWriter {
public byte floor, wall; public byte floor, wall;
public byte rotation; public byte rotation;
public byte team; public byte team;
private void read(){ public void read(ByteBuffer buffer){
floor = buffer.get(); floor = buffer.get();
wall = buffer.get(); wall = buffer.get();
byte rt = buffer.get(); byte rt = buffer.get();
@ -65,7 +72,7 @@ public class MapTileData {
team = Bits.getRightByte(rt); team = Bits.getRightByte(rt);
} }
private void write(){ public void write(ByteBuffer buffer){
buffer.put(floor); buffer.put(floor);
buffer.put(wall); buffer.put(wall);
byte rt = Bits.packByte(rotation, team); byte rt = Bits.packByte(rotation, team);

View File

@ -1,9 +1,11 @@
package io.anuke.mindustry.io; package io.anuke.mindustry.io;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
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.ObjectMap; import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.ucore.util.Log;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
@ -13,30 +15,43 @@ import static io.anuke.mindustry.Vars.customMapDirectory;
import static io.anuke.mindustry.Vars.mapExtension; import static io.anuke.mindustry.Vars.mapExtension;
public class Maps implements Disposable{ public class Maps implements Disposable{
/**List of all built-in maps.*/
private static final String[] defaultMapNames = {};
private ObjectMap<String, Map> maps = new ObjectMap<>(); private ObjectMap<String, Map> maps = new ObjectMap<>();
private Array<Map> allMaps = new Array<>(); private Array<Map> allMaps = new Array<>();
private Array<Map> customMaps = new Array<>(); private Array<Map> returnArray = new Array<>();
private Array<Map> defaultMaps = new Array<>();
public void load(){
//TODO
}
public void save(){
//TODO?
}
/**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.*/
public Array<Map> customMaps(){
returnArray.clear();
for(Map map : allMaps){
if(map.custom) returnArray.add(map);
}
return returnArray;
}
/**Returns a list of only default maps.*/
public Array<Map> defaultMaps(){
returnArray.clear();
for(Map map : allMaps){
if(!map.custom) returnArray.add(map);
}
return returnArray;
}
/**Returns map by internal name.*/ /**Returns map by internal name.*/
public Map getByName(String name){ public Map getByName(String name){
return maps.get(name); return maps.get(name);
} }
//TODO GWT support: read from prefs string if custom //TODO GWT support: read from prefs string if custom
/**Reads all tile data from a map. Should be used sparingly.*/
public MapTileData readTileData(Map map){ public MapTileData readTileData(Map map){
try { try {
InputStream stream; InputStream stream;
@ -56,6 +71,35 @@ public class Maps implements Disposable{
} }
} }
/**Load all maps. Should be called at application start.*/
public void load(){
try {
for (String name : defaultMapNames) {
loadMap(Gdx.files.internal("maps/" + name + "." + mapExtension), false);
}
}catch (IOException e){
throw new RuntimeException(e);
}
for(FileHandle file : customMapDirectory.list()){
try{
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{
DataInputStream ds = new DataInputStream(file.read());
MapMeta meta = readMapMeta(ds);
Map map = new Map(file.nameWithoutExtension(), meta, custom);
maps.put(map.name, map);
allMaps.add(map);
}
private MapTileData readTileData(DataInputStream stream) throws IOException{ private MapTileData readTileData(DataInputStream stream) throws IOException{
MapMeta meta = readMapMeta(stream); MapMeta meta = readMapMeta(stream);
byte[] bytes = new byte[stream.available()]; byte[] bytes = new byte[stream.available()];

View File

@ -2,7 +2,7 @@ package io.anuke.mindustry.world;
import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.io.MapTileData; import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileData; import io.anuke.mindustry.io.MapTileData.TileDataWriter;
import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.noise.Noise; import io.anuke.ucore.noise.Noise;
@ -23,7 +23,7 @@ public class WorldGenerator {
for(int x = 0; x < data.width(); x ++){ for(int x = 0; x < data.width(); x ++){
for(int y = 0; y < data.height(); y ++){ for(int y = 0; y < data.height(); y ++){
TileData tile = data.read(); TileDataWriter tile = data.read();
tiles[x][y] = new Tile(x, y, tile.floor, tile.wall, tile.rotation, tile.team); tiles[x][y] = new Tile(x, y, tile.floor, tile.wall, tile.rotation, tile.team);
//TODO ores, plants, extra decoration? //TODO ores, plants, extra decoration?

View File

@ -8,6 +8,7 @@ import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.EventType.GameOverEvent; import io.anuke.mindustry.game.EventType.GameOverEvent;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.io.Map;
import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.io.SaveIO;
import io.anuke.mindustry.io.Version; import io.anuke.mindustry.io.Version;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
@ -17,7 +18,6 @@ import io.anuke.mindustry.net.Packets.ChatPacket;
import io.anuke.mindustry.net.Packets.KickReason; import io.anuke.mindustry.net.Packets.KickReason;
import io.anuke.mindustry.net.TraceInfo; import io.anuke.mindustry.net.TraceInfo;
import io.anuke.mindustry.ui.fragments.DebugFragment; import io.anuke.mindustry.ui.fragments.DebugFragment;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.*; import io.anuke.ucore.core.*;
import io.anuke.ucore.modules.Module; import io.anuke.ucore.modules.Module;
@ -34,8 +34,6 @@ import java.util.Scanner;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
import static io.anuke.ucore.util.Log.*; import static io.anuke.ucore.util.Log.*;
;
public class ServerControl extends Module { public class ServerControl extends Module {
private final CommandHandler handler = new CommandHandler(""); private final CommandHandler handler = new CommandHandler("");
private ShuffleMode mode; private ShuffleMode mode;
@ -81,12 +79,12 @@ public class ServerControl extends Module {
} }
if (mode != ShuffleMode.off) { if (mode != ShuffleMode.off) {
Array<Map> maps = mode == ShuffleMode.both ? world.maps().getAllMaps() : Array<Map> maps = mode == ShuffleMode.both ? world.maps().all() :
mode == ShuffleMode.normal ? world.maps().getDefaultMaps() : world.maps().getCustomMaps(); mode == ShuffleMode.normal ? world.maps().defaultMaps() : world.maps().customMaps();
Map previous = world.getMap(); Map previous = world.getMap();
Map map = previous; Map map = previous;
while (map == previous || !map.visible) map = maps.random(); while (map == previous) map = maps.random();
info("Selected next map to be {0}.", map.name); info("Selected next map to be {0}.", map.name);
state.set(State.playing); state.set(State.playing);
@ -134,7 +132,7 @@ public class ServerControl extends Module {
String search = arg[0]; String search = arg[0];
Map result = null; Map result = null;
for(Map map : world.maps().list()){ for(Map map : world.maps().all()){
if(map.name.equalsIgnoreCase(search)) if(map.name.equalsIgnoreCase(search))
result = map; result = map;
} }
@ -165,8 +163,8 @@ public class ServerControl extends Module {
handler.register("maps", "Display all available maps.", arg -> { handler.register("maps", "Display all available maps.", arg -> {
Log.info("Maps:"); Log.info("Maps:");
for(Map map : world.maps().getAllMaps()){ for(Map map : world.maps().all()){
Log.info(" &ly{0}: &lb&fi{1} / {2}x{3}", map.name, map.custom ? "Custom" : "Default", map.getWidth(), map.getHeight()); Log.info(" &ly{0}: &lb&fi{1} / {2}x{3}", map.name, map.custom ? "Custom" : "Default", map.meta.width, map.meta.height);
} }
}); });
@ -505,7 +503,8 @@ public class ServerControl extends Module {
return; return;
} }
world.removeBlock(world.getCore()); Events.fire(GameOverEvent.class);
info("Core destroyed."); info("Core destroyed.");
}); });

View File

@ -1,6 +1,6 @@
package io.anuke.mindustry.server.mapgen; package io.anuke.mindustry.server.mapgen;
import io.anuke.mindustry.world.Map; import io.anuke.mindustry.io.Map;
import io.anuke.ucore.noise.RidgedPerlin; import io.anuke.ucore.noise.RidgedPerlin;
import io.anuke.ucore.noise.Simplex; import io.anuke.ucore.noise.Simplex;