Files
Mindustry/core/src/mindustry/entities/part/RegionPart.java
2023-05-11 01:06:49 -04:00

206 lines
7.3 KiB
Java

package mindustry.entities.part;
import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
import mindustry.graphics.*;
public class RegionPart extends DrawPart{
protected PartParams childParam = new PartParams();
/** Appended to unit/weapon/block name and drawn. */
public String suffix = "";
/** Overrides suffix if set. */
public @Nullable String name;
public TextureRegion heat;
public TextureRegion[] regions = {};
public TextureRegion[] outlines = {};
/** If true, parts are mirrored across the turret. Requires -1 and -2 regions. */
public boolean mirror = false;
/** If true, an outline is drawn under the part. */
public boolean outline = true;
/** If true, the base + outline regions are drawn. Set to false for heat-only regions. */
public boolean drawRegion = true;
/** If true, the heat region produces light. */
public boolean heatLight = false;
/** Progress function for determining position/rotation. */
public PartProgress progress = PartProgress.warmup;
/** Progress function for scaling. */
public PartProgress growProgress = PartProgress.warmup;
/** Progress function for heat alpha. */
public PartProgress heatProgress = PartProgress.heat;
public Blending blending = Blending.normal;
public float layer = -1, layerOffset = 0f, heatLayerOffset = 1f, turretHeatLayer = Layer.turretHeat;
public float outlineLayerOffset = -0.001f;
public float x, y, xScl = 1f, yScl = 1f, rotation;
public float moveX, moveY, growX, growY, moveRot;
public float heatLightOpacity = 0.3f;
public @Nullable Color color, colorTo, mixColor, mixColorTo;
public Color heatColor = Pal.turretHeat.cpy();
public Seq<DrawPart> children = new Seq<>();
public Seq<PartMove> moves = new Seq<>();
public RegionPart(String region){
this.suffix = region;
}
public RegionPart(String region, Blending blending, Color color){
this.suffix = region;
this.blending = blending;
this.color = color;
outline = false;
}
public RegionPart(){
}
@Override
public void draw(PartParams params){
float z = Draw.z();
if(layer > 0) Draw.z(layer);
//TODO 'under' should not be special cased like this...
if(under && turretShading) Draw.z(z - 0.0001f);
Draw.z(Draw.z() + layerOffset);
float prevZ = Draw.z();
float prog = progress.getClamp(params), sclProg = growProgress.getClamp(params);
float mx = moveX * prog, my = moveY * prog, mr = moveRot * prog + rotation,
gx = growX * sclProg, gy = growY * sclProg;
if(moves.size > 0){
for(int i = 0; i < moves.size; i++){
var move = moves.get(i);
float p = move.progress.getClamp(params);
mx += move.x * p;
my += move.y * p;
mr += move.rot * p;
gx += move.gx * p;
gy += move.gy * p;
}
}
int len = mirror && params.sideOverride == -1 ? 2 : 1;
float preXscl = Draw.xscl, preYscl = Draw.yscl;
Draw.xscl *= xScl + gx;
Draw.yscl *= yScl + gy;
for(int s = 0; s < len; s++){
//use specific side if necessary
int i = params.sideOverride == -1 ? s : params.sideOverride;
//can be null
var region = drawRegion ? regions[Math.min(i, regions.length - 1)] : null;
float sign = (i == 0 ? 1 : -1) * params.sideMultiplier;
Tmp.v1.set((x + mx) * sign, y + my).rotateRadExact((params.rotation - 90) * Mathf.degRad);
float
rx = params.x + Tmp.v1.x,
ry = params.y + Tmp.v1.y,
rot = mr * sign + params.rotation - 90;
Draw.xscl *= sign;
if(outline && drawRegion){
Draw.z(prevZ + outlineLayerOffset);
Draw.rect(outlines[Math.min(i, regions.length - 1)], rx, ry, rot);
Draw.z(prevZ);
}
if(drawRegion && region.found()){
if(color != null && colorTo != null){
Draw.color(color, colorTo, prog);
}else if(color != null){
Draw.color(color);
}
if(mixColor != null && mixColorTo != null){
Draw.mixcol(mixColor, mixColorTo, prog);
}else if(mixColor != null){
Draw.mixcol(mixColor, mixColor.a);
}
Draw.blend(blending);
Draw.rect(region, rx, ry, rot);
Draw.blend();
if(color != null) Draw.color();
}
if(heat.found()){
float hprog = heatProgress.getClamp(params);
heatColor.write(Tmp.c1).a(hprog * heatColor.a);
Drawf.additive(heat, Tmp.c1, rx, ry, rot, turretShading ? turretHeatLayer : Draw.z() + heatLayerOffset);
if(heatLight) Drawf.light(rx, ry, heat, rot, Tmp.c1, heatLightOpacity * hprog);
}
Draw.xscl *= sign;
}
Draw.color();
Draw.mixcol();
Draw.z(z);
//draw child, if applicable - only at the end
//TODO lots of copy-paste here
if(children.size > 0){
for(int s = 0; s < len; s++){
int i = (params.sideOverride == -1 ? s : params.sideOverride);
float sign = (i == 1 ? -1 : 1) * params.sideMultiplier;
Tmp.v1.set((x + mx) * sign, y + my).rotateRadExact((params.rotation - 90) * Mathf.degRad);
childParam.set(params.warmup, params.reload, params.smoothReload, params.heat, params.recoil, params.charge, params.x + Tmp.v1.x, params.y + Tmp.v1.y, i * sign + mr * sign + params.rotation);
childParam.sideMultiplier = params.sideMultiplier;
childParam.life = params.life;
childParam.sideOverride = i;
for(var child : children){
child.draw(childParam);
}
}
}
Draw.scl(preXscl, preYscl);
}
@Override
public void load(String name){
String realName = this.name == null ? name + suffix : this.name;
if(drawRegion){
if(mirror && turretShading){
regions = new TextureRegion[]{
Core.atlas.find(realName + "-r"),
Core.atlas.find(realName + "-l")
};
outlines = new TextureRegion[]{
Core.atlas.find(realName + "-r-outline"),
Core.atlas.find(realName + "-l-outline")
};
}else{
regions = new TextureRegion[]{Core.atlas.find(realName)};
outlines = new TextureRegion[]{Core.atlas.find(realName + "-outline")};
}
}
heat = Core.atlas.find(realName + "-heat");
for(var child : children){
child.turretShading = turretShading;
child.load(name);
}
}
@Override
public void getOutlines(Seq<TextureRegion> out){
if(outline && drawRegion){
out.addAll(regions);
}
for(var child : children){
child.getOutlines(out);
}
}
}