Mobile schematics / Randomized projector reloads

This commit is contained in:
Anuken 2019-10-31 22:44:07 -04:00
parent 3be3253a08
commit 91dc25f69d
16 changed files with 10456 additions and 10299 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

After

Width:  |  Height:  |  Size: 736 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 KiB

After

Width:  |  Height:  |  Size: 718 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 KiB

After

Width:  |  Height:  |  Size: 891 KiB

View File

@ -32,12 +32,14 @@ public class Schematics implements Loadable{
private static final byte version = 0;
private static final int padding = 2;
private static final int maxPreviewsMobile = 32;
private static final int resolution = 32;
private OptimizedByteArrayOutputStream out = new OptimizedByteArrayOutputStream(1024);
private Array<Schematic> all = new Array<>();
private OrderedMap<Schematic, FrameBuffer> previews = new OrderedMap<>();
private FrameBuffer shadowBuffer;
private long lastClearTime;
public Schematics(){
Events.on(DisposeEvent.class, e -> {
@ -144,6 +146,19 @@ public class Schematics implements Loadable{
}
public FrameBuffer getBuffer(Schematic schematic){
//dispose unneeded previews to prevent memory outage errors.
//only runs every 2 seconds
if(mobile && Time.timeSinceMillis(lastClearTime) > 1000 * 2 && previews.size > maxPreviewsMobile){
Array<Schematic> keys = previews.orderedKeys().copy();
for(int i = 0; i < previews.size - maxPreviewsMobile; i++){
//dispose and remove unneeded previews
previews.get(keys.get(i)).dispose();
previews.remove(keys.get(i));
}
//update last clear time
lastClearTime = Time.millis();
}
if(!previews.containsKey(schematic)){
Draw.blend();
Draw.reset();

View File

@ -66,23 +66,7 @@ public class DesktopInput extends InputHandler{
Core.keybinds.get(Binding.schematic_flip_y).key.name())).style(Styles.outlineLabel);
b.row();
b.table(a -> {
a.addImageTextButton("$schematic.add", Icon.saveSmall, () -> {
ui.showTextInput("$schematic.add", "$name", "", text -> {
Schematic replacement = schematics.all().find(s -> s.name().equals(text));
if(replacement != null){
ui.showConfirm("$confirm", "$schematic.replace", () -> {
schematics.overwrite(replacement, lastSchematic);
ui.showInfoFade("$schematic.saved");
ui.schematics.showInfo(replacement);
});
}else{
lastSchematic.tags.put("name", text);
schematics.add(lastSchematic);
ui.showInfoFade("$schematic.saved");
ui.schematics.showInfo(lastSchematic);
}
});
}).colspan(2).size(250f, 50f).disabled(f -> lastSchematic == null || lastSchematic.file != null);
a.addImageTextButton("$schematic.add", Icon.saveSmall, this::showSchematicSave).colspan(2).size(250f, 50f).disabled(f -> lastSchematic == null || lastSchematic.file != null);
});
}).margin(6f);
});

View File

@ -233,8 +233,28 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
selectRequests.addAll(schematics.toRequests(schem, world.toTile(player.x), world.toTile(player.y)));
}
protected void showSchematicSave(){
if(lastSchematic == null) return;
ui.showTextInput("$schematic.add", "$name", "", text -> {
Schematic replacement = schematics.all().find(s -> s.name().equals(text));
if(replacement != null){
ui.showConfirm("$confirm", "$schematic.replace", () -> {
schematics.overwrite(replacement, lastSchematic);
ui.showInfoFade("$schematic.saved");
ui.schematics.showInfo(replacement);
});
}else{
lastSchematic.tags.put("name", text);
schematics.add(lastSchematic);
ui.showInfoFade("$schematic.saved");
ui.schematics.showInfo(lastSchematic);
}
});
}
public void rotateRequests(Array<BuildRequest> requests, int direction){
int ox = rawTileX(), oy = rawTileY();
int ox = schemOriginX(), oy = schemOriginY();
requests.each(req -> {
//rotate config position
@ -269,7 +289,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
public void flipRequests(Array<BuildRequest> requests, boolean x){
int origin = (x ? rawTileX() : rawTileY()) * tilesize;
int origin = (x ? schemOriginX() : schemOriginY()) * tilesize;
requests.each(req -> {
float value = -((x ? req.x : req.y) * tilesize - origin + req.block.offset()) + origin;
@ -299,6 +319,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
});
}
protected int schemOriginX(){
return rawTileX();
}
protected int schemOriginY(){
return rawTileY();
}
/** Returns the selection request that overlaps this position, or null. */
protected BuildRequest getRequest(int x, int y){
return getRequest(x, y, 1, null);

View File

@ -2,14 +2,17 @@ package io.anuke.mindustry.input;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.func.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.input.GestureDetector.*;
import io.anuke.arc.input.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.*;
import io.anuke.arc.scene.ui.ImageButton.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.entities.*;
@ -51,7 +54,7 @@ public class MobileInput extends InputHandler implements GestureListener{
/** Whether or not the player is currently shifting all placed tiles. */
private boolean selecting;
/** Whether the player is currently in line-place mode. */
private boolean lineMode;
private boolean lineMode, schematicMode;
/** Current place mode. */
private PlaceMode mode = none;
/** Whether no recipe was available when switching to break mode. */
@ -187,8 +190,23 @@ public class MobileInput extends InputHandler implements GestureListener{
}).update(l -> l.setChecked(Core.settings.getBool("swapdiagonal")));
//rotate button
table.addImageButton(Icon.arrowSmall, Styles.clearPartiali,() -> rotation = Mathf.mod(rotation + 1, 4))
.update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center)).visible(() -> block != null && block.rotate);
table.addImageButton(Icon.arrowSmall, Styles.clearTogglePartiali, () -> {
if(block != null && block.rotate){
rotation = Mathf.mod(rotation + 1, 4);
}else{
schematicMode = !schematicMode;
if(schematicMode){
block = null;
mode = none;
}
}
}).update(i -> {
boolean arrow = block != null && block.rotate;
i.getImage().setRotationOrigin(!arrow ? 0 : rotation * 90, Align.center);
i.getStyle().imageUp = arrow ? Icon.arrowSmall : Icon.wikiSmall;
i.setChecked(!arrow && schematicMode);
});
//confirm button
table.addImageButton(Icon.checkSmall, Styles.clearPartiali, () -> {
@ -218,8 +236,10 @@ public class MobileInput extends InputHandler implements GestureListener{
@Override
public void buildUI(Group group){
Boolp schem = () -> lastSchematic != null && !selectRequests.isEmpty();
group.fill(t -> {
t.bottom().left().visible(() -> (player.isBuilding() || block != null || mode == breaking || !selectRequests.isEmpty()) && !state.is(State.menu));
t.bottom().left().visible(() -> (player.isBuilding() || block != null || mode == breaking || !selectRequests.isEmpty()) && !schem.get());
t.addImageTextButton("$cancel", Icon.cancelSmall, () -> {
player.clearBuilding();
selectRequests.clear();
@ -227,6 +247,41 @@ public class MobileInput extends InputHandler implements GestureListener{
block = null;
}).width(155f);
});
group.fill(t -> {
t.visible(schem);
t.bottom().left();
t.table(Tex.pane, b -> {
b.defaults().size(50f);
ImageButtonStyle style = Styles.clearPartiali;
b.addImageButton(Icon.floppySmall, style, this::showSchematicSave).disabled(f -> lastSchematic == null || lastSchematic.file != null);
b.addImageButton(Icon.cancelSmall, style, () -> {
selectRequests.clear();
});
b.row();
b.addImageButton(Icon.flipSmall, style, () -> flipRequests(selectRequests, true));
b.addImageButton(Icon.flipSmall, style, () -> flipRequests(selectRequests, false)).update(i -> i.getImage().setRotationOrigin(90f, Align.center));
b.row();
b.addImageButton(Icon.rotateSmall, style, () -> rotateRequests(selectRequests, 1));
}).margin(4f);
});
}
@Override
protected int schemOriginX(){
Tmp.v1.setZero();
selectRequests.each(r -> Tmp.v1.add(r.drawx(), r.drawy()));
return world.toTile(Tmp.v1.scl(1f / selectRequests.size).x);
}
@Override
protected int schemOriginY(){
Tmp.v1.setZero();
selectRequests.each(r -> Tmp.v1.add(r.drawx(), r.drawy()));
return world.toTile(Tmp.v1.scl(1f / selectRequests.size).y);
}
@Override
@ -251,8 +306,6 @@ public class MobileInput extends InputHandler implements GestureListener{
}else{
request.block.drawRequest(request, allRequests(), true);
}
//TODO
//drawRequest(request);
}
//draw list of requests
@ -331,6 +384,15 @@ public class MobileInput extends InputHandler implements GestureListener{
Draw.reset();
}
@Override
public void drawTop(){
//draw schematic selection
if(mode == schematicSelect){
drawSelection(lineStartX, lineStartY, lastLineX, lastLineY, Vars.maxSchematicSize);
}
}
@Override
protected void drawRequest(BuildRequest request){
if(request.tile() == null) return;
@ -367,11 +429,20 @@ public class MobileInput extends InputHandler implements GestureListener{
if(cursor == null || Core.scene.hasMouse(screenX, screenY)) return false;
//only begin selecting if the tapped block is a request
selecting = hasRequest(cursor) && isPlacing() && mode == placing;
selecting = hasRequest(cursor);
//call tap events
if(pointer == 0 && !selecting){
if(!tryTapPlayer(worldx, worldy) && Core.settings.getBool("keyboard")){
if(schematicMode && block == null){
mode = schematicSelect;
//engage schematic selection mode
int tileX = tileX(screenX);
int tileY = tileY(screenY);
lineStartX = tileX;
lineStartY = tileY;
lastLineX = tileX;
lastLineY = tileY;
}else if(!tryTapPlayer(worldx, worldy) && Core.settings.getBool("keyboard")){
//shoot on touch down when in keyboard mode
player.isShooting = true;
}
@ -388,6 +459,8 @@ public class MobileInput extends InputHandler implements GestureListener{
down = false;
}
selecting = false;
//place down a line if in line mode
if(lineMode){
int tileX = tileX(screenX);
@ -401,6 +474,15 @@ public class MobileInput extends InputHandler implements GestureListener{
}
lineMode = false;
}else if(mode == schematicSelect){
selectRequests.clear();
lastSchematic = schematics.create(lineStartX, lineStartY, lastLineX, lastLineY);
useSchematic(lastSchematic);
if(selectRequests.isEmpty()){
lastSchematic = null;
}
schematicMode = false;
mode = none;
}else{
Tile tile = tileAt(screenX, screenY);
@ -419,7 +501,7 @@ public class MobileInput extends InputHandler implements GestureListener{
Tile cursor = tileAt(x, y);
//ignore off-screen taps
if(cursor == null || Core.scene.hasMouse(x, y)) return false;
if(cursor == null || Core.scene.hasMouse(x, y) || schematicMode) return false;
//remove request if it's there
//long pressing enables line mode otherwise
@ -505,7 +587,6 @@ public class MobileInput extends InputHandler implements GestureListener{
//reset state when not placing
if(mode == none){
selecting = false;
lineMode = false;
}
@ -522,6 +603,22 @@ public class MobileInput extends InputHandler implements GestureListener{
mode = none;
}
//stop schematic when in block mode
if(block != null){
schematicMode = false;
}
//stop select when not in schematic mode
if(!schematicMode && mode == schematicSelect){
mode = none;
}
if(mode == schematicSelect){
lastLineX = rawTileX();
lastLineY = rawTileY();
autoPan();
}
//automatically switch to placing after a new recipe is selected
if(lastBlock != block && mode == breaking && block != null){
mode = placing;
@ -533,32 +630,7 @@ public class MobileInput extends InputHandler implements GestureListener{
//When in line mode, pan when near screen edges automatically
if(Core.input.isTouched(0)){
float screenX = Core.input.mouseX(), screenY = Core.input.mouseY();
float panX = 0, panY = 0;
if(screenX <= edgePan){
panX = -(edgePan - screenX);
}
if(screenX >= Core.graphics.getWidth() - edgePan){
panX = (screenX - Core.graphics.getWidth()) + edgePan;
}
if(screenY <= edgePan){
panY = -(edgePan - screenY);
}
if(screenY >= Core.graphics.getHeight() - edgePan){
panY = (screenY - Core.graphics.getHeight()) + edgePan;
}
vector.set(panX, panY).scl((Core.camera.width) / Core.graphics.getWidth());
vector.limit(maxPanSpeed);
//pan view
Core.camera.position.x += vector.x;
Core.camera.position.y += vector.y;
autoPan();
}
int lx = tileX(Core.input.mouseX()), ly = tileY(Core.input.mouseY());
@ -584,6 +656,35 @@ public class MobileInput extends InputHandler implements GestureListener{
}
}
protected void autoPan(){
float screenX = Core.input.mouseX(), screenY = Core.input.mouseY();
float panX = 0, panY = 0;
if(screenX <= edgePan){
panX = -(edgePan - screenX);
}
if(screenX >= Core.graphics.getWidth() - edgePan){
panX = (screenX - Core.graphics.getWidth()) + edgePan;
}
if(screenY <= edgePan){
panY = -(edgePan - screenY);
}
if(screenY >= Core.graphics.getHeight() - edgePan){
panY = (screenY - Core.graphics.getHeight()) + edgePan;
}
vector.set(panX, panY).scl((Core.camera.width) / Core.graphics.getWidth());
vector.limit(maxPanSpeed);
//pan view
Core.camera.position.x += vector.x;
Core.camera.position.y += vector.y;
}
@Override
public boolean pan(float x, float y, float deltaX, float deltaY){
if(Core.scene.hasDialog() || Core.settings.getBool("keyboard")) return false;
@ -593,7 +694,7 @@ public class MobileInput extends InputHandler implements GestureListener{
deltaY *= scale;
//can't pan in line mode with one finger or while dropping items!
if((lineMode && !Core.input.isTouched(1)) || droppingItem){
if((lineMode && !Core.input.isTouched(1)) || droppingItem || schematicMode){
return false;
}

View File

@ -40,7 +40,7 @@ public class HudFragment extends Fragment{
private Table lastUnlockTable;
private Table lastUnlockLayout;
private boolean shown = true;
private float dsize = 59;
private float dsize = 47.2f;
private float coreAttackTime;
private float lastCoreHP;
@ -65,10 +65,14 @@ public class HudFragment extends Fragment{
ImageButtonStyle style = Styles.clearTransi;
select.addImageButton(Icon.menuLarge, style, ui.paused::show);
flip = select.addImageButton(Icon.arrowUp, style, this::toggleMenus).get();
select.addImageButton(Icon.menuLargeSmall, style, ui.paused::show);
flip = select.addImageButton(Icon.arrowUpSmall, style, this::toggleMenus).get();
select.addImageButton(Icon.pause, style, () -> {
select.addImageButton(Icon.wikiSmall, style, () -> {
ui.schematics.show();
});
select.addImageButton(Icon.pauseSmall, style, () -> {
if(net.active()){
ui.listfrag.toggle();
}else{
@ -76,14 +80,14 @@ public class HudFragment extends Fragment{
}
}).name("pause").update(i -> {
if(net.active()){
i.getStyle().imageUp = Icon.players;
i.getStyle().imageUp = Icon.playersSmall;
}else{
i.setDisabled(false);
i.getStyle().imageUp = state.is(State.paused) ? Icon.play : Icon.pause;
i.getStyle().imageUp = state.is(State.paused) ? Icon.playSmall : Icon.pauseSmall;
}
}).get();
});
select.addImageButton(Icon.settings, style,() -> {
select.addImageButton(Icon.chatSmall, style,() -> {
if(net.active() && mobile){
if(ui.chatfrag.chatOpen()){
ui.chatfrag.hide();
@ -97,11 +101,11 @@ public class HudFragment extends Fragment{
}
}).update(i -> {
if(net.active() && mobile){
i.getStyle().imageUp = Icon.chat;
i.getStyle().imageUp = Icon.chatSmall;
}else{
i.getStyle().imageUp = Icon.database;
i.getStyle().imageUp = Icon.databaseSmall;
}
}).get();
});
select.addImage().color(Pal.gray).width(4f).fillY();
@ -114,7 +118,7 @@ public class HudFragment extends Fragment{
int fi = index++;
parent.addChild(elem);
elem.visible(() -> {
if(fi < 4){
if(fi < 5){
elem.setSize(size);
}else{
elem.setSize(Scl.scl(4f), size);
@ -124,7 +128,7 @@ public class HudFragment extends Fragment{
});
}
cont.add().size(dsize * 4 + 3, dsize).left();
cont.add().size(dsize * 5 + 3, dsize).left();
}
cont.row();
@ -154,7 +158,7 @@ public class HudFragment extends Fragment{
addWaveTable(waves);
addPlayButton(btable);
wavesMain.add(stack).width(dsize * 4 + 4f);
wavesMain.add(stack).width(dsize * 5 + 4f);
wavesMain.row();
wavesMain.table(Tex.button, t -> t.margin(10f).add(new Bar("boss.health", Pal.health, () -> state.boss() == null ? 0f : state.boss().healthf()).blink(Color.white))
.grow()).fillX().visible(() -> state.rules.waves && state.boss() != null).height(60f).get();
@ -578,7 +582,7 @@ public class HudFragment extends Fragment{
private void toggleMenus(){
if(flip != null){
flip.getStyle().imageUp = shown ? Icon.arrowDown : Icon.arrowUp;
flip.getStyle().imageUp = shown ? Icon.arrowDownSmall : Icon.arrowUpSmall;
}
shown = !shown;

View File

@ -238,7 +238,14 @@ public class PlacementFragment extends Fragment{
frame.row();
frame.table(Tex.pane2, blocksSelect -> {
blocksSelect.margin(4).marginTop(0);
blocksSelect.pane(blocks -> blockTable = blocks).height(194f).grow().get().setStyle(Styles.smallPane);
blocksSelect.pane(blocks -> blockTable = blocks).height(194f).update(pane -> {
if(pane.hasScroll()){
Element result = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
if(result == null || !result.isDescendantOf(pane)){
Core.scene.setScrollFocus(null);
}
}
}).grow().get().setStyle(Styles.smallPane);
blocksSelect.row();
blocksSelect.table(control.input::buildPlacementUI).name("inputTable").growX();
}).fillY().bottom().touchable(Touchable.enabled);
@ -274,7 +281,7 @@ public class PlacementFragment extends Fragment{
currentCategory = cat;
if(control.input.block != null){
if(selectedBlocks.get(currentCategory) == null){
selectFirstBlock(currentCategory);
selectedBlocks.put(currentCategory, getByCategory(currentCategory).find(this::unlocked));
}
control.input.block = selectedBlocks.get(currentCategory);
}
@ -313,16 +320,6 @@ public class PlacementFragment extends Fragment{
return returnArray;
}
Block selectFirstBlock(Category cat) {
for(Block block : getByCategory(currentCategory)){
if(unlocked(block)){
selectedBlocks.put(currentCategory, block);
return block;
}
}
return null;
}
boolean unlocked(Block block){
return !world.isZone() || data.isUnlocked(block);
}

View File

@ -139,7 +139,7 @@ public class MendProjector extends Block{
class MendEntity extends TileEntity{
float heat;
float charge;
float charge = Mathf.random(reload);
float phaseHeat;
@Override

View File

@ -139,7 +139,7 @@ public class OverdriveProjector extends Block{
class OverdriveEntity extends TileEntity{
float heat;
float charge;
float charge = Mathf.random(reload);
float phaseHeat;
@Override