mirror of
https://github.com/yawaflua/Informatis.git
synced 2025-12-10 20:19:26 +02:00
map editor windows - edit tools
This commit is contained in:
268
src/UnitInfo/ui/EditorTool.java
Normal file
268
src/UnitInfo/ui/EditorTool.java
Normal file
@@ -0,0 +1,268 @@
|
||||
package UnitInfo.ui;
|
||||
|
||||
import UnitInfo.ui.windows.WindowTables;
|
||||
import arc.func.Boolf;
|
||||
import arc.func.Cons;
|
||||
import arc.input.KeyCode;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.Bresenham2;
|
||||
import arc.math.geom.Point2;
|
||||
import arc.struct.IntSeq;
|
||||
import arc.util.Structs;
|
||||
import mindustry.content.Blocks;
|
||||
import mindustry.game.Team;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
import static UnitInfo.ui.windows.MapEditorDisplay.drawTeam;
|
||||
import static UnitInfo.ui.windows.MapEditorDisplay.selected;
|
||||
import static UnitInfo.ui.windows.WindowTables.editorTable;
|
||||
import static mindustry.Vars.world;
|
||||
|
||||
public enum EditorTool{
|
||||
zoom(KeyCode.v),
|
||||
pick(KeyCode.i){
|
||||
public void touched(int x, int y){
|
||||
if(!Structs.inBounds(x, y, world.width(), world.height())) return;
|
||||
|
||||
Tile tile = world.tile(x, y);
|
||||
selected = tile.block() == Blocks.air || !tile.block().inEditor ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
|
||||
}
|
||||
},
|
||||
line(KeyCode.l, "replace", "orthogonal"){
|
||||
|
||||
@Override
|
||||
public void touchedLine(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
|
||||
editorTable.drawBlocksReplace(x, y);
|
||||
}else{
|
||||
//normal
|
||||
editorTable.drawBlocks(x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
pencil(KeyCode.b, "replace", "square", "drawteams"){
|
||||
{
|
||||
edit = true;
|
||||
draggable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touched(int x, int y){
|
||||
if(mode == -1){
|
||||
//normal mode
|
||||
editorTable.drawBlocks(x, y);
|
||||
}else if(mode == 0){
|
||||
//replace mode
|
||||
editorTable.drawBlocksReplace(x, y);
|
||||
}else if(mode == 1){
|
||||
//square mode
|
||||
editorTable.drawBlocks(x, y, true, tile -> true);
|
||||
}else if(mode == 2){
|
||||
//draw teams
|
||||
editorTable.drawCircle(x, y, tile -> tile.setTeam(drawTeam));
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
eraser(KeyCode.e, "eraseores"){
|
||||
{
|
||||
edit = true;
|
||||
draggable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touched(int x, int y){
|
||||
editorTable.drawCircle(x, y, tile -> {
|
||||
if(mode == -1){
|
||||
//erase block
|
||||
tile.remove();
|
||||
}else if(mode == 0){
|
||||
//erase ore
|
||||
tile.clearOverlay();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
fill(KeyCode.g, "replaceall", "fillteams"){
|
||||
{
|
||||
edit = true;
|
||||
}
|
||||
|
||||
IntSeq stack = new IntSeq();
|
||||
|
||||
@Override
|
||||
public void touched(int x, int y){
|
||||
if(!Structs.inBounds(x, y, world.width(), world.height()) || world.tile(x, y).block()!=null&&world.tile(x, y).block().isMultiblock()) return;
|
||||
Tile tile = world.tile(x, y);
|
||||
|
||||
//mode 0 or 1, fill everything with the floor/tile or replace it
|
||||
if(mode == 0 || mode == -1){
|
||||
if(tile.block().isMultiblock()) return;
|
||||
|
||||
Boolf<Tile> tester;
|
||||
Cons<Tile> setter;
|
||||
Block drawBlock = selected;
|
||||
|
||||
if(drawBlock.isOverlay()){
|
||||
Block dest = tile.overlay();
|
||||
if(dest == drawBlock) return;
|
||||
tester = t -> t.overlay() == dest && (t.floor().hasSurface() || !t.floor().needsSurface);
|
||||
setter = t -> t.setOverlay(drawBlock);
|
||||
}else if(drawBlock.isFloor()){
|
||||
Block dest = tile.floor();
|
||||
if(dest == drawBlock) return;
|
||||
tester = t -> t.floor() == dest;
|
||||
setter = t -> t.setFloorUnder(drawBlock.asFloor());
|
||||
}else{
|
||||
Block dest = tile.block();
|
||||
if(dest == drawBlock) return;
|
||||
tester = t -> t.block() == dest;
|
||||
setter = t -> t.setBlock(drawBlock, drawTeam);
|
||||
}
|
||||
|
||||
//replace only when the mode is 0 using the specified functions
|
||||
fill(x, y, mode == 0, tester, setter);
|
||||
}else if(mode == 1){ //mode 1 is team fill
|
||||
//only fill synthetic blocks, it's meaningless otherwise
|
||||
if(tile.synthetic()){
|
||||
Team dest = tile.team();
|
||||
if(dest == drawTeam) return;
|
||||
fill(x, y, false, t -> t.getTeamID() == dest.id && t.synthetic(), t -> t.setTeam(drawTeam));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fill(int x, int y, boolean replace, Boolf<Tile> tester, Cons<Tile> filler){
|
||||
int width = world.width(), height = world.height();
|
||||
|
||||
if(replace){
|
||||
//just do it on everything
|
||||
for(int cx = 0; cx < width; cx++){
|
||||
for(int cy = 0; cy < height; cy++){
|
||||
Tile tile = world.tile(cx, cy);
|
||||
if(tester.get(tile)){
|
||||
filler.get(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
//perform flood fill
|
||||
int x1;
|
||||
|
||||
stack.clear();
|
||||
stack.add(Point2.pack(x, y));
|
||||
|
||||
try{
|
||||
while(stack.size > 0 && stack.size < width*height){
|
||||
int popped = stack.pop();
|
||||
x = Point2.x(popped);
|
||||
y = Point2.y(popped);
|
||||
|
||||
x1 = x;
|
||||
while(x1 >= 0 && tester.get(world.tile(x1, y))) x1--;
|
||||
x1++;
|
||||
boolean spanAbove = false, spanBelow = false;
|
||||
while(x1 < width && tester.get(world.tile(x1, y))){
|
||||
filler.get(world.tile(x1, y));
|
||||
|
||||
if(!spanAbove && y > 0 && tester.get(world.tile(x1, y - 1))){
|
||||
stack.add(Point2.pack(x1, y - 1));
|
||||
spanAbove = true;
|
||||
}else if(spanAbove && !tester.get(world.tile(x1, y - 1))){
|
||||
spanAbove = false;
|
||||
}
|
||||
|
||||
if(!spanBelow && y < height - 1 && tester.get(world.tile(x1, y + 1))){
|
||||
stack.add(Point2.pack(x1, y + 1));
|
||||
spanBelow = true;
|
||||
}else if(spanBelow && y < height - 1 && !tester.get(world.tile(x1, y + 1))){
|
||||
spanBelow = false;
|
||||
}
|
||||
x1++;
|
||||
}
|
||||
}
|
||||
stack.clear();
|
||||
}catch(OutOfMemoryError e){
|
||||
//hack
|
||||
stack = null;
|
||||
System.gc();
|
||||
e.printStackTrace();
|
||||
stack = new IntSeq();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
spray(KeyCode.r, "replace"){
|
||||
final double chance = 0.012;
|
||||
|
||||
{
|
||||
edit = true;
|
||||
draggable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touched(int x, int y){
|
||||
//floor spray
|
||||
if(selected.isFloor()){
|
||||
editorTable.drawCircle(x, y, tile -> {
|
||||
if(Mathf.chance(chance)){
|
||||
tile.setFloor(selected.asFloor());
|
||||
}
|
||||
});
|
||||
}else if(mode == 0){ //replace-only mode, doesn't affect air
|
||||
editorTable.drawBlocks(x, y, tile -> Mathf.chance(chance) && tile.block() != Blocks.air);
|
||||
}else{
|
||||
editorTable.drawBlocks(x, y, tile -> Mathf.chance(chance));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static final EditorTool[] all = values();
|
||||
|
||||
/** All the internal alternate placement modes of this tool. */
|
||||
public final String[] altModes;
|
||||
/** Key to activate this tool. */
|
||||
public KeyCode key = KeyCode.unset;
|
||||
/** 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;
|
||||
|
||||
EditorTool(){
|
||||
this(new String[]{});
|
||||
}
|
||||
|
||||
EditorTool(KeyCode code){
|
||||
this(new String[]{});
|
||||
this.key = code;
|
||||
}
|
||||
|
||||
EditorTool(String... altModes){
|
||||
this.altModes = altModes;
|
||||
}
|
||||
|
||||
EditorTool(KeyCode code, String... altModes){
|
||||
this.altModes = altModes;
|
||||
this.key = code;
|
||||
}
|
||||
|
||||
public void touched(int x, int y){}
|
||||
|
||||
public void touchedLine(int x1, int y1, int x2, int y2){}
|
||||
}
|
||||
@@ -19,7 +19,8 @@ public class HUDFragment extends Fragment{
|
||||
waveTable,
|
||||
coreTable,
|
||||
playerTable,
|
||||
toolTable
|
||||
toolTable,
|
||||
editorTable
|
||||
)).visible(TaskbarTable.visibility);
|
||||
|
||||
// windows (totally not a copyright violation)
|
||||
@@ -28,6 +29,7 @@ public class HUDFragment extends Fragment{
|
||||
t.add(coreTable).size(250f).visible(false);
|
||||
t.add(playerTable).size(250f).visible(false);
|
||||
t.add(toolTable).size(250f).visible(false);
|
||||
t.add(editorTable).size(250f).visible(false);
|
||||
|
||||
t.update(()->{
|
||||
for (Element child : t.getChildren()) {
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
package UnitInfo.ui.draws;
|
||||
|
||||
import arc.Events;
|
||||
import arc.func.Boolf;
|
||||
import arc.func.Cons;
|
||||
import arc.input.KeyCode;
|
||||
import arc.math.Angles;
|
||||
import arc.math.geom.Geometry;
|
||||
import arc.math.geom.Point2;
|
||||
import arc.scene.style.TextureRegionDrawable;
|
||||
import arc.scene.ui.Button;
|
||||
import arc.scene.ui.CheckBox;
|
||||
import arc.scene.ui.layout.Table;
|
||||
import arc.struct.IntSeq;
|
||||
import arc.util.Structs;
|
||||
import mindustry.content.Blocks;
|
||||
import mindustry.entities.Units;
|
||||
import mindustry.game.EventType;
|
||||
import mindustry.game.Team;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.logic.Ranged;
|
||||
import mindustry.world.Block;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.blocks.ControlBlock;
|
||||
import mindustry.world.blocks.defense.turrets.Turret;
|
||||
|
||||
@@ -20,6 +33,7 @@ public class UtilDraw extends OverDraw {
|
||||
UtilDraw(String name, TextureRegionDrawable icon) {
|
||||
super(name, icon);
|
||||
registerOption("autoShooting");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,4 +91,5 @@ public class UtilDraw extends OverDraw {
|
||||
unit.controlWeapons(player.shooting && !boosted);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
335
src/UnitInfo/ui/windows/MapEditorDisplay.java
Normal file
335
src/UnitInfo/ui/windows/MapEditorDisplay.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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 -> {});
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user