195 lines
6.5 KiB
Java
195 lines
6.5 KiB
Java
package mindustry.editor;
|
|
|
|
import arc.*;
|
|
import arc.graphics.*;
|
|
import arc.graphics.g2d.*;
|
|
import arc.math.*;
|
|
import arc.struct.*;
|
|
import arc.util.*;
|
|
import mindustry.content.*;
|
|
import mindustry.game.*;
|
|
import mindustry.graphics.*;
|
|
import mindustry.world.*;
|
|
import mindustry.world.blocks.environment.*;
|
|
|
|
import static mindustry.Vars.*;
|
|
|
|
public class MapRenderer implements Disposable{
|
|
private static final int chunkSize = 64;
|
|
private IndexedRenderer[][] chunks;
|
|
private IntSet updates = new IntSet();
|
|
private IntSet delayedUpdates = new IntSet();
|
|
private TextureRegion clearEditor;
|
|
private int width, height;
|
|
|
|
public void resize(int width, int height){
|
|
updates.clear();
|
|
delayedUpdates.clear();
|
|
if(chunks != null){
|
|
for(int x = 0; x < chunks.length; x++){
|
|
for(int y = 0; y < chunks[0].length; y++){
|
|
chunks[x][y].dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
chunks = new IndexedRenderer[(int)Math.ceil((float)width / chunkSize)][(int)Math.ceil((float)height / chunkSize)];
|
|
|
|
for(int x = 0; x < chunks.length; x++){
|
|
for(int y = 0; y < chunks[0].length; y++){
|
|
chunks[x][y] = new IndexedRenderer(chunkSize * chunkSize * 2);
|
|
}
|
|
}
|
|
this.width = width;
|
|
this.height = height;
|
|
updateAll();
|
|
}
|
|
|
|
public void draw(float tx, float ty, float tw, float th){
|
|
Draw.flush();
|
|
clearEditor = Core.atlas.find("clear-editor");
|
|
|
|
updates.each(i -> render(i % width, i / width));
|
|
updates.clear();
|
|
|
|
updates.addAll(delayedUpdates);
|
|
delayedUpdates.clear();
|
|
|
|
//????
|
|
if(chunks == null){
|
|
return;
|
|
}
|
|
|
|
var texture = Core.atlas.find("clear-editor").texture;
|
|
|
|
for(int x = 0; x < chunks.length; x++){
|
|
for(int y = 0; y < chunks[0].length; y++){
|
|
IndexedRenderer mesh = chunks[x][y];
|
|
|
|
if(mesh == null){
|
|
continue;
|
|
}
|
|
|
|
mesh.getTransformMatrix().setToTranslation(tx, ty).scale(tw / (width * tilesize), th / (height * tilesize));
|
|
mesh.setProjectionMatrix(Draw.proj());
|
|
|
|
mesh.render(texture);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void updatePoint(int x, int y){
|
|
updates.add(x + y * width);
|
|
}
|
|
|
|
public void updateAll(){
|
|
clearEditor = Core.atlas.find("clear-editor");
|
|
for(int x = 0; x < width; x++){
|
|
for(int y = 0; y < height; y++){
|
|
render(x, y);
|
|
}
|
|
}
|
|
}
|
|
|
|
private TextureRegion getIcon(Block wall, int index){
|
|
return !wall.editorIcon().found() ?
|
|
clearEditor : wall.variants > 0 ?
|
|
wall.editorVariantRegions()[Mathf.randomSeed(index, 0, wall.editorVariantRegions().length - 1)] :
|
|
wall.editorIcon();
|
|
}
|
|
|
|
private void render(int wx, int wy){
|
|
int x = wx / chunkSize, y = wy / chunkSize;
|
|
if(x >= chunks.length || y >= chunks[0].length) return;
|
|
IndexedRenderer mesh = chunks[x][y];
|
|
Tile tile = editor.tiles().getn(wx, wy);
|
|
|
|
Team team = tile.team();
|
|
Floor floor = tile.floor();
|
|
Floor overlay = tile.overlay();
|
|
Block wall = tile.block();
|
|
|
|
TextureRegion region;
|
|
|
|
int idxWall = (wx % chunkSize) + (wy % chunkSize) * chunkSize;
|
|
int idxDecal = (wx % chunkSize) + (wy % chunkSize) * chunkSize + chunkSize * chunkSize;
|
|
boolean center = tile.isCenter();
|
|
boolean useSyntheticWall = wall.synthetic() || overlay.wallOre;
|
|
|
|
//draw synthetic wall or floor OR standard wall if wall ore
|
|
if(wall != Blocks.air && useSyntheticWall){
|
|
region = !center ? clearEditor : getIcon(wall, idxWall);
|
|
|
|
float width = region.width * region.scl(), height = region.height * region.scl(), ox = wall.offset + (tilesize - width) / 2f, oy = wall.offset + (tilesize - height) / 2f;
|
|
|
|
//force fit to tile
|
|
if(overlay.wallOre && !wall.synthetic()){
|
|
width = height = tilesize;
|
|
ox = oy = 0f;
|
|
}
|
|
|
|
mesh.draw(idxWall, region,
|
|
wx * tilesize + ox,
|
|
wy * tilesize + oy,
|
|
width, height,
|
|
tile.build == null || !wall.rotate ? 0 : tile.build.rotdeg());
|
|
}else{
|
|
region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)];
|
|
|
|
mesh.draw(idxWall, region, wx * tilesize, wy * tilesize, 8, 8);
|
|
}
|
|
|
|
float offsetX = -((wall.size + 1) / 3) * tilesize, offsetY = -((wall.size + 1) / 3) * tilesize;
|
|
|
|
//draw non-synthetic wall or ore
|
|
if((wall.update || wall.destructible) && center){
|
|
mesh.setColor(team.color);
|
|
region = Core.atlas.find("block-border-editor");
|
|
if(wall.size == 2){
|
|
offsetX += tilesize;
|
|
offsetY += tilesize;
|
|
}
|
|
}else if(!useSyntheticWall && wall != Blocks.air && center){
|
|
region = getIcon(wall, idxWall);
|
|
|
|
if(wall == Blocks.cliff){
|
|
mesh.setColor(Tmp.c1.set(floor.mapColor).mul(1.6f));
|
|
region = ((Cliff)Blocks.cliff).editorCliffs[tile.data & 0xff];
|
|
}
|
|
|
|
offsetX = tilesize / 2f - region.width * region.scl() / 2f;
|
|
offsetY = tilesize / 2f - region.height * region.scl() / 2f;
|
|
}else if((wall == Blocks.air || overlay.wallOre) && !overlay.isAir()){
|
|
if(floor.isLiquid){
|
|
mesh.setColor(Tmp.c1.set(1f, 1f, 1f, floor.overlayAlpha));
|
|
}
|
|
region = overlay.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, tile.overlay().editorVariantRegions().length - 1)];
|
|
}else{
|
|
region = clearEditor;
|
|
}
|
|
|
|
float width = region.width * region.scl(), height = region.height * region.scl();
|
|
if(!wall.synthetic() && wall != Blocks.air && !wall.isMultiblock()){
|
|
offsetX = offsetY = 0f;
|
|
width = height = tilesize;
|
|
}
|
|
|
|
mesh.draw(idxDecal, region, wx * tilesize + offsetX, wy * tilesize + offsetY, width, height);
|
|
mesh.setColor(Color.white);
|
|
}
|
|
|
|
@Override
|
|
public void dispose(){
|
|
if(chunks == null){
|
|
return;
|
|
}
|
|
for(int x = 0; x < chunks.length; x++){
|
|
for(int y = 0; y < chunks[0].length; y++){
|
|
if(chunks[x][y] != null){
|
|
chunks[x][y].dispose();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|