mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-10-01 10:40:38 +03:00
Generate icons for content in data patch editor
This commit is contained in:
@@ -173,7 +173,7 @@ public abstract class UnlockableContent extends MappableContent{
|
||||
if(!makeNew || !packer.has(name + "-outline")){
|
||||
String regName = name + (makeNew ? "-outline" : "");
|
||||
if(packer.registerOutlined(regName)){
|
||||
PixmapRegion base = Core.atlas.getPixmap(region);
|
||||
PixmapRegion base = packer.get(region);
|
||||
var result = Pixmaps.outline(base, outlineColor, outlineRadius);
|
||||
Drawf.checkBleed(result);
|
||||
packer.add(page, regName, result);
|
||||
@@ -185,7 +185,7 @@ public abstract class UnlockableContent extends MappableContent{
|
||||
|
||||
protected void makeOutline(MultiPacker packer, TextureRegion region, String name, Color outlineColor, int outlineRadius){
|
||||
if(region.found() && packer.registerOutlined(name)){
|
||||
PixmapRegion base = Core.atlas.getPixmap(region);
|
||||
PixmapRegion base = packer.get(region);
|
||||
var result = Pixmaps.outline(base, outlineColor, outlineRadius);
|
||||
Drawf.checkBleed(result);
|
||||
packer.add(PageType.main, name, result);
|
||||
|
||||
@@ -116,6 +116,7 @@ public class MapAssetsDialog extends BaseDialog{
|
||||
//make sure new assets appear correctly when switching to the content view
|
||||
if(type == DataAssetType.content){
|
||||
state.data.reloadContent(false);
|
||||
state.data.regenerateContentSprites(false);
|
||||
}
|
||||
|
||||
rebuild();
|
||||
@@ -153,6 +154,9 @@ public class MapAssetsDialog extends BaseDialog{
|
||||
Seq<DataAsset> results = new Seq<>();
|
||||
Fi zipped = new ZipFi(targetFile);
|
||||
Seq<String> errors = new Seq<>();
|
||||
//force regen
|
||||
state.data.clearGeneratedImages();
|
||||
|
||||
for(var type : DataAssetType.all){
|
||||
Fi folder = zipped.child(type.folder);
|
||||
|
||||
@@ -208,6 +212,10 @@ public class MapAssetsDialog extends BaseDialog{
|
||||
prev.addAll(results);
|
||||
prev.sort();
|
||||
state.data.load(prev);
|
||||
if(state.data.getContent().size > 0){
|
||||
//TODO: packs twice (bad)
|
||||
state.data.regenerateContentSprites(false);
|
||||
}
|
||||
rebuild();
|
||||
}
|
||||
|
||||
@@ -219,7 +227,7 @@ public class MapAssetsDialog extends BaseDialog{
|
||||
ep.add(Seq.with(errors).toString("\n", s -> "[gray]- []" + s)).labelAlign(Align.left, Align.left).grow();
|
||||
});
|
||||
}else if(results.size == 0){
|
||||
idiag.cont.add("@asset.image.none");
|
||||
idiag.cont.add("@asset.import.none");
|
||||
}
|
||||
idiag.buttons.button("@ok", Icon.ok, idiag::hide).size(200f, 64f);
|
||||
idiag.show();
|
||||
|
||||
@@ -102,8 +102,11 @@ public class MapContentView implements AssetView{
|
||||
list.button(Icon.refresh, Styles.graySquarei, Vars.iconMed, () -> {
|
||||
Cons<String> handler = str -> {
|
||||
content.data = str;
|
||||
state.data.reloadContent(false);
|
||||
diag.rebuild();
|
||||
ui.loadAnd(() -> {
|
||||
state.data.reloadContent(false);
|
||||
state.data.regenerateContentSprites(false);
|
||||
diag.rebuild();
|
||||
});
|
||||
};
|
||||
|
||||
BaseDialog dialog = new BaseDialog("@editor.import");
|
||||
@@ -176,10 +179,14 @@ public class MapContentView implements AssetView{
|
||||
buttons.button("@add", Icon.add, () -> showImport(diag)).size(190f, 64f);
|
||||
}
|
||||
|
||||
void addContent(ContentType type, String path, String data){
|
||||
ContentAsset asset = new ContentAsset(path, type, data);
|
||||
state.data.getContent().add(asset);
|
||||
state.data.reloadContent(false);
|
||||
void addContent(MapAssetsDialog diag, ContentType type, String path, String data){
|
||||
ui.loadAnd(() -> {
|
||||
ContentAsset asset = new ContentAsset(path, type, data);
|
||||
state.data.getContent().add(asset);
|
||||
state.data.reloadContent(false);
|
||||
state.data.regenerateContentSprites(false);
|
||||
diag.rebuild();
|
||||
});
|
||||
}
|
||||
|
||||
void showImport(MapAssetsDialog diag){
|
||||
@@ -220,7 +227,7 @@ public class MapContentView implements AssetView{
|
||||
|
||||
choose.buttons.button("@asset.content.import.file", Icon.fileText, () -> FileChooser.open("json", "json5", "hjson").submit(file -> {
|
||||
choose.hide();
|
||||
addContent(selected[0], nameField.getText() + ".json", file.readString());
|
||||
addContent(diag, selected[0], nameField.getText() + ".json", file.readString());
|
||||
diag.rebuild();
|
||||
})).size(200f, 64f).disabled(b -> nameField.getText().isEmpty() || invalid[0]);
|
||||
|
||||
@@ -229,8 +236,7 @@ public class MapContentView implements AssetView{
|
||||
if(text == null) return;
|
||||
|
||||
choose.hide();
|
||||
addContent(selected[0], nameField.getText() + ".json", text);
|
||||
diag.rebuild();
|
||||
addContent(diag, selected[0], nameField.getText() + ".json", text);
|
||||
}).size(200f, 64f).disabled(b -> nameField.getText().isEmpty() || invalid[0] || Core.app.getClipboardText() == null);
|
||||
choose.show();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public class MapImagesView implements AssetView{
|
||||
buttons.button("@add", Icon.add, () -> {
|
||||
FileChooser.open("png", "jpeg", "jpg").submitMulti(results -> {
|
||||
var images = getImages();
|
||||
state.data.clearGeneratedImages();
|
||||
|
||||
for(var result : results){
|
||||
try{
|
||||
@@ -49,14 +50,13 @@ public class MapImagesView implements AssetView{
|
||||
|
||||
String name = result.nameWithoutExtension();
|
||||
String path = result.name();
|
||||
var other = images.find(p -> (p.path.equalsIgnoreCase(path) || p.name.equalsIgnoreCase(name)));
|
||||
var other = images.find(p -> p.path.equalsIgnoreCase(path) || p.name.equalsIgnoreCase(name));
|
||||
if(other != null){
|
||||
ui.showErrorMessage(Core.bundle.format("asset.image.exists", other.name + " (" + other.path + ")"));
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] hash = assetCache.add(bytes);
|
||||
|
||||
images.add(new ImageAsset(path, hash));
|
||||
}catch(Exception e){
|
||||
ui.showException(e);
|
||||
@@ -64,7 +64,7 @@ public class MapImagesView implements AssetView{
|
||||
}
|
||||
|
||||
images.sort();
|
||||
state.data.reloadImages(images);
|
||||
state.data.regenerateContentSprites(true);
|
||||
diag.rebuild();
|
||||
});
|
||||
}).size(190f, 64f);
|
||||
@@ -132,6 +132,8 @@ public class MapImagesView implements AssetView{
|
||||
zipped.delete(); //closes the zip file
|
||||
int imported = 0;
|
||||
|
||||
state.data.clearGeneratedImages();
|
||||
|
||||
for(var future : images){
|
||||
var image = (Result)future.get();
|
||||
if(image != null){
|
||||
@@ -141,11 +143,12 @@ public class MapImagesView implements AssetView{
|
||||
}
|
||||
|
||||
String path = image.path.pathWithoutExtension(), name = image.path.nameWithoutExtension();
|
||||
var other = getImages().find(op -> (op.path.equalsIgnoreCase(path) || op.name.equalsIgnoreCase(name)));
|
||||
var other = getImages().find(op -> !op.isGenerated() && (op.path.equalsIgnoreCase(path) || op.name.equalsIgnoreCase(name)));
|
||||
if(other != null){
|
||||
errors.add("[accent]" + image.path + "[white]: " + Core.bundle.format("asset.image.exists", other.name + " (" + other.path + ")").replace("\n", " "));
|
||||
continue;
|
||||
}
|
||||
getImages().removeAll(i -> i.isGenerated() && i.name.equals(name));
|
||||
getImages().add(new ImageAsset(path, image.hash));
|
||||
imported ++;
|
||||
}
|
||||
@@ -154,6 +157,7 @@ public class MapImagesView implements AssetView{
|
||||
getImages().sort();
|
||||
|
||||
state.data.reloadImages(getImages());
|
||||
state.data.regenerateContentSprites(true);
|
||||
diag.rebuild();
|
||||
|
||||
var idiag = new BaseDialog("@asset.image.imports");
|
||||
@@ -211,7 +215,10 @@ public class MapImagesView implements AssetView{
|
||||
int cols = (int)Math.max(1, Core.graphics.getWidth() / Scl.scl(size + 12f));
|
||||
int i = 0;
|
||||
for(var image : getImages()){
|
||||
//showing generated images is confusing, so don't.
|
||||
if(image.isGenerated()) continue;
|
||||
if(diag.searchString != null && !image.path.toLowerCase().contains(diag.searchString)) continue;
|
||||
|
||||
TextureRegion region = Core.atlas.find(regionPrefix + image.name, "nomap");
|
||||
boolean found = Core.atlas.has(regionPrefix + image.name);
|
||||
@Nullable Fi cacheFile = image.getCacheFile();
|
||||
@@ -254,10 +261,12 @@ public class MapImagesView implements AssetView{
|
||||
var istyle = Styles.emptyi;
|
||||
b.button(Icon.pencil, istyle, () -> {
|
||||
ui.showTextInput("@save.rename", "@patch.path", image.path, res -> {
|
||||
if(!res.endsWith(".png")) res = res + ".png";
|
||||
|
||||
Fi fi = new Fi(res);
|
||||
String name = fi.nameWithoutExtension();
|
||||
String path = fi.pathWithoutExtension();
|
||||
var other = getImages().find(p -> p != image && (p.path.equalsIgnoreCase(path) || p.name.equalsIgnoreCase(name)));
|
||||
var other = getImages().find(p -> p != image && !p.isGenerated() && (p.path.equalsIgnoreCase(path) || p.name.equalsIgnoreCase(name)));
|
||||
if(other != null){
|
||||
ui.showErrorMessage(Core.bundle.format("asset.image.exists", other.name + " (" + other.path + ")"));
|
||||
}else{
|
||||
@@ -269,7 +278,7 @@ public class MapImagesView implements AssetView{
|
||||
at.name = regionPrefix + name;
|
||||
}
|
||||
|
||||
image.setPath(path);
|
||||
image.setPath(fi.path());
|
||||
image.name = name;
|
||||
diag.rebuild();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.graphics;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.graphics.g2d.*;
|
||||
@@ -9,17 +10,31 @@ import arc.util.Log.*;
|
||||
import mindustry.*;
|
||||
|
||||
public class MultiPacker implements Disposable{
|
||||
private PixmapPacker[] packers = new PixmapPacker[PageType.all.length];
|
||||
private PixmapPacker[] packers;
|
||||
private ObjectSet<String> outlined = new ObjectSet<>();
|
||||
|
||||
public MultiPacker(){
|
||||
for(int i = 0; i < packers.length; i++){
|
||||
packers[i] = new PixmapPacker(Math.min(Vars.maxTextureSize, PageType.all[i].width), Math.min(Vars.maxTextureSize, PageType.all[i].height), 2, true);
|
||||
this(true);
|
||||
}
|
||||
|
||||
public MultiPacker(boolean initialize){
|
||||
if(initialize){
|
||||
packers = new PixmapPacker[PageType.all.length];
|
||||
for(int i = 0; i < packers.length; i++){
|
||||
packers[i] = new PixmapPacker(Math.min(Vars.maxTextureSize, PageType.all[i].width), Math.min(Vars.maxTextureSize, PageType.all[i].height), 2, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PixmapRegion get(String name){
|
||||
public PixmapRegion get(TextureRegion region){
|
||||
return Core.atlas.getPixmap(region);
|
||||
}
|
||||
|
||||
public PixmapRegion get(String region){
|
||||
return Core.atlas.getPixmap(region);
|
||||
}
|
||||
|
||||
public @Nullable PixmapRegion getPacked(String name){
|
||||
for(var packer : packers){
|
||||
var region = packer.getRegion(name);
|
||||
if(region != null){
|
||||
@@ -59,10 +74,6 @@ public class MultiPacker implements Disposable{
|
||||
return outlined.contains(name);
|
||||
}
|
||||
|
||||
public PixmapPacker getPacker(PageType type){
|
||||
return packers[type.ordinal()];
|
||||
}
|
||||
|
||||
public boolean has(String name){
|
||||
for(var page : PageType.all){
|
||||
if(packers[page.ordinal()].getRect(name) != null){
|
||||
@@ -97,6 +108,7 @@ public class MultiPacker implements Disposable{
|
||||
|
||||
@Override
|
||||
public void dispose(){
|
||||
if(packers == null) return;
|
||||
for(int i = 0; i < PageType.all.length; i ++){
|
||||
var packer = packers[i];
|
||||
//the UI packer's image is later used when merging with the font, don't dispose it
|
||||
|
||||
@@ -70,8 +70,27 @@ public class DataImagePacker{
|
||||
TextureRegion envReserveRegion = Core.atlas.find("data-patch-reserved-env");
|
||||
PixmapPacker envPacker = anyEnv ? new PixmapPacker(envReserveRegion.width, envReserveRegion.height, 2, true) : null;
|
||||
|
||||
var tasks = new Seq<Future<?>>();
|
||||
Seq<ImageAsset> toPack = new Seq<>(), pending = new Seq<>();
|
||||
ObjectSet<String> generatedNames = new ObjectSet<>();
|
||||
|
||||
//this makes sure that generated images are prioritized
|
||||
for(var image : images){
|
||||
if(image.isGenerated()){
|
||||
generatedNames.add(image.name);
|
||||
toPack.add(image);
|
||||
}else{
|
||||
pending.add(image);
|
||||
}
|
||||
}
|
||||
|
||||
for(var image : pending){
|
||||
if(!generatedNames.contains(image.name)){
|
||||
toPack.add(image);
|
||||
}
|
||||
}
|
||||
|
||||
var tasks = new Seq<Future<?>>();
|
||||
for(var image : toPack){
|
||||
tasks.add(Vars.mainExecutor.submit(() -> {
|
||||
Fi cacheFile = image.getCacheFile();
|
||||
//logged elsewhere
|
||||
@@ -131,7 +150,7 @@ public class DataImagePacker{
|
||||
|
||||
printStats(packer, envPacker);
|
||||
|
||||
packer.dispose();
|
||||
packer.forceDispose();
|
||||
//textures are never updated, so force disposal
|
||||
if(envPacker != null) envPacker.forceDispose();
|
||||
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
package mindustry.mod;
|
||||
|
||||
import arc.files.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.g2d.TextureAtlas.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.mod.data.*;
|
||||
|
||||
public class DataManager{
|
||||
@@ -22,6 +29,139 @@ public class DataManager{
|
||||
rebuildOrderedAssets();
|
||||
}
|
||||
|
||||
public void regenerateContentSprites(boolean forcePack){
|
||||
var allContent = patcher.getAddedContent();
|
||||
|
||||
//TODO: what to do when headless (server?)
|
||||
if(allContent.isEmpty()){
|
||||
if(forcePack) reloadImages();
|
||||
return;
|
||||
}
|
||||
|
||||
Seq<UnlockableContent> contentToPack = allContent.select(c -> c instanceof UnlockableContent && c.minfo.asset != null).as();
|
||||
ObjectSet<String> existingContentHashes = new ObjectSet<>();
|
||||
ObjectSet<String> imagesWithHashes = new ObjectSet<>();
|
||||
ObjectMap<UnlockableContent, String> hashes = new ObjectMap<>();
|
||||
|
||||
//store hashes based on JSON contents
|
||||
for(var content : contentToPack){
|
||||
String hash = content.minfo.asset.hashData();
|
||||
hashes.put(content, hash);
|
||||
existingContentHashes.add(hash);
|
||||
}
|
||||
|
||||
var images = getImages();
|
||||
images.removeAll(i -> {
|
||||
if(i.isGenerated()){
|
||||
Fi file = new Fi(i.path);
|
||||
String imageToContentHash = file.parent().name();
|
||||
imagesWithHashes.add(imageToContentHash);
|
||||
//don't remove images that correspond to content that exists with that hash
|
||||
return !existingContentHashes.contains(imageToContentHash);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
//remove content that doesn't need to be packed
|
||||
contentToPack.removeAll(u -> imagesWithHashes.contains(hashes.get(u)));
|
||||
|
||||
ObjectMap<String, ImageAsset> imageMap = new ObjectMap<>();
|
||||
for(var image : images){
|
||||
imageMap.put(DataImagePacker.regionPrefix + image.name, image);
|
||||
}
|
||||
int[] packed = {0};
|
||||
ObjectMap<String, PixmapRegion> imagePixmaps = new ObjectMap<>();
|
||||
PixmapRegion error = new PixmapRegion(Pixmaps.blankPixmap());
|
||||
UnlockableContent[] currentContent = {null};
|
||||
String[] currentHash = {null};
|
||||
|
||||
MultiPacker saver = new MultiPacker(false){
|
||||
@Override
|
||||
public void add(PageType type, String name, PixmapRegion region, int[] splits, int[] pads){
|
||||
try{
|
||||
if(region.pixmap.width > 2000) throw new IllegalArgumentException("Max image size exceeded");
|
||||
|
||||
//strip duplicate prefix
|
||||
if(name.startsWith(DataImagePacker.regionPrefix)) name = name.substring(DataImagePacker.regionPrefix.length());
|
||||
String path = "generated/" + currentHash[0] + "/" + name + ".png";
|
||||
ImageAsset newImage = new ImageAsset();
|
||||
newImage.setPath(path);
|
||||
//it would be nice to do this async, but the pixmap typically gets disposed right after add() exist
|
||||
byte[] bytes = PixmapIO.writePngBytes(region.pixmap);
|
||||
newImage.updateData(bytes);
|
||||
|
||||
images.add(newImage);
|
||||
packed[0] ++;
|
||||
}catch(Exception e){
|
||||
Log.err("Failed to pack image " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String name){
|
||||
return imageMap.containsKey(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(PageType type, String name){
|
||||
return has(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PixmapRegion get(TextureRegion region){
|
||||
return get(((AtlasRegion)region).name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PixmapRegion get(String name){
|
||||
var pix = imagePixmaps.get(name);
|
||||
if(pix != null) return pix;
|
||||
|
||||
var image = imageMap.get(name);
|
||||
if(image == null) return error;
|
||||
|
||||
try{
|
||||
var result = new PixmapRegion(new Pixmap(image.getCacheFileNoNull()));
|
||||
imagePixmaps.put(name, result);
|
||||
return result;
|
||||
}catch(Exception e){
|
||||
Log.err("Failed loading image: " + image.path, e);
|
||||
imagePixmaps.put(name, error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for(var content : contentToPack){
|
||||
currentContent[0] = content;
|
||||
currentHash[0] = hashes.get(content);
|
||||
|
||||
try{
|
||||
content.createIcons(saver);
|
||||
}catch(Throwable e){
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
|
||||
imagePixmaps.each((key, val) -> val.pixmap.dispose());
|
||||
error.pixmap.dispose();
|
||||
|
||||
if(packed[0] > 0 || forcePack){
|
||||
reloadImages();
|
||||
|
||||
if(!Vars.headless){
|
||||
for(var cont : contentToPack){
|
||||
try{
|
||||
cont.loadIcon();
|
||||
cont.load();
|
||||
}catch(Exception e){
|
||||
Log.err("Failed to load icons for " + cont, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadPatches(Seq<PatchAsset> patches){
|
||||
if(patches != getPatches()) getPatches().set(patches);
|
||||
|
||||
@@ -31,13 +171,17 @@ public class DataManager{
|
||||
rebuildOrderedAssets();
|
||||
}
|
||||
|
||||
public void reloadImages(){
|
||||
packer.unload();
|
||||
packer.pack(getImages());
|
||||
|
||||
rebuildOrderedAssets();
|
||||
}
|
||||
|
||||
public void reloadImages(Seq<ImageAsset> images){
|
||||
if(images != getImages()) getImages().set(images);
|
||||
|
||||
packer.unload();
|
||||
packer.pack(images);
|
||||
|
||||
rebuildOrderedAssets();
|
||||
reloadImages();
|
||||
}
|
||||
|
||||
public void reloadAudio(){
|
||||
@@ -134,6 +278,10 @@ public class DataManager{
|
||||
return assets.get(type, Seq::new).as();
|
||||
}
|
||||
|
||||
public void clearGeneratedImages(){
|
||||
getImages().removeAll(ImageAsset::isGenerated);
|
||||
}
|
||||
|
||||
public Seq<ImageAsset> getImages(){
|
||||
return getAssets(DataAssetType.image);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ public class DataPatcher{
|
||||
private Seq<Runnable> resetters = new Seq<>();
|
||||
private Seq<Runnable> afterCallbacks = new Seq<>();
|
||||
private Seq<Object> visitStack = new Seq<>();
|
||||
private Seq<Content> addedContent = new Seq<>();
|
||||
private @Nullable PatchAsset currentlyApplyingPatch;
|
||||
private @Nullable ContentAsset currentlyApplyingContent;
|
||||
private Seq<LVar> addedVars = new Seq<>();
|
||||
@@ -203,7 +204,9 @@ public class DataPatcher{
|
||||
Vars.content.remove(errored);
|
||||
}
|
||||
|
||||
Seq<Content> all = new Seq<>();
|
||||
addedContent.clear();
|
||||
Seq<Content> all = addedContent;
|
||||
|
||||
for(var arr : Vars.content.getContentMap()){
|
||||
all.addAll(arr.select(c -> c.minfo.mod == dpMod));
|
||||
}
|
||||
@@ -287,10 +290,15 @@ public class DataPatcher{
|
||||
afterCallbacks.each(Runnable::run);
|
||||
afterCallbacks.clear();
|
||||
usedpatches.clear();
|
||||
addedContent.clear();
|
||||
|
||||
if(reloadContentWorld) fixContentArrays();
|
||||
}
|
||||
|
||||
public Seq<Content> getAddedContent(){
|
||||
return addedContent;
|
||||
}
|
||||
|
||||
void callContentRemove(){
|
||||
for(var arr : Vars.content.getContentMap()){
|
||||
for(var value : arr){
|
||||
|
||||
@@ -263,7 +263,7 @@ public class Mods implements Loadable{
|
||||
|
||||
@Override
|
||||
public AtlasRegion find(String name){
|
||||
var base = packer.get(name);
|
||||
var base = packer.getPacked(name);
|
||||
|
||||
if(base != null){
|
||||
var reg = new AtlasRegion(shadow.find(name).texture, base.x, base.y, base.width, base.height);
|
||||
@@ -287,15 +287,15 @@ public class Mods implements Loadable{
|
||||
|
||||
@Override
|
||||
public boolean has(String s){
|
||||
return shadow.has(s) || packer.get(s) != null;
|
||||
return shadow.has(s) || packer.getPacked(s) != null;
|
||||
}
|
||||
|
||||
//return the *actual* pixmap regions, not the disposed ones.
|
||||
@Override
|
||||
public PixmapRegion getPixmap(AtlasRegion region){
|
||||
PixmapRegion out = packer.get(region.name);
|
||||
PixmapRegion out = packer.getPacked(region.name);
|
||||
//this should not happen in normal situations
|
||||
if(out == null) return packer.get("error");
|
||||
if(out == null) return packer.getPacked("error");
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ import arc.files.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.mod.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@@ -31,6 +32,10 @@ public class ContentAsset extends DataAsset{
|
||||
public ContentAsset(){
|
||||
}
|
||||
|
||||
public String hashData(){
|
||||
return type.name() + "_" + DataAssetCache.encodeHash(Strings.sha256(data));
|
||||
}
|
||||
|
||||
public void readOverride(String path, Fi file, ContentType type) throws IOException{
|
||||
this.type = type;
|
||||
setPath(path);
|
||||
|
||||
@@ -9,6 +9,10 @@ public class ImageAsset extends DataAsset{
|
||||
setHash(hash);
|
||||
}
|
||||
|
||||
public boolean isGenerated(){
|
||||
return path.startsWith("generated/");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataAssetType getType(){
|
||||
return DataAssetType.image;
|
||||
|
||||
@@ -129,7 +129,7 @@ public class Item extends UnlockableContent implements Senseable{
|
||||
var pixmaps = new PixmapRegion[frames];
|
||||
|
||||
for(int i = 0; i < frames; i++){
|
||||
pixmaps[i] = Core.atlas.getPixmap(name + (i + 1));
|
||||
pixmaps[i] = packer.get(name + (i + 1));
|
||||
}
|
||||
|
||||
for(int i = 0; i < frames; i++){
|
||||
|
||||
@@ -1232,7 +1232,7 @@ public class UnitType extends UnlockableContent implements Senseable{
|
||||
for(var region : toOutline){
|
||||
if(region instanceof AtlasRegion atlas && !Core.atlas.has(atlas.name + "-outline")){
|
||||
String regionName = atlas.name;
|
||||
Pixmap outlined = Pixmaps.outline(Core.atlas.getPixmap(region), outlineColor, outlineRadius);
|
||||
Pixmap outlined = Pixmaps.outline(packer.get(region), outlineColor, outlineRadius);
|
||||
|
||||
Drawf.checkBleed(outlined);
|
||||
|
||||
@@ -1268,7 +1268,7 @@ public class UnitType extends UnlockableContent implements Senseable{
|
||||
}
|
||||
|
||||
if(sample instanceof Tankc){
|
||||
PixmapRegion pix = Core.atlas.getPixmap(treadRegion);
|
||||
PixmapRegion pix = packer.get(treadRegion);
|
||||
|
||||
for(int r = 0; r < treadRects.length; r++){
|
||||
Rect treadRect = treadRects[r];
|
||||
|
||||
@@ -1538,7 +1538,7 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
super.createIcons(packer);
|
||||
|
||||
if(!synthetic()){
|
||||
PixmapRegion image = Core.atlas.getPixmap(fullIcon);
|
||||
PixmapRegion image = packer.get(fullIcon);
|
||||
mapColor.set(image.get(image.width/2, image.height/2));
|
||||
}
|
||||
|
||||
@@ -1549,7 +1549,7 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
for(Team team : Team.all){
|
||||
//if there's an override, don't generate anything
|
||||
if(team.hasPalette && !Core.atlas.has(name + "-team-" + team.name)){
|
||||
var base = Core.atlas.getPixmap(teamRegion);
|
||||
var base = packer.get(teamRegion);
|
||||
Pixmap out = new Pixmap(base.width, base.height);
|
||||
|
||||
for(int x = 0; x < base.width; x++){
|
||||
@@ -1584,7 +1584,7 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
|
||||
if(outlineIcon){
|
||||
AtlasRegion atlasRegion = (AtlasRegion)gen[outlinedIcon >= 0 ? Math.min(outlinedIcon, gen.length - 1) : gen.length -1];
|
||||
PixmapRegion region = Core.atlas.getPixmap(atlasRegion);
|
||||
PixmapRegion region = packer.get(atlasRegion);
|
||||
Pixmap out = last = Pixmaps.outline(region, outlineColor, outlineRadius);
|
||||
Drawf.checkBleed(out);
|
||||
packer.add(PageType.main, atlasRegion.name, out);
|
||||
@@ -1597,7 +1597,7 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
for(var region : toOutline){
|
||||
if(region instanceof AtlasRegion atlas){
|
||||
String regionName = atlas.name;
|
||||
Pixmap outlined = Pixmaps.outline(Core.atlas.getPixmap(region), outlineColor, outlineRadius);
|
||||
Pixmap outlined = Pixmaps.outline(packer.get(region), outlineColor, outlineRadius);
|
||||
|
||||
Drawf.checkBleed(outlined);
|
||||
|
||||
@@ -1607,19 +1607,19 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
}
|
||||
|
||||
if(gen.length > 1){
|
||||
Pixmap base = Core.atlas.getPixmap(gen[0]).crop();
|
||||
Pixmap base = packer.get(gen[0]).crop();
|
||||
for(int i = 1; i < gen.length; i++){
|
||||
if(i == gen.length - 1 && last != null){
|
||||
base.draw(last, 0, 0, true);
|
||||
}else{
|
||||
base.draw(Core.atlas.getPixmap(gen[i]), true);
|
||||
base.draw(packer.get(gen[i]), true);
|
||||
}
|
||||
}
|
||||
packer.add(PageType.main, "block-" + name + "-full", base);
|
||||
|
||||
toDispose.add(base);
|
||||
}else{
|
||||
if(gen[0] != null) packer.add(PageType.main, "block-" + name + "-full", Core.atlas.getPixmap(gen[0]));
|
||||
if(gen[0] != null) packer.add(PageType.main, "block-" + name + "-full", packer.get(gen[0]));
|
||||
}
|
||||
|
||||
toDispose.each(Pixmap::dispose);
|
||||
|
||||
@@ -220,8 +220,8 @@ public class Floor extends Block{
|
||||
|
||||
if(Core.atlas.has(name + "-edge")) return;
|
||||
|
||||
var image = Core.atlas.getPixmap(icons()[0]);
|
||||
var edge = Core.atlas.getPixmap(Core.atlas.find(name + "-edge-stencil", "edge-stencil"));
|
||||
var image = packer.get(icons()[0]);
|
||||
var edge = packer.get(Core.atlas.find(name + "-edge-stencil", "edge-stencil"));
|
||||
Pixmap result = new Pixmap(edge.width, edge.height);
|
||||
|
||||
for(int x = 0; x < edge.width; x++){
|
||||
|
||||
@@ -46,8 +46,8 @@ public class OreBlock extends OverlayFloor{
|
||||
for(int i = 0; i < variants; i++){
|
||||
//use name (e.g. "ore-copper1"), fallback to "copper1" as per the old naming system
|
||||
PixmapRegion shadow = Core.atlas.has(name + (i + 1)) ?
|
||||
Core.atlas.getPixmap(name + (i + 1)) :
|
||||
Core.atlas.getPixmap(itemDrop.name + (i + 1));
|
||||
packer.get(name + (i + 1)) :
|
||||
packer.get(itemDrop.name + (i + 1));
|
||||
|
||||
Pixmap image = shadow.crop();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package mindustry.world.blocks.environment;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.util.*;
|
||||
@@ -37,10 +36,10 @@ public class ShallowLiquid extends Floor{
|
||||
//super.createIcons(packer);
|
||||
|
||||
if(liquidBase != null && floorBase != null){
|
||||
var overlay = Core.atlas.getPixmap(liquidBase.region);
|
||||
var overlay = packer.get(liquidBase.region);
|
||||
int index = 0;
|
||||
for(TextureRegion region : floorBase.variantRegions()){
|
||||
var res = Core.atlas.getPixmap(region).crop();
|
||||
var res = packer.get(region).crop();
|
||||
for(int x = 0; x < res.width; x++){
|
||||
for(int y = 0; y < res.height; y++){
|
||||
res.setRaw(x, y, Pixmap.blend((overlay.getRaw(x, y) & 0xffffff00) | (int)(liquidOpacity * 255), res.getRaw(x, y)));
|
||||
|
||||
+1
-1
@@ -26,4 +26,4 @@ org.gradle.caching=true
|
||||
org.gradle.internal.http.socketTimeout=100000
|
||||
org.gradle.internal.http.connectionTimeout=100000
|
||||
android.enableR8.fullMode=false
|
||||
archash=6e3c0bbc30
|
||||
archash=2b0a95e325
|
||||
|
||||
Reference in New Issue
Block a user