Skip to content

Commit 92ef02d

Browse files
committed
add layerstates and some tests and a bit of cleanup
1 parent 1f61fec commit 92ef02d

File tree

12 files changed

+343
-68
lines changed

12 files changed

+343
-68
lines changed

app/src/main/java/app/rive/runtime/example/AndroidPlayerActivity.kt

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -102,30 +102,30 @@ class AndroidPlayerActivity : AppCompatActivity() {
102102
}
103103

104104
fun addAnimationControl(animationName: String): View {
105-
var layout = LinearLayout(this)
105+
val layout = LinearLayout(this)
106106
layout.orientation = LinearLayout.HORIZONTAL
107107
layout.gravity = Gravity.END
108108

109-
var text = TextView(this)
109+
val text = TextView(this)
110110
text.text = animationName
111111

112-
var playButton = AppCompatButton(this)
112+
val playButton = AppCompatButton(this)
113113
playButton.text = ">"
114114
playButton.background.setTint(Color.WHITE)
115115
playButton.setOnClickListener {
116116
animationView.play(animationName, loop, direction)
117117
}
118118
playButtonMap[animationName] = playButton
119119

120-
var pauseButton = AppCompatButton(this)
120+
val pauseButton = AppCompatButton(this)
121121
pauseButton.text = "||"
122122
pauseButton.background.setTint(Color.WHITE)
123123
pauseButton.setOnClickListener {
124124
animationView.pause(animationName)
125125
}
126126
pauseButtonMap[animationName] = pauseButton
127127

128-
var stopButton = AppCompatButton(this)
128+
val stopButton = AppCompatButton(this)
129129
stopButton.text = "[]"
130130
stopButton.background.setTint(Color.RED)
131131
stopButton.setOnClickListener {
@@ -185,13 +185,13 @@ class AndroidPlayerActivity : AppCompatActivity() {
185185

186186

187187
stateMachine.inputs.forEach {
188-
val layout = LinearLayout(this)
189-
layout.orientation = LinearLayout.HORIZONTAL
190-
layout.gravity = Gravity.END
188+
val innerLayout = LinearLayout(this)
189+
innerLayout.orientation = LinearLayout.HORIZONTAL
190+
innerLayout.gravity = Gravity.END
191191

192-
val text = TextView(this)
193-
text.text = it.name
194-
layout.addView(text)
192+
val innerText = TextView(this)
193+
innerText.text = it.name
194+
innerLayout.addView(innerText)
195195

196196
if (it.isTrigger) {
197197
val triggerButton = AppCompatButton(this)
@@ -200,7 +200,7 @@ class AndroidPlayerActivity : AppCompatActivity() {
200200
triggerButton.setOnClickListener { _ ->
201201
animationView.fireState(stateMachineName, it.name)
202202
}
203-
layout.addView(triggerButton)
203+
innerLayout.addView(triggerButton)
204204
}
205205

206206
if (it.isBoolean) {
@@ -211,7 +211,7 @@ class AndroidPlayerActivity : AppCompatActivity() {
211211
boolBox.setOnCheckedChangeListener { _, b ->
212212
animationView.setBooleanState(stateMachineName, it.name, b)
213213
}
214-
layout.addView(boolBox)
214+
innerLayout.addView(boolBox)
215215
}
216216

217217
if (it.isNumber) {
@@ -222,25 +222,25 @@ class AndroidPlayerActivity : AppCompatActivity() {
222222
editTriggerButton.background.setTint(Color.WHITE)
223223
editTriggerButton.setOnClickListener { _ ->
224224
try {
225-
var value = editText.text.toString().toFloat()
225+
val value = editText.text.toString().toFloat()
226226
animationView.setNumberState(stateMachineName, it.name, value)
227227
} catch (e: Error) {
228228

229229
}
230230
}
231231

232-
layout.addView(editText)
233-
layout.addView(editTriggerButton)
232+
innerLayout.addView(editText)
233+
innerLayout.addView(editTriggerButton)
234234
}
235235

236-
views.add(layout)
236+
views.add(innerLayout)
237237
}
238238

239239
return views
240240
}
241241

242242
fun loadArtboard(artboardName: String) {
243-
var controls = findViewById<LinearLayout>(R.id.controls)
243+
val controls = findViewById<LinearLayout>(R.id.controls)
244244
controls.removeAllViews()
245245
animationView.drawable.file?.artboard(artboardName)?.let { artboard ->
246246
if (artboard.stateMachineNames.size > 0) {
@@ -267,8 +267,8 @@ class AndroidPlayerActivity : AppCompatActivity() {
267267

268268
fun setSpinner() {
269269
animationView.drawable.file?.artboardNames?.let { artboardNames ->
270-
var dropdown = findViewById<Spinner>(R.id.artboards)
271-
var adapter = ArrayAdapter<String>(
270+
val dropdown = findViewById<Spinner>(R.id.artboards)
271+
val adapter = ArrayAdapter<String>(
272272
this,
273273
android.R.layout.simple_spinner_dropdown_item,
274274
artboardNames
@@ -295,8 +295,8 @@ class AndroidPlayerActivity : AppCompatActivity() {
295295

296296
fun setResourceSpinner() {
297297
animationResources.let { _ ->
298-
var dropdown = findViewById<Spinner>(R.id.resources)
299-
var adapter = ArrayAdapter<String>(
298+
val dropdown = findViewById<Spinner>(R.id.resources)
299+
val adapter = ArrayAdapter<String>(
300300
this,
301301
android.R.layout.simple_spinner_dropdown_item,
302302
resourceNames
@@ -333,19 +333,13 @@ class AndroidPlayerActivity : AppCompatActivity() {
333333
} else if (animation is StateMachineInstance) {
334334
text = animation.stateMachine.name
335335
}
336-
text?.let {
336+
text?.let { theText ->
337337
val textView = TextView(that)
338-
textView.text = "Play $text"
338+
textView.text = "Play $theText"
339339
events.addView(textView, 0)
340-
playButtonMap.get(text)?.let {
341-
it.background.setTint(Color.GREEN)
342-
}
343-
pauseButtonMap.get(text)?.let {
344-
it.background.setTint(Color.WHITE)
345-
}
346-
stopButtonMap.get(text)?.let {
347-
it.background.setTint(Color.WHITE)
348-
}
340+
playButtonMap[theText]?.background?.setTint(Color.GREEN)
341+
pauseButtonMap[theText]?.background?.setTint(Color.WHITE)
342+
stopButtonMap[theText]?.background?.setTint(Color.WHITE)
349343
}
350344
}
351345

@@ -360,15 +354,9 @@ class AndroidPlayerActivity : AppCompatActivity() {
360354
val textView = TextView(that)
361355
textView.text = "Pause $text"
362356
events.addView(textView, 0)
363-
playButtonMap.get(text)?.let {
364-
it.background.setTint(Color.WHITE)
365-
}
366-
pauseButtonMap.get(text)?.let {
367-
it.background.setTint(Color.BLUE)
368-
}
369-
stopButtonMap.get(text)?.let {
370-
it.background.setTint(Color.WHITE)
371-
}
357+
playButtonMap[text]?.background?.setTint(Color.WHITE)
358+
pauseButtonMap[text]?.background?.setTint(Color.BLUE)
359+
stopButtonMap[text]?.background?.setTint(Color.WHITE)
372360
}
373361
}
374362

@@ -383,15 +371,9 @@ class AndroidPlayerActivity : AppCompatActivity() {
383371
val textView = TextView(that)
384372
textView.text = "Stop $text"
385373
events.addView(textView, 0)
386-
playButtonMap.get(text)?.let {
387-
it.background.setTint(Color.WHITE)
388-
}
389-
pauseButtonMap.get(text)?.let {
390-
it.background.setTint(Color.WHITE)
391-
}
392-
stopButtonMap.get(text)?.let {
393-
it.background.setTint(Color.RED)
394-
}
374+
playButtonMap[text]?.background?.setTint(Color.WHITE)
375+
pauseButtonMap[text]?.background?.setTint(Color.WHITE)
376+
stopButtonMap[text]?.background?.setTint(Color.RED)
395377
}
396378
}
397379

@@ -402,6 +384,13 @@ class AndroidPlayerActivity : AppCompatActivity() {
402384
events.addView(text, 0)
403385
}
404386
}
387+
388+
override fun notifyStateChanged(layerState: LayerState) {
389+
390+
val text = TextView(that)
391+
text.text = "State Changed $layerState"
392+
events.addView(text, 0)
393+
}
405394
}
406395

407396
animationView.registerListener(listener)

kotlin/src/androidTest/java/app/rive/runtime/kotlin/core/RiveEventTest.kt

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class Observer : RiveDrawable.Listener {
1616
var pauses = mutableListOf<PlayableInstance>()
1717
var stops = mutableListOf<PlayableInstance>()
1818
var loops = mutableListOf<PlayableInstance>()
19+
var states = mutableListOf<LayerState>()
1920
override fun notifyPlay(playableInstance: PlayableInstance) {
2021
plays.add(playableInstance)
2122
}
@@ -31,15 +32,16 @@ class Observer : RiveDrawable.Listener {
3132
override fun notifyLoop(playableInstance: PlayableInstance) {
3233
loops.add(playableInstance)
3334
}
35+
override fun notifyStateChanged(state: LayerState) {
36+
states.add(state)
37+
}
3438
}
3539

3640
@RunWith(AndroidJUnit4::class)
3741
class RiveEventTest {
3842

3943
@Test
40-
@Ignore
4144
fun testRegisterOrder() {
42-
// doesn't work right now, because we trash the drawable
4345
UiThreadStatement.runOnUiThread {
4446
val appContext = initTests()
4547
val view = RiveAnimationView(appContext)
@@ -229,4 +231,105 @@ class RiveEventTest {
229231
}
230232
}
231233

234+
@Test
235+
fun testStateMachineLayerStates() {
236+
UiThreadStatement.runOnUiThread {
237+
val appContext = initTests()
238+
val observer = Observer()
239+
240+
val view = RiveAnimationView(appContext)
241+
view.registerListener(observer)
242+
view.setRiveResource(R.raw.what_a_state, stateMachineName = "State Machine 2")
243+
assertEquals(1, observer.states.size)
244+
assertEquals(true, observer.states[0].isAnimationState)
245+
view.drawable.advance(2000f)
246+
assertEquals(2, observer.states.size)
247+
assertEquals(true, observer.states[1].isExitState)
248+
}
249+
}
250+
251+
@Test
252+
fun testStateMachineLayerStatesAnimations() {
253+
UiThreadStatement.runOnUiThread {
254+
val appContext = initTests()
255+
val observer = Observer()
256+
257+
val view = RiveAnimationView(appContext)
258+
view.registerListener(observer)
259+
view.setRiveResource(R.raw.what_a_state, stateMachineName = "State Machine 1")
260+
assertEquals(0, observer.states.size)
261+
262+
view.fireState("State Machine 1", "right")
263+
264+
// lets just start, expect 1 change.
265+
view.drawable.advance(400f)
266+
assertEquals(1, observer.states.size)
267+
assertEquals(true, observer.states[0].isAnimationState)
268+
assertEquals("go right", (observer.states[0] as AnimationState).animation.name)
269+
observer.states.clear()
270+
271+
// should be in same animation still. no state change
272+
view.drawable.advance(400f)
273+
assertEquals(0, observer.states.size)
274+
assertEquals(true, view.isPlaying)
275+
276+
// animation came to an end inside this time period, this still means no state change
277+
view.drawable.advance(400f)
278+
assertEquals(false, view.isPlaying)
279+
assertEquals(0, observer.states.size)
280+
281+
// animation is just kinda stuck there. no change no happening.
282+
view.drawable.advance(400f)
283+
assertEquals(false, view.isPlaying)
284+
assertEquals(0, observer.states.size)
285+
286+
// ok lets change thigns up again.
287+
view.fireState("State Machine 1", "change")
288+
view.drawable.advance(400f)
289+
assertEquals(true, view.isPlaying)
290+
assertEquals(1, observer.states.size)
291+
assertEquals(true, observer.states[0].isAnimationState)
292+
assertEquals("change!", (observer.states[0] as AnimationState).animation.name)
293+
observer.states.clear()
294+
295+
// as before lets advance inside the animation -> no change
296+
view.drawable.advance(400f)
297+
assertEquals(true, view.isPlaying)
298+
assertEquals(0, observer.states.size)
299+
300+
// as before lets advance beyond the end of the animaiton, in this case change to exit!
301+
view.drawable.advance(400f)
302+
assertEquals(false, view.isPlaying)
303+
assertEquals(1, observer.states.size)
304+
assertEquals(true, observer.states[0].isExitState)
305+
observer.states.clear()
306+
307+
// chill on exit. no change.
308+
view.drawable.advance(400f)
309+
assertEquals(false, view.isPlaying)
310+
assertEquals(0, observer.states.size)
311+
}
312+
}
313+
314+
@Test
315+
fun testStateMachineLayerStatesAnimationsDoubleChange() {
316+
UiThreadStatement.runOnUiThread {
317+
val appContext = initTests()
318+
val observer = Observer()
319+
320+
val view = RiveAnimationView(appContext)
321+
view.registerListener(observer)
322+
view.setRiveResource(R.raw.what_a_state, stateMachineName = "State Machine 1")
323+
assertEquals(0, observer.states.size)
324+
325+
view.fireState("State Machine 1", "change")
326+
// lets just start, expect 1 change.
327+
view.drawable.advance(1200f)
328+
assertEquals(2, observer.states.size)
329+
assertEquals(true, observer.states[0].isAnimationState)
330+
assertEquals("change!", (observer.states[0] as AnimationState).animation.name)
331+
assertEquals(true, observer.states[1].isExitState)
332+
}
333+
}
334+
232335
}

kotlin/src/androidTest/java/app/rive/runtime/kotlin/core/RiveViewStateMachineTest.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,32 @@ class RiveViewStateMachineTest {
6666
}
6767
}
6868

69+
@Test
70+
fun viewStateMachinesPause() {
71+
UiThreadStatement.runOnUiThread {
72+
val appContext = initTests()
73+
74+
val view = RiveAnimationView(appContext)
75+
view.setRiveResource(R.raw.what_a_state, stateMachineName = "State Machine 2")
76+
assertEquals(true, view.isPlaying)
77+
view.drawable.advance(2000f)
78+
assertEquals(false, view.isPlaying)
79+
}
80+
}
81+
82+
@Test
83+
@Ignore("We're not stopping state machines when all layers are stopped atm.")
84+
fun viewStateMachinesInstancesRemoveOnStop() {
85+
UiThreadStatement.runOnUiThread {
86+
val appContext = initTests()
87+
88+
val view = RiveAnimationView(appContext)
89+
view.setRiveResource(R.raw.what_a_state, stateMachineName = "State Machine 2")
90+
91+
assertEquals(1, view.drawable.stateMachines.size)
92+
view.drawable.advance(2000f)
93+
assertEquals(false, view.isPlaying)
94+
assertEquals(0, view.drawable.stateMachines.size)
95+
}
96+
}
6997
}

kotlin/src/androidTest/java/app/rive/runtime/kotlin/core/RiveViewTest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ class RiveViewTest {
442442
}
443443

444444
@Test
445-
@Ignore
445+
@Ignore("Doesn't work because we splat over the original animations loop mode!!")
446446
fun viewStopAnimationDetailsTime() {
447447
UiThreadStatement.runOnUiThread {
448448
val appContext = initTests()
@@ -458,7 +458,6 @@ class RiveViewTest {
458458
view.play("one")
459459
assertEquals(0f, view.animations.first().time)
460460
assertEquals(Loop.ONESHOT, view.animations.first().animation.loop)
461-
462461
}
463462
}
464463

384 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)