Better colored floor/wall support

This commit is contained in:
Anuken
2025-07-17 16:09:45 -04:00
parent 4c8f956fef
commit 24cfb000de
19 changed files with 134 additions and 84 deletions

View File

@@ -905,16 +905,10 @@ public class Blocks{
autotile = true;
drawEdgeOut = false;
drawEdgeIn = false;
//there is no proper support for displaying colors or placing with colors
inEditor = false;
}};
coloredWall = new ColoredWall("colored-wall"){{
autotile = true;
//there is no proper support for displaying colors or placing with colors
inEditor = false;
//TODO: should this apply darkness?
//fillsTile = false;
}};
Seq.with(metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor4, metalFloor5, darkPanel1, darkPanel2, darkPanel3, darkPanel4, darkPanel5, darkPanel6)

View File

@@ -36,6 +36,7 @@ public class EditorTile extends Tile{
op(DrawOperation.opFloor, floor.id);
this.floor = type;
type.floorChanged(this);
}
@Override

View File

@@ -134,6 +134,10 @@ public class MapRenderer implements Disposable{
width, height,
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg());
}else{
if(floor instanceof ColoredFloor){
mesh.setColor(Tmp.c1.set(tile.extraData | 0xff));
}
region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)];
mesh.draw(idxWall, region, wx * tilesize, wy * tilesize, 8, 8);
@@ -155,6 +159,8 @@ public class MapRenderer implements Disposable{
if(wall == Blocks.cliff){
mesh.setColor(Tmp.c1.set(floor.mapColor).mul(1.6f));
region = ((Cliff)Blocks.cliff).editorCliffs[tile.data & 0xff];
}else if(wall instanceof ColoredWall){
mesh.setColor(Tmp.c1.set(tile.extraData | 0xff));
}
offsetX = tilesize / 2f - region.width * region.scl() / 2f;

View File

@@ -1627,6 +1627,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
/** Draws a placement icon for a specific block. */
protected void drawPlan(int x, int y, Block block, int rotation){
bplan.set(x, y, rotation, block);
if(block.saveConfig){
bplan.config = block.lastConfig;
}
bplan.animScale = 1f;
block.drawPlan(bplan, allPlans(), validPlace(x, y, block, rotation));
}

View File

@@ -139,6 +139,23 @@ public class MapIO{
}
return tile;
}
@Override
public void onReadTileData(){
//colored floor/wall tile data will affect the map preview
if(!tile.block().synthetic() && tile.block() != Blocks.air){
int color = tile.block().minimapColor(tile);
if(color != 0){
walls.set(tile.x, walls.height - 1 - tile.y, color);
}
}else if(tile.overlay() == Blocks.air && tile.block() == Blocks.air){
int color = tile.floor().minimapColor(tile);
if(color != 0){
floors.set(tile.x, floors.height - 1 - tile.y, color);
}
}
}
}));
floors.draw(walls, true);
@@ -154,7 +171,14 @@ public class MapIO{
for(int x = 0; x < pixmap.width; x++){
for(int y = 0; y < pixmap.height; y++){
Tile tile = tiles.getn(x, y);
pixmap.set(x, pixmap.height - 1 - y, colorFor(tile.block(), tile.floor(), tile.overlay(), tile.team()));
int color = 0;
if(!tile.block().synthetic() && tile.block() != Blocks.air){
color = tile.block().minimapColor(tile);
}else if(tile.overlay() == Blocks.air && tile.block() == Blocks.air){
color = tile.floor().minimapColor(tile);
}
if(color == 0) color = colorFor(tile.block(), tile.floor(), tile.overlay(), tile.team());
pixmap.set(x, pixmap.height - 1 - y, color);
}
}
return pixmap;

View File

@@ -347,6 +347,7 @@ public abstract class SaveVersion extends SaveFileReader{
tile.floorData = floorData;
tile.overlayData = overlayData;
tile.extraData = extraData;
context.onReadTileData();
}
if(hadEntity){

View File

@@ -78,6 +78,24 @@ public class HudFragment{
.name("editor/search").maxTextLength(maxNameLength).get().setMessageText("@players.search");
}).growX().pad(-2).padLeft(6f);
cont.row();
cont.collapser(t -> {
t.button(b -> {
b.margin(4f);
b.left();
b.table(Tex.pane, in -> {
in.image(Tex.whiteui).update(i -> {
if(control.input.block != null && control.input.block.lastConfig instanceof Integer col){
i.color.set(col | 0xff);
}
}).grow();
}).margin(4).size(50f).padRight(10);
b.add("@color");
}, Styles.cleart, () -> ui.picker.show(control.input.block != null && control.input.block.lastConfig instanceof Integer col ? new Color(col | 0xff) : new Color(Color.white), false, col -> {
if(control.input.block != null){
control.input.block.lastConfig = col.rgba8888();
}
})).left().width(250f).pad(3f).row();
}, () -> control.input.block != null && control.input.block.showColorEdit).growX().row();
cont.add(pane).expandY().top().left();
rebuildBlockSelection(blockSelection, "");

View File

@@ -126,39 +126,41 @@ public class PlacementFragment{
}
boolean updatePick(InputHandler input){
if(Core.input.keyTap(Binding.pick) && player.isBuilder() && !Core.scene.hasDialog()){ //mouse eyedropper select
var build = world.buildWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
Tile tile = world.tileWorld(Core.input.mouseWorldX(), Core.input.mouseWorldY());
if(tile != null && Core.input.keyTap(Binding.pick) && player.isBuilder() && !Core.scene.hasDialog()){ //mouse eyedropper select
var build = tile.build;
//can't middle click buildings in fog
if(build != null && build.inFogTo(player.team())){
build = null;
}
Block tryRecipe = build == null ? null : build instanceof ConstructBuild c ? c.current : build.block;
Block tryBlock = build == null ? null : build instanceof ConstructBuild c ? c.current : build.block;
Object tryConfig = build == null || !build.block.copyConfig ? null : build.config();
if(tryBlock != null && tryBlock.showColorEdit && tryConfig == null){
tryConfig = tile.extraData;
}
for(BuildPlan req : player.unit().plans()){
if(!req.breaking && req.block.bounds(req.x, req.y, Tmp.r1).contains(Core.input.mouseWorld())){
tryRecipe = req.block;
tryBlock = req.block;
tryConfig = req.config;
break;
}
}
if(tryRecipe == null && state.rules.editor){
var tile = world.tileWorld(Core.input.mouseWorldX(), Core.input.mouseWorldY());
if(tile != null){
tryRecipe =
if(tryBlock == null && state.rules.editor){
tryBlock =
tile.block() != Blocks.air ? tile.block() :
tile.overlay() != Blocks.air ? tile.overlay() :
tile.floor() != Blocks.air ? tile.floor() : null;
}
}
if(tryRecipe != null && ((tryRecipe.isVisible() && unlocked(tryRecipe)) || state.rules.editor)){
input.block = tryRecipe;
tryRecipe.lastConfig = tryConfig;
if(tryRecipe.isVisible()){
if(tryBlock != null && ((tryBlock.isVisible() && unlocked(tryBlock)) || state.rules.editor)){
input.block = tryBlock;
tryBlock.lastConfig = tryConfig;
if(tryBlock.isVisible()){
currentCategory = input.block.category;
}
return true;

View File

@@ -80,6 +80,8 @@ public class Block extends UnlockableContent implements Senseable{
public boolean displayFlow = true;
/** whether this block is visible in the editor */
public boolean inEditor = true;
/** if true, a color picker will be shown for the lastConfig field in the in-game-editor, and will be assigned as an integer. */
public boolean showColorEdit;
/** the last configuration value applied to this block. */
public @Nullable Object lastConfig;
/** whether to save the last config and apply it to newly placed blocks */

View File

@@ -26,6 +26,9 @@ public interface WorldContext{
/** Called when a building is finished reading. */
default void onReadBuilding(){}
/** Called when data finishes reading for a tile. */
default void onReadTileData(){}
default @Nullable Sector getSector(){
return null;
}

View File

@@ -24,12 +24,14 @@ public class ColoredFloor extends Floor{
public ColoredFloor(String name){
super(name);
saveData = true;
showColorEdit = true;
saveConfig = true;
}
@Override
public void init(){
super.init();
defaultColorRgba = defaultColor.rgba();
lastConfig = defaultColorRgba = defaultColor.rgba();
}
@Override
@@ -132,7 +134,9 @@ public class ColoredFloor extends Floor{
@Override
public void floorChanged(Tile tile){
//reset to white
tile.extraData = defaultColorRgba;
if(tile.extraData == 0){
tile.extraData = defaultColorRgba;
}
}
@Override

View File

@@ -19,17 +19,19 @@ public class ColoredWall extends StaticWall{
public ColoredWall(String name){
super(name);
saveData = true;
showColorEdit = true;
saveConfig = true;
}
@Override
public void init(){
super.init();
defaultColorRgba = defaultColor.rgba();
lastConfig = defaultColorRgba = defaultColor.rgba();
}
@Override
public void drawBase(Tile tile){
//make sure to mask out the alpha channel - it's generally undesirable, and leads to invisible blocks when the data is not initialized
//make sure to mask out the alpha channel - it's generally undesirable, and leads to invisible blocks when thtoe data is not initialized
Draw.color(tile.extraData | 0xff);
super.drawBase(tile);
Draw.color();
@@ -37,8 +39,10 @@ public class ColoredWall extends StaticWall{
@Override
public void blockChanged(Tile tile){
//reset to white
tile.extraData = defaultColorRgba;
//reset to white on first placement
if(tile.extraData == 0){
tile.extraData = defaultColorRgba;
}
}
@Override
@@ -59,12 +63,12 @@ public class ColoredWall extends StaticWall{
@Override
public boolean checkAutotileSame(Tile tile, @Nullable Tile other){
return other != null && other.block() == this && ((tile.extraData & flagIgnoreDifferentColor) != 0 || tile.extraData == other.extraData);
return other != null && other.block() == this && ((tile.extraData == flagIgnoreDifferentColor) || tile.extraData == other.extraData);
}
@Override
public boolean isDarkened(Tile tile){
return (tile.extraData & flagApplyDarkness) != 0;
return (tile.extraData == flagApplyDarkness);
}
@Override

View File

@@ -378,19 +378,6 @@ public class Floor extends Block{
}
}
//'new' style of edges with shadows instead of colors, not used currently
protected void drawEdgesFlat(Tile tile, boolean sameLayer){
for(int i = 0; i < 4; i++){
Tile other = tile.nearby(i);
if(other != null && doEdge(tile, other, other.floor())){
Color color = other.floor().mapColor;
Draw.color(color.r, color.g, color.b, 1f);
Draw.rect(edgeRegion, tile.worldx(), tile.worldy(), i*90);
}
}
Draw.color();
}
public int realBlendId(Tile tile){
if(tile.floor().isLiquid && !tile.overlay().isAir() && !(tile.overlay() instanceof OreBlock)){
return -((tile.overlay().blendId) | (tile.floor().blendId << 15));