Schematic flipping + rotation

This commit is contained in:
Anuken
2019-10-18 14:38:43 -04:00
parent f7d98591c9
commit 6a12effd6a
7 changed files with 114 additions and 49 deletions

View File

@@ -33,6 +33,8 @@ public class Vars implements Loadable{
public static boolean loadLocales = true; public static boolean loadLocales = true;
/** Maximum number of broken blocks. TODO implement or remove.*/ /** Maximum number of broken blocks. TODO implement or remove.*/
public static final int maxBrokenBlocks = 256; public static final int maxBrokenBlocks = 256;
/** Maximum schematic size.*/
public static final int maxSchematicSize = 32;
/** IO buffer size. */ /** IO buffer size. */
public static final int bufferSize = 8192; public static final int bufferSize = 8192;
/** global charset, since Android doesn't support the Charsets class */ /** global charset, since Android doesn't support the Charsets class */

View File

@@ -278,7 +278,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
/** Config int. Not used unless hasConfig is true.*/ /** Config int. Not used unless hasConfig is true.*/
public int config; public int config;
/** Original position, only used in schematics.*/ /** Original position, only used in schematics.*/
public int originalX, originalY; public int originalX, originalY, originalWidth, originalHeight;
/** Last progress.*/ /** Last progress.*/
public float progress; public float progress;
@@ -327,9 +327,11 @@ public interface BuilderTrait extends Entity, TeamTrait{
return copy; return copy;
} }
public BuildRequest original(int x, int y){ public BuildRequest original(int x, int y, int originalWidth, int originalHeight){
originalX = x; originalX = x;
originalY = y; originalY = y;
this.originalWidth = originalWidth;
this.originalHeight = originalHeight;
return this; return this;
} }

View File

