Tileable displays nobody asked for

This commit is contained in:
Anuken
2025-01-08 17:10:05 -05:00
parent 84dc0027a8
commit a24dfedb68
6 changed files with 185 additions and 22 deletions

View File

@@ -592,3 +592,4 @@
63090=remove-ore|block-remove-ore-ui 63090=remove-ore|block-remove-ore-ui
63089=small-heat-redirector|block-small-heat-redirector-ui 63089=small-heat-redirector|block-small-heat-redirector-ui
63088=large-cliff-crusher|block-large-cliff-crusher-ui 63088=large-cliff-crusher|block-large-cliff-crusher-ui
63087=tile-logic-display|block-tile-logic-display-ui

Binary file not shown.

View File

@@ -158,7 +158,7 @@ public class Blocks{
payloadConveyor, payloadRouter, reinforcedPayloadConveyor, reinforcedPayloadRouter, payloadMassDriver, largePayloadMassDriver, smallDeconstructor, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader, payloadConveyor, payloadRouter, reinforcedPayloadConveyor, reinforcedPayloadRouter, payloadMassDriver, largePayloadMassDriver, smallDeconstructor, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader,
//logic //logic
message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, memoryCell, memoryBank, message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, logicDisplayTile, memoryCell, memoryBank,
canvas, reinforcedMessage, canvas, reinforcedMessage,
worldProcessor, worldCell, worldMessage, worldSwitch, worldProcessor, worldCell, worldMessage, worldSwitch,
@@ -6066,6 +6066,10 @@ public class Blocks{
size = 6; size = 6;
}}; }};
logicDisplayTile = new TileableLogicDisplay("tile-logic-display"){{
requirements(Category.logic, with(Items.lead, 10, Items.silicon, 10, Items.metaglass, 10, Items.phaseFabric, 6));
}};
canvas = new CanvasBlock("canvas"){{ canvas = new CanvasBlock("canvas"){{
requirements(Category.logic, BuildVisibility.shown, with(Items.silicon, 10, Items.beryllium, 10)); requirements(Category.logic, BuildVisibility.shown, with(Items.silicon, 10, Items.beryllium, 10));

View File

@@ -935,11 +935,7 @@ public class LExecutor{
if(Vars.headless) return; if(Vars.headless) return;
if(target.building() instanceof LogicDisplayBuild d && (d.team == exec.team || exec.privileged)){ if(target.building() instanceof LogicDisplayBuild d && (d.team == exec.team || exec.privileged)){
if(d.commands.size + exec.graphicsBuffer.size < maxDisplayBuffer){ d.flushCommands(exec.graphicsBuffer);
for(int i = 0; i < exec.graphicsBuffer.size; i++){
d.commands.addLast(exec.graphicsBuffer.items[i]);
}
}
exec.graphicsBuffer.clear(); exec.graphicsBuffer.clear();
} }
} }

View File

@@ -13,6 +13,7 @@ import mindustry.annotations.Annotations.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.logic.*;
import mindustry.ui.*; import mindustry.ui.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
@@ -65,7 +66,7 @@ public class LogicDisplay extends Block{
} }
public class LogicDisplayBuild extends Building{ public class LogicDisplayBuild extends Building{
public FrameBuffer buffer; public @Nullable FrameBuffer buffer;
public float color = Color.whiteFloatBits; public float color = Color.whiteFloatBits;
public float stroke = 1f; public float stroke = 1f;
public LongQueue commands = new LongQueue(256); public LongQueue commands = new LongQueue(256);
@@ -87,12 +88,32 @@ public class LogicDisplay extends Block{
} }
}); });
processCommands();
Draw.blend(Blending.disabled);
Draw.draw(Draw.z(), () -> {
if(buffer != null){
Draw.rect(Draw.wrap(buffer.getTexture()), x, y, buffer.getWidth() * scaleFactor * Draw.scl, -buffer.getHeight() * scaleFactor * Draw.scl);
}
});
Draw.blend();
}
public void flushCommands(LongSeq graphicsBuffer){
int added = Math.min(graphicsBuffer.size, LExecutor.maxDisplayBuffer - commands.size);
for(int i = 0; i < added; i++){
commands.addLast(graphicsBuffer.items[i]);
}
}
public void processCommands(){
//don't bother processing commands if displays are off //don't bother processing commands if displays are off
if(!commands.isEmpty()){ if(!commands.isEmpty() && buffer != null){
Draw.draw(Draw.z(), () -> { Draw.draw(Draw.z(), () -> {
Tmp.m1.set(Draw.proj()); Tmp.m1.set(Draw.proj());
Tmp.m2.set(Draw.trans()); Tmp.m2.set(Draw.trans());
Draw.proj(0, 0, displaySize, displaySize); Draw.proj(0, 0, buffer.getWidth(), buffer.getHeight());
if(transform != null){ if(transform != null){
Draw.trans(transform); Draw.trans(transform);
} }
@@ -148,14 +169,6 @@ public class LogicDisplay extends Block{
Draw.reset(); Draw.reset();
}); });
} }
Draw.blend(Blending.disabled);
Draw.draw(Draw.z(), () -> {
if(buffer != null){
Draw.rect(Draw.wrap(buffer.getTexture()), x, y, buffer.getWidth() * scaleFactor * Draw.scl, -buffer.getHeight() * scaleFactor * Draw.scl);
}
});
Draw.blend();
} }
@Override @Override

