Skip to content

Commit

Permalink
Refactoring IndigoOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
davesmith00000 committed Aug 28, 2023
1 parent 5d985ca commit 37a9995
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 79 deletions.
244 changes: 193 additions & 51 deletions indigo-plugin/indigo-plugin/src/indigoplugin/IndigoOptions.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,111 @@
package indigoplugin

/** Represents the various options that go into an Indigo game build.
*
* @param metadata
* Metadata about your game, such as the title.
* @param assets
* Represents you game's assets processing.
* @param electron
* Represents options specific to Electron builds of your game.
*/
final case class IndigoOptions(
metadata: IndigoGameMetadata,
assets: IndigoAssets,
electron: IndigoElectronOptions
) {

/** Sets a new title for your game's window / title bar / tab */
def withTitle(newTitle: String): IndigoOptions =
this.copy(metadata = metadata.withTitle(newTitle))

/** Make the cursor visible */
def cursorVisible: IndigoOptions =
this.copy(metadata = metadata.cursorVisible)

/** Hide the cursor */
def cursorHidden: IndigoOptions =
this.copy(metadata = metadata.cursorHidden)

/** Sets the background color, any valid CSS color representation acceptable, e.g. 'black' or '#000000' */
def withBackgroundColor(cssColorValue: String): IndigoOptions =
this.copy(metadata = metadata.withBackgroundColor(cssColorValue))

/** Set the background color from RGBA values */
def withBackgroundColor(r: Double, g: Double, b: Double, a: Double): IndigoOptions =
this.copy(metadata = metadata.withBackgroundColor(r, g, b, a))

/** Set the background color from RGB values */
def withBackgroundColor(r: Double, g: Double, b: Double): IndigoOptions =
this.copy(metadata = metadata.withBackgroundColor(r, g, b))

/** Sets the asset directory path */
def withAssetDirectory(path: String): IndigoOptions =
this.copy(assets = assets.withAssetDirectory(path))
def withAssetDirectory(path: os.Path): IndigoOptions =
this.copy(assets = assets.withAssetDirectory(path))

/** Set the window start width */
def withWindowWidth(value: Int): IndigoOptions =
this.copy(metadata = metadata.withWindowWidth(value))

/** Set the window start height */
def withWindowHeight(value: Int): IndigoOptions =
this.copy(metadata = metadata.withWindowHeight(value))

/** Set the window start width */
def withWindowSize(w: Int, h: Int): IndigoOptions =
this.copy(metadata = metadata.withWindowSize(w, h))

/** Electron will limit the frame rate using the default browser refresh rate, typically it will sync with your
* monitor's refresh rate. It is recommended that you do this, and set your indigo config to limit the framerate too.
*/
def electronLimitsFrameRate: IndigoOptions =
this.copy(electron = electron.electronLimitsFrameRate)

/** Electron will not limit the frame rate. */
def electronUnlimitedFrameRate: IndigoOptions =
this.copy(electron = electron.electronUnlimitedFrameRate)

/** Sets the electron installation type. It is recommended that, during development at least, you set this to
* `ElectronInstall.Latest` to take advantage of performance improvements.
*/
def withElectronInstallType(value: ElectronInstall): IndigoOptions =
this.copy(electron = electron.withElectronInstallType(value))

/** Use the latest version of Electron with the `indigoRun` command, which will be installed with NPM. */
def useLatestElectron: IndigoOptions =
withElectronInstallType(ElectronInstall.Latest)

/** Use a globally installed version of Electron with the `indigoRun` command. Global installs of Electron have the
* advantage of a slightly faster `indigoRun` startup time, however, global Electron installs can be of dubious
* quality, and suffer from poor performance or limited features. Not recommended.
*/
def useGlobalElectron: IndigoOptions =
withElectronInstallType(ElectronInstall.Global)

/** Use a specific version of Electron, follows normal NPM version formats. */
def useElectronVersion(version: String): IndigoOptions =
withElectronInstallType(ElectronInstall.Version(version))

/** Use an Electron install at the specified path with the `indigoRun` command. */
def useElectronExecutable(path: String): IndigoOptions =
withElectronInstallType(ElectronInstall.PathToExecutable(path))

}

object IndigoOptions {

/** Default configuration for an Indigo game. */
val defaults: IndigoOptions =
IndigoOptions(
metadata = IndigoGameMetadata.defaults,
assets = IndigoAssets.defaults,
electron = IndigoElectronOptions.defaults
)

}

