diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index d5f3554507..0eb1ff2508 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -27,7 +27,7 @@ import java.util.Locale; public class Vars{ - public static final boolean testMobile = false; + public static final boolean testMobile = true; //shorthand for whether or not this is running on android or ios public static final boolean mobile = (Gdx.app.getType() == ApplicationType.Android) || Gdx.app.getType() == ApplicationType.iOS || testMobile; diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index c066a0f97f..98a4eb0bc0 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -16,10 +16,7 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Mech; -import io.anuke.mindustry.type.Upgrade; -import io.anuke.mindustry.type.Weapon; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.Floor; import io.anuke.ucore.core.*; @@ -275,8 +272,8 @@ public class Player extends Unit implements BlockBuilder { }else{ Draw.color(Palette.accent); Lines.stroke((1f-request.progress)); - Lines.poly(request.x * tilesize + request.recipe.result.getPlaceOffset().x, - request.y * tilesize + request.recipe.result.getPlaceOffset().y, + Lines.poly(request.x * tilesize + request.recipe.result.offset(), + request.y * tilesize + request.recipe.result.offset(), 4, request.recipe.result.size * tilesize /2f + Mathf.absin(Timers.time(), 3f, 1f)); } } @@ -313,6 +310,10 @@ public class Player extends Unit implements BlockBuilder { updateMech(); } + if(!isShooting()) { + updateBuilding(this); + } + x = Mathf.clamp(x, 0, world.width() * tilesize); y = Mathf.clamp(y, 0, world.height() * tilesize); } @@ -346,10 +347,6 @@ public class Player extends Unit implements BlockBuilder { damage(health + 1); //die instantly } - if(!isShooting()) { - updateBuilding(this); - } - if(ui.chatfrag.chatOpen()) return; dashing = Inputs.keyDown("dash"); @@ -401,16 +398,16 @@ public class Player extends Unit implements BlockBuilder { } protected void updateFlying(){ - rotation = Mathf.slerpDelta(rotation, targetAngle, 0.2f); + rotation = Mathf.slerpDelta(rotation, targetAngle, 0.1f); } @Override - public boolean acceptsAmmo(io.anuke.mindustry.type.Item item) { + public boolean acceptsAmmo(Item item) { return weapon.getAmmoType(item) != null && inventory.canAcceptAmmo(weapon.getAmmoType(item)); } @Override - public void addAmmo(io.anuke.mindustry.type.Item item) { + public void addAmmo(Item item) { inventory.addAmmo(weapon.getAmmoType(item)); } diff --git a/core/src/io/anuke/mindustry/game/ContentDatabase.java b/core/src/io/anuke/mindustry/game/ContentDatabase.java index 7606b10990..66ab5034ef 100644 --- a/core/src/io/anuke/mindustry/game/ContentDatabase.java +++ b/core/src/io/anuke/mindustry/game/ContentDatabase.java @@ -11,6 +11,7 @@ import static io.anuke.mindustry.Vars.debug; public class ContentDatabase { private ObjectMap> unlocked = new ObjectMap<>(); + /**Returns whether or not this piece of content is unlocked yet.*/ public boolean isUnlocked(Content content){ if(debug){ return true; @@ -25,6 +26,17 @@ public class ContentDatabase { return set.contains(content.getContentName()); } + /**Makes this piece of content 'unlocked'. + * If this piece of content is already unlocked, nothing changes. + * Results are not saved until you call {@link #save()}.*/ + public void unlockContent(Content content){ + if(!unlocked.containsKey(content.getContentTypeName())){ + unlocked.put(content.getContentTypeName(), new ObjectSet<>()); + } + + unlocked.get(content.getContentTypeName()).add(content.getContentName()); + } + private void load(){ ObjectMap> result = Settings.getJson("content-database", ObjectMap.class); diff --git a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java index 6a0d1bad8a..6590d35f91 100644 --- a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.graphics; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; @@ -10,8 +9,6 @@ import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.game.TeamInfo.TeamData; import io.anuke.mindustry.input.InputHandler; -import io.anuke.mindustry.input.PlaceMode; -import io.anuke.mindustry.ui.fragments.ToolFragment; import io.anuke.mindustry.world.BlockBar; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Graphics; @@ -25,7 +22,6 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; -import static io.anuke.mindustry.Vars.playerGroup; public class OverlayRenderer { @@ -41,34 +37,7 @@ public class OverlayRenderer { tile.block().drawConfigure(tile); } - int tilex = input.getBlockX(); - int tiley = input.getBlockY(); - - //draw placement box - if ((input.recipe != null && (!ui.hasMouse() || mobile) - && input.drawPlace())) { - - input.placeMode.draw(input, input.getBlockX(), - input.getBlockY(), input.getBlockEndX(), input.getBlockEndY()); - - if (input.breakMode == PlaceMode.holdDelete) - input.breakMode.draw(input, tilex, tiley, 0, 0); - - } else if (input.breakMode.delete && input.drawPlace() - && (input.recipe == null) - && (input.placeMode.delete || input.breakMode.both || !mobile)) { - - if (input.breakMode == PlaceMode.holdDelete) - input.breakMode.draw(input, tilex, tiley, 0, 0); - else - input.breakMode.draw(input, input.getBlockX(), - input.getBlockY(), input.getBlockEndX(), input.getBlockEndY()); - } - - if (input.frag.tool.confirming) { - ToolFragment t = input.frag.tool; - PlaceMode.areaDelete.draw(input, t.px, t.py, t.px2, t.py2); - } + input.draw(); Draw.reset(); @@ -182,7 +151,7 @@ public class OverlayRenderer { drawBar(Color.valueOf("32cf6d"), x, y - 9f, unit.inventory.totalAmmo() / (float) unit.inventory.ammoCapacity()); } - public void drawBar(Color color, float x, float y, float finion){ + void drawBar(Color color, float x, float y, float finion){ finion = Mathf.clamp(finion); if(finion > 0) finion = Mathf.clamp(finion + 0.2f, 0.24f, 1f); @@ -202,7 +171,7 @@ public class OverlayRenderer { Draw.reset(); } - public void drawEncloser(float x, float y, float height){ + void drawEncloser(float x, float y, float height){ x -= 0.5f; y += 0.5f - (height-1f)/2f; diff --git a/core/src/io/anuke/mindustry/input/AndroidInput.java b/core/src/io/anuke/mindustry/input/AndroidInput.java index 4d17bb004a..d8c9f65003 100644 --- a/core/src/io/anuke/mindustry/input/AndroidInput.java +++ b/core/src/io/anuke/mindustry/input/AndroidInput.java @@ -1,150 +1,237 @@ package io.anuke.mindustry.input; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.input.GestureDetector; +import com.badlogic.gdx.input.GestureDetector.GestureListener; import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.net.NetEvents; +import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.graphics.Lines; +import io.anuke.ucore.scene.Group; +import io.anuke.ucore.scene.builders.imagebutton; +import io.anuke.ucore.scene.builders.table; import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; -public class AndroidInput extends InputHandler{ - public float lmousex, lmousey; - public float mousex, mousey; - public boolean brokeBlock = false; - public boolean placing = false; - - private boolean enableHold = false; - private float warmup; - private float warmupDelay = 20; +public class AndroidInput extends InputHandler implements GestureListener{ + //gesture data + private Vector2 pinch1 = new Vector2(-1, -1), pinch2 = pinch1.cpy(); + private Vector2 vector = new Vector2(); + private float initzoom = -1; + private boolean zoomed = false; + + /**List of currently selected tiles to place.*/ + private Array placement = new Array<>(); + /**Whether or not the player is currently shifting all placed tiles.*/ + private boolean selecting; public AndroidInput(Player player){ super(player); - Inputs.addProcessor(new GestureDetector(20, 0.5f, 2, 0.15f, new GestureHandler(this))); + Inputs.addProcessor(new GestureDetector(20, 0.5f, 2, 0.15f, this)); } - - @Override public float getCursorEndX(){ return Gdx.input.getX(0); } - @Override public float getCursorEndY(){ return Gdx.input.getY(0); } - @Override public float getCursorX(){ return mousex; } - @Override public float getCursorY(){ return mousey; } - @Override public boolean drawPlace(){ return (placing && !brokeBlock) || (placeMode.pan && recipe != null); } - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button){ - if(brokeBlock){ - brokeBlock = false; - return false; - } - - if(placing && pointer == 0 && !placeMode.pan && !breaking()){ - placeMode.released(this, getBlockX(), getBlockY(), getBlockEndX(), getBlockEndY()); - }else if(pointer == 0 && !breakMode.pan && breaking() && drawPlace()){ - breakMode.released(this, getBlockX(), getBlockY(), getBlockEndX(), getBlockEndY()); - } + boolean hasRequest(Tile tile){ + for(PlaceRequest req : placement){ + if(req.tile() == tile) return true; + } + return false; + } - placing = false; - return false; - } + @Override + public void buildUI(Group group) { + + //Create confirm/cancel table + new table(){{ + abottom().aleft(); + defaults().size(60f); + + //Add a cancel button, which clears the selection. + new imagebutton("icon-cancel", 14*2f, () -> { + placement.clear(); + selecting = false; + }); + + //Add an accept button, which places everything. + new imagebutton("icon-check", 14*2f, () -> { + for(PlaceRequest request : placement){ + Tile tile = request.tile(); + + if(tile != null){ + rotation = request.rotation; + recipe = request.recipe; + tryPlaceBlock(tile.x, tile.y); + } + } + + placement.clear(); + selecting = false; + }); + }}.visible(this::isPlacing).end(); + } + + @Override + public void draw(){ + Draw.color(Palette.accent); + + //Draw all placement requests as squares + for(PlaceRequest request : placement){ + Tile tile = request.tile(); + if(tile == null) continue; + Lines.square(tile.worldx() + request.recipe.result.offset(), tile.worldy() + request.recipe.result.offset(), + request.recipe.result.size * tilesize/2f); + } + + Draw.color(); + } @Override public boolean touchDown(int screenX, int screenY, int pointer, int button){ - if(ui.hasMouse()){ - brokeBlock = true; - return false; - } + if(state.is(State.menu)) return false; - lmousex = screenX; - lmousey = screenY; - - if((!placeMode.pan || breaking()) && pointer == 0){ - mousex = screenX; - mousey = screenY; - } + //get tile on cursor + Tile cursor = world.tile(Mathf.scl2(Graphics.mouseWorld().x, tilesize), Mathf.scl2(Graphics.mouseWorld().y, tilesize)); - placing = pointer == 0; - - warmup = 0; + //ignore off-screen taps + if(cursor == null || ui.hasMouse(screenX, screenY)) return false; - if(!state.is(State.menu)){ - Tile cursor = world.tile(Mathf.scl2(Graphics.mouseWorld().x, tilesize), Mathf.scl2(Graphics.mouseWorld().y, tilesize)); - if(cursor != null && !ui.hasMouse(screenX, screenY)){ - Tile linked = cursor.isLinked() ? cursor.getLinked() : cursor; - if(linked != null && linked.block().isConfigurable(linked)){ - frag.config.showConfig(linked); - }else if(!frag.config.hasConfigMouse()){ - frag.config.hideConfig(); - } + //only begin selecting if the tapped block is a request + selecting = hasRequest(cursor); + + Tile linked = cursor.target(); + + //show-hide configuration fragment for blocks + if(linked.block().isConfigurable(linked)){ + frag.config.showConfig(linked); + }else if(!frag.config.hasConfigMouse()){ + frag.config.hideConfig(); + } + + //call tapped() event + //TODO net event for block tapped + linked.block().tapped(linked, player); - if(linked != null) { - linked.block().tapped(linked, player); - if(Net.active()) NetEvents.handleBlockTap(linked); - } - } - } return false; } - - @Override - public void resetCursor(){ - mousex = Gdx.graphics.getWidth()/2; - mousey = Gdx.graphics.getHeight()/2; - } - public Tile selected(){ - Vector2 vec = Graphics.world(mousex, mousey); - return world.tile(Mathf.scl2(vec.x, tilesize), Mathf.scl2(vec.y, tilesize)); - } + @Override + public boolean tap(float x, float y, int count, int button) { + if(state.is(State.menu)) return false; + + //get tile on cursor + Tile cursor = world.tile(Mathf.scl2(Graphics.mouseWorld().x, tilesize), Mathf.scl2(Graphics.mouseWorld().y, tilesize)); + + //ignore off-screen taps + if(cursor == null || ui.hasMouse(x, y)) return false; + + //add to placement queue if it's a valid place position + if(isPlacing() && validPlace(cursor.x, cursor.y, recipe.result)){ + placement.add(new PlaceRequest(cursor.worldx(), cursor.worldy(), recipe, rotation)); + } + + return false; + } @Override public void update(){ - enableHold = breakMode == PlaceMode.holdDelete; - float xa = Inputs.getAxis("move_x"); - float ya = Inputs.getAxis("move_y"); - if(Math.abs(xa) < controllerMin) xa = 0; - if(Math.abs(ya) < controllerMin) ya = 0; - - player.x += xa * 4f; - player.y += ya * 4f; - - rotation += Inputs.getAxis("rotate_alt"); - rotation += Inputs.getAxis("rotate"); - rotation = Mathf.mod(rotation, 4); - - if(enableHold && Gdx.input.isTouched(0) && Mathf.near2d(lmousex, lmousey, Gdx.input.getX(0), Gdx.input.getY(0), Unit.dp.scl(50)) - && !ui.hasMouse()){ - warmup += Timers.delta(); - - float lx = mousex, ly = mousey; - - mousex = Gdx.input.getX(0); - mousey = Gdx.input.getY(0); - - Tile sel = selected(); - - if(sel == null) - return; - - mousex = lx; - mousey = ly; - }else{ - warmup = 0; - breaktime = 0; - - mousex = Mathf.clamp(mousex, 0, Gdx.graphics.getWidth()); - mousey = Mathf.clamp(mousey, 0, Gdx.graphics.getHeight()); - } + if(!isPlacing()){ + selecting = false; + placement.clear(); + } } - public boolean breaking(){ - return recipe == null; - } + @Override + public boolean pan(float x, float y, float deltaX, float deltaY){ + float dx = deltaX * Core.camera.zoom / Core.cameraScale, dy = deltaY * Core.camera.zoom / Core.cameraScale; + + if(selecting){ + for(PlaceRequest req : placement){ + req.x += dx; + req.y -= dy; + } + }else{ + player.x -= dx; + player.y += dy; + player.targetAngle = Mathf.atan2(dx, -dy) + 180f; + } + + return false; + } + + @Override + public boolean panStop(float x, float y, int pointer, int button) { + return false; + } + + @Override + public boolean pinch (Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) { + if(pinch1.x < 0){ + pinch1.set(initialPointer1); + pinch2.set(initialPointer2); + } + + Vector2 vec = (vector.set(pointer1).add(pointer2).scl(0.5f)).sub(pinch1.add(pinch2).scl(0.5f)); + + player.x -= vec.x*Core.camera.zoom/Core.cameraScale; + player.y += vec.y*Core.camera.zoom/Core.cameraScale; + + pinch1.set(pointer1); + pinch2.set(pointer2); + + return false; + } + + @Override + public boolean zoom(float initialDistance, float distance){ + if(initzoom < 0){ + initzoom = initialDistance; + } + + if(Math.abs(distance - initzoom) > Unit.dp.scl(100f) && !zoomed){ + int amount = (distance > initzoom ? 1 : -1); + renderer.scaleCamera(Math.round(Unit.dp.scl(amount))); + initzoom = distance; + zoomed = true; + return true; + } + + return false; + } + + @Override + public void pinchStop () { + initzoom = -1; + pinch2.set(pinch1.set(-1, -1)); + zoomed = false; + } + + @Override public boolean touchDown(float x, float y, int pointer, int button) { return false; } + @Override public boolean longPress(float x, float y) { return false; } + @Override public boolean fling(float velocityX, float velocityY, int button) { return false; } + + class PlaceRequest{ + float x, y; + Recipe recipe; + int rotation; + + PlaceRequest(float x, float y, Recipe recipe, int rotation) { + this.x = x; + this.y = y; + this.recipe = recipe; + this.rotation = rotation; + } + + Tile tile(){ + return world.tileWorld(x - recipe.result.offset(), y - recipe.result.offset()); + } + } } diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index c686db4fb0..67022d9c56 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -32,26 +32,12 @@ public class DesktopInput extends InputHandler{ this.index = player.playerIndex; this.section = "player_" + (player.playerIndex + 1); } - - @Override public float getCursorEndX(){ return endx; } - @Override public float getCursorEndY(){ return endy; } - @Override public float getCursorX(){ return prmousex; } - @Override public float getCursorY(){ return prmousey; } - @Override public boolean drawPlace(){ return !beganBreak; } @Override public void update(){ if(player.isDead()) return; - if(Inputs.keyRelease(section, "select") && recipe != null){ - placeMode.released(this, getBlockX(), getBlockY(), getBlockEndX(), getBlockEndY()); - } - - if(Inputs.keyRelease(section, "break") && !beganBreak){ - breakMode.released(this, getBlockX(), getBlockY(), getBlockEndX(), getBlockEndY()); - } - if(!Inputs.keyDown(section, "select")){ shooting = false; } @@ -97,12 +83,6 @@ public class DesktopInput extends InputHandler{ rotation += Inputs.getAxis(section,"rotate"); rotation = Mathf.mod(rotation, 4); - - if(Inputs.keyDown(section,"break")){ - breakMode = PlaceMode.areaDelete; - }else{ - breakMode = PlaceMode.hold; - } int keyIndex = 1; diff --git a/core/src/io/anuke/mindustry/input/GestureHandler.java b/core/src/io/anuke/mindustry/input/GestureHandler.java deleted file mode 100644 index c87384196f..0000000000 --- a/core/src/io/anuke/mindustry/input/GestureHandler.java +++ /dev/null @@ -1,116 +0,0 @@ -package io.anuke.mindustry.input; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.input.GestureDetector.GestureAdapter; -import com.badlogic.gdx.math.Vector2; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.*; - -public class GestureHandler extends GestureAdapter{ - AndroidInput input; - Vector2 pinch1 = new Vector2(-1, -1), pinch2 = pinch1.cpy(); - Vector2 vector = new Vector2(); - float initzoom = -1; - boolean zoomed = false; - - GestureHandler(AndroidInput input){ - this.input = input; - } - - @Override - public boolean longPress(float x, float y){ - return false; - } - - @Override - public boolean tap (float x, float y, int count, int button) { - if(ui.hasMouse() || input.brokeBlock) return false; - - if(!input.placeMode.pan || input.recipe == null){ - input.mousex = x; - input.mousey = y; - - if(input.recipe == null) - input.breakMode.tapped(input, input.getBlockX(), input.getBlockY()); - else - input.placeMode.tapped(input, input.getBlockX(), input.getBlockY()); - } - return false; - } - - @Override - public boolean pan(float x, float y, float deltaX, float deltaY){ - if(input.isCursorVisible() && !Inputs.keyDown("select")) return false; - - if(!input.isCursorVisible() && !(input.recipe != null - && input.placeMode.lockCamera) && - !(input.recipe == null && input.breakMode.lockCamera)){ - float dx = deltaX*Core.camera.zoom/Core.cameraScale, dy = deltaY*Core.camera.zoom/Core.cameraScale; - input.player.x -= dx; - input.player.y += dy; - input.player.targetAngle = Mathf.atan2(dx, -dy) + 180f; - }else if(input.placeMode.lockCamera && (input.placeMode.pan && input.recipe != null)){ - input.mousex += deltaX; - input.mousey += deltaY; - } - - return false; - } - - @Override - public boolean pinch (Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) { - if(input.recipe == null && !input.breakMode.lockCamera) - return false; - - if(pinch1.x < 0){ - pinch1.set(initialPointer1); - pinch2.set(initialPointer2); - } - - Vector2 vec = (vector.set(pointer1).add(pointer2).scl(0.5f)).sub(pinch1.add(pinch2).scl(0.5f)); - - input.player.x -= vec.x*Core.camera.zoom/Core.cameraScale; - input.player.y += vec.y*Core.camera.zoom/Core.cameraScale; - - pinch1.set(pointer1); - pinch2.set(pointer2); - - return false; - } - - @Override - public boolean zoom(float initialDistance, float distance){ - if(initzoom < 0){ - initzoom = initialDistance; - } - - if(Math.abs(distance - initzoom) > Unit.dp.scl(100f) && !zoomed){ - int amount = (distance > initzoom ? 1 : -1); - renderer.scaleCamera(Math.round(Unit.dp.scl(amount))); - initzoom = distance; - zoomed = true; - return true; - } - - return false; - } - - @Override - public void pinchStop () { - initzoom = -1; - pinch2.set(pinch1.set(-1, -1)); - zoomed = false; - } - - int touches(){ - int sum = 0; - for(int i = 0; i < 10; i ++){ - if(Gdx.input.isTouched(i)) sum++; - } - return sum; - } -} diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index f38fa8d4d6..5a6c01a91f 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -16,6 +16,7 @@ import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Inputs; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.scene.Group; import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; @@ -27,37 +28,61 @@ public abstract class InputHandler extends InputAdapter{ public final static float playerSelectRange = Unit.dp.scl(60f); private final static Translator stackTrns = new Translator(); - public float breaktime = 0; + private float mx, my; + + public final Player player; + public final OverlayFragment frag = new OverlayFragment(this); + public Recipe recipe; public int rotation; - public Player player; - public PlaceMode placeMode = mobile ? PlaceMode.cursor : PlaceMode.hold; - public PlaceMode breakMode = mobile ? PlaceMode.none : PlaceMode.holdDelete; - public PlaceMode lastPlaceMode = placeMode; - public PlaceMode lastBreakMode = breakMode; public boolean droppingItem, transferring; public boolean shooting; - public OverlayFragment frag = new OverlayFragment(this); public InputHandler(Player player){ this.player = player; Timers.run(1f, () -> frag.build(Core.scene.getRoot())); } - public abstract void update(); - public abstract float getCursorX(); - public abstract float getCursorY(); - public abstract float getCursorEndX(); - public abstract float getCursorEndY(); - public float getMouseX(){ return Gdx.input.getX(); }; - public float getMouseY(){ return Gdx.input.getY(); }; - public int getBlockX(){ return Mathf.sclb(Graphics.world(getCursorX(), getCursorY()).x, tilesize, round2()); } - public int getBlockY(){ return Mathf.sclb(Graphics.world(getCursorX(), getCursorY()).y, tilesize, round2()); } - public int getBlockEndX(){ return Mathf.sclb(Graphics.world(getCursorEndX(), getCursorEndY()).x, tilesize, round2()); } - public int getBlockEndY(){ return Mathf.sclb(Graphics.world(getCursorEndX(), getCursorEndY()).y, tilesize, round2()); } - public void resetCursor(){} - public boolean isCursorVisible(){ return false; } - public void updateController(){} + //methods to override + + public void update(){ + + } + + public float getMouseX(){ + return mx; + } + + public float getMouseY(){ + return my; + } + + public void resetCursor(){ + + } + + public boolean isCursorVisible(){ + return false; + } + + public void updateController(){ + mx = Gdx.input.getX(); + my = Gdx.input.getY(); + } + + public void buildUI(Group group){ + + } + + public void draw(){ + + } + + //utility methods + + public boolean isPlacing(){ + return recipe != null; + } public float mouseAngle(float x, float y){ return Graphics.world(getMouseX(), getMouseY()).sub(x, y).angle(); @@ -75,12 +100,9 @@ public abstract class InputHandler extends InputAdapter{ public boolean isShooting(){ return shooting; } - - public boolean drawPlace(){ return true; } public boolean onConfigurable(){ - Tile tile = world.tile(getBlockX(), getBlockY()); - return tile != null && (tile.block().isConfigurable(tile) || (tile.isLinked() && tile.getLinked().block().isConfigurable(tile))); + return false; } public boolean isDroppingItem(){ @@ -129,26 +151,8 @@ public abstract class InputHandler extends InputAdapter{ } }); } - }else{ - //TODO create drop on the ground - /* - Vector2 vec = Graphics.screen(player.x, player.y); - - if(vec.dst(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY()) > playerSelectRange) { - int sent = Mathf.clamp(stack.amount / 4, 1, 8); - float backTrns = 3f; - for (int i = 0; i < sent; i++) { - Timers.run(i, () -> { - float x = player.x + Angles.trnsx(rotation + 180f, backTrns), - y = player.y + Angles.trnsy(rotation + 180f, backTrns); - - ItemTransfer.create(stack.item, - x, y, x + Mathf.range(20f), y + Mathf.range(20f), () -> {}); - }); - } - player.inventory.clear(); - }*/ } + //TODO create drop on the ground otherwise } public boolean cursorNear(){ @@ -156,8 +160,7 @@ public abstract class InputHandler extends InputAdapter{ } public boolean tryPlaceBlock(int x, int y){ - if(recipe != null && - validPlace(x, y, recipe.result) && !ui.hasMouse() && cursorNear()){ + if(recipe != null && validPlace(x, y, recipe.result) && cursorNear()){ placeBlock(x, y, recipe, rotation); @@ -174,10 +177,6 @@ public abstract class InputHandler extends InputAdapter{ return false; } - public boolean round2(){ - return !(recipe != null && recipe.result.isMultiblock() && recipe.result.size % 2 == 0); - } - public boolean validPlace(int x, int y, Block type){ for(Tile tile : state.teams.get(player.team).cores){ if(tile.distanceTo(x * tilesize, y * tilesize) < coreBuildRange){ diff --git a/core/src/io/anuke/mindustry/input/PlaceMode.java b/core/src/io/anuke/mindustry/input/PlaceMode.java index 59a222214a..02c669707a 100644 --- a/core/src/io/anuke/mindustry/input/PlaceMode.java +++ b/core/src/io/anuke/mindustry/input/PlaceMode.java @@ -3,10 +3,8 @@ package io.anuke.mindustry.input; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; -import io.anuke.mindustry.ui.fragments.ToolFragment; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Build; import io.anuke.mindustry.world.Tile; @@ -34,14 +32,14 @@ public enum PlaceMode{ float y = tiley * tilesize; boolean valid = input.validPlace(tilex, tiley, input.recipe.result) && (mobile || input.cursorNear()); - - Vector2 offset = input.recipe.result.getPlaceOffset(); + + float offset = input.recipe.result.offset(); float si = MathUtils.sin(Timers.time() / 6f) + 1.5f; Draw.color(valid ? Palette.place : Palette.remove); Lines.stroke(2f); - Lines.crect(x + offset.x, y + offset.y, tilesize * input.recipe.result.size + si, + Lines.crect(x + offset, y + offset, tilesize * input.recipe.result.size + si, tilesize * input.recipe.result.size + si); input.recipe.result.drawPlace(tilex, tiley, input.rotation, valid); @@ -77,29 +75,6 @@ public enum PlaceMode{ both = true; } }, - holdDelete{ - { - delete = true; - shown = true; - both = true; - } - - public void draw(InputHandler input, int tilex, int tiley, int endx, int endy){ - Tile tile = world.tile(tilex, tiley); - - if(tile != null && input.validBreak(tilex, tiley)){ - if(tile.isLinked()) - tile = tile.getLinked(); - float fin = input.breaktime / tile.getBreakTime(); - - if(mobile && input.breaktime > 0){ - Draw.color(Palette.place, Palette.remove, fin); - Lines.poly(tile.drawx(), tile.drawy(), 25, 4 + (1f - fin) * 26); - } - Draw.reset(); - } - } - }, touchDelete{ { shown = true; @@ -174,18 +149,6 @@ public enum PlaceMode{ input.player.clearBuilding(); - if(mobile){ - ToolFragment t = input.frag.tool; - 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; - } - } - for(int cx = tilex; cx <= endx; cx ++){ for(int cy = tiley; cy <= endy; cy ++){ input.tryDeleteBlock(cx, cy); @@ -241,7 +204,7 @@ public enum PlaceMode{ float t = tilesize; Block block = input.recipe.result; - Vector2 offset = block.getPlaceOffset(); + float offset = block.offset(); process(input, tilex, tiley, endx, endy); float x = rtilex * t, y = rtiley * t, @@ -257,10 +220,10 @@ public enum PlaceMode{ y2 += block.size * t/2; } - x += offset.x; - y += offset.y; - x2 += offset.x; - y2 += offset.y; + x += offset; + y += offset; + x2 += offset; + y2 += offset; if(tilex == endx && tiley == endy){ cursor.draw(input, tilex, tiley, endx, endy); @@ -285,7 +248,7 @@ public enum PlaceMode{ Draw.color(Palette.accent); } - drawPreview(block, wx * t + offset.x, wy * t + offset.y); + drawPreview(block, wx * t + offset, wy * t + offset); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java index f52b7278c3..312f92ec23 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java @@ -1,11 +1,292 @@ package io.anuke.mindustry.ui.fragments; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Interpolation; +import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.input.InputHandler; +import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.Recipe; +import io.anuke.mindustry.type.Section; +import io.anuke.ucore.scene.Element; import io.anuke.ucore.scene.Group; +import io.anuke.ucore.scene.actions.Actions; +import io.anuke.ucore.scene.builders.table; +import io.anuke.ucore.scene.event.ClickListener; +import io.anuke.ucore.scene.event.InputEvent; +import io.anuke.ucore.scene.event.Touchable; +import io.anuke.ucore.scene.ui.ButtonGroup; +import io.anuke.ucore.scene.ui.Image; +import io.anuke.ucore.scene.ui.ImageButton; +import io.anuke.ucore.scene.ui.Label; +import io.anuke.ucore.scene.ui.layout.Stack; +import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.ucore.util.Bundles; +import io.anuke.ucore.util.Mathf; + +import static io.anuke.mindustry.Vars.*; public class BlocksFragment implements Fragment{ + private Table desctable, blocks; + private Stack stack = new Stack(); + private boolean shown = true; + private Recipe hoveredDescriptionRecipe; - @Override public void build(Group parent){ + InputHandler input = control.input(0); + new table(){{ + abottom(); + aright(); + + visible(() -> !state.is(State.menu) && shown); + + blocks = new table(){{ + desctable = new Table("button"); + desctable.setVisible(() -> hoveredDescriptionRecipe != null || input.recipe != null); + desctable.update(() -> { + // note: This is required because there is no direct connection between + // input.recipe and the description ui. If input.recipe gets set to null + // a proper cleanup of the ui elements is required. + boolean anyRecipeShown = input.recipe != null || hoveredDescriptionRecipe != null; + boolean descriptionTableClean = desctable.getChildren().size == 0; + boolean cleanupRequired = !anyRecipeShown && !descriptionTableClean; + if(cleanupRequired){ + desctable.clear(); + } + }); + + stack.add(desctable); + + add(stack).fillX().uniformX(); + + row(); + + new table("pane") {{ + touchable(Touchable.enabled); + int rows = 4; + int maxcol = 0; + float size = 48; + + Stack stack = new Stack(); + ButtonGroup group = new ButtonGroup<>(); + Array recipes = new Array<>(); + + for (Section sec : Section.values()) { + recipes.clear(); + Recipe.getBySection(sec, recipes); + maxcol = Math.max((int) ((float) recipes.size / rows + 1), maxcol); + } + + for (Section sec : Section.values()) { + int secrows = 4; + + recipes.clear(); + Recipe.getBySection(sec, recipes); + + Table table = new Table(); + + ImageButton button = new ImageButton("icon-" + sec.name(), "toggle"); + button.clicked(() -> { + if (!table.isVisible() && input.recipe != null) { + input.recipe = null; + } + }); + + button.setName("sectionbutton" + sec.name()); + add(button).growX().height(54).padLeft(-1).padTop(sec.ordinal() <= secrows-1 ? -10 : -5); + button.getImageCell().size(40).padBottom(4).padTop(2); + group.add(button); + + if (sec.ordinal() % secrows == secrows-1) { + row(); + } + + table.margin(4); + table.top().left(); + + int i = 0; + + for (Recipe r : recipes) { + ImageButton image = new ImageButton(new TextureRegion(), "select"); + + TextureRegion[] regions = r.result.getCompactIcon(); + Stack istack = new Stack(); + for(TextureRegion region : regions){ + istack.add(new Image(region)); + } + + image.getImageCell().setActor(istack).size(size); + image.addChild(istack); + image.getImage().remove(); + + image.addListener(new ClickListener(){ + @Override + public void enter(InputEvent event, float x, float y, int pointer, Element fromActor) { + super.enter(event, x, y, pointer, fromActor); + if (hoveredDescriptionRecipe != r) { + hoveredDescriptionRecipe = r; + updateRecipe(r); + } + } + + @Override + public void exit(InputEvent event, float x, float y, int pointer, Element toActor) { + super.exit(event, x, y, pointer, toActor); + hoveredDescriptionRecipe = null; + updateRecipe(input.recipe); + } + }); + + image.addListener(new ClickListener(){ + @Override + public void clicked(InputEvent event, float x, float y){ + // note: input.recipe only gets set here during a click. + // during a hover only the visual description will be updated. + InputHandler handler = mobile ? input : control.input(event.getPointer()); + + boolean nothingSelectedYet = handler.recipe == null; + boolean selectedSomethingElse = !nothingSelectedYet && handler.recipe != r; + boolean shouldMakeSelection = nothingSelectedYet || selectedSomethingElse; + if (shouldMakeSelection) { + handler.recipe = r; + hoveredDescriptionRecipe = r; + updateRecipe(r); + } else { + handler.recipe = null; + hoveredDescriptionRecipe = null; + updateRecipe(null); + } + } + }); + + table.add(image).size(size + 8); + + image.update(() -> { + image.setTouchable(Touchable.enabled); + for(Element e : istack.getChildren()){ + e.setColor(Color.WHITE); + } + + for(Player player : players){ + if(control.input(player.playerIndex).recipe == r){ + image.setChecked(true); + return; + } + } + image.setChecked(false); + }); + + if (i % rows == rows - 1) { + table.row(); + } + + i++; + } + + table.setVisible(button::isChecked); + + stack.add(table); + } + + row(); + add(stack).colspan(Section.values().length); + margin(10f); + + marginLeft(1f); + marginRight(1f); + + end(); + }}.right().bottom().uniformX(); + + visible(() -> !state.is(State.menu) && shown); + + }}.end().get(); + }}.end(); } -} + + public void toggle(boolean show, float t, Interpolation ip){ + if(!show){ + blocks.actions(Actions.translateBy(0, -blocks.getHeight() - stack.getHeight(), t, ip), Actions.call(() -> shown = false)); + }else{ + shown = true; + blocks.actions(Actions.translateBy(0, -blocks.getTranslation().y, t, ip)); + } + } + + void updateRecipe(Recipe recipe){ + if (recipe == null) { + desctable.clear(); + return; + } + + desctable.clear(); + desctable.setTouchable(Touchable.enabled); + + desctable.defaults().left(); + desctable.left(); + desctable.margin(12); + + Table header = new Table(); + + desctable.add(header).left(); + + desctable.row(); + + TextureRegion[] regions = recipe.result.getCompactIcon(); + + Stack istack = new Stack(); + + for(TextureRegion region : regions) istack.add(new Image(region)); + + header.add(istack).size(8*5).padTop(4); + Label nameLabel = new Label(recipe.result.formalName); + nameLabel.setWrap(true); + header.add(nameLabel).padLeft(2).width(120f); + + desctable.add().pad(2); + + Table requirements = new Table(); + + desctable.row(); + + desctable.add(requirements); + desctable.left(); + + for(ItemStack stack : recipe.requirements){ + requirements.addImage(stack.item.region).size(8*3); + Label reqlabel = new Label(""); + + reqlabel.update(() -> { + int current = stack.amount; + String text = Mathf.clamp(current, 0, stack.amount) + "/" + stack.amount; + + reqlabel.setText(text); + }); + + requirements.add(reqlabel).left(); + requirements.row(); + } + + desctable.row(); + + Label label = new Label("[health]"+ Bundles.get("text.health")+": " + recipe.result.health); + label.setWrap(true); + desctable.add(label).width(200).padTop(4).padBottom(2); + } + + private void checkUnlockableBlocks(){ + TileEntity entity = players[0].getClosestCore(); + + if(entity == null) return; + + for(Recipe recipe : Recipe.all()){ + if(entity.items.hasAtLeastOneOfItems(recipe.requirements)){ + control.database().unlockContent(recipe); + } + } + } +} \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index 9f716d80ea..587edb3eb7 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -48,7 +48,7 @@ public class DebugFragment implements Fragment { new table(){{ visible(() -> debug); - abottom().aleft(); + atop().aright(); new table("pane"){{ defaults().fillX().width(100f); diff --git a/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java b/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java index 0bd50d5190..902e61b67d 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java @@ -9,8 +9,11 @@ public class OverlayFragment implements Fragment{ public final BlockConfigFragment config; private Group group = new Group(); + private InputHandler input; public OverlayFragment(InputHandler input){ + this.input = input; + tool = new ToolFragment(input); inv = new BlockInventoryFragment(input); config = new BlockConfigFragment(); @@ -24,6 +27,8 @@ public class OverlayFragment implements Fragment{ inv.build(group); tool.build(group); config.build(group); + + input.buildUI(group); } public void remove(){ diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index 84b90ab3a8..3d1930ddb0 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -1,237 +1,12 @@ package io.anuke.mindustry.ui.fragments; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.Interpolation; -import com.badlogic.gdx.utils.Align; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.input.AndroidInput; -import io.anuke.mindustry.input.InputHandler; -import io.anuke.mindustry.input.PlaceMode; -import io.anuke.ucore.core.Core; import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.actions.Actions; -import io.anuke.ucore.scene.builders.imagebutton; -import io.anuke.ucore.scene.builders.label; -import io.anuke.ucore.scene.builders.table; -import io.anuke.ucore.scene.event.Touchable; -import io.anuke.ucore.scene.ui.ButtonGroup; -import io.anuke.ucore.scene.ui.ImageButton; -import io.anuke.ucore.scene.ui.Label; -import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Bundles; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.*; public class PlacementFragment implements Fragment{ - boolean shown = false, placing = false; - Table breaktable, next, container; - Label modelabel; - + + @Override public void build(Group parent){ - if(!mobile) return; - InputHandler input = control.input(0); - - float s = 50f; - float translation = Unit.dp.scl(58f); - - new table(){{ - visible(() -> !state.is(State.menu)); - - abottom(); - aleft(); - - ButtonGroup placeGroup = new ButtonGroup<>(); - ButtonGroup breakGroup = new ButtonGroup<>(); - - update(t -> { - if((input.recipe == null) == placing){ - float i = 0.1f; - Interpolation n = Interpolation.pow3Out; - if(input.recipe == null){ - placing = false; - container.clearActions(); - container.actions(Actions.translateBy(0, -(container.getTranslation().y + translation), i, n)); - if (!input.lastBreakMode.both) input.placeMode = input.lastBreakMode; - }else{ - placing = true; - container.clearActions(); - container.actions(Actions.translateBy(0, -(container.getTranslation().y), i, n)); - input.placeMode = input.lastPlaceMode; - } - } - - if(!input.placeMode.delete){ - placeGroup.setMinCheckCount(1); - for(ImageButton button : placeGroup.getButtons()){ - if(button.getName().equals(input.placeMode.name())){ - button.setChecked(true); - break; - } - } - }else{ - placeGroup.setMinCheckCount(0); - for(ImageButton button : placeGroup.getButtons()) - button.setChecked(false); - } - - if(input.placeMode.delete || input.breakMode.both){ - PlaceMode mode = input.breakMode; - breakGroup.setMinCheckCount(1); - for(ImageButton button : breakGroup.getButtons()){ - if(button.getName().equals(mode.name())){ - button.setChecked(true); - break; - } - } - }else{ - breakGroup.setMinCheckCount(0); - for(ImageButton button : breakGroup.getButtons()) - button.setChecked(false); - } - }); - - container = new table(){{ - modelabel = new label("").get(); - - row(); - - //break menu - new table() {{ - abottom(); - aleft(); - - height(s + 5 + 4); - - next = new table("pane") {{ - margin(5f); - - defaults().padBottom(-5.5f); - - new imagebutton("icon-arrow-right", 10 * 3, () -> { - toggle(!shown); - }).update(l -> l.getStyle().imageUp = Core.skin.getDrawable(shown ? "icon-arrow-left" : "icon-" + input.breakMode.name())).size(s, s + 4); - - }}.end().get(); - - breaktable = new table("pane") {{ - visible(() -> shown); - margin(5f); - marginLeft(-(Unit.dp.scl(1f) - 1f) * 2.5f); - touchable(Touchable.enabled); - aleft(); - - defaults().size(s, s + 4); - - for (PlaceMode mode : PlaceMode.values()) { - if (!mode.shown || !mode.delete) continue; - - defaults().padBottom(-5.5f); - - ImageButton button = new imagebutton("icon-" + mode.name(), "toggle", 10 * 3, () -> { - input.resetCursor(); - input.breakMode = mode; - input.lastBreakMode = mode; - if (!mode.both){ - input.placeMode = mode; - }else{ - input.placeMode = input.lastPlaceMode; - } - modeText(Bundles.format("text.mode.break", mode.toString())); - }).group(breakGroup).get(); - - button.setName(mode.name()); - button.released(() -> { - //TODO hack - if(mode == PlaceMode.areaDelete){ - ((AndroidInput)input).placing = false; - } - }); - } - - }}.end().get(); - - breaktable.getParent().swapActor(breaktable, next); - - breaktable.getTranslation().set(-breaktable.getPrefWidth(), 0); - - }}.end().get(); - - row(); - - //place menu - new table() {{ - touchable(Touchable.enabled); - - aleft(); - - new table("pane") {{ - margin(5f); - aleft(); - - defaults().size(s, s + 4).padBottom(-5.5f); - - Color color = Color.GRAY; - - new imagebutton("icon-cancel", 14 * 3, () -> { - input.recipe = null; - }).imageColor(color) - .visible(() -> input.recipe != null); - - for (PlaceMode mode : PlaceMode.values()) { - if (!mode.shown || mode.delete) continue; - - new imagebutton("icon-" + mode.name(), "toggle", 10 * 3, () -> { - input.resetCursor(); - input.placeMode = mode; - input.lastPlaceMode = mode; - modeText(Bundles.format("text.mode.place", mode.toString())); - }).group(placeGroup).get().setName(mode.name()); - } - - new imagebutton("icon-arrow", 14 * 3, () -> { - input.rotation = Mathf.mod(input.rotation + 1, 4); - }).imageColor(color).visible(() -> input.recipe != null).update(image -> { - image.getImage().setRotation(input.rotation * 90); - image.getImage().setOrigin(Align.center); - }); - - }}.left().end(); - }}.left().end(); - - }}.end().get(); - - container.setTranslation(0, -translation); - - }}.end(); } - private void modeText(String text){ - modelabel.setText(text); - modelabel.clearActions(); - modelabel.setColor(Color.WHITE); - modelabel.actions(Actions.fadeOut(5f, Interpolation.fade)); - } - - private void toggle(boolean show){ - InputHandler input = control.input(0); - - float dur = 0.3f; - Interpolation in = Interpolation.pow3Out; - - if(breaktable.getActions().size != 0 || shown == show) return; - - breaktable.getParent().swapActor(breaktable, next); - - if(!show){ - input.breakMode = PlaceMode.none; - if(input.placeMode.delete) input.placeMode = PlaceMode.none; - breaktable.actions(Actions.translateBy(-breaktable.getWidth() - 5, 0, dur, in), Actions.call(() -> shown = false)); - }else{ - shown = true; - breaktable.actions(Actions.translateBy(-breaktable.getTranslation().x - 5, 0, dur, in)); - } - } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java b/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java index a4325d7fc7..cd92c13125 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java @@ -1,24 +1,10 @@ package io.anuke.mindustry.ui.fragments; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Align; -import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.input.InputHandler; -import io.anuke.mindustry.input.PlaceMode; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Graphics; import io.anuke.ucore.scene.Group; -import io.anuke.ucore.scene.ui.layout.Table; - -import static io.anuke.mindustry.Vars.*; public class ToolFragment implements Fragment{ - private Table tools; - private InputHandler input; - - public int px, py, px2, py2; - public boolean confirming; + private final InputHandler input; public ToolFragment(InputHandler input){ this.input = input; @@ -26,53 +12,6 @@ public class ToolFragment implements Fragment{ @Override public void build(Group parent){ - float isize = 14*3; - - tools = new Table(); - - tools.addImageButton("icon-cancel", isize, () -> { - if(input.placeMode == PlaceMode.areaDelete && confirming){ - confirming = false; - }else{ - input.recipe = null; - } - }); - - tools.addImageButton("icon-rotate", isize, () -> { - input.rotation++; - input.rotation %= 4; - }); - - tools.addImageButton("icon-check", isize, () -> { - if(input.placeMode == PlaceMode.areaDelete && confirming){ - input.placeMode.released(input, px, py, px2, py2); - confirming = false; - }else{ - input.placeMode.tapped(input, input.getBlockX(), input.getBlockY()); - } - }); - - tools.setVisible(() -> - !state.is(State.menu) && mobile && ((input.recipe != null && - input.placeMode == PlaceMode.cursor) || confirming) - ); - - tools.update(() -> { - if(confirming){ - Vector2 v = Graphics.screen((px + px2)/2f * tilesize, Math.min(py, py2) * tilesize - tilesize*1.5f); - tools.setPosition(v.x, v.y, Align.top); - }else{ - tools.setPosition(input.getCursorX(), - Gdx.graphics.getHeight() - input.getCursorY() - 15*Core.cameraScale, Align.top); - } - - if(input.placeMode != PlaceMode.areaDelete){ - confirming = false; - } - }); - - - parent.addChild(tools); } } diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 2ae0020225..9f4044caa4 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.world; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.reflect.ClassReflection; @@ -39,7 +38,6 @@ public class Block extends BaseBlock implements Content{ private static ObjectMap map = new ObjectMap<>(); protected Array tempTiles = new Array<>(); - protected Vector2 tempVector = new Vector2(); protected Color tempColor = new Color(); protected TextureRegion[] blockIcon; @@ -405,8 +403,8 @@ public class Block extends BaseBlock implements Content{ } /**Offset for placing and drawing multiblocks.*/ - public Vector2 getPlaceOffset(){ - return tempVector.set(((size + 1) % 2) * tilesize/2, ((size + 1) % 2) * tilesize/2); + public float offset(){ + return ((size + 1) % 2) * tilesize/2; } public boolean isMultiblock(){ diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index 1b06049d07..5ac2f32ded 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.world; import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.fx.Fx; @@ -90,14 +89,13 @@ public class Build { } rect.setSize(type.size * tilesize, type.size * tilesize); - Vector2 offset = type.getPlaceOffset(); - rect.setCenter(offset.x + x * tilesize, offset.y + y * tilesize); + rect.setCenter(type.offset() + x * tilesize, type.offset() + y * tilesize); if(type.solid || type.solidifes) synchronized (Entities.entityLock) { try { - rect.setSize(tilesize * type.size).setCenter(x * tilesize + type.getPlaceOffset().x, y * tilesize + type.getPlaceOffset().y); + rect.setSize(tilesize * type.size).setCenter(x * tilesize + type.offset(), y * tilesize + type.offset()); boolean[] result = {false}; Units.getNearby(rect, e -> { diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 442c7c17e2..be8691c940 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -110,11 +110,11 @@ public class Tile implements Position{ } public float drawx(){ - return block().getPlaceOffset().x + worldx(); + return block().offset() + worldx(); } public float drawy(){ - return block().getPlaceOffset().y + worldy(); + return block().offset() + worldy(); } public Floor floor(){ diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java index f152e498ae..3b5a6260ff 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java @@ -136,7 +136,7 @@ public abstract class Turret extends Block{ public void drawPlace(int x, int y, int rotation, boolean valid){ Draw.color(Palette.place); Lines.stroke(1f); - Lines.dashCircle(x * tilesize + getPlaceOffset().x, y * tilesize + getPlaceOffset().y, range); + Lines.dashCircle(x * tilesize + offset(), y * tilesize + offset(), range); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/types/modules/InventoryModule.java b/core/src/io/anuke/mindustry/world/blocks/types/modules/InventoryModule.java index 4d9d4f03a0..a104acedc6 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/modules/InventoryModule.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/modules/InventoryModule.java @@ -10,8 +10,24 @@ import java.io.IOException; import java.util.Arrays; public class InventoryModule extends BlockModule{ + //TODO make private! public int[] items = new int[Item.all().size]; + public boolean hasItems(ItemStack[] stacks){ + for(ItemStack stack : stacks){ + if(!hasItem(stack.item, stack.amount)) return false; + } + return true; + } + + /**Returns true if this entity has at least one of each item in each stack.*/ + public boolean hasAtLeastOneOfItems(ItemStack[] stacks){ + for(ItemStack stack : stacks){ + if(!hasItem(stack.item, 1)) return false; + } + return true; + } + //TODO optimize! public int totalItems(){ int sum = 0;