Schematic export buttons, workshop support progress

This commit is contained in:
Anuken
2019-10-19 01:03:49 -04:00
parent 32edf58f75
commit 08a51d8f1b
11 changed files with 172 additions and 26 deletions

View File

@@ -16,6 +16,7 @@ screenshot.invalid = Map too large, potentially not enough memory for screenshot
gameover = Game Over gameover = Game Over
gameover.pvp = The[accent] {0}[] team is victorious! gameover.pvp = The[accent] {0}[] team is victorious!
highscore = [accent]New highscore! highscore = [accent]New highscore!
copied = Copied.
load.sound = Sounds load.sound = Sounds
load.map = Maps load.map = Maps
@@ -24,10 +25,17 @@ load.content = Content
load.system = System load.system = System
load.mod = Mods load.mod = Mods
schematic = Schematic
schematic.add = Save Schematic... schematic.add = Save Schematic...
schematics = Schematics schematics = Schematics
schematic.exportfile = Export File
schematic.copy = Copy to Clipboard
schematic.shareworkshop = Share on Workshop
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Flip Schematic schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Flip Schematic
schematic.saved = Schematic saved. schematic.saved = Schematic saved.
schematic.delete.confirm = This schematic will be utterly eradicated.
schematic.rename = Rename Schematic
schematic.info = {0}x{1}, {2} blocks
stat.wave = Waves Defeated:[accent] {0} stat.wave = Waves Defeated:[accent] {0}
stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} stat.enemiesDestroyed = Enemies Destroyed:[accent] {0}

View File

@@ -36,6 +36,11 @@ public interface Platform{
return Array.with(); return Array.with();
} }
/** Steam: Return external workshop schematics to be loaded.*/
default Array<FileHandle> getExternalSchematics(){
return Array.with();
}
/** Steam: View a map listing on the workshop.*/ /** Steam: View a map listing on the workshop.*/
default void viewMapListing(Map map){} default void viewMapListing(Map map){}

View File

