Skip to content

Commit

Permalink
Merge pull request Hexworks#403 from Hexworks/augment-application
Browse files Browse the repository at this point in the history
Augment application
  • Loading branch information
adam-arold authored Aug 30, 2021
2 parents e286b55 + 82741f8 commit 2c086b4
Show file tree
Hide file tree
Showing 133 changed files with 1,799 additions and 1,554 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group=org.hexworks.zircon
version=2020.2.0-RELEASE
version=2021.1.0-RELEASE

kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.mpp.stability.nowarn=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ import org.hexworks.zircon.api.builder.application.AppConfigBuilder
import org.hexworks.zircon.api.color.TileColor
import org.hexworks.zircon.api.component.ColorTheme
import org.hexworks.zircon.api.data.Size
import org.hexworks.zircon.api.modifier.TextureTransformModifier
import org.hexworks.zircon.api.resource.TilesetResource
import org.hexworks.zircon.api.tileset.TextureTransformer
import org.hexworks.zircon.api.tileset.TilesetFactory
import org.hexworks.zircon.api.tileset.TilesetLoader
import org.hexworks.zircon.internal.renderer.Renderer
import org.hexworks.zircon.internal.resource.TileType
import org.hexworks.zircon.internal.resource.TilesetType
import kotlin.reflect.KClass
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmName

