Canvas block dialog refactored / Fixed crateredBattleground being in the wrong place

This commit is contained in:
Anuken
2026-03-12 22:18:01 -04:00
parent ab14f3dfb4
commit 1fb6c0976d
3 changed files with 209 additions and 164 deletions

View File

@@ -1 +1 @@
{presets:{windsweptIslands:97,stainedMountains:223,weatheredChannels:166,craters:219,extractionOutpost:213,littoralShipyard:204,coastline:164,navalFortress:165,frontier:86,sunkenPier:173,groundZero:170,mycelialBastion:143,facility32m:65,atolls:75,overgrowth:142,testingGrounds:169,frozenForest:64,saltFlats:98,taintedWoods:145,infestedCanyons:85,desolateRift:271,nuclearComplex:228,ruinousShores:41,planetaryTerminal:217,impact0078:266,perilousHarbor:214,fallenVessel:95,fungalPass:221,tarFields:99,biomassFacility:23},attackSectors:[0,6,13,16,19,20,24,27,30,47,55,66,67,69,76,92,94,103,111,116,127,133,138,150,157,161,162,176,180,185,191,192,197,200,207,225,230,237,240,242,243,244,245,246,247,248,251,254,259,263,265]}
{presets:{windsweptIslands:97,stainedMountains:223,weatheredChannels:166,crateredBattleground:219,extractionOutpost:213,littoralShipyard:204,coastline:164,navalFortress:165,frontier:86,sunkenPier:173,groundZero:170,mycelialBastion:143,facility32m:65,atolls:75,overgrowth:142,testingGrounds:169,frozenForest:64,saltFlats:98,taintedWoods:145,infestedCanyons:85,desolateRift:271,nuclearComplex:228,ruinousShores:41,planetaryTerminal:217,impact0078:266,perilousHarbor:214,fallenVessel:95,fungalPass:221,tarFields:99,biomassFacility:23},attackSectors:[0,6,13,16,19,20,24,27,30,47,55,66,67,69,76,92,94,103,111,116,127,133,138,150,157,161,162,176,180,185,191,192,197,200,207,225,230,237,240,242,243,244,245,246,247,248,251,254,259,263,265]}

View File