@@ -15,6 +15,8 @@ import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.traits.BuilderTrait.*; import io.anuke.mindustry.entities.traits.BuilderTrait.*;
import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.Schematic.*; 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.type.*;
import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.*;
@@ -29,7 +31,6 @@ public class Schematics implements Loadable{
private static final byte version = 0; private static final byte version = 0;
private static final int padding = 2; private static final int padding = 2;
private static final int maxSize = 64;
private OptimizedByteArrayOutputStream out = new OptimizedByteArrayOutputStream(1024); private OptimizedByteArrayOutputStream out = new OptimizedByteArrayOutputStream(1024);
private Array<Schematic> all = new Array<>(); private Array<Schematic> all = new Array<>();
@@ -63,7 +64,7 @@ public class Schematics implements Loadable{
} }
Core.app.post(() -> { 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. */ /** 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){ 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.*/ /** 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. */ /** Creates a schematic from a world selection. */
public Schematic create(int x, int y, int x2, int y2){ public Schematic create(int x, int y, int x2, int y2){
if(x > x2){ NormalizeResult result = PlaceUtils.normalizeArea(x, y, x2, y2, 0, false, maxSchematicSize);
int temp = x; x = result.x;
x = x2; y = result.y;
x2 = temp; x2 = result.x2;
} y2 = result.y2;
if(y > y2){
int temp = y;
y = y2;
y2 = temp;
}
Array<Stile> tiles = new Array<>(); Array<Stile> tiles = new Array<>();

View File

@@ -10,6 +10,7 @@ import io.anuke.arc.scene.*;
import io.anuke.arc.scene.event.*; import io.anuke.arc.scene.event.*;
import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.*;
import io.anuke.arc.util.ArcAnnotate.*; import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.core.GameState.*; import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.entities.traits.BuilderTrait.*; import io.anuke.mindustry.entities.traits.BuilderTrait.*;
import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.EventType.*;
@@ -91,7 +92,7 @@ public class DesktopInput extends InputHandler{
drawRequest(lineRequests.get(i)); drawRequest(lineRequests.get(i));
} }
}else if(mode == breaking){ }else if(mode == breaking){
drawSelection(selectX, selectY, cursorX, cursorY); drawBreakSelection(selectX, selectY, cursorX, cursorY);
}else if(isPlacing()){ }else if(isPlacing()){
if(block.rotate){ if(block.rotate){
drawArrow(block, cursorX, cursorY, rotation); drawArrow(block, cursorX, cursorY, rotation);
@@ -126,10 +127,7 @@ public class DesktopInput extends InputHandler{
} }
if(Core.input.keyDown(Binding.schematic)){ if(Core.input.keyDown(Binding.schematic)){
Lines.stroke(2f); drawSelection(schemX, schemY, cursorX, cursorY, Vars.maxSchematicSize);
Draw.color(Pal.accent);
Lines.rect(schemX * tilesize, schemY * tilesize, (cursorX - schemX) * tilesize, (cursorY - schemY) * tilesize);
} }
Draw.reset(); Draw.reset();
@@ -156,7 +154,7 @@ public class DesktopInput extends InputHandler{
if(state.is(State.menu) || Core.scene.hasDialog()) return; if(state.is(State.menu) || Core.scene.hasDialog()) return;
//zoom things //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)); 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); 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){ if(!Core.input.keyDown(Binding.zoom_hold) && Math.abs((int)Core.input.axisTap(Binding.rotate)) > 0){
updateLine(selectX, selectY); if(isPlacing() && mode == placing){
}else if(Math.abs((int)Core.input.axisTap(Binding.rotate)) > 0 && !selectRequests.isEmpty()){ updateLine(selectX, selectY);
rotateRequests(selectRequests, (int)Core.input.axisTap(Binding.rotate)); }else if(!selectRequests.isEmpty()){
rotateRequests(selectRequests, (int)Core.input.axisTap(Binding.rotate));
}
} }
Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY()); 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 //TODO remove
if(Core.input.keyTap(KeyCode.V)){ if(Core.input.keyTap(KeyCode.V)){
ui.schematics.show(); ui.schematics.show();

View File

@@ -227,11 +227,25 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
} }
public void rotateRequests(Array<BuildRequest> requests, int direction){ public void rotateRequests(Array<BuildRequest> requests, int direction){
int ox = tileX(getMouseX()), oy = tileY(getMouseY()); int ox = rawTileX(), oy = rawTileY();
requests.each(req -> { requests.each(req -> {
//req.x -= ox; //rotate config position
//req.y -= oy; 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 wx = (req.x - ox) * tilesize + req.block.offset(), wy = (req.y - oy) * tilesize + req.block.offset();
float x = wx; float x = wx;
if(direction >= 0){ if(direction >= 0){
@@ -243,7 +257,38 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
} }
req.x = world.toTile(wx - req.block.offset()) + ox; req.x = world.toTile(wx - req.block.offset()) + ox;
req.y = world.toTile(wy - req.block.offset()) + oy; 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; 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); NormalizeDrawResult result = PlaceUtils.normalizeDrawArea(Blocks.air, x1, y1, x2, y2, false, maxLength, 1f);
NormalizeResult dresult = PlaceUtils.normalizeArea(x1, y1, x2, y2, rotation, false, maxLength); 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); 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){ protected void flushSelectRequests(Array<BuildRequest> requests){
for(BuildRequest req : requests){ for(BuildRequest req : requests){
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){ 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){ if(!showedInventory){
frag.inv.hide(); frag.inv.hide();
} }
@@ -531,6 +579,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
return world.tile(tileX(x), tileY(y)); 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){ int tileX(float cursorX){
Vector2 vec = Core.input.mouseWorld(cursorX, 0); Vector2 vec = Core.input.mouseWorld(cursorX, 0);
if(selectedBlock()){ if(selectedBlock()){

View File

@@ -302,7 +302,7 @@ public class MobileInput extends InputHandler implements GestureListener{
drawRequest(lineRequests.get(i)); drawRequest(lineRequests.get(i));
} }
}else if(mode == breaking){ }else if(mode == breaking){
drawSelection(lineStartX, lineStartY, tileX, tileY); drawBreakSelection(lineStartX, lineStartY, tileX, tileY);
} }
} }

View File

@@ -95,14 +95,14 @@ public class PlaceUtils{
}else{ }else{
endx = tilex; endx = tilex;
} }
}
if(Math.abs(endx - tilex) > maxLength){ if(Math.abs(endx - tilex) > maxLength){
endx = Mathf.sign(endx - tilex) * maxLength + tilex; endx = Mathf.sign(endx - tilex) * maxLength + tilex;
} }
if(Math.abs(endy - tiley) > maxLength){ if(Math.abs(endy - tiley) > maxLength){
endy = Mathf.sign(endy - tiley) * maxLength + tiley; endy = Mathf.sign(endy - tiley) * maxLength + tiley;
}
} }
int dx = endx - tilex, dy = endy - tiley; int dx = endx - tilex, dy = endy - tiley;
@@ -141,12 +141,12 @@ public class PlaceUtils{
return result; return result;
} }
static class NormalizeDrawResult{ public static class NormalizeDrawResult{
float x, y, x2, y2; float x, y, x2, y2;
} }
static class NormalizeResult{ public static class NormalizeResult{
int x, y, x2, y2, rotation; public int x, y, x2, y2, rotation;
boolean isX(){ boolean isX(){
return Math.abs(x2 - x) > Math.abs(y2 - y); return Math.abs(x2 - x) > Math.abs(y2 - y);