/**
* Object that encapsulates the configuration parameters for an [Application].
Expand Down Expand Up @@ -94,7 +101,7 @@ class AppConfig internal constructor(
val fpsLimit: Int,
/**
* Sets the [DebugConfig] to be used when [debugMode] is `true`.
* By default all settings are `false`.
* By default, all settings are `false`.
*/
val debugConfig: DebugConfig,
/**
Expand All @@ -118,15 +125,20 @@ class AppConfig internal constructor(
* to an icon image that will be used in the application window.
*/
val iconPath: String?,
/**
* If set, contains custom properties that plugin authors can set and access.
*/
internal val customProperties: Map<AppConfigKey<*>, Any>,
/**
* If set [tilesetLoaders] will contain the list of [TilesetLoaders][TilesetLoader] to try to use
* before using the default [TilesetLoader] of the [Renderer].
*/
val tilesetLoaders: List<TilesetLoader<*>>
val tilesetLoaders: Map<Pair<TileType, TilesetType>, TilesetFactory<*>>,
/**
* If set [modifierSupports] will contain the list of [TextureTransformer]s to try to use
* before using the default [TextureTransformer] of the [Renderer].
*/
var modifierSupports: Map<KClass<out TextureTransformModifier>, ModifierSupport<*>>,
/**
* If set, contains custom properties that plugin authors can set and access.
*/
internal val customProperties: Map<AppConfigKey<*>, Any>,
) {

/**
Expand Down Expand Up @@ -173,3 +185,14 @@ class AppConfig internal constructor(

}
}

@JvmName("filterTilesetFactoriesByType")
@Suppress("UNCHECKED_CAST")
fun <T : Any> Map<Pair<TileType, TilesetType>, TilesetFactory<*>>.filterByType(type: KClass<T>): Map<Pair<TileType, TilesetType>, TilesetFactory<T>> {
return this.filterValues { it.targetType == type } as Map<Pair<TileType, TilesetType>, TilesetFactory<T>>
}

@Suppress("UNCHECKED_CAST")
fun <T : Any> Map<KClass<out TextureTransformModifier>, ModifierSupport<*>>.filterByType(type: KClass<T>): Map<KClass<out TextureTransformModifier>, ModifierSupport<T>> {
return this.filterValues { it.targetType == type } as Map<KClass<out TextureTransformModifier>, ModifierSupport<T>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.hexworks.zircon.api.application

import org.hexworks.cobalt.events.api.Subscription
import org.hexworks.zircon.api.grid.TileGrid
import org.hexworks.zircon.internal.application.InternalApplication

/**
* An [Application] enhances a [TileGrid] with continuous rendering,
Expand Down Expand Up @@ -49,4 +50,9 @@ interface Application {
* block the rendering. Very fast is `<1ms`.
*/
fun afterRender(listener: (RenderData) -> Unit): Subscription

/**
* Exposes the internal API of this [Application].
*/
fun asInternal(): InternalApplication
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.hexworks.zircon.api.application

import org.hexworks.zircon.api.builder.application.ModifierSupportBuilder
import org.hexworks.zircon.api.builder.application.ShortcutsConfigBuilder
import org.hexworks.zircon.api.data.Tile
import org.hexworks.zircon.api.modifier.TextureTransformModifier
import org.hexworks.zircon.api.tileset.TextureTransformer
import org.hexworks.zircon.api.tileset.TileTexture
import org.hexworks.zircon.api.uievent.KeyCode
import org.hexworks.zircon.api.uievent.KeyboardEventMatcher
import org.hexworks.zircon.api.uievent.KeyboardEventType
import kotlin.jvm.JvmStatic
import kotlin.reflect.KClass

/**
* Contains all the necessary data / functionality to support drawing a specific [modifierType].
*/
class ModifierSupport<T : Any> internal constructor(
val modifierType: KClass<out TextureTransformModifier>,
val targetType: KClass<T>,
val transformer: TextureTransformer<T>
) {
companion object {

@JvmStatic
fun <T: Any> newBuilder() = ModifierSupportBuilder.newBuilder<T>()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.hexworks.zircon.api.application

import org.hexworks.cobalt.core.behavior.DisposeState
import org.hexworks.cobalt.core.behavior.DisposedByHand
import org.hexworks.cobalt.events.api.EventBus
import org.hexworks.cobalt.events.api.Subscription
import org.hexworks.zircon.api.grid.TileGrid
import org.hexworks.zircon.internal.application.InternalApplication
import org.hexworks.zircon.internal.event.ZirconScope

/**
* Use this class when you don't want to have an application implementation, and
* you're using just a Renderer
*/
class NoOpApplication(
override val config: AppConfig,
override val eventBus: EventBus,
override val eventScope: ZirconScope
) : InternalApplication {

override lateinit var tileGrid: TileGrid

override fun start() {}

override fun pause() {}

override fun resume() {}

override fun stop() {}

override fun beforeRender(listener: (RenderData) -> Unit) = NoOpSubscription

override fun afterRender(listener: (RenderData) -> Unit) = NoOpSubscription

override fun asInternal() = this

object NoOpSubscription : Subscription {
override val disposeState: DisposeState = DisposedByHand

override fun dispose(disposeState: DisposeState) {}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,28 @@ import org.hexworks.zircon.api.builder.Builder
import org.hexworks.zircon.api.color.TileColor
import org.hexworks.zircon.api.component.ColorTheme
import org.hexworks.zircon.api.data.Size
import org.hexworks.zircon.api.modifier.TextureTransformModifier
import org.hexworks.zircon.api.resource.TilesetResource
import org.hexworks.zircon.api.tileset.TextureTransformer
import org.hexworks.zircon.api.tileset.TilesetFactory
import org.hexworks.zircon.api.tileset.TilesetLoader
import org.hexworks.zircon.internal.config.RuntimeConfig
import org.hexworks.zircon.internal.dsl.ZirconDsl
import org.hexworks.zircon.internal.renderer.Renderer
import org.hexworks.zircon.internal.resource.TileType
import org.hexworks.zircon.internal.resource.TilesetType
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmStatic
import kotlin.reflect.KClass


/**
* This *builder* class can be used to build [AppConfig] instances. This builder
* has sensible default values so
* @see AppConfig for all the default values.
*/
@Suppress("unused")
@ZirconDsl
class AppConfigBuilder private constructor(
/**
* The amount of time (in milliseconds) that should pass before the next
Expand Down Expand Up @@ -96,7 +105,7 @@ class AppConfigBuilder private constructor(
var fpsLimit: Int = 60,
/**
* Sets the [DebugConfig] to be used when [debugMode] is `true`.
* By default all settings are `false`.
* By default, all settings are `false`.
*/
var debugConfig: DebugConfig = DebugConfig.defaultConfig(),
/**
Expand Down Expand Up @@ -125,10 +134,15 @@ class AppConfigBuilder private constructor(
*/
var customProperties: Map<AppConfigKey<*>, Any> = emptyMap(),
/**
* If set [tilesetLoaders] will contain the list of [TilesetLoaders][TilesetLoader] to try to use
* If set [tilesetFactories] will contain the list of [TilesetLoaders][TilesetLoader] to try to use
* before using the default [TilesetLoader] of the [Renderer].
*/
var tilesetLoaders: List<TilesetLoader<*>> = emptyList()
var tilesetFactories: Map<Pair<TileType, TilesetType>, TilesetFactory<*>> = mapOf(),
/**
* If set [modifierSupports] will contain the list of [TextureTransformer]s to try to use
* before using the default [TextureTransformer] of the [Renderer].
*/
var modifierSupports: Map<KClass<out TextureTransformModifier>, ModifierSupport<*>> = mapOf()
) : Builder<AppConfig> {

fun withDebugConfig(debugConfig: DebugConfig) = also {
Expand Down Expand Up @@ -233,15 +247,23 @@ class AppConfigBuilder private constructor(
}

/**
* Sets the additional tileset loaders that should be attempted before falling back to the default
* tileset loader the renderer uses.
*
* **Order matters.** Loaders earlier in the list will be attempted first.
* Sets custom [TilesetFactory] objects that will be used by the tileset loader. There can be only one
* [TilesetFactory] for a combination of [TileType] + [TilesetType]
*/
fun withTilesetLoaders(vararg tilesetLoaders: TilesetLoader<*>) = also {
this.tilesetLoaders = tilesetLoaders.toList()
fun withTilesetFactories(vararg tilesetFactories: TilesetFactory<*>) = also {
this.tilesetFactories =
this.tilesetFactories + tilesetFactories.associateBy { it.supportedTileType to it.supportedTilesetType }
}

/**
* Sets custom [TilesetFactory] objects that will be used by the tileset loader. There can be only one
* [TilesetFactory] for a combination of [TileType] + [TilesetType]
*/
fun withModifierSupports(vararg modifierSupports: ModifierSupport<*>) =
also {
this.modifierSupports = this.modifierSupports + modifierSupports.associateBy { it.modifierType }
}

override fun build() = AppConfig(
blinkLengthInMilliSeconds = blinkLengthInMilliSeconds,
cursorStyle = cursorStyle,
Expand All @@ -263,7 +285,8 @@ class AppConfigBuilder private constructor(
iconData = iconData,
iconPath = iconPath,
customProperties = customProperties,
tilesetLoaders = tilesetLoaders
tilesetLoaders = tilesetFactories,
modifierSupports = modifierSupports
).also {
RuntimeConfig.config = it
}
Expand All @@ -289,7 +312,8 @@ class AppConfigBuilder private constructor(
iconData = iconData,
iconPath = iconPath,
customProperties = customProperties,
tilesetLoaders = tilesetLoaders
tilesetFactories = tilesetFactories,
modifierSupports = modifierSupports
)

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.hexworks.zircon.api.builder.application

import org.hexworks.zircon.api.application.ModifierSupport
import org.hexworks.zircon.api.builder.Builder
import org.hexworks.zircon.api.data.Tile
import org.hexworks.zircon.api.modifier.TextureTransformModifier
import org.hexworks.zircon.api.tileset.TextureTransformer
import org.hexworks.zircon.api.tileset.TileTexture
import org.hexworks.zircon.internal.dsl.ZirconDsl
import org.hexworks.zircon.internal.tileset.impl.DefaultTextureTransformer
import kotlin.reflect.KClass
import kotlin.jvm.JvmStatic

@ZirconDsl
class ModifierSupportBuilder<T : Any> private constructor(
var modifierType: KClass<out TextureTransformModifier>? = null,
var targetType: KClass<T>? = null,
var transformerFunction: ((texture: TileTexture<T>, tile: Tile) -> TileTexture<T>)? = null,
var transformer: TextureTransformer<T>? = null
) : Builder<ModifierSupport<T>> {

override fun createCopy() = ModifierSupportBuilder(
modifierType = modifierType,
targetType = targetType,
transformerFunction = transformerFunction
)

override fun build(): ModifierSupport<T> {
requireNotNull(targetType) {
"Target type is missing."
}
requireNotNull(modifierType) {
"Modifier type is missing"
}
require(transformerFunction != null || transformer != null) {
"Transformer is missing."
}
return ModifierSupport(
modifierType = modifierType!!,
targetType = targetType!!,
transformer = transformer ?: DefaultTextureTransformer(targetType!!, transformerFunction!!)
)
}

companion object {

@JvmStatic
fun <T : Any> newBuilder() = ModifierSupportBuilder<T>()

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import org.hexworks.zircon.api.builder.Builder
import org.hexworks.zircon.api.uievent.KeyCode
import org.hexworks.zircon.api.uievent.KeyboardEventMatcher
import org.hexworks.zircon.api.uievent.KeyboardEventType
import org.hexworks.zircon.internal.dsl.ZirconDsl
import kotlin.jvm.JvmStatic

/**
* [Builder] for creating [ShortcutsConfig]s.
*/
@ZirconDsl
class ShortcutsConfigBuilder private constructor(
/**
* Default is `<Space>` press.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.hexworks.zircon.api.builder.application

import org.hexworks.zircon.api.builder.Builder
import org.hexworks.zircon.api.resource.TilesetResource
import org.hexworks.zircon.api.tileset.Tileset
import org.hexworks.zircon.api.tileset.TilesetFactory
import org.hexworks.zircon.internal.dsl.ZirconDsl
import org.hexworks.zircon.internal.resource.TileType
import org.hexworks.zircon.internal.resource.TilesetType
import org.hexworks.zircon.internal.tileset.impl.DefaultTilesetFactory
import kotlin.reflect.KClass
import kotlin.jvm.JvmStatic

@ZirconDsl
class TilesetFactoryBuilder<S : Any> private constructor(
var targetType: KClass<S>? = null,
var supportedTileType: TileType? = null,
var supportedTilesetType: TilesetType? = null,
var factoryFunction: ((TilesetResource) -> Tileset<S>)? = null

) : Builder<TilesetFactory<S>> {

override fun createCopy() = TilesetFactoryBuilder(
targetType = targetType,
supportedTileType = supportedTileType,
supportedTilesetType = supportedTilesetType,
factoryFunction = factoryFunction
)

override fun build(): TilesetFactory<S> {
requireNotNull(targetType) {
"Target type is missing."
}
requireNotNull(supportedTileType) {
"Supported tile type is missing."
}
requireNotNull(supportedTilesetType) {
"Supported tileset type is missing."
}
requireNotNull(factoryFunction) {
"Factory function is missing"
}
return DefaultTilesetFactory(
targetType = targetType!!,
supportedTileType = supportedTileType!!,
supportedTilesetType = supportedTilesetType!!,
factoryFunction = factoryFunction!!
)
}

companion object {

@JvmStatic
fun <S : Any> newBuilder() = TilesetFactoryBuilder<S>()

}
}
Loading

0 comments on commit 2c086b4

Please sign in to comment.