/** Represents the various options that go into an Indigo game build.
*
* @param title
Expand All @@ -8,47 +114,37 @@ package indigoplugin
* Show the cursor? Default 'true'.
* @param backgroundColor
* HTML page background color Default 'white'.
* @param gameAssetsDirectory
* Project relative path to a directory that contains all of the assets the game needs to load. Default './assets'.
* @param windowStartWidth
* @param width
* Initial window width. Default '550'.
* @param windowStartHeight
* @param height
* Initial window height. Default '400'.
* @param disableFrameRateLimit
* If possible, disables the runtime's frame rate limit, recommended to be `false`. Default 'false'.
* @param electronInstall
* How should electron be run? ElectronInstall.Global | ElectronInstall.Version(version: String) |
* ElectronInstall.Latest | ElectronInstall.PathToExecutable(path: String). Default 'ElectronInstall.Latest'.
*/
final case class IndigoOptions(
final case class IndigoGameMetadata(
title: String,
showCursor: Boolean,
backgroundColor: String,
gameAssetsDirectory: os.Path,
windowStartWidth: Int,
windowStartHeight: Int,
disableFrameRateLimit: Boolean,
electronInstall: ElectronInstall
width: Int,
height: Int
) {

/** Sets a new title for your game's window / title bar / tab */
def withTitle(newTitle: String): IndigoOptions =
def withTitle(newTitle: String): IndigoGameMetadata =
this.copy(title = newTitle)

/** Make the cursor visible */
def cursorVisible: IndigoOptions =
def cursorVisible: IndigoGameMetadata =
this.copy(showCursor = true)

/** Hide the cursor */
def cursorHidden: IndigoOptions =
def cursorHidden: IndigoGameMetadata =
this.copy(showCursor = false)

/** Sets the background color, any valid CSS color representation acceptable, e.g. 'black' or '#000000' */
def withBackgroundColor(cssColorValue: String): IndigoOptions =
def withBackgroundColor(cssColorValue: String): IndigoGameMetadata =
this.copy(backgroundColor = cssColorValue)

/** Set the background color from RGBA values */
def withBackgroundColor(r: Double, g: Double, b: Double, a: Double): IndigoOptions = {
def withBackgroundColor(r: Double, g: Double, b: Double, a: Double): IndigoGameMetadata = {
val convert: Double => String = d => {
val hex = Integer.toHexString((Math.min(1, Math.max(0, d)) * 255).toInt)
if (hex.length == 1) "0" + hex else hex
Expand All @@ -57,81 +153,127 @@ final case class IndigoOptions(
}

/** Set the background color from RGB values */
def withBackgroundColor(r: Double, g: Double, b: Double): IndigoOptions = {
def withBackgroundColor(r: Double, g: Double, b: Double): IndigoGameMetadata = {
val convert: Double => String = d => {
val hex = Integer.toHexString((Math.min(1, Math.max(0, d)) * 255).toInt)
if (hex.length == 1) "0" + hex else hex
}
withBackgroundColor("#" + convert(r) + convert(g) + convert(b))
}

/** Sets the asset directory path */
def withAssetDirectory(path: String): IndigoOptions =
this.copy(
gameAssetsDirectory =
if (path.startsWith("/")) os.Path(path)
else os.RelPath(path).resolveFrom(os.pwd)
)
def withAssetDirectory(path: os.Path): IndigoOptions =
this.copy(gameAssetsDirectory = path)

/** Set the window start width */
def withWindowStartWidth(value: Int): IndigoOptions =
this.copy(windowStartWidth = value)
def withWindowWidth(value: Int): IndigoGameMetadata =
this.copy(width = value)

/** Set the window start height */
def withWindowStartHeight(value: Int): IndigoOptions =
this.copy(windowStartHeight = value)
def withWindowHeight(value: Int): IndigoGameMetadata =
this.copy(height = value)

/** Set the window start width */
def withWindowSize(w: Int, h: Int): IndigoGameMetadata =
this.copy(width = w, height = h)

}

object IndigoGameMetadata {

/** The default metadata for an Indigo game. */
val defaults: IndigoGameMetadata =
IndigoGameMetadata(
title = "Made with Indigo",
showCursor = true,
backgroundColor = "white",
width = 550,
height = 400
)
}

/** Represents options specific to Electron builds of your game.
*
* @param disableFrameRateLimit
* If possible, disables the runtime's frame rate limit, recommended to be `false`. Default 'false'.
* @param electronInstall
* How should electron be run? ElectronInstall.Global | ElectronInstall.Version(version: String) |
* ElectronInstall.Latest | ElectronInstall.PathToExecutable(path: String). Default 'ElectronInstall.Latest'.
*/
final case class IndigoElectronOptions(
disableFrameRateLimit: Boolean,
electronInstall: ElectronInstall
) {

/** Electron will limit the frame rate using the default browser refresh rate, typically it will sync with your
* monitor's refresh rate. It is recommended that you do this, and set your indigo config to limit the framerate too.
*/
def electronLimitsFrameRate: IndigoOptions =
def electronLimitsFrameRate: IndigoElectronOptions =
this.copy(disableFrameRateLimit = false)

/** Electron will not limit the frame rate. */
def electronUnlimitedFrameRate: IndigoOptions =
def electronUnlimitedFrameRate: IndigoElectronOptions =
this.copy(disableFrameRateLimit = true)

/** Sets the electron installation type. It is recommended that, during development at least, you set this to
* `ElectronInstall.Latest` to take advantage of performance improvements.
*/
def withElectronInstallType(value: ElectronInstall): IndigoOptions =
def withElectronInstallType(value: ElectronInstall): IndigoElectronOptions =
this.copy(electronInstall = value)

/** Use the latest version of Electron with the `indigoRun` command, which will be installed with NPM. */
def useLatestElectron: IndigoOptions =
def useLatestElectron: IndigoElectronOptions =
withElectronInstallType(ElectronInstall.Latest)

/** Use a globally installed version of Electron with the `indigoRun` command. Global installs of Electron have the
* advantage of a slightly faster `indigoRun` startup time, however, global Electron installs can be of dubious
* quality, and suffer from poor performance or limited features. Not recommended.
*/
def useGlobalElectron: IndigoOptions =
def useGlobalElectron: IndigoElectronOptions =
withElectronInstallType(ElectronInstall.Global)

/** Use a specific version of Electron, follows normal NPM version formats. */
def useElectronVersion(version: String): IndigoOptions =
def useElectronVersion(version: String): IndigoElectronOptions =
withElectronInstallType(ElectronInstall.Version(version))

/** Use an Electron install at the specified path with the `indigoRun` command. */
def useElectronExecutable(path: String): IndigoOptions =
def useElectronExecutable(path: String): IndigoElectronOptions =
withElectronInstallType(ElectronInstall.PathToExecutable(path))

}

object IndigoOptions {
object IndigoElectronOptions {

val defaults: IndigoOptions =
IndigoOptions(
title = "Made with Indigo",
showCursor = true,
backgroundColor = "white",
gameAssetsDirectory = os.pwd / "assets",
windowStartWidth = 550,
windowStartHeight = 400,
/** Default settings for Electron */
val defaults: IndigoElectronOptions =
IndigoElectronOptions(
disableFrameRateLimit = false,
electronInstall = indigoplugin.ElectronInstall.Latest
)
}

/** Represents you game's assets processing.
*
* @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.Path
) {

/** Sets the asset directory path */
def withAssetDirectory(path: String): IndigoAssets =
this.copy(
gameAssetsDirectory =
if (path.startsWith("/")) os.Path(path)
else os.RelPath(path).resolveFrom(os.pwd)
)
def withAssetDirectory(path: os.Path): IndigoAssets =
this.copy(gameAssetsDirectory = path)

}

object IndigoAssets {

/** Default settings for an Indigo game's asset management */
val defaults: IndigoAssets =
IndigoAssets(
gameAssetsDirectory = os.pwd / "assets"
)
}
23 changes: 12 additions & 11 deletions indigo-plugin/indigo-plugin/src/indigoplugin/core/IndigoBuild.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,30 @@ package indigoplugin.core
import os._
import indigoplugin.templates.HtmlTemplate
import indigoplugin.templates.SupportScriptTemplate
import indigoplugin.datatypes.TemplateOptions
import indigoplugin.datatypes.DirectoryStructure
import indigoplugin.utils.Utils
import indigoplugin.IndigoOptions

object IndigoBuild {

def build(
templateOptions: TemplateOptions,
scriptPathBase: Path,
options: IndigoOptions,
directoryStructure: DirectoryStructure,
scriptNames: List[String]
): Unit = {

val scriptName = findScriptName(scriptNames, templateOptions.scriptPathBase)
val scriptName = findScriptName(scriptNames, scriptPathBase)

// copy built js file into scripts dir
IndigoBuild.copyScript(templateOptions, directoryStructure.artefacts, scriptName)
IndigoBuild.copyScript(scriptPathBase, directoryStructure.artefacts, scriptName)

// copy assets into folder
IndigoBuild.copyAssets(templateOptions.gameAssetsDirectoryPath, directoryStructure.assets)
IndigoBuild.copyAssets(options.assets.gameAssetsDirectory, directoryStructure.assets)

// copy built js source map file into scripts dir
IndigoBuild.copyScript(
templateOptions,
scriptPathBase,
directoryStructure.artefacts,
scriptName + ".map"
)
Expand All @@ -40,10 +41,10 @@ object IndigoBuild {

// Fill out html template
val html = HtmlTemplate.template(
templateOptions.title,
templateOptions.showCursor,
options.metadata.title,
options.metadata.showCursor,
scriptName,
templateOptions.backgroundColor
options.metadata.backgroundColor
)

// Write out file
Expand Down Expand Up @@ -85,8 +86,8 @@ object IndigoBuild {
}

@SuppressWarnings(Array("org.wartremover.warts.Throw"))
def copyScript(templateOptions: TemplateOptions, destScriptsFolder: Path, fileName: String): Unit = {
val scriptFile = templateOptions.scriptPathBase / fileName
def copyScript(scriptPathBase: Path, destScriptsFolder: Path, fileName: String): Unit = {
val scriptFile = scriptPathBase / fileName

if (os.exists(scriptFile))
os.copy(scriptFile, destScriptsFolder / fileName, true, false, false, false, false)
Expand Down
Loading

0 comments on commit 37a9995

Please sign in to comment.