-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathHybridRiveFile.kt
More file actions
168 lines (143 loc) · 4.96 KB
/
HybridRiveFile.kt
File metadata and controls
168 lines (143 loc) · 4.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package com.margelo.nitro.rive
import androidx.annotation.Keep
import app.rive.runtime.kotlin.core.File
import com.facebook.proguard.annotations.DoNotStrip
import com.margelo.nitro.core.Promise
import java.lang.ref.WeakReference
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
@Keep
@DoNotStrip
class HybridRiveFile : HybridRiveFileSpec() {
var riveFile: File? = null
var referencedAssetCache: ReferencedAssetCache? = null
var assetLoader: ReferencedAssetLoader? = null
private val weakViews = mutableListOf<WeakReference<HybridRiveView>>()
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
override val viewModelCount: Double?
get() = riveFile?.viewModelCount?.toDouble()
override fun viewModelByIndex(index: Double): HybridViewModelSpec? {
if (index < 0) return null
return try {
val vm = riveFile?.getViewModelByIndex(index.toInt()) ?: return null
HybridViewModel(vm)
} catch (e: Exception) {
null
}
}
override fun viewModelByName(name: String): HybridViewModelSpec? {
return try {
val vm = riveFile?.getViewModelByName(name) ?: return null
HybridViewModel(vm)
} catch (e: Exception) {
null
}
}
override fun defaultArtboardViewModel(artboardBy: ArtboardBy?): HybridViewModelSpec? {
try {
val artboard = when (artboardBy?.type) {
ArtboardByTypes.INDEX -> riveFile?.artboard(artboardBy.index!!.toInt())
ArtboardByTypes.NAME -> riveFile?.artboard(artboardBy.name!!)
null -> riveFile?.firstArtboard
} ?: return null
val vm = riveFile?.defaultViewModelForArtboard(artboard) ?: return null
return HybridViewModel(vm)
} catch (e: Exception) {
return null
}
}
override val artboardCount: Double
get() = riveFile?.artboardNames?.size?.toDouble() ?: 0.0
override val artboardNames: Array<String>
get() = riveFile?.artboardNames?.toTypedArray() ?: emptyArray()
override fun getBindableArtboard(name: String): HybridBindableArtboardSpec {
val file = riveFile ?: throw IllegalStateException("RiveFile not loaded")
val bindable = file.createBindableArtboardByName(name)
return HybridBindableArtboard(bindable)
}
fun registerView(view: HybridRiveView) {
weakViews.add(WeakReference(view))
}
fun unregisterView(view: HybridRiveView) {
weakViews.removeAll { it.get() == view }
}
private fun refreshAfterAssetChange() {
weakViews.removeAll { it.get() == null }
for (weakView in weakViews) {
weakView.get()?.refreshAfterAssetChange()
}
}
override fun getViewModelNamesAsync(): Promise<Array<String>> {
return Promise.async {
val file = riveFile ?: return@async emptyArray()
val count = file.viewModelCount
val names = mutableListOf<String>()
for (i in 0 until count) {
try {
val vm = file.getViewModelByIndex(i)
names.add(vm.name)
} catch (_: Exception) {
}
}
names.toTypedArray()
}
}
override fun viewModelByNameAsync(name: String, validate: Boolean?): Promise<HybridViewModelSpec?> {
return Promise.async { viewModelByName(name) }
}
override fun defaultArtboardViewModelAsync(artboardBy: ArtboardBy?): Promise<HybridViewModelSpec?> {
return Promise.async { defaultArtboardViewModel(artboardBy) }
}
override fun getArtboardCountAsync(): Promise<Double> {
return Promise.async { artboardCount }
}
override fun getArtboardNamesAsync(): Promise<Array<String>> {
return Promise.async { artboardNames }
}
override fun updateReferencedAssets(referencedAssets: ReferencedAssetsType) {
val assetsData = referencedAssets.data ?: return
val cache = referencedAssetCache ?: return
val loader = assetLoader ?: return
val loadJobs = mutableListOf<kotlinx.coroutines.Deferred<Unit>>()
for ((key, assetData) in assetsData) {
val asset = cache[key] ?: continue
loadJobs.add(loader.updateAsset(assetData, asset))
}
if (loadJobs.isNotEmpty()) {
scope.launch {
loadJobs.awaitAll()
refreshAfterAssetChange()
}
}
}
override fun getEnums(): Promise<Array<RiveEnumDefinition>> {
val file = riveFile ?: return Promise.resolved(emptyArray())
return Promise.async {
try {
file.enums
.map { enum ->
RiveEnumDefinition(
name = enum.name,
values = enum.values.toTypedArray()
)
}.toTypedArray()
} catch (e: NoSuchMethodError) {
throw UnsupportedOperationException("getEnums requires rive-android SDK with enums support")
}
}
}
override fun dispose() {
scope.cancel()
weakViews.clear()
assetLoader?.dispose()
assetLoader = null
riveFile?.release()
riveFile = null
referencedAssetCache?.clear()
referencedAssetCache = null
}
}