diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 63a3e099d4..72a00fc860 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -270,6 +270,7 @@ setting.multithread.name=Multithreading setting.fps.name=Show FPS setting.vsync.name=VSync setting.lasers.name=Show Power Lasers +setting.previewopacity.name = Placing Preview Opacity setting.healthbars.name=Show Entity Health bars setting.pixelate.name=Pixelate Screen setting.musicvol.name=Music Volume diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index e53ffacd1b..84e3cf8b17 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -12,12 +12,16 @@ import io.anuke.mindustry.world.Layer; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.types.StaticBlock; +import io.anuke.mindustry.world.blocks.types.defense.Turret; +import io.anuke.mindustry.world.blocks.types.production.Drill; +import io.anuke.mindustry.world.blocks.types.production.Pump; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.graphics.CacheBatch; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; +import io.anuke.ucore.core.*; import java.util.Arrays; @@ -25,259 +29,297 @@ import static io.anuke.mindustry.Vars.*; import static io.anuke.ucore.core.Core.camera; public class BlockRenderer{ - private final static int chunksize = 32; - private final static int initialRequests = 32*32; - - private int[][][] cache; - private CacheBatch cbatch; - - private Array requests = new Array(initialRequests); - private int requestidx = 0; - private int iterateidx = 0; - - public BlockRenderer(){ - for(int i = 0; i < requests.size; i ++){ - requests.set(i, new BlockRequest()); - } - } - - private class BlockRequest implements Comparable{ - Tile tile; - Layer layer; - - @Override - public int compareTo(BlockRequest other){ - return layer.compareTo(other.layer); - } - - @Override - public String toString(){ - return tile.block().name + ":" + layer.toString(); - } - } - - /**Process all blocks to draw, simultaneously drawing block shadows and static blocks.*/ - public void processBlocks(){ - requestidx = 0; - - int crangex = (int) (camera.viewportWidth / (chunksize * tilesize)) + 1; - int crangey = (int) (camera.viewportHeight / (chunksize * tilesize)) + 1; - - int rangex = (int) (camera.viewportWidth * camera.zoom / tilesize / 2)+2; - int rangey = (int) (camera.viewportHeight * camera.zoom / tilesize / 2)+2; - - int expandr = 3; - - Graphics.surface(renderer.shadowSurface); - - for(int x = -rangex - expandr; x <= rangex + expandr; x++){ - for(int y = -rangey - expandr; y <= rangey + expandr; y++){ - int worldx = Mathf.scl(camera.position.x, tilesize) + x; - int worldy = Mathf.scl(camera.position.y, tilesize) + y; - boolean expanded = (x < -rangex || x > rangex || y < -rangey || y > rangey); - - Tile tile = world.tile(worldx, worldy); - - if(tile != null){ - Block block = tile.block(); - - if(!expanded && block != Blocks.air && world.isAccessible(worldx, worldy)){ - block.drawShadow(tile); - } - - if(!(block instanceof StaticBlock)){ - if(block == Blocks.air){ - if(!state.is(State.paused)) tile.floor().update(tile); - }else{ - - if(!expanded){ - addRequest(tile, Layer.block); - } - - if(block.expanded || !expanded){ - if(block.layer != null && block.isLayer(tile)){ - addRequest(tile, block.layer); - } - - if(block.layer2 != null && block.isLayer2(tile)){ - addRequest(tile, block.layer2); - } - } - } - } - } - } - } - - Draw.color(0, 0, 0, 0.15f); - Graphics.flushSurface(); - Draw.color(); - - Graphics.end(); - drawCache(1, crangex, crangey); - Graphics.begin(); - - Arrays.sort(requests.items, 0, requestidx); - iterateidx = 0; - } - - public int getRequests(){ - return requestidx; - } - - public void drawBlocks(boolean top){ - Layer stopAt = top ? Layer.laser : Layer.overlay; - - for(; iterateidx < requestidx; iterateidx ++){ - - if(iterateidx < requests.size - 1 && requests.get(iterateidx).layer.ordinal() > stopAt.ordinal()){ - break; - } - - BlockRequest req = requests.get(iterateidx); - Block block = req.tile.block(); - - if(req.layer == Layer.block){ - block.draw(req.tile); - }else if(req.layer == block.layer){ - block.drawLayer(req.tile); - }else if(req.layer == block.layer2){ - block.drawLayer2(req.tile); - } - } - } - - private void addRequest(Tile tile, Layer layer){ - if(requestidx >= requests.size){ - requests.add(new BlockRequest()); - } - BlockRequest r = requests.get(requestidx); - if(r == null){ - requests.set(requestidx, r = new BlockRequest()); - } - r.tile = tile; - r.layer = layer; - requestidx ++; - } - - public void drawFloor(){ - int chunksx = world.width() / chunksize, chunksy = world.height() / chunksize; - - //render the entire map - if(cache == null || cache.length != chunksx || cache[0].length != chunksy){ - cache = new int[chunksx][chunksy][2]; - - for(int x = 0; x < chunksx; x++){ - for(int y = 0; y < chunksy; y++){ - cacheChunk(x, y, true); - cacheChunk(x, y, false); - } - } - } - - OrthographicCamera camera = Core.camera; - - if(Graphics.drawing()) Graphics.end(); - - int crangex = (int)(camera.viewportWidth * camera.zoom / (chunksize * tilesize))+1; - int crangey = (int)(camera.viewportHeight * camera.zoom / (chunksize * tilesize))+1; - - drawCache(0, crangex, crangey); - - Graphics.begin(); - - Draw.reset(); - - if(showPaths && debug){ - drawPaths(); - } - - if(debug && debugChunks){ - Draw.color(Color.YELLOW); - Lines.stroke(1f); - for(int x = -crangex; x <= crangex; x++){ - for(int y = -crangey; y <= crangey; y++){ - int worldx = Mathf.scl(camera.position.x, chunksize * tilesize) + x; - int worldy = Mathf.scl(camera.position.y, chunksize * tilesize) + y; - - if(!Mathf.inBounds(worldx, worldy, cache)) - continue; - Lines.rect(worldx * chunksize * tilesize, worldy * chunksize * tilesize, chunksize * tilesize, chunksize * tilesize); - } - } - Draw.reset(); - } - } - - void drawPaths(){ - Draw.color(Color.RED); - for(SpawnPoint point : world.getSpawns()){ - if(point.pathTiles != null){ - for(int i = 1; i < point.pathTiles.length; i ++){ - Lines.line(point.pathTiles[i-1].worldx(), point.pathTiles[i-1].worldy(), - point.pathTiles[i].worldx(), point.pathTiles[i].worldy()); - Lines.circle(point.pathTiles[i-1].worldx(), point.pathTiles[i-1].worldy(), 6f); - } - } - } - Draw.reset(); - } - - - void drawCache(int layer, int crangex, int crangey){ - Gdx.gl.glEnable(GL20.GL_BLEND); - - cbatch.setProjectionMatrix(Core.camera.combined); - cbatch.beginDraw(); - for(int x = -crangex; x <= crangex; x++){ - for(int y = -crangey; y <= crangey; y++){ - int worldx = Mathf.scl(camera.position.x, chunksize * tilesize) + x; - int worldy = Mathf.scl(camera.position.y, chunksize * tilesize) + y; - - if(!Mathf.inBounds(worldx, worldy, cache)) - continue; - - cbatch.drawCache(cache[worldx][worldy][layer]); - } - } - - cbatch.endDraw(); - } - - void cacheChunk(int cx, int cy, boolean floor){ - if(cbatch == null){ - createBatch(); - } - - cbatch.begin(); - Graphics.useBatch(cbatch); - - for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){ - for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++){ - Tile tile = world.tile(tilex, tiley); - if(tile == null) continue; - if(floor){ - if(!(tile.block() instanceof StaticBlock)){ - tile.floor().draw(tile); - } - }else if(tile.block() instanceof StaticBlock){ - tile.block().draw(tile); - } - } - } - Graphics.popBatch(); - cbatch.end(); - cache[cx][cy][floor ? 0 : 1] = cbatch.getLastCache(); - } - - public void clearTiles(){ - cache = null; - createBatch(); - } - - private void createBatch(){ - if(cbatch != null) - cbatch.dispose(); - cbatch = new CacheBatch(world.width() * world.height() * 4); - } -} + private final static int chunksize = 32; + private final static int initialRequests = 32*32; + + private int[][][] cache; + private CacheBatch cbatch; + + private Array requests = new Array(initialRequests); + private int requestidx = 0; + private int iterateidx = 0; + + public BlockRenderer(){ + for(int i = 0; i < requests.size; i ++){ + requests.set(i, new BlockRequest()); + } + } + + private class BlockRequest implements Comparable{ + Tile tile; + Layer layer; + + @Override + public int compareTo(BlockRequest other){ + return layer.compareTo(other.layer); + } + + @Override + public String toString(){ + return tile.block().name + ":" + layer.toString(); + } + } + + /**Process all blocks to draw, simultaneously drawing block shadows and static blocks.*/ + public void processBlocks(){ + requestidx = 0; + + int crangex = (int) (camera.viewportWidth / (chunksize * tilesize)) + 1; + int crangey = (int) (camera.viewportHeight / (chunksize * tilesize)) + 1; + + int rangex = (int) (camera.viewportWidth * camera.zoom / tilesize / 2)+2; + int rangey = (int) (camera.viewportHeight * camera.zoom / tilesize / 2)+2; + + int expandr = 3; + + Graphics.surface(renderer.shadowSurface); + + for(int x = -rangex - expandr; x <= rangex + expandr; x++){ + for(int y = -rangey - expandr; y <= rangey + expandr; y++){ + int worldx = Mathf.scl(camera.position.x, tilesize) + x; + int worldy = Mathf.scl(camera.position.y, tilesize) + y; + boolean expanded = (x < -rangex || x > rangex || y < -rangey || y > rangey); + + Tile tile = world.tile(worldx, worldy); + + if(tile != null){ + Block block = tile.block(); + + if(!expanded && block != Blocks.air && world.isAccessible(worldx, worldy)){ + block.drawShadow(tile); + } + + if(!(block instanceof StaticBlock)){ + if(block == Blocks.air){ + if(!state.is(State.paused)) tile.floor().update(tile); + }else{ + + if(!expanded){ + addRequest(tile, Layer.block); + } + + if(block.expanded || !expanded){ + if(block.layer != null && block.isLayer(tile)){ + addRequest(tile, block.layer); + } + + if(block.layer2 != null && block.isLayer2(tile)){ + addRequest(tile, block.layer2); + } + } + } + } + } + } + } + + Draw.color(0, 0, 0, 0.15f); + Graphics.flushSurface(); + Draw.color(); + + Graphics.end(); + drawCache(1, crangex, crangey); + Graphics.begin(); + + Arrays.sort(requests.items, 0, requestidx); + iterateidx = 0; + } + + public int getRequests(){ + return requestidx; + } + + public void drawBlocks(boolean top){ + Layer stopAt = top ? Layer.laser : Layer.overlay; + + for(; iterateidx < requestidx; iterateidx ++){ + + if(iterateidx < requests.size - 1 && requests.get(iterateidx).layer.ordinal() > stopAt.ordinal()){ + break; + } + + BlockRequest req = requests.get(iterateidx); + Block block = req.tile.block(); + + if(req.layer == Layer.block){ + block.draw(req.tile); + }else if(req.layer == block.layer){ + block.drawLayer(req.tile); + }else if(req.layer == block.layer2){ + block.drawLayer2(req.tile); + } + } + } + + private void addRequest(Tile tile, Layer layer){ + if(requestidx >= requests.size){ + requests.add(new BlockRequest()); + } + BlockRequest r = requests.get(requestidx); + if(r == null){ + requests.set(requestidx, r = new BlockRequest()); + } + r.tile = tile; + r.layer = layer; + requestidx ++; + } + + public void drawFloor(){ + int chunksx = world.width() / chunksize, chunksy = world.height() / chunksize; + + //render the entire map + if(cache == null || cache.length != chunksx || cache[0].length != chunksy){ + cache = new int[chunksx][chunksy][2]; + + for(int x = 0; x < chunksx; x++){ + for(int y = 0; y < chunksy; y++){ + cacheChunk(x, y, true); + cacheChunk(x, y, false); + } + } + } + + OrthographicCamera camera = Core.camera; + + if(Graphics.drawing()) Graphics.end(); + + int crangex = (int)(camera.viewportWidth * camera.zoom / (chunksize * tilesize))+1; + int crangey = (int)(camera.viewportHeight * camera.zoom / (chunksize * tilesize))+1; + + drawCache(0, crangex, crangey); + + Graphics.begin(); + + Draw.reset(); + + if(showPaths && debug){ + drawPaths(); + } + + if(debug && debugChunks){ + Draw.color(Color.YELLOW); + Lines.stroke(1f); + for(int x = -crangex; x <= crangex; x++){ + for(int y = -crangey; y <= crangey; y++){ + int worldx = Mathf.scl(camera.position.x, chunksize * tilesize) + x; + int worldy = Mathf.scl(camera.position.y, chunksize * tilesize) + y; + + if(!Mathf.inBounds(worldx, worldy, cache)) + continue; + Lines.rect(worldx * chunksize * tilesize, worldy * chunksize * tilesize, chunksize * tilesize, chunksize * tilesize); + } + } + Draw.reset(); + } + } + + void drawPaths(){ + Draw.color(Color.RED); + for(SpawnPoint point : world.getSpawns()){ + if(point.pathTiles != null){ + for(int i = 1; i < point.pathTiles.length; i ++){ + Lines.line(point.pathTiles[i-1].worldx(), point.pathTiles[i-1].worldy(), + point.pathTiles[i].worldx(), point.pathTiles[i].worldy()); + Lines.circle(point.pathTiles[i-1].worldx(), point.pathTiles[i-1].worldy(), 6f); + } + } + } + Draw.reset(); + } + + + void drawCache(int layer, int crangex, int crangey){ + Gdx.gl.glEnable(GL20.GL_BLEND); + + cbatch.setProjectionMatrix(Core.camera.combined); + cbatch.beginDraw(); + for(int x = -crangex; x <= crangex; x++){ + for(int y = -crangey; y <= crangey; y++){ + int worldx = Mathf.scl(camera.position.x, chunksize * tilesize) + x; + int worldy = Mathf.scl(camera.position.y, chunksize * tilesize) + y; + + if(!Mathf.inBounds(worldx, worldy, cache)) + continue; + + cbatch.drawCache(cache[worldx][worldy][layer]); + } + } + + cbatch.endDraw(); + } + + void cacheChunk(int cx, int cy, boolean floor){ + if(cbatch == null){ + createBatch(); + } + + cbatch.begin(); + Graphics.useBatch(cbatch); + + for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){ + for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++){ + Tile tile = world.tile(tilex, tiley); + if(tile == null) continue; + if(floor){ + if(!(tile.block() instanceof StaticBlock)){ + tile.floor().draw(tile); + } + }else if(tile.block() instanceof StaticBlock){ + tile.block().draw(tile); + } + } + } + Graphics.popBatch(); + cbatch.end(); + cache[cx][cy][floor ? 0 : 1] = cbatch.getLastCache(); + } + + public void clearTiles(){ + cache = null; + createBatch(); + } + + private void createBatch(){ + if(cbatch != null) + cbatch.dispose(); + cbatch = new CacheBatch(world.width() * world.height() * 4); + } + + public void drawPreview(Block block, float drawx, float drawy, float rotation, float opacity) { + Draw.reset(); + Draw.alpha(opacity); + Draw.rect(block.name(), drawx, drawy, rotation); + } + + public void handlePreview(Block block, float rotation, float drawx, float drawy, int tilex, int tiley) { + + if(control.input().recipe != null && state.inventory.hasItems(control.input().recipe.requirements) + && control.input().validPlace(tilex, tiley, block) && (android || control.input().cursorNear())) { + + float opacity = (float)Settings.getInt("previewopacity")/100f; + + if(block.isMultiblock()) { + if((tiley - control.input().getBlockY()) % block.height != 0 + || (tilex - control.input().getBlockX()) % block.width != 0) return; + } + + if(block instanceof Turret) { + Draw.alpha(opacity); + if (block.isMultiblock()) { + Draw.rect("block-" + block.width + "x" + block.height, drawx, drawy); + } else { + Draw.rect("block", drawx, drawy); + } + } + + drawPreview(block, drawx, drawy, rotation, opacity); + + Tile tile = world.tile(tilex, tiley); + if((block instanceof Drill || block instanceof Pump) && block.isLayer(tile)) { + block.drawLayer(tile); + } + + Draw.reset(); + } + } +} \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/input/PlaceMode.java b/core/src/io/anuke/mindustry/input/PlaceMode.java index 0ac5439057..7c96d2dea2 100644 --- a/core/src/io/anuke/mindustry/input/PlaceMode.java +++ b/core/src/io/anuke/mindustry/input/PlaceMode.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.ui.fragments.ToolFragment; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.types.production.Drill; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; @@ -17,373 +18,379 @@ import io.anuke.ucore.util.Translator; import static io.anuke.mindustry.Vars.*; public enum PlaceMode{ - cursor{ - { - shown = true; - lockCamera = true; - pan = true; - } - - public void draw(int tilex, int tiley, int endx, int endy){ - float x = tilex * tilesize; - float y = tiley * tilesize; - - boolean valid = control.input().validPlace(tilex, tiley, control.input().recipe.result) && (android || control.input().cursorNear()); - - Vector2 offset = control.input().recipe.result.getPlaceOffset(); - - float si = MathUtils.sin(Timers.time() / 6f) + 1.5f; - - Draw.color(valid ? Colors.get("place") : Colors.get("placeInvalid")); - Lines.stroke(2f); - Lines.crect(x + offset.x, y + offset.y, tilesize * control.input().recipe.result.width + si, - tilesize * control.input().recipe.result.height + si); - - control.input().recipe.result.drawPlace(tilex, tiley, control.input().rotation, valid); - Lines.stroke(2f); - - if(control.input().recipe.result.rotate){ - Draw.color(Colors.get("placeRotate")); - tr.trns(control.input().rotation * 90, 7, 0); - Lines.line(x, y, x + tr.x, y + tr.y); - } - } - - public void tapped(int tilex, int tiley){ - control.input().tryPlaceBlock(tilex, tiley, true); - } - }, - touch{ - { - shown = true; - lockCamera = false; - showRotate = true; - showCancel = true; - } - - public void tapped(int x, int y){ - control.input().tryPlaceBlock(x, y, true); - } - }, - none{ - { - delete = true; - shown = true; - both = true; - } - }, - holdDelete{ - { - delete = true; - shown = true; - both = true; - } - - public void draw(int tilex, int tiley, int endx, int endy){ - Tile tile = world.tile(tilex, tiley); - - if(tile != null && control.input().validBreak(tilex, tiley)){ - if(tile.isLinked()) - tile = tile.getLinked(); - float fin = control.input().breaktime / tile.getBreakTime(); - - if(android && control.input().breaktime > 0){ - Draw.color(Colors.get("breakStart"), Colors.get("break"), fin); - Lines.poly(tile.drawx(), tile.drawy(), 25, 4 + (1f - fin) * 26); - } - Draw.reset(); - } - } - }, - touchDelete{ - { - shown = true; - lockCamera = false; - showRotate = true; - showCancel = true; - delete = true; - } - - public void tapped(int x, int y){ - control.input().tryDeleteBlock(x, y, true); - } - }, - areaDelete{ - int maxlen = 20; - int tilex; - int tiley; - int endx; - int endy; - - { - shown = true; - lockCamera = true; - delete = true; - } - - public void draw(int tilex, int tiley, int endx, int endy){ - float t = tilesize; - - process(tilex, tiley, endx, endy); - - tilex = this.tilex; tiley = this.tiley; - endx = this.endx; endy = this.endy; - float x = this.tilex * t, y = this.tiley * t, - x2 = this.endx * t, y2 = this.endy * t; - - if(x2 >= x){ - x -= t/2; - x2 += t/2; - } - - if(y2 >= y){ - y -= t/2; - y2 += t/2; - } - - Draw.color(Colors.get("break")); - Lines.stroke(1f); - for(int cx = tilex; cx <= endx; cx ++){ - for(int cy = tiley; cy <= endy; cy ++){ - Tile tile = world.tile(cx, cy); - if(tile != null && tile.getLinked() != null) - tile = tile.getLinked(); - if(tile != null && control.input().validBreak(tile.x, tile.y)){ - Lines.crect(tile.drawx(), tile.drawy(), - tile.block().width * t, tile.block().height * t); - } - } - } - - Lines.stroke(2f); - Draw.color(control.input().cursorNear() ? Colors.get("break") : Colors.get("breakInvalid")); - Lines.rect(x, y, x2 - x, y2 - y); - Draw.alpha(0.3f); - Draw.crect("blank", x, y, x2 - x, y2 - y); - Draw.reset(); - } - - public void released(int tilex, int tiley, int endx, int endy){ - process(tilex, tiley, endx, endy); - tilex = this.tilex; tiley = this.tiley; - endx = this.endx; endy = this.endy; - - if(android){ - ToolFragment t = ui.toolfrag; - if(!t.confirming || t.px != tilex || t.py != tiley || t.px2 != endx || t.py2 != endy) { - t.confirming = true; - t.px = tilex; - t.py = tiley; - t.px2 = endx; - t.py2 = endy; - return; - } - } - - boolean first = true; - - for(int cx = tilex; cx <= endx; cx ++){ - for(int cy = tiley; cy <= endy; cy ++){ - if(control.input().tryDeleteBlock(cx, cy, first)){ - first = false; - } - } - } - } - - void process(int tilex, int tiley, int endx, int endy){ - - if(Math.abs(endx - tilex) > maxlen){ - endx = Mathf.sign(endx - tilex) * maxlen + tilex; - } - - if(Math.abs(endy - tiley) > maxlen){ - endy = Mathf.sign(endy - tiley) * maxlen + tiley; - } - - if(endx < tilex){ - int t = endx; - endx = tilex; - tilex = t; - } - if(endy < tiley){ - int t = endy; - endy = tiley; - tiley = t; - } - - this.endx = endx; - this.endy = endy; - this.tilex = tilex; - this.tiley = tiley; - } - }, - hold{ - int maxlen = 20; - int tilex; - int tiley; - int endx; - int endy; - int rotation; - - { - lockCamera = true; - shown = true; - showCancel = true; - showRotate = true; - } - - public void draw(int tilex, int tiley, int endx, int endy){ - if(android && !Gdx.input.isTouched(0) && !control.showCursor()){ - return; - } - - float t = tilesize; - Block block = control.input().recipe.result; - Vector2 offset = block.getPlaceOffset(); - - process(tilex, tiley, endx, endy); - int tx = tilex, ty = tiley, ex = endx, ey = endy; - tilex = this.tilex; tiley = this.tiley; - endx = this.endx; endy = this.endy; - float x = this.tilex * t, y = this.tiley * t, - x2 = this.endx * t, y2 = this.endy * t; - - if(x2 >= x){ - x -= block.width * t/2; - x2 += block.width * t/2; - } - - if(y2 >= y){ - y -= block.height * t/2; - y2 += block.height * t/2; - } - - x += offset.x; - y += offset.y; - x2 += offset.x; - y2 += offset.y; - - if(tilex == endx && tiley == endy){ - cursor.draw(tilex, tiley, endx, endy); - }else{ - Lines.stroke(2f); - Draw.color(control.input().cursorNear() ? Colors.get("place") : Colors.get("placeInvalid")); - Lines.rect(x, y, x2 - x, y2 - y); - Draw.alpha(0.3f); - Draw.crect("blank", x, y, x2 - x, y2 - y); - - Draw.color(Colors.get("placeInvalid")); - - int amount = 1; - for(int cx = 0; cx <= Math.abs(endx - tilex); cx ++){ - for(int cy = 0; cy <= Math.abs(endy - tiley); cy ++){ - int px = tx + cx * Mathf.sign(ex - tx), - py = ty + cy * Mathf.sign(ey - ty); - - if(!control.input().validPlace(px, py, control.input().recipe.result) - || !state.inventory.hasItems(control.input().recipe.requirements, amount)){ - Lines.crect(px * t + offset.x, py * t + offset.y, t*block.width, t*block.height); - } - amount ++; - } - } - - if(control.input().recipe.result.rotate){ - float cx = tx * t, cy = ty * t; - Draw.color(Colors.get("placeRotate")); - tr.trns(rotation * 90, 7, 0); - Lines.line(cx, cy, cx + tr.x, cy + tr.y); - } - Draw.reset(); - } - } - - public void released(int tilex, int tiley, int endx, int endy){ - process(tilex, tiley, endx, endy); - - control.input().rotation = this.rotation; - - boolean first = true; - for(int x = 0; x <= Math.abs(this.endx - this.tilex); x ++){ - for(int y = 0; y <= Math.abs(this.endy - this.tiley); y ++){ - if(control.input().tryPlaceBlock( - tilex + x * Mathf.sign(endx - tilex), - tiley + y * Mathf.sign(endy - tiley), first)){ - first = false; - } - - } - } - } - - void process(int tilex, int tiley, int endx, int endy){ - if(Math.abs(tilex - endx) > Math.abs(tiley - endy)){ - endy = tiley; - }else{ - endx = tilex; - } - - if(Math.abs(endx - tilex) > maxlen){ - endx = Mathf.sign(endx - tilex) * maxlen + tilex; - } - - if(Math.abs(endy - tiley) > maxlen){ - endy = Mathf.sign(endy - tiley) * maxlen + tiley; - } - - if(endx > tilex) - rotation = 0; - else if(endx < tilex) - rotation = 2; - else if(endy > tiley) - rotation = 1; - else if(endy < tiley) - rotation = 3; - else - rotation = control.input().rotation; - - if(endx < tilex){ - int t = endx; - endx = tilex; - tilex = t; - } - if(endy < tiley){ - int t = endy; - endy = tiley; - tiley = t; - } - - this.endx = endx; - this.endy = endy; - this.tilex = tilex; - this.tiley = tiley; - } - }; - public boolean lockCamera; - public boolean pan = false; - public boolean shown = false; - public boolean showRotate; - public boolean showCancel; - public boolean delete = false; - public boolean both = false; - - private static final Translator tr = new Translator(); - - public void draw(int tilex, int tiley, int endx, int endy){ - - } - - public void released(int tilex, int tiley, int endx, int endy){ - - } - - public void tapped(int x, int y){ - - } - - @Override - public String toString(){ - return Bundles.get("placemode."+name().toLowerCase()+".name"); - } -} + cursor{ + { + shown = true; + lockCamera = true; + pan = true; + } + + public void draw(int tilex, int tiley, int endx, int endy){ + float x = tilex * tilesize; + float y = tiley * tilesize; + + boolean valid = control.input().validPlace(tilex, tiley, control.input().recipe.result) && (android || control.input().cursorNear()); + + Vector2 offset = control.input().recipe.result.getPlaceOffset(); + + float si = MathUtils.sin(Timers.time() / 6f) + 1.5f; + + Draw.color(valid ? Colors.get("place") : Colors.get("placeInvalid")); + Lines.stroke(2f); + Lines.crect(x + offset.x, y + offset.y, tilesize * control.input().recipe.result.width + si, + tilesize * control.input().recipe.result.height + si); + + control.input().recipe.result.drawPlace(tilex, tiley, control.input().rotation, valid); + + renderer.getBlocks().handlePreview(control.input().recipe.result, control.input().recipe.result.rotate ? control.input().rotation * 90 : 0f, x + offset.x, y + offset.y, tilex, tiley); + + if(control.input().recipe.result.rotate){ + + Draw.color(Colors.get("placeRotate")); + tr.trns(control.input().rotation * 90, 7, 0); + Lines.stroke(2f); + Lines.line(x, y, x + tr.x, y + tr.y); + } + } + + public void tapped(int tilex, int tiley){ + control.input().tryPlaceBlock(tilex, tiley, true); + } + }, + touch{ + { + shown = true; + lockCamera = false; + showRotate = true; + showCancel = true; + } + + public void tapped(int x, int y){ + control.input().tryPlaceBlock(x, y, true); + } + }, + none{ + { + delete = true; + shown = true; + both = true; + } + }, + holdDelete{ + { + delete = true; + shown = true; + both = true; + } + + public void draw(int tilex, int tiley, int endx, int endy){ + Tile tile = world.tile(tilex, tiley); + + if(tile != null && control.input().validBreak(tilex, tiley)){ + if(tile.isLinked()) + tile = tile.getLinked(); + float fin = control.input().breaktime / tile.getBreakTime(); + + if(android && control.input().breaktime > 0){ + Draw.color(Colors.get("breakStart"), Colors.get("break"), fin); + Lines.poly(tile.drawx(), tile.drawy(), 25, 4 + (1f - fin) * 26); + } + Draw.reset(); + } + } + }, + touchDelete{ + { + shown = true; + lockCamera = false; + showRotate = true; + showCancel = true; + delete = true; + } + + public void tapped(int x, int y){ + control.input().tryDeleteBlock(x, y, true); + } + }, + areaDelete{ + int maxlen = 20; + int tilex; + int tiley; + int endx; + int endy; + + { + shown = true; + lockCamera = true; + delete = true; + } + + public void draw(int tilex, int tiley, int endx, int endy){ + float t = tilesize; + + process(tilex, tiley, endx, endy); + + tilex = this.tilex; tiley = this.tiley; + endx = this.endx; endy = this.endy; + float x = this.tilex * t, y = this.tiley * t, + x2 = this.endx * t, y2 = this.endy * t; + + if(x2 >= x){ + x -= t/2; + x2 += t/2; + } + + if(y2 >= y){ + y -= t/2; + y2 += t/2; + } + + Draw.color(Colors.get("break")); + Lines.stroke(1f); + for(int cx = tilex; cx <= endx; cx ++){ + for(int cy = tiley; cy <= endy; cy ++){ + Tile tile = world.tile(cx, cy); + if(tile != null && tile.getLinked() != null) + tile = tile.getLinked(); + if(tile != null && control.input().validBreak(tile.x, tile.y)){ + Lines.crect(tile.drawx(), tile.drawy(), + tile.block().width * t, tile.block().height * t); + } + } + } + + Lines.stroke(2f); + Draw.color(control.input().cursorNear() ? Colors.get("break") : Colors.get("breakInvalid")); + Lines.rect(x, y, x2 - x, y2 - y); + Draw.alpha(0.3f); + Draw.crect("blank", x, y, x2 - x, y2 - y); + Draw.reset(); + } + + public void released(int tilex, int tiley, int endx, int endy){ + process(tilex, tiley, endx, endy); + tilex = this.tilex; tiley = this.tiley; + endx = this.endx; endy = this.endy; + + if(android){ + ToolFragment t = ui.toolfrag; + if(!t.confirming || t.px != tilex || t.py != tiley || t.px2 != endx || t.py2 != endy) { + t.confirming = true; + t.px = tilex; + t.py = tiley; + t.px2 = endx; + t.py2 = endy; + return; + } + } + + boolean first = true; + + for(int cx = tilex; cx <= endx; cx ++){ + for(int cy = tiley; cy <= endy; cy ++){ + if(control.input().tryDeleteBlock(cx, cy, first)){ + first = false; + } + } + } + } + + void process(int tilex, int tiley, int endx, int endy){ + + if(Math.abs(endx - tilex) > maxlen){ + endx = Mathf.sign(endx - tilex) * maxlen + tilex; + } + + if(Math.abs(endy - tiley) > maxlen){ + endy = Mathf.sign(endy - tiley) * maxlen + tiley; + } + + if(endx < tilex){ + int t = endx; + endx = tilex; + tilex = t; + } + if(endy < tiley){ + int t = endy; + endy = tiley; + tiley = t; + } + + this.endx = endx; + this.endy = endy; + this.tilex = tilex; + this.tiley = tiley; + } + }, + hold{ + int maxlen = 20; + int tilex; + int tiley; + int endx; + int endy; + int rotation; + + { + lockCamera = true; + shown = true; + showCancel = true; + showRotate = true; + } + + public void draw(int tilex, int tiley, int endx, int endy){ + if(android && !Gdx.input.isTouched(0) && !control.showCursor()){ + return; + } + + float t = tilesize; + Block block = control.input().recipe.result; + Vector2 offset = block.getPlaceOffset(); + + process(tilex, tiley, endx, endy); + int tx = tilex, ty = tiley, ex = endx, ey = endy; + tilex = this.tilex; tiley = this.tiley; + endx = this.endx; endy = this.endy; + float x = this.tilex * t, y = this.tiley * t, + x2 = this.endx * t, y2 = this.endy * t; + + if(x2 >= x){ + x -= block.width * t/2; + x2 += block.width * t/2; + } + + if(y2 >= y){ + y -= block.height * t/2; + y2 += block.height * t/2; + } + + x += offset.x; + y += offset.y; + x2 += offset.x; + y2 += offset.y; + + if(tilex == endx && tiley == endy){ + cursor.draw(tilex, tiley, endx, endy); + }else{ + Lines.stroke(2f); + Draw.color(control.input().cursorNear() ? Colors.get("place") : Colors.get("placeInvalid")); + Lines.rect(x, y, x2 - x, y2 - y); + Draw.alpha(0.3f); + Draw.crect("blank", x, y, x2 - x, y2 - y); + + Draw.color(Colors.get("placeInvalid")); + + int amount = 1; + for(int cx = 0; cx <= Math.abs(endx - tilex); cx ++){ + for(int cy = 0; cy <= Math.abs(endy - tiley); cy ++){ + int px = tx + cx * Mathf.sign(ex - tx), + py = ty + cy * Mathf.sign(ey - ty); + + renderer.getBlocks().handlePreview(control.input().recipe.result, control.input().recipe.result.rotate ? rotation * 90 : 0f, px * t + offset.x, py * t + offset.y, px, py); + + if(!control.input().validPlace(px, py, control.input().recipe.result) + || !state.inventory.hasItems(control.input().recipe.requirements, amount)) + Lines.crect(px * t + offset.x, py * t + offset.y, t*block.width, t*block.height); + + amount ++; + } + } + + if(control.input().recipe.result.rotate){ + float cx = tx * t, cy = ty * t; + Lines.stroke(2f); + Draw.color(Colors.get("placeRotate")); + tr.trns(rotation * 90, 7, 0); + Lines.line(cx, cy, cx + tr.x, cy + tr.y); + } + Draw.reset(); + } + } + + public void released(int tilex, int tiley, int endx, int endy){ + process(tilex, tiley, endx, endy); + + control.input().rotation = this.rotation; + + boolean first = true; + for(int x = 0; x <= Math.abs(this.endx - this.tilex); x ++){ + for(int y = 0; y <= Math.abs(this.endy - this.tiley); y ++){ + if(control.input().tryPlaceBlock( + tilex + x * Mathf.sign(endx - tilex), + tiley + y * Mathf.sign(endy - tiley), first)){ + first = false; + } + + } + } + } + + void process(int tilex, int tiley, int endx, int endy){ + if(Math.abs(tilex - endx) > Math.abs(tiley - endy)){ + endy = tiley; + }else{ + endx = tilex; + } + + if(Math.abs(endx - tilex) > maxlen){ + endx = Mathf.sign(endx - tilex) * maxlen + tilex; + } + + if(Math.abs(endy - tiley) > maxlen){ + endy = Mathf.sign(endy - tiley) * maxlen + tiley; + } + + if(endx > tilex) + rotation = 0; + else if(endx < tilex) + rotation = 2; + else if(endy > tiley) + rotation = 1; + else if(endy < tiley) + rotation = 3; + else + rotation = control.input().rotation; + + if(endx < tilex){ + int t = endx; + endx = tilex; + tilex = t; + } + if(endy < tiley){ + int t = endy; + endy = tiley; + tiley = t; + } + + this.endx = endx; + this.endy = endy; + this.tilex = tilex; + this.tiley = tiley; + } + }; + public boolean lockCamera; + public boolean pan = false; + public boolean shown = false; + public boolean showRotate; + public boolean showCancel; + public boolean delete = false; + public boolean both = false; + + private static final Translator tr = new Translator(); + + public void draw(int tilex, int tiley, int endx, int endy){ + + } + + public void released(int tilex, int tiley, int endx, int endy){ + + } + + public void tapped(int x, int y){ + + } + + @Override + public String toString(){ + return Bundles.get("placemode."+name().toLowerCase()+".name"); + } +} \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index 6d2e79c610..895122b158 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -139,6 +139,7 @@ public class SettingsMenuDialog extends SettingsDialog{ graphics.checkPref("fps", false); graphics.checkPref("lasers", true); + graphics.sliderPref("previewopacity", 50, 0, 100, i -> i + "%"); graphics.checkPref("indicators", true); graphics.checkPref("healthbars", true); graphics.checkPref("pixelate", true, b -> {