mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-12-05 18:30:22 -08:00
531 lines
19 KiB
Java
531 lines
19 KiB
Java
package mindustry.graphics;
|
|
|
|
import arc.*;
|
|
import arc.graphics.*;
|
|
import arc.graphics.g2d.*;
|
|
import arc.math.*;
|
|
import arc.math.geom.*;
|
|
import arc.struct.*;
|
|
import arc.util.*;
|
|
import mindustry.ctype.*;
|
|
import mindustry.gen.*;
|
|
import mindustry.world.*;
|
|
|
|
import java.util.*;
|
|
|
|
import static mindustry.Vars.*;
|
|
|
|
public class Drawf{
|
|
private static final Vec2[] vecs = new Vec2[]{new Vec2(), new Vec2(), new Vec2(), new Vec2()};
|
|
private static final FloatSeq points = new FloatSeq();
|
|
|
|
/** Bleeds a mod pixmap if linear filtering is enabled. */
|
|
public static void checkBleed(Pixmap pixmap){
|
|
if(Core.settings.getBool("linear", true)){
|
|
Pixmaps.bleed(pixmap);
|
|
}
|
|
}
|
|
|
|
public static void underwater(Runnable run){
|
|
renderer.blocks.floor.drawUnderwater(run);
|
|
}
|
|
|
|
//TODO offset unused
|
|
public static void flame(float x, float y, int divisions, float rotation, float length, float width, float pan){
|
|
float len1 = length * pan, len2 = length * (1f - pan);
|
|
|
|
points.clear();
|
|
|
|
//left side; half arc beginning at 90 degrees and ending at 270
|
|
for(int i = 0; i < divisions; i++){
|
|
float rot = 90f + 180f * i / (float)divisions;
|
|
Tmp.v1.trnsExact(rot, width);
|
|
|
|
point(
|
|
(Tmp.v1.x + width) / width * len1, //convert to 0..1, then multiply by desired length
|
|
Tmp.v1.y, //Y axis remains unchanged
|
|
x, y,
|
|
rotation
|
|
);
|
|
}
|
|
|
|
//right side; half arc beginning at -90 (270) and ending at 90
|
|
for(int i = 0; i < divisions; i++){
|
|
float rot = -90f + 180f * i / (float)divisions;
|
|
Tmp.v1.trnsExact(rot, width);
|
|
|
|
point(
|
|
len1 + (Tmp.v1.x) / width * len2, //convert to 0..1, then multiply by desired length and offset relative to previous segment
|
|
Tmp.v1.y, //Y axis remains unchanged
|
|
x, y,
|
|
rotation
|
|
);
|
|
}
|
|
|
|
Fill.poly(points);
|
|
}
|
|
|
|
public static void flameFront(float x, float y, int divisions, float rotation, float length, float width){
|
|
//TODO I don't know why this is necessary yet. Does FIll.poly screw up with triangles?
|
|
divisions = Mathf.round(divisions, 2) + 1;
|
|
|
|
points.clear();
|
|
|
|
//right side; half arc beginning at -90 (270) and ending at 90
|
|
for(int i = 0; i <= divisions; i++){
|
|
float rot = -90f + 180f * i / (float)divisions;
|
|
Tmp.v1.trnsExact(rot, width);
|
|
|
|
point(
|
|
(Tmp.v1.x) / width * length, //convert to 0..1, then multiply by desired length and offset relative to previous segment
|
|
Tmp.v1.y, //Y axis remains unchanged
|
|
x, y,
|
|
rotation
|
|
);
|
|
}
|
|
|
|
Fill.poly(points);
|
|
}
|
|
|
|
private static void point(float x, float y, float baseX, float baseY, float rotation){
|
|
//TODO test exact and non-exact
|
|
Tmp.v1.set(x, y).rotateRadExact(rotation * Mathf.degRad);
|
|
points.add(Tmp.v1.x + baseX, Tmp.v1.y + baseY);
|
|
}
|
|
|
|
public static void buildBeam(float x, float y, float tx, float ty, float radius){
|
|
float ang = Angles.angle(x, y, tx, ty);
|
|
|
|
vecs[0].set(tx - radius, ty - radius);
|
|
vecs[1].set(tx + radius, ty - radius);
|
|
vecs[2].set(tx - radius, ty + radius);
|
|
vecs[3].set(tx + radius, ty + radius);
|
|
|
|
Arrays.sort(vecs, Structs.comparingFloat(vec -> -Angles.angleDist(Angles.angle(x, y, vec.x, vec.y), ang)));
|
|
|
|
Vec2 close = Geometry.findClosest(x, y, vecs);
|
|
|
|
float x1 = vecs[0].x, y1 = vecs[0].y,
|
|
x2 = close.x, y2 = close.y,
|
|
x3 = vecs[1].x, y3 = vecs[1].y;
|
|
|
|
if(renderer.animateShields){
|
|
if(close != vecs[0] && close != vecs[1]){
|
|
Fill.tri(x, y, x1, y1, x2, y2);
|
|
Fill.tri(x, y, x3, y3, x2, y2);
|
|
}else{
|
|
Fill.tri(x, y, x1, y1, x3, y3);
|
|
}
|
|
}else{
|
|
Lines.line(x, y, x1, y1);
|
|
Lines.line(x, y, x3, y3);
|
|
}
|
|
}
|
|
|
|
public static void additive(TextureRegion region, Color color, float x, float y){
|
|
additive(region, color, x, y, 0f, Layer.blockAdditive);
|
|
}
|
|
|
|
public static void additive(TextureRegion region, Color color, float x, float y, float rotation){
|
|
additive(region, color, x, y, rotation, Layer.blockAdditive);
|
|
}
|
|
|
|
public static void additive(TextureRegion region, Color color, float x, float y, float rotation, float layer){
|
|
additive(region, color, 1f, x, y, rotation, layer);
|
|
}
|
|
|
|
public static void additive(TextureRegion region, Color color, float alpha, float x, float y, float width, float height, float layer){
|
|
float pz = Draw.z();
|
|
Draw.z(layer);
|
|
Draw.color(color, alpha * color.a);
|
|
Draw.blend(Blending.additive);
|
|
Draw.rect(region, x, y, width, height, 0f);
|
|
Draw.blend();
|
|
Draw.color();
|
|
Draw.z(pz);
|
|
}
|
|
|
|
public static void additive(TextureRegion region, Color color, float alpha, float x, float y, float rotation, float layer){
|
|
float pz = Draw.z();
|
|
Draw.z(layer);
|
|
Draw.color(color, alpha * color.a);
|
|
Draw.blend(Blending.additive);
|
|
Draw.rect(region, x, y, rotation);
|
|
Draw.blend();
|
|
Draw.color();
|
|
Draw.z(pz);
|
|
}
|
|
|
|
public static void additive(TextureRegion region, Color color, float alpha, float x, float y, float rotation, float layer, float originX, float originY){
|
|
float pz = Draw.z(), w = region.width * region.scl() * Draw.xscl, h = region.height * region.scl() * Draw.yscl;
|
|
Draw.z(layer);
|
|
Draw.color(color, alpha * color.a);
|
|
Draw.blend(Blending.additive);
|
|
Draw.rect(region, x, y, w, h, w / 2f + originX * region.scl() * Draw.xscl, h / 2f + originY * region.scl() * Draw.yscl, rotation);
|
|
Draw.blend();
|
|
Draw.color();
|
|
Draw.z(pz);
|
|
}
|
|
|
|
public static void limitLine(Position start, Position dest, float len1, float len2, Color color){
|
|
if(start.within(dest, len1 + len2)){
|
|
return;
|
|
}
|
|
Tmp.v1.set(dest).sub(start).setLength(len1);
|
|
Tmp.v2.set(Tmp.v1).scl(-1f).setLength(len2);
|
|
|
|
Drawf.line(color, start.getX() + Tmp.v1.x, start.getY() + Tmp.v1.y, dest.getX() + Tmp.v2.x, dest.getY() + Tmp.v2.y);
|
|
}
|
|
|
|
public static void limitLine(Position start, Position dest, float len1, float len2){
|
|
limitLine(start, dest, len1, len2, Pal.accent);
|
|
}
|
|
|
|
public static void dashLineDst(Color color, float x, float y, float x2, float y2){
|
|
dashLine(color, x, y, x2, y2, (int)(Mathf.dst(x, y, x2, y2) / tilesize * 1.6f));
|
|
}
|
|
|
|
public static void dashLine(Color color, float x, float y, float x2, float y2){
|
|
dashLine(color, x, y, x2, y2, (int)(Math.max(Math.abs(x - x2), Math.abs(y - y2)) / tilesize * 2));
|
|
}
|
|
|
|
public static void dashLine(Color color, float x, float y, float x2, float y2, int segments){
|
|
Lines.stroke(3f);
|
|
Draw.color(Pal.gray, color.a);
|
|
Lines.dashLine(x, y, x2, y2, segments);
|
|
Lines.stroke(1f, color);
|
|
Lines.dashLine(x, y, x2, y2, segments);
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void line(Color color, float x, float y, float x2, float y2){
|
|
Lines.stroke(3f);
|
|
Draw.color(Pal.gray, color.a);
|
|
Lines.line(x, y, x2, y2);
|
|
Lines.stroke(1f, color);
|
|
Lines.line(x, y, x2, y2);
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void dashLineBasic(float x, float y, float x2, float y2){
|
|
Lines.dashLine(x, y, x2, y2, (int)(Math.max(Math.abs(x - x2), Math.abs(y - y2)) / tilesize * 2));
|
|
}
|
|
|
|
public static void dashSquare(Color color, float x, float y, float size){
|
|
dashRect(color, x - size/2f, y - size/2f, size, size);
|
|
}
|
|
|
|
public static void dashRect(Color color, Rect rect){
|
|
dashRect(color, rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
|
|
public static void dashRect(Color color, float x, float y, float width, float height){
|
|
dashLine(color, x, y, x + width, y);
|
|
dashLine(color, x + width, y, x + width, y + height);
|
|
dashLine(color, x + width, y + height, x, y + height);
|
|
dashLine(color, x, y + height, x, y);
|
|
}
|
|
|
|
public static void dashSquareBasic(float x, float y, float size){
|
|
dashRectBasic(x - size/2f, y - size/2f, size, size);
|
|
}
|
|
|
|
public static void dashRectBasic(float x, float y, float width, float height){
|
|
dashLineBasic(x, y, x + width, y);
|
|
dashLineBasic(x + width, y, x + width, y + height);
|
|
dashLineBasic(x + width, y + height, x, y + height);
|
|
dashLineBasic( x, y + height, x, y);
|
|
}
|
|
|
|
public static void target(float x, float y, float rad, Color color){
|
|
target(x, y, rad, 1, color);
|
|
}
|
|
|
|
public static void target(float x, float y, float rad, float alpha, Color color){
|
|
Lines.stroke(3f);
|
|
Draw.color(Pal.gray, alpha);
|
|
Lines.poly(x, y, 4, rad, Time.time * 1.5f);
|
|
Lines.spikes(x, y, 3f/7f * rad, 6f/7f * rad, 4, Time.time * 1.5f);
|
|
Lines.stroke(1f);
|
|
Draw.color(color, alpha);
|
|
Lines.poly(x, y, 4, rad, Time.time * 1.5f);
|
|
Lines.spikes(x, y, 3f/7f * rad, 6f/7f * rad, 4, Time.time * 1.5f);
|
|
Draw.reset();
|
|
}
|
|
|
|
/** Sets Draw.z to the text layer, and returns the previous layer. */
|
|
public static float text(){
|
|
float z = Draw.z();
|
|
if(renderer.pixelate){
|
|
Draw.z(Layer.endPixeled);
|
|
}
|
|
|
|
return z;
|
|
}
|
|
|
|
public static void light(float x, float y, float radius, Color color, float opacity){
|
|
if(renderer == null) return;
|
|
renderer.lights.add(x, y, radius, color, opacity);
|
|
}
|
|
|
|
public static void light(Position pos, float radius, Color color, float opacity){
|
|
if(renderer == null) return;
|
|
light(pos.getX(), pos.getY(), radius, color, opacity);
|
|
}
|
|
|
|
public static void light(float x, float y, TextureRegion region, Color color, float opacity){
|
|
light(x, y, region, 0f, color, opacity);
|
|
}
|
|
|
|
public static void light(float x, float y, TextureRegion region, float rotation, Color color, float opacity){
|
|
if(renderer == null) return;
|
|
renderer.lights.add(x, y, region, rotation, color, opacity);
|
|
}
|
|
|
|
public static void light(float x, float y, float x2, float y2){
|
|
if(renderer == null) return;
|
|
renderer.lights.line(x, y, x2, y2, 30, Color.orange, 0.3f);
|
|
}
|
|
|
|
public static void light(float x, float y, float x2, float y2, float stroke, Color tint, float alpha){
|
|
if(renderer == null) return;
|
|
renderer.lights.line(x, y, x2, y2, stroke, tint, alpha);
|
|
}
|
|
|
|
public static void selected(Building tile, Color color){
|
|
selected(tile.tile, color);
|
|
}
|
|
|
|
public static void selected(Tile tile, Color color){
|
|
selected(tile.x, tile.y, tile.block(), color);
|
|
}
|
|
|
|
public static void selected(int x, int y, Block block, Color color){
|
|
Draw.color(color);
|
|
for(int i = 0; i < 4; i++){
|
|
Point2 p = Geometry.d8edge[i];
|
|
float offset = -Math.max(block.size - 1, 0) / 2f * tilesize;
|
|
Draw.rect("block-select",
|
|
x*tilesize + block.offset + offset * p.x,
|
|
y*tilesize + block.offset + offset * p.y, i * 90);
|
|
}
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void shadow(float x, float y, float rad){
|
|
shadow(x, y, rad, 1f);
|
|
}
|
|
|
|
public static void squareShadow(float x, float y, float rad, float alpha){
|
|
Draw.color(0, 0, 0, 0.4f * alpha);
|
|
Draw.rect("square-shadow", x, y, rad * Draw.xscl, rad * Draw.yscl);
|
|
Draw.color();
|
|
}
|
|
|
|
public static void shadow(float x, float y, float rad, float alpha){
|
|
Draw.color(0, 0, 0, 0.4f * alpha);
|
|
Draw.rect("circle-shadow", x, y, rad * Draw.xscl, rad * Draw.yscl);
|
|
Draw.color();
|
|
}
|
|
|
|
public static void shadow(TextureRegion region, float x, float y, float rotation){
|
|
Draw.color(Pal.shadow);
|
|
Draw.rect(region, x, y, rotation);
|
|
Draw.color();
|
|
}
|
|
|
|
public static void shadow(TextureRegion region, float x, float y){
|
|
Draw.color(Pal.shadow);
|
|
Draw.rect(region, x, y);
|
|
Draw.color();
|
|
}
|
|
|
|
public static void shadow(TextureRegion region, float x, float y, float width, float height, float rotation){
|
|
Draw.color(Pal.shadow);
|
|
Draw.rect(region, x, y, width, height, rotation);
|
|
Draw.color();
|
|
}
|
|
|
|
public static void liquid(TextureRegion region, float x, float y, float alpha, Color color, float rotation){
|
|
Draw.color(color, alpha * color.a);
|
|
Draw.rect(region, x, y, rotation);
|
|
Draw.color();
|
|
}
|
|
|
|
public static void liquid(TextureRegion region, float x, float y, float alpha, Color color){
|
|
Draw.color(color, alpha * color.a);
|
|
Draw.rect(region, x, y);
|
|
Draw.color();
|
|
}
|
|
|
|
public static void dashCircle(float x, float y, float rad, Color color){
|
|
Lines.stroke(3f, Pal.gray);
|
|
Lines.dashCircle(x, y, rad);
|
|
Lines.stroke(1f, color);
|
|
Lines.dashCircle(x, y, rad);
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void circles(float x, float y, float rad){
|
|
circles(x, y, rad, Pal.accent);
|
|
}
|
|
|
|
public static void circles(float x, float y, float rad, Color color){
|
|
Lines.stroke(3f, Pal.gray);
|
|
Lines.circle(x, y, rad);
|
|
Lines.stroke(1f, color);
|
|
Lines.circle(x, y, rad);
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void select(float x, float y, float radius, Color color){
|
|
Lines.stroke(3f, Pal.gray);
|
|
Lines.square(x, y, radius + 1f);
|
|
Lines.stroke(1f, color);
|
|
Lines.square(x, y, radius);
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void square(float x, float y, float radius, float rotation, Color color){
|
|
Lines.stroke(3f, Pal.gray.write(Tmp.c3).a(color.a));
|
|
Lines.square(x, y, radius + 1f, rotation);
|
|
Lines.stroke(1f, color);
|
|
Lines.square(x, y, radius + 1f, rotation);
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void poly(float x, float y, int sides, float radius, float rotation, Color color){
|
|
Lines.stroke(3f, Pal.gray);
|
|
Lines.poly(x, y, sides, radius + 1f, rotation);
|
|
Lines.stroke(1f, color);
|
|
Lines.poly(x, y, sides, radius + 1f, rotation);
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void square(float x, float y, float radius, float rotation){
|
|
square(x, y, radius, rotation, Pal.accent);
|
|
}
|
|
|
|
public static void square(float x, float y, float radius, Color color){
|
|
square(x, y, radius, 45, color);
|
|
}
|
|
|
|
public static void square(float x, float y, float radius){
|
|
square(x, y, radius, 45);
|
|
}
|
|
|
|
public static void arrow(float x, float y, float x2, float y2, float length, float radius){
|
|
arrow(x, y, x2, y2, length, radius, Pal.accent);
|
|
}
|
|
|
|
public static void arrow(float x, float y, float x2, float y2, float length, float radius, Color color){
|
|
float angle = Angles.angle(x, y, x2, y2);
|
|
float space = 2f;
|
|
Tmp.v1.set(x2, y2).sub(x, y).limit(length);
|
|
float vx = Tmp.v1.x + x, vy = Tmp.v1.y + y;
|
|
|
|
Draw.color(Pal.gray);
|
|
Fill.poly(vx, vy, 3, radius + space, angle);
|
|
Draw.color(color);
|
|
Fill.poly(vx, vy, 3, radius, angle);
|
|
Draw.color();
|
|
}
|
|
|
|
public static void laser(TextureRegion line, TextureRegion edge, float x, float y, float x2, float y2){
|
|
laser(line, edge, edge, x, y, x2, y2, 1f);
|
|
}
|
|
|
|
public static void laser(TextureRegion line, TextureRegion start, TextureRegion end, float x, float y, float x2, float y2){
|
|
laser(line, start, end, x, y, x2, y2, 1f);
|
|
}
|
|
|
|
public static void laser(TextureRegion line, TextureRegion edge, float x, float y, float x2, float y2, float scale){
|
|
laser(line, edge, edge, x, y, x2, y2, scale);
|
|
}
|
|
|
|
public static void laser(TextureRegion line, TextureRegion start, TextureRegion end, float x, float y, float x2, float y2, float scale){
|
|
float scl = 8f * scale * Draw.scl, rot = Mathf.angle(x2 - x, y2 - y);
|
|
float vx = Mathf.cosDeg(rot) * scl, vy = Mathf.sinDeg(rot) * scl;
|
|
|
|
Draw.rect(start, x, y, start.width * scale * start.scl(), start.height * scale * start.scl(), rot + 180);
|
|
Draw.rect(end, x2, y2, end.width * scale * end.scl(), end.height * scale * end.scl(), rot);
|
|
|
|
Lines.stroke(12f * scale);
|
|
Lines.line(line, x + vx, y + vy, x2 - vx, y2 - vy, false);
|
|
Lines.stroke(1f);
|
|
|
|
light(x, y, x2, y2);
|
|
}
|
|
|
|
public static void tri(float x, float y, float width, float length, float rotation){
|
|
float
|
|
fx = Angles.trnsx(rotation, length),
|
|
fy = Angles.trnsy(rotation, length),
|
|
rx = Angles.trnsx(rotation - 90f, width / 2f),
|
|
ry = Angles.trnsy(rotation - 90f, width / 2f);
|
|
Fill.tri(
|
|
x + rx, y + ry,
|
|
x + fx, y + fy,
|
|
x - rx, y - ry
|
|
);
|
|
}
|
|
|
|
public static void construct(Building t, UnlockableContent content, float rotation, float progress, float alpha, float time){
|
|
construct(t, content.fullIcon, rotation, progress, alpha, time);
|
|
}
|
|
|
|
public static void construct(float x, float y, TextureRegion region, float rotation, float progress, float alpha, float time){
|
|
construct(x, y, region, Pal.accent, rotation, progress, alpha, time);
|
|
}
|
|
|
|
public static void construct(float x, float y, TextureRegion region, Color color, float rotation, float progress, float alpha, float time){
|
|
Shaders.build.region = region;
|
|
Shaders.build.progress = progress;
|
|
Shaders.build.color.set(color);
|
|
Shaders.build.color.a = alpha;
|
|
Shaders.build.time = -time / 20f;
|
|
|
|
Draw.shader(Shaders.build);
|
|
Draw.rect(region, x, y, rotation);
|
|
Draw.shader();
|
|
|
|
Draw.reset();
|
|
}
|
|
|
|
public static void construct(Building t, TextureRegion region, float rotation, float progress, float alpha, float time){
|
|
construct(t, region, Pal.accent, rotation, progress, alpha, time);
|
|
}
|
|
|
|
public static void construct(Building t, TextureRegion region, Color color, float rotation, float progress, float alpha, float time){
|
|
construct(t, region, color, rotation, progress, alpha, time, t.block.size * tilesize - 4f);
|
|
}
|
|
|
|
public static void construct(Building t, TextureRegion region, Color color, float rotation, float progress, float alpha, float time, float size){
|
|
Shaders.build.region = region;
|
|
Shaders.build.progress = progress;
|
|
Shaders.build.color.set(color);
|
|
Shaders.build.color.a = alpha;
|
|
Shaders.build.time = -time / 20f;
|
|
|
|
Draw.shader(Shaders.build);
|
|
Draw.rect(region, t.x, t.y, rotation);
|
|
Draw.shader();
|
|
|
|
Draw.color(Pal.accent);
|
|
Draw.alpha(alpha);
|
|
|
|
Lines.lineAngleCenter(t.x + Mathf.sin(time, 20f, size / 2f), t.y, 90, size);
|
|
|
|
Draw.reset();
|
|
}
|
|
|
|
/** Draws a sprite that should be light-wise correct, when rotated. Provided sprite must be symmetrical in shape. */
|
|
public static void spinSprite(TextureRegion region, float x, float y, float r){
|
|
float a = Draw.getColorAlpha();
|
|
r = Mathf.mod(r, 90f);
|
|
Draw.rect(region, x, y, r);
|
|
Draw.alpha(r / 90f*a);
|
|
Draw.rect(region, x, y, r - 90f);
|
|
Draw.alpha(a);
|
|
}
|
|
}
|