Skip to content

Commit

Permalink
Allow custom renaming function
Browse files Browse the repository at this point in the history
  • Loading branch information
davesmith00000 committed Sep 13, 2023
1 parent cbcde76 commit 2fc6587
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 29 deletions.
30 changes: 27 additions & 3 deletions indigo-plugin/indigo-plugin/src/indigoplugin/IndigoAssets.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package indigoplugin

/** Represents you game's assets processing.
/** Represents you game's assets processing. All assets and details are based around a single asset directory and it's
* sub-tree.
*
* @param gameAssetsDirectory
* Project relative path to a directory that contains all of the assets the game needs to load. Default './assets'.
*/
final case class IndigoAssets(
gameAssetsDirectory: os.RelPath,
include: os.RelPath => Boolean,
exclude: os.RelPath => Boolean
exclude: os.RelPath => Boolean,
rename: Option[(String, String) => String]
) {

/** Sets the asset directory path */
Expand All @@ -18,15 +20,35 @@ final case class IndigoAssets(
if (path.startsWith("/")) os.Path(path).relativeTo(os.pwd)
else os.RelPath(path)
)

/** Sets the asset directory path */
def withAssetDirectory(path: os.RelPath): IndigoAssets =
this.copy(gameAssetsDirectory = path)

/** Function that decides if a path in the assets folder should specifically be included. Useful for including a file
* inside a folder that has been excluded.
*/
def withInclude(p: os.RelPath => Boolean): IndigoAssets =
this.copy(include = p)

/** Function that decides if a path in the assets folder should specifically be excluded. Useful for excluding source
* files or folders used during asset development.
*/
def withExclude(p: os.RelPath => Boolean): IndigoAssets =
this.copy(exclude = p)

/** Provide a custom renaming function (arguments are (name, ext) => ???) used during asset listing generation to
* produce safe names for generated code. Original file names will not be affected. For example: A file called
* `some_text-file!.txt` by default will copied as is with it's path preserved, but in the generated Scala code it's
* name will be `someTextFile`, i.e. `val someTextFile: AssetName = ???`
*
* @param f
* Function that takes a tuple of Strings, file name and extension, and returns a new 'safe for Scala' name.
*/
def withRenameFunction(f: (String, String) => String): IndigoAssets =
this.copy(rename = Option(f))

/** Decides if a relative path will be included in the assets or not. */
def isCopyAllowed(rel: os.RelPath): Boolean =
// val rel = toCopy.relativeTo(base)
if (include(rel))
Expand All @@ -39,13 +61,15 @@ final case class IndigoAssets(
// Otherwise, no specific instruction so assume copy.
true

/** List which absolute paths will be copied from the source asset directory. */
def filesToCopy(baseDirectory: os.Path): List[os.Path] =
os.walk(baseDirectory / gameAssetsDirectory)
.toList
.filter(path => isCopyAllowed(path.relativeTo(baseDirectory / gameAssetsDirectory)))
def filesToCopy: List[os.Path] =
filesToCopy(os.pwd)

/** List all relative paths that will be available to the game. */
def listAssetFiles(baseDirectory: os.Path): List[os.RelPath] =
filesToCopy(baseDirectory)
.filterNot(os.isDir)
Expand All @@ -61,6 +85,6 @@ object IndigoAssets {
val defaults: IndigoAssets = {
val pf: PartialFunction[os.RelPath, Boolean] = { case _ => false }

IndigoAssets(gameAssetsDirectory = os.RelPath("assets"), pf, pf)
IndigoAssets(gameAssetsDirectory = os.RelPath("assets"), pf, pf, None)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ object AssetListing {
indigoAssets: IndigoAssets
): Seq[os.Path] = {

val toSafeName: (String, String) => String =
indigoAssets.rename.getOrElse(toDefaultSafeName)

val fileContents: String =
renderContent(indigoAssets.listAssetFiles)
renderContent(indigoAssets.listAssetFiles, toSafeName)

val wd = outDir / Generators.OutputDirName

Expand All @@ -25,6 +28,7 @@ object AssetListing {
|
|import indigo.*
|
|// DO NOT EDIT: Generated by Indigo.
|object $moduleName:
|
|${fileContents}
Expand All @@ -36,8 +40,8 @@ object AssetListing {
Seq(file)
}

def renderContent(paths: List[os.RelPath]): String =
(convertPathsToTree _ andThen renderTree(0))(paths)
def renderContent(paths: List[os.RelPath], toSafeName: (String, String) => String): String =
(convertPathsToTree _ andThen renderTree(0, toSafeName))(paths)

def convertPathsToTree(paths: List[os.RelPath]): PathTree =
PathTree
Expand All @@ -51,29 +55,35 @@ object AssetListing {
)
.sorted

def renderTree(indent: Int)(pathTree: PathTree): String =
def renderTree(indent: Int, toSafeName: (String, String) => String)(pathTree: PathTree): String =
pathTree match {
case PathTree.File(_, _, _) =>
""

case PathTree.Folder(folderName, children) =>
renderFolderContents(folderName, children, indent)
renderFolderContents(folderName, children, indent, toSafeName)

case PathTree.Root(children) =>
renderFolderContents("", children, indent)
renderFolderContents("", children, indent, toSafeName)
}

def renderFolderContents(folderName: String, children: List[PathTree], indent: Int): String = {
def renderFolderContents(
folderName: String,
children: List[PathTree],
indent: Int,
toSafeName: (String, String) => String
): String = {

val indentSpaces = List.fill(indent)(" ").mkString
val indentSpacesNext = indentSpaces + " "
val safeFolderName = toSafeName(folderName)
val safeFolderName = toSafeName(folderName, "")
val files: List[PathTree.File] = children.collect { case f: PathTree.File => f }

val renderedFiles: List[(String, String)] =
files
.map {
case PathTree.File(name, ext, path) if AudioFileExtensions.contains(ext) =>
val safeName = toSafeName(name)
val safeName = toSafeName(name, ext)

val vals =
s"""${indentSpacesNext}val ${safeName}: AssetName = AssetName("${name}.${ext}")
Expand All @@ -86,7 +96,7 @@ object AssetListing {
(vals, loadable)

case PathTree.File(name, ext, path) if ImageFileExtensions.contains(ext) =>
val safeName = toSafeName(name)
val safeName = toSafeName(name, ext)

val vals =
s"""${indentSpacesNext}val ${safeName}: AssetName = AssetName("${name}.${ext}")
Expand All @@ -102,7 +112,7 @@ object AssetListing {
(vals, loadable)

case PathTree.File(name, ext, path) =>
val safeName = toSafeName(name)
val safeName = toSafeName(name, ext)

val vals =
s"""${indentSpacesNext}val ${safeName}: AssetName = AssetName("${name}.${ext}")"""
Expand All @@ -127,20 +137,21 @@ object AssetListing {
}

val contents =
s"""${children.map(renderTree(indent + 1)).mkString}""".stripMargin + assetSeq
s"""${children.map(renderTree(indent + 1, toSafeName)).mkString}""".stripMargin + assetSeq

if (safeFolderName.isEmpty) contents
else
s"""${indentSpaces}object ${safeFolderName}:
|${contents}"""
}

def toSafeName(name: String): String =
def toDefaultSafeName: (String, String) => String = { (name: String, _: String) =>
name.replaceAll("[^a-zA-Z0-9]", "-").split("-").toList.filterNot(_.isEmpty) match {
case h :: t if h.take(1).matches("[0-9]") => ("_" :: h :: t.map(_.capitalize)).mkString
case h :: t => (h :: t.map(_.capitalize)).mkString
case l => l.map(_.capitalize).mkString
}
}

val AudioFileExtensions: Set[String] =
Set(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class AcceptanceTests extends munit.FunSuite {
case p if p.startsWith(os.RelPath("ignored-folder")) => true
case p if p.startsWith(os.RelPath("mixed")) => true
case _ => false
}
},
None
)

test("List assets to copy") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class IndigoBuildTests extends munit.FunSuite {
val toCopy: os.RelPath = os.RelPath("some/path/foo.txt")
val include: os.RelPath => Boolean = _ => false
val exclude: os.RelPath => Boolean = _ => false
val indigoAssets: IndigoAssets = IndigoAssets(base, include, exclude)
val indigoAssets: IndigoAssets = IndigoAssets(base, include, exclude, None)

val actual = indigoAssets.isCopyAllowed(toCopy)

Expand All @@ -23,7 +23,7 @@ class IndigoBuildTests extends munit.FunSuite {
val toCopy: os.RelPath = os.RelPath("some/path/foo.txt")
val include: os.RelPath => Boolean = _ => false
val exclude: os.RelPath => Boolean = _ == os.RelPath("path/foo.txt")
val indigoAssets: IndigoAssets = IndigoAssets(base, include, exclude)
val indigoAssets: IndigoAssets = IndigoAssets(base, include, exclude, None)

val actual = indigoAssets.isCopyAllowed(toCopy)

Expand All @@ -36,7 +36,7 @@ class IndigoBuildTests extends munit.FunSuite {
val toCopy: os.RelPath = os.RelPath("some/path/foo.txt")
val include: os.RelPath => Boolean = _ == os.RelPath("path/foo.txt")
val exclude: os.RelPath => Boolean = _ => false
val indigoAssets: IndigoAssets = IndigoAssets(base, include, exclude)
val indigoAssets: IndigoAssets = IndigoAssets(base, include, exclude, None)

val actual = indigoAssets.isCopyAllowed(toCopy)

Expand All @@ -49,7 +49,7 @@ class IndigoBuildTests extends munit.FunSuite {
val toCopy: os.RelPath = os.RelPath("some/path/foo.txt")
val include: os.RelPath => Boolean = _ == os.RelPath("path/foo.txt")
val exclude: os.RelPath => Boolean = _ == os.RelPath("path")
val indigoAssets: IndigoAssets = IndigoAssets(base, include, exclude)
val indigoAssets: IndigoAssets = IndigoAssets(base, include, exclude, None)

val actual = indigoAssets.isCopyAllowed(toCopy)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package indigoplugin.generators

class AssetListingTests extends munit.FunSuite {

test("toSafeName should be able to convert file and folder names into something safe") {
assertEquals(AssetListing.toSafeName("hello"), "hello")
assertEquals(AssetListing.toSafeName("hello-there-01"), "helloThere01")
assertEquals(AssetListing.toSafeName("hello-there-01.jpg"), "helloThere01Jpg")
assertEquals(AssetListing.toSafeName("^hello!there_0 1.jpg"), "helloThere01Jpg")
assertEquals(AssetListing.toSafeName("00-hello"), "_00Hello")
test("should be able to convert file and folder names into something safe (using default)") {
def toSafeName(name: String) = AssetListing.toDefaultSafeName(name, "")

assertEquals(toSafeName("hello"), "hello")
assertEquals(toSafeName("hello-there-01"), "helloThere01")
assertEquals(toSafeName("hello-there-01.jpg"), "helloThere01Jpg")
assertEquals(toSafeName("^hello!there_0 1.jpg"), "helloThere01Jpg")
assertEquals(toSafeName("00-hello"), "_00Hello")
}

test("It should be able to render a simple tree of assets") {
Expand All @@ -19,7 +21,7 @@ class AssetListingTests extends munit.FunSuite {
)

val actual =
AssetListing.renderContent(paths)
AssetListing.renderContent(paths, AssetListing.toDefaultSafeName)

val expected =
"""
Expand Down Expand Up @@ -58,7 +60,7 @@ class AssetListingTests extends munit.FunSuite {
)

val actual =
AssetListing.renderContent(paths)
AssetListing.renderContent(paths, AssetListing.toDefaultSafeName)

val expected =
"""
Expand Down

0 comments on commit 2fc6587

Please sign in to comment.