Files
mindustry/tools/build.gradle
2026-09-21 15:15:33 -04:00

284 lines
9.5 KiB
Groovy

sourceSets.main.java.srcDirs = ["src/"]
import arc.files.*
import arc.func.*
import arc.graphics.*
import arc.packer.*
import arc.struct.*
import arc.util.*
import arc.util.io.*
import groovy.transform.*
import java.util.concurrent.*
def genFolder = "../core/assets-raw/sprites_out/generated/"
def enableAA = true
@CompileStatic
static void antialias(File file){
Pixmap result = new Pixmap(new Fi(file))
Pixmaps.antialias(result)
new Fi(file).writePng(result)
result.dispose()
}
tasks.register('antialiasImages'){
doLast{
for(def img : project.getProperty("images").split(",")){
println(project.getProperty("startdir") + "/" + img)
antialias(new File(project.getProperty("startdir") + "/" + img))
}
}
}
tasks.register('tileImages'){
doLast{
for(def img : project.getProperty("images").split(",")){
println(project.getProperty("startdir") + "/" + img)
tileImage(new File(project.getProperty("startdir") + "/" + img))
}
}
}
tasks.register('pack'){
dependsOn = [classes, configurations.runtimeClasspath]
doLast{
//cleanup old sprites
delete{
delete "../core/assets-raw/sprites_out/"
}
//copy in new sprites
copy{
from "../core/assets-raw/sprites/"
into "../core/assets-raw/sprites_out/"
}
new File(rootDir, "core/build/last_pack_version").text = versionNumber
//run generation task; generate all needed sprites
file(genFolder).mkdirs()
project.services.get(ExecOperations).javaexec{
mainClass = "mindustry.tools.ImagePacker"
classpath = sourceSets.main.runtimeClasspath
workingDir = genFolder
}
copy{
from "../core/assets-raw/sprites_out/ui/icons"
into "../core/assets-raw/sprites_out/ui/"
}
delete{
delete "../core/assets-raw/sprites_out/ui/icons"
}
if(enableAA){
ExecutorService executor = Executors.newFixedThreadPool(OS.cores)
long ms = System.currentTimeMillis()
//antialias everything except UI elements
fileTree(dir: new File(rootDir, 'core/assets-raw/sprites_out/').absolutePath, include: "**/*.png").visit{ file ->
if(file.isDirectory() || (file.toString().replace("\\", "/").contains("/ui/") && file.toString().startsWith("icon-")) || file.toString().contains(".9.png") || file.toString().contains("aaaa")) return
executor.submit{
antialias(file.file)
}
}
Threads.await(executor)
println "Time taken for AA: ${(System.currentTimeMillis() - ms) / 1000f} seconds"
}
println("Running sprite packer...")
//pack normal sprites
TexturePacker.process(new File(rootDir, "core/assets-raw/sprites_out/").absolutePath, new File(rootDir, "core/assets/sprites/").absolutePath, "sprites.aatls")
}
}
tasks.register('genSprites', JavaExec){
dependsOn classes
finalizedBy 'antialiasGen'
mainClass = "mindustry.tools.ImagePacker"
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = genFolder
}
tasks.register('fontgen', JavaExec){
dependsOn classes
/* icon font pipeline:
1. take set of pre-defined icons and SVGs
2. use Fontello API to get a font with these
3. combine fontello font and standard font, get output font
4. use json to generate a file with constants for every icon size+type (during annotation processing)
*/
doLast{
Fi folder = Fi.get("core/assets-raw/fontgen/out/")
folder.mkdirs()
Log.info("Session...")
OS.exec("curl", "--fail", "--output", "core/assets-raw/fontgen/out/session", "--form", "config=@core/assets-raw/fontgen/config.json", "https://fontello.com")
Log.info("Zip...")
String session = folder.child("session").readString()
Http.get("https://fontello.com/" + session + "/get").block(result -> {
Streams.copy(result.getResultAsStream(), folder.child("font.zip").write())
})
Log.info("Icon font...")
ZipFi zip = new ZipFi(folder.child("font.zip"))
Fi dest = folder.child("font.woff")
zip.list()[0].child("font").child("fontello.ttf").copyTo(dest)
dest.copyTo(Fi.get("core/assets/fonts/icon.ttf"))
Log.info("Merge...")
//TODO this is broken
Log.info(OS.exec("fontforge", "-script",
Fi.get("core/assets-raw/fontgen/merge.pe").absolutePath(),
Fi.get("core/assets/fonts/font.woff").absolutePath(),
Fi.get("core/assets-raw/fontgen/out/font.woff").absolutePath())
)
Log.info("Done.")
}
}
tasks.register('icongen', JavaExec){
dependsOn classes
mainClass = "mindustry.tools.IconConverter"
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = "../core/assets-raw"
}
tasks.register('updateScripts', JavaExec){
dependsOn classes
mainClass = "mindustry.tools.ScriptMainGenerator"
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = "../core/assets"
}
tasks.register('fixMaps', JavaExec){
dependsOn classes
mainClass = "mindustry.tools.MapFixer"
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = "../core/assets"
}
tasks.register('updateBundles'){
doLast{
def uniEscape = { String string ->
StringBuilder outBuffer = new StringBuilder()
int len = string.length()
for(int i = 0; i < len; i++){
char ch = string.charAt(i)
if((ch > 61) && (ch < 127)){
outBuffer.append(ch == (char) '\\' ? "\\\\" : ch)
continue
}
if(ch >= 0xE000 && ch <= 0xF8FF){
String hex = Integer.toHexString((int) ch)
outBuffer.append("\\u")
for(int j = 0; j < 4 - hex.length(); j++){
outBuffer.append('0')
}
outBuffer.append(hex)
}else{
outBuffer.append(ch)
}
}
return outBuffer.toString()
}
OrderedMap<String, String> base = new OrderedMap<>()
PropertiesUtils.load(base, Fi.get("core/assets/bundles/bundle.properties").reader())
//map of line number to comment (or just empty string for blank line) content
IntMap<String> commentAndBlankLines = new IntMap<>()
var lines = Fi.get("core/assets/bundles/bundle.properties").reader().readLines()
int offset = 0
for(int i = 0; i < lines.size(); i++){
var line = lines.get(i)
if(i > 0 && lines.get(i - 1).endsWith("\\")) offset++ //multiline value escaped with \\ at end of line
else if(line.isEmpty() || line.startsWith("#")) commentAndBlankLines.put(i - offset, line)
}
Log.info("Updating bundles...")
Fi.get("core/assets/bundles").walk(child -> {
if(child.name() == "bundle.properties" || child.name() == "global.properties" || child.toString().contains("output")) return
if(project.hasProperty("bundle") && child.name() != project.property("bundle")) return
Log.info("| @", child.nameWithoutExtension())
OrderedMap<String, String> other = new OrderedMap<>()
ObjectMap<String, String> extras = new OrderedMap<>()
Seq<String> removals = new Seq<>()
PropertiesUtils.load(other, child.reader())
for(String key : other.orderedKeys()){
if(!base.containsKey(key) && key.contains(".details") && false){
extras.put(key, other.get(key))
}else if(!base.containsKey(key)){
removals.add(key)
Log.info("&lr- Removing unused key '@'...", key)
}
}
if(removals.size > 0) Log.info("&lr@ keys removed.", removals.size)
for(String s : removals){
other.remove(s)
}
int added = 0
for(String key : base.orderedKeys()){
if(other.get(key) == null || other.get(key).trim().isEmpty()){
other.put(key, base.get(key))
added++
Log.info("&lc- Adding missing key '@'...", key)
}
}
Func2<String, String, String> processor = (key, value) ->
(key + " =" + (value.trim().isEmpty() ? "" : " ") + uniEscape(value)).replace("\n", "\\n") + "\n"
Fi output = child.sibling("output/" + child.name())
if(added > 0) Log.info("&lc@ keys added.", added)
if(removals.size + added > 0) Log.info("Writing bundle to @", output)
StringBuilder result = new StringBuilder()
int i = 0
//add everything ordered
for(String key : base.orderedKeys().copy().add(extras.keys().toSeq())){
//append any comments or blank lines as needed to match the english bundle
while(commentAndBlankLines.containsKey(i++)) result.append(commentAndBlankLines.get(i - 1) + "\n")
if(other.get(key) == null) continue
result.append(processor.get(key, other.get(key)))
other.remove(key)
}
child.writeString(result.toString())
})
}
}