save code
@@ -80,4 +80,7 @@ dependencies {
|
||||
implementation 'com.google.flogger:flogger-system-backend:0.7.4'
|
||||
|
||||
implementation 'com.google.guava:guava:31.1-android'
|
||||
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7") // 提供 lifecycleScope
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
|
||||
}
|
||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -71,13 +71,38 @@
|
||||
"7.png"
|
||||
],
|
||||
"11": [
|
||||
"11.png"
|
||||
"002.png",
|
||||
"003.png",
|
||||
"004.png",
|
||||
"005.png",
|
||||
"006.png",
|
||||
"007.png",
|
||||
"008.png",
|
||||
"009.png",
|
||||
"010.png",
|
||||
"011.png",
|
||||
"11.png",
|
||||
"012.png"
|
||||
],
|
||||
"12": [
|
||||
"12.png"
|
||||
],
|
||||
"13": [
|
||||
"13.png"
|
||||
"001.png",
|
||||
"002.png",
|
||||
"003.png",
|
||||
"004.png",
|
||||
"005.png",
|
||||
"006.png",
|
||||
"007.png",
|
||||
"008.png",
|
||||
"009.png",
|
||||
"010.png",
|
||||
"011.png",
|
||||
"012.png",
|
||||
"013.png",
|
||||
"13.png",
|
||||
"014.png"
|
||||
],
|
||||
"14": [
|
||||
"14.png"
|
||||
|
||||
@@ -7,11 +7,13 @@ import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.KeyEvent.KEYCODE_BACK
|
||||
import android.view.MotionEvent
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.hmwl.face_sdk.FaceActivity
|
||||
import com.hmwl.face_sdk.InitArg
|
||||
import com.hmwl.face_sdk.Motion
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.json.JSONObject
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
@@ -19,8 +21,43 @@ import java.io.InputStreamReader
|
||||
|
||||
class MakeupActivity : FaceActivity()
|
||||
{
|
||||
private var curIndex = 0
|
||||
private var pngFilesByFolder: List<FolderInfo>? = null
|
||||
var isLoadFinished: Boolean = false;
|
||||
var isMotionFinished: Boolean = true;
|
||||
var _motionIndex : Int = 0
|
||||
|
||||
|
||||
var animationFinishedFun = object : AnimationFinishedCallbackInterface {
|
||||
override fun OnAnimationFinished() {
|
||||
isMotionFinished = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var loadFinishedFun = object : CallbackInterface {
|
||||
override fun OnLoadActionFinished(motion_type: String) {
|
||||
isLoadFinished = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private val motionQueue: MutableList<String> = mutableListOf()
|
||||
fun PlayMotionQueue(motions: List<String>)
|
||||
{
|
||||
for (m in motions) {
|
||||
var motion = getMotionByName(m);
|
||||
var motionJsonString = motion.toJson();
|
||||
motionQueue.add(motionJsonString)
|
||||
}
|
||||
//开始播放动画的时候需要先加载第一个动画
|
||||
isLoadFinished = false;
|
||||
_motionIndex = 0;
|
||||
PreLoadAction(motionQueue[_motionIndex], loadFinishedFun)
|
||||
}
|
||||
|
||||
private var updateJob: Job? = null
|
||||
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
@@ -35,20 +72,37 @@ class MakeupActivity : FaceActivity()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
var motion = getMotionByIndex(0);
|
||||
var motionJsonString = motion.toJson()
|
||||
val result = PreLoadAction(motionJsonString,object : CallbackInterface {
|
||||
override fun OnLoadActionFinished(motion_type: String) {
|
||||
//加载完成后,切断到对应的动画
|
||||
Log.i("info","加载完成后,切换到对应的动画")
|
||||
ChangeMotion(motion_type, object : AnimationFinishedCallbackInterface{
|
||||
override fun OnAnimationFinished(){
|
||||
Log.i("info","动画播放完成,收到回调")
|
||||
}
|
||||
}, false)
|
||||
|
||||
// 启动一个生命周期感知的协程
|
||||
updateJob = lifecycleScope.launch {
|
||||
while (true) {
|
||||
update()
|
||||
delay(10) // 每 10 毫秒执行一次
|
||||
}
|
||||
})
|
||||
Toast.makeText(this, "开始加载动画: $result", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun update()
|
||||
{
|
||||
//下一个动画加载完成,并且当前动画已经播放完了 (刚开始的时候当前动画初始化为播放完成)
|
||||
if(isLoadFinished && isMotionFinished)
|
||||
{
|
||||
//切换到加载完成的动画
|
||||
isMotionFinished = false
|
||||
ChangeMotion(motionQueue[_motionIndex], animationFinishedFun, false)
|
||||
|
||||
isLoadFinished = false
|
||||
|
||||
//如果还有动画,则开始预先加载
|
||||
if(_motionIndex + 1 < motionQueue.size)
|
||||
{
|
||||
_motionIndex += 1
|
||||
PreLoadAction(motionQueue[_motionIndex], loadFinishedFun)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
@@ -66,70 +120,21 @@ class MakeupActivity : FaceActivity()
|
||||
}
|
||||
|
||||
|
||||
private fun getMotionByIndex(index: Int): Motion {
|
||||
pngFilesByFolder?.let { folders ->
|
||||
val motion = Motion().apply {
|
||||
type = folders[index].folderName
|
||||
png_names = folders[index].fileList
|
||||
}
|
||||
return motion
|
||||
private fun getMotionByName(m: String): Motion {
|
||||
val motion = Motion().apply {
|
||||
type = m
|
||||
png_names = pngFilesByFolder?.get(m)?.fileList
|
||||
}
|
||||
return Motion()
|
||||
return motion
|
||||
}
|
||||
|
||||
private fun getCurMotionState(index: Int): String {
|
||||
pngFilesByFolder?.let { folders ->
|
||||
val motion = Motion().apply {
|
||||
type = folders[index].folderName
|
||||
png_names = folders[index].fileList
|
||||
}
|
||||
return motion.toJson()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var nextMotionLoadFinished = false
|
||||
var nextMotionType = ""
|
||||
|
||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
pngFilesByFolder?.let { folders ->
|
||||
if (curIndex > folders.size - 1) {
|
||||
//动画播放完成,切换到主界面
|
||||
curIndex = 0
|
||||
Stop();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP -> {
|
||||
if (!nextMotionLoadFinished)
|
||||
{
|
||||
var nextMotion = getMotionByIndex(curIndex + 1);
|
||||
var json_str = nextMotion.toJson()
|
||||
PreLoadAction(json_str,object : CallbackInterface {
|
||||
override fun OnLoadActionFinished(motion_type: String) {
|
||||
Log.i("info","加载完成后,还会继续播放当前的动画,可以手动切换动画")
|
||||
nextMotionLoadFinished = true;
|
||||
nextMotionType = motion_type;
|
||||
}
|
||||
})
|
||||
Toast.makeText(this, "开始加载下一个动画 ${nextMotion.type}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
else
|
||||
{
|
||||
//手动切换动画
|
||||
ChangeMotion(nextMotionType, object: AnimationFinishedCallbackInterface{
|
||||
override fun OnAnimationFinished(){
|
||||
Log.i("info","动画播放完成的回调")
|
||||
}
|
||||
}, false);
|
||||
nextMotionLoadFinished = false;
|
||||
curIndex++;
|
||||
Toast.makeText(this, "切换到下一个动画 $nextMotionType", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
val motions: List<String> = listOf("4", "11", "13")
|
||||
PlayMotionQueue(motions)
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -140,8 +145,8 @@ class MakeupActivity : FaceActivity()
|
||||
val fileList: List<String>
|
||||
)
|
||||
|
||||
private fun readPngFilenamesFromAssets(context: Context, filename: String): List<FolderInfo> {
|
||||
val folderList = mutableListOf<FolderInfo>()
|
||||
private fun readPngFilenamesFromAssets(context: Context, filename: String): Map<String,FolderInfo> {
|
||||
val folderMap = mutableMapOf<String, FolderInfo>()
|
||||
|
||||
try {
|
||||
context.assets.open(filename).use { inputStream ->
|
||||
@@ -164,7 +169,7 @@ class MakeupActivity : FaceActivity()
|
||||
filesInFolder.add(fileArray.getString(i))
|
||||
}
|
||||
|
||||
folderList.add(FolderInfo(folderName, filesInFolder))
|
||||
folderMap[folderName] = (FolderInfo(folderName, filesInFolder))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,9 +177,10 @@ class MakeupActivity : FaceActivity()
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return folderList
|
||||
return folderMap
|
||||
}
|
||||
|
||||
private var pngFilesByFolder: Map<String, FolderInfo>? = null
|
||||
private fun FaceInit(context: Context) {
|
||||
pngFilesByFolder = readPngFilenamesFromAssets(context, "pic/motion_data.json")
|
||||
}
|
||||
|
||||
@@ -1401,6 +1401,7 @@ void FaceApp::changeMotion(const string motion_type, AnimationFinishedCallback c
|
||||
_motionState = ready;
|
||||
_animationFinishedCallback = callback;
|
||||
_animationLoop = loop;
|
||||
_curTexIndex = 0;
|
||||
|
||||
|
||||
// for (int i = 0; i < _curMotion.png_names.size(); ++i)
|
||||
|
||||