@@ -0,0 +1,206 @@
package mindustry.ui.dialogs;
import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.input.*;
import arc.math.*;
import arc.math.geom.*;
import arc.scene.*;
import arc.scene.event.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.ui.*;
import mindustry.world.blocks.logic.*;
import mindustry.world.blocks.logic.CanvasBlock.*;
import static mindustry.Vars.*;
public class CanvasEditDialog extends BaseDialog{
static final float refreshTime = 60f * 2f;
int curColor;
boolean fill, modified;
float time;
CanvasBuild canvas;
Pixmap pix;
public CanvasEditDialog(CanvasBuild canvas){
super("");
titleTable.remove();
this.canvas = canvas;
CanvasBlock block = (CanvasBlock)canvas.block;
int size = block.canvasSize;
pix = block.makePixmap(canvas.data, new Pixmap(size, size));
Texture texture = new Texture(pix);
curColor = block.palette[0];
addCloseButton();
hidden(() -> {
save();
texture.dispose();
pix.dispose();
});
resized(this::hide);
//update at an interval so that people can see what is being drawn
update(() -> {
time += Time.delta;
if(time >= refreshTime){
save();
time = 0f;
}
});
cont.table(Tex.pane, body -> {
body.add(new Element(){
int lastX, lastY;
IntSeq stack = new IntSeq();
int convertX(float ex){
return (int)((ex) / (width / size));
}
int convertY(float ey){
return pix.height - 1 - (int)((ey) / (height / size));
}
{
addListener(new InputListener(){
@Override
public boolean touchDown(InputEvent event, float ex, float ey, int pointer, KeyCode button){
int cx = convertX(ex), cy = convertY(ey);
if(button == KeyCode.mouseLeft){
if(fill){
stack.clear();
int src = curColor;
int dst = pix.get(cx, cy);
if(src != dst){
stack.add(Point2.pack(cx, cy));
while(!stack.isEmpty()){
int current = stack.pop();
int x = Point2.x(current), y = Point2.y(current);
draw(x, y);
for(int i = 0; i < 4; i++){
int nx = x + Geometry.d4x(i), ny = y + Geometry.d4y(i);
if(nx >= 0 && ny >= 0 && nx < pix.width && ny < pix.height && pix.getRaw(nx, ny) == dst){
stack.add(Point2.pack(nx, ny));
}
}
}
}
return false;
}else{
draw(cx, cy);
lastX = cx;
lastY = cy;
}
}else if(button == KeyCode.mouseMiddle){
curColor = pix.get(cx, cy);
return false;
}
return true;
}
@Override
public void touchDragged(InputEvent event, float ex, float ey, int pointer){
if(fill) return;
int cx = convertX(ex), cy = convertY(ey);
Bresenham2.line(lastX, lastY, cx, cy, (x, y) -> draw(x, y));
lastX = cx;
lastY = cy;
}
});
}
void draw(int x, int y){
if(pix.get(x, y) != curColor){
pix.set(x, y, curColor);
Pixmaps.drawPixel(texture, x, y, curColor);
modified = true;
}
}
@Override
public void draw(){
Tmp.tr1.set(texture);
Draw.alpha(parentAlpha);
Draw.rect(Tmp.tr1, x + width/2f, y + height/2f, width, height);
//draw grid
{
float xspace = (getWidth() / size);
float yspace = (getHeight() / size);
float s = 1f;
int minspace = 10;
int jumpx = (int)(Math.max(minspace, xspace) / xspace);
int jumpy = (int)(Math.max(minspace, yspace) / yspace);
for(int x = 0; x <= size; x += jumpx){
Fill.crect((int)(this.x + xspace * x - s), y - s, 2, getHeight() + (x == size ? 1 : 0));
}
for(int y = 0; y <= size; y += jumpy){
Fill.crect(x - s, (int)(this.y + y * yspace - s), getWidth(), 2);
}
}
if(!mobile){
Vec2 s = screenToLocalCoordinates(Core.input.mouse());
if(s.x >= 0 && s.y >= 0 && s.x < width && s.y < height){
float sx = Mathf.round(s.x, width / size), sy = Mathf.round(s.y, height / size);
Lines.stroke(Scl.scl(6f));
Draw.color(Pal.accent);
Lines.rect(sx + x, sy + y, width / size, height / size, Lines.getStroke() - 1f);
Draw.reset();
}
}
}
}).size(mobile && !Core.graphics.isPortrait() ? Math.min(290f, Core.graphics.getHeight() / Scl.scl(1f) - 75f / Scl.scl(1f)) : 480f);
}).colspan(3);
cont.row();
cont.add().size(60f);
cont.table(Tex.button, p -> {
for(int i = 0; i < block.palette.length; i++){
int fi = i;
var button = p.button(Tex.whiteui, Styles.squareTogglei, 30, () -> {
curColor = block.palette[fi];
}).size(44).checked(b -> curColor == block.palette[fi]).get();
button.getStyle().imageUpColor = new Color(block.palette[i]);
}
});
cont.table(Tex.button, t -> {
t.button(Icon.fill, Styles.clearNoneTogglei, () -> fill = !fill).size(44f);
});
closeOnBack();
buttons.defaults().size(150f, 64f);
}
void save(){
if(modified){
canvas.configure(canvas.packPixmap(pix));
modified = false;
}
}
}

View File

