Mindustry/tools/build.gradle

360 lines
12 KiB
Groovy
Raw Permalink Normal View History

2019-04-08 20:03:18 +07:00
sourceSets.main.java.srcDirs = ["src/"]
2018-06-16 05:06:05 +07:00
2021-06-02 22:08:08 +07:00
import arc.files.Fi
import arc.files.ZipFi
2021-11-23 00:04:09 +07:00
import arc.func.Func2
2021-06-02 22:08:08 +07:00
import arc.graphics.Color
import arc.graphics.Pixmap
import arc.packer.TexturePacker
2021-11-23 00:04:09 +07:00
import arc.struct.ObjectMap
import arc.struct.OrderedMap
import arc.struct.Seq
import arc.util.Http
2021-11-23 00:04:09 +07:00
import arc.util.Log
import arc.util.OS
2022-02-20 03:08:55 +07:00
import arc.util.Threads
2021-11-23 00:04:09 +07:00
import arc.util.io.PropertiesUtils
import arc.util.io.Streams
2021-06-02 22:08:08 +07:00
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
2018-11-13 07:03:23 +07:00
def genFolder = "../core/assets-raw/sprites_out/generated/"
2021-12-13 06:29:44 +07:00
def enableAA = true
2022-02-25 00:59:57 +07:00
@groovy.transform.CompileStatic
2022-04-19 03:58:50 +07:00
static int getRGB(Pixmap image, int ix, int iy) {
return image.getRaw(Math.max(Math.min(ix, image.width - 1), 0), Math.max(Math.min(iy, image.height - 1), 0))
}
2020-07-22 22:03:38 +07:00
2022-04-19 03:58:50 +07:00
@groovy.transform.CompileStatic
static void antialias(File file){
Pixmap image = new Pixmap(new Fi(file))
Pixmap out = image.copy()
2019-01-17 10:45:51 +07:00
2022-04-19 03:58:50 +07:00
Color color = new Color()
Color sum = new Color()
Color suma = new Color()
2019-10-17 01:36:46 +07:00
int[] p = new int[9]
2019-01-17 10:45:51 +07:00
2021-06-02 22:08:08 +07:00
for(int x = 0; x < image.width; x++){
for(int y = 0; y < image.height; y++){
2022-04-19 03:58:50 +07:00
int A = getRGB(image, x - 1, y + 1),
B = getRGB(image, x, y + 1),
C = getRGB(image, x + 1, y + 1),
D = getRGB(image, x - 1, y),
E = getRGB(image, x, y),
F = getRGB(image, x + 1, y),
G = getRGB(image, x - 1, y - 1),
H = getRGB(image, x, y - 1),
I = getRGB(image, x + 1, y - 1)
2019-01-17 10:45:51 +07:00
2021-06-02 22:08:08 +07:00
Arrays.fill(p, E)
2019-10-17 01:36:46 +07: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-17 10:45:51 +07:00
suma.set(0)
2019-01-17 10:45:51 +07:00
2019-10-17 01:36:46 +07:00
for(int val : p){
2021-06-02 22:08:08 +07:00
color.rgba8888(val)
2022-04-19 03:58:50 +07:00
color.premultiplyAlpha()
suma.r(suma.r + color.r)
suma.g(suma.g + color.g)
suma.b(suma.b + color.b)
suma.a(suma.a + color.a)
}
2021-06-02 22:08:08 +07:00
float fm = suma.a <= 0.001f ? 0f : (float)(1f / suma.a)
2020-01-23 07:16:56 +07:00
suma.mul(fm, fm, fm, fm)
float total = 0
sum.set(0)
2019-01-17 10:45:51 +07:00
2019-10-17 01:36:46 +07:00
for(int val : p){
2021-06-02 22:08:08 +07:00
color.rgba8888(val)
float a = color.a
2019-04-08 20:03:18 +07:00
color.lerp(suma, (float) (1f - a))
2022-04-19 03:58:50 +07:00
sum.r(sum.r + color.r)
sum.g(sum.g + color.g)
sum.b(sum.b + color.b)
sum.a(sum.a + a)
total += 1f
2019-01-17 10:45:51 +07:00
}
2020-01-23 07:16:56 +07:00
fm = (float)(1f / total)
sum.mul(fm, fm, fm, fm)
2021-06-02 22:08:08 +07:00
out.setRaw(x, y, sum.rgba8888())
2019-01-17 10:45:51 +07:00
sum.set(0)
}
}
2021-06-02 22:08:08 +07:00
image.dispose()
out.dispose()
2019-04-21 06:57:20 +07:00
2021-06-02 22:08:08 +07:00
new Fi(file).writePng(out)
2019-04-21 06:57:20 +07:00
}
2019-08-04 20:41:25 +07: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-21 06:57:20 +07:00
}
}
}
task pack(dependsOn: [classes, configurations.runtimeClasspath]){
2018-11-13 07:03:23 +07: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 13:39:38 +07: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-13 06:29:44 +07:00
if(enableAA){
2022-04-19 03:58:50 +07:00
ExecutorService executor = Executors.newFixedThreadPool(OS.cores)
2021-12-13 06:29:44 +07:00
long ms = System.currentTimeMillis()
2019-10-17 01:36:46 +07:00
2021-12-13 06:29:44 +07:00
//antialias everything except UI elements
fileTree(dir: new File(rootDir, 'core/assets-raw/sprites_out/').absolutePath, include: "**/*.png").visit{ file ->
2022-04-10 23:14:22 +07:00
if(file.isDirectory() || (file.toString().replace("\\", "/").contains("/ui/") && file.toString().startsWith("icon-")) || file.toString().contains(".9.png") || file.toString().contains("aaaa")) return
2021-12-13 06:29:44 +07:00
executor.submit{
2022-04-19 03:58:50 +07:00
antialias(file.file)
2021-12-13 06:29:44 +07:00
}
2021-06-03 21:15:34 +07:00
}
2018-11-14 10:11:29 +07:00
2021-12-13 06:29:44 +07:00
Threads.await(executor)
2020-07-22 22:03:38 +07:00
2022-04-19 03:58:50 +07:00
println "Time taken for AA: ${(System.currentTimeMillis() - ms) / 1000f} seconds"
2021-12-13 06:29:44 +07:00
}
2021-06-03 22:37:33 +07:00
2020-06-12 02:25:46 +07:00
println("\n\nPacking normal 4096 sprites...\n\n")
//pack normal sprites
2021-06-02 22:08:08 +07:00
TexturePacker.process(new File(rootDir, "core/assets-raw/sprites_out/").absolutePath, new File(rootDir, "core/assets/sprites/").absolutePath, "sprites.aatls")
2020-06-12 02:25:46 +07: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-25 06:28:50 +07: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-15 05:14:22 +07:00
}
2019-06-21 03:27:57 +07:00
}
2019-04-08 20:03:18 +07:00
task genSprites(dependsOn: classes, type: JavaExec){
finalizedBy 'antialiasGen'
2019-04-08 20:03:18 +07:00
2021-11-22 23:43:13 +07:00
mainClass = "mindustry.tools.ImagePacker"
2018-06-16 05:06:05 +07:00
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
2018-11-13 05:37:25 +07:00
workingDir = genFolder
2018-06-16 05:06:05 +07:00
}
2020-01-18 01:57:04 +07: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 12:05:02 +07:00
Fi folder = Fi.get("core/assets-raw/fontgen/out/")
folder.mkdirs()
2021-12-22 12:05:02 +07:00
Log.info("Session...")
2021-12-22 12:05:02 +07: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 12:05:02 +07:00
Log.info("Zip...")
2021-12-22 12:05:02 +07:00
String session = folder.child("session").readString()
Http.get("https://fontello.com/" + session + "/get").block(result -> {
2021-12-22 12:05:02 +07:00
Streams.copy(result.getResultAsStream(), folder.child("font.zip").write())
})
2021-12-22 12:05:02 +07:00
Log.info("Icon font...")
2021-12-22 12:05:02 +07: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 12:05:02 +07: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 12:05:02 +07:00
)
2021-12-22 12:05:02 +07:00
Log.info("Done.")
}
2020-01-18 01:57:04 +07:00
}
2020-11-06 08:21:30 +07:00
task icongen(dependsOn: classes, type: JavaExec){
2021-11-22 23:43:13 +07:00
mainClass = "mindustry.tools.IconConverter"
2020-11-06 08:21:30 +07:00
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = "../core/assets-raw"
2020-12-13 01:26:30 +07:00
}
task updateScripts(dependsOn: classes, type: JavaExec){
2021-11-22 23:43:13 +07:00
mainClass = "mindustry.tools.ScriptMainGenerator"
2020-12-13 01:26:30 +07:00
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = "../"
}
2021-11-22 23:43:13 +07:00
2021-11-23 00:04:09 +07:00
task updateBundles{
doLast{
def uniEscape = { String string ->
2021-12-22 12:05:02 +07:00
StringBuilder outBuffer = new StringBuilder()
int len = string.length()
2021-11-23 00:04:09 +07:00
for(int i = 0; i < len; i++){
2021-12-22 12:05:02 +07:00
char ch = string.charAt(i)
2021-11-23 00:04:09 +07:00
if((ch > 61) && (ch < 127)){
2021-12-22 12:05:02 +07:00
outBuffer.append(ch == (char)'\\' ? "\\\\" : ch)
continue
2021-11-23 00:04:09 +07:00
}
2021-11-22 23:43:13 +07:00
2021-11-23 00:13:14 +07:00
if(ch >= 0xE000 && ch <= 0xF8FF){
2021-12-22 12:05:02 +07:00
String hex = Integer.toHexString((int)ch)
outBuffer.append("\\u")
2021-11-23 00:04:09 +07:00
for(int j = 0; j < 4 - hex.length(); j++){
2021-12-22 12:05:02 +07:00
outBuffer.append('0')
2021-11-23 00:04:09 +07:00
}
2021-12-22 12:05:02 +07:00
outBuffer.append(hex)
2021-11-23 00:04:09 +07:00
}else{
2021-12-22 12:05:02 +07:00
outBuffer.append(ch)
2021-11-23 00:04:09 +07:00
}
}
2021-12-22 12:05:02 +07:00
return outBuffer.toString()
2021-11-23 00:04:09 +07:00
}
2021-12-22 12:05:02 +07: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-23 00:04:09 +07:00
2021-12-22 12:05:02 +07:00
Log.info("Updating bundles...")
2021-11-23 00:08:10 +07:00
2021-11-23 00:04:09 +07:00
Fi.get("core/assets/bundles").walk(child -> {
2021-12-22 12:05:02 +07:00
if(child.name().equals("bundle.properties") || child.toString().contains("output")) return
2021-11-23 00:04:09 +07:00
2021-12-22 12:05:02 +07:00
Log.info("| @", child.nameWithoutExtension())
2021-11-23 00:04:09 +07:00
2021-12-22 12:05:02 +07:00
OrderedMap<String, String> other = new OrderedMap<>()
2021-11-23 00:04:09 +07:00
//find the last known comment of each line
2021-12-22 12:05:02 +07:00
ObjectMap<String, String> comments = new ObjectMap<>()
StringBuilder curComment = new StringBuilder()
2021-11-23 00:04:09 +07:00
for(String line : Seq.with(child.readString().split("\n", -1))){
if(line.startsWith("#") || line.isEmpty()){
2021-12-22 12:05:02 +07:00
curComment.append(line).append("\n")
2021-11-23 00:04:09 +07:00
}else if(line.contains("=")){
2021-12-22 12:05:02 +07:00
String lastKey = line.substring(0, line.indexOf("=")).trim()
2021-11-23 00:04:09 +07:00
if(curComment.length() != 0){
2021-12-22 12:05:02 +07:00
comments.put(lastKey, curComment.toString())
curComment.setLength(0)
2021-11-23 00:04:09 +07:00
}
}
}
2021-12-22 12:05:02 +07:00
ObjectMap<String, String> extras = new OrderedMap<>()
PropertiesUtils.load(other, child.reader())
removals.clear()
2021-11-23 00:04:09 +07:00
for(String key : other.orderedKeys()){
2022-08-29 23:08:12 +07:00
if(!base.containsKey(key) && key.contains(".details") && false){
2021-12-22 12:05:02 +07:00
extras.put(key, other.get(key))
2021-11-23 00:04:09 +07:00
}else if(!base.containsKey(key)){
2021-12-22 12:05:02 +07:00
removals.add(key)
Log.info("&lr- Removing unused key '@'...", key)
2021-11-23 00:04:09 +07:00
}
}
2021-12-22 12:05:02 +07:00
if(removals.size > 0) Log.info("&lr@ keys removed.", removals.size)
2021-11-23 00:04:09 +07:00
for(String s : removals){
2021-12-22 12:05:02 +07:00
other.remove(s)
2021-11-23 00:04:09 +07:00
}
2021-12-22 12:05:02 +07:00
int added = 0
2021-11-23 00:04:09 +07:00
for(String key : base.orderedKeys()){
if(other.get(key) == null || other.get(key).trim().isEmpty()){
2021-12-22 12:05:02 +07:00
other.put(key, base.get(key))
added++
Log.info("&lc- Adding missing key '@'...", key)
2021-11-23 00:04:09 +07:00
}
}
Func2<String, String, String> processor = (key, value) ->
(comments.containsKey(key) ? comments.get(key) : "") + //append last known comment if present
2021-12-22 12:05:02 +07:00
(key + " =" + (value.trim().isEmpty() ? "" : " ") + uniEscape(value)).replace("\n", "\\n") + "\n"
Fi output = child.sibling("output/" + child.name())
2021-11-23 00:04:09 +07:00
2021-12-22 12:05:02 +07: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-23 00:04:09 +07:00
//add everything ordered
2022-05-10 11:14:33 +07:00
for(String key : base.orderedKeys().copy().add(extras.keys().toSeq())){
2021-12-22 12:05:02 +07:00
if(other.get(key) == null) continue
2021-11-23 00:04:09 +07:00
2021-12-22 12:05:02 +07:00
result.append(processor.get(key, other.get(key)))
other.remove(key)
2021-11-23 00:04:09 +07:00
}
2021-12-22 12:05:02 +07:00
child.writeString(result.toString())
})
2021-11-23 00:04:09 +07:00
}
2021-11-22 23:43:13 +07:00
}