Schematic flipping + rotation
This commit is contained in:
@@ -33,6 +33,8 @@ public class Vars implements Loadable{
|
||||
public static boolean loadLocales = true;
|
||||
/** Maximum number of broken blocks. TODO implement or remove.*/
|
||||
public static final int maxBrokenBlocks = 256;
|
||||
/** Maximum schematic size.*/
|
||||
public static final int maxSchematicSize = 32;
|
||||
/** IO buffer size. */
|
||||
public static final int bufferSize = 8192;
|
||||
/** global charset, since Android doesn't support the Charsets class */
|
||||
|
||||
@@ -278,7 +278,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
/** Config int. Not used unless hasConfig is true.*/
|
||||
public int config;
|
||||
/** Original position, only used in schematics.*/
|
||||
public int originalX, originalY;
|
||||
public int originalX, originalY, originalWidth, originalHeight;
|
||||
|
||||
/** Last progress.*/
|
||||
public float progress;
|
||||
@@ -327,9 +327,11 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
return copy;
|
||||
}
|
||||
|
||||
public BuildRequest original(int x, int y){
|
||||
public BuildRequest original(int x, int y, int originalWidth, int originalHeight){
|
||||
originalX = x;
|
||||
originalY = y;
|
||||
this.originalWidth = originalWidth;
|
||||
this.originalHeight = originalHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ import io.anuke.mindustry.content.*;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||
import io.anuke.mindustry.game.EventType.*;
|
||||
import io.anuke.mindustry.game.Schematic.*;
|
||||
import io.anuke.mindustry.input.*;
|
||||
import io.anuke.mindustry.input.PlaceUtils.*;
|
||||
import io.anuke.mindustry.type.*;
|
||||
import io.anuke.mindustry.world.*;
|
||||
|
||||
@@ -29,7 +31,6 @@ public class Schematics implements Loadable{
|
||||
private static final byte version = 0;
|
||||
|
||||
private static final int padding = 2;
|
||||
private static final int maxSize = 64;
|
||||
|
||||
private OptimizedByteArrayOutputStream out = new OptimizedByteArrayOutputStream(1024);
|
||||
private Array<Schematic> all = new Array<>();
|
||||
@@ -63,7 +64,7 @@ public class Schematics implements Loadable{
|
||||
}
|
||||
|
||||
Core.app.post(() -> {
|
||||
shadowBuffer = new FrameBuffer(maxSize + padding, maxSize + padding);
|
||||
shadowBuffer = new FrameBuffer(maxSchematicSize + padding, maxSchematicSize + padding);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -145,7 +146,7 @@ public class Schematics implements Loadable{
|
||||
|
||||
/** Creates an array of build requests from a schematic's data, centered on the provided x+y coordinates. */
|
||||
public Array<BuildRequest> toRequests(Schematic schem, int x, int y){
|
||||
return schem.tiles.map(t -> new BuildRequest(t.x + x - schem.width/2, t.y + y - schem.height/2, t.rotation, t.block).original(t.x, t.y).configure(t.config));
|
||||
return schem.tiles.map(t -> new BuildRequest(t.x + x - schem.width/2, t.y + y - schem.height/2, t.rotation, t.block).original(t.x, t.y, schem.width, schem.height).configure(t.config));
|
||||
}
|
||||
|
||||
/** Adds a schematic to the list, also copying it into the files.*/
|
||||
@@ -160,17 +161,11 @@ public class Schematics implements Loadable{
|
||||
|
||||
/** Creates a schematic from a world selection. */
|
||||
public Schematic create(int x, int y, int x2, int y2){
|
||||
if(x > x2){
|
||||
int temp = x;
|
||||
x = x2;
|
||||
x2 = temp;
|
||||
}
|
||||
|
||||
if(y > y2){
|
||||
int temp = y;
|
||||
y = y2;
|
||||
y2 = temp;
|
||||
}
|
||||
NormalizeResult result = PlaceUtils.normalizeArea(x, y, x2, y2, 0, false, maxSchematicSize);
|
||||
x = result.x;
|
||||
y = result.y;
|
||||
x2 = result.x2;
|
||||
y2 = result.y2;
|
||||
|
||||
Array<Stile> tiles = new Array<>();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import io.anuke.arc.scene.*;
|
||||
import io.anuke.arc.scene.event.*;
|
||||
import io.anuke.arc.scene.ui.*;
|
||||
import io.anuke.arc.util.ArcAnnotate.*;
|
||||
import io.anuke.mindustry.*;
|
||||
import io.anuke.mindustry.core.GameState.*;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||
import io.anuke.mindustry.game.EventType.*;
|
||||
@@ -91,7 +92,7 @@ public class DesktopInput extends InputHandler{
|
||||
drawRequest(lineRequests.get(i));
|
||||
}
|
||||
}else if(mode == breaking){
|
||||
drawSelection(selectX, selectY, cursorX, cursorY);
|
||||
drawBreakSelection(selectX, selectY, cursorX, cursorY);
|
||||
}else if(isPlacing()){
|
||||
if(block.rotate){
|
||||
drawArrow(block, cursorX, cursorY, rotation);
|
||||
@@ -126,10 +127,7 @@ public class DesktopInput extends InputHandler{
|
||||
}
|
||||
|
||||
if(Core.input.keyDown(Binding.schematic)){
|
||||
Lines.stroke(2f);
|
||||
|
||||
Draw.color(Pal.accent);
|
||||
Lines.rect(schemX * tilesize, schemY * tilesize, (cursorX - schemX) * tilesize, (cursorY - schemY) * tilesize);
|
||||
drawSelection(schemX, schemY, cursorX, cursorY, Vars.maxSchematicSize);
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
@@ -156,7 +154,7 @@ public class DesktopInput extends InputHandler{
|
||||
if(state.is(State.menu) || Core.scene.hasDialog()) return;
|
||||
|
||||
//zoom things
|
||||
if(Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && (Core.input.keyDown(Binding.zoom_hold))){
|
||||
if(Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && Core.input.keyDown(Binding.zoom_hold)){
|
||||
renderer.scaleCamera(Core.input.axisTap(Binding.zoom));
|
||||
}
|
||||
|
||||
@@ -193,10 +191,12 @@ public class DesktopInput extends InputHandler{
|
||||
sreq.rotation = Mathf.mod(sreq.rotation + (int)Core.input.axisTap(Binding.rotate), 4);
|
||||
}
|
||||
|
||||
if(Math.abs((int)Core.input.axisTap(Binding.rotate)) > 0 && isPlacing() && mode == placing){
|
||||
updateLine(selectX, selectY);
|
||||
}else if(Math.abs((int)Core.input.axisTap(Binding.rotate)) > 0 && !selectRequests.isEmpty()){
|
||||
rotateRequests(selectRequests, (int)Core.input.axisTap(Binding.rotate));
|
||||
if(!Core.input.keyDown(Binding.zoom_hold) && Math.abs((int)Core.input.axisTap(Binding.rotate)) > 0){
|
||||
if(isPlacing() && mode == placing){
|
||||
updateLine(selectX, selectY);
|
||||
}else if(!selectRequests.isEmpty()){
|
||||
rotateRequests(selectRequests, (int)Core.input.axisTap(Binding.rotate));
|
||||
}
|
||||
}
|
||||
|
||||
Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY());
|
||||
@@ -288,6 +288,16 @@ public class DesktopInput extends InputHandler{
|
||||
}
|
||||
}
|
||||
|
||||
if(!selectRequests.isEmpty()){
|
||||
if(Core.input.keyTap(Binding.schematic_flip_x)){
|
||||
flipRequests(selectRequests, true);
|
||||
}
|
||||
|
||||
if(Core.input.keyTap(Binding.schematic_flip_y)){
|
||||
flipRequests(selectRequests, false);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO remove
|
||||
if(Core.input.keyTap(KeyCode.V)){
|
||||
ui.schematics.show();
|
||||
|
||||
@@ -227,11 +227,25 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
|
||||
public void rotateRequests(Array<BuildRequest> requests, int direction){
|
||||
int ox = tileX(getMouseX()), oy = tileY(getMouseY());
|
||||
int ox = rawTileX(), oy = rawTileY();
|
||||
|
||||
requests.each(req -> {
|
||||
//req.x -= ox;
|
||||
//req.y -= oy;
|
||||
//rotate config position
|
||||
if(req.block.posConfig){
|
||||
int cx = Pos.x(req.config) - req.originalX, cy = Pos.y(req.config) - req.originalY;
|
||||
int lx = cx;
|
||||
|
||||
if(direction >= 0){
|
||||
cx = -cy;
|
||||
cy = lx;
|
||||
}else{
|
||||
cx = cy;
|
||||
cy = -lx;
|
||||
}
|
||||
req.config = Pos.get(cx + req.originalX, cy + req.originalY);
|
||||
}
|
||||
|
||||
//rotate actual request, centered on its multiblock position
|
||||
float wx = (req.x - ox) * tilesize + req.block.offset(), wy = (req.y - oy) * tilesize + req.block.offset();
|
||||
float x = wx;
|
||||
if(direction >= 0){
|
||||
@@ -243,7 +257,38 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
req.x = world.toTile(wx - req.block.offset()) + ox;
|
||||
req.y = world.toTile(wy - req.block.offset()) + oy;
|
||||
req.rotation += direction;
|
||||
req.rotation = Mathf.mod(req.rotation + direction, 4);
|
||||
});
|
||||
}
|
||||
|
||||
public void flipRequests(Array<BuildRequest> requests, boolean x){
|
||||
int origin = x ? rawTileX() : rawTileY();
|
||||
|
||||
requests.each(req -> {
|
||||
int value = -((x ? req.x : req.y) - origin) + origin;
|
||||
|
||||
if(x){
|
||||
req.x = value;
|
||||
}else{
|
||||
req.y = value;
|
||||
}
|
||||
|
||||
if(req.block.posConfig){
|
||||
int corigin = x ? req.originalWidth/2 : req.originalHeight/2;
|
||||
int nvalue = -((x ? Pos.x(req.config) : Pos.y(req.config)) - corigin) + corigin;
|
||||
if(x){
|
||||
req.originalX = -(req.originalX - corigin) + corigin;
|
||||
req.config = Pos.get(nvalue, Pos.y(req.config));
|
||||
}else{
|
||||
req.originalY = -(req.originalY - corigin) + corigin;
|
||||
req.config = Pos.get(Pos.x(req.config), nvalue);
|
||||
}
|
||||
}
|
||||
|
||||
//flip rotation
|
||||
if(x == (req.rotation % 2 == 0)){
|
||||
req.rotation = Mathf.mod(req.rotation + 2, 4);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -287,7 +332,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void drawSelection(int x1, int y1, int x2, int y2){
|
||||
protected void drawBreakSelection(int x1, int y1, int x2, int y2){
|
||||
NormalizeDrawResult result = PlaceUtils.normalizeDrawArea(Blocks.air, x1, y1, x2, y2, false, maxLength, 1f);
|
||||
NormalizeResult dresult = PlaceUtils.normalizeArea(x1, y1, x2, y2, rotation, false, maxLength);
|
||||
|
||||
@@ -335,6 +380,17 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
||||
}
|
||||
|
||||
protected void drawSelection(int x1, int y1, int x2, int y2, int maxLength){
|
||||
NormalizeDrawResult result = PlaceUtils.normalizeDrawArea(Blocks.air, x1, y1, x2, y2, false, maxLength, 1f);
|
||||
|
||||
Lines.stroke(2f);
|
||||
|
||||
Draw.color(Pal.accentBack);
|
||||
Lines.rect(result.x, result.y - 1, result.x2 - result.x, result.y2 - result.y);
|
||||
Draw.color(Pal.accent);
|
||||
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
||||
}
|
||||
|
||||
protected void flushSelectRequests(Array<BuildRequest> requests){
|
||||
for(BuildRequest req : requests){
|
||||
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
|
||||
@@ -480,14 +536,6 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//clear when the player taps on something else
|
||||
if(!consumed && !mobile && player.isBuilding() && block == null){
|
||||
//player.clearBuilding();
|
||||
block = null;
|
||||
return true;
|
||||
}*/
|
||||
|
||||
if(!showedInventory){
|
||||
frag.inv.hide();
|
||||
}
|
||||
@@ -531,6 +579,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
return world.tile(tileX(x), tileY(y));
|
||||
}
|
||||
|
||||
int rawTileX(){
|
||||
return world.toTile(Core.input.mouseWorld().x);
|
||||
}
|
||||
|
||||
int rawTileY(){
|
||||
return world.toTile(Core.input.mouseWorld().y);
|
||||
}
|
||||
|
||||
int tileX(float cursorX){
|
||||
Vector2 vec = Core.input.mouseWorld(cursorX, 0);
|
||||
if(selectedBlock()){
|
||||
|
||||
@@ -302,7 +302,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
drawRequest(lineRequests.get(i));
|
||||
}
|
||||
}else if(mode == breaking){
|
||||
drawSelection(lineStartX, lineStartY, tileX, tileY);
|
||||
drawBreakSelection(lineStartX, lineStartY, tileX, tileY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,14 +95,14 @@ public class PlaceUtils{
|
||||
}else{
|
||||
endx = tilex;
|
||||
}
|
||||
}
|
||||
|
||||
if(Math.abs(endx - tilex) > maxLength){
|
||||
endx = Mathf.sign(endx - tilex) * maxLength + tilex;
|
||||
}
|
||||
if(Math.abs(endx - tilex) > maxLength){
|
||||
endx = Mathf.sign(endx - tilex) * maxLength + tilex;
|
||||
}
|
||||
|
||||
if(Math.abs(endy - tiley) > maxLength){
|
||||
endy = Mathf.sign(endy - tiley) * maxLength + tiley;
|
||||
}
|
||||
if(Math.abs(endy - tiley) > maxLength){
|
||||
endy = Mathf.sign(endy - tiley) * maxLength + tiley;
|
||||
}
|
||||
|
||||
int dx = endx - tilex, dy = endy - tiley;
|
||||
@@ -141,12 +141,12 @@ public class PlaceUtils{
|
||||
return result;
|
||||
}
|
||||
|
||||
static class NormalizeDrawResult{
|
||||
public static class NormalizeDrawResult{
|
||||
float x, y, x2, y2;
|
||||
}
|
||||
|
||||
static class NormalizeResult{
|
||||
int x, y, x2, y2, rotation;
|
||||
public static class NormalizeResult{
|
||||
public int x, y, x2, y2, rotation;
|
||||
|
||||
boolean isX(){
|
||||
return Math.abs(x2 - x) > Math.abs(y2 - y);
|
||||
|
||||
Reference in New Issue
Block a user