View File

@@ -0,0 +1,149 @@
package mindustry.world.blocks.logic;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.graphics.gl.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.graphics.*;
import static mindustry.Vars.*;
public class TileableLogicDisplay extends LogicDisplay{
protected static final Seq<TileableLogicDisplayBuild> queue = new Seq<>();
protected static final Seq<TileableLogicDisplayBuild> displays = new Seq<>();
protected static final IntSet processed = new IntSet();
public TileableLogicDisplay(String name){
super(name);
displaySize = 32;
}
public static void linkDisplays(TileableLogicDisplayBuild start){
TileableLogicDisplayBuild root = null;
int topX = start.tile.x, topY = start.tile.y, botX = start.tile.x, botY = start.tile.y;
queue.clear();
displays.clear();
processed.clear();
queue.add(start);
displays.add(start);
while(!queue.isEmpty()){
var next = queue.pop();
processed.add(next.id);
//assign root based on bottom leftmost position
if(root == null || next.tile.x < root.tile.x || next.tile.y < root.tile.y){
root = next;
}
topX = Math.max(next.tile.x, topX);
topY = Math.max(next.tile.y, topY);
botX = Math.min(next.tile.x, botX);
botY = Math.min(next.tile.y, botY);
for(var prox : next.proximity){
if(prox instanceof TileableLogicDisplayBuild disp && processed.add(disp.id)){
queue.add(disp);
displays.add(disp);
}
}
}
int tilesWidth = topX - botX + 1, tilesHeight = topY - botY + 1;
//the new root display has been assigned
for(var member : displays){
member.rootDisplay = root;
member.tilesWidth = tilesWidth;
member.tilesHeight = tilesHeight;
member.originX = botX;
member.originY = botY;
//TODO: preserve buffers later
if(member.buffer != null){
member.buffer.dispose();
member.buffer = null;
}
}
}
public class TileableLogicDisplayBuild extends LogicDisplayBuild{
//bottom left corner of display
public TileableLogicDisplayBuild rootDisplay = this;
//size of display area
public int tilesWidth = 1, tilesHeight = 1, originX, originY;
@Override
public void draw(){
Draw.rect(block.region, x, y);
//don't even bother processing anything when displays are off.
if(!Vars.renderer.drawDisplays) return;
if(isRoot()){
Draw.draw(Draw.z(), () -> {
if(buffer == null){
buffer = new FrameBuffer(32 * tilesWidth, 32 * tilesHeight);
Log.info("create " + buffer.getWidth() + " " + buffer.getHeight());
//clear the buffer - some OSs leave garbage in it
buffer.begin(Pal.darkerMetal);
buffer.end();
}
});
processCommands();
}
Draw.blend(Blending.disabled);
Draw.draw(Draw.z(), () -> {
if(rootDisplay.buffer != null){
int rtx = (tile.x - originX), rty = (tile.y - originY);
Tmp.tr1.set(rootDisplay.buffer.getTexture(), rtx * 32, rty * 32, 32, 32);
Draw.rect(Tmp.tr1, x, y, tilesize, -tilesize);
}
});
Draw.blend();
}
@Override
public void flushCommands(LongSeq graphicsBuffer){
if(isRoot()){
super.flushCommands(graphicsBuffer);
}else{
rootDisplay.flushCommands(graphicsBuffer);
}
}
@Override
public void onProximityAdded(){
super.onProximityAdded();
linkDisplays(this);
}
@Override
public void onProximityRemoved(){
super.onProximityRemoved();
processed.clear();
for(var other : proximity){
if(other instanceof TileableLogicDisplayBuild tl && !processed.contains(tl.id)){
linkDisplays(tl);
}
}
}
public boolean isRoot(){
return rootDisplay == this;
}
}
}