Files
Mindustry/tools/build.gradle

369 lines
12 KiB
Groovy
Raw Normal View History

2019-04-08 09:03:18 -04:00
sourceSets.main.java.srcDirs = ["src/"]
2018-06-15 18:06:05 -04:00
2021-06-06 11:05:36 -04:00
2021-12-22 00:05:02 -05:00
2021-06-02 11:08:08 -04:00
import arc.files.Fi
import arc.files.ZipFi
2021-11-22 12:04:09 -05:00
import arc.func.Func2
2021-06-02 11:08:08 -04:00
import arc.graphics.Color
import arc.graphics.Pixmap
import arc.packer.TexturePacker
2021-11-22 12:04:09 -05:00
import arc.struct.ObjectMap
import arc.struct.OrderedMap
import arc.struct.Seq
import arc.util.Http
2021-11-22 12:04:09 -05:00
import arc.util.Log
import arc.util.OS
2021-06-06 11:05:36 -04:00
import arc.util.async.Threads
2021-11-22 12:04:09 -05:00
import arc.util.io.PropertiesUtils
import arc.util.io.Streams
2021-06-02 11:08:08 -04:00
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
2018-11-12 19:03:23 -05:00
def genFolder = "../core/assets-raw/sprites_out/generated/"
2019-03-02 23:06:14 -05:00
def doAntialias = !project.hasProperty("disableAntialias")
2021-12-12 18:29:44 -05:00
def enableAA = true
2020-07-22 11:03:38 -04:00
//on my machine, I have a native Nim AA implementation that is ~10x faster
//it's not compiled for other platforms so they don't get it
def useFastAA = project.hasProperty("fastAA") || System.getProperty("user.name") == "anuke"
2019-04-08 09:03:18 -04:00
def antialias = { File file ->
2020-05-18 15:38:56 -04:00
if(!doAntialias) return
2019-02-07 09:36:39 -05:00
2020-07-22 11:03:38 -04:00
if(useFastAA){
"antialias ${file.absolutePath}".execute().waitFor()
return
}
2021-06-02 11:08:08 -04:00
def image = new Pixmap(new Fi(file))
def out = image.copy()
2019-01-16 22:45:51 -05:00
def getRGB = { int ix, int iy ->
2021-06-02 11:08:08 -04:00
return image.getRaw(Math.max(Math.min(ix, image.width - 1), 0), Math.max(Math.min(iy, image.height - 1), 0))
2019-01-16 22:45:51 -05:00
}
def color = new Color()
def sum = new Color()
def suma = new Color()
2019-10-16 14:36:46 -04:00
int[] p = new int[9]
2019-01-16 22:45:51 -05:00
2021-06-02 11:08:08 -04:00
for(int x = 0; x < image.width; x++){
for(int y = 0; y < image.height; y++){
2019-04-16 12:15:06 -04:00
int A = getRGB(x - 1, y + 1),
2019-01-16 22:45:51 -05:00
B = getRGB(x, y + 1),
C = getRGB(x + 1, y + 1),
D = getRGB(x - 1, y),
E = getRGB(x, y),
F = getRGB(x + 1, y),
G = getRGB(x - 1, y - 1),
H = getRGB(x, y - 1),
I = getRGB(x + 1, y - 1)
2021-06-02 11:08:08 -04:00
Arrays.fill(p, E)
2019-10-16 14:36:46 -04:00
if(D == B && D != H && B != F) p[0] = D
if((D == B && D != H && B != F && E != C) || (B == F && B != D && F != H && E != A)) p[1] = B
if(B == F && B != D && F != H) p[2] = F
if((H == D && H != F && D != B && E != A) || (D == B && D != H && B != F && E != G)) p[3] = D
if((B == F && B != D && F != H && E != I) || (F == H && F != B && H != D && E != C)) p[5] = F
if(H == D && H != F && D != B) p[6] = D
if((F == H && F != B && H != D && E != G) || (H == D && H != F && D != B && E != I)) p[7] = H
if(F == H && F != B && H != D) p[8] = F
2019-01-16 22:45:51 -05:00
suma.set(0)
2019-01-16 22:45:51 -05:00
2019-10-16 14:36:46 -04:00
for(int val : p){
2021-06-02 11:08:08 -04:00
color.rgba8888(val)
2019-04-08 09:03:18 -04:00
suma.r += color.r * color.a
suma.g += color.g * color.a
suma.b += color.b * color.a
suma.a += color.a
}
2021-06-02 11:08:08 -04:00
float fm = suma.a <= 0.001f ? 0f : (float)(1f / suma.a)
2020-01-22 19:16:56 -05:00
suma.mul(fm, fm, fm, fm)
float total = 0
sum.set(0)
2019-01-16 22:45:51 -05:00
2019-10-16 14:36:46 -04:00
for(int val : p){
2021-06-02 11:08:08 -04:00
color.rgba8888(val)
float a = color.a
2019-04-08 09:03:18 -04:00
color.lerp(suma, (float) (1f - a))
sum.r += color.r
sum.g += color.g
sum.b += color.b
sum.a += a
total += 1f
2019-01-16 22:45:51 -05:00
}
2020-01-22 19:16:56 -05:00
fm = (float)(1f / total)
sum.mul(fm, fm, fm, fm)
2021-06-02 11:08:08 -04:00
out.setRaw(x, y, sum.rgba8888())
2019-01-16 22:45:51 -05:00
sum.set(0)
}
}
2021-06-02 11:08:08 -04:00
image.dispose()
out.dispose()
2019-04-20 19:57:20 -04:00
2021-06-02 11:08:08 -04:00
new Fi(file).writePng(out)
2019-04-20 19:57:20 -04:00
}
2019-08-04 09:41:25 -04:00
task antialiasImages(){
doLast{
for(def img : project.getProperty("images").split(",")){
println(project.getProperty("startdir") + "/" + img)
antialias(new File(project.getProperty("startdir") + "/" + img))
}
}
}
task tileImages(){
doLast{
for(def img : project.getProperty("images").split(",")){
println(project.getProperty("startdir") + "/" + img)
tileImage(new File(project.getProperty("startdir") + "/" + img))
2019-04-20 19:57:20 -04:00
}
}
}
task pack(dependsOn: [classes, configurations.runtimeClasspath]){
2018-11-12 19:03:23 -05:00
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/"
}
//run generation task; generate all needed sprites
file(genFolder).mkdirs()
javaexec{
2019-12-25 01:39:38 -05:00
main = "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"
}
2021-12-12 18:29:44 -05:00
if(enableAA){
ExecutorService executor = Executors.newFixedThreadPool(16)
long ms = System.currentTimeMillis()
2019-10-16 14:36:46 -04:00
2021-12-12 18:29:44 -05:00
//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")) return
2021-12-12 18:29:44 -05:00
executor.submit{
antialias(file.file)
}
2021-06-03 10:15:34 -04:00
}
2018-11-13 22:11:29 -05:00
2021-12-12 18:29:44 -05:00
Threads.await(executor)
2020-07-22 11:03:38 -04:00
2021-12-12 18:29:44 -05:00
println "Time taken for AA: ${(System.currentTimeMillis() - ms) / 1000f}"
}
2021-06-03 11:37:33 -04:00
2020-06-11 15:25:46 -04:00
println("\n\nPacking normal 4096 sprites...\n\n")
//pack normal sprites
2021-06-02 11:08:08 -04:00
TexturePacker.process(new File(rootDir, "core/assets-raw/sprites_out/").absolutePath, new File(rootDir, "core/assets/sprites/").absolutePath, "sprites.aatls")
2020-06-11 15:25:46 -04:00
println("\n\nPacking fallback 2048 sprites...\n\n")
//replace config file contents
fileTree(dir: '../core/assets-raw/sprites_out/', include: "**/*.json").visit{ file ->
if(!file.isDirectory()) file.file.text = file.file.text.replace("4096", "2048")
}
2021-11-24 18:28:50 -05:00
//pack fallback 2048x2048 sprites - disabled when debugging
if(!project.hasProperty("args")){
TexturePacker.process(new File(rootDir, "core/assets-raw/sprites_out/").absolutePath, new File(rootDir, "core/assets/sprites/fallback/").absolutePath, "sprites.aatls")
}
2018-11-14 17:14:22 -05:00
}
2019-06-20 16:27:57 -04:00
}
2019-04-08 09:03:18 -04:00
task genSprites(dependsOn: classes, type: JavaExec){
finalizedBy 'antialiasGen'
2019-04-08 09:03:18 -04:00
2021-11-22 11:43:13 -05:00
mainClass = "mindustry.tools.ImagePacker"
2018-06-15 18:06:05 -04:00
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
2018-11-12 17:37:25 -05:00
workingDir = genFolder
2018-06-15 18:06:05 -04:00
}
2020-01-17 13:57:04 -05:00
task fontgen(dependsOn: classes, type: JavaExec){
/* 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{
2021-12-22 00:05:02 -05:00
Fi folder = Fi.get("core/assets-raw/fontgen/out/")
folder.mkdirs()
2021-12-22 00:05:02 -05:00
Log.info("Session...")
2021-12-22 00:05:02 -05:00
OS.exec("curl", "--fail", "--output", "core/assets-raw/fontgen/out/session", "--form", "config=@core/assets-raw/fontgen/config.json", "https://fontello.com")
2021-12-22 00:05:02 -05:00
Log.info("Zip...")
2021-12-22 00:05:02 -05:00
String session = folder.child("session").readString()
Http.get("https://fontello.com/" + session + "/get").block(result -> {
2021-12-22 00:05:02 -05:00
Streams.copy(result.getResultAsStream(), folder.child("font.zip").write())
})
2021-12-22 00:05:02 -05:00
Log.info("Icon font...")
2021-12-22 00:05:02 -05:00
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"))
2021-12-22 00:05:02 -05:00
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())
2021-12-22 00:05:02 -05:00
)
2021-12-22 00:05:02 -05:00
Log.info("Done.")
}
2020-01-17 13:57:04 -05:00
}
2020-11-05 20:21:30 -05:00
task icongen(dependsOn: classes, type: JavaExec){
2021-11-22 11:43:13 -05:00
mainClass = "mindustry.tools.IconConverter"
2020-11-05 20:21:30 -05:00
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = "../core/assets-raw"
2020-12-12 13:26:30 -05:00
}
task updateScripts(dependsOn: classes, type: JavaExec){
2021-11-22 11:43:13 -05:00
mainClass = "mindustry.tools.ScriptMainGenerator"
2020-12-12 13:26:30 -05:00
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = "../"
}
2021-11-22 11:43:13 -05:00
2021-11-22 12:04:09 -05:00
task updateBundles{
doLast{
def uniEscape = { String string ->
2021-12-22 00:05:02 -05:00
StringBuilder outBuffer = new StringBuilder()
int len = string.length()
2021-11-22 12:04:09 -05:00
for(int i = 0; i < len; i++){
2021-12-22 00:05:02 -05:00
char ch = string.charAt(i)
2021-11-22 12:04:09 -05:00
if((ch > 61) && (ch < 127)){
2021-12-22 00:05:02 -05:00
outBuffer.append(ch == (char)'\\' ? "\\\\" : ch)
continue
2021-11-22 12:04:09 -05:00
}
2021-11-22 11:43:13 -05:00
2021-11-22 12:13:14 -05:00
if(ch >= 0xE000 && ch <= 0xF8FF){
2021-12-22 00:05:02 -05:00
String hex = Integer.toHexString((int)ch)
outBuffer.append("\\u")
2021-11-22 12:04:09 -05:00
for(int j = 0; j < 4 - hex.length(); j++){
2021-12-22 00:05:02 -05:00
outBuffer.append('0')
2021-11-22 12:04:09 -05:00
}
2021-12-22 00:05:02 -05:00
outBuffer.append(hex)
2021-11-22 12:04:09 -05:00
}else{
2021-12-22 00:05:02 -05:00
outBuffer.append(ch)
2021-11-22 12:04:09 -05:00
}
}
2021-12-22 00:05:02 -05:00
return outBuffer.toString()
2021-11-22 12:04:09 -05:00
}
2021-12-22 00:05:02 -05:00
OrderedMap<String, String> base = new OrderedMap<>()
PropertiesUtils.load(base, Fi.get("core/assets/bundles/bundle.properties").reader())
Seq<String> removals = new Seq<>()
2021-11-22 12:04:09 -05:00
2021-12-22 00:05:02 -05:00
Log.info("Updating bundles...")
2021-11-22 12:08:10 -05:00
2021-11-22 12:04:09 -05:00
Fi.get("core/assets/bundles").walk(child -> {
2021-12-22 00:05:02 -05:00
if(child.name().equals("bundle.properties") || child.toString().contains("output")) return
2021-11-22 12:04:09 -05:00
2021-12-22 00:05:02 -05:00
Log.info("| @", child.nameWithoutExtension())
2021-11-22 12:04:09 -05:00
2021-12-22 00:05:02 -05:00
OrderedMap<String, String> other = new OrderedMap<>()
2021-11-22 12:04:09 -05:00
//find the last known comment of each line
2021-12-22 00:05:02 -05:00
ObjectMap<String, String> comments = new ObjectMap<>()
StringBuilder curComment = new StringBuilder()
2021-11-22 12:04:09 -05:00
for(String line : Seq.with(child.readString().split("\n", -1))){
if(line.startsWith("#") || line.isEmpty()){
2021-12-22 00:05:02 -05:00
curComment.append(line).append("\n")
2021-11-22 12:04:09 -05:00
}else if(line.contains("=")){
2021-12-22 00:05:02 -05:00
String lastKey = line.substring(0, line.indexOf("=")).trim()
2021-11-22 12:04:09 -05:00
if(curComment.length() != 0){
2021-12-22 00:05:02 -05:00
comments.put(lastKey, curComment.toString())
curComment.setLength(0)
2021-11-22 12:04:09 -05:00
}
}
}
2021-12-22 00:05:02 -05:00
ObjectMap<String, String> extras = new OrderedMap<>()
PropertiesUtils.load(other, child.reader())
removals.clear()
2021-11-22 12:04:09 -05:00
for(String key : other.orderedKeys()){
if(!base.containsKey(key) && key.contains(".details")){
2021-12-22 00:05:02 -05:00
extras.put(key, other.get(key))
2021-11-22 12:04:09 -05:00
}else if(!base.containsKey(key)){
2021-12-22 00:05:02 -05:00
removals.add(key)
Log.info("&lr- Removing unused key '@'...", key)
2021-11-22 12:04:09 -05:00
}
}
2021-12-22 00:05:02 -05:00
if(removals.size > 0) Log.info("&lr@ keys removed.", removals.size)
2021-11-22 12:04:09 -05:00
for(String s : removals){
2021-12-22 00:05:02 -05:00
other.remove(s)
2021-11-22 12:04:09 -05:00
}
2021-12-22 00:05:02 -05:00
int added = 0
2021-11-22 12:04:09 -05:00
for(String key : base.orderedKeys()){
if(other.get(key) == null || other.get(key).trim().isEmpty()){
2021-12-22 00:05:02 -05:00
other.put(key, base.get(key))
added++
Log.info("&lc- Adding missing key '@'...", key)
2021-11-22 12:04:09 -05:00
}
}
Func2<String, String, String> processor = (key, value) ->
(comments.containsKey(key) ? comments.get(key) : "") + //append last known comment if present
2021-12-22 00:05:02 -05:00
(key + " =" + (value.trim().isEmpty() ? "" : " ") + uniEscape(value)).replace("\n", "\\n") + "\n"
Fi output = child.sibling("output/" + child.name())
2021-11-22 12:04:09 -05:00
2021-12-22 00:05:02 -05:00
if(added > 0) Log.info("&lc@ keys added.", added)
if(removals.size + added > 0) Log.info("Writing bundle to @", output)
StringBuilder result = new StringBuilder()
2021-11-22 12:04:09 -05:00
//add everything ordered
for(String key : base.orderedKeys().copy().and(extras.keys().toSeq())){
2021-12-22 00:05:02 -05:00
if(other.get(key) == null) continue
2021-11-22 12:04:09 -05:00
2021-12-22 00:05:02 -05:00
result.append(processor.get(key, other.get(key)))
other.remove(key)
2021-11-22 12:04:09 -05:00
}
2021-12-22 00:05:02 -05:00
child.writeString(result.toString())
})
2021-11-22 12:04:09 -05:00
}
2021-11-22 11:43:13 -05:00
}