@@ -1,14 +1,9 @@
package mindustry.world.blocks.logic;
import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.input.*;
import arc.math.*;
import arc.math.geom.*;
import arc.scene.*;
import arc.scene.event.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
@@ -16,9 +11,9 @@ import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.ui.*;
import mindustry.ui.dialogs.*;
import mindustry.world.*;
import static mindustry.Vars.*;
@@ -307,163 +302,7 @@ public class CanvasBlock extends Block{
@Override
public void buildConfiguration(Table table){
table.button(Icon.pencil, Styles.cleari, () -> {
Dialog dialog = new Dialog();
Pixmap pix = makePixmap(data, new Pixmap(canvasSize, canvasSize));
Texture texture = new Texture(pix);
int[] curColor = {palette[0]};
boolean[] modified = {false};
boolean[] fill = {false};
dialog.hidden(() -> {
texture.dispose();
pix.dispose();
});
dialog.resized(dialog::hide);
dialog.cont.table(Tex.pane, body -> {
body.add(new Element(){
int lastX, lastY;
IntSeq stack = new IntSeq();
int convertX(float ex){
return (int)((ex) / (width / canvasSize));
}
int convertY(float ey){
return pix.height - 1 - (int)((ey) / (height / canvasSize));
}
{
addListener(new InputListener(){
@Override
public boolean touchDown(InputEvent event, float ex, float ey, int pointer, KeyCode button){
int cx = convertX(ex), cy = convertY(ey);
if(fill[0]){
stack.clear();
int src = curColor[0];
int dst = pix.get(cx, cy);
if(src != dst){
stack.add(Point2.pack(cx, cy));
while(!stack.isEmpty()){
int current = stack.pop();
int x = Point2.x(current), y = Point2.y(current);
draw(x, y);
for(int i = 0; i < 4; i++){
int nx = x + Geometry.d4x(i), ny = y + Geometry.d4y(i);
if(nx >= 0 && ny >= 0 && nx < pix.width && ny < pix.height && pix.getRaw(nx, ny) == dst){
stack.add(Point2.pack(nx, ny));
}
}
}
}
}else{
draw(cx, cy);
lastX = cx;
lastY = cy;
}
return true;
}
@Override
public void touchDragged(InputEvent event, float ex, float ey, int pointer){
if(fill[0]) return;
int cx = convertX(ex), cy = convertY(ey);
Bresenham2.line(lastX, lastY, cx, cy, (x, y) -> draw(x, y));
lastX = cx;
lastY = cy;
}
});
}
void draw(int x, int y){
if(pix.get(x, y) != curColor[0]){
pix.set(x, y, curColor[0]);
Pixmaps.drawPixel(texture, x, y, curColor[0]);
modified[0] = true;
}
}
@Override
public void draw(){
Tmp.tr1.set(texture);
Draw.alpha(parentAlpha);
Draw.rect(Tmp.tr1, x + width/2f, y + height/2f, width, height);
//draw grid
{
float xspace = (getWidth() / canvasSize);
float yspace = (getHeight() / canvasSize);
float s = 1f;
int minspace = 10;
int jumpx = (int)(Math.max(minspace, xspace) / xspace);
int jumpy = (int)(Math.max(minspace, yspace) / yspace);
for(int x = 0; x <= canvasSize; x += jumpx){
Fill.crect((int)(this.x + xspace * x - s), y - s, 2, getHeight() + (x == canvasSize ? 1 : 0));
}
for(int y = 0; y <= canvasSize; y += jumpy){
Fill.crect(x - s, (int)(this.y + y * yspace - s), getWidth(), 2);
}
}
if(!mobile){
Vec2 s = screenToLocalCoordinates(Core.input.mouse());
if(s.x >= 0 && s.y >= 0 && s.x < width && s.y < height){
float sx = Mathf.round(s.x, width / canvasSize), sy = Mathf.round(s.y, height / canvasSize);
Lines.stroke(Scl.scl(6f));
Draw.color(Pal.accent);
Lines.rect(sx + x, sy + y, width / canvasSize, height / canvasSize, Lines.getStroke() - 1f);
Draw.reset();
}
}
}
}).size(mobile && !Core.graphics.isPortrait() ? Math.min(290f, Core.graphics.getHeight() / Scl.scl(1f) - 75f / Scl.scl(1f)) : 480f);
}).colspan(3);
dialog.cont.row();
dialog.cont.add().size(60f);
dialog.cont.table(Tex.button, p -> {
for(int i = 0; i < palette.length; i++){
int fi = i;
var button = p.button(Tex.whiteui, Styles.squareTogglei, 30, () -> {
curColor[0] = palette[fi];
}).size(44).checked(b -> curColor[0] == palette[fi]).get();
button.getStyle().imageUpColor = new Color(palette[i]);
}
});
dialog.cont.table(Tex.button, t -> {
t.button(Icon.fill, Styles.clearNoneTogglei, () -> {
fill[0] = !fill[0];
}).size(44f);
});
dialog.closeOnBack();
dialog.buttons.defaults().size(150f, 64f);
dialog.buttons.button("@cancel", Icon.cancel, dialog::hide);
dialog.buttons.button("@ok", Icon.ok, () -> {
if(modified[0]){
configure(packPixmap(pix));
}
dialog.hide();
});
dialog.show();
}).size(40f);
table.button(Icon.pencil, Styles.cleari, () -> new CanvasEditDialog(this).show()).size(40f);
}
@Override