Desktop/mobile descriptive tool modes
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.collection.IntArray;
|
||||
import io.anuke.arc.function.IntPositionConsumer;
|
||||
import io.anuke.arc.input.KeyCode;
|
||||
import io.anuke.arc.util.*;
|
||||
import io.anuke.arc.function.*;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.math.geom.Bresenham2;
|
||||
import io.anuke.arc.util.Structs;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.content.Blocks;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.world.*;
|
||||
import io.anuke.mindustry.world.blocks.*;
|
||||
|
||||
public enum EditorTool{
|
||||
zoom,
|
||||
@@ -16,12 +17,34 @@ public enum EditorTool{
|
||||
if(!Structs.inBounds(x, y, editor.width(), editor.height())) return;
|
||||
|
||||
Tile tile = editor.tile(x, y).link();
|
||||
|
||||
editor.drawBlock = tile.block() == Blocks.air ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
|
||||
}
|
||||
},
|
||||
line,
|
||||
pencil{
|
||||
line("replace", "straight"){
|
||||
|
||||
@Override
|
||||
public void touchedLine(MapEditor editor, int x1, int y1, int x2, int y2){
|
||||
//straight
|
||||
if(mode == 1){
|
||||
if(Math.abs(x2 - x1) > Math.abs(y2 - y1)){
|
||||
y2 = y1;
|
||||
}else{
|
||||
x2 = x1;
|
||||
}
|
||||
}
|
||||
|
||||
Bresenham2.line(x1, y1, x2, y2, (x, y) -> {
|
||||
if(mode == 0){
|
||||
//replace
|
||||
editor.drawBlocksReplace(x, y);
|
||||
}else{
|
||||
//normal
|
||||
editor.drawBlocks(x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
pencil("replace", "square"){
|
||||
{
|
||||
edit = true;
|
||||
draggable = true;
|
||||
@@ -29,10 +52,20 @@ public enum EditorTool{
|
||||
|
||||
@Override
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
editor.draw(x, y, isPaint());
|
||||
if(mode == -1){
|
||||
//normal mode
|
||||
editor.drawBlocks(x, y);
|
||||
}else if(mode == 0){
|
||||
//replace mode
|
||||
editor.drawBlocksReplace(x, y);
|
||||
}else if(mode == 1){
|
||||
//square mode
|
||||
editor.drawBlocks(x, y, true, tile -> true);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
eraser{
|
||||
eraser("eraseores"){
|
||||
{
|
||||
edit = true;
|
||||
draggable = true;
|
||||
@@ -40,19 +73,25 @@ public enum EditorTool{
|
||||
|
||||
@Override
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
editor.draw(x, y, isPaint(), Blocks.air);
|
||||
editor.drawCircle(x, y, tile -> {
|
||||
if(mode == -1){
|
||||
//erase block
|
||||
Vars.world.removeBlock(tile);
|
||||
}else if(mode == 0){
|
||||
//erase ore
|
||||
tile.clearOverlay();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
fill{
|
||||
fill("replaceall", "fillteams"){
|
||||
{
|
||||
edit = true;
|
||||
}
|
||||
|
||||
IntArray stack = new IntArray();
|
||||
Block dest;
|
||||
boolean isFloor;
|
||||
MapEditor data;
|
||||
|
||||
@Override
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
if(!Structs.inBounds(x, y, editor.width(), editor.height())) return;
|
||||
Tile tile = editor.tile(x, y);
|
||||
@@ -63,74 +102,57 @@ public enum EditorTool{
|
||||
return;
|
||||
}
|
||||
|
||||
data = editor;
|
||||
isFloor = editor.drawBlock instanceof Floor;
|
||||
//mode 0 or 1, fill everything with the floor/tile or replace it
|
||||
if(mode == 0 || mode == -1){
|
||||
Predicate<Tile> tester;
|
||||
Consumer<Tile> setter;
|
||||
|
||||
Block floor = tile.floor();
|
||||
Block block = tile.block();
|
||||
boolean synth = editor.drawBlock.synthetic();
|
||||
|
||||
Block draw = editor.drawBlock;
|
||||
dest = draw instanceof OverlayFloor ? tile.overlay() : isFloor ? floor : block;
|
||||
|
||||
if(dest == draw || block instanceof BlockPart || block.isMultiblock()){
|
||||
return;
|
||||
}
|
||||
|
||||
boolean alt = isAlt();
|
||||
|
||||
int width = editor.width();
|
||||
int height = editor.height();
|
||||
|
||||
IntPositionConsumer writer = (px, py) -> {
|
||||
Tile write = editor.tile(px, py);
|
||||
|
||||
if(isFloor){
|
||||
if(alt && !(draw instanceof OverlayFloor)){
|
||||
Block ore = write.overlay();
|
||||
write.setFloor((Floor)draw);
|
||||
write.setOverlay(ore);
|
||||
}else{
|
||||
write.setFloor((Floor)draw);
|
||||
}
|
||||
if(editor.drawBlock.isOverlay()){
|
||||
Block dest = tile.overlay();
|
||||
tester = t -> t.overlay() == dest;
|
||||
setter = t -> t.setOverlay(editor.drawBlock);
|
||||
}else if(editor.drawBlock.isFloor()){
|
||||
Block dest = tile.floor();
|
||||
tester = t -> t.floor() == dest;
|
||||
setter = t -> t.setFloorUnder(editor.drawBlock.asFloor());
|
||||
}else{
|
||||
write.setBlock(draw);
|
||||
Block dest = tile.block();
|
||||
tester = t -> t.block() == dest;
|
||||
setter = t -> t.setBlock(editor.drawBlock);
|
||||
}
|
||||
|
||||
if(synth){
|
||||
write.setTeam(editor.drawTeam);
|
||||
}
|
||||
//replace only when the mode is 0 using the specified functions
|
||||
fill(editor, x, y, mode == 0, tester, setter);
|
||||
}else if(mode == 1){ //mode 1 is team fill
|
||||
|
||||
if(draw.rotate){
|
||||
write.rotation((byte)editor.rotation);
|
||||
}
|
||||
};
|
||||
//only fill synthetic blocks, it's meaningless otherwise
|
||||
if(tile.link().synthetic()){
|
||||
|
||||
if(isAlt()){
|
||||
//fill all of the same type regardless of borders
|
||||
Team dest = tile.getTeam();
|
||||
fill(editor, x, y, false, t -> t.getTeam() == dest, t -> t.setTeam(editor.drawTeam));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fill(MapEditor editor, int x, int y, boolean replace, Predicate<Tile> tester, Consumer<Tile> filler){
|
||||
int width = editor.width(), height = editor.height();
|
||||
|
||||
if(replace){
|
||||
//just do it on everything
|
||||
for(int cx = 0; cx < width; cx++){
|
||||
for(int cy = 0; cy < height; cy++){
|
||||
if(eq(cx, cy)){
|
||||
writer.accept(cx, cy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(isAlt2()){
|
||||
//fill all teams.
|
||||
for(int cx = 0; cx < width; cx++){
|
||||
for(int cy = 0; cy < height; cy++){
|
||||
Tile write = editor.tile(cx, cy);
|
||||
if(write.block().synthetic()){
|
||||
write.setTeam(editor.drawTeam);
|
||||
Tile tile = editor.tile(cx, cy);
|
||||
if(tester.test(tile)){
|
||||
filler.accept(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
//normal fill
|
||||
//perform flood fill
|
||||
int x1;
|
||||
|
||||
stack.clear();
|
||||
|
||||
stack.add(Pos.get(x, y));
|
||||
|
||||
while(stack.size > 0){
|
||||
@@ -139,23 +161,23 @@ public enum EditorTool{
|
||||
y = Pos.y(popped);
|
||||
|
||||
x1 = x;
|
||||
while(x1 >= 0 && eq(x1, y)) x1--;
|
||||
while(x1 >= 0 && tester.test(editor.tile(x1, y))) x1--;
|
||||
x1++;
|
||||
boolean spanAbove = false, spanBelow = false;
|
||||
while(x1 < width && eq(x1, y)){
|
||||
writer.accept(x1, y);
|
||||
while(x1 < width && tester.test(editor.tile(x1, y))){
|
||||
filler.accept(editor.tile(x1, y));
|
||||
|
||||
if(!spanAbove && y > 0 && eq(x1, y - 1)){
|
||||
if(!spanAbove && y > 0 && tester.test(editor.tile(x1, y - 1))){
|
||||
stack.add(Pos.get(x1, y - 1));
|
||||
spanAbove = true;
|
||||
}else if(spanAbove && !eq(x1, y - 1)){
|
||||
}else if(spanAbove && !tester.test(editor.tile(x1, y - 1))){
|
||||
spanAbove = false;
|
||||
}
|
||||
|
||||
if(!spanBelow && y < height - 1 && eq(x1, y + 1)){
|
||||
if(!spanBelow && y < height - 1 && tester.test(editor.tile(x1, y + 1))){
|
||||
stack.add(Pos.get(x1, y + 1));
|
||||
spanBelow = true;
|
||||
}else if(spanBelow && y < height - 1 && !eq(x1, y + 1)){
|
||||
}else if(spanBelow && y < height - 1 && !tester.test(editor.tile(x1, y + 1))){
|
||||
spanBelow = false;
|
||||
}
|
||||
x1++;
|
||||
@@ -163,14 +185,10 @@ public enum EditorTool{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean eq(int px, int py){
|
||||
Tile tile = data.tile(px, py);
|
||||
|
||||
return (data.drawBlock instanceof OverlayFloor ? tile.overlay() : isFloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OverlayFloor && tile.floor().isLiquid);
|
||||
}
|
||||
},
|
||||
spray{
|
||||
spray("replace"){
|
||||
final double chance = 0.012;
|
||||
|
||||
{
|
||||
edit = true;
|
||||
draggable = true;
|
||||
@@ -178,25 +196,40 @@ public enum EditorTool{
|
||||
|
||||
@Override
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
editor.draw(x, y, isPaint(), editor.drawBlock, 0.012);
|
||||
|
||||
//floor spray
|
||||
if(editor.drawBlock.isFloor()){
|
||||
editor.drawCircle(x, y, tile -> {
|
||||
if(Mathf.chance(chance)){
|
||||
tile.setFloor(editor.drawBlock.asFloor());
|
||||
}
|
||||
});
|
||||
}else if(mode == 0){ //replace-only mode, doesn't affect air
|
||||
editor.drawBlocks(x, y, tile -> Mathf.chance(chance) && tile.block() != Blocks.air);
|
||||
}else{
|
||||
editor.drawBlocks(x, y, tile -> Mathf.chance(chance));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
boolean edit, draggable;
|
||||
/** All the internal alternate placement modes of this tool. */
|
||||
public final String[] altModes;
|
||||
/** The current alternate placement mode. -1 is the standard mode, no changes.*/
|
||||
public int mode = -1;
|
||||
/** Whether this tool causes canvas changes when touched.*/
|
||||
public boolean edit;
|
||||
/** Whether this tool should be dragged across the canvas when the mouse moves.*/
|
||||
public boolean draggable;
|
||||
|
||||
public static boolean isPaint(){
|
||||
return Core.input.keyDown(KeyCode.CONTROL_LEFT);
|
||||
EditorTool(){
|
||||
this(new String[]{});
|
||||
}
|
||||
|
||||
public static boolean isAlt(){
|
||||
return Core.input.keyDown(KeyCode.TAB);
|
||||
EditorTool(String... altModes){
|
||||
this.altModes = altModes;
|
||||
}
|
||||
|
||||
public static boolean isAlt2(){
|
||||
return Core.input.keyDown(KeyCode.GRAVE);
|
||||
}
|
||||
public void touched(MapEditor editor, int x, int y){}
|
||||
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
|
||||
}
|
||||
public void touchedLine(MapEditor editor, int x1, int y1, int x2, int y2){}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.arc.collection.StringMap;
|
||||
import io.anuke.arc.files.FileHandle;
|
||||
import io.anuke.arc.function.Consumer;
|
||||
import io.anuke.arc.function.Predicate;
|
||||
import io.anuke.arc.graphics.Pixmap;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.util.Structs;
|
||||
@@ -132,15 +134,111 @@ public class MapEditor{
|
||||
return world.height();
|
||||
}
|
||||
|
||||
public void draw(int x, int y, boolean paint){
|
||||
draw(x, y, paint, drawBlock);
|
||||
public void drawBlocksReplace(int x, int y){
|
||||
drawBlocks(x, y, tile -> tile.block() != Blocks.air || drawBlock.isFloor());
|
||||
}
|
||||
|
||||
public void draw(int x, int y, boolean paint, Block drawBlock){
|
||||
draw(x, y, paint, drawBlock, 1.0);
|
||||
public void drawBlocks(int x, int y){
|
||||
drawBlocks(x, y, false, tile -> true);
|
||||
}
|
||||
|
||||
public void draw(int x, int y, boolean paint, Block drawBlock, double chance){
|
||||
public void drawBlocks(int x, int y, Predicate<Tile> tester){
|
||||
drawBlocks(x, y, false, tester);
|
||||
}
|
||||
|
||||
public void drawBlocks(int x, int y, boolean square, Predicate<Tile> tester){
|
||||
if(drawBlock.isMultiblock()){
|
||||
x = Mathf.clamp(x, (drawBlock.size - 1) / 2, width() - drawBlock.size / 2 - 1);
|
||||
y = Mathf.clamp(y, (drawBlock.size - 1) / 2, height() - drawBlock.size / 2 - 1);
|
||||
|
||||
int offsetx = -(drawBlock.size - 1) / 2;
|
||||
int offsety = -(drawBlock.size - 1) / 2;
|
||||
|
||||
for(int dx = 0; dx < drawBlock.size; dx++){
|
||||
for(int dy = 0; dy < drawBlock.size; dy++){
|
||||
int worldx = dx + offsetx + x;
|
||||
int worldy = dy + offsety + y;
|
||||
|
||||
if(Structs.inBounds(worldx, worldy, width(), height())){
|
||||
Tile tile = tile(worldx, worldy);
|
||||
|
||||
Block block = tile.block();
|
||||
|
||||
//bail out if there's anything blocking the way
|
||||
if(block.isMultiblock() || block instanceof BlockPart){
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.updatePoint(worldx, worldy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
world.setBlock(tile(x, y), drawBlock, drawTeam);
|
||||
}else{
|
||||
|
||||
boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air;
|
||||
|
||||
Consumer<Tile> drawer = tile -> {
|
||||
if(!tester.test(tile)) return;
|
||||
|
||||
//remove linked tiles blocking the way
|
||||
if(!isFloor && (tile.isLinked() || tile.block().isMultiblock())){
|
||||
world.removeBlock(tile.link());
|
||||
}
|
||||
|
||||
if(isFloor){
|
||||
tile.setFloor(drawBlock.asFloor());
|
||||
}else{
|
||||
tile.setBlock(drawBlock);
|
||||
if(drawBlock.synthetic()){
|
||||
tile.setTeam(drawTeam);
|
||||
}
|
||||
if(drawBlock.rotate){
|
||||
tile.rotation((byte)rotation);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(square){
|
||||
drawSquare(x, y, drawer);
|
||||
}else{
|
||||
drawCircle(x, y, drawer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawCircle(int x, int y, Consumer<Tile> drawer){
|
||||
for(int rx = -brushSize; rx <= brushSize; rx++){
|
||||
for(int ry = -brushSize; ry <= brushSize; ry++){
|
||||
if(Mathf.dst2(rx, ry) <= (brushSize - 0.5f) * (brushSize - 0.5f)){
|
||||
int wx = x + rx, wy = y + ry;
|
||||
|
||||
if(wx < 0 || wy < 0 || wx >= width() || wy >= height()){
|
||||
continue;
|
||||
}
|
||||
|
||||
drawer.accept(tile(wx, wy));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawSquare(int x, int y, Consumer<Tile> drawer){
|
||||
for(int rx = -brushSize; rx <= brushSize; rx++){
|
||||
for(int ry = -brushSize; ry <= brushSize; ry++){
|
||||
int wx = x + rx, wy = y + ry;
|
||||
|
||||
if(wx < 0 || wy < 0 || wx >= width() || wy >= height()){
|
||||
continue;
|
||||
}
|
||||
|
||||
drawer.accept(tile(wx, wy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void draw_DEPRECATED(int x, int y, boolean paint, Block drawBlock, double chance){
|
||||
boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air;
|
||||
Tile[][] tiles = world.getTiles();
|
||||
|
||||
|
||||
@@ -12,8 +12,10 @@ import io.anuke.arc.input.KeyCode;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.math.geom.Vector2;
|
||||
import io.anuke.arc.scene.actions.Actions;
|
||||
import io.anuke.arc.scene.event.Touchable;
|
||||
import io.anuke.arc.scene.style.TextureRegionDrawable;
|
||||
import io.anuke.arc.scene.ui.*;
|
||||
import io.anuke.arc.scene.ui.TextButton.TextButtonStyle;
|
||||
import io.anuke.arc.scene.ui.layout.Table;
|
||||
import io.anuke.arc.scene.ui.layout.Unit;
|
||||
import io.anuke.arc.util.*;
|
||||
@@ -21,6 +23,7 @@ import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.game.*;
|
||||
import io.anuke.mindustry.graphics.Pal;
|
||||
import io.anuke.mindustry.io.JsonIO;
|
||||
import io.anuke.mindustry.io.MapIO;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
@@ -380,15 +383,77 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
|
||||
Consumer<EditorTool> addTool = tool -> {
|
||||
Table[] lastTable = {null};
|
||||
|
||||
ImageButton button = new ImageButton("icon-" + tool.name(), "clear-toggle");
|
||||
button.clicked(() -> view.setTool(tool));
|
||||
button.clicked(() -> {
|
||||
view.setTool(tool);
|
||||
if(lastTable[0] != null){
|
||||
lastTable[0].remove();
|
||||
}
|
||||
});
|
||||
button.resizeImage(16 * 2f);
|
||||
button.update(() -> button.setChecked(view.getTool() == tool));
|
||||
group.add(button);
|
||||
if(tool == EditorTool.pencil)
|
||||
button.setChecked(true);
|
||||
|
||||
tools.add(button);
|
||||
if(tool.altModes.length > 0){
|
||||
button.clicked(l -> {
|
||||
if(!mobile){
|
||||
//desktop: rightclick
|
||||
l.setButton(KeyCode.MOUSE_RIGHT);
|
||||
}
|
||||
}, e -> {
|
||||
//need to double tap
|
||||
if(mobile && e.getTapCount() < 2){
|
||||
return;
|
||||
}
|
||||
|
||||
if(lastTable[0] != null){
|
||||
lastTable[0].remove();
|
||||
}
|
||||
|
||||
Table table = new Table("dialogDim");
|
||||
table.defaults().size(280f, 70f);
|
||||
|
||||
for(int i = 0; i < tool.altModes.length; i++){
|
||||
int mode = i;
|
||||
String name = tool.altModes[i];
|
||||
|
||||
table.addButton(b -> {
|
||||
b.left();
|
||||
b.marginLeft(6);
|
||||
b.setStyle(Core.scene.skin.get("clear-toggle", TextButtonStyle.class));
|
||||
b.add(Core.bundle.get("toolmode." + name)).left();
|
||||
b.row();
|
||||
b.add(Core.bundle.get("toolmode." + name + ".description")).color(Color.LIGHT_GRAY).left();
|
||||
}, () -> {
|
||||
tool.mode = (tool.mode == mode ? -1 : mode);
|
||||
table.remove();
|
||||
}).update(b -> b.setChecked(tool.mode == mode));
|
||||
table.row();
|
||||
}
|
||||
|
||||
table.update(() -> {
|
||||
Vector2 v = button.localToStageCoordinates(Tmp.v1.setZero());
|
||||
table.setPosition(v.x, v.y, Align.topLeft);
|
||||
});
|
||||
|
||||
table.pack();
|
||||
table.act(Core.graphics.getDeltaTime());
|
||||
|
||||
Core.scene.add(table);
|
||||
lastTable[0] = table;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Label mode = new Label("");
|
||||
mode.setColor(Pal.remove);
|
||||
mode.update(() -> mode.setText(tool.mode == -1 ? "" : "M" + (tool.mode + 1) + " "));
|
||||
mode.setAlignment(Align.bottomRight, Align.bottomRight);
|
||||
mode.touchable(Touchable.disabled);
|
||||
|
||||
tools.stack(button, mode);
|
||||
};
|
||||
|
||||
tools.defaults().size(size, size);
|
||||
@@ -479,14 +544,26 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
}
|
||||
|
||||
private void doInput(){
|
||||
//tool select
|
||||
for(int i = 0; i < EditorTool.values().length; i++){
|
||||
if(Core.input.keyTap(KeyCode.valueOf("NUM_" + (i + 1)))){
|
||||
view.setTool(EditorTool.values()[i]);
|
||||
break;
|
||||
|
||||
if(Core.input.ctrl()){
|
||||
//alt mode select
|
||||
//TODO these keycode are unusable, tweak later
|
||||
for(int i = 0; i < view.getTool().altModes.length + 1; i++){
|
||||
if(Core.input.keyTap(KeyCode.valueOf("NUM_" + (i + 1)))){
|
||||
view.getTool().mode = i - 1;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//tool select
|
||||
for(int i = 0; i < EditorTool.values().length; i++){
|
||||
if(Core.input.keyTap(KeyCode.valueOf("NUM_" + (i + 1)))){
|
||||
view.setTool(EditorTool.values()[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(Core.input.keyTap(KeyCode.ESCAPE)){
|
||||
if(!menu.isShown()){
|
||||
menu.show();
|
||||
|
||||
@@ -29,47 +29,49 @@ public class MapInfoDialog extends FloatingDialog{
|
||||
cont.clear();
|
||||
|
||||
ObjectMap<String, String> tags = editor.getTags();
|
||||
|
||||
cont.pane(t -> {
|
||||
t.add("$editor.name").padRight(8).left();
|
||||
t.defaults().padTop(15);
|
||||
|
||||
cont.add("$editor.name").padRight(8).left();
|
||||
TextField name = t.addField(tags.get("name", ""), text -> {
|
||||
tags.put("name", text);
|
||||
}).size(400, 55f).get();
|
||||
name.setMessageText("$unknown");
|
||||
|
||||
cont.defaults().padTop(15);
|
||||
t.row();
|
||||
t.add("$editor.description").padRight(8).left();
|
||||
|
||||
TextField name = cont.addField(tags.get("name", ""), text -> {
|
||||
tags.put("name", text);
|
||||
}).size(400, 55f).get();
|
||||
name.setMessageText("$unknown");
|
||||
TextArea description = t.addArea(tags.get("description", ""), "textarea", text -> {
|
||||
tags.put("description", text);
|
||||
}).size(400f, 140f).get();
|
||||
|
||||
cont.row();
|
||||
cont.add("$editor.description").padRight(8).left();
|
||||
t.row();
|
||||
t.add("$editor.author").padRight(8).left();
|
||||
|
||||
TextArea description = cont.addArea(tags.get("description", ""), "textarea", text -> {
|
||||
tags.put("description", text);
|
||||
}).size(400f, 140f).get();
|
||||
TextField author = t.addField(tags.get("author", Core.settings.getString("mapAuthor", "")), text -> {
|
||||
tags.put("author", text);
|
||||
Core.settings.put("mapAuthor", text);
|
||||
Core.settings.save();
|
||||
}).size(400, 55f).get();
|
||||
author.setMessageText("$unknown");
|
||||
|
||||
cont.row();
|
||||
cont.add("$editor.author").padRight(8).left();
|
||||
t.row();
|
||||
t.add("$editor.rules").padRight(8).left();
|
||||
t.addButton("$edit", () -> ruleInfo.show(Vars.state.rules, () -> Vars.state.rules = new Rules())).left().width(200f);
|
||||
|
||||
TextField author = cont.addField(tags.get("author", Core.settings.getString("mapAuthor", "")), text -> {
|
||||
tags.put("author", text);
|
||||
Core.settings.put("mapAuthor", text);
|
||||
Core.settings.save();
|
||||
}).size(400, 55f).get();
|
||||
author.setMessageText("$unknown");
|
||||
t.row();
|
||||
t.add("$editor.waves").padRight(8).left();
|
||||
t.addButton("$edit", waveInfo::show).left().width(200f);
|
||||
|
||||
cont.row();
|
||||
cont.add("$editor.rules").padRight(8).left();
|
||||
cont.addButton("$edit", () -> ruleInfo.show(Vars.state.rules, () -> Vars.state.rules = new Rules())).left().width(200f);
|
||||
name.change();
|
||||
description.change();
|
||||
author.change();
|
||||
|
||||
cont.row();
|
||||
cont.add("$editor.waves").padRight(8).left();
|
||||
cont.addButton("$edit", waveInfo::show).left().width(200f);
|
||||
|
||||
name.change();
|
||||
description.change();
|
||||
author.change();
|
||||
|
||||
Platform.instance.addDialog(name, 50);
|
||||
Platform.instance.addDialog(author, 50);
|
||||
Platform.instance.addDialog(description, 1000);
|
||||
Platform.instance.addDialog(name, 50);
|
||||
Platform.instance.addDialog(author, 50);
|
||||
Platform.instance.addDialog(description, 1000);
|
||||
t.margin(16f);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.arc.Core;
|
||||
import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.graphics.g2d.*;
|
||||
import io.anuke.arc.input.GestureDetector;
|
||||
@@ -24,7 +23,6 @@ import static io.anuke.mindustry.Vars.ui;
|
||||
public class MapView extends Element implements GestureListener{
|
||||
private MapEditor editor;
|
||||
private EditorTool tool = EditorTool.pencil;
|
||||
private Bresenham2 br = new Bresenham2();
|
||||
private float offsetx, offsety;
|
||||
private float zoom = 1f;
|
||||
private boolean grid = false;
|
||||
@@ -107,19 +105,8 @@ public class MapView extends Element implements GestureListener{
|
||||
Point2 p = project(x, y);
|
||||
|
||||
if(tool == EditorTool.line){
|
||||
if(Core.input.keyDown(KeyCode.TAB)){
|
||||
if(Math.abs(p.x - firstTouch.x) > Math.abs(p.y - firstTouch.y)){
|
||||
p.y = firstTouch.y;
|
||||
}else{
|
||||
p.x = firstTouch.x;
|
||||
}
|
||||
}
|
||||
|
||||
ui.editor.resetSaved();
|
||||
Array<Point2> points = br.line(startx, starty, p.x, p.y);
|
||||
for(Point2 point : points){
|
||||
editor.draw(point.x, point.y, EditorTool.isPaint());
|
||||
}
|
||||
tool.touchedLine(editor, startx, starty, p.x, p.y);
|
||||
}
|
||||
|
||||
editor.flushOp();
|
||||
@@ -133,7 +120,6 @@ public class MapView extends Element implements GestureListener{
|
||||
|
||||
@Override
|
||||
public void touchDragged(InputEvent event, float x, float y, int pointer){
|
||||
|
||||
mousex = x;
|
||||
mousey = y;
|
||||
|
||||
@@ -141,13 +127,10 @@ public class MapView extends Element implements GestureListener{
|
||||
|
||||
if(drawing && tool.draggable && !(p.x == lastx && p.y == lasty)){
|
||||
ui.editor.resetSaved();
|
||||
Array<Point2> points = br.line(lastx, lasty, p.x, p.y);
|
||||
for(Point2 point : points){
|
||||
tool.touched(editor, point.x, point.y);
|
||||
}
|
||||
Bresenham2.line(lastx, lasty, p.x, p.y, (cx, cy) -> tool.touched(editor, cx, cy));
|
||||
}
|
||||
|
||||
if(tool == EditorTool.line && Core.input.keyDown(KeyCode.TAB)){
|
||||
if(tool == EditorTool.line && tool.mode == 1){
|
||||
if(Math.abs(p.x - firstTouch.x) > Math.abs(p.y - firstTouch.y)){
|
||||
lastx = p.x;
|
||||
lasty = firstTouch.y;
|
||||
@@ -296,7 +279,13 @@ public class MapView extends Element implements GestureListener{
|
||||
if((tool.edit || (tool == EditorTool.line && !drawing)) && (!mobile || drawing)){
|
||||
Point2 p = project(mousex, mousey);
|
||||
Vector2 v = unproject(p.x, p.y).add(x, y);
|
||||
Lines.poly(brushPolygons[index], v.x, v.y, scaling);
|
||||
|
||||
//pencil square outline
|
||||
if(tool == EditorTool.pencil && tool.mode == 1){
|
||||
Lines.square(v.x + scaling/2f, v.y + scaling/2f, scaling * (editor.brushSize + 0.5f));
|
||||
}else{
|
||||
Lines.poly(brushPolygons[index], v.x, v.y, scaling);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if((tool.edit || tool == EditorTool.line) && (!mobile || drawing)){
|
||||
|
||||
@@ -27,17 +27,8 @@ public class Net{
|
||||
private static ObjectMap<Class<?>, BiConsumer<Integer, Object>> serverListeners = new ObjectMap<>();
|
||||
private static ClientProvider clientProvider;
|
||||
private static ServerProvider serverProvider;
|
||||
|
||||
private static IntMap<StreamBuilder> streams = new IntMap<>();
|
||||
|
||||
public static boolean hasClient(){
|
||||
return clientProvider != null;
|
||||
}
|
||||
|
||||
public static boolean hasServer(){
|
||||
return serverProvider != null;
|
||||
}
|
||||
|
||||
/** Display a network error. Call on the graphics thread. */
|
||||
public static void showError(Throwable e){
|
||||
|
||||
@@ -50,12 +41,13 @@ public class Net{
|
||||
|
||||
String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase();
|
||||
String type = t.getClass().toString().toLowerCase();
|
||||
boolean isError = false;
|
||||
|
||||
if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){
|
||||
error = Core.bundle.get("error.io");
|
||||
}else if(error.equals("mismatch")){
|
||||
error = Core.bundle.get("error.mismatch");
|
||||
}else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address"))){
|
||||
}else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address")) || Strings.parseException(e, true).contains("address associated")){
|
||||
error = Core.bundle.get("error.invalidaddress");
|
||||
}else if(error.contains("connection refused") || error.contains("route to host") || type.contains("unknownhost")){
|
||||
error = Core.bundle.get("error.unreachable");
|
||||
@@ -65,9 +57,14 @@ public class Net{
|
||||
error = Core.bundle.get("error.alreadyconnected");
|
||||
}else if(!error.isEmpty()){
|
||||
error = Core.bundle.get("error.any") + "\n" + Strings.parseException(e, true);
|
||||
isError = true;
|
||||
}
|
||||
|
||||
ui.showText("", Core.bundle.format("connectfail", error));
|
||||
if(isError){
|
||||
ui.showError(Core.bundle.format("connectfail", error));
|
||||
}else{
|
||||
ui.showText("", Core.bundle.format("connectfail", error));
|
||||
}
|
||||
ui.loadfrag.hide();
|
||||
|
||||
if(Net.client()){
|
||||
|
||||
@@ -27,6 +27,8 @@ import io.anuke.mindustry.input.InputHandler.PlaceDraw;
|
||||
import io.anuke.mindustry.type.*;
|
||||
import io.anuke.mindustry.ui.Bar;
|
||||
import io.anuke.mindustry.ui.ContentDisplay;
|
||||
import io.anuke.mindustry.world.blocks.Floor;
|
||||
import io.anuke.mindustry.world.blocks.OverlayFloor;
|
||||
import io.anuke.mindustry.world.consumers.*;
|
||||
import io.anuke.mindustry.world.meta.*;
|
||||
|
||||
@@ -658,6 +660,18 @@ public class Block extends BlockStorage{
|
||||
return buildVisibility.get() && !isHidden();
|
||||
}
|
||||
|
||||
public boolean isFloor(){
|
||||
return this instanceof Floor;
|
||||
}
|
||||
|
||||
public boolean isOverlay(){
|
||||
return this instanceof OverlayFloor;
|
||||
}
|
||||
|
||||
public Floor asFloor(){
|
||||
return (Floor)this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden(){
|
||||
return !buildVisibility.get();
|
||||
|
||||
@@ -9,8 +9,7 @@ import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||
import io.anuke.mindustry.entities.type.TileEntity;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.blocks.BlockPart;
|
||||
import io.anuke.mindustry.world.blocks.Floor;
|
||||
import io.anuke.mindustry.world.blocks.*;
|
||||
import io.anuke.mindustry.world.modules.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
@@ -161,6 +160,13 @@ public class Tile implements Position, TargetTrait{
|
||||
this.overlay = 0;
|
||||
}
|
||||
|
||||
/** Sets the floor, preserving overlay.*/
|
||||
public void setFloorUnder(Floor floor){
|
||||
Block overlay = overlay();
|
||||
setFloor(floor);
|
||||
setOverlay(overlay);
|
||||
}
|
||||
|
||||
public byte rotation(){
|
||||
return rotation;
|
||||
}
|
||||
@@ -190,7 +196,7 @@ public class Tile implements Position, TargetTrait{
|
||||
}
|
||||
|
||||
public void clearOverlay(){
|
||||
this.overlay = 0;
|
||||
setOverlayID((short)0);
|
||||
}
|
||||
|
||||
public boolean passable(){
|
||||
|
||||
Reference in New Issue
Block a user