multi window go brr

This commit is contained in:
Sharlotte
2022-09-28 16:39:05 +09:00
parent 3be43e733e
commit ce57bbc2d6
14 changed files with 464 additions and 460 deletions

View File

@@ -3,7 +3,6 @@ package informatis;
import arc.input.KeyCode;
import informatis.core.OverDrawer;
import informatis.core.Setting;
import informatis.ui.*;
import informatis.draws.OverDraws;
import informatis.ui.fragments.FragmentManager;
import informatis.ui.windows.*;
@@ -15,7 +14,7 @@ import mindustry.mod.*;
import static informatis.SVars.*;
import static arc.Core.*;
import static informatis.SUtils.*;
import static informatis.ui.WindowManager.windows;
import static informatis.ui.windows.WindowManager.windows;
public class Informatis extends Mod {
@Override
@@ -28,17 +27,9 @@ public class Informatis extends Mod {
});
Events.run(Trigger.update, () -> {
//TODO: why not just use Events in its own class constructor?
for (Window window : windows) {
window.update();
}
//TODO: target should be not global variable anymore for multiple window system
target = getTarget();
if((input.keyDown(KeyCode.shiftRight) || input.keyDown(KeyCode.shiftLeft))) {
if(input.keyTap(KeyCode.r)) {
if(target == getTarget()) locked = !locked;
target = getTarget();
windows.get(UnitWindow.class).each(window -> ((UnitWindow) window).locked = !((UnitWindow) window).locked);
}
}
});

View File

