MainActivity.kt 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated April 5, 2025. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2025, Esoteric Software LLC
  6. *
  7. * Integration of the Spine Runtimes into software or otherwise creating
  8. * derivative works of the Spine Runtimes is permitted under the terms and
  9. * conditions of Section 2 of the Spine Editor License Agreement:
  10. * http://esotericsoftware.com/spine-editor-license
  11. *
  12. * Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. * or otherwise create derivative works of the Spine Runtimes (collectively,
  14. * "Products"), provided that each user of the Products must obtain their own
  15. * Spine Editor license and redistribution of the Products in any form must
  16. * include this license and copyright notice.
  17. *
  18. * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *****************************************************************************/
  29. package com.esotericsoftware.spine
  30. import android.content.Intent
  31. import android.os.Bundle
  32. import androidx.activity.ComponentActivity
  33. import androidx.activity.compose.setContent
  34. import androidx.compose.foundation.clickable
  35. import androidx.compose.foundation.layout.Arrangement
  36. import androidx.compose.foundation.layout.PaddingValues
  37. import androidx.compose.foundation.layout.fillMaxSize
  38. import androidx.compose.foundation.layout.fillMaxWidth
  39. import androidx.compose.foundation.layout.padding
  40. import androidx.compose.foundation.lazy.LazyColumn
  41. import androidx.compose.material3.Card
  42. import androidx.compose.material3.ExperimentalMaterial3Api
  43. import androidx.compose.material3.MaterialTheme
  44. import androidx.compose.material3.Scaffold
  45. import androidx.compose.material3.Surface
  46. import androidx.compose.material3.Text
  47. import androidx.compose.material3.TopAppBar
  48. import androidx.compose.runtime.Composable
  49. import androidx.compose.ui.Modifier
  50. import androidx.compose.ui.unit.dp
  51. import androidx.navigation.NavHostController
  52. import androidx.navigation.compose.NavHost
  53. import androidx.navigation.compose.composable
  54. import androidx.navigation.compose.rememberNavController
  55. import com.esotericsoftware.spine.ui.theme.SpineAndroidExamplesTheme
  56. class MainActivity : ComponentActivity() {
  57. override fun onCreate(savedInstanceState: Bundle?) {
  58. super.onCreate(savedInstanceState)
  59. setContent {
  60. AppContent()
  61. }
  62. }
  63. }
  64. @OptIn(ExperimentalMaterial3Api::class)
  65. @Composable
  66. fun AppContent() {
  67. val navController = rememberNavController()
  68. SpineAndroidExamplesTheme {
  69. Surface(
  70. modifier = Modifier.fillMaxSize(),
  71. color = MaterialTheme.colorScheme.background
  72. ) {
  73. NavHost(
  74. navController = navController,
  75. startDestination = Destination.Samples.route
  76. ) {
  77. composable(
  78. Destination.Samples.route
  79. ) {
  80. Scaffold(
  81. topBar = { TopAppBar(title = { Text(text = Destination.Samples.title) }) }
  82. ) { paddingValues ->
  83. Samples(
  84. navController,
  85. listOf(
  86. Destination.SimpleAnimation,
  87. Destination.PlayPause,
  88. Destination.AnimationStateEvents,
  89. Destination.DebugRendering,
  90. Destination.DressUp,
  91. Destination.IKFollowing,
  92. Destination.Physics,
  93. Destination.DisableRendering
  94. ),
  95. paddingValues
  96. )
  97. }
  98. }
  99. composable(
  100. Destination.SimpleAnimation.route
  101. ) {
  102. SimpleAnimation(navController)
  103. }
  104. composable(
  105. Destination.PlayPause.route
  106. ) {
  107. PlayPause(navController)
  108. }
  109. composable(
  110. Destination.AnimationStateEvents.route
  111. ) {
  112. AnimationState(navController)
  113. }
  114. composable(
  115. Destination.DebugRendering.route
  116. ) {
  117. DebugRendering(navController)
  118. }
  119. composable(
  120. Destination.DressUp.route
  121. ) {
  122. DressUp(navController)
  123. }
  124. composable(
  125. Destination.IKFollowing.route
  126. ) {
  127. IKFollowing(navController)
  128. }
  129. composable(
  130. Destination.Physics.route
  131. ) {
  132. Physics(navController)
  133. }
  134. composable(
  135. Destination.DisableRendering.route
  136. ) {
  137. DisableRendering(navController)
  138. }
  139. }
  140. }
  141. }
  142. }
  143. @Composable
  144. fun Samples(
  145. nav: NavHostController,
  146. samples: List<Destination>,
  147. paddingValues: PaddingValues
  148. ) {
  149. LazyColumn(
  150. verticalArrangement = Arrangement.spacedBy(8.dp),
  151. modifier = Modifier
  152. .padding(8.dp)
  153. .padding(paddingValues)
  154. ) {
  155. item {
  156. Text(text = "Kotlin + Jetpack Compose", Modifier.padding(8.dp))
  157. }
  158. samples.forEach {
  159. item {
  160. Card(
  161. Modifier
  162. .fillMaxWidth()
  163. .clickable(onClick = { nav.navigate(it.route) }),
  164. shape = MaterialTheme.shapes.large
  165. ) {
  166. Text(text = it.title, Modifier.padding(24.dp))
  167. }
  168. }
  169. }
  170. item {
  171. Text(text = "Java + XML", Modifier.padding(8.dp))
  172. }
  173. item {
  174. Card(
  175. Modifier
  176. .fillMaxWidth()
  177. .clickable(onClick = {
  178. nav.context.startActivity(
  179. Intent(
  180. nav.context,
  181. SimpleAnimationActivity::class.java
  182. )
  183. )
  184. }),
  185. shape = MaterialTheme.shapes.large
  186. ) {
  187. Text(text = "Simple Animation", Modifier.padding(24.dp))
  188. }
  189. }
  190. }
  191. }
  192. sealed class Destination(val route: String, val title: String) {
  193. data object Samples: Destination("samples", "Spine Android Examples")
  194. data object SimpleAnimation : Destination("simpleAnimation", "Simple Animation")
  195. data object PlayPause : Destination("playPause", "Play/Pause")
  196. data object DebugRendering: Destination("debugRendering", "Debug Renderer")
  197. data object AnimationStateEvents : Destination("animationStateEvents", "Animation State Listener")
  198. data object DressUp : Destination("dressUp", "Dress Up")
  199. data object IKFollowing : Destination("ikFollowing", "IK Following")
  200. data object Physics: Destination("physics", "Physics (drag anywhere)")
  201. data object DisableRendering: Destination("disableRendering", "Disable Rendering")
  202. }