mirror of
https://github.com/yawaflua/Informatis.git
synced 2025-12-10 20:19:26 +02:00
clean code up
This commit is contained in:
@@ -1,204 +1,40 @@
|
||||
package UnitInfo.core;
|
||||
|
||||
import UnitInfo.ui.windows.*;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.input.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
|
||||
import mindustry.*;
|
||||
import mindustry.entities.Units;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.logic.Ranged;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.defense.turrets.*;
|
||||
|
||||
import static UnitInfo.SUtils.*;
|
||||
import static UnitInfo.SVars.*;
|
||||
import static arc.Core.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class HudUi {
|
||||
public Table waveInfoTable = new Table();
|
||||
public SchemDisplay schemTable;
|
||||
|
||||
public Teamc shotTarget;
|
||||
public Teamc lockedTarget;
|
||||
public boolean locked = false;
|
||||
|
||||
public boolean waveShown;
|
||||
|
||||
public float a;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Teamc> T getTarget(){
|
||||
if(locked && lockedTarget != null) {
|
||||
if(settings.getBool("deadTarget") && !Groups.all.contains(e -> e == lockedTarget)) {
|
||||
lockedTarget = null;
|
||||
locked = false;
|
||||
}
|
||||
else return (T) lockedTarget; //if there is locked target, return it first.
|
||||
}
|
||||
|
||||
Seq<Unit> units = Groups.unit.intersect(input.mouseWorldX(), input.mouseWorldY(), 4, 4); // well, 0.5tile is enough to search them
|
||||
if(units.size > 0)
|
||||
return (T) units.peek(); //if there is unit, return it.
|
||||
else if(getTile() != null && getTile().build != null)
|
||||
return (T) getTile().build; //if there isn't unit but there is build, return it.
|
||||
else if(player.unit() instanceof BlockUnitUnit b && b.tile() != null)
|
||||
return (T)b.tile();
|
||||
return (T) player.unit(); //if there aren't unit and not build, return player.
|
||||
}
|
||||
|
||||
public @Nullable Tile getTile(){
|
||||
return Vars.world.tileWorld(input.mouseWorldX(), input.mouseWorldY());
|
||||
}
|
||||
|
||||
float heat = 0;
|
||||
public void setEvents() {
|
||||
Events.run(EventType.Trigger.update, ()->{
|
||||
target = getTarget();
|
||||
if(settings.getBool("deadTarget") && locked && lockedTarget != null && !Groups.all.contains(e -> e == lockedTarget)) {
|
||||
lockedTarget = null;
|
||||
locked = false;
|
||||
}
|
||||
heat+=Time.delta;
|
||||
if(heat>60) {
|
||||
heat=0;
|
||||
heat += Time.delta;
|
||||
if(heat > 60) {
|
||||
heat = 0;
|
||||
schemTable.setSchemTable();
|
||||
}
|
||||
|
||||
if(Scl.scl(modUiScale) != settings.getInt("infoUiScale") / 100f){
|
||||
modUiScale = settings.getInt("infoUiScale") / 100f;
|
||||
if(modUiScale <= 0) {
|
||||
Log.warn("ui scaling reached zero");
|
||||
modUiScale = 0.25f;
|
||||
}
|
||||
}
|
||||
|
||||
if(settings.getBool("autoShooting")) {
|
||||
Unit unit = player.unit();
|
||||
if (unit.type == null) return;
|
||||
boolean omni = unit.type.omniMovement;
|
||||
boolean validHealTarget = unit.type.canHeal && shotTarget instanceof Building b && b.isValid() && b.damaged() && shotTarget.team() == unit.team && shotTarget.within(unit, unit.type.range);
|
||||
boolean boosted = (unit instanceof Mechc && unit.isFlying());
|
||||
if ((unit.type != null && Units.invalidateTarget(shotTarget, unit, unit.type.range) && !validHealTarget) || state.isEditor()) {
|
||||
shotTarget = null;
|
||||
}
|
||||
|
||||
float mouseAngle = unit.angleTo(unit.aimX(), unit.aimY());
|
||||
boolean aimCursor = omni && player.shooting && unit.type.hasWeapons() && unit.type.faceTarget && !boosted && unit.type.rotateShooting;
|
||||
unit.lookAt(aimCursor ? mouseAngle : unit.prefRotation());
|
||||
|
||||
//update shooting if not building + not mining
|
||||
if(!player.unit().activelyBuilding() && player.unit().mineTile == null) {
|
||||
if(input.keyDown(KeyCode.mouseLeft)) {
|
||||
player.shooting = !boosted;
|
||||
unit.aim(player.mouseX = input.mouseWorldX(), player.mouseY = input.mouseWorldY());
|
||||
} else if(shotTarget == null) {
|
||||
player.shooting = false;
|
||||
if(unit instanceof BlockUnitUnit b) {
|
||||
if(b.tile() instanceof ControlBlock c && !c.shouldAutoTarget()) {
|
||||
Building build = b.tile();
|
||||
float range = build instanceof Ranged ? ((Ranged) build).range() : 0f;
|
||||
boolean targetGround = build instanceof Turret.TurretBuild && ((Turret) build.block).targetAir;
|
||||
boolean targetAir = build instanceof Turret.TurretBuild && ((Turret) build.block).targetGround;
|
||||
shotTarget = Units.closestTarget(build.team, build.x, build.y, range, u -> u.checkTarget(targetAir, targetGround), u -> targetGround);
|
||||
}
|
||||
else shotTarget = null;
|
||||
} else if(unit.type != null) {
|
||||
float range = unit.hasWeapons() ? unit.range() : 0f;
|
||||
shotTarget = Units.closestTarget(unit.team, unit.x, unit.y, range, u -> u.checkTarget(unit.type.targetAir, unit.type.targetGround), u -> unit.type.targetGround);
|
||||
|
||||
if(unit.type.canHeal && shotTarget == null) {
|
||||
shotTarget = Geometry.findClosest(unit.x, unit.y, indexer.getDamaged(Team.sharded));
|
||||
if (shotTarget != null && !unit.within(shotTarget, range)) {
|
||||
shotTarget = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.shooting = !boosted;
|
||||
unit.rotation(Angles.angle(unit.x, unit.y, shotTarget.x(), shotTarget.y()));
|
||||
unit.aim(shotTarget.x(), shotTarget.y());
|
||||
}
|
||||
}
|
||||
unit.controlWeapons(player.shooting && !boosted);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setLeftUnitTable(Table table) {
|
||||
table.table(t -> {
|
||||
t.center();
|
||||
int[] i = {0};
|
||||
|
||||
content.units().each(type -> Groups.unit.contains(u -> u.type == type && (state.rules.pvp ? (u.team != player.team()) : (u.team == state.rules.waveTeam)) && u.isBoss()), type -> {
|
||||
t.table(tt ->
|
||||
tt.stack(
|
||||
new Table(ttt -> ttt.image(type.uiIcon).size(iconSmall)),
|
||||
new Table(ttt -> {
|
||||
ttt.right().bottom();
|
||||
Label label = new Label(() -> Groups.unit.count(u -> u.type == type && (state.rules.pvp ? (u.team != player.team()) : (u.team == state.rules.waveTeam)) && u.isBoss()) + "");
|
||||
label.setFontScale(0.75f);
|
||||
ttt.add(label);
|
||||
ttt.pack();
|
||||
}),
|
||||
new Table(ttt -> {
|
||||
ttt.top().right();
|
||||
Image image = new Image(Icon.warning.getRegion()).setScaling(Scaling.fit);
|
||||
image.update(() -> image.setColor(Tmp.c2.set(Color.orange).lerp(Color.scarlet, Mathf.absin(Time.time, 2f, 1f))));
|
||||
ttt.add(image).size(Scl.scl(modUiScale) * 12f);
|
||||
ttt.pack();
|
||||
})
|
||||
).pad(6)
|
||||
);
|
||||
if(++i[0] % 6 == 0) t.row();
|
||||
});
|
||||
t.row();
|
||||
i[0] = 0;
|
||||
content.units().each(type -> Groups.unit.contains(u -> u.type == type && (state.rules.pvp ? (u.team != player.team()) : (u.team == state.rules.waveTeam)) && !u.isBoss()), type -> {
|
||||
t.table(tt ->
|
||||
tt.add(new Stack() {{
|
||||
add(new Table(ttt -> ttt.add(new Image(type.uiIcon)).size(iconSmall)));
|
||||
add(new Table(ttt -> {
|
||||
ttt.right().bottom();
|
||||
Label label = new Label(() -> Groups.unit.count(u -> u.type == type &&(state.rules.pvp ? (u.team != player.team()) : (u.team == state.rules.waveTeam)) && !u.isBoss()) + "");
|
||||
label.setFontScale(0.75f);
|
||||
ttt.add(label);
|
||||
ttt.pack();
|
||||
}));
|
||||
}}).pad(6)
|
||||
);
|
||||
if(++i[0] % 6 == 0) t.row();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void setTile(Table table){
|
||||
table.table(t ->
|
||||
t.table(Tex.underline2, head -> {
|
||||
head.table(image -> {
|
||||
image.left();
|
||||
image.image(() -> getTile() == null ? clear : getTile().floor().uiIcon == error ? clear : getTile().floor().uiIcon).size(iconSmall);
|
||||
image.image(() -> getTile() == null ? clear : getTile().overlay().uiIcon == error ? clear : getTile().overlay().uiIcon).size(iconSmall);
|
||||
image.image(() -> getTile() == null ? clear : getTile().block().uiIcon == error ? clear : getTile().block().uiIcon).size(iconSmall);
|
||||
});
|
||||
Label label = new Label(() -> getTile() == null ? "(null, null)" : "(" + getTile().x + ", " + getTile().y + ")");
|
||||
head.add(label).center();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public void addSchemTable() {
|
||||
Table table = ((Table) scene.find("minimap/position")).row();
|
||||
schemTable = new SchemDisplay();
|
||||
@@ -206,14 +42,65 @@ public class HudUi {
|
||||
}
|
||||
|
||||
public void addWaveInfoTable() {
|
||||
waveInfoTable = new Table(Tex.buttonEdge4, t -> {
|
||||
t.defaults().width(34 * 8f).center();
|
||||
t.table().update(tt -> {
|
||||
tt.clear();
|
||||
setTile(tt);
|
||||
tt.row();
|
||||
setLeftUnitTable(tt);
|
||||
Table waveInfoTable = new Table(Tex.buttonEdge4, table -> {
|
||||
table.center();
|
||||
table.table(head -> {
|
||||
head.table(image -> {
|
||||
image.left();
|
||||
image.image(() -> getTile() == null || getTile().floor().uiIcon == error ? clear : getTile().floor().uiIcon).size(iconSmall);
|
||||
image.image(() -> getTile() == null || getTile().overlay().uiIcon == error ? clear : getTile().overlay().uiIcon).size(iconSmall);
|
||||
image.image(() -> getTile() == null || getTile().block().uiIcon == error ? clear : getTile().block().uiIcon).size(iconSmall);
|
||||
});
|
||||
head.label(() -> Strings.format("(@, @)", getTile() == null ? "NaN" : getTile().x, getTile() == null ? "NaN" : getTile().y)).center();
|
||||
});
|
||||
table.row();
|
||||
table.image().height(4f).color(Pal.gray).growX().row();
|
||||
/*
|
||||
table.table(tttt -> {
|
||||
tttt.center();
|
||||
int[] i = {0};
|
||||
|
||||
content.units().each(type -> Groups.unit.contains(u -> u.type == type && (state.rules.pvp ? (u.team != player.team()) : (u.team == state.rules.waveTeam)) && u.isBoss()), type -> {
|
||||
tttt.table(stt ->
|
||||
stt.stack(
|
||||
new Table(ttt -> ttt.image(type.uiIcon).size(iconSmall)),
|
||||
new Table(ttt -> {
|
||||
ttt.right().bottom();
|
||||
Label label = new Label(() -> Groups.unit.count(u -> u.type == type && (state.rules.pvp ? (u.team != player.team()) : (u.team == state.rules.waveTeam)) && u.isBoss()) + "");
|
||||
label.setFontScale(0.75f);
|
||||
ttt.add(label);
|
||||
ttt.pack();
|
||||
}),
|
||||
new Table(ttt -> {
|
||||
ttt.top().right();
|
||||
Image image = new Image(Icon.warning.getRegion()).setScaling(Scaling.fit);
|
||||
image.update(() -> image.setColor(Tmp.c2.set(Color.orange).lerp(Color.scarlet, Mathf.absin(Time.time, 2f, 1f))));
|
||||
ttt.add(image).size(12f);
|
||||
ttt.pack();
|
||||
})
|
||||
).pad(6)
|
||||
);
|
||||
if(++i[0] % 6 == 0) tttt.row();
|
||||
});
|
||||
tttt.row();
|
||||
i[0] = 0;
|
||||
content.units().each(type -> Groups.unit.contains(u -> u.type == type && (state.rules.pvp ? (u.team != player.team()) : (u.team == state.rules.waveTeam)) && !u.isBoss()), type -> {
|
||||
tttt.table(ttt ->
|
||||
ttt.add(new Stack() {{
|
||||
add(new Table(ttt -> ttt.add(new Image(type.uiIcon)).size(iconSmall)));
|
||||
add(new Table(ttt -> {
|
||||
ttt.right().bottom();
|
||||
Label label = new Label(() -> Groups.unit.count(u -> u.type == type &&(state.rules.pvp ? (u.team != player.team()) : (u.team == state.rules.waveTeam)) && !u.isBoss()) + "");
|
||||
label.setFontScale(0.75f);
|
||||
ttt.add(label);
|
||||
ttt.pack();
|
||||
}));
|
||||
}}).pad(6)
|
||||
);
|
||||
if(++i[0] % 6 == 0) tttt.row();
|
||||
});
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
Table waveTable = (Table) scene.find("waves");
|
||||
|
||||
@@ -5,18 +5,15 @@ import UnitInfo.ui.*;
|
||||
import UnitInfo.ui.draws.OverDraws;
|
||||
import UnitInfo.ui.windows.*;
|
||||
import arc.*;
|
||||
import arc.scene.ui.Dialog;
|
||||
import arc.struct.Seq;
|
||||
import arc.util.Log;
|
||||
import arc.struct.*;
|
||||
import mindustry.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.mod.*;
|
||||
|
||||
import static UnitInfo.SVars.*;
|
||||
import static UnitInfo.ui.windows.UnitDisplay.getTarget;
|
||||
import static arc.Core.*;
|
||||
import static mindustry.Vars.mobile;
|
||||
import static mindustry.Vars.ui;
|
||||
import static mindustry.Vars.*;
|
||||
import static UnitInfo.SUtils.*;
|
||||
|
||||
public class Main extends Mod {
|
||||
@Override
|
||||
@@ -51,17 +48,15 @@ public class Main extends Mod {
|
||||
hud.addSchemTable();
|
||||
hud.setEvents();
|
||||
OverDrawer.setEvent();
|
||||
if(jsonGen) ContentJSON.save();
|
||||
|
||||
scene.add(new ElementDisplay());
|
||||
Seq.with(
|
||||
Seq.with(scene.root,
|
||||
ui.picker, ui.editor, ui.controls, ui.restart, ui.join, ui.discord,
|
||||
ui.load, ui.custom, ui.language, ui.database, ui.settings, ui.host,
|
||||
ui.paused, ui.about, ui.bans, ui.admins, ui.traces, ui.maps, ui.content,
|
||||
ui.planet, ui.research, ui.mods, ui.schematics, ui.logic
|
||||
).each(dialog-> dialog.add(new ElementDisplay(dialog)));
|
||||
|
||||
).each(dialog-> dialog.addChild(new ElementDisplay(dialog)));
|
||||
|
||||
if(jsonGen) ContentJSON.save();
|
||||
});
|
||||
|
||||
Events.on(WorldLoadEvent.class, e -> {
|
||||
|
||||
@@ -1,32 +1,17 @@
|
||||
package UnitInfo.core;
|
||||
|
||||
import UnitInfo.ui.*;
|
||||
import UnitInfo.ui.draws.OverDraw;
|
||||
import UnitInfo.ui.draws.OverDraws;
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.ai.types.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.defense.turrets.*;
|
||||
import mindustry.world.blocks.storage.*;
|
||||
import mindustry.world.blocks.units.*;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static UnitInfo.SVars.*;
|
||||
import static arc.Core.*;
|
||||
@@ -36,11 +21,9 @@ public class OverDrawer {
|
||||
|
||||
public static void setEvent(){
|
||||
Events.run(EventType.Trigger.draw, () -> {
|
||||
|
||||
float sin = Mathf.absin(Time.time, 6f, 1f);
|
||||
|
||||
Draw.z(Layer.max);
|
||||
//local drawing, drawn on player/camera position
|
||||
if(settings.getBool("spawnerarrow")) {
|
||||
float leng = (player.unit() != null && player.unit().hitSize > 4 * 8f ? player.unit().hitSize * 1.5f : 4 * 8f) + sin;
|
||||
Tmp.v1.set(camera.position);
|
||||
|
||||
@@ -103,65 +103,32 @@ public class SettingS {
|
||||
settingUi.button(bundle.get("setting.shar-title"), Styles.cleart, dialog::show);
|
||||
});
|
||||
|
||||
|
||||
Seq<Seq<SharSetting>> settingSeq = new Seq<>();
|
||||
Seq<SharSetting> tapSeq = new Seq<>();
|
||||
addGraphicSlideSetting("barstyle", 0, 0, 5, 1, s -> s == 0 ? bundle.get("default-bar") : s + bundle.get("th-bar"), tapSeq);
|
||||
addGraphicSlideSetting("infoUiScale", mobile ? 25 : 50, 25, 100, 5, s -> s + "%", tapSeq);
|
||||
addGraphicSlideSetting("coreItemCheckRate", 60, 6, 180, 6, s -> Strings.fixed(s/60f,1) + bundle.get("sec"), tapSeq);
|
||||
addGraphicTypeSetting("wavemax", 0, 200,100, true, () -> true, s -> s + "waves", tapSeq);
|
||||
addGraphicCheckSetting("infoui", true, tapSeq);
|
||||
addGraphicCheckSetting("pastwave", false, tapSeq);
|
||||
addGraphicCheckSetting("emptywave", true, tapSeq);
|
||||
addGraphicCheckSetting("itemcal", false, tapSeq);
|
||||
addGraphicCheckSetting("schem", !mobile, tapSeq);
|
||||
|
||||
//TODO: remove all drawing settings
|
||||
Seq<SharSetting> rangeSeq = new Seq<>();
|
||||
//addGraphicTypeSetting("rangeRadius", 0, 500, 70, true, () -> true, s -> s + "tiles", rangeSeq);
|
||||
//addGraphicCheckSetting("rangeNearby", true, rangeSeq);
|
||||
//addGraphicCheckSetting("allTargetRange", false, rangeSeq);
|
||||
addGraphicCheckSetting("aliceRange", false, rangeSeq);
|
||||
addGraphicCheckSetting("RangeShader", false, rangeSeq);
|
||||
|
||||
Seq<SharSetting> opacitySeq = new Seq<>();
|
||||
addGraphicSlideSetting("selectopacity", 50, 0, 100, 5, s -> s + "%", opacitySeq);
|
||||
addGraphicSlideSetting("baropacity", 50, 0, 100, 5, s -> s + "%", opacitySeq);
|
||||
addGraphicSlideSetting("uiopacity", 50, 0, 100, 5, s -> s + "%", opacitySeq);
|
||||
addGraphicSlideSetting("softRangeOpacity", 60, 0, 100, 10, s -> s + "%", opacitySeq);
|
||||
|
||||
Seq<SharSetting> drawSeq = new Seq<>();
|
||||
/*
|
||||
addGraphicTypeSetting("pathlinelimit", 0, 5000, 50, true, () -> true, s -> s + "lines", drawSeq);
|
||||
addGraphicTypeSetting("unitlinelimit", 0, 5000, 50, true, () -> true, s -> s + "lines", drawSeq);
|
||||
addGraphicTypeSetting("logiclinelimit", 0, 5000, 50, true, () -> true, s -> s + "lines", drawSeq);
|
||||
addGraphicTypeSetting("spawnarrowlimit", 0, 5000, 50, true, () -> true, s -> s + "arrows", drawSeq);
|
||||
addGraphicCheckSetting("gaycursor", false, drawSeq);
|
||||
addGraphicCheckSetting("unithealthui", true, drawSeq);
|
||||
addGraphicCheckSetting("blockfont", false, drawSeq);
|
||||
addGraphicCheckSetting("linkedMass", true, drawSeq);
|
||||
addGraphicCheckSetting("linkedNode", false, drawSeq);
|
||||
addGraphicCheckSetting("deadTarget", false, drawSeq);
|
||||
*/
|
||||
addGraphicSlideSetting("selectopacity", 50, 0, 100, 5, s -> s + "%", drawSeq);
|
||||
addGraphicSlideSetting("baropacity", 50, 0, 100, 5, s -> s + "%", drawSeq);
|
||||
addGraphicCheckSetting("aliceRange", false, drawSeq);
|
||||
addGraphicCheckSetting("RangeShader", false, drawSeq);
|
||||
addGraphicCheckSetting("select", false, drawSeq);
|
||||
addGraphicCheckSetting("distanceLine", false, drawSeq);
|
||||
addGraphicCheckSetting("spawnerarrow", false, drawSeq);
|
||||
addGraphicCheckSetting("elementdebug", false, drawSeq);
|
||||
addGraphicCheckSetting("hiddenElem", false, drawSeq);
|
||||
|
||||
Seq<SharSetting> etcSeq = new Seq<>();
|
||||
addGraphicCheckSetting("autoShooting", false, etcSeq);
|
||||
|
||||
settingSeq.add(tapSeq, rangeSeq, opacitySeq);
|
||||
settingSeq.add(drawSeq, etcSeq);
|
||||
settingSeq.add(tapSeq, drawSeq);
|
||||
|
||||
sharset.table(t -> {
|
||||
Seq<TextButton> buttons = new Seq<>();
|
||||
buttons.add(new TextButton(bundle.get("setting.shar-ui"), Styles.clearToggleMenut));
|
||||
buttons.add(new TextButton(bundle.get("setting.shar-range"), Styles.clearToggleMenut));
|
||||
buttons.add(new TextButton(bundle.get("setting.shar-opacity"), Styles.clearToggleMenut));
|
||||
buttons.add(new TextButton(bundle.get("setting.shar-draw"), Styles.clearToggleMenut));
|
||||
buttons.add(new TextButton(bundle.get("setting.shar-etc"), Styles.clearToggleMenut));
|
||||
buttons.each(b -> b.clicked(() -> buttons.each(b1 -> b1.setChecked(b1 == b))));
|
||||
t.table(Styles.black8, bt -> {
|
||||
bt.top().align(Align.top);
|
||||
|
||||
Reference in New Issue
Block a user