@@ -26,27 +26,23 @@ import static mindustry.Vars.player;
public class SUtils {
/**
* move camera to given coordination
* @param x - world unit x
* @param y - world unit y
* @param x world unit x
* @param y world unit y
*/
public static void moveCamera(float x, float y) {
if(control.input instanceof DesktopInput)
((DesktopInput) control.input).panning = true;
Core.camera.position.set(x, y);
}
/**
* move camera to given coordination
* @param pos world unit coordination
*/
public static void moveCamera(Position pos) {
moveCamera(pos.getX(), pos.getY());
}
@SuppressWarnings("unchecked")
public static <T extends Teamc> T getTarget(){
if(locked && target != null) {
if(settings.getBool("deadTarget") && !Groups.all.contains(e -> e == target)) {
target = player.unit();
locked = false;
}
else return (T) target; //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.
@@ -109,11 +105,6 @@ public class SUtils {
return field.get(ut);
}
public static boolean isOutCamera(float x, float y) {
return !isInCamera(x, y, 0);
}
public static boolean isInCamera(float x, float y, float size) {
Tmp.r2.setCentered(x, y, size);
return Tmp.r1.overlaps(Tmp.r2);

View File

@@ -8,10 +8,9 @@ import mindustry.gen.Teamc;
import static arc.Core.atlas;
public class SVars {
public static TextureRegion clear = atlas.find("clear");
public static TextureRegion error = atlas.find("error");
public static TextureRegion
clear = atlas.find("clear"),
error = atlas.find("error");
public static RangeShader turretRange = new RangeShader();
public static informatis.core.Pathfinder pathfinder;
public static Teamc target;
public static boolean locked;
}

View File

@@ -7,11 +7,14 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import informatis.ui.windows.UnitWindow;
import informatis.ui.windows.WindowManager;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.ui.*;
import static informatis.SUtils.getTarget;
import static informatis.SVars.*;
import static arc.Core.*;
import static mindustry.Vars.*;
@@ -32,18 +35,22 @@ public class OverDrawer {
}
if(settings.getBool("select")) {
Draw.color(Tmp.c1.set(locked ? Color.orange : Color.darkGray).lerp(locked ? Color.scarlet : Color.gray, Mathf.absin(Time.time, 3f, 1f)).a(settings.getInt("selectopacity") / 100f));
float length = (target instanceof Unit u ? u.hitSize : target instanceof Building b ? b.block.size * tilesize : 0) * 1.5f + 2.5f;
for(int i = 0; i < 4; i++){
float rot = i * 90f + 45f + (-Time.time) % 360f;
Draw.rect("select-arrow", target.x() + Angles.trnsx(rot, length), target.y() + Angles.trnsy(rot, length), length / 1.9f, length / 1.9f, rot - 135f);
}
WindowManager.windows.get(UnitWindow.class).each(w -> {
UnitWindow window = (UnitWindow) w;
Draw.color(Tmp.c1.set(window.locked ? Color.orange : Color.darkGray).lerp(window.locked ? Color.scarlet : Color.gray, Mathf.absin(Time.time, 3f, 1f)).a(settings.getInt("selectopacity") / 100f));
float length = (window.target instanceof Unit u ? u.hitSize : window.target instanceof Building b ? b.block.size * tilesize : 0) * 1.5f + 2.5f;
for(int i = 0; i < 4; i++){
float rot = i * 90f + 45f + (-Time.time) % 360f;
Draw.rect("select-arrow", window.target.x() + Angles.trnsx(rot, length), window.target.y() + Angles.trnsy(rot, length), length / 1.9f, length / 1.9f, rot - 135f);
}
});
Draw.color();
}
if(settings.getBool("distanceLine")) {
Posc from = player;
Position to = target;
Position to = getTarget();
if(to == from || to == null) to = input.mouseWorld();
if(player.unit() instanceof BlockUnitUnit bu) Tmp.v1.set(bu.x() + bu.tile().block.offset, bu.y() + bu.tile().block.offset).sub(to.getX(), to.getY()).limit(bu.tile().block.size * tilesize + sin + 0.5f);
else Tmp.v1.set(from.x(), from.y()).sub(to.getX(), to.getY()).limit((player.unit()==null?0:player.unit().hitSize) + sin + 0.5f);

View File

@@ -13,6 +13,7 @@ import arc.util.Tmp;
import mindustry.core.Renderer;
import mindustry.gen.Building;
import mindustry.gen.Groups;
import mindustry.gen.Teamc;
import mindustry.graphics.Drawf;
import mindustry.graphics.Layer;
import mindustry.graphics.Pal;
@@ -21,6 +22,7 @@ import mindustry.world.blocks.payloads.PayloadMassDriver;
import static arc.Core.atlas;
import static arc.Core.settings;
import static informatis.SUtils.getTarget;
import static mindustry.Vars.*;
import static informatis.SVars.*;
@@ -38,7 +40,7 @@ public class LinkDraw extends OverDraw {
@Override
public void draw() {
if(!enabled) return;
Teamc target = getTarget();
Draw.z(Layer.max);
if(target instanceof Building b){
if(settings.getBool("powerNode") && enabled) {

View File

@@ -1,53 +0,0 @@
package informatis.ui;
import arc.*;
import arc.struct.*;
import mindustry.*;
import mindustry.ui.*;
import informatis.ui.windows.*;
public class WindowManager {
public static Seq<Window> windows = new Seq<>();
public static void init(){
Vars.ui.hudGroup.fill(t -> {
t.name = "Windows";
for(Window window : windows){
t.add(window).height(window.getHeight()).width(window.getWidth());
}
});
Vars.ui.hudGroup.fill(t -> {
t.center().left();
t.table(Core.atlas.drawable("informatis-sidebar"), b -> {
b.name = "Window Buttons";
b.left();
for(Window window : windows){
b.button(window.icon, Styles.emptyi, () -> {
window.toggle();
// Disabling the parent's layout fixes issues with updating elements inside windows.
// However, it also disables the layout of all its children, so we need to re-enable them.
window.parent.setLayoutEnabled(false);
window.setLayoutEnabled(true);
for(Window w : windows){
w.setLayoutEnabled(true);
}
}).disabled(window.shown)
.size(40f)
.tooltip(tt -> {
tt.setBackground(Styles.black6);
tt.label(() -> Core.bundle.get("window."+window.name+".name")).pad(2f);
});
b.row();
}
}).left();
});
}
public static int register(Window window){
windows.add(window);
return windows.size - 1;
}
}

View File

@@ -32,6 +32,20 @@ public class CoreWindow extends Window {
public CoreWindow() {
super(Icon.list, "core");
resetUsed();
only = true;
Events.run(EventType.Trigger.update, () -> {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
ScrollPane pane = find("core-pane");
pane.setWidget(rebuild());
for(Team team : getTeams()) {
if(!itemData.containsKey(team)) itemData.put(team, new ItemData());
itemData.get(team).updateItems(team);
}
}
});
}
@Override
@@ -44,19 +58,6 @@ public class CoreWindow extends Window {
Events.on(EventType.WorldLoadEvent.class, e -> resetUsed());
}
public void update() {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
ScrollPane pane = find("core-pane");
pane.setWidget(rebuild());
for(Team team : getTeams()) {
if(!itemData.containsKey(team)) itemData.put(team, new ItemData());
itemData.get(team).updateItems(team);
}
}
}
Table rebuild() {
return new Table(table -> {
table.top();
@@ -135,7 +136,7 @@ public class CoreWindow extends Window {
}),
new Table(ttt -> {
ttt.bottom().right();
if(itemData.get(team) == null) return;
if(itemData == null || itemData.get(team) == null) return;
int amount = itemData.get(team).updateItems.isEmpty()?0:Mathf.floor(itemData.get(team).updateItems.get(item.id).amount);
Label label = new Label(amount + "/s");
label.setFontScale(0.65f);

View File

@@ -26,8 +26,6 @@ import mindustry.gen.*;
import mindustry.ui.*;
import mindustry.world.*;
import static informatis.ui.windows.MapEditorWindow.drawBlock;
import static informatis.ui.windows.MapEditorWindow.drawTeam;
import static informatis.ui.windows.Windows.editorTable;
import static mindustry.Vars.*;
@@ -49,8 +47,9 @@ public class MapEditorWindow extends Window {
public MapEditorWindow() {
super(Icon.map, "editor");
height = 800;
width = 600;
width = 800;
height = 600;
only = true;
for(int i = 0; i < MapEditor.brushSizes.length; i++){
float size = MapEditor.brushSizes[i];
@@ -111,6 +110,35 @@ public class MapEditorWindow extends Window {
}
}
});
Events.run(EventType.Trigger.update, () -> {
//TODO make it more responsive, time -> width delta detect
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
if(lastw != window.getWidth() || lasth != window.getHeight()) resetPane();
lastw = width;
lasth = height;
}
Tile tile = world.tileWorld(Core.input.mouseWorldX(), Core.input.mouseWorldY());
if(tile == null || tool == null || brushSize < 1 || drawBlock == null || hasMouse()) return;
if(Core.input.isTouched()) {
if((tool == EditorTool.line && drawing) || (!mobile && !Core.input.keyDown(KeyCode.mouseLeft))) return;
drawing = true;
lastx = tile.x;
lasty = tile.y;
tool.touched(lastx, lasty);
}
else {
if(tool == EditorTool.line && drawing) tool.touchedLine(lastx, lasty, tile.x, tile.y);
drawing = false;
lastx = -1;
lasty = -1;
}
});
}
@Override
@@ -148,34 +176,6 @@ public class MapEditorWindow extends Window {
}).growY();
}
public void update() {
//TODO make it more responsive, time -> width delta detect
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
if(lastw != window.getWidth() || lasth != window.getHeight()) resetPane();
lastw = width;
lasth = height;
}
Tile tile = world.tileWorld(Core.input.mouseWorldX(), Core.input.mouseWorldY());
if(tile == null || tool == null || brushSize < 1 || drawBlock == null || hasMouse()) return;
if(Core.input.isTouched()) {
if((tool == EditorTool.line && drawing) || (!mobile && !Core.input.keyDown(KeyCode.mouseLeft))) return;
drawing = true;
lastx = tile.x;
lasty = tile.y;
tool.touched(lastx, lasty);
}
else {
if(tool == EditorTool.line && drawing) tool.touchedLine(lastx, lasty, tile.x, tile.y);
drawing = false;
lastx = -1;
lasty = -1;
}
}
void resetPane() {
ScrollPane pane = find("editor-pane");
if(pane != null) pane.setWidget(rebuildEditor());
@@ -465,255 +465,254 @@ public class MapEditorWindow extends Window {
}
}
}
return false;
}
}
enum EditorTool{
zoom(KeyCode.v),
pick(KeyCode.i){
public void touched(int x, int y){
if(!Structs.inBounds(x, y, world.width(), world.height())) return;
enum EditorTool{
zoom(KeyCode.v),
pick(KeyCode.i){
public void touched(int x, int y){
if(!Structs.inBounds(x, y, world.width(), world.height())) return;
Tile tile = world.tile(x, y);
drawBlock = tile.block() == Blocks.air || !tile.block().inEditor ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
}
},
line(KeyCode.l, "replace", "orthogonal"){
@Override
public void touchedLine(int x1, int y1, int x2, int y2){
//straight
if(mode == 1){
if(Math.abs(x2 - x1) > Math.abs(y2 - y1)){
y2 = y1;
}else{
x2 = x1;
}
Tile tile = world.tile(x, y);
drawBlock = tile.block() == Blocks.air || !tile.block().inEditor ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block();
}
},
line(KeyCode.l, "replace", "orthogonal"){
Bresenham2.line(x1, y1, x2, y2, (x, y) -> {
if(mode == 0){
//replace
editorTable.drawBlocksReplace(x, y);
}else{
//normal
editorTable.drawBlocks(x, y);
}
});
}
},
pencil(KeyCode.b, "replace", "square", "drawteams"){
{
edit = true;
draggable = true;
}
@Override
public void touched(int x, int y){
if(mode == -1){
//normal mode
editorTable.drawBlocks(x, y);
}else if(mode == 0){
//replace mode
editorTable.drawBlocksReplace(x, y);
}else if(mode == 1){
//square mode
editorTable.drawBlocks(x, y, true, tile -> true);
}else if(mode == 2){
//draw teams
editorTable.drawCircle(x, y, tile -> tile.setTeam(drawTeam));
}
}
},
eraser(KeyCode.e, "eraseores"){
{
edit = true;
draggable = true;
}
@Override
public void touched(int x, int y){
editorTable.drawCircle(x, y, tile -> {
if(mode == -1){
//erase block
tile.remove();
}else if(mode == 0){
//erase ore
tile.clearOverlay();
}
});
}
},
fill(KeyCode.g, "replaceall", "fillteams"){
{
edit = true;
}
IntSeq stack = new IntSeq();
@Override
public void touched(int x, int y){
if(!Structs.inBounds(x, y, world.width(), world.height()) || world.tile(x, y).block()!=null&&world.tile(x, y).block().isMultiblock()) return;
Tile tile = world.tile(x, y);
//mode 0 or 1, fill everything with the floor/tile or replace it
if(mode == 0 || mode == -1){
if(tile.block().isMultiblock()) return;
Boolf<Tile> tester;
Cons<Tile> setter;
Block drawBlock = MapEditorWindow.drawBlock;
if(drawBlock.isOverlay()){
Block dest = tile.overlay();
if(dest == drawBlock) return;
tester = t -> t.overlay() == dest && (t.floor().hasSurface() || !t.floor().needsSurface);
setter = t -> t.setOverlay(drawBlock);
}else if(drawBlock.isFloor()){
Block dest = tile.floor();
if(dest == drawBlock) return;
tester = t -> t.floor() == dest;
setter = t -> t.setFloorUnder(drawBlock.asFloor());
}else{
Block dest = tile.block();
if(dest == drawBlock) return;
tester = t -> t.block() == dest;
setter = t -> t.setBlock(drawBlock, drawTeam);
}
//replace only when the mode is 0 using the specified functions
fill(x, y, mode == 0, tester, setter);
}else if(mode == 1){ //mode 1 is team fill
//only fill synthetic blocks, it's meaningless otherwise
if(tile.synthetic()){
Team dest = tile.team();
if(dest == drawTeam) return;
fill(x, y, false, t -> t.getTeamID() == dest.id && t.synthetic(), t -> t.setTeam(drawTeam));
}
}
}
void fill(int x, int y, boolean replace, Boolf<Tile> tester, Cons<Tile> filler){
int width = world.width(), height = world.height();
if(replace){
//just do it on everything
for(int cx = 0; cx < width; cx++){
for(int cy = 0; cy < height; cy++){
Tile tile = world.tile(cx, cy);
if(tester.get(tile)){
filler.get(tile);
}
@Override
public void touchedLine(int x1, int y1, int x2, int y2){
//straight
if(mode == 1){
if(Math.abs(x2 - x1) > Math.abs(y2 - y1)){
y2 = y1;
}else{
x2 = x1;
}
}
}else{
//perform flood fill
int x1;
stack.clear();
stack.add(Point2.pack(x, y));
try{
while(stack.size > 0 && stack.size < width*height){
int popped = stack.pop();
x = Point2.x(popped);
y = Point2.y(popped);
x1 = x;
while(x1 >= 0 && tester.get(world.tile(x1, y))) x1--;
x1++;
boolean spanAbove = false, spanBelow = false;
while(x1 < width && tester.get(world.tile(x1, y))){
filler.get(world.tile(x1, y));
if(!spanAbove && y > 0 && tester.get(world.tile(x1, y - 1))){
stack.add(Point2.pack(x1, y - 1));
spanAbove = true;
}else if(spanAbove && !tester.get(world.tile(x1, y - 1))){
spanAbove = false;
}
if(!spanBelow && y < height - 1 && tester.get(world.tile(x1, y + 1))){
stack.add(Point2.pack(x1, y + 1));
spanBelow = true;
}else if(spanBelow && y < height - 1 && !tester.get(world.tile(x1, y + 1))){
spanBelow = false;
}
x1++;
}
}
stack.clear();
}catch(OutOfMemoryError e){
//hack
stack = null;
System.gc();
e.printStackTrace();
stack = new IntSeq();
}
}
}
},
spray(KeyCode.r, "replace"){
final double chance = 0.012;
{
edit = true;
draggable = true;
}
@Override
public void touched(int x, int y){
//floor spray
if(drawBlock.isFloor()){
editorTable.drawCircle(x, y, tile -> {
if(Mathf.chance(chance)){
tile.setFloor(drawBlock.asFloor());
Bresenham2.line(x1, y1, x2, y2, (x, y) -> {
if(mode == 0){
//replace
editorTable.drawBlocksReplace(x, y);
}else{
//normal
editorTable.drawBlocks(x, y);
}
});
}else if(mode == 0){ //replace-only mode, doesn't affect air
editorTable.drawBlocks(x, y, tile -> Mathf.chance(chance) && tile.block() != Blocks.air);
}else{
editorTable.drawBlocks(x, y, tile -> Mathf.chance(chance));
}
},
pencil(KeyCode.b, "replace", "square", "drawteams"){
{
edit = true;
draggable = true;
}
@Override
public void touched(int x, int y){
if(mode == -1){
//normal mode
editorTable.drawBlocks(x, y);
}else if(mode == 0){
//replace mode
editorTable.drawBlocksReplace(x, y);
}else if(mode == 1){
//square mode
editorTable.drawBlocks(x, y, true, tile -> true);
}else if(mode == 2){
//draw teams
editorTable.drawCircle(x, y, tile -> tile.setTeam(drawTeam));
}
}
},
eraser(KeyCode.e, "eraseores"){
{
edit = true;
draggable = true;
}
@Override
public void touched(int x, int y){
editorTable.drawCircle(x, y, tile -> {
if(mode == -1){
//erase block
tile.remove();
}else if(mode == 0){
//erase ore
tile.clearOverlay();
}
});
}
},
fill(KeyCode.g, "replaceall", "fillteams"){
{
edit = true;
}
IntSeq stack = new IntSeq();
@Override
public void touched(int x, int y){
if(!Structs.inBounds(x, y, world.width(), world.height()) || world.tile(x, y).block()!=null&&world.tile(x, y).block().isMultiblock()) return;
Tile tile = world.tile(x, y);
//mode 0 or 1, fill everything with the floor/tile or replace it
if(mode == 0 || mode == -1){
if(tile.block().isMultiblock()) return;
Boolf<Tile> tester;
Cons<Tile> setter;
Block drawBlock = MapEditorWindow.drawBlock;
if(drawBlock.isOverlay()){
Block dest = tile.overlay();
if(dest == drawBlock) return;
tester = t -> t.overlay() == dest && (t.floor().hasSurface() || !t.floor().needsSurface);
setter = t -> t.setOverlay(drawBlock);
}else if(drawBlock.isFloor()){
Block dest = tile.floor();
if(dest == drawBlock) return;
tester = t -> t.floor() == dest;
setter = t -> t.setFloorUnder(drawBlock.asFloor());
}else{
Block dest = tile.block();
if(dest == drawBlock) return;
tester = t -> t.block() == dest;
setter = t -> t.setBlock(drawBlock, drawTeam);
}
//replace only when the mode is 0 using the specified functions
fill(x, y, mode == 0, tester, setter);
}else if(mode == 1){ //mode 1 is team fill
//only fill synthetic blocks, it's meaningless otherwise
if(tile.synthetic()){
Team dest = tile.team();
if(dest == drawTeam) return;
fill(x, y, false, t -> t.getTeamID() == dest.id && t.synthetic(), t -> t.setTeam(drawTeam));
}
}
}
void fill(int x, int y, boolean replace, Boolf<Tile> tester, Cons<Tile> filler){
int width = world.width(), height = world.height();
if(replace){
//just do it on everything
for(int cx = 0; cx < width; cx++){
for(int cy = 0; cy < height; cy++){
Tile tile = world.tile(cx, cy);
if(tester.get(tile)){
filler.get(tile);
}
}
}
}else{
//perform flood fill
int x1;
stack.clear();
stack.add(Point2.pack(x, y));
try{
while(stack.size > 0 && stack.size < width*height){
int popped = stack.pop();
x = Point2.x(popped);
y = Point2.y(popped);
x1 = x;
while(x1 >= 0 && tester.get(world.tile(x1, y))) x1--;
x1++;
boolean spanAbove = false, spanBelow = false;
while(x1 < width && tester.get(world.tile(x1, y))){
filler.get(world.tile(x1, y));
if(!spanAbove && y > 0 && tester.get(world.tile(x1, y - 1))){
stack.add(Point2.pack(x1, y - 1));
spanAbove = true;
}else if(spanAbove && !tester.get(world.tile(x1, y - 1))){
spanAbove = false;
}
if(!spanBelow && y < height - 1 && tester.get(world.tile(x1, y + 1))){
stack.add(Point2.pack(x1, y + 1));
spanBelow = true;
}else if(spanBelow && y < height - 1 && !tester.get(world.tile(x1, y + 1))){
spanBelow = false;
}
x1++;
}
}
stack.clear();
}catch(OutOfMemoryError e){
//hack
stack = null;
System.gc();
e.printStackTrace();
stack = new IntSeq();
}
}
}
},
spray(KeyCode.r, "replace"){
final double chance = 0.012;
{
edit = true;
draggable = true;
}
@Override
public void touched(int x, int y){
//floor spray
if(drawBlock.isFloor()){
editorTable.drawCircle(x, y, tile -> {
if(Mathf.chance(chance)){
tile.setFloor(drawBlock.asFloor());
}
});
}else if(mode == 0){ //replace-only mode, doesn't affect air
editorTable.drawBlocks(x, y, tile -> Mathf.chance(chance) && tile.block() != Blocks.air);
}else{
editorTable.drawBlocks(x, y, tile -> Mathf.chance(chance));
}
}
};
public static final EditorTool[] all = values();
/** All the internal alternate placement modes of this tool. */
public final String[] altModes;
/** Key to activate this tool. */
public KeyCode key = KeyCode.unset;
/** The current alternate placement mode. -1 is the standard mode, no changes.*/
public int mode = -1;
/** Whether this tool causes canvas changes when touched.*/
public boolean edit;
/** Whether this tool should be dragged across the canvas when the mouse moves.*/
public boolean draggable;
EditorTool(){
this(new String[]{});
}
};
public static final EditorTool[] all = values();
EditorTool(KeyCode code){
this(new String[]{});
this.key = code;
}
/** All the internal alternate placement modes of this tool. */
public final String[] altModes;
/** Key to activate this tool. */
public KeyCode key = KeyCode.unset;
/** The current alternate placement mode. -1 is the standard mode, no changes.*/
public int mode = -1;
/** Whether this tool causes canvas changes when touched.*/
public boolean edit;
/** Whether this tool should be dragged across the canvas when the mouse moves.*/
public boolean draggable;
EditorTool(String... altModes){
this.altModes = altModes;
}
EditorTool(){
this(new String[]{});
EditorTool(KeyCode code, String... altModes){
this.altModes = altModes;
this.key = code;
}
public void touched(int x, int y){}
public void touchedLine(int x1, int y1, int x2, int y2){}
}
EditorTool(KeyCode code){
this(new String[]{});
this.key = code;
}
EditorTool(String... altModes){
this.altModes = altModes;
}
EditorTool(KeyCode code, String... altModes){
this.altModes = altModes;
this.key = code;
}
public void touched(int x, int y){}
public void touchedLine(int x1, int y1, int x2, int y2){}
}

View File

@@ -10,6 +10,7 @@ import arc.scene.ui.layout.*;
import arc.scene.utils.*;
import arc.struct.*;
import arc.util.*;
import mindustry.game.EventType;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.input.*;
@@ -26,6 +27,20 @@ public class PlayerWindow extends Window {
public PlayerWindow() {
super(Icon.players, "player");
only = true;
Events.run(EventType.Trigger.update, () -> {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
ScrollPane pane = find("player-pane");
pane.setWidget(rebuild());
}
if(target != null) {
if(control.input instanceof DesktopInput desktopInput) desktopInput.panning = true;
Core.camera.position.set(target.x, target.y);
}
});
}
@Override
@@ -48,20 +63,6 @@ public class PlayerWindow extends Window {
table.add(new OverScrollPane(rebuild(), Styles.noBarPane, scrollPos).disableScroll(true, false)).grow().name("player-pane");
}
public void update() {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
ScrollPane pane = find("player-pane");
pane.setWidget(rebuild());
}
if(target!=null) {
if(control.input instanceof DesktopInput)
((DesktopInput) control.input).panning = true;
Core.camera.position.set(target.x, target.y);
}
}
public Table rebuild(){
return new Table(table -> {
float h = 74f;

View File

@@ -1,11 +1,13 @@
package informatis.ui.windows;
import arc.Events;
import informatis.ui.*;
import informatis.draws.*;
import arc.math.geom.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.game.EventType;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.ui.*;
@@ -17,6 +19,15 @@ public class ToolWindow extends Window {
public ToolWindow() {
super(Icon.edit, "tool");
only = true;
Events.run(EventType.Trigger.update, () -> {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
((ScrollPane) find("tool-pane")).setWidget(rebuild());
}
});
}
@Override
@@ -33,15 +44,6 @@ public class ToolWindow extends Window {
}).growY();
}
public void update() {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
ScrollPane pane = find("tool-pane");
pane.setWidget(rebuild());
}
}
Table rebuild() {
return new Table(icons->{
for(OverDraw draw : OverDraws.all) {

View File

@@ -3,9 +3,7 @@ package informatis.ui.windows;
import arc.*;
import arc.math.*;
import arc.scene.*;
import arc.scene.style.Drawable;
import arc.scene.style.TextureRegionDrawable;
import informatis.core.*;
import arc.scene.style.*;
import informatis.ui.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
@@ -16,39 +14,27 @@ import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.core.*;
import mindustry.ctype.UnlockableContent;
import mindustry.ctype.*;
import mindustry.entities.Units;
import mindustry.entities.abilities.ShieldRegenFieldAbility;
import mindustry.entities.abilities.*;
import mindustry.entities.units.*;
import mindustry.game.EventType;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.logic.LAccess;
import mindustry.logic.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.blocks.*;
import mindustry.world.blocks.defense.ForceProjector;
import mindustry.world.blocks.defense.MendProjector;
import mindustry.world.blocks.defense.OverdriveProjector;
import mindustry.world.blocks.defense.turrets.ItemTurret;
import mindustry.world.blocks.defense.turrets.LiquidTurret;
import mindustry.world.blocks.defense.turrets.PowerTurret;
import mindustry.world.blocks.defense.turrets.ReloadTurret;
import mindustry.world.blocks.distribution.MassDriver;
import mindustry.world.blocks.environment.Floor;
import mindustry.world.blocks.defense.*;
import mindustry.world.blocks.defense.turrets.*;
import mindustry.world.blocks.distribution.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.payloads.*;
import mindustry.world.blocks.power.PowerGenerator;
import mindustry.world.blocks.power.PowerNode;
import mindustry.world.blocks.power.ThermalGenerator;
import mindustry.world.blocks.production.AttributeCrafter;
import mindustry.world.blocks.production.Drill;
import mindustry.world.blocks.production.GenericCrafter;
import mindustry.world.blocks.production.SolidPump;
import mindustry.world.blocks.storage.CoreBlock;
import mindustry.world.blocks.storage.StorageBlock;
import mindustry.world.blocks.units.Reconstructor;
import mindustry.world.blocks.units.UnitFactory;
import mindustry.world.consumers.ConsumePower;
import mindustry.world.blocks.power.*;
import mindustry.world.blocks.production.*;
import mindustry.world.blocks.storage.*;
import mindustry.world.blocks.units.*;
import mindustry.world.consumers.*;
import java.lang.reflect.Field;
import java.util.Objects;
@@ -67,14 +53,17 @@ public class UnitWindow extends Window {
float lastWidth;
final Seq<Color> lastColors = new Seq<>();
final Bits statuses = new Bits();
Teamc lastTarget;
public Teamc lastTarget, target;
public boolean locked;
Seq<BarInfo.BarData> data = new Seq<>();
public UnitWindow() {
super(Icon.units, "unit");
Events.run(EventType.Trigger.update, () -> {
if(!locked) target = getTarget();
try {
BarInfo.getInfo(getTarget());
data = BarInfo.getInfo(target);
} catch (IllegalAccessException | NoSuchFieldException err) {
err.printStackTrace();
}
@@ -89,7 +78,7 @@ public class UnitWindow extends Window {
public void draw() {
super.draw();
Draw.color(locked? Pal.accent:Pal.gray);
Draw.color(locked ? Pal.accent : Pal.gray);
Draw.alpha(parentAlpha);
Lines.stroke(Scl.scl(3f));
Lines.rect(x-size/2f, y-size/2f, width+size, height+size);
@@ -105,10 +94,7 @@ public class UnitWindow extends Window {
}
profileImage.setDrawable(region);
});
profileImage.clicked(() -> {
if (target == getTarget()) locked = !locked;
target = getTarget();
});
profileImage.clicked(() -> locked = !locked);
Label profileLabel = new Label(() -> {
if (target instanceof Unit u && u.type != null) return u.type.localizedName;
if (target instanceof Building b && b.block != null) {
@@ -124,7 +110,7 @@ public class UnitWindow extends Window {
if (lastTarget != target) {
lastTarget = target;
for (int i = 0; i < barSize; i++) {
Color color = i >= BarInfo.data.size ? Color.clear : BarInfo.data.get(i).color;
Color color = i >= data.size ? Color.clear : data.get(i).color;
if (i >= lastColors.size) lastColors.add(color);
else lastColors.set(i, color);
}
@@ -161,7 +147,7 @@ public class UnitWindow extends Window {
).margin(3f).growX().row();
table.table().update(tt -> {
tt.clear();
if(getTarget() instanceof Unit u && u.type != null && u.hasWeapons()) {
if(target instanceof Unit u && u.type != null && u.hasWeapons()) {
for(int r = 0; r < u.type.weapons.size; r++){
Weapon weapon = u.type.weapons.get(r);
WeaponMount mount = u.mounts[r];
@@ -266,45 +252,43 @@ public class UnitWindow extends Window {
Table addBar(int index) {
return new Table(bar -> {
bar.add(new SBar(
() -> index >= BarInfo.data.size ? "[lightgray]<Empty>[]" : BarInfo.data.get(index).name,
() -> index >= BarInfo.data.size ? Color.clear : BarInfo.data.get(index).color,
() -> index >= data.size ? "[lightgray]<Empty>[]" : data.get(index).name,
() -> index >= data.size ? Color.clear : data.get(index).color,
() -> lastColors.get(index),
() -> index >= BarInfo.data.size ? 0 : BarInfo.data.get(index).number)
() -> index >= data.size ? 0 : data.get(index).number)
).height(4 * 8f).growX();
if(index >= BarInfo.data.size) return;
if(index >= data.size) return;
Image icon = new Image(){
@Override
public void draw() {
validate();
if(index >= BarInfo.data.size) return;
if(index >= data.size) return;
float x = this.x + imageX;
float y = this.y + imageY;
float width = imageWidth * this.scaleX;
float height = imageHeight * this.scaleY;
Draw.color(Color.white);
Draw.alpha(parentAlpha * color.a);
BarInfo.BarData data = BarInfo.data.get(index);
BarInfo.BarData da = data.get(index);
if(hasMouse()) getDrawable().draw(x, y, width, height);
else {
data.icon.draw(x, y, width, height);
if(ScissorStack.push(Tmp.r1.set(ScissorStack.peek().x + x, ScissorStack.peek().y + y, width, height * data.number))) {
Draw.color(data.color);
data.icon.draw(x, y, width, height);
da.icon.draw(x, y, width, height);
if(ScissorStack.push(Tmp.r1.set(ScissorStack.peek().x + x, ScissorStack.peek().y + y, width, height * da.number))) {
Draw.color(da.color);
da.icon.draw(x, y, width, height);
ScissorStack.pop();
}
}
}
};
icon.setDrawable(BarInfo.data.get(index).icon);
icon.setDrawable(data.get(index).icon);
bar.add(icon).size(iconMed * 0.75f).padLeft(8f);
});
}
}
class BarInfo {
public static Seq<BarData> data = new Seq<>();
public static <T extends Teamc> void getInfo(T target) throws IllegalAccessException, NoSuchFieldException {
data.clear();
public static <T extends Teamc> Seq<BarData> getInfo(T target) throws IllegalAccessException, NoSuchFieldException {
Seq<BarData> data = new Seq<>();
if(target instanceof Healthc healthc){
data.add(new BarData(bundle.format("shar-stat.health", formatNumber(healthc.health())), Pal.health, healthc.healthf(), health));
@@ -473,6 +457,8 @@ class BarInfo {
data.add(new BarData(bundle.format("shar-stat.attr", Mathf.round(display)), Pal.ammo, pro));
}
return data;
}
static class BarData {

View File

@@ -30,6 +30,15 @@ public class WaveWindow extends Window {
super(Icon.waves, "wave");
height = 500;
width = 450;
only = true;
Events.run(EventType.Trigger.update, () -> {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
((ScrollPane) find("wave-pane")).setWidget(rebuild());
}
});
}
@Override
@@ -93,15 +102,6 @@ public class WaveWindow extends Window {
});
}
public void update() {
heat += Time.delta;
if(heat >= 60f) {
heat = 0f;
ScrollPane pane = find("wave-pane");
pane.setWidget(rebuild());
}
}
public ObjectIntMap<SpawnGroup> getWaveGroup(int index) {
ObjectIntMap<SpawnGroup> groups = new ObjectIntMap<>();
for (SpawnGroup group : state.rules.spawns) {

View File

@@ -12,13 +12,11 @@ import arc.scene.ui.layout.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.ui.*;
import informatis.ui.*;
public class Window extends Table {
public TextureRegionDrawable icon;
public int id;
public Cons<Table> content;
public boolean shown = false;
public boolean shown = false, only = false;
public Table window;
public float minWindowWidth = 160, minWindowHeight = 60;
@@ -33,7 +31,7 @@ public class Window extends Table {
this.name = name;
this.icon = icon;
window = this;
id = WindowManager.register(this);
WindowManager.register(this);
titleBar();
row();
@@ -74,7 +72,10 @@ public class Window extends Table {
b.image(icon.getRegion()).size(20f).padLeft(15);
b.add(Core.bundle.get("window."+name+".name")).padLeft(20);
}).touchable(Touchable.disabled).grow();
t.table(Tex.buttonEdge3, b -> b.button(Icon.cancel, Styles.emptyi, () -> shown = false).fill()).width(80f).growY();
t.table(Tex.buttonEdge3, b -> b.button(Icon.cancel, Styles.emptyi, () -> {
shown = false;
if(!only) WindowManager.windows.get(getClass()).remove(this);
}).fill()).width(80f).growY();
// handles the dragging.
t.touchable = Touchable.enabled;

View File

@@ -0,0 +1,77 @@
package informatis.ui.windows;
import arc.*;
import arc.scene.ui.layout.Table;
import arc.struct.*;
import mindustry.*;
import mindustry.graphics.Pal;
import mindustry.ui.*;
import java.lang.reflect.InvocationTargetException;
public class WindowManager {
public static ObjectMap<Class<? extends Window>, Seq<Window>> windows = new ObjectMap<>();
public static void init(){
Vars.ui.hudGroup.fill(t -> {
t.name = "Windows";
for(Seq<Window> windows : windows.values()){
for(Window window : windows) {
t.add(window).height(window.getHeight()).width(window.getWidth());
}
}
});
Vars.ui.hudGroup.fill(t -> {
t.name = "window sidebar";
t.center().left();
t.table(Core.atlas.drawable("informatis-sidebar"), b -> {
b.name = "Window Buttons";
b.left();
for(ObjectMap.Entry<Class<? extends Window>, Seq<Window>> windows : windows){
Class<? extends Window> key = windows.key;
Seq<Window> value = windows.value;
Window window = value.peek();
b.stack(
new Table(bt -> {
bt.button(window.icon, Styles.emptyi, () -> {
Window window1 = window;
window1.parent.setLayoutEnabled(false);
if(!window.only) {
try {
window1 = key.getConstructor().newInstance();
window1.setPosition(value.peek().x + 50, value.peek().y + 50);
window1.sizeBy(200, 200);
} catch (InstantiationException | IllegalAccessException |
InvocationTargetException | NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
}
window1.toggle();
for (Seq<Window> ws : WindowManager.windows.values()) {
ws.each(w -> w.setLayoutEnabled(true));
}
}).size(40f).tooltip(tt -> {
tt.setBackground(Styles.black6);
tt.label(() -> Core.bundle.get("window."+window.name+".name")).pad(2f);
});
}),
new Table(bt -> {
bt.right().bottom();
if(!window.only) bt.label(() -> String.valueOf(value.size)).get().setColor(Pal.accent);
})
).row();
}
}).left();
});
}
public static void register(Window window){
Table table = Vars.ui.hudGroup.find("Windows");
if(table != null) table.add(window).height(window.getHeight()).width(window.getWidth());
if(!windows.containsKey(window.getClass())) windows.put(window.getClass(), Seq.with(window));
else windows.get(window.getClass()).add(window);
}
}