@@ -305,7 +305,7 @@ public class UI implements ApplicationListener, Loadable{
} }
public void showTextInput(String title, String text, String def, Consumer<String> confirmed){ public void showTextInput(String title, String text, String def, Consumer<String> confirmed){
showTextInput(title, text, 24, def, confirmed); showTextInput(title, text, 32, def, confirmed);
} }
public void showTextInput(String titleText, String text, int textLength, String def, Consumer<String> confirmed){ public void showTextInput(String titleText, String text, int textLength, String def, Consumer<String> confirmed){

View File

@@ -1,15 +1,17 @@
package io.anuke.mindustry.game; package io.anuke.mindustry.game;
import io.anuke.arc.collection.*; import io.anuke.arc.collection.*;
import io.anuke.arc.collection.IntIntMap.*;
import io.anuke.arc.files.*; import io.anuke.arc.files.*;
import io.anuke.arc.util.ArcAnnotate.*; import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.*;
public class Schematic{ public class Schematic{
public final Array<Stile> tiles; public final Array<Stile> tiles;
public StringMap tags; public StringMap tags;
public int width, height; public int width, height;
public boolean workshop;
public @Nullable FileHandle file; public @Nullable FileHandle file;
public Schematic(Array<Stile> tiles, StringMap tags, int width, int height){ public Schematic(Array<Stile> tiles, StringMap tags, int width, int height){
@@ -19,10 +21,30 @@ public class Schematic{
this.height = height; this.height = height;
} }
public Array<ItemStack> requirements(){
IntIntMap amounts = new IntIntMap();
tiles.each(t -> {
for(ItemStack stack : t.block.requirements){
amounts.getAndIncrement(stack.item.id, 0, stack.amount);
}
});
Array<ItemStack> stacks = new Array<>();
for(Entry ent : amounts.entries()){
stacks.add(new ItemStack(Vars.content.item(ent.key), ent.value));
}
stacks.sort();
return stacks;
}
public String name(){ public String name(){
return tags.get("name", "unknown"); return tags.get("name", "unknown");
} }
public boolean isWorkshop(){
return tags.containsKey("workshop");
}
public static class Stile{ public static class Stile{
public @NonNull Block block; public @NonNull Block block;
public short x, y; public short x, y;

View File

@@ -53,21 +53,28 @@ public class Schematics implements Loadable{
/** Load all schematics in the folder immediately.*/ /** Load all schematics in the folder immediately.*/
public void load(){ public void load(){
all.clear(); all.clear();
for(FileHandle file : schematicDirectory.list()){
if(!file.extension().equals(schematicExtension)) continue;
try{ for(FileHandle file : schematicDirectory.list()){
all.add(read(file)); loadFile(file);
}catch(IOException e){
e.printStackTrace();
}
} }
platform.getExternalSchematics().each(this::loadFile);
Core.app.post(() -> { Core.app.post(() -> {
shadowBuffer = new FrameBuffer(maxSchematicSize + padding, maxSchematicSize + padding); shadowBuffer = new FrameBuffer(maxSchematicSize + padding + 2, maxSchematicSize + padding + 2);
}); });
} }
private void loadFile(FileHandle file){
if(!file.extension().equals(schematicExtension)) return;
try{
all.add(read(file));
}catch(IOException e){
Log.err(e);
}
}
public Array<Schematic> all(){ public Array<Schematic> all(){
return all; return all;
} }
@@ -159,6 +166,13 @@ public class Schematics implements Loadable{
} }
} }
public void remove(Schematic s){
all.remove(s);
if(s.file != null){
s.file.delete();
}
}
/** 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){
NormalizeResult result = PlaceUtils.normalizeArea(x, y, x2, y2, 0, false, maxSchematicSize); NormalizeResult result = PlaceUtils.normalizeArea(x, y, x2, y2, 0, false, maxSchematicSize);

View File

@@ -71,7 +71,7 @@ public class DesktopInput extends InputHandler{
lastSchematic.tags.put("name", text); lastSchematic.tags.put("name", text);
schematics.add(lastSchematic); schematics.add(lastSchematic);
ui.showInfoFade("$schematic.saved"); ui.showInfoFade("$schematic.saved");
ui.schematics.showInfo(lastSchematic); //ui.schematics.showInfo(lastSchematic);
}); });
}).colspan(2).size(250f, 50f); }).colspan(2).size(250f, 50f);
}); });

View File

@@ -1,16 +1,20 @@
package io.anuke.mindustry.ui.dialogs; package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.*; import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.graphics.*; import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.Texture.*; import io.anuke.arc.graphics.Texture.*;
import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.ImageButton.*;
import io.anuke.arc.scene.ui.TextButton.*;
import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*; import io.anuke.arc.util.*;
import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.Schematics.*; import io.anuke.mindustry.game.Schematics.*;
import io.anuke.mindustry.gen.*; import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.*; import io.anuke.mindustry.ui.*;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -39,7 +43,7 @@ public class SchematicsDialog extends FloatingDialog{
cont.table(s -> { cont.table(s -> {
s.left(); s.left();
s.addImage(Icon.zoom).color(Pal.gray); s.addImage(Icon.zoom);
s.addField(search, res -> { s.addField(search, res -> {
search = res; search = res;
rebuildPane[0].run(); rebuildPane[0].run();
@@ -54,37 +58,64 @@ public class SchematicsDialog extends FloatingDialog{
rebuildPane[0] = () -> { rebuildPane[0] = () -> {
t.clear(); t.clear();
int i = 0; int i = 0;
if(!schematics.all().contains(s -> search.isEmpty() || s.name().contains(search))){
t.add("$none");
}
for(Schematic s : schematics.all()){ for(Schematic s : schematics.all()){
if(!search.isEmpty() && !s.name().contains(search)) continue; if(!search.isEmpty() && !s.name().contains(search)) continue;
Button[] sel = {null}; Button[] sel = {null};
sel[0] = t.addButton(b -> { sel[0] = t.addButton(b -> {
b.top(); b.top();
b.margin(4f); b.margin(0f);
b.table(buttons -> { b.table(buttons -> {
buttons.left(); buttons.left();
buttons.defaults().size(50f); buttons.defaults().size(50f);
buttons.addImageButton(Icon.pencilSmall, Styles.clearPartiali, () -> {
ImageButtonStyle style = Styles.clearPartiali;
buttons.addImageButton(Icon.infoSmall, style, () -> {
showInfo(s);
}); });
buttons.addImageButton(Icon.trash16Small, Styles.clearPartiali, () -> { //if(s.isWorkshop()){
buttons.addImageButton(Icon.loadMapSmall, style, () -> {
showExport(s);
});
//}
buttons.addImageButton(Icon.pencilSmall, style, () -> {
ui.showTextInput("$schematic.rename", "$name", s.name(), res -> {
s.tags.put("name", res);
});
});
buttons.addImageButton(Icon.trash16Small, style, () -> {
ui.showConfirm("$confirm", "$schematic.delete.confirm", () -> {
schematics.remove(s);
rebuildPane[0].run();
});
}); });
}).growX().height(50f); }).growX().height(50f);
b.row(); b.row();
b.add(s.name()).center().color(Color.lightGray).top().left().get().setEllipsis(true); b.stack(new SchematicImage(s).setScaling(Scaling.fit), new Table(n -> {
b.row(); n.top();
b.add(new SchematicImage(s).setScaling(Scaling.fit).setName("border")).size(200f); n.table(Styles.black3, c -> {
Label label = c.add(s.name()).style(Styles.outlineLabel).color(Color.white).top().growX().get();
label.setEllipsis(true);
label.setAlignment(Align.center);
}).growX().margin(1).pad(4).padBottom(0);
})).size(200f);
}, () -> { }, () -> {
if(sel[0].childrenPressed()) return; if(sel[0].childrenPressed()) return;
control.input.useSchematic(s); control.input.useSchematic(s);
hide(); hide();
}).pad(4).style(Styles.cleari).get(); }).pad(4).style(Styles.cleari).get();
//BorderImage image = sel[0].find("border"); sel[0].getStyle().up = Tex.pane;
//image.update(() -> image.borderColor = (sel[0].isOver() ? Pal.accent : Pal.gray));
if(++i % 4 == 0){ if(++i % 4 == 0){
t.row(); t.row();
@@ -100,6 +131,38 @@ public class SchematicsDialog extends FloatingDialog{
info.show(schematic); info.show(schematic);
} }
public void showExport(Schematic s){
FloatingDialog dialog = new FloatingDialog("$editor.export");
dialog.cont.pane(p -> {
p.margin(10f);
p.table(Tex.button, t -> {
TextButtonStyle style = Styles.cleart;
t.defaults().size(280f, 60f).left();
t.addImageTextButton("$schematic.shareworkshop", Icon.wikiSmall, style, () -> {
}).marginLeft(12f);
t.row();
t.addImageTextButton("$schematic.copy", Icon.copySmall, style, () -> {
dialog.hide();
ui.showInfoFade("$copied");
Core.app.setClipboardText(schematics.writeBase64(s));
}).marginLeft(12f);
t.row();
t.addImageTextButton("$schematic.exportfile", Icon.saveMapSmall, style, () -> platform.showFileChooser(false, schematicExtension, file -> {
dialog.hide();
try{
Schematics.write(s, file);
}catch(Exception e){
ui.showException(e);
}
})).marginLeft(12f);
});
});
dialog.addCloseButton();
dialog.show();
}
public static class SchematicImage extends Image{ public static class SchematicImage extends Image{
public float scaling = 16f; public float scaling = 16f;
public float thickness = 4f; public float thickness = 4f;
@@ -107,21 +170,27 @@ public class SchematicsDialog extends FloatingDialog{
public SchematicImage(Schematic s){ public SchematicImage(Schematic s){
super(schematics.getPreview(s, PreviewRes.high)); super(schematics.getPreview(s, PreviewRes.high));
setScaling(Scaling.fit);
} }
@Override @Override
public void draw(){ public void draw(){
boolean checked = getParent().getParent() instanceof Button
&& ((Button)getParent().getParent()).isOver();
Texture background = Core.assets.get("sprites/schematic-background.png", Texture.class); Texture background = Core.assets.get("sprites/schematic-background.png", Texture.class);
TextureRegion region = Draw.wrap(background); TextureRegion region = Draw.wrap(background);
float xr = width / scaling; float xr = width / scaling;
float yr = height / scaling; float yr = height / scaling;
region.setU2(xr); region.setU2(xr);
region.setV2(yr); region.setV2(yr);
Draw.color();
Draw.alpha(parentAlpha);
Draw.rect(region, x + width/2f, y + height/2f, width, height); Draw.rect(region, x + width/2f, y + height/2f, width, height);
super.draw(); super.draw();
Draw.color(borderColor); Draw.color(checked ? Pal.accent : borderColor);
Draw.alpha(parentAlpha); Draw.alpha(parentAlpha);
Lines.stroke(Scl.scl(thickness)); Lines.stroke(Scl.scl(thickness));
Lines.rect(x, y, width, height); Lines.rect(x, y, width, height);
@@ -133,16 +202,31 @@ public class SchematicsDialog extends FloatingDialog{
SchematicInfoDialog(){ SchematicInfoDialog(){
super(""); super("");
setFillParent(false); setFillParent(true);
addCloseButton(); addCloseButton();
} }
public void show(Schematic schem){ public void show(Schematic schem){
cont.clear(); cont.clear();
title.setText(schem.name()); title.setText("[[" + Core.bundle.get("schematic") + "] " +schem.name());
cont.add(new BorderImage(schematics.getPreview(schem, PreviewRes.high))).maxSize(400f); cont.add(Core.bundle.format("schematic.info", schem.width, schem.height, schem.tiles.size)).color(Color.lightGray);
cont.row(); cont.row();
cont.add(new SchematicImage(schem)).maxSize(800f);
cont.row();
Array<ItemStack> arr = schem.requirements();
cont.table(r -> {
int i = 0;
for(ItemStack s : arr){
r.addImage(s.item.icon(Cicon.small)).left();
r.add(s.amount + "").padLeft(2).left().color(Color.lightGray).padRight(4);
if(++i % 4 == 0){
r.row();
}
}
});
show(); show();
} }

View File

@@ -118,7 +118,7 @@ public class Block extends BlockStorage{
public float idleSoundVolume = 0.5f; public float idleSoundVolume = 0.5f;
/** Cost of constructing this block. */ /** Cost of constructing this block. */
public ItemStack[] requirements = new ItemStack[]{}; public ItemStack[] requirements = {};
/** Category in place menu. */ /** Category in place menu. */
public Category category = Category.distribution; public Category category = Category.distribution;
/** Cost of building this block; do not modify directly! */ /** Cost of building this block; do not modify directly! */

View File

@@ -258,6 +258,12 @@ public class DesktopLauncher extends ClientLauncher{
return !steam ? super.getExternalMods() : SVars.workshop.getModFiles(); return !steam ? super.getExternalMods() : SVars.workshop.getModFiles();
} }
@Override
public Array<FileHandle> getExternalSchematics(){
return !steam ? super.getExternalMods() : SVars.workshop.getSchematicFiles();
}
@Override @Override
public void viewMapListing(Map map){ public void viewMapListing(Map map){
viewListing(map.file.parent().name()); viewListing(map.file.parent().name());

View File

@@ -23,6 +23,7 @@ public class SWorkshop implements SteamUGCCallback{
private Map lastMap; private Map lastMap;
private Array<FileHandle> mapFiles; private Array<FileHandle> mapFiles;
private Array<FileHandle> modFiles; private Array<FileHandle> modFiles;
private Array<FileHandle> schematicFiles;
private ObjectMap<SteamUGCQuery, BiConsumer<Array<SteamUGCDetails>, SteamResult>> detailHandlers = new ObjectMap<>(); private ObjectMap<SteamUGCQuery, BiConsumer<Array<SteamUGCDetails>, SteamResult>> detailHandlers = new ObjectMap<>();
public SWorkshop(){ public SWorkshop(){
@@ -37,6 +38,7 @@ public class SWorkshop implements SteamUGCCallback{
}).select(f -> f != null && f.list().length > 0); }).select(f -> f != null && f.list().length > 0);
mapFiles = folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(mapExtension)).map(f -> f.list()[0]); mapFiles = folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(mapExtension)).map(f -> f.list()[0]);
schematicFiles = folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(schematicExtension)).map(f -> f.list()[0]);
modFiles = folders.select(f -> f.child("mod.json").exists()); modFiles = folders.select(f -> f.child("mod.json").exists());
if(!mapFiles.isEmpty()){ if(!mapFiles.isEmpty()){
@@ -55,6 +57,11 @@ public class SWorkshop implements SteamUGCCallback{
return modFiles; return modFiles;
} }
public Array<FileHandle> getSchematicFiles(){
return schematicFiles;
}
public void publishMap(Map map){ public void publishMap(Map map){
if(map.tags.containsKey("steamid")){ if(map.tags.containsKey("steamid")){
Log.info("Map already published, redirecting to ID."); Log.info("Map already published, redirecting to ID.");

View File

@@ -1,3 +1,3 @@
org.gradle.daemon=true org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m org.gradle.jvmargs=-Xms256m -Xmx1024m
archash=85f95089a6521880c87e0fc011b4a09f207d360d archash=e82f446a81abba5d6f712b9053c1b84ec9a73156