diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index f9d668db70..bb16016601 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1785,7 +1785,6 @@ block.disperse.name = Disperse block.afflict.name = Afflict block.lustre.name = Lustre block.scathe.name = Scathe -block.fabricator.name = Fabricator block.tank-refabricator.name = Tank Refabricator block.mech-refabricator.name = Mech Refabricator block.ship-refabricator.name = Ship Refabricator @@ -2111,7 +2110,6 @@ block.logic-display.description = Displays arbitrary graphics from a logic proce block.large-logic-display.description = Displays arbitrary graphics from a logic processor. block.interplanetary-accelerator.description = A massive electromagnetic railgun tower. Accelerates cores to escape velocity for interplanetary deployment. block.repair-turret.description = Continuously repairs the closest damaged unit in its vicinity. Optionally accepts coolant. -block.payload-propulsion-tower.description = Long-range payload transport structure. Shoots payloads to other linked payload propulsion towers. #Erekir block.core-bastion.description = Core of the base. Armored. Once destroyed, the sector is lost. @@ -2149,7 +2147,6 @@ block.impact-drill.description = When placed on ore, outputs items in bursts ind block.eruption-drill.description = An improved impact drill. Capable of mining thorium. Requires hydrogen. block.reinforced-conduit.description = Moves fluids forward. Doesn't accept non-conduit inputs to the sides. block.reinforced-liquid-router.description = Distributes fluids equally to all sides. -block.reinforced-junction.description = Acts as a bridge between two crossing conduits. block.reinforced-liquid-tank.description = Stores a large amount of fluids. block.reinforced-liquid-container.description = Stores a sizeable amount of fluids. block.reinforced-bridge-conduit.description = Transports fluids over structures and terrain. @@ -2350,6 +2347,7 @@ graphicstype.poly = Fill a regular polygon. graphicstype.linepoly = Draw a regular polygon outline. graphicstype.triangle = Fill a triangle. graphicstype.image = Draw an image of some content.\nex: [accent]@router[] or [accent]@dagger[]. +graphicstype.print = Draws text from the print buffer.\nClears the print buffer. lenum.always = Always true. lenum.idiv = Integer division. diff --git a/core/assets/fonts/logic.ttf b/core/assets/fonts/logic.ttf new file mode 100644 index 0000000000..0270cdfe3c Binary files /dev/null and b/core/assets/fonts/logic.ttf differ diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index fea21b936b..6e2bf9ee4a 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -19,6 +19,7 @@ import mindustry.game.Teams.*; import mindustry.gen.*; import mindustry.logic.LogicFx.*; import mindustry.type.*; +import mindustry.ui.*; import mindustry.world.*; import mindustry.world.blocks.environment.*; import mindustry.world.blocks.logic.*; @@ -962,6 +963,54 @@ public class LExecutor{ a = ((value & 0x000000ff)); exec.graphicsBuffer.add(DisplayCmd.get(LogicDisplay.commandColor, pack(r), pack(g), pack(b), pack(a), 0, 0)); + }else if(type == LogicDisplay.commandPrint){ + CharSequence str = exec.textBuffer; + + if(str.length() > 0){ + var data = Fonts.logic.getData(); + int advance = (int)data.spaceXadvance, lineHeight = (int)data.lineHeight; + + int xOffset, yOffset; + int align = p1; //p1 is not a variable, it's a raw align value. what a massive hack + + int maxWidth = 0, lines = 1, lineWidth = 0; + for(int i = 0; i < str.length(); i++){ + char next = str.charAt(i); + if(next == '\n'){ + maxWidth = Math.max(maxWidth, lineWidth); + lineWidth = 0; + lines ++; + }else{ + lineWidth ++; + } + } + maxWidth = Math.max(maxWidth, lineWidth); + + float + width = maxWidth * advance, + height = lines * lineHeight, + ha = ((Align.isLeft(align) ? -1f : 0f) + 1f + (Align.isRight(align) ? 1f : 0f))/2f, + va = ((Align.isBottom(align) ? -1f : 0f) + 1f + (Align.isTop(align) ? 1f : 0f))/2f; + + xOffset = -(int)(width * ha); + yOffset = -(int)(height * va) + (lines - 1) * lineHeight; + + + int curX = exec.numi(x), curY = exec.numi(y); + for(int i = 0; i < str.length(); i++){ + char next = str.charAt(i); + if(next == '\n'){ + //move Y down when newline is encountered + curY -= lineHeight; + curX = exec.numi(x); //reset + continue; + } + exec.graphicsBuffer.add(DisplayCmd.get(LogicDisplay.commandPrint, packSign(curX + xOffset), packSign(curY + yOffset), next, 0, 0, 0)); + curX += advance; + } + + exec.textBuffer.setLength(0); + } }else{ //add graphics calls, cap graphics buffer size exec.graphicsBuffer.add(DisplayCmd.get(type, packSign(exec.numi(x)), packSign(exec.numi(y)), packSign(num1), packSign(exec.numi(p2)), packSign(exec.numi(p3)), packSign(exec.numi(p4)))); diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java index 3806254550..2c0c8159c4 100644 --- a/core/src/mindustry/logic/LStatements.java +++ b/core/src/mindustry/logic/LStatements.java @@ -6,6 +6,7 @@ import arc.graphics.*; import arc.scene.style.*; import arc.scene.ui.*; import arc.scene.ui.layout.*; +import arc.struct.*; import arc.util.*; import mindustry.*; import mindustry.annotations.Annotations.*; @@ -121,6 +122,20 @@ public class LStatements{ @RegisterStatement("draw") public static class DrawStatement extends LStatement{ + static final String[] aligns = {"center", "top", "bottom", "left", "right", "topLeft", "topRight", "bottomLeft", "bottomRight"}; + //yes, boxing Integer is gross but this is easier to construct and Integers <128 don't allocate anyway + static final ObjectMap nameToAlign = ObjectMap.of( + "center", Align.center, + "top", Align.top, + "bottom", Align.bottom, + "left", Align.left, + "right", Align.right, + "topLeft", Align.topLeft, + "topRight", Align.topRight, + "bottomLeft", Align.bottomLeft, + "bottomRight", Align.bottomRight + ); + public GraphicsType type = GraphicsType.clear; public String x = "0", y = "0", p1 = "0", p2 = "0", p3 = "0", p4 = "0"; @@ -147,6 +162,11 @@ public class LStatements{ p2 = "32"; p3 = "0"; } + + if(type == GraphicsType.print){ + p2 = "bottomLeft"; + } + rebuild(table); }, 2, cell -> cell.size(100, 50))); }, Styles.logict, () -> {}).size(90, 40).color(table.color).left().padLeft(2); @@ -221,14 +241,21 @@ public class LStatements{ row(s); fields(s, "rotation", p3, v -> p3 = v); } - //TODO - /* - case character -> { + case print -> { fields(s, "x", x, v -> x = v); fields(s, "y", y, v -> y = v); + row(s); - fields(s, "char", p1, v -> p1 = v); - }*/ + + s.add("align "); + + s.button(b -> { + b.label(() -> nameToAlign.containsKey(p1) ? p1 : "bottomLeft"); + b.clicked(() -> showSelect(b, aligns, p1, t -> { + p1 = t; + }, 2, cell -> cell.size(165, 50))); + }, Styles.logict, () -> {}).size(165, 40).color(s.color).left().padLeft(2); + } } }).expand().left(); } @@ -243,7 +270,8 @@ public class LStatements{ @Override public LInstruction build(LAssembler builder){ - return new DrawI((byte)type.ordinal(), 0, builder.var(x), builder.var(y), builder.var(p1), builder.var(p2), builder.var(p3), builder.var(p4)); + return new DrawI((byte)type.ordinal(), 0, builder.var(x), builder.var(y), + type == GraphicsType.print ? nameToAlign.get(p1, Align.bottomLeft) : builder.var(p1), builder.var(p2), builder.var(p3), builder.var(p4)); } @Override diff --git a/core/src/mindustry/ui/Fonts.java b/core/src/mindustry/ui/Fonts.java index b32847a353..6dd4ff1c24 100644 --- a/core/src/mindustry/ui/Fonts.java +++ b/core/src/mindustry/ui/Fonts.java @@ -35,7 +35,7 @@ public class Fonts{ private static TextureRegion[] iconTable; private static int lastCid; - public static Font def, outline, icon, iconLarge, tech; + public static Font def, outline, icon, iconLarge, tech, logic; public static TextureRegion logicIcon(int id){ return iconTable[id]; @@ -71,11 +71,13 @@ public class Fonts{ FreeTypeFontParameter param = fontParameter(); Core.assets.load("default", Font.class, new FreeTypeFontLoaderParameter(mainFont, param)).loaded = f -> Fonts.def = f; + Core.assets.load("icon", Font.class, new FreeTypeFontLoaderParameter("fonts/icon.ttf", new FreeTypeFontParameter(){{ size = 30; incremental = true; characters = "\0"; }})).loaded = f -> Fonts.icon = f; + Core.assets.load("iconLarge", Font.class, new FreeTypeFontLoaderParameter("fonts/icon.ttf", new FreeTypeFontParameter(){{ size = 48; incremental = false; @@ -83,6 +85,14 @@ public class Fonts{ borderWidth = 5f; borderColor = Color.darkGray; }})).loaded = f -> Fonts.iconLarge = f; + + Core.assets.load("logic", Font.class, new FreeTypeFontLoaderParameter("fonts/logic.ttf", new FreeTypeFontParameter(){{ + size = 16; + //generated all at once, it's fast enough anyway + incremental = false; + //ASCII only + characters = "\0ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890\"!`?'.,;:()[]{}<>|/@\\^$€-%+=#_&~*"; + }})).loaded = f -> Fonts.logic = f; } public static TextureRegion getLargeIcon(String name){ diff --git a/core/src/mindustry/world/blocks/logic/LogicDisplay.java b/core/src/mindustry/world/blocks/logic/LogicDisplay.java index 453a3391bd..cfd5c45be8 100644 --- a/core/src/mindustry/world/blocks/logic/LogicDisplay.java +++ b/core/src/mindustry/world/blocks/logic/LogicDisplay.java @@ -28,7 +28,8 @@ public class LogicDisplay extends Block{ commandLinePoly = 8, commandTriangle = 9, commandImage = 10, - commandCharacter = 11; + //note that this command actually only draws 1 character, unpacked in instruction + commandPrint = 11; public int maxSides = 25; @@ -103,8 +104,14 @@ public class LogicDisplay extends Block{ var icon = Fonts.logicIcon(p1); Draw.rect(Fonts.logicIcon(p1), x, y, p2, p2 / icon.ratio(), p3); } - case commandCharacter -> { - //TODO + case commandPrint -> { + var glyph = Fonts.logic.getData().getGlyph((char)p1); + if(glyph != null){ + Tmp.tr1.set(Fonts.logic.getRegion().texture); + Tmp.tr1.set(glyph.u, glyph.v2, glyph.u2, glyph.v); + + Draw.rect(Tmp.tr1, x + Tmp.tr1.width/2f + glyph.xoffset, y + Tmp.tr1.height/2f + glyph.yoffset + Fonts.logic.getData().capHeight + Fonts.logic.getData().ascent, Tmp.tr1.width, Tmp.tr1.height); + } } } } @@ -151,7 +158,8 @@ public class LogicDisplay extends Block{ linePoly, triangle, image, - ;//character; + //note that this command actually only draws 1 character, unpacked in instruction + print; public static final GraphicsType[] all = values(); }