tools.aqua.bgw.builder.AnimationBuilder.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bgw-core Show documentation
Show all versions of bgw-core Show documentation
A framework for board game applications.
/*
* Copyright 2021 The BoardGameWork Authors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:Suppress("unused")
package tools.aqua.bgw.builder
import javafx.animation.*
import javafx.application.Platform
import javafx.event.EventHandler
import javafx.util.Duration
import tools.aqua.bgw.animation.*
import tools.aqua.bgw.animation.Animation
import tools.aqua.bgw.components.ComponentView
import tools.aqua.bgw.components.gamecomponentviews.CardView
import tools.aqua.bgw.core.Scene
import tools.aqua.bgw.event.AnimationFinishedEvent
import kotlin.random.Random
internal class AnimationBuilder {
companion object {
/**
* Switches between Animations.
*/
internal fun build(scene: Scene, anim: Animation): javafx.animation.Animation =
when (anim) {
is MovementAnimation<*> -> buildMovementAnimation(scene, anim)
is RotationAnimation<*> -> buildRotateAnimation(scene, anim)
is ScaleAnimation<*> -> buildScaleAnimation(scene, anim)
is FadeAnimation<*> -> buildFadeAnimation(scene, anim)
is FlipAnimation<*> -> buildFlipAnimation(scene, anim)
is DelayAnimation -> buildDelayAnimation(scene, anim)
is DiceAnimation<*> -> buildDiceAnimation(scene, anim)
is RandomizeAnimation<*> -> buildRandomizeAnimation(scene, anim)
}
/**
* Builds [MovementAnimation].
*/
private fun buildMovementAnimation(
scene: Scene,
anim: MovementAnimation<*>
): javafx.animation.Animation {
val node = scene.componentsMap[anim.componentView]!!
//Move node to initial position
node.layoutX = anim.fromX
node.layoutY = anim.fromY
//set transition as relative movement
return TranslateTransition(Duration.millis(anim.duration.toDouble()), node).apply {
byX = anim.toX - anim.fromX
byY = anim.toY - anim.fromY
//set on finished
onFinished = EventHandler {
node.layoutX = anim.toX
node.layoutY = anim.toY
node.translateX = 0.0
node.translateY = 0.0
onFinished(scene, anim)
}
}
}
/**
* Builds [RotationAnimation].
*/
private fun buildRotateAnimation(
scene: Scene,
anim: RotationAnimation<*>
): javafx.animation.Animation {
val node = scene.componentsMap[anim.componentView]!!
//Move node to initial position
node.rotate = anim.fromAngle
//set transition as relative movement
return RotateTransition(Duration.millis(anim.duration.toDouble()), node).apply {
byAngle = anim.toAngle - anim.fromAngle
//set on finished
onFinished = EventHandler {
node.rotate = anim.toAngle
node.translateX = 0.0
node.translateY = 0.0
onFinished(scene, anim)
}
}
}
/**
* Builds [FlipAnimation].
*/
private fun buildScaleAnimation(
scene: Scene,
anim: ScaleAnimation<*>
): javafx.animation.Animation {
val node = scene.componentsMap[anim.componentView]!!
//Set initial scale
node.scaleX = anim.fromScaleX
node.scaleY = anim.fromScaleY
return ScaleTransition(Duration.millis(anim.duration.toDouble()), node).apply {
toX = anim.toScaleX
toY = anim.toScaleY
//set on finished
onFinished = EventHandler{
onFinished(scene, anim)
}
}
}
/**
* Builds [FlipAnimation].
*/
private fun buildFadeAnimation(
scene: Scene,
anim: FadeAnimation<*>
): javafx.animation.Animation {
val node = scene.componentsMap[anim.componentView]!!
//Set initial opacity
node.opacity = anim.fromOpacity
return FadeTransition(Duration.millis(anim.duration.toDouble()), node).apply {
fromValue = anim.fromOpacity
toValue = anim.toOpacity
onFinished = EventHandler {
onFinished(scene, anim)
}
}
}
/**
* Builds [FlipAnimation].
*/
private fun buildFlipAnimation(
scene: Scene,
anim: FlipAnimation<*>
): javafx.animation.Animation {
val node = scene.componentsMap[anim.componentView]!!
val fromVisual = VisualBuilder.buildVisual(anim.fromVisual)
val toVisual = VisualBuilder.buildVisual(anim.toVisual).apply { scaleX = 0.0 }
val animation1 = ScaleTransition(Duration.millis(anim.duration / 2.0), fromVisual).apply {
fromX = 1.0
toX = 0.0
}
val animation2 = ScaleTransition(Duration.millis(anim.duration / 2.0), toVisual).apply {
fromX = 0.0
toX = 1.0
}
node.children[0] = fromVisual
animation1.setOnFinished {
node.children[0] = toVisual
animation2.play()
}
//set on finished
animation2.setOnFinished {
onFinished(scene, anim)
}
return animation1
}
/**
* Builds [DelayAnimation].
*/
private fun buildDelayAnimation(
scene: Scene,
anim: DelayAnimation
): javafx.animation.Animation = PauseTransition(
Duration.millis(anim.duration.toDouble())).apply {
//set on finished
onFinished = EventHandler {
onFinished(scene, anim)
}
}
/**
* Builds [DiceAnimation].
*/
private fun buildDiceAnimation(
scene: Scene,
anim: DiceAnimation<*>
): javafx.animation.Animation {
val seq = SequentialTransition()
repeat(anim.speed) {
seq.children += PauseTransition(Duration.millis(anim.duration / anim.speed.toDouble())).apply {
onFinished = EventHandler {
anim.componentView.currentSide = Random.nextInt(anim.componentView.visuals.size)
}
}
}
seq.setOnFinished {
anim.componentView.currentSide = anim.toSide
onFinished(scene, anim)
}
return seq
}
/**
* Builds [RandomizeAnimation].
*/
private fun buildRandomizeAnimation(
scene: Scene,
anim: RandomizeAnimation<*>
): javafx.animation.Animation {
val seq = SequentialTransition()
repeat(anim.speed) {
seq.children += PauseTransition(Duration.millis(anim.duration / anim.speed.toDouble())).apply {
setOnFinished {
(anim.componentView as CardView).backVisual = anim.visuals[Random.nextInt(anim.visuals.size)]
}
}
}
seq.setOnFinished {
(anim.componentView as CardView).backVisual = anim.toVisual
onFinished(scene, anim)
}
return seq
}
/**
* Removes [anim] from animations list and invokes [Animation.onFinished].
*/
private fun onFinished(scene: Scene, anim: Animation) {
scene.animations.remove(anim)
Platform.runLater {
anim.onFinished?.invoke(AnimationFinishedEvent())
}
}
}
}