Skip to content

Instantly share code, notes, and snippets.

@nilium
Created July 22, 2014 01:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nilium/b9f0088d525da4848d5c to your computer and use it in GitHub Desktop.
Save nilium/b9f0088d525da4848d5c to your computer and use it in GitHub Desktop.
package net.spifftastic.ascension2.backend
import net.spifftastic.spastic.graphics.ColorSpace
abstract class ColorGenerator {
trait TouchColorGenerator {
/**
* Modifies the given HSV color in hsvInOut depending on the bar state and
* alpha. This color stage is applied before color shimmer is applied.
* @param state The bar state to use for the color.
* @param alpha How much blending to apply between a color's off/on or
* touched/untouched state.
* @param hsvInOut An HSV color. The resulting HSV color must be placed in
* this array. Hue, saturation, and value are always at indices 0, 1,
* and 2 respectively. Other indices are undefined.
*/
def pre(state: BarState, alpha: Float, hsvInOut: Array[Float]): Unit
/**
* Modifies the given RGB color in rgbInOut depending on the bar state and
* alpha. This color stage is applied after color shimmer is applied.
* @param state The bar state to use for the color.
* @param alpha How much blending to apply between a color's off/on or
* touched/untouched state.
* @param rgbInOut An RGB color. The resulting RGB color must be placed in
* this array. Red, green, and blue components are always at indices 0,
* 1, and 2 respectively. Other indices are undefined.
*/
def post(state: BarState, alpha: Float, rgbInOut: Array[Float]): Unit
}
/**
* Returns a touch color generator that makes use of custom touch colors. This may be called
* during each call to prepare, so it's worth caching the result if it doesn't change.
* @return a TouchColorGenerator.
*/
def specificTouchColorGenerator: TouchColorGenerator
/**
* Returns a touch color generator that doesn't make use of custom touch colors. This may be
* called during each call to prepare, so it's worth caching the result if it doesn't change.
* @return a TouchColorGenerator.
*/
def baseTouchColorGenerator: TouchColorGenerator
/** The current touch color generator as acquired by prepare(BarState). */
private[this] var touchGen: TouchColorGenerator = null
private[this] val shimmerTemp = new Array[Float](3)
/**
* Given the BarState, do any preparation necessary for computing bar colors. This is called once
* per frame. By default, it simply caches the TouchColorGenerator based on the current config.
* @param state The bar state to prepare with.
*/
def prepare(state: BarState): Unit = {
if (state.config.useTouchColor) touchGen = specificTouchColorGenerator
else touchGen = baseTouchColorGenerator
}
@inline
final def applyShimmer(state: BarState, barIndex: Int, output: Array[Float]): Unit = {
state.shimmerForBar(barIndex, shimmerTemp)
val hue = output(0) + shimmerTemp(0)
if (hue < 0f) output(0) = hue + 1f
else if (hue > 1f) output(0) = hue - 1f
else output(0) = hue
output(1) += shimmerTemp(1)
output(2) += shimmerTemp(2)
}
@inline
final def initColorForBar(state: BarState, barIndex: Int, output: Array[Float]): Unit = {
state.baseColorForBar(barIndex, output)
}
@inline
final def applyPreTouchColor(state: BarState, barIndex: Int, transition: Float, output: Array[Float]): Unit = {
touchGen.pre(state, transition, output)
}
@inline
final def applyPostTouchColor(state: BarState, barIndex: Int, transition: Float, output: Array[Float]): Unit = {
touchGen.post(state, transition, output)
}
/**
* Gets the RGB color of a bar given the touch state provided. The default implementation
* simply calls initColorForBar, applyPreTouchColor, applyShimmer, converts from HSV to RGB,
* and calls then applyPostTouchColor in order. Subclasses should implement this without
* calling into the super method, as the super method overwrites any current output. @param
* state The bar state to use when generating the color.
*
* @param state The BarState to compute with.
* @param barIndex The bar index to get the color of.
* @param output An array of at least length 3 to write the HSV components to. RGB components are
* always written to indices 0, 1, and 2 respectively.
*/
def colorForBar(state: BarState, barIndex: Int, output: Array[Float]): Unit = {
initColorForBar(state, barIndex, output)
applyPreTouchColor(state, barIndex, state.transitionForBar(barIndex), output)
applyShimmer(state, barIndex, output)
ColorSpace.RGB.coerce(ColorSpace.HSV, output, 0)
applyPostTouchColor(state, barIndex, state.transitionForBar(barIndex), output)
}
}
package net.spifftastic.ascension2.backend
class GelColorGenerator extends ColorGenerator {
object BaseTouchColorGenerator extends TouchColorGenerator {
def pre(state: BarState, alpha: Float, hsvInOut: Array[Float]): Unit = {
hsvInOut(2) *= 0.4f + (1f - alpha) * 0.6f
}
def post(state: BarState, alpha: Float, rgbInOut: Array[Float]): Unit = ()
}
object SpecificTouchColorGenerator extends TouchColorGenerator {
def pre(state: BarState, alpha: Float, hsvInOut: Array[Float]): Unit = ()
def post(state: BarState, alpha: Float, rgbInOut: Array[Float]): Unit = {
val color = state.config.touchColor
val beta = 1f - alpha
rgbInOut(0) = rgbInOut(0) * beta + color.red * alpha
rgbInOut(1) = rgbInOut(1) * beta + color.green * alpha
rgbInOut(2) = rgbInOut(2) * beta + color.blue * alpha
}
}
/**
* Returns a touch color generator that makes use of custom touch colors. This may be called
* during each call to prepare, so it's worth caching the result if it doesn't change.
* @return a TouchColorGenerator.
*/
def specificTouchColorGenerator = SpecificTouchColorGenerator
/**
* Returns a touch color generator that doesn't make use of custom touch colors. This may be
* called during each call to prepare, so it's worth caching the result if it doesn't change.
* @return a TouchColorGenerator.
*/
def baseTouchColorGenerator = BaseTouchColorGenerator
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment