map editor windows - edit tools

This commit is contained in:
sharlottes
2022-04-19 19:45:00 +09:00
parent de799fffd7
commit 8cc932a647
6 changed files with 624 additions and 2 deletions

View File

@@ -0,0 +1,335 @@
package UnitInfo.ui.windows;
import UnitInfo.ui.EditorTool;
import UnitInfo.ui.OverScrollPane;
import UnitInfo.ui.Updatable;
import arc.Core;
import arc.Events;
import arc.func.Boolf;
import arc.func.Cons;
import arc.func.Prov;
import arc.graphics.Color;
import arc.input.KeyCode;
import arc.math.Mathf;
import arc.math.geom.Point2;
import arc.math.geom.Vec2;
import arc.scene.event.Touchable;
import arc.scene.style.TextureRegionDrawable;
import arc.scene.ui.*;
import arc.scene.ui.layout.Scl;
import arc.scene.ui.layout.Table;
import arc.scene.utils.Elem;
import arc.struct.IntSeq;
import arc.struct.Seq;
import arc.util.*;
import mindustry.Vars;
import mindustry.content.Blocks;
import mindustry.editor.DrawOperation;
import mindustry.game.EventType;
import mindustry.game.Team;
import mindustry.gen.Icon;
import mindustry.gen.Tex;
import mindustry.gen.TileOp;
import mindustry.graphics.Pal;
import mindustry.ui.Styles;
import mindustry.world.Block;
import mindustry.world.Tile;
import static mindustry.Vars.*;
public class MapEditorDisplay extends WindowTable implements Updatable {
Vec2 scrollPos = new Vec2(0, 0);
TextField search;
Table window;
float heat;
float brushSize = -1;
UnitInfo.ui.EditorTool tool;
public static Team drawTeam = Team.sharded;
public static Block selected = Blocks.router;
public MapEditorDisplay() {
super("Map Editor Display", Icon.map, t -> {});
}
@Override
public void build() {
scrollPos = new Vec2(0, 0);
search = Elem.newField(null, f->{});
search.setMessageText("Search...");
top();
topBar();
table(Styles.black8, table -> {
window=table;
table.table(t->{
t.left().background(Tex.underline2);
t.label(()->"[accent]"+selected.localizedName+"[] "+selected.emoji());
t.add(search).growX().pad(8).name("search");
}).growX().row();
table.add(new OverScrollPane(rebuild(), Styles.nonePane, scrollPos).disableScroll(true, false)).grow().name("editor-pane");
}).top().right().grow().get().parent = null;
resizeButton();
}
boolean hold = false;
int pastX, pastY;
@Override
public void update() {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
resetPane();
}
if(tool != null) {
if(Core.input.isTouched()) {
if(!(!mobile&&Core.input.keyDown(KeyCode.mouseLeft))) return;
if(tool== EditorTool.line) {
if(!hold) {
pastX = (int) player.mouseX / 8;
pastY = (int) player.mouseY / 8;
}
hold = true;
}
else {
pastX = (int) player.mouseX / 8;
pastY = (int) player.mouseY / 8;
}
tool.touched(pastX, pastY);
}
else if(tool== EditorTool.line) {
if(hold&&pastX>=0&&pastY>=0) tool.touchedLine(pastX, pastY, (int) player.mouseX/8, (int) player.mouseY/8);
hold = false;
pastX = -1;
pastY = -1;
}
}
}
void resetPane() {
ScrollPane pane = find("editor-pane");
pane.setWidget(rebuild());
}
public Table rebuild() {
return new Table(table-> {
table.top();
Seq<Block> blocks = Vars.content.blocks().copy();
if(search.getText().length() > 0){
blocks.filter(p -> p.name.toLowerCase().contains(search.getText().toLowerCase())||p.localizedName.toLowerCase().contains(search.getText().toLowerCase()));
}
table.table(select->buildTable(Blocks.boulder, select, blocks, ()->selected, block->selected=block, false)).marginTop(16f).marginBottom(16f).row();
table.image().height(4f).color(Pal.gray).growX().row();
table.table(body-> {
body.table(tools -> {
tools.top().left();
tools.table(title -> title.left().background(Tex.underline2).add("Tools [accent]"+(tool==null?"":tool.name())+"[]")).growX().row();
tools.table(bt->{
Cons<UnitInfo.ui.EditorTool> addTool = tool -> {
ImageButton button = new ImageButton(ui.getIcon(tool.name()), Styles.clearTogglei);
button.clicked(() -> {
button.toggle();
if(this.tool==tool) this.tool = null;
else this.tool = tool;
resetPane();
});
button.update(()->button.setChecked(this.tool == tool));
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;
bt.stack(button, mode);
};
addTool.get(UnitInfo.ui.EditorTool.line);
addTool.get(UnitInfo.ui.EditorTool.pencil);
addTool.get(UnitInfo.ui.EditorTool.eraser);
addTool.get(UnitInfo.ui.EditorTool.fill);
addTool.get(UnitInfo.ui.EditorTool.spray);
});
tools.row();
Slider slider = new Slider(1, 16, 1, false);
slider.moved(size->brushSize=size);
slider.setValue(brushSize);
Label label = new Label("Brush: "+brushSize);
label.touchable = Touchable.disabled;
tools.stack(slider, label).width(window.getWidth()/5).center();
}).left().width(window.getWidth() / 2).margin(8f).growY();
body.image().width(4f).height(body.getHeight()).color(Pal.gray).growY();
body.table(options -> {
options.top().left();
options.table(title -> title.left().background(Tex.underline2).add("Options [accent]"+(tool!=null&&tool.mode>=0&&tool.mode<tool.altModes.length?tool.altModes[tool.mode]:"")+"[]")).growX().row();
options.table(option-> {
option.defaults().size(300f, 70f).left();
if(tool==null) return;
for (int i = 0; i < tool.altModes.length; i++) {
int mode = i;
String name = tool.altModes[i];
option.button(b -> {
b.left().marginLeft(6);
b.setStyle(Styles.clearTogglet);
b.add(Core.bundle.get("toolmode." + name)).left().row();
b.add(Core.bundle.get("toolmode." + name + ".description")).color(Color.lightGray).left();
}, () -> {
tool.mode = (tool.mode == mode ? -1 : mode);
}).update(b -> b.setChecked(tool.mode == mode));
option.row();
}
});
}).left().width(window.getWidth() / 2).margin(8f).growY();
}).grow();
});
}
<T extends Block> void buildTable(@Nullable Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){
ButtonGroup<ImageButton> group = new ButtonGroup<>();
group.setMinCheckCount(0);
Table cont = new Table();
cont.defaults().size(40);
int i = 0;
int max = Math.max(4, Math.round(window.getWidth()/64));
for(T item : items){
if(!item.unlockedNow()) continue;
ImageButton button = cont.button(Tex.whiteui, Styles.clearToggleTransi, 24, () -> {
if(closeSelect) control.input.frag.config.hideConfig();
}).group(group).tooltip(t->t.background(Styles.black8).add(item.localizedName)).get();
button.changed(() -> consumer.get(button.isChecked() ? item : null));
button.getStyle().imageUp = new TextureRegionDrawable(item.uiIcon);
button.update(() -> button.setChecked(holder.get() == item));
if(i++ % max == max-1){
cont.row();
}
}
//add extra blank spaces so it looks nice
if(i % max != 0){
int remaining = max - (i % max);
for(int j = 0; j < remaining; j++){
cont.image(Styles.black6);
}
}
ScrollPane pane = new ScrollPane(cont, Styles.smallPane);
pane.setScrollingDisabled(true, false);
if(block != null){
pane.setScrollYForce(block.selectScroll);
pane.update(() -> {
block.selectScroll = pane.getScrollY();
});
}
pane.setOverscroll(false, false);
table.add(pane).maxHeight(Scl.scl(40 * 5));
}
public void drawBlocksReplace(int x, int y){
drawBlocks(x, y, tile -> tile.block() != Blocks.air || selected.isFloor());
}
public void drawBlocks(int x, int y){
drawBlocks(x, y, false, tile -> true);
}
public void drawBlocks(int x, int y, Boolf<Tile> tester){
drawBlocks(x, y, false, tester);
}
int rotation = 0;
public void drawBlocks(int x, int y, boolean square, Boolf<Tile> tester){
if(selected.isMultiblock()){
x = Mathf.clamp(x, (selected.size - 1) / 2, world.width() - selected.size / 2 - 1);
y = Mathf.clamp(y, (selected.size - 1) / 2, world.height() - selected.size / 2 - 1);
if(!hasOverlap(x, y)){
world.tile(x, y).setBlock(selected, drawTeam, rotation);
}
}else{
boolean isFloor = selected.isFloor() && selected != Blocks.air;
Cons<Tile> drawer = tile -> {
if(!tester.get(tile)) return;
if(isFloor){
tile.setFloor(selected.asFloor());
}else if(!(tile.block().isMultiblock() && !selected.isMultiblock())){
tile.setBlock(selected, drawTeam, rotation);
}
};
if(square){
drawSquare(x, y, drawer);
}else{
drawCircle(x, y, drawer);
}
}
}
public void drawCircle(int x, int y, Cons<Tile> drawer){
int clamped = (int)brushSize;
for(int rx = -clamped; rx <= clamped; rx++){
for(int ry = -clamped; ry <= clamped; ry++){
if(Mathf.within(rx, ry, brushSize - 0.5f + 0.0001f)){
int wx = x + rx, wy = y + ry;
if(wx < 0 || wy < 0 || wx >= world.width() || wy >= world.height()){
continue;
}
drawer.get(world.tile(wx, wy));
}
}
}
}
public void drawSquare(int x, int y, Cons<Tile> drawer){
int clamped = (int)brushSize;
for(int rx = -clamped; rx <= clamped; rx++){
for(int ry = -clamped; ry <= clamped; ry++){
int wx = x + rx, wy = y + ry;
if(wx < 0 || wy < 0 || wx >= world.width() || wy >= world.height()){
continue;
}
drawer.get(world.tile(wx, wy));
}
}
}
boolean hasOverlap(int x, int y){
Tile tile = world.tile(x, y);
//allow direct replacement of blocks of the same size
if(tile != null && tile.isCenter() && tile.block() != selected && tile.block().size == selected.size && tile.x == x && tile.y == y){
return false;
}
//else, check for overlap
int offsetx = -(selected.size - 1) / 2;
int offsety = -(selected.size - 1) / 2;
for(int dx = 0; dx < selected.size; dx++){
for(int dy = 0; dy < selected.size; dy++){
int worldx = dx + offsetx + x;
int worldy = dy + offsety + y;
Tile other = world.tile(worldx, worldy);
if(other != null && other.block().isMultiblock()){
return true;
}
}
}
return false;
}
}

View File

@@ -23,9 +23,9 @@ import static mindustry.Vars.*;
public class PlayerDisplay extends WindowTable implements Updatable {
Vec2 scrollPos = new Vec2(0, 0);
TextField search;
ImageButton.ImageButtonStyle ustyle;
@Nullable Player target;
float heat;
ImageButton.ImageButtonStyle ustyle;
public PlayerDisplay() {
super("Player Display", Icon.players, t -> {});

View File

@@ -3,6 +3,7 @@ package UnitInfo.ui.windows;
public class WindowTables {
public static WindowTable
unitTable, waveTable, coreTable, playerTable, toolTable;
public static MapEditorDisplay editorTable;
public static void init() {
unitTable = new UnitDisplay();
@@ -10,5 +11,6 @@ public class WindowTables {
coreTable = new CoreDisplay();
playerTable = new PlayerDisplay();
toolTable = new ToolDisplay();
editorTable = new MapEditorDisplay();
}
}