save code
This commit is contained in:
@@ -165,7 +165,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|||||||
return JNI_VERSION_1_6;
|
return JNI_VERSION_1_6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCallback(const string& motion_type)
|
void CppCallback()
|
||||||
{
|
{
|
||||||
JNIEnv* env = nullptr;
|
JNIEnv* env = nullptr;
|
||||||
bool needDetach = false;
|
bool needDetach = false;
|
||||||
@@ -205,7 +205,7 @@ void CppCallback(const string& motion_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 构造 jstring 参数
|
// 3. 构造 jstring 参数
|
||||||
jstring jResult = env->NewStringUTF(motion_type.c_str());
|
jstring jResult = env->NewStringUTF("ok");
|
||||||
|
|
||||||
// 4. 调用 Java 回调
|
// 4. 调用 Java 回调
|
||||||
env->CallVoidMethod(g_callback, methodId, jResult);
|
env->CallVoidMethod(g_callback, methodId, jResult);
|
||||||
@@ -309,7 +309,7 @@ Java_com_hmwl_face_1sdk_FaceActivity_PreReadAction(JNIEnv *env, jobject thiz, js
|
|||||||
aout << "ArgLen to long:" << len << std::endl;
|
aout << "ArgLen to long:" << len << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ret = g_Application->preReadyMotion(nativeString, CppCallback);
|
std::string ret = g_Application->preLoadMotionList(nativeString, CppCallback);
|
||||||
return env->NewStringUTF(ret.c_str());
|
return env->NewStringUTF(ret.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +336,6 @@ Java_com_hmwl_face_1sdk_FaceActivity_ChangeMotionCpp(JNIEnv *env, jobject thiz,
|
|||||||
|
|
||||||
if(g_Application->isInited())
|
if(g_Application->isInited())
|
||||||
{
|
{
|
||||||
g_Application->changeMotion(nativeString, CppAnimationFinishedCallback, loop);
|
g_Application->changeMotionList(CppAnimationFinishedCallback, loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.hmwl.face_sdk;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class Frame {
|
||||||
|
public String name;
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
public Frame(String name, float x, float y)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
public JSONObject toJsonObject(){
|
||||||
|
try {
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("name", name);
|
||||||
|
jsonObject.put("x", x);
|
||||||
|
jsonObject.put("y", y);
|
||||||
|
return jsonObject;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,32 +5,29 @@ import org.json.JSONObject;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
public class Motion {
|
public class Motion {
|
||||||
public String type = "no";
|
public String name = "no";
|
||||||
public List<String> png_names = new ArrayList<>();
|
public List<Frame> frames = new ArrayList<>();
|
||||||
|
public Motion(String name, List<Frame> frames)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.frames = frames;
|
||||||
|
}
|
||||||
|
|
||||||
public JSONObject toJsonObject() {
|
public JSONObject toJsonObject() {
|
||||||
try {
|
try {
|
||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.put("type", type);
|
jsonObject.put("name", name);
|
||||||
JSONArray ja = new JSONArray();
|
JSONObject jframes = new JSONObject();
|
||||||
for(int i = 0; i < png_names.size(); ++i){
|
for(int i = 0; i < frames.size(); ++i){
|
||||||
ja.put(png_names.get(i));
|
jframes.put(frames.get(i).name, frames.get(i).toJsonObject());
|
||||||
}
|
}
|
||||||
jsonObject.put("png_names", ja);
|
jsonObject.put("frames", jframes);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toJson() {
|
|
||||||
try {
|
|
||||||
return toJsonObject().toString();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.hmwl.face_sdk;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MotionList {
|
||||||
|
public List<Motion> motions = new ArrayList<>();
|
||||||
|
public JSONObject toJsonObject() {
|
||||||
|
try {
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
JSONArray jMotions = new JSONArray();
|
||||||
|
for(int i = 0; i < motions.size(); ++i){
|
||||||
|
jMotions.put(motions.get(i).toJsonObject());
|
||||||
|
}
|
||||||
|
jsonObject.put("motions", jMotions);
|
||||||
|
return jsonObject;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new JSONObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public String toJsonString(){
|
||||||
|
return toJsonObject().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,8 +9,10 @@ import android.view.KeyEvent.KEYCODE_BACK
|
|||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.hmwl.face_sdk.FaceActivity
|
import com.hmwl.face_sdk.FaceActivity
|
||||||
|
import com.hmwl.face_sdk.Frame
|
||||||
import com.hmwl.face_sdk.InitArg
|
import com.hmwl.face_sdk.InitArg
|
||||||
import com.hmwl.face_sdk.Motion
|
import com.hmwl.face_sdk.Motion
|
||||||
|
import com.hmwl.face_sdk.MotionList
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -21,18 +23,13 @@ import java.io.InputStreamReader
|
|||||||
|
|
||||||
class MakeupActivity : FaceActivity()
|
class MakeupActivity : FaceActivity()
|
||||||
{
|
{
|
||||||
var isLoadFinished: Boolean = false;
|
|
||||||
var isMotionFinished: Boolean = true;
|
|
||||||
var _motionIndex : Int = 0
|
|
||||||
|
|
||||||
|
|
||||||
var animationFinishedFun = object : AnimationFinishedCallbackInterface {
|
var animationFinishedFun = object : AnimationFinishedCallbackInterface {
|
||||||
override fun OnAnimationFinished() {
|
override fun OnAnimationFinished() {
|
||||||
isMotionFinished = true;
|
Log.i("MakeupActivity", "OnAnimationFinished: ")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isLoadFinished : Boolean = false
|
||||||
var loadFinishedFun = object : CallbackInterface {
|
var loadFinishedFun = object : CallbackInterface {
|
||||||
override fun OnLoadActionFinished(motion_type: String) {
|
override fun OnLoadActionFinished(motion_type: String) {
|
||||||
isLoadFinished = true;
|
isLoadFinished = true;
|
||||||
@@ -40,28 +37,13 @@ class MakeupActivity : FaceActivity()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
private var updateJob: Job? = null
|
||||||
|
|
||||||
|
|
||||||
|
private var existMotions: Map<String, Motion>? = null
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
FaceInit(this)
|
existMotions = readMotionsFromAssets(this, "pic/motion_data_ex.json")
|
||||||
|
|
||||||
val initArg = InitArg().apply {
|
val initArg = InitArg().apply {
|
||||||
action_fps = 10
|
action_fps = 10
|
||||||
@@ -81,27 +63,32 @@ class MakeupActivity : FaceActivity()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val mlist = MotionList();
|
||||||
|
getMotionByName("4")?.let { mlist.motions.add(it) }
|
||||||
|
//getMotionByName("11")?.let { mlist.motions.add(it) }
|
||||||
|
//getMotionByName("13")?.let { mlist.motions.add(it) }
|
||||||
|
PreLoadAction(mlist.toJsonString(), loadFinishedFun)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun update()
|
private fun update()
|
||||||
{
|
{
|
||||||
//下一个动画加载完成,并且当前动画已经播放完了 (刚开始的时候当前动画初始化为播放完成)
|
// //下一个动画加载完成,并且当前动画已经播放完了 (刚开始的时候当前动画初始化为播放完成)
|
||||||
if(isLoadFinished && isMotionFinished)
|
// if(isLoadFinished && isMotionFinished)
|
||||||
{
|
// {
|
||||||
//切换到加载完成的动画
|
// //切换到加载完成的动画
|
||||||
isMotionFinished = false
|
// isMotionFinished = false
|
||||||
ChangeMotion(motionQueue[_motionIndex], animationFinishedFun, false)
|
// ChangeMotion(motionQueue[_motionIndex], animationFinishedFun, false)
|
||||||
|
//
|
||||||
isLoadFinished = false
|
// isLoadFinished = false
|
||||||
|
//
|
||||||
//如果还有动画,则开始预先加载
|
// //如果还有动画,则开始预先加载
|
||||||
if(_motionIndex + 1 < motionQueue.size)
|
// if(_motionIndex + 1 < motionQueue.size)
|
||||||
{
|
// {
|
||||||
_motionIndex += 1
|
// _motionIndex += 1
|
||||||
PreLoadAction(motionQueue[_motionIndex], loadFinishedFun)
|
// PreLoadAction(motionQueue[_motionIndex], loadFinishedFun)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,12 +107,8 @@ class MakeupActivity : FaceActivity()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun getMotionByName(m: String): Motion {
|
private fun getMotionByName(m: String): Motion? {
|
||||||
val motion = Motion().apply {
|
return existMotions?.get(m);
|
||||||
type = m
|
|
||||||
png_names = pngFilesByFolder?.get(m)?.fileList
|
|
||||||
}
|
|
||||||
return motion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -133,20 +116,14 @@ class MakeupActivity : FaceActivity()
|
|||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
when (event.action) {
|
when (event.action) {
|
||||||
MotionEvent.ACTION_UP -> {
|
MotionEvent.ACTION_UP -> {
|
||||||
val motions: List<String> = listOf("4", "11", "13")
|
|
||||||
PlayMotionQueue(motions)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class FolderInfo(
|
private fun readMotionsFromAssets(context: Context, filename: String): Map<String,Motion> {
|
||||||
val folderName: String,
|
val motionMap = mutableMapOf<String, Motion>()
|
||||||
val fileList: List<String>
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun readPngFilenamesFromAssets(context: Context, filename: String): Map<String,FolderInfo> {
|
|
||||||
val folderMap = mutableMapOf<String, FolderInfo>()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
context.assets.open(filename).use { inputStream ->
|
context.assets.open(filename).use { inputStream ->
|
||||||
@@ -158,30 +135,32 @@ class MakeupActivity : FaceActivity()
|
|||||||
}
|
}
|
||||||
|
|
||||||
val jsonObject = JSONObject(stringBuilder.toString())
|
val jsonObject = JSONObject(stringBuilder.toString())
|
||||||
val folderIterator = jsonObject.keys()
|
// 遍历JSON对象
|
||||||
|
val keys = jsonObject.keys()
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
val key = keys.next() // 获取键,即"Motion"的名字
|
||||||
|
val motionObject = jsonObject.getJSONObject(key)
|
||||||
|
|
||||||
while (folderIterator.hasNext()) {
|
val frameList = mutableListOf<Frame>()
|
||||||
val folderName = folderIterator.next()
|
val fileKeys = motionObject.keys()
|
||||||
val fileArray = jsonObject.getJSONArray(folderName)
|
while (fileKeys.hasNext()) {
|
||||||
val filesInFolder = mutableListOf<String>()
|
val fileKey = fileKeys.next() // 获取每个文件名
|
||||||
|
val fileObject = motionObject.getJSONObject(fileKey)
|
||||||
for (i in 0 until fileArray.length()) {
|
val x = fileObject.getDouble("x").toFloat()
|
||||||
filesInFolder.add(fileArray.getString(i))
|
val y = fileObject.getDouble("y").toFloat()
|
||||||
|
frameList.add(Frame(fileKey, x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
folderMap[folderName] = (FolderInfo(folderName, filesInFolder))
|
motionMap[key] = Motion(key, frameList)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
return folderMap
|
return motionMap
|
||||||
}
|
}
|
||||||
|
|
||||||
private var pngFilesByFolder: Map<String, FolderInfo>? = null
|
|
||||||
private fun FaceInit(context: Context) {
|
|
||||||
pngFilesByFolder = readPngFilenamesFromAssets(context, "pic/motion_data.json")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+4
-7
@@ -1370,7 +1370,7 @@ void FaceApp::drawFrame(long long frameTime)
|
|||||||
// changeMotion(motion);
|
// changeMotion(motion);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
string FaceApp::preLoadMotionList(const vector<string>& motions, Callback callback)
|
string FaceApp::preLoadMotionList(string motion_list_str, Callback callback)
|
||||||
{
|
{
|
||||||
if (_isLoadMotion)
|
if (_isLoadMotion)
|
||||||
{
|
{
|
||||||
@@ -1379,12 +1379,9 @@ string FaceApp::preLoadMotionList(const vector<string>& motions, Callback callba
|
|||||||
_isLoadMotion = true;
|
_isLoadMotion = true;
|
||||||
_callback_loadfinish = callback;
|
_callback_loadfinish = callback;
|
||||||
_preLoadMotions.clear();
|
_preLoadMotions.clear();
|
||||||
for (auto s : motions)
|
json j = json::parse(motion_list_str);
|
||||||
{
|
MotionList motion_list = j.get<MotionList>();
|
||||||
json j = json::parse(s);
|
_preLoadMotions = motion_list.motions;
|
||||||
Motion motion = j.get<Motion>();
|
|
||||||
_preLoadMotions.push_back(motion);
|
|
||||||
}
|
|
||||||
worker_ = std::thread(&FaceApp::loadMotionThread, this);
|
worker_ = std::thread(&FaceApp::loadMotionThread, this);
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -28,6 +28,12 @@ struct Motion {
|
|||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Motion, name, frames)
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Motion, name, frames)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MotionList
|
||||||
|
{
|
||||||
|
vector<Motion> motions;
|
||||||
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(MotionList, motions)
|
||||||
|
};
|
||||||
|
|
||||||
struct InitArg
|
struct InitArg
|
||||||
{
|
{
|
||||||
int action_fps;
|
int action_fps;
|
||||||
@@ -152,7 +158,7 @@ public:
|
|||||||
Callback _callback_loadfinish;
|
Callback _callback_loadfinish;
|
||||||
AnimationFinishedCallback _animationFinishedCallback;
|
AnimationFinishedCallback _animationFinishedCallback;
|
||||||
bool _animationLoop = true;
|
bool _animationLoop = true;
|
||||||
string preLoadMotionList(const vector<string>& motions, Callback callback);
|
string preLoadMotionList(string motion_list_str, Callback callback);
|
||||||
vector<Motion>_preLoadMotions;
|
vector<Motion>_preLoadMotions;
|
||||||
vector<Motion>_curMotions;
|
vector<Motion>_curMotions;
|
||||||
void changeMotionList(AnimationFinishedCallback callback, bool loop);
|
void changeMotionList(AnimationFinishedCallback callback, bool loop);
|
||||||
|
|||||||
+5
-4
@@ -140,11 +140,12 @@ int main() {
|
|||||||
std::cout << "Warning: Empty motion string" << std::endl;
|
std::cout << "Warning: Empty motion string" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> s_motions;
|
MotionList s_motions;
|
||||||
json j = motions["4"];
|
s_motions.motions.push_back(motions["4"]);
|
||||||
s_motions.push_back(j.dump());
|
json j = s_motions;
|
||||||
|
auto s = j.dump();
|
||||||
|
|
||||||
app.preLoadMotionList(s_motions, CppCallback);
|
app.preLoadMotionList(s, CppCallback);
|
||||||
app.mainLoop();
|
app.mainLoop();
|
||||||
//try {
|
//try {
|
||||||
// app.mainLoop();
|
// app.mainLoop();
|
||||||
|
|||||||
Reference in New Issue
Block a user