1
This commit is contained in:
commit
a02f7b2e22
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
*.iml
|
||||
local.properties
|
||||
|
||||
/baidu/build/
|
||||
/app/build/
|
||||
/.idea/
|
||||
/.gradle/
|
||||
/beauty/build/
|
||||
/billing/build/
|
||||
/build/
|
||||
/common/build/
|
||||
/lib_beauty360/build/
|
||||
/lib_country_code/build/
|
||||
/live/build/
|
||||
/main/build/
|
||||
/video/build/
|
1
FaceUnity/.gitignore
vendored
Normal file
1
FaceUnity/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
73
FaceUnity/build.gradle
Normal file
73
FaceUnity/build.gradle
Normal file
@ -0,0 +1,73 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'img-optimizer'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
packagingOptions {
|
||||
pickFirst "lib/armeabi/libyuvutils.so"
|
||||
pickFirst "lib/arm64-v8a/libyuvutils.so"
|
||||
pickFirst "lib/armeabi-v7a/libyuvutils.so"
|
||||
pickFirst "lib/armeabi/libyuvtools.so"
|
||||
pickFirst "lib/arm64-v8a/libyuvtools.so"
|
||||
pickFirst "lib/armeabi-v7a/libyuvtools.so"
|
||||
exclude "lib/arm64-v8a/libmmcv_api_handgesture.so"
|
||||
exclude "lib/arm64-v8a/libmmcv_api_express.so"
|
||||
exclude "lib/arm64-v8a/libMediaEncoder.so"
|
||||
exclude "lib/arm64-v8a/libarcore_sdk_c.so"
|
||||
exclude "lib/arm64-v8a/libmediadecoder.so"
|
||||
exclude "lib/arm64-v8a/libMediaMuxer.so"
|
||||
exclude "lib/arm64-v8a/libarcore_sdk_jni.so"
|
||||
exclude "lib/arm64-v8a/libMediaUtils.so"
|
||||
exclude "lib/arm64-v8a/libcosmosffmpeg.so"
|
||||
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode rootProject.ext.android.versionCode
|
||||
versionName rootProject.ext.android.versionName
|
||||
manifestPlaceholders = rootProject.ext.manifestPlaceholders
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "arm64-v8a"
|
||||
}
|
||||
}
|
||||
aaptOptions {
|
||||
cruncherEnabled = false
|
||||
useNewCruncher = false
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs 'libs', '../libs'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation rootProject.ext.dependencies["appcompat-androidx"]
|
||||
implementation rootProject.ext.dependencies["recyclerview-androidx"]
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
//common
|
||||
implementation project(path: ':common')
|
||||
|
||||
implementation 'com.faceunity:core:8.3.1'
|
||||
implementation 'com.faceunity:model:8.3.1'
|
||||
//implementation 'com.faceunity:nama:8.3.1' //底层库-标准版
|
||||
|
||||
|
||||
}
|
0
FaceUnity/consumer-rules.pro
Normal file
0
FaceUnity/consumer-rules.pro
Normal file
21
FaceUnity/proguard-rules.pro
vendored
Normal file
21
FaceUnity/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@ -0,0 +1,26 @@
|
||||
package com.yunbao.faceunity;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("com.yunbao.faceunity.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
18
FaceUnity/src/main/AndroidManifest.xml
Normal file
18
FaceUnity/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.yunbao.faceunity"
|
||||
>
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:icon="@mipmap/ico_home_animoji"
|
||||
android:allowBackup="true">
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
301
FaceUnity/src/main/java/com/yunbao/faceunity/FaceManager.java
Normal file
301
FaceUnity/src/main/java/com/yunbao/faceunity/FaceManager.java
Normal file
@ -0,0 +1,301 @@
|
||||
package com.yunbao.faceunity;
|
||||
|
||||
import static android.content.Context.SENSOR_SERVICE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
|
||||
import com.faceunity.core.entity.FURenderOutputData;
|
||||
import com.faceunity.core.enumeration.CameraFacingEnum;
|
||||
import com.faceunity.core.enumeration.FUAIProcessorEnum;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.enumeration.FUInputTextureEnum;
|
||||
import com.faceunity.core.enumeration.FUTransformMatrixEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.utils.CameraUtils;
|
||||
import com.yunbao.faceunity.data.FaceBeautyDataFactory;
|
||||
import com.yunbao.faceunity.data.FaceUnityDataFactory;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||
import com.yunbao.faceunity.listener.FURendererListener;
|
||||
import com.yunbao.faceunity.ui.FaceUnityView;
|
||||
import com.yunbao.faceunity.utils.CSVUtils;
|
||||
import com.yunbao.faceunity.utils.FURenderer;
|
||||
import com.yunbao.faceunity.utils.FaceSPUtils;
|
||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||
import com.yunbao.faceunity.utils.net.OkHttpUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import cn.rongcloud.rtc.api.RCRTCEngine;
|
||||
import cn.rongcloud.rtc.api.callback.IRCRTCVideoOutputFrameListener;
|
||||
import cn.rongcloud.rtc.base.RCRTCVideoFrame;
|
||||
|
||||
/**
|
||||
* 美颜模块管理类
|
||||
*/
|
||||
public class FaceManager implements SensorEventListener {
|
||||
private static boolean isInit = false;
|
||||
private static final String TAG = FaceManager.class.getSimpleName();
|
||||
private FaceUnityDataFactory mFaceUnityDataFactory;
|
||||
private FaceManager.FaceStatusChanged faceStatusChanged;
|
||||
private boolean pauseFace = false;
|
||||
|
||||
/**
|
||||
* 初始化美颜模块,在AppContext中调用
|
||||
*/
|
||||
public static void initFaceUnity(Context context) {
|
||||
if (isInit) {
|
||||
return;
|
||||
}
|
||||
FaceUnityData.mApplication = context;
|
||||
OkHttpUtils.getInstance().init(context, false);
|
||||
FURenderer.getInstance().setup(context);
|
||||
isInit = true;
|
||||
}
|
||||
|
||||
private FURenderer mFURenderer;
|
||||
|
||||
/**
|
||||
* 配置美颜SDK
|
||||
*/
|
||||
public void initFURender(Context context) {
|
||||
initFaceUnity(context);
|
||||
mFURenderer = FURenderer.getInstance();
|
||||
mFURenderer.setInputTextureType(FUInputTextureEnum.FU_ADM_FLAG_COMMON_TEXTURE);
|
||||
mFURenderer.setCameraFacing(CameraFacingEnum.CAMERA_FRONT);
|
||||
mFURenderer.setInputBufferMatrix(FUTransformMatrixEnum.CCROT90_FLIPHORIZONTAL);
|
||||
mFURenderer.setInputTextureMatrix(FUTransformMatrixEnum.CCROT90_FLIPHORIZONTAL);
|
||||
mFURenderer.setOutputMatrix(FUTransformMatrixEnum.CCROT270);
|
||||
mFURenderer.setInputOrientation(CameraUtils.INSTANCE.getCameraOrientation(Camera.CameraInfo.CAMERA_FACING_FRONT));
|
||||
mFURenderer.setMarkFPSEnable(true);
|
||||
mFaceUnityDataFactory = FaceUnityDataFactory.getInstance();
|
||||
|
||||
SensorManager mSensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
|
||||
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册长按对比键事件
|
||||
*
|
||||
* @param faceUnityView
|
||||
*/
|
||||
public void setFaceUnityView(FaceUnityView faceUnityView) {
|
||||
faceUnityView.setIFaceUnityInter(new FaceUnityView.IFaceUnityInter() {
|
||||
@Override
|
||||
public void onPause() {
|
||||
pauseFace = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
pauseFace = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void loadConfig() {
|
||||
initFaceBeauty();
|
||||
}
|
||||
|
||||
public void initFaceBeauty() {
|
||||
FaceBeautyDataFactory faceBeautyDataFactory;
|
||||
faceBeautyDataFactory = new FaceBeautyDataFactory();
|
||||
Map<String, ?> configMap = FaceSPUtils.getInstance().getAll();
|
||||
for (String key : configMap.keySet()) {
|
||||
if ("FilterViewHolder_".equals(key)) {
|
||||
for (FaceBeautyFilterBean filter : faceBeautyDataFactory.getBeautyFilters()) {
|
||||
if (filter.getKey().equals(configMap.get(key)) && !"origin".equals(configMap.get(key))) {
|
||||
try {
|
||||
faceBeautyDataFactory.onFilterSelected(filter.getKey(), Double.parseDouble((String) Objects.requireNonNull(configMap.get("FilterViewHolder_" + configMap.get(key) + "_val"))) / 100, filter.getDesRes());
|
||||
Log.i(TAG, "test: 设置滤镜 =" + filter.getKey() + " val = " + configMap.get("FilterViewHolder_" + configMap.get(key) + "_val"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (key.startsWith("BeautySkinViewHolder_")) {
|
||||
String name = key.replace("BeautySkinViewHolder_", "");
|
||||
for (FaceBeautyBean bean : faceBeautyDataFactory.getShapeBeauty()) {
|
||||
if (bean.getKey().equals(name)) {
|
||||
try {
|
||||
faceBeautyDataFactory.updateParamIntensity(bean.getKey(), Double.parseDouble((String) Objects.requireNonNull(configMap.get(key))));
|
||||
Log.i(TAG, "test: 设置美颜 = " + bean.getKey() + " val = " + configMap.get(key));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (key.startsWith("BeautyShapeViewHolder")) {
|
||||
String name = key.replace("BeautyShapeViewHolder_", "");
|
||||
for (FaceBeautyBean bean : faceBeautyDataFactory.getShapeBeauty()) {
|
||||
if (bean.getKey().equals(name)) {
|
||||
try {
|
||||
faceBeautyDataFactory.updateParamIntensity(bean.getKey(), Double.parseDouble((String) Objects.requireNonNull(configMap.get(key))));
|
||||
Log.i(TAG, "test: 设置美肤 = " + bean.getKey() + " val = " + configMap.get(key));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听人脸识别个数
|
||||
*/
|
||||
public void setFaceStatusChanged(FaceStatusChanged faceStatusChanged) {
|
||||
this.faceStatusChanged = faceStatusChanged;
|
||||
}
|
||||
|
||||
private boolean mIsFirstFrame = true;
|
||||
private CSVUtils mCSVUtils;
|
||||
private int mSkippedFrames = CAMERA_SWITCH_SKIP_FRAME;
|
||||
// 相机切换跳过 5 帧,如果还有问题,可以增加帧数
|
||||
private static final int CAMERA_SWITCH_SKIP_FRAME = 0;
|
||||
private volatile boolean mSkip;
|
||||
|
||||
/**
|
||||
* 渲染融云视频帧
|
||||
*/
|
||||
public void drawRongFrame(Context context) {
|
||||
RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(new IRCRTCVideoOutputFrameListener() {
|
||||
@Override
|
||||
public RCRTCVideoFrame processVideoFrame(RCRTCVideoFrame callVideoFrame) {
|
||||
//Log.i(TAG, "processVideoFrame: egl context " + EGL14.eglGetCurrentContext());
|
||||
if (pauseFace) {
|
||||
return callVideoFrame;
|
||||
}
|
||||
int width = callVideoFrame.getWidth();
|
||||
int height = callVideoFrame.getHeight();
|
||||
|
||||
if (mIsFirstFrame) {
|
||||
mIsFirstFrame = false;
|
||||
//initCsvUtil(context);
|
||||
mFURenderer.prepareRenderer(mFURendererListener);
|
||||
}
|
||||
//long start = System.nanoTime();
|
||||
mFURenderer.setInputOrientation(callVideoFrame.getRotation());
|
||||
FURenderOutputData data = mFURenderer.onDrawFrameInputWithReturn(callVideoFrame.getData(), width, height);
|
||||
/* long time = System.nanoTime() - start;
|
||||
if (mCSVUtils != null) {
|
||||
mCSVUtils.writeCsv(null, time);
|
||||
}*/
|
||||
if (mSkippedFrames > 0 || mSkip) {
|
||||
--mSkippedFrames;
|
||||
return callVideoFrame;
|
||||
}
|
||||
if (data != null && data.getImage() != null && data.getImage().getBuffer() != null) {
|
||||
callVideoFrame.setData(data.getImage().getBuffer());
|
||||
}
|
||||
return callVideoFrame;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录渲染工具,调试用,在processVideoFrame里使用
|
||||
*/
|
||||
private void initCsvUtil(Context context) {
|
||||
mCSVUtils = new CSVUtils(context);
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault());
|
||||
String dateStrDir = format.format(new Date(System.currentTimeMillis()));
|
||||
dateStrDir = dateStrDir.replaceAll("-", "").replaceAll("_", "");
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault());
|
||||
String dateStrFile = df.format(new Date());
|
||||
String filePath = Environment.getExternalStoragePublicDirectory("") + dateStrDir + File.separator + "excel-" + dateStrFile + ".csv";
|
||||
Log.d("CSV", "initLog: CSV file path:" + filePath);
|
||||
StringBuilder headerInfo = new StringBuilder();
|
||||
headerInfo.append("version:").append(FURenderer.getInstance().getVersion()).append(CSVUtils.COMMA)
|
||||
.append("机型:").append(android.os.Build.MANUFACTURER).append(android.os.Build.MODEL)
|
||||
.append("处理方式:Texture").append(CSVUtils.COMMA);
|
||||
mCSVUtils.initHeader(filePath, headerInfo);
|
||||
}
|
||||
|
||||
|
||||
private FURendererListener mFURendererListener = new FURendererListener() {
|
||||
|
||||
@Override
|
||||
public void onPrepare() {
|
||||
mFaceUnityDataFactory.bindCurrentRenderer();
|
||||
//Log.e(TAG, "mFURendererListener: onPrepare: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackStatusChanged(FUAIProcessorEnum type, int status) {
|
||||
Log.e(TAG, "onTrackStatusChanged: 人脸数: " + status);
|
||||
if (faceStatusChanged != null) {
|
||||
faceStatusChanged.onFaceChanged(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFpsChanged(double fps, double callTime) {
|
||||
final String FPS = String.format(Locale.getDefault(), "%.2f", fps);
|
||||
// Log.d(TAG, "onFpsChanged FPS: " + FPS + ", callTime: " + String.format("%.2f", callTime));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRelease() {
|
||||
// RongCallClient.getInstance().unregisterVideoFrameObserver();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent sensorEvent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int i) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 离开渲染界面时注销融云监听器,不然会绿屏
|
||||
*/
|
||||
public void onClose() {
|
||||
RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
public void release() {
|
||||
mFURenderer.release();
|
||||
try {
|
||||
for (FUAITypeEnum value : FUAITypeEnum.values()) {
|
||||
FUAIKit.getInstance().releaseAIProcessor(value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
isInit = false;
|
||||
|
||||
}
|
||||
|
||||
public interface FaceStatusChanged {
|
||||
void onFaceChanged(int num);
|
||||
}
|
||||
}
|
@ -0,0 +1,258 @@
|
||||
package com.yunbao.faceunity.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.yunbao.common.utils.DpUtil;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.adapters.vh.AnimViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.AnimojiViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BaseViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BeautyBodyViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BeautyShapeViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BeautySkinViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.BigHeadViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.FilterViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.FineStickerViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.MakeupCustomItemViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.MakeupViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.StickerViewHolder;
|
||||
import com.yunbao.faceunity.adapters.vh.StyleViewHolder;
|
||||
import com.yunbao.faceunity.data.AnimojiDataFactory;
|
||||
import com.yunbao.faceunity.data.BodyBeautyDataFactory;
|
||||
import com.yunbao.faceunity.data.FaceBeautyDataFactory;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.data.FineStickerDataFactory;
|
||||
import com.yunbao.faceunity.data.MakeupDataFactory;
|
||||
import com.yunbao.faceunity.data.PropDataFactory;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.PropBean;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.FaceSPUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 美颜配置适配器
|
||||
*/
|
||||
public class ContainerRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> {
|
||||
|
||||
private Context mContext;
|
||||
private List<? extends BaseBean> list;
|
||||
public int selectPosition = -1;
|
||||
private FaceBeautyDataFactory faceBeautyDataFactory;//美颜工厂
|
||||
private MakeupDataFactory makeupDataFactory;//美妆工厂
|
||||
private BodyBeautyDataFactory bodyBeautyDataFactory;//美体工厂
|
||||
private PropDataFactory propDataFactory;//道具业务工厂:道具贴图、AR面具、搞笑大头、表情识别、哈哈镜、手势识别
|
||||
private AnimojiDataFactory animojiDataFactory;//Animoji工厂
|
||||
private FineStickerDataFactory fineStickerDataFactory;//精品贴图
|
||||
private DiscreteSeekBar seekBar;
|
||||
private float seekY = 0;
|
||||
|
||||
public ContainerRecyclerAdapter(Context mContext) {
|
||||
this.mContext = mContext;
|
||||
initDataFactory();
|
||||
}
|
||||
|
||||
public void setSeekBar(DiscreteSeekBar seekBar) {
|
||||
this.seekBar = seekBar;
|
||||
}
|
||||
|
||||
public DiscreteSeekBar getSeekBar() {
|
||||
return seekBar;
|
||||
}
|
||||
|
||||
public void showSeekBar() {
|
||||
if (seekBar.getVisibility() == View.VISIBLE) {
|
||||
return;
|
||||
}
|
||||
seekBar.setVisibility(View.VISIBLE);
|
||||
if (seekY == 0) {
|
||||
seekY = seekBar.getY() - DpUtil.dp2px(20);
|
||||
}
|
||||
seekBar.setY(seekY);
|
||||
}
|
||||
|
||||
public void hideSeekBar() {
|
||||
if (seekBar.getVisibility() == View.INVISIBLE) {
|
||||
return;
|
||||
}
|
||||
seekBar.setOnProgressChangeListener(null);
|
||||
seekBar.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
|
||||
private void initDataFactory() {
|
||||
faceBeautyDataFactory = new FaceBeautyDataFactory(new FaceBeautyDataFactory.FaceBeautyListener() {
|
||||
@Override
|
||||
public void onFilterSelected(int res) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFaceBeautyEnable(boolean enable) {
|
||||
|
||||
}
|
||||
});
|
||||
propDataFactory = new PropDataFactory(new PropDataFactory.PropListener() {
|
||||
@Override
|
||||
public void onItemSelected(PropBean bean) {
|
||||
|
||||
}
|
||||
}, 0, 0);
|
||||
animojiDataFactory = new AnimojiDataFactory(0, 0);
|
||||
makeupDataFactory = new MakeupDataFactory(0);
|
||||
bodyBeautyDataFactory = new BodyBeautyDataFactory();
|
||||
bodyBeautyDataFactory.bindCurrentRenderer();
|
||||
}
|
||||
|
||||
public void setList(ArrayList<? extends BaseBean> list) {
|
||||
this.list = list;
|
||||
this.selectPosition = -1;
|
||||
hideSeekBar();
|
||||
}
|
||||
|
||||
public int getSelectPosition() {
|
||||
return selectPosition;
|
||||
}
|
||||
|
||||
public void setSelectPosition(int selectPosition) {
|
||||
this.selectPosition = selectPosition;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public FaceBeautyDataFactory getFaceBeautyDataFactory() {
|
||||
return faceBeautyDataFactory;
|
||||
}
|
||||
|
||||
public MakeupDataFactory getMakeupDataFactory() {
|
||||
return makeupDataFactory;
|
||||
}
|
||||
|
||||
public BodyBeautyDataFactory getBodyBeautyDataFactory() {
|
||||
return bodyBeautyDataFactory;
|
||||
}
|
||||
|
||||
public PropDataFactory getPropDataFactory() {
|
||||
return propDataFactory;
|
||||
}
|
||||
|
||||
public AnimojiDataFactory getAnimojiDataFactory() {
|
||||
return animojiDataFactory;
|
||||
}
|
||||
|
||||
BaseViewHolder vh = null;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater from = LayoutInflater.from(mContext);
|
||||
switch (viewType) {
|
||||
case FaceParam.FACE_BEAUTY_SKIN:
|
||||
vh = new BeautySkinViewHolder(from.inflate(R.layout.list_item_face_config, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_SHAPE:
|
||||
vh = new BeautyShapeViewHolder(from.inflate(R.layout.list_item_face_config, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_BODY:
|
||||
vh = new BeautyBodyViewHolder(from.inflate(R.layout.list_item_face_config, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_FILTER:
|
||||
vh = new FilterViewHolder(from.inflate(R.layout.list_item_face_config_filter, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP:
|
||||
vh = new MakeupViewHolder(from.inflate(R.layout.list_item_face_config_filter, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_STYLE:
|
||||
vh = new StyleViewHolder(from.inflate(R.layout.list_item_face_config_style, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_ANIMOJI:
|
||||
vh = new AnimojiViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_ANIM:
|
||||
vh = new AnimViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_STICKER:
|
||||
vh = new StickerViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_BIG_HEAD:
|
||||
vh = new BigHeadViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_FINE_STICKER:
|
||||
case FaceParam.FACE_FINE_STICKER_MIDDLE:
|
||||
case FaceParam.FACE_FINE_STICKER_HIGH:
|
||||
case FaceParam.FACE_FINE_STICKER_GAME:
|
||||
vh = new FineStickerViewHolder(from.inflate(R.layout.list_item_face_config_fine_sticker, parent, false));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_FOUNDATION:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_LIP_STICK:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_BLUSHER:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_BROW:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_LINER:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_LASH:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_SHADOW:
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL:
|
||||
vh = new MakeupCustomItemViewHolder(from.inflate(R.layout.list_item_face_config_filter, parent, false));
|
||||
break;
|
||||
default:
|
||||
vh = new BeautySkinViewHolder(LayoutInflater.from(mContext).inflate(R.layout.list_item_face_config, parent, false));
|
||||
}
|
||||
vh.adapter = this;
|
||||
return vh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return list.get(position).getBeanType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
|
||||
holder.setData(list.get(position));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存配置
|
||||
*/
|
||||
public void save(String key, String data) {
|
||||
FaceSPUtils.getInstance().saveString(key, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取配置
|
||||
*/
|
||||
public String getString(String key) {
|
||||
return FaceSPUtils.getInstance().getString(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除配置
|
||||
*/
|
||||
public void del(String key) {
|
||||
FaceSPUtils.getInstance().del(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复默认设置
|
||||
*/
|
||||
public void reset() {
|
||||
if (vh != null) {
|
||||
vh.reset(list);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.yunbao.faceunity.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.yunbao.common.adapter.OnItemClickListener;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.MenuGroupBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 主菜单适配器
|
||||
*/
|
||||
public class MenuGroupRecyclerAdapter extends RecyclerView.Adapter<MenuGroupRecyclerAdapter.Vh> {
|
||||
private Context context;
|
||||
private List<MenuGroupBean> list;
|
||||
private OnItemClickListener onItemClickListener;
|
||||
|
||||
public MenuGroupRecyclerAdapter(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
|
||||
this.onItemClickListener = onItemClickListener;
|
||||
}
|
||||
|
||||
public void setList(List<MenuGroupBean> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new Vh(LayoutInflater.from(context).inflate(R.layout.list_item_menu_group, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull Vh holder, int position) {
|
||||
holder.setData(list.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
|
||||
protected class Vh extends RecyclerView.ViewHolder {
|
||||
ImageView icon;
|
||||
TextView title;
|
||||
|
||||
public Vh(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.item_icon);
|
||||
title = itemView.findViewById(R.id.item_text);
|
||||
itemView.setOnClickListener(v -> {
|
||||
if (onItemClickListener != null) {
|
||||
onItemClickListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setData(MenuGroupBean menuGroupBean) {
|
||||
icon.setImageResource(menuGroupBean.getIconId());
|
||||
title.setText(menuGroupBean.getTitleId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.AnimationFilterBean;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 动画滤镜 *暂无权限
|
||||
*/
|
||||
public class AnimViewHolder extends BaseViewHolder {
|
||||
ImageView icon;
|
||||
|
||||
public AnimViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
TextView title = itemView.findViewById(R.id.tv_control);
|
||||
title.setVisibility(View.GONE);
|
||||
icon.setBackgroundResource(R.drawable.bg_control_square_selector);
|
||||
itemView.setOnClickListener(v -> {
|
||||
adapter.getAnimojiDataFactory().onFilterSelected((AnimationFilterBean) itemView.getTag());
|
||||
setSelectPosition(getAdapterPosition());
|
||||
saveData();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
icon.setSelected(getAdapterPosition() == getSelectPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
adapter.setSelectPosition(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.AnimojiBean;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Animoji
|
||||
*/
|
||||
public class AnimojiViewHolder extends BaseViewHolder {
|
||||
ImageView icon;
|
||||
TextView title;
|
||||
|
||||
public AnimojiViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
title = itemView.findViewById(R.id.tv_control);
|
||||
title.setVisibility(View.GONE);
|
||||
itemView.setOnClickListener(v -> {
|
||||
adapter.getAnimojiDataFactory().onAnimojiSelected((AnimojiBean) itemView.getTag());
|
||||
setSelectPosition(getLayoutPosition());
|
||||
saveData();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
int adapterPosition = getAdapterPosition();
|
||||
int selectPosition = getSelectPosition();
|
||||
if (loadData()) {
|
||||
return;
|
||||
}
|
||||
icon.setSelected(adapterPosition == selectPosition);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
String data = adapter.getString(getName(this));
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
if (!data.equals(String.valueOf(getLayoutPosition()))) {
|
||||
return false;
|
||||
}
|
||||
icon.setSelected(true);
|
||||
adapter.getAnimojiDataFactory().onAnimojiSelected((AnimojiBean) itemView.getTag());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
adapter.save(getName(this), String.valueOf(getLayoutPosition()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
adapter.save(getName(this),"0");
|
||||
adapter.getAnimojiDataFactory().onAnimojiSelected((AnimojiBean) list.get(0));
|
||||
adapter.setSelectPosition(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.yunbao.faceunity.adapters.ContainerRecyclerAdapter;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
|
||||
public ContainerRecyclerAdapter adapter;
|
||||
|
||||
public int getSelectPosition() {
|
||||
return adapter.selectPosition;
|
||||
}
|
||||
|
||||
public void setSelectPosition(int selectPosition) {
|
||||
adapter.selectPosition = selectPosition;
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public BaseViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
public String getName(Object obj){
|
||||
return obj.getClass().getSimpleName()+"_";
|
||||
}
|
||||
|
||||
public abstract void setData(BaseBean data);
|
||||
|
||||
/**
|
||||
* 读取配置
|
||||
* @return 是否有保存的配置
|
||||
*/
|
||||
public abstract boolean loadData();
|
||||
|
||||
/**
|
||||
* 保存配置
|
||||
*/
|
||||
public abstract void saveData();
|
||||
|
||||
/**
|
||||
* 恢复默认配置
|
||||
*/
|
||||
public abstract void reset(List<? extends BaseBean> list);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.BodyBeautyBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.SeekBarUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 美体
|
||||
*/
|
||||
public class BeautyBodyViewHolder extends BaseViewHolder {
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
private TextView value;
|
||||
private DiscreteSeekBar seekBar;
|
||||
|
||||
public BeautyBodyViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.item_icon);
|
||||
title = itemView.findViewById(R.id.item_title);
|
||||
value = itemView.findViewById(R.id.item_value);
|
||||
seekBar = itemView.findViewById(R.id.item_seekBar);
|
||||
seekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
|
||||
super.onProgressChanged(seekBar, value, fromUser);
|
||||
BodyBeautyBean bean = (BodyBeautyBean) itemView.getTag();
|
||||
double toValue = SeekBarUtils.Companion.seekToValue(bean.getModelAttributeData().getMaxRange(), value, seekBar.getMin());
|
||||
BeautyBodyViewHolder.this.value.setText(String.format("%.1f", toValue));
|
||||
adapter.getBodyBeautyDataFactory().updateParamIntensity(bean.getKey(), toValue);
|
||||
saveData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
if (loadData()) {
|
||||
return;
|
||||
}
|
||||
ModelAttributeData attributeData = data.getModelAttributeData();
|
||||
value.setText(attributeData.getDefault() + "");
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
attributeData.getDefault(),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
BodyBeautyBean bean = (BodyBeautyBean) itemView.getTag();
|
||||
String val = adapter.getString(getName(this) + bean.getKey());
|
||||
if (val == null) {
|
||||
return false;
|
||||
}
|
||||
ModelAttributeData attributeData = bean.getModelAttributeData();
|
||||
value.setText(val);
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
Double.parseDouble(val),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
BodyBeautyBean bean = (BodyBeautyBean) itemView.getTag();
|
||||
String key = getName(this) + bean.getKey();
|
||||
adapter.save(key, (String) value.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
String name = getName(this);
|
||||
for (BaseBean bean : list) {
|
||||
adapter.del(name + bean.getKey());
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.SeekBarUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 美型
|
||||
*/
|
||||
public class BeautyShapeViewHolder extends BaseViewHolder {
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
private TextView value;
|
||||
private DiscreteSeekBar seekBar;
|
||||
|
||||
|
||||
public BeautyShapeViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.item_icon);
|
||||
title = itemView.findViewById(R.id.item_title);
|
||||
value = itemView.findViewById(R.id.item_value);
|
||||
seekBar = itemView.findViewById(R.id.item_seekBar);
|
||||
seekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
|
||||
super.onProgressChanged(seekBar, value, fromUser);
|
||||
FaceBeautyBean bean = (FaceBeautyBean) itemView.getTag();
|
||||
double toValue = SeekBarUtils.Companion.seekToValue(bean.getModelAttributeData().getMaxRange(), value, seekBar.getMin());
|
||||
BeautyShapeViewHolder.this.value.setTag(String.format("%.1f", toValue));
|
||||
BeautyShapeViewHolder.this.value.setText(value+"");
|
||||
adapter.getFaceBeautyDataFactory().updateParamIntensity(bean.getKey(), toValue);
|
||||
saveData();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
if(loadData()){
|
||||
return;
|
||||
}
|
||||
ModelAttributeData attributeData = data.getModelAttributeData();
|
||||
value.setText(attributeData.getDefault() + "");
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
attributeData.getDefault(),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
FaceBeautyBean bean = (FaceBeautyBean) itemView.getTag();
|
||||
String val = adapter.getString(getName(this) + bean.getKey());
|
||||
if(val==null) {
|
||||
return false;
|
||||
}
|
||||
ModelAttributeData attributeData = bean.getModelAttributeData();
|
||||
value.setText(val);
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
Double.parseDouble(val),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
FaceBeautyBean bean = (FaceBeautyBean) itemView.getTag();
|
||||
adapter.save(getName(this)+bean.getKey(), (String) value.getTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
String name = getName(this);
|
||||
for (BaseBean bean : list) {
|
||||
adapter.del(name+bean.getKey());
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.SeekBarUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 美肤
|
||||
*/
|
||||
public class BeautySkinViewHolder extends BaseViewHolder{
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
private TextView value;
|
||||
private DiscreteSeekBar seekBar;
|
||||
|
||||
public BeautySkinViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.item_icon);
|
||||
title = itemView.findViewById(R.id.item_title);
|
||||
value = itemView.findViewById(R.id.item_value);
|
||||
seekBar = itemView.findViewById(R.id.item_seekBar);
|
||||
seekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener(){
|
||||
@Override
|
||||
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
|
||||
super.onProgressChanged(seekBar, value, fromUser);
|
||||
FaceBeautyBean bean = (FaceBeautyBean) itemView.getTag();
|
||||
double toValue = SeekBarUtils.Companion.seekToValue(bean.getModelAttributeData().getMaxRange(), value, seekBar.getMin());
|
||||
BeautySkinViewHolder.this.value.setTag(String.format("%.1f",toValue));
|
||||
BeautySkinViewHolder.this.value.setText(value+"");
|
||||
adapter.getFaceBeautyDataFactory().updateParamIntensity(bean.getKey(),toValue);
|
||||
saveData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
if(loadData()){
|
||||
return;
|
||||
}
|
||||
ModelAttributeData attributeData = data.getModelAttributeData();
|
||||
value.setText(attributeData.getDefault() + "");
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
attributeData.getDefault(),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
BaseBean data = (FaceBeautyBean) itemView.getTag();
|
||||
ModelAttributeData attributeData = data.getModelAttributeData();
|
||||
String key = getName(this)+data.getKey();
|
||||
String val=adapter.getString(key);
|
||||
if (val==null){
|
||||
return false;
|
||||
}
|
||||
value.setText(val);
|
||||
SeekBarUtils.Companion.seekToSeekBar(seekBar,
|
||||
Double.parseDouble(val),
|
||||
attributeData.getStand(),
|
||||
attributeData.getMaxRange()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
String key = ((FaceBeautyBean)itemView.getTag()).getKey();
|
||||
String val= (String) value.getTag();
|
||||
adapter.save(getName(this)+key,val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
for (BaseBean bean : list) {
|
||||
adapter.del(getName(this)+bean.getKey());
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||
import com.yunbao.faceunity.entity.PropBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 大头
|
||||
*/
|
||||
public class BigHeadViewHolder extends BaseViewHolder {
|
||||
ImageView icon;
|
||||
|
||||
public BigHeadViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
TextView title = itemView.findViewById(R.id.tv_control);
|
||||
title.setVisibility(View.GONE);
|
||||
itemView.setOnClickListener(v -> {
|
||||
PropBean bean = (PropBean) itemView.getTag();
|
||||
adapter.getPropDataFactory().setPropType(FunctionEnum.BIG_HEAD);
|
||||
adapter.getPropDataFactory().onItemSelected(bean);
|
||||
setSelectPosition(getAdapterPosition());
|
||||
saveData();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
if(loadData()){
|
||||
return;
|
||||
}
|
||||
|
||||
if (getAdapterPosition() == 0) {
|
||||
icon.setBackgroundResource(R.drawable.bg_control_oval2_selector);
|
||||
}
|
||||
icon.setSelected(getSelectPosition() == getAdapterPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
PropBean bean = (PropBean) itemView.getTag();
|
||||
String val = adapter.getString(getName(this));
|
||||
if(val==null){
|
||||
return false;
|
||||
}
|
||||
if(!val.equals(bean.getKey())){
|
||||
return false;
|
||||
}
|
||||
icon.setSelected(true);
|
||||
adapter.getPropDataFactory().setPropType(FunctionEnum.BIG_HEAD);
|
||||
adapter.getPropDataFactory().onItemSelected(bean);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
PropBean bean = (PropBean) itemView.getTag();
|
||||
adapter.save(getName(this),bean.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
adapter.save(getName(this),list.get(0).getKey());
|
||||
adapter.getPropDataFactory().setPropType(FunctionEnum.BIG_HEAD);
|
||||
adapter.getPropDataFactory().onItemSelected((PropBean) list.get(0));
|
||||
adapter.setSelectPosition(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.SeekBarUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 滤镜
|
||||
*/
|
||||
public class FilterViewHolder extends BaseViewHolder {
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
private String KEY_VAL;
|
||||
|
||||
public FilterViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
title = itemView.findViewById(R.id.tv_control);
|
||||
itemView.setOnClickListener(view -> {
|
||||
FaceBeautyFilterBean bean = (FaceBeautyFilterBean) itemView.getTag();
|
||||
adapter.getFaceBeautyDataFactory().onFilterSelected(bean.getKey(), bean.getIntensity(), bean.getDesRes());
|
||||
setSelectPosition(getAdapterPosition());
|
||||
saveData();
|
||||
if("origin".equals(bean.getKey())){
|
||||
adapter.hideSeekBar();
|
||||
return;
|
||||
}
|
||||
adapter.showSeekBar();
|
||||
adapter.getSeekBar().setMax(100);
|
||||
adapter.getSeekBar().setTag(bean);
|
||||
adapter.getSeekBar().setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener(){
|
||||
@Override
|
||||
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
|
||||
super.onProgressChanged(seekBar, value, fromUser);
|
||||
KEY_VAL=getName(FilterViewHolder.this)+((BaseBean)seekBar.getTag()).getKey()+"_val";
|
||||
double toValue = SeekBarUtils.Companion.seekToValue(1, value, seekBar.getMin());
|
||||
adapter.getFaceBeautyDataFactory().updateFilterIntensity(toValue);
|
||||
adapter.save(KEY_VAL,value+"");
|
||||
}
|
||||
});
|
||||
if(adapter.getString(KEY_VAL)==null) {
|
||||
adapter.getSeekBar().setProgress((int) (bean.getIntensity() * 100));
|
||||
}else{
|
||||
adapter.getSeekBar().setProgress(Integer.parseInt(adapter.getString(KEY_VAL)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
if (loadData()) {
|
||||
return;
|
||||
}
|
||||
icon.setSelected(getSelectPosition() == getAdapterPosition());
|
||||
title.setSelected(getSelectPosition() == getAdapterPosition());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
FaceBeautyFilterBean bean = (FaceBeautyFilterBean) itemView.getTag();
|
||||
KEY_VAL=getName(FilterViewHolder.this)+bean.getKey()+"_val";
|
||||
String val = adapter.getString(getName(this));
|
||||
if (val == null) {
|
||||
return false;
|
||||
}
|
||||
if (!val.equals(bean.getKey())) {
|
||||
return false;
|
||||
}
|
||||
if(!"origin".equals(bean.getKey())){
|
||||
adapter.showSeekBar();
|
||||
}
|
||||
icon.setSelected(true);
|
||||
title.setSelected(true);
|
||||
if(adapter.getString(KEY_VAL)!=null) {
|
||||
bean.setIntensity(Double.parseDouble(adapter.getString(KEY_VAL))/100);
|
||||
}
|
||||
adapter.getFaceBeautyDataFactory().onFilterSelected(bean.getKey(), bean.getIntensity(), bean.getDesRes());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
FaceBeautyFilterBean bean = (FaceBeautyFilterBean) itemView.getTag();
|
||||
adapter.save(getName(this), bean.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
FaceBeautyFilterBean bean = (FaceBeautyFilterBean) list.get(0);
|
||||
for (BaseBean baseBean : list) {
|
||||
String key=getName(this)+baseBean.getKey()+"_val";
|
||||
adapter.save(key,"40");
|
||||
}
|
||||
adapter.hideSeekBar();
|
||||
adapter.save(getName(this),bean.getKey());
|
||||
adapter.getFaceBeautyDataFactory().onFilterSelected(bean.getKey(), bean.getIntensity(), bean.getDesRes());
|
||||
adapter.setSelectPosition(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.common.glide.ImgLoader;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.data.FineStickerDataFactory;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
||||
import com.yunbao.faceunity.utils.net.StickerDownloadHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 精品贴纸
|
||||
*/
|
||||
public class FineStickerViewHolder extends BaseViewHolder implements StickerDownloadHelper.Callback {
|
||||
ImageView icon;
|
||||
|
||||
public FineStickerViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
TextView title = itemView.findViewById(R.id.tv_control);
|
||||
title.setVisibility(View.GONE);
|
||||
itemView.setOnClickListener(view -> {
|
||||
FineStickerDataFactory.getInstance().downloadSticker((FineStickerEntity.DocsBean) itemView.getTag());
|
||||
setSelectPosition(getAdapterPosition());
|
||||
saveData();
|
||||
});
|
||||
FineStickerDataFactory.getInstance().addCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
if (data.getImageUrl().isEmpty()) {
|
||||
icon.setImageResource(R.mipmap.icon_control_none);
|
||||
} else {
|
||||
ImgLoader.display(icon.getContext(), data.getImageUrl(), icon);
|
||||
}
|
||||
if (loadData()) {
|
||||
return;
|
||||
}
|
||||
icon.setSelected(getSelectPosition() == getAdapterPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
FineStickerEntity.DocsBean bean = (FineStickerEntity.DocsBean) itemView.getTag();
|
||||
String val = adapter.getString(getName(this) + bean.getKey());
|
||||
if(val==null){
|
||||
return false;
|
||||
}
|
||||
if(!val.equals(bean.getKey())){
|
||||
return false;
|
||||
}
|
||||
FineStickerDataFactory.getInstance().downloadSticker(bean);
|
||||
icon.setSelected(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
FineStickerEntity.DocsBean bean = (FineStickerEntity.DocsBean) itemView.getTag();
|
||||
adapter.save(getName(this), bean.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
adapter.save(getName(this),list.get(0).getKey());
|
||||
itemView.callOnClick();
|
||||
adapter.setSelectPosition(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetTags(String[] tags) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetList(String tag, FineStickerEntity fineSticker) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownload(FineStickerEntity.DocsBean entity) {
|
||||
FineStickerDataFactory.getInstance().onItemSelected(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadError(FineStickerEntity.DocsBean entity, String msg) {
|
||||
ToastUtil.show("下载失败 = " + msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.MakeupCustomBean;
|
||||
import com.yunbao.faceunity.repo.MakeupSource;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 美妆 - 自定义
|
||||
*/
|
||||
public class MakeupCustomItemViewHolder extends BaseViewHolder {
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
|
||||
|
||||
public MakeupCustomItemViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
title = itemView.findViewById(R.id.tv_control);
|
||||
title.setVisibility(View.INVISIBLE);
|
||||
itemView.setOnClickListener(new View.OnClickListener() {
|
||||
private String key = null;
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
adapter.showSeekBar();
|
||||
MakeupCustomBean bean = (MakeupCustomBean) itemView.getTag();
|
||||
key = getMakeupKey(bean.getBeanType());
|
||||
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
adapter.getMakeupDataFactory().enterCustomMakeup();
|
||||
adapter.getMakeupDataFactory().onCustomBeanSelected(key, getAdapterPosition());
|
||||
adapter.getMakeupDataFactory().bindCurrentRenderer();
|
||||
setSelectPosition(getAdapterPosition());
|
||||
double intensity = adapter.getMakeupDataFactory().getCurrentCustomIntensity(key, adapter.getMakeupDataFactory().getCurrentCustomItemIndex(key));
|
||||
adapter.getSeekBar().setProgress((int) (intensity * 100));
|
||||
adapter.getSeekBar().setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
|
||||
super.onProgressChanged(seekBar, value, fromUser);
|
||||
float valueF = (float) (1.0 * (value - seekBar.getMin()) / 100);
|
||||
int current = adapter.getMakeupDataFactory().getCurrentCustomItemIndex(key);
|
||||
adapter.getMakeupDataFactory().updateCustomItemIntensity(key, current, valueF);
|
||||
saveData();
|
||||
}
|
||||
});
|
||||
saveData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageDrawable(data.getImageDrawable());
|
||||
if (loadData()) {
|
||||
return;
|
||||
}
|
||||
if (getSelectPosition() == getAdapterPosition()) {
|
||||
icon.setSelected(true);
|
||||
return;
|
||||
}
|
||||
icon.setSelected(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
MakeupCustomBean bean = (MakeupCustomBean) itemView.getTag();
|
||||
String model = adapter.getString(getName(this));
|
||||
String val = adapter.getString(getName(this) + bean.getKey() + "_val");
|
||||
if (model == null || val == null) {
|
||||
return false;
|
||||
}
|
||||
if(!model.equals(bean.getKey())){
|
||||
return false;
|
||||
}
|
||||
icon.setSelected(true);
|
||||
String key = getMakeupKey(bean.getBeanType());
|
||||
if (key == null) {
|
||||
return false;
|
||||
}
|
||||
adapter.getMakeupDataFactory().enterCustomMakeup();
|
||||
adapter.getMakeupDataFactory().onCustomBeanSelected(key, getAdapterPosition());
|
||||
adapter.getMakeupDataFactory().bindCurrentRenderer();
|
||||
adapter.getSeekBar().setProgress(Integer.parseInt(val));
|
||||
|
||||
float valueF = (float) (1.0 * (Integer.parseInt(val) - adapter.getSeekBar().getMin()) / 100);
|
||||
int current = adapter.getMakeupDataFactory().getCurrentCustomItemIndex(key);
|
||||
adapter.getMakeupDataFactory().updateCustomItemIntensity(key, current, valueF);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
MakeupCustomBean bean = (MakeupCustomBean) itemView.getTag();
|
||||
String key=getMakeupKey(bean.getBeanType());
|
||||
if(key==null){
|
||||
return;
|
||||
}
|
||||
adapter.save(getName(this), key);
|
||||
adapter.save(getName(this) + bean.getKey() + "_val", adapter.getSeekBar().getProgress() + "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
adapter.save(getName(this),list.get(0).getKey());
|
||||
for (BaseBean bean : list) {
|
||||
adapter.del(getName(this) + bean.getKey() + "_val");
|
||||
}
|
||||
adapter.setSelectPosition(0);
|
||||
}
|
||||
|
||||
public String getMakeupKey(int beanType) {
|
||||
String key = null;
|
||||
switch (beanType) {
|
||||
case FaceParam.FACE_MAKEUP_TYPE_FOUNDATION:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_FOUNDATION;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_LIP_STICK:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_LIP_STICK;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_BLUSHER:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_BLUSHER;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_BROW:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_EYE_BROW;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_EYE_SHADOW;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_LINER:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_EYE_LINER;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_LASH:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_EYE_LASH;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_HIGH_LIGHT;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_SHADOW:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_SHADOW;
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL:
|
||||
key = MakeupSource.FACE_MAKEUP_TYPE_EYE_PUPIL;
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.MakeupCombinationBean;
|
||||
import com.yunbao.faceunity.utils.FaceSPUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 美妆
|
||||
*/
|
||||
public class MakeupViewHolder extends BaseViewHolder {
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
|
||||
public MakeupViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon = itemView.findViewById(R.id.iv_control);
|
||||
title = itemView.findViewById(R.id.tv_control);
|
||||
itemView.setOnClickListener(v -> {
|
||||
adapter.getMakeupDataFactory().onMakeupCombinationSelected((MakeupCombinationBean) itemView.getTag());
|
||||
setSelectPosition(getAdapterPosition());
|
||||
saveData();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
if(loadData()){
|
||||
return;
|
||||
}
|
||||
if (getSelectPosition() == getAdapterPosition()) {
|
||||
icon.setSelected(true);
|
||||
title.setSelected(true);
|
||||
return;
|
||||
}
|
||||
icon.setSelected(false);
|
||||
title.setSelected(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
MakeupCombinationBean bean = (MakeupCombinationBean) itemView.getTag();
|
||||
String val = adapter.getString(getName(this));
|
||||
if(val==null){
|
||||
return false;
|
||||
}
|
||||
if(!val.equals(bean.getKey())){
|
||||
return false;
|
||||
}
|
||||
icon.setSelected(true);
|
||||
title.setSelected(true);
|
||||
adapter.getMakeupDataFactory().onMakeupCombinationSelected(bean);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
MakeupCombinationBean bean = (MakeupCombinationBean) itemView.getTag();
|
||||
adapter.save(getName(this),bean.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean>list) {
|
||||
adapter.save(getName(this),list.get(0).getKey());
|
||||
FaceSPUtils.getInstance().delStart("MakeupCustomItemViewHolder");
|
||||
adapter.getMakeupDataFactory().onMakeupCombinationSelected((MakeupCombinationBean) list.get(0));
|
||||
adapter.getMakeupDataFactory().clearAll();
|
||||
adapter.setSelectPosition(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||
import com.yunbao.faceunity.entity.PropBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 普通贴纸
|
||||
*/
|
||||
public class StickerViewHolder extends BaseViewHolder{
|
||||
ImageView icon;
|
||||
public StickerViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon =itemView.findViewById(R.id.iv_control);
|
||||
TextView title = itemView.findViewById(R.id.tv_control);
|
||||
title.setVisibility(View.GONE);
|
||||
itemView.setOnClickListener(v -> {
|
||||
PropBean bean= (PropBean) itemView.getTag();
|
||||
adapter.getPropDataFactory().setPropType(FunctionEnum.STICKER);
|
||||
adapter.getPropDataFactory().onItemSelected(bean);
|
||||
setSelectPosition(getAdapterPosition());
|
||||
saveData();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
if(loadData()){
|
||||
return;
|
||||
}
|
||||
if(getAdapterPosition()==0){
|
||||
icon.setBackgroundResource(R.drawable.bg_control_oval2_selector);
|
||||
}
|
||||
icon.setSelected(getSelectPosition() == getAdapterPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
PropBean bean= (PropBean) itemView.getTag();
|
||||
String val = adapter.getString(getName(this));
|
||||
if(val==null){
|
||||
return false;
|
||||
}
|
||||
if(!val.equals(bean.getKey())){
|
||||
return false;
|
||||
}
|
||||
icon.setSelected(true);
|
||||
adapter.getPropDataFactory().setPropType(FunctionEnum.STICKER);
|
||||
adapter.getPropDataFactory().onItemSelected(bean);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
PropBean bean= (PropBean) itemView.getTag();
|
||||
adapter.save(getName(this),bean.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
adapter.save(getName(this),list.get(0).getKey());
|
||||
adapter.getPropDataFactory().setPropType(FunctionEnum.STICKER);
|
||||
adapter.getPropDataFactory().onItemSelected((PropBean) list.get(0));
|
||||
adapter.setSelectPosition(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.yunbao.faceunity.adapters.vh;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 风格推荐
|
||||
*/
|
||||
public class StyleViewHolder extends BaseViewHolder{
|
||||
private ImageView icon;
|
||||
private TextView title;
|
||||
public StyleViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
icon=itemView.findViewById(R.id.iv_control);
|
||||
title=itemView.findViewById(R.id.tv_control);
|
||||
itemView.setOnClickListener(v -> {
|
||||
BaseBean bean= (BaseBean) itemView.getTag();
|
||||
adapter.getFaceBeautyDataFactory().onStyleSelected(bean.getKey());
|
||||
setSelectPosition(getAdapterPosition());
|
||||
saveData();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(BaseBean data) {
|
||||
itemView.setTag(data);
|
||||
icon.setImageResource(data.getImageRes());
|
||||
title.setText(data.getDesRes());
|
||||
if(loadData()){
|
||||
return;
|
||||
}
|
||||
icon.setSelected(getSelectPosition()==getAdapterPosition());
|
||||
title.setSelected(getSelectPosition()==getAdapterPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData() {
|
||||
BaseBean bean= (BaseBean) itemView.getTag();
|
||||
String val = adapter.getString(getName(this));
|
||||
if(val==null){
|
||||
icon.setSelected(false);
|
||||
title.setSelected(false);
|
||||
return true;
|
||||
}
|
||||
if(!val.equals(bean.getKey())){
|
||||
return false;
|
||||
}
|
||||
icon.setSelected(true);
|
||||
title.setSelected(true);
|
||||
adapter.getFaceBeautyDataFactory().onStyleSelected(bean.getKey());
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
BaseBean bean= (BaseBean) itemView.getTag();
|
||||
adapter.save(getName(this),bean.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(List<? extends BaseBean> list) {
|
||||
// adapter.save(getName(this),list.get(0).getKey());
|
||||
adapter.setSelectPosition(0);
|
||||
adapter.del(getName(this));
|
||||
adapter.getFaceBeautyDataFactory().onStyleSelected(null);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.yunbao.faceunity.checkbox;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatCheckBox;
|
||||
|
||||
|
||||
/**
|
||||
* 解决 RadioButton 在 Android4.4 调用setButtonDrawable(null) 和 XML 设置 android:button="@null"无效的问题
|
||||
*
|
||||
* @author Richie on 2020.05.18
|
||||
*/
|
||||
public class CheckBoxCompat extends AppCompatCheckBox {
|
||||
|
||||
public CheckBoxCompat(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public CheckBoxCompat(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public CheckBoxCompat(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setButtonDrawable(new StateListDrawable());
|
||||
}
|
||||
}
|
@ -0,0 +1,278 @@
|
||||
package com.yunbao.faceunity.checkbox;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
|
||||
/**
|
||||
* Created by tujh on 2018/4/17.
|
||||
*/
|
||||
public class CheckGroup extends LinearLayout {
|
||||
private static final String LOG_TAG = CheckGroup.class.getSimpleName();
|
||||
|
||||
// holds the checked id; the selection is empty by default
|
||||
private int mCheckedId = View.NO_ID;
|
||||
// tracks children radio buttons checked state
|
||||
private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
|
||||
// when true, mOnCheckedChangeListener discards events
|
||||
private boolean mProtectFromCheckedChange = false;
|
||||
private OnCheckedChangeListener mOnCheckedChangeListener;
|
||||
private PassThroughHierarchyChangeListener mPassThroughListener;
|
||||
private OnDispatchActionUpListener mOnDispatchActionUpListener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CheckGroup(Context context) {
|
||||
super(context);
|
||||
setOrientation(VERTICAL);
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CheckGroup(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mChildOnCheckedChangeListener = new CheckedStateTracker();
|
||||
mPassThroughListener = new PassThroughHierarchyChangeListener();
|
||||
super.setOnHierarchyChangeListener(mPassThroughListener);
|
||||
}
|
||||
|
||||
public void setOnDispatchActionUpListener(OnDispatchActionUpListener onDispatchActionUpListener) {
|
||||
mOnDispatchActionUpListener = onDispatchActionUpListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
|
||||
// the user listener is delegated to our pass-through listener
|
||||
mPassThroughListener.mOnHierarchyChangeListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_UP) {
|
||||
if (mOnDispatchActionUpListener != null) {
|
||||
mOnDispatchActionUpListener.onDispatchActionUp((int) ev.getX());
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
// checks the appropriate radio button as requested in the XML file
|
||||
if (mCheckedId != View.NO_ID) {
|
||||
mProtectFromCheckedChange = true;
|
||||
setCheckedStateForView(mCheckedId, true);
|
||||
mProtectFromCheckedChange = false;
|
||||
setCheckedId(mCheckedId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
if (child instanceof CheckBox) {
|
||||
final CheckBox button = (CheckBox) child;
|
||||
if (button.isChecked()) {
|
||||
mProtectFromCheckedChange = true;
|
||||
if (mCheckedId != View.NO_ID) {
|
||||
setCheckedStateForView(mCheckedId, false);
|
||||
}
|
||||
mProtectFromCheckedChange = false;
|
||||
setCheckedId(button.getId());
|
||||
}
|
||||
}
|
||||
|
||||
super.addView(child, index, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the selection to the radio button whose identifier is passed in
|
||||
* parameter. Using View.NO_ID as the selection identifier clears the selection;
|
||||
* such an operation is equivalent to invoking {@link #clearCheck()}.</p>
|
||||
*
|
||||
* @param id the unique id of the radio button to select in this group
|
||||
* @see #getCheckedCheckBoxId()
|
||||
* @see #clearCheck()
|
||||
*/
|
||||
public void check(@IdRes int id) {
|
||||
// don't even bother
|
||||
if (id != View.NO_ID && (id == mCheckedId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCheckedId != View.NO_ID) {
|
||||
setCheckedStateForView(mCheckedId, false);
|
||||
}
|
||||
|
||||
if (id != View.NO_ID) {
|
||||
setCheckedStateForView(id, true);
|
||||
}
|
||||
|
||||
setCheckedId(id);
|
||||
}
|
||||
|
||||
private void setCheckedId(@IdRes int id) {
|
||||
mCheckedId = id;
|
||||
if (mOnCheckedChangeListener != null) {
|
||||
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
|
||||
}
|
||||
}
|
||||
|
||||
private void setCheckedStateForView(int viewId, boolean checked) {
|
||||
View checkedView = findViewById(viewId);
|
||||
if (checkedView != null && checkedView instanceof CheckBox) {
|
||||
((CheckBox) checkedView).setChecked(checked);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the identifier of the selected radio button in this group.
|
||||
* Upon empty selection, the returned value is View.NO_ID.</p>
|
||||
*
|
||||
* @return the unique id of the selected radio button in this group
|
||||
* @attr ref android.R.styleable#CheckGroup_checkedButton
|
||||
* @see #check(int)
|
||||
* @see #clearCheck()
|
||||
*/
|
||||
@IdRes
|
||||
public int getCheckedCheckBoxId() {
|
||||
return mCheckedId;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Clears the selection. When the selection is cleared, no radio button
|
||||
* in this group is selected and {@link #getCheckedCheckBoxId()} returns
|
||||
* null.</p>
|
||||
*
|
||||
* @see #check(int)
|
||||
* @see #getCheckedCheckBoxId()
|
||||
*/
|
||||
public void clearCheck() {
|
||||
check(View.NO_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Register a callback to be invoked when the checked radio button
|
||||
* changes in this group.</p>
|
||||
*
|
||||
* @param listener the callback to call on checked state change
|
||||
*/
|
||||
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
|
||||
mOnCheckedChangeListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getAccessibilityClassName() {
|
||||
return CheckGroup.class.getName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Interface definition for a callback to be invoked when the checked
|
||||
* radio button changed in this group.</p>
|
||||
*/
|
||||
public interface OnCheckedChangeListener {
|
||||
/**
|
||||
* <p>Called when the checked radio button has changed. When the
|
||||
* selection is cleared, checkedId is View.NO_ID.</p>
|
||||
*
|
||||
* @param group the group in which the checked radio button has changed
|
||||
* @param checkedId the unique identifier of the newly checked radio button
|
||||
*/
|
||||
public void onCheckedChanged(CheckGroup group, @IdRes int checkedId);
|
||||
}
|
||||
|
||||
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
// prevents from infinite recursion
|
||||
if (mProtectFromCheckedChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
int id = buttonView.getId();
|
||||
mProtectFromCheckedChange = true;
|
||||
if (mCheckedId != View.NO_ID && mCheckedId != id) {
|
||||
setCheckedStateForView(mCheckedId, false);
|
||||
}
|
||||
mProtectFromCheckedChange = false;
|
||||
|
||||
setCheckedId(isChecked ? id : View.NO_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>A pass-through listener acts upon the events and dispatches them
|
||||
* to another listener. This allows the table layout to set its own internal
|
||||
* hierarchy change listener without preventing the user to setup his.</p>
|
||||
*/
|
||||
private class PassThroughHierarchyChangeListener implements
|
||||
OnHierarchyChangeListener {
|
||||
private OnHierarchyChangeListener mOnHierarchyChangeListener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onChildViewAdded(View parent, View child) {
|
||||
if (parent == CheckGroup.this && child instanceof CheckBox) {
|
||||
int id = child.getId();
|
||||
// generates an id if it's missing
|
||||
if (id == View.NO_ID) {
|
||||
id = View.generateViewId();
|
||||
child.setId(id);
|
||||
}
|
||||
((CheckBox) child).setOnCheckedChangeListener(
|
||||
mChildOnCheckedChangeListener);
|
||||
}
|
||||
|
||||
if (mOnHierarchyChangeListener != null) {
|
||||
mOnHierarchyChangeListener.onChildViewAdded(parent, child);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onChildViewRemoved(View parent, View child) {
|
||||
if (parent == CheckGroup.this && child instanceof CheckBox) {
|
||||
((CheckBox) child).setOnCheckedChangeListener(null);
|
||||
}
|
||||
|
||||
if (mOnHierarchyChangeListener != null) {
|
||||
mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnDispatchActionUpListener {
|
||||
/**
|
||||
* 分发 action up 事件时回调
|
||||
*
|
||||
* @param x
|
||||
*/
|
||||
void onDispatchActionUp(int x);
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.animationFilter.AnimationFilter;
|
||||
import com.faceunity.core.model.antialiasing.Antialiasing;
|
||||
import com.faceunity.core.model.prop.Prop;
|
||||
import com.faceunity.core.model.prop.PropContainer;
|
||||
import com.faceunity.core.model.prop.animoji.Animoji;
|
||||
import com.yunbao.faceunity.entity.AnimationFilterBean;
|
||||
import com.yunbao.faceunity.entity.AnimojiBean;
|
||||
import com.yunbao.faceunity.infe.AbstractAnimojiDataFactory;
|
||||
import com.yunbao.faceunity.repo.AnimojiSource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* DESC:Animoji业务工厂
|
||||
* Created on 2021/3/3
|
||||
*/
|
||||
public class AnimojiDataFactory extends AbstractAnimojiDataFactory {
|
||||
|
||||
/*渲染控制器*/
|
||||
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
private FUAIKit mFUAIKit = FUAIKit.getInstance();
|
||||
/*3D抗锯齿*/
|
||||
public final Antialiasing antialiasing;
|
||||
/*动漫滤镜模型*/
|
||||
public final AnimationFilter animationFilter;
|
||||
/*当前选中贴图模型*/
|
||||
private Prop currentAnimoji;
|
||||
/*当前选中下标*/
|
||||
private int currentAnimojiIndex;
|
||||
/*当前滤镜下标*/
|
||||
private int currentFilterIndex;
|
||||
/*Animoji数据*/
|
||||
private ArrayList<AnimojiBean> animojiBeans;
|
||||
/*Animoji滤镜数据*/
|
||||
private ArrayList<AnimationFilterBean> animationFilterBeans;
|
||||
|
||||
/**
|
||||
* 构造 AnimojiDataFactory
|
||||
*
|
||||
* @param animojiIndex 贴图下标
|
||||
* @param filterIndex 滤镜下标
|
||||
*/
|
||||
public AnimojiDataFactory(int animojiIndex, int filterIndex) {
|
||||
antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING));
|
||||
animationFilter = new AnimationFilter(new FUBundleData(FaceUnityConfig.BUNDLE_ANIMATION_FILTER));
|
||||
currentAnimojiIndex = animojiIndex;
|
||||
currentFilterIndex = filterIndex;
|
||||
animojiBeans = AnimojiSource.buildAnimojis();
|
||||
animationFilterBeans = AnimojiSource.buildFilters();
|
||||
bindCurrentRenderer();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 动漫贴图列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<AnimojiBean> getAnimojis() {
|
||||
return animojiBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动漫滤镜列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<AnimationFilterBean> getFilters() {
|
||||
return animationFilterBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前选中动漫贴图下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentAnimojiIndex() {
|
||||
return currentAnimojiIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前选中动漫贴图下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentAnimojiIndex(int currentAnimojiIndex) {
|
||||
this.currentAnimojiIndex = currentAnimojiIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前选中滤镜下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentFilterIndex() {
|
||||
return currentFilterIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前选中动漫贴图下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentFilterIndex(int currentFilterIndex) {
|
||||
this.currentFilterIndex = currentFilterIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置选中贴图
|
||||
*
|
||||
* @param bean
|
||||
*/
|
||||
@Override
|
||||
public void onAnimojiSelected(AnimojiBean bean) {
|
||||
PropContainer propContainer = mFURenderKit.getPropContainer();
|
||||
String path = bean.getPath();
|
||||
Prop prop = null;
|
||||
if (path != null && path.trim().length() > 0) {
|
||||
prop = new Animoji(new FUBundleData(path));
|
||||
}
|
||||
propContainer.replaceProp(currentAnimoji, prop);
|
||||
currentAnimoji = prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置选中滤镜
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
@Override
|
||||
public void onFilterSelected(AnimationFilterBean data) {
|
||||
|
||||
animationFilter.setStyle(data.getStyle());
|
||||
}
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
mFUAIKit.loadAIProcessor(FaceUnityConfig.BUNDLE_AI_TONGUE, FUAITypeEnum.FUAITYPE_TONGUETRACKING);
|
||||
mFUAIKit.setMaxFaces(4);
|
||||
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
mFURenderKit.setAntialiasing(antialiasing);
|
||||
mFURenderKit.setAnimationFilter(animationFilter);
|
||||
animationFilter.setStyle(animationFilterBeans.get(currentFilterIndex).getStyle());
|
||||
onAnimojiSelected(animojiBeans.get(currentAnimojiIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束需要释放AI驱动
|
||||
*/
|
||||
public void releaseAIProcessor() {
|
||||
mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_TONGUETRACKING);
|
||||
}
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
import com.faceunity.core.avatar.model.Avatar;
|
||||
import com.faceunity.core.avatar.model.Scene;
|
||||
import com.faceunity.core.avatar.scene.ProcessorConfig;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUCoordinate3DData;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.faceunity.FUSceneKit;
|
||||
import com.faceunity.core.model.antialiasing.Antialiasing;
|
||||
import com.yunbao.faceunity.entity.AvatarBean;
|
||||
import com.yunbao.faceunity.infe.AbstractAvatarDataFactory;
|
||||
import com.yunbao.faceunity.repo.AvatarSource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* DESC:
|
||||
* Created on 2021/3/30
|
||||
*/
|
||||
public class AvatarDataFactory extends AbstractAvatarDataFactory {
|
||||
|
||||
/*渲染控制器*/
|
||||
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
private FUAIKit mFUAIKit = FUAIKit.getInstance();
|
||||
/*3D抗锯齿*/
|
||||
public final Antialiasing antialiasing;
|
||||
|
||||
/* 人物队列 */
|
||||
private ArrayList<AvatarBean> members;
|
||||
/* 当前选中人物下标 */
|
||||
private int currentMemberIndex;
|
||||
/* 驱动类型是否为全身 */
|
||||
private Boolean isHumanTrackSceneFull;
|
||||
|
||||
/* 场景 */
|
||||
private Scene sceneModel;
|
||||
/* 男孩对象 */
|
||||
private Avatar boyAvatarModel;
|
||||
/* 女孩对象 */
|
||||
private Avatar girlAvatarModel;
|
||||
/*当前对象*/
|
||||
private Avatar currentAvatarModel;
|
||||
|
||||
|
||||
public AvatarDataFactory(int index, boolean isFull) {
|
||||
isHumanTrackSceneFull = isFull;
|
||||
currentMemberIndex = index;
|
||||
members = AvatarSource.buildMembers();
|
||||
antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING));
|
||||
boyAvatarModel = AvatarSource.buildBoyData(isFull);
|
||||
girlAvatarModel = AvatarSource.buildGirlData(isFull);
|
||||
|
||||
if (index == 0) {
|
||||
currentAvatarModel = girlAvatarModel;
|
||||
} else if (index == 1) {
|
||||
currentAvatarModel = boyAvatarModel;
|
||||
}
|
||||
|
||||
sceneModel = AvatarSource.buildSceneModel(currentAvatarModel);
|
||||
AvatarSource.setSceneBackGround(sceneModel, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取人物队列
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<AvatarBean> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前选中人物下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentMemberIndex() {
|
||||
return currentMemberIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前人物选中下标
|
||||
*
|
||||
* @param index
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentMemberIndex(int index) {
|
||||
currentMemberIndex = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前驱动类型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isHumanTrackSceneFull() {
|
||||
return isHumanTrackSceneFull;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前驱动类型
|
||||
*
|
||||
* @param isFull
|
||||
*/
|
||||
@Override
|
||||
public void setHumanTrackSceneFull(boolean isFull) {
|
||||
isHumanTrackSceneFull = isFull;
|
||||
sceneModel.processorConfig.setTrackScene(isFull ? ProcessorConfig.TrackScene.SceneFull : ProcessorConfig.TrackScene.SceneHalf);
|
||||
if (isFull) {
|
||||
boyAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 58.14, -618.94));
|
||||
girlAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 58.14, -618.94));
|
||||
} else {
|
||||
boyAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 11.76, -183.89));
|
||||
girlAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 11.76, -183.89));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 人物切换
|
||||
*
|
||||
* @param bean
|
||||
*/
|
||||
@Override
|
||||
public void onMemberSelected(AvatarBean bean) {
|
||||
if (mAvatarChoiceListener != null)
|
||||
mAvatarChoiceListener.choiceAvatar(bean);
|
||||
|
||||
sceneModel.replaceAvatar(currentAvatarModel, bean.getDes().equals(AvatarSource.GIRL) ? girlAvatarModel : boyAvatarModel);
|
||||
currentAvatarModel = bean.getDes().equals(AvatarSource.GIRL) ? girlAvatarModel : boyAvatarModel;
|
||||
}
|
||||
|
||||
public void bindCurrentRenderer() {
|
||||
mFUAIKit.loadAIProcessor(FaceUnityConfig.getAIHumanBundle(), FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||
mFUAIKit.setMaxFaces(1);
|
||||
mFURenderKit.setAntialiasing(antialiasing);
|
||||
FUSceneKit.getInstance().addSceneGL(sceneModel);
|
||||
FUSceneKit.getInstance().setCurrentSceneGL(sceneModel);
|
||||
setHumanTrackSceneFull(isHumanTrackSceneFull);
|
||||
}
|
||||
|
||||
public AvatarChoiceListener mAvatarChoiceListener;
|
||||
|
||||
public interface AvatarChoiceListener {
|
||||
void choiceAvatar(AvatarBean avatarBean);
|
||||
}
|
||||
|
||||
public void setAvatarChoiceListener(AvatarChoiceListener avatarChoiceListener) {
|
||||
this.mAvatarChoiceListener = avatarChoiceListener;
|
||||
}
|
||||
}
|
@ -0,0 +1,347 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.faceunity.core.controller.bgSegGreen.BgSegGreenParam;
|
||||
import com.faceunity.core.entity.FUColorRGBData;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.bgSegGreen.BgSegGreen;
|
||||
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean;
|
||||
import com.yunbao.faceunity.entity.BgSegGreenBean;
|
||||
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.infe.AbstractBgSegGreenDataFactory;
|
||||
import com.yunbao.faceunity.repo.BgSegGreenSource;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* DESC:绿幕抠像业务工厂
|
||||
* Created on 2021/3/4
|
||||
*/
|
||||
public class BgSegGreenDataFactory extends AbstractBgSegGreenDataFactory {
|
||||
public interface BgSegGreenListener {
|
||||
/**
|
||||
* 取色状态回调
|
||||
*
|
||||
* @param isSelected 是否选中
|
||||
* @param color 默认颜色
|
||||
*/
|
||||
void onColorPickerStateChanged(boolean isSelected, int color);
|
||||
|
||||
/**
|
||||
* 切换背景道具
|
||||
*
|
||||
* @param bean
|
||||
*/
|
||||
void onBackgroundSelected(BgSegGreenBackgroundBean bean);
|
||||
|
||||
/**
|
||||
* 添加自定义安全区域图片
|
||||
*/
|
||||
void onSafeAreaAdd();
|
||||
|
||||
/**
|
||||
* 切换安全区域图片
|
||||
*
|
||||
* @param bean
|
||||
*/
|
||||
void onSafeAreaSelected(BgSegGreenSafeAreaBean bean);
|
||||
}
|
||||
|
||||
|
||||
/*渲染控制器*/
|
||||
private final FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
|
||||
/*绿幕抠像特效模型*/
|
||||
private final BgSegGreen mBgSegGreen;
|
||||
|
||||
/*绿幕抠像背景列表*/
|
||||
private final ArrayList<BgSegGreenBackgroundBean> mBgSegGreenBackgroundBeans;
|
||||
/* 绿幕抠像当前背景下标 */
|
||||
private int mCurrentBackgroundIndex;
|
||||
|
||||
/*绿幕抠像安全区域列表*/
|
||||
private ArrayList<BgSegGreenSafeAreaBean> mBgSegGreenSafeAreaBeans;
|
||||
/* 绿幕抠像当前安全区域下标 */
|
||||
private int mCurrentSafeAreaIndex;
|
||||
|
||||
/* 回调 */
|
||||
private final BgSegGreenListener mBgSegGreenListener;
|
||||
|
||||
|
||||
/**
|
||||
* 构造绿幕抠像
|
||||
*
|
||||
* @param listener 回调
|
||||
* @param index 背景下标
|
||||
*/
|
||||
public BgSegGreenDataFactory(BgSegGreenListener listener, int index) {
|
||||
mBgSegGreenListener = listener;
|
||||
mBgSegGreen = BgSegGreenSource.buildBgSegGreen();
|
||||
mBgSegGreenBackgroundBeans = BgSegGreenSource.buildBgSegGreenBackground();
|
||||
mBgSegGreenSafeAreaBeans = BgSegGreenSource.buildBgSegGreenSafeArea();
|
||||
mCurrentBackgroundIndex = index;
|
||||
mCurrentSafeAreaIndex = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取绿幕抠像当前背景下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
|
||||
public int getBackgroundIndex() {
|
||||
return mCurrentBackgroundIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置绿幕抠像当前背景下标
|
||||
*
|
||||
* @param backgroundIndex
|
||||
*/
|
||||
@Override
|
||||
public void setBackgroundIndex(int backgroundIndex) {
|
||||
this.mCurrentBackgroundIndex = backgroundIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取绿幕抠像当前安全区域下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getBgSafeAreaIndex() {
|
||||
return mCurrentSafeAreaIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置绿幕抠像安全区域下标
|
||||
*
|
||||
* @param currentSafeAreaIndex
|
||||
*/
|
||||
@Override
|
||||
public void setBgSafeAreaIndex(int currentSafeAreaIndex) {
|
||||
this.mCurrentSafeAreaIndex = currentSafeAreaIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新安全区UI
|
||||
*/
|
||||
public boolean updateSafeAreaBeansAndIndex() {
|
||||
ArrayList<BgSegGreenSafeAreaBean> bgSegGreenSafeAreaBeans = BgSegGreenSource.buildBgSegGreenSafeArea();
|
||||
if (!bgSegGreenSafeAreaBeans.equals(mBgSegGreenSafeAreaBeans)) {
|
||||
//需要刷新数据
|
||||
//比对数据 1、数据增加 or 自定义数据修改 -> 当前应该选中的角标
|
||||
if (bgSegGreenSafeAreaBeans.size() > mBgSegGreenSafeAreaBeans.size()) {
|
||||
//数据增加
|
||||
if (mCurrentSafeAreaIndex > 2) {
|
||||
mCurrentSafeAreaIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
mBgSegGreenSafeAreaBeans = bgSegGreenSafeAreaBeans;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取绿幕抠像项目数据扩展模型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public HashMap<String, ModelAttributeData> getModelAttributeRange() {
|
||||
return BgSegGreenSource.buildModelAttributeRange();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取绿幕抠像功能列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<BgSegGreenBean> getBgSegGreenActions() {
|
||||
return BgSegGreenSource.buildBgSegGreenAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取绿幕抠像安全区域功能列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<BgSegGreenSafeAreaBean> getBgSegGreenSafeAreas() {
|
||||
return mBgSegGreenSafeAreaBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取绿幕抠像背景列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<BgSegGreenBackgroundBean> getBgSegGreenBackgrounds() {
|
||||
return mBgSegGreenBackgroundBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 背景图片变更
|
||||
*
|
||||
* @param data BgSegGreenBackgroundBean
|
||||
*/
|
||||
@Override
|
||||
public void onBackgroundSelected(BgSegGreenBackgroundBean data) {
|
||||
mBgSegGreenListener.onBackgroundSelected(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义安全区域
|
||||
*/
|
||||
@Override
|
||||
public void onSafeAreaAdd() {
|
||||
mBgSegGreenListener.onSafeAreaAdd();
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全区域变更
|
||||
*
|
||||
* @param data BgSegGreenBackgroundBean
|
||||
*/
|
||||
@Override
|
||||
public void onSafeAreaSelected(BgSegGreenSafeAreaBean data) {
|
||||
mBgSegGreenListener.onSafeAreaSelected(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseTemplate() {
|
||||
return getCurrentBgSegGreenModel().isUseTemplate() == 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取色锚点颜色变更
|
||||
*
|
||||
* @param array DoubleArray
|
||||
*/
|
||||
@Override
|
||||
public void onColorRGBChanged(double[] array) {
|
||||
mBgSegGreen.setColorRGB(new FUColorRGBData(array[0], array[1], array[2]));
|
||||
mBgSegGreen.setEnable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绿幕开关
|
||||
*
|
||||
* @param enable Boolean
|
||||
*/
|
||||
@Override
|
||||
public void onBgSegGreenEnableChanged(boolean enable) {
|
||||
mBgSegGreen.setEnable(enable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据名称标识获取对应的值
|
||||
*
|
||||
* @param key String 标识
|
||||
* @return Double 值
|
||||
*/
|
||||
@Override
|
||||
public double getParamIntensity(@NonNull String key) {
|
||||
if (bgSegGreenGetMapping.containsKey(key)) {
|
||||
return bgSegGreenGetMapping.get(key).getValue();
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据名称标识更新对应的值
|
||||
*
|
||||
* @param key String 标识
|
||||
* @return Double 值
|
||||
*/
|
||||
@Override
|
||||
public void updateParamIntensity(@NonNull String key, double value) {
|
||||
if (bgSegGreenSetMapping.containsKey(key)) {
|
||||
Objects.requireNonNull(bgSegGreenSetMapping.get(key)).setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用取色器功能状态变更
|
||||
*
|
||||
* @param selected
|
||||
* @param color
|
||||
*/
|
||||
@Override
|
||||
public void onColorPickerStateChanged(boolean selected, int color) {
|
||||
mBgSegGreenListener.onColorPickerStateChanged(selected, color);
|
||||
}
|
||||
|
||||
//region 业务映射
|
||||
|
||||
/**
|
||||
* 参数设置
|
||||
*/
|
||||
interface BgSegGreenSetParam {
|
||||
void setValue(double value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型参数获取
|
||||
*/
|
||||
interface BgSegGreenGetParam {
|
||||
double getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前绿幕对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private BgSegGreen getCurrentBgSegGreenModel() {
|
||||
return mBgSegGreen;
|
||||
}
|
||||
|
||||
|
||||
/* 模型映射 */
|
||||
private final HashMap<String, BgSegGreenSetParam> bgSegGreenSetMapping = new HashMap<String, BgSegGreenSetParam>() {
|
||||
{
|
||||
put(BgSegGreenParam.SIMILARITY, value -> getCurrentBgSegGreenModel().setSimilarity(value));
|
||||
put(BgSegGreenParam.SMOOTHNESS, value -> getCurrentBgSegGreenModel().setSmoothness(value));
|
||||
put(BgSegGreenParam.TRANSPARENCY, value -> getCurrentBgSegGreenModel().setTransparency(value));
|
||||
}
|
||||
};
|
||||
|
||||
/*模型映射获取模型值*/
|
||||
private final HashMap<String, BgSegGreenGetParam> bgSegGreenGetMapping = new HashMap<String, BgSegGreenGetParam>() {
|
||||
{
|
||||
put(BgSegGreenParam.SIMILARITY, () -> getCurrentBgSegGreenModel().getSimilarity());
|
||||
put(BgSegGreenParam.SMOOTHNESS, () -> getCurrentBgSegGreenModel().getSmoothness());
|
||||
put(BgSegGreenParam.TRANSPARENCY, () -> getCurrentBgSegGreenModel().getTransparency());
|
||||
}
|
||||
};
|
||||
|
||||
//endregion 业务映射
|
||||
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
FUAIKit.getInstance().setMaxFaces(1);
|
||||
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
mFURenderKit.setBgSegGreen(mBgSegGreen);
|
||||
mBgSegGreenListener.onBackgroundSelected(mBgSegGreenBackgroundBeans.get(mCurrentBackgroundIndex));
|
||||
mBgSegGreenListener.onSafeAreaSelected(mBgSegGreenSafeAreaBeans.get(mCurrentSafeAreaIndex));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
import com.faceunity.core.controller.bodyBeauty.BodyBeautyParam;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.bodyBeauty.BodyBeauty;
|
||||
|
||||
import com.yunbao.faceunity.entity.BodyBeautyBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.infe.AbstractBodyBeautyDataFactory;
|
||||
import com.yunbao.faceunity.repo.BodyBeautySource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* DESC:美体业务工厂
|
||||
* Created on 2021/3/2
|
||||
*/
|
||||
public class BodyBeautyDataFactory extends AbstractBodyBeautyDataFactory {
|
||||
|
||||
|
||||
interface BodyBeautySetParamInterface {
|
||||
void setValue(double value);
|
||||
}
|
||||
|
||||
interface BodyBeautyGetParamInterface {
|
||||
double getValue();
|
||||
}
|
||||
|
||||
|
||||
/*渲染控制器*/
|
||||
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
private FUAIKit mFUAIKit = FUAIKit.getInstance();
|
||||
|
||||
/*美体数据模型*/
|
||||
public final BodyBeauty bodyBeauty;
|
||||
|
||||
public BodyBeautyDataFactory() {
|
||||
bodyBeauty = new BodyBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_BODY_BEAUTY));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取美体属性列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<BodyBeautyBean> getBodyBeautyParam() {
|
||||
return BodyBeautySource.buildBodyBeauty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取美体扩展参数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public HashMap<String, ModelAttributeData> getModelAttributeRange() {
|
||||
return BodyBeautySource.buildModelAttributeRange();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取模型参数
|
||||
*
|
||||
* @param key 名称标识
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public double getParamIntensity(String key) {
|
||||
if (bodyBeautyGetMapping.containsKey(key)) {
|
||||
return bodyBeautyGetMapping.get(key).getValue();
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置属性参数
|
||||
*
|
||||
* @param key 名称标识
|
||||
* @param value 结果值
|
||||
*/
|
||||
@Override
|
||||
public void updateParamIntensity(String key, double value) {
|
||||
if (bodyBeautySetMapping.containsKey(key)) {
|
||||
bodyBeautySetMapping.get(key).setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableBodyBeauty(boolean enable) {
|
||||
if (mFURenderKit.getBodyBeauty() != null) {
|
||||
mFURenderKit.getBodyBeauty().setEnable(enable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前模型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private BodyBeauty getCurrentBodyBeautyModel() {
|
||||
return bodyBeauty;
|
||||
}
|
||||
|
||||
|
||||
/*模型映射设置模型值*/
|
||||
private final HashMap<String, BodyBeautySetParamInterface> bodyBeautySetMapping = new HashMap<String, BodyBeautySetParamInterface>() {
|
||||
{
|
||||
put(BodyBeautyParam.BODY_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setBodySlimIntensity(value));
|
||||
put(BodyBeautyParam.LEG_STRETCH_INTENSITY, value -> getCurrentBodyBeautyModel().setLegStretchIntensity(value));
|
||||
put(BodyBeautyParam.WAIST_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setWaistSlimIntensity(value));
|
||||
put(BodyBeautyParam.SHOULDER_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setShoulderSlimIntensity(value));
|
||||
put(BodyBeautyParam.HIP_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setHipSlimIntensity(value));
|
||||
put(BodyBeautyParam.HEAD_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setHeadSlimIntensity(value));
|
||||
put(BodyBeautyParam.LEG_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setLegSlimIntensity(value));
|
||||
}
|
||||
};
|
||||
|
||||
/*模型映射获取模型值*/
|
||||
HashMap<String, BodyBeautyGetParamInterface> bodyBeautyGetMapping = new HashMap<String, BodyBeautyGetParamInterface>() {
|
||||
{
|
||||
put(BodyBeautyParam.BODY_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getBodySlimIntensity());
|
||||
put(BodyBeautyParam.LEG_STRETCH_INTENSITY, ()->getCurrentBodyBeautyModel().getLegStretchIntensity());
|
||||
put(BodyBeautyParam.WAIST_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getWaistSlimIntensity());
|
||||
put(BodyBeautyParam.SHOULDER_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getShoulderSlimIntensity());
|
||||
put(BodyBeautyParam.HIP_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getHipSlimIntensity());
|
||||
put(BodyBeautyParam.HEAD_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getHeadSlimIntensity());
|
||||
put(BodyBeautyParam.LEG_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getLegSlimIntensity());
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
mFUAIKit.loadAIProcessor(FaceUnityConfig.getAIHumanBundle(), FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||
mFUAIKit.setMaxFaces(1);
|
||||
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
mFURenderKit.setBodyBeauty(bodyBeauty);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束需要释放AI驱动
|
||||
*/
|
||||
public void releaseAIProcessor() {
|
||||
mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
import com.faceunity.core.model.facebeauty.FaceBeautyBlurTypeEnum;
|
||||
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 保存到磁盘的对象
|
||||
* 该例只保存特效demo展示出来的美颜功能
|
||||
*/
|
||||
public class FaceBeautyData implements Serializable {
|
||||
/* 美肤 */
|
||||
/* 磨皮类型 */
|
||||
public int blurType = FaceBeautyBlurTypeEnum.FineSkin;
|
||||
/* 磨皮程度 */
|
||||
public double blurIntensity = 0.0;
|
||||
/* 美白程度 */
|
||||
public double colorIntensity = 0.0;
|
||||
/* 红润程度 */
|
||||
public double redIntensity = 0.0;
|
||||
/* 锐化程度 */
|
||||
public double sharpenIntensity = 0.0;
|
||||
/* 亮眼程度 */
|
||||
public double eyeBrightIntensity = 0.0;
|
||||
/* 美牙程度 */
|
||||
public double toothIntensity = 0.0;
|
||||
/* 去黑眼圈强度*/
|
||||
public double removePouchIntensity = 0.0;
|
||||
/* 去法令纹强度*/
|
||||
public double removeLawPatternIntensity = 0.0;
|
||||
|
||||
/*美型*/
|
||||
/* 瘦脸程度 */
|
||||
public double cheekThinningIntensity = 0.0;
|
||||
/* V脸程度 */
|
||||
public double cheekVIntensity = 0.0;
|
||||
/* 窄脸程度 */
|
||||
public double cheekNarrowIntensity = 0.0;
|
||||
/* 短脸程度 */
|
||||
public double cheekShortIntensity = 0.0;
|
||||
/* 小脸程度 */
|
||||
public double cheekSmallIntensity = 0.0;
|
||||
/* 瘦颧骨 */
|
||||
public double cheekBonesIntensity = 0.0;
|
||||
/* 瘦下颌骨 */
|
||||
public double lowerJawIntensity = 0.0;
|
||||
/* 大眼程度 */
|
||||
public double eyeEnlargingIntensity = 0.0;
|
||||
/* 圆眼程度 */
|
||||
public double eyeCircleIntensity = 0.0;
|
||||
/* 下巴调整程度 */
|
||||
public double chinIntensity = 0.5;
|
||||
/* 额头调整程度 */
|
||||
public double forHeadIntensity = 0.5;
|
||||
/* 瘦鼻程度 */
|
||||
public double noseIntensity = 0.0;
|
||||
/* 嘴巴调整程度 */
|
||||
public double mouthIntensity = 0.5;
|
||||
/* 开眼角强度 */
|
||||
public double canthusIntensity = 0.0;
|
||||
/* 眼睛间距 */
|
||||
public double eyeSpaceIntensity = 0.5;
|
||||
/* 眼睛角度 */
|
||||
public double eyeRotateIntensity = 0.5;
|
||||
/* 鼻子长度 */
|
||||
public double longNoseIntensity = 0.5;
|
||||
/* 调节人中 */
|
||||
public double philtrumIntensity = 0.5;
|
||||
/* 微笑嘴角强度 */
|
||||
public double smileIntensity = 0.0;
|
||||
/* 眉毛上下 */
|
||||
public double browHeightIntensity = 0.5;
|
||||
/* 眉毛间距 */
|
||||
public double browSpaceIntensity = 0.5;
|
||||
/* 眼睑 */
|
||||
public double eyeLidIntensity = 0.0;
|
||||
/* 眼睛高度 */
|
||||
public double eyeHeightIntensity = 0.5;
|
||||
/* 眉毛粗细 */
|
||||
public double browThickIntensity = 0.5;
|
||||
/* 嘴巴厚度 */
|
||||
public double lipThickIntensity = 0.5;
|
||||
/* 五官立体 */
|
||||
public double faceThreeIntensity = 0.5;
|
||||
|
||||
/* 风格推荐 */
|
||||
/* 是否开启风格推荐 */
|
||||
/* 风格推荐类型 */
|
||||
public int styleTypeIndex = -1;
|
||||
|
||||
//所有滤镜
|
||||
public HashMap<String,Double> filterMap = new HashMap<>();
|
||||
|
||||
/* 滤镜相关 */
|
||||
/* 滤镜名称 */
|
||||
public String filterName = FaceBeautyFilterEnum.ORIGIN;
|
||||
/* 滤镜程度 */
|
||||
public double filterIntensity = 0.0f;
|
||||
}
|
@ -0,0 +1,470 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.faceunity.core.controller.facebeauty.FaceBeautyParam;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.facebeauty.FaceBeauty;
|
||||
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||
import com.faceunity.core.model.prop.expression.ExpressionRecognition;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyStyleBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.infe.AbstractFaceBeautyDataFactory;
|
||||
import com.yunbao.faceunity.repo.FaceBeautySource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* DESC:美颜业务工厂
|
||||
* Created on 2021/3/1
|
||||
*/
|
||||
public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
||||
|
||||
public interface FaceBeautyListener {
|
||||
/**
|
||||
* 风格切换
|
||||
*
|
||||
* @param res
|
||||
*/
|
||||
void onFilterSelected(int res);
|
||||
|
||||
/**
|
||||
* 美颜开关
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
void onFaceBeautyEnable(boolean enable);
|
||||
}
|
||||
|
||||
interface FaceBeautySetParamInterface {
|
||||
/**
|
||||
* 设置属性值
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void setValue(double value);
|
||||
}
|
||||
|
||||
interface FaceBeautyGetParamInterface {
|
||||
/**
|
||||
* 获取属性值
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
double getValue();
|
||||
}
|
||||
|
||||
/*渲染控制器*/
|
||||
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
|
||||
/*推荐风格标识*/
|
||||
private static int currentStyleIndex = -1;
|
||||
|
||||
/*美颜缓存数据模型 用于普通美颜*/
|
||||
public static final FaceBeauty defaultFaceBeauty = FaceBeautySource.getDefaultFaceBeauty();
|
||||
|
||||
/*当前生效美颜数据模型 普通 or 风格的*/
|
||||
public static FaceBeauty faceBeauty = defaultFaceBeauty;
|
||||
|
||||
|
||||
/*默认滤镜选中下标*/
|
||||
private int currentFilterIndex = 0;
|
||||
/*业务回调*/
|
||||
private final FaceBeautyListener mFaceBeautyListener;
|
||||
|
||||
|
||||
public FaceBeautyDataFactory(FaceBeautyListener listener) {
|
||||
mFaceBeautyListener = listener;
|
||||
}
|
||||
public FaceBeautyDataFactory(){
|
||||
mFaceBeautyListener=new FaceBeautyListener() {
|
||||
@Override
|
||||
public void onFilterSelected(int res) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFaceBeautyEnable(boolean enable) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取美肤参数列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<FaceBeautyBean> getSkinBeauty() {
|
||||
return FaceBeautySource.buildSkinParams();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取美型参数列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<FaceBeautyBean> getShapeBeauty() {
|
||||
return FaceBeautySource.buildShapeParams();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取美型参数列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<FaceBeautyBean> getShapeBeautySubItem() {
|
||||
return FaceBeautySource.buildFaceShapeSubItemParams();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取美肤、美型扩展参数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public HashMap<String, ModelAttributeData> getModelAttributeRange() {
|
||||
return FaceBeautySource.buildModelAttributeRange();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取滤镜参数列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<FaceBeautyFilterBean> getBeautyFilters() {
|
||||
ArrayList<FaceBeautyFilterBean> filterBeans = FaceBeautySource.buildFilters();
|
||||
for (int i = 0; i < filterBeans.size(); i++) {
|
||||
if (filterBeans.get(i).getKey().equals(defaultFaceBeauty.getFilterName())) {
|
||||
filterBeans.get(i).setIntensity(defaultFaceBeauty.getFilterIntensity());
|
||||
currentFilterIndex = i;
|
||||
}
|
||||
}
|
||||
return filterBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前滤镜下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentFilterIndex() {
|
||||
return currentFilterIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前滤镜下标
|
||||
*
|
||||
* @param currentFilterIndex
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentFilterIndex(int currentFilterIndex) {
|
||||
this.currentFilterIndex = currentFilterIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推荐风格列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<FaceBeautyStyleBean> getBeautyStyles() {
|
||||
return FaceBeautySource.buildStylesParams();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前风格推荐标识
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentStyleIndex() {
|
||||
return currentStyleIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置风格推荐标识
|
||||
*
|
||||
* @param styleIndex
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentStyleIndex(int styleIndex) {
|
||||
currentStyleIndex = styleIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置风格推荐标识 来自于硬盘
|
||||
*
|
||||
* @param styleIndex
|
||||
*/
|
||||
public static void setDiskCurrentStyleIndex(int styleIndex) {
|
||||
currentStyleIndex = styleIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 美颜开关设置
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
@Override
|
||||
public void enableFaceBeauty(boolean enable) {
|
||||
mFaceBeautyListener.onFaceBeautyEnable(enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型参数
|
||||
*
|
||||
* @param key 名称标识
|
||||
* @return 属性值
|
||||
*/
|
||||
@Override
|
||||
public double getParamIntensity(@NonNull String key) {
|
||||
if (faceBeautyGetMapping.containsKey(key)) {
|
||||
return faceBeautyGetMapping.get(key).getValue();
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置模型参数
|
||||
*
|
||||
* @param key 名称标识
|
||||
* @param value 属性值
|
||||
*/
|
||||
@Override
|
||||
public void updateParamIntensity(@NonNull String key, double value) {
|
||||
if (faceBeautySetMapping.containsKey(key)) {
|
||||
faceBeautySetMapping.get(key).setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有效果制空
|
||||
*/
|
||||
@Override
|
||||
public void resetParamIntensity() {
|
||||
if (faceBeauty != defaultFaceBeauty) {
|
||||
faceBeauty = defaultFaceBeauty;
|
||||
FURenderKit.getInstance().setFaceBeauty(faceBeauty);
|
||||
}
|
||||
|
||||
ArrayList<FaceBeautyBean> skinBeauty = getSkinBeauty();
|
||||
ArrayList<FaceBeautyBean> shapeBeauty = getShapeBeauty();
|
||||
HashMap<String, ModelAttributeData> modelAttributeRange = getModelAttributeRange();
|
||||
|
||||
//还原美肤
|
||||
for (FaceBeautyBean faceBeautyBean : skinBeauty) {
|
||||
String key = faceBeautyBean.getKey();
|
||||
ModelAttributeData modelAttributeData = modelAttributeRange.get(key);
|
||||
updateParamIntensity(key, modelAttributeData.getStand());
|
||||
}
|
||||
|
||||
//还原美型
|
||||
for (FaceBeautyBean faceBeautyBean : shapeBeauty) {
|
||||
String key = faceBeautyBean.getKey();
|
||||
ModelAttributeData modelAttributeData = modelAttributeRange.get(key);
|
||||
updateParamIntensity(key, modelAttributeData.getStand());
|
||||
}
|
||||
|
||||
//还原滤镜
|
||||
defaultFaceBeauty.setFilterName(FaceBeautyFilterEnum.ORIGIN);
|
||||
defaultFaceBeauty.setFilterIntensity(0.0);
|
||||
setCurrentFilterIndex(0);
|
||||
|
||||
//设置风格角标
|
||||
setCurrentStyleIndex(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentOneHotFaceShape() {
|
||||
return CurrentFaceShapeUIValue.currentFaceShape == null ? FaceBeautyParam.CHEEK_V_INTENSITY : CurrentFaceShapeUIValue.currentFaceShape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentOneHotFaceShape(String faceShape) {
|
||||
CurrentFaceShapeUIValue.currentFaceShape = faceShape;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置当前脸型的UI值
|
||||
*/
|
||||
public void setCurrentFaceShapeUIValue(HashMap<String, Double> hashMap) {
|
||||
CurrentFaceShapeUIValue.currentFaceShapeValue.clear();
|
||||
CurrentFaceShapeUIValue.currentFaceShapeValue.putAll(hashMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前脸型的UI值
|
||||
*/
|
||||
public HashMap<String, Double> getCurrentFaceShapeUIValue() {
|
||||
return CurrentFaceShapeUIValue.currentFaceShapeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换滤镜
|
||||
*
|
||||
* @param name 滤镜名称标识
|
||||
* @param intensity 滤镜强度
|
||||
* @param resID 滤镜名称
|
||||
*/
|
||||
@Override
|
||||
public void onFilterSelected(@NonNull String name, double intensity, int resID) {
|
||||
defaultFaceBeauty.setFilterName(name);
|
||||
defaultFaceBeauty.setFilterIntensity(intensity);
|
||||
mFaceBeautyListener.onFilterSelected(resID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更换滤镜强度
|
||||
*
|
||||
* @param intensity 滤镜强度
|
||||
*/
|
||||
@Override
|
||||
public void updateFilterIntensity(double intensity) {
|
||||
defaultFaceBeauty.setFilterIntensity(intensity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置推荐风格
|
||||
*
|
||||
* @param name 风格key
|
||||
*/
|
||||
@Override
|
||||
public void onStyleSelected(String name) {
|
||||
if (name == null) {
|
||||
faceBeauty = defaultFaceBeauty;
|
||||
FURenderKit.getInstance().setFaceBeauty(faceBeauty);
|
||||
} else {
|
||||
Runnable runnable = FaceBeautySource.styleParams.get(name);
|
||||
if (runnable != null) {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*模型映射设置模型值*/
|
||||
private final HashMap<String, FaceBeautySetParamInterface> faceBeautySetMapping = new HashMap<String, FaceBeautySetParamInterface>() {{
|
||||
put(FaceBeautyParam.COLOR_INTENSITY, defaultFaceBeauty::setColorIntensity);
|
||||
put(FaceBeautyParam.BLUR_INTENSITY, defaultFaceBeauty::setBlurIntensity);
|
||||
put(FaceBeautyParam.RED_INTENSITY, defaultFaceBeauty::setRedIntensity);
|
||||
put(FaceBeautyParam.SHARPEN_INTENSITY, defaultFaceBeauty::setSharpenIntensity);
|
||||
put(FaceBeautyParam.EYE_BRIGHT_INTENSITY, defaultFaceBeauty::setEyeBrightIntensity);
|
||||
put(FaceBeautyParam.TOOTH_WHITEN_INTENSITY, defaultFaceBeauty::setToothIntensity);
|
||||
put(FaceBeautyParam.REMOVE_POUCH_INTENSITY, defaultFaceBeauty::setRemovePouchIntensity);
|
||||
put(FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, defaultFaceBeauty::setRemoveLawPatternIntensity);
|
||||
/*美型*/
|
||||
put(FaceBeautyParam.FACE_SHAPE_INTENSITY, defaultFaceBeauty::setSharpenIntensity);
|
||||
put(FaceBeautyParam.CHEEK_THINNING_INTENSITY, defaultFaceBeauty::setCheekThinningIntensity);
|
||||
put(FaceBeautyParam.CHEEK_V_INTENSITY, defaultFaceBeauty::setCheekVIntensity);
|
||||
put(FaceBeautyParam.CHEEK_LONG_INTENSITY, defaultFaceBeauty::setCheekLongIntensity);
|
||||
put(FaceBeautyParam.CHEEK_CIRCLE_INTENSITY, defaultFaceBeauty::setCheekCircleIntensity);
|
||||
put(FaceBeautyParam.CHEEK_NARROW_INTENSITY, defaultFaceBeauty::setCheekNarrowIntensity);
|
||||
put(FaceBeautyParam.CHEEK_SHORT_INTENSITY, defaultFaceBeauty::setCheekShortIntensity);
|
||||
put(FaceBeautyParam.CHEEK_SMALL_INTENSITY, defaultFaceBeauty::setCheekSmallIntensity);
|
||||
put(FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, defaultFaceBeauty::setCheekBonesIntensity);
|
||||
put(FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, defaultFaceBeauty::setLowerJawIntensity);
|
||||
put(FaceBeautyParam.EYE_ENLARGING_INTENSITY, defaultFaceBeauty::setEyeEnlargingIntensity);
|
||||
put(FaceBeautyParam.EYE_CIRCLE_INTENSITY, defaultFaceBeauty::setEyeCircleIntensity);
|
||||
put(FaceBeautyParam.BROW_HEIGHT_INTENSITY, defaultFaceBeauty::setBrowHeightIntensity);
|
||||
put(FaceBeautyParam.BROW_SPACE_INTENSITY, defaultFaceBeauty::setBrowSpaceIntensity);
|
||||
put(FaceBeautyParam.CHIN_INTENSITY, defaultFaceBeauty::setChinIntensity);
|
||||
put(FaceBeautyParam.FOREHEAD_INTENSITY, defaultFaceBeauty::setForHeadIntensity);
|
||||
put(FaceBeautyParam.NOSE_INTENSITY, defaultFaceBeauty::setNoseIntensity);
|
||||
put(FaceBeautyParam.MOUTH_INTENSITY, defaultFaceBeauty::setMouthIntensity);
|
||||
put(FaceBeautyParam.CANTHUS_INTENSITY, defaultFaceBeauty::setCanthusIntensity);
|
||||
put(FaceBeautyParam.EYE_SPACE_INTENSITY, defaultFaceBeauty::setEyeSpaceIntensity);
|
||||
put(FaceBeautyParam.EYE_ROTATE_INTENSITY, defaultFaceBeauty::setEyeRotateIntensity);
|
||||
put(FaceBeautyParam.LONG_NOSE_INTENSITY, defaultFaceBeauty::setLongNoseIntensity);
|
||||
put(FaceBeautyParam.PHILTRUM_INTENSITY, defaultFaceBeauty::setPhiltrumIntensity);
|
||||
put(FaceBeautyParam.SMILE_INTENSITY, defaultFaceBeauty::setSmileIntensity);
|
||||
}};
|
||||
|
||||
/*模型映射获取模型值*/
|
||||
HashMap<String, FaceBeautyGetParamInterface> faceBeautyGetMapping = new HashMap<String, FaceBeautyGetParamInterface>() {
|
||||
{
|
||||
put(FaceBeautyParam.COLOR_INTENSITY, defaultFaceBeauty::getColorIntensity);
|
||||
put(FaceBeautyParam.BLUR_INTENSITY, defaultFaceBeauty::getBlurIntensity);
|
||||
put(FaceBeautyParam.RED_INTENSITY, defaultFaceBeauty::getRedIntensity);
|
||||
put(FaceBeautyParam.SHARPEN_INTENSITY, defaultFaceBeauty::getSharpenIntensity);
|
||||
put(FaceBeautyParam.EYE_BRIGHT_INTENSITY, defaultFaceBeauty::getEyeBrightIntensity);
|
||||
put(FaceBeautyParam.TOOTH_WHITEN_INTENSITY, defaultFaceBeauty::getToothIntensity);
|
||||
put(FaceBeautyParam.REMOVE_POUCH_INTENSITY, defaultFaceBeauty::getRemovePouchIntensity);
|
||||
put(FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, defaultFaceBeauty::getRemoveLawPatternIntensity);
|
||||
/*美型*/
|
||||
put(FaceBeautyParam.FACE_SHAPE_INTENSITY, defaultFaceBeauty::getSharpenIntensity);
|
||||
put(FaceBeautyParam.CHEEK_THINNING_INTENSITY, defaultFaceBeauty::getCheekThinningIntensity);
|
||||
put(FaceBeautyParam.CHEEK_V_INTENSITY, defaultFaceBeauty::getCheekVIntensity);
|
||||
put(FaceBeautyParam.CHEEK_LONG_INTENSITY, defaultFaceBeauty::getCheekLongIntensity);
|
||||
put(FaceBeautyParam.CHEEK_CIRCLE_INTENSITY, defaultFaceBeauty::getCheekCircleIntensity);
|
||||
put(FaceBeautyParam.CHEEK_NARROW_INTENSITY, defaultFaceBeauty::getCheekNarrowIntensity);
|
||||
put(FaceBeautyParam.CHEEK_SHORT_INTENSITY, defaultFaceBeauty::getCheekShortIntensity);
|
||||
put(FaceBeautyParam.CHEEK_SMALL_INTENSITY, defaultFaceBeauty::getCheekSmallIntensity);
|
||||
put(FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, defaultFaceBeauty::getCheekBonesIntensity);
|
||||
put(FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, defaultFaceBeauty::getLowerJawIntensity);
|
||||
put(FaceBeautyParam.EYE_ENLARGING_INTENSITY, defaultFaceBeauty::getEyeEnlargingIntensity);
|
||||
put(FaceBeautyParam.EYE_CIRCLE_INTENSITY, defaultFaceBeauty::getEyeCircleIntensity);
|
||||
put(FaceBeautyParam.BROW_HEIGHT_INTENSITY, defaultFaceBeauty::getBrowHeightIntensity);
|
||||
put(FaceBeautyParam.BROW_SPACE_INTENSITY, defaultFaceBeauty::getBrowSpaceIntensity);
|
||||
put(FaceBeautyParam.CHIN_INTENSITY, defaultFaceBeauty::getChinIntensity);
|
||||
put(FaceBeautyParam.FOREHEAD_INTENSITY, defaultFaceBeauty::getForHeadIntensity);
|
||||
put(FaceBeautyParam.NOSE_INTENSITY, defaultFaceBeauty::getNoseIntensity);
|
||||
put(FaceBeautyParam.MOUTH_INTENSITY, defaultFaceBeauty::getMouthIntensity);
|
||||
put(FaceBeautyParam.CANTHUS_INTENSITY, defaultFaceBeauty::getCanthusIntensity);
|
||||
put(FaceBeautyParam.EYE_SPACE_INTENSITY, defaultFaceBeauty::getEyeSpaceIntensity);
|
||||
put(FaceBeautyParam.EYE_ROTATE_INTENSITY, defaultFaceBeauty::getEyeRotateIntensity);
|
||||
put(FaceBeautyParam.LONG_NOSE_INTENSITY, defaultFaceBeauty::getLongNoseIntensity);
|
||||
put(FaceBeautyParam.PHILTRUM_INTENSITY, defaultFaceBeauty::getPhiltrumIntensity);
|
||||
put(FaceBeautyParam.SMILE_INTENSITY, defaultFaceBeauty::getSmileIntensity);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
mFURenderKit.setFaceBeauty(faceBeauty);
|
||||
FUAIKit.getInstance().setMaxFaces(4);
|
||||
if (FaceUnityConfig.IS_OPEN_LAND_MARK) {
|
||||
ExpressionRecognition expressionRecognition = new ExpressionRecognition(new FUBundleData(FaceUnityConfig.BUNDLE_LANDMARKS));
|
||||
expressionRecognition.setLandmarksType(FUAITypeEnum.FUAITYPE_FACELANDMARKS239);
|
||||
mFURenderKit.getPropContainer().addProp(expressionRecognition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于记录当前脸型的UI值 -> 用于用户下次点入的时候恢复
|
||||
*/
|
||||
static class CurrentFaceShapeUIValue {
|
||||
/* 当前生效的脸型 */
|
||||
public static String currentFaceShape = FaceBeautyParam.CHEEK_V_INTENSITY;
|
||||
/* 当前脸型的UI值 */
|
||||
public static HashMap<String, Double> currentFaceShapeValue = new HashMap<>();
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
public class FaceParam {
|
||||
public static final int FACE_BEAUTY=100;//美颜
|
||||
public static final int FACE_BEAUTY_SKIN=101;//美肤
|
||||
public static final int FACE_BEAUTY_SHAPE=102;//美型
|
||||
public static final int FACE_BEAUTY_FILTER=103;//滤镜
|
||||
public static final int FACE_BEAUTY_STYLE=104;//风格推荐
|
||||
public static final int FACE_MAKEUP=200;//美妆
|
||||
public static final int FACE_MAKEUP_TYPE_FOUNDATION=201;//粉底
|
||||
public static final int FACE_MAKEUP_TYPE_LIP_STICK=202;//口红
|
||||
public static final int FACE_MAKEUP_TYPE_BLUSHER=203;//腮红
|
||||
public static final int FACE_MAKEUP_TYPE_EYE_BROW=204;//眉毛
|
||||
public static final int FACE_MAKEUP_TYPE_EYE_SHADOW=205;//眼影
|
||||
public static final int FACE_MAKEUP_TYPE_EYE_LINER=206;//眼线
|
||||
public static final int FACE_MAKEUP_TYPE_EYE_LASH=207;//睫毛
|
||||
public static final int FACE_MAKEUP_TYPE_HIGH_LIGHT=208;//高光
|
||||
public static final int FACE_MAKEUP_TYPE_SHADOW=209;//阴影
|
||||
public static final int FACE_MAKEUP_TYPE_EYE_PUPIL=210;//美瞳
|
||||
public static final int FACE_BEAUTY_BODY=300;//美体
|
||||
public static final int FACE_BIG_HEAD=400;//大头
|
||||
public static final int FACE_ANIMOJI=500;//Animoji
|
||||
public static final int FACE_STICKER=600;//贴纸
|
||||
public static final int FACE_FINE_STICKER=700;//精品贴纸
|
||||
public static final int FACE_FINE_STICKER_MIDDLE=701;//中级道具
|
||||
public static final int FACE_FINE_STICKER_HIGH=702;//高级道具
|
||||
public static final int FACE_FINE_STICKER_GAME=703;//游戏道具
|
||||
public static final int FACE_ANIM=800;//动漫滤镜
|
||||
// 占位符,以下均未使用
|
||||
public static final int FACE_ANIM_AR_MASK=900;
|
||||
public static final int FACE_EXPRESSION_RECOGNITION=1000;
|
||||
public static final int FACE_FACE_WARP=1100;
|
||||
public static final int FACE_GESTURE_RECOGNITION=1200;
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
import com.faceunity.core.enumeration.FUAIProcessorEnum;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.yunbao.faceunity.entity.PropBean;
|
||||
import com.yunbao.faceunity.utils.FURenderer;
|
||||
|
||||
/**
|
||||
* DESC:
|
||||
* Created on 2021/4/25
|
||||
*/
|
||||
public class FaceUnityDataFactory {
|
||||
|
||||
/**
|
||||
* 道具数据工厂
|
||||
*/
|
||||
public FaceBeautyDataFactory mFaceBeautyDataFactory;
|
||||
public BodyBeautyDataFactory mBodyBeautyDataFactory;
|
||||
public MakeupDataFactory mMakeupDataFactory;
|
||||
public PropDataFactory mPropDataFactory;
|
||||
|
||||
|
||||
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
private FURenderer mFURenderer = FURenderer.getInstance();
|
||||
|
||||
private static FaceUnityDataFactory sInstance;
|
||||
public static FaceUnityDataFactory getInstance() {
|
||||
if (sInstance == null) {
|
||||
synchronized (FaceUnityDataFactory.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new FaceUnityDataFactory(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static void release() {
|
||||
sInstance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 道具加载标识
|
||||
*/
|
||||
public int currentFunctionIndex;
|
||||
private boolean hasFaceBeautyLoaded = false;
|
||||
private boolean hasBodyBeautyLoaded = false;
|
||||
private boolean hasMakeupLoaded = false;
|
||||
private boolean hasPropLoaded = false;
|
||||
|
||||
|
||||
public FaceUnityDataFactory(int index) {
|
||||
currentFunctionIndex = index;
|
||||
mFaceBeautyDataFactory = new FaceBeautyDataFactory(new FaceBeautyDataFactory.FaceBeautyListener() {
|
||||
@Override
|
||||
public void onFilterSelected(int res) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFaceBeautyEnable(boolean enable) {
|
||||
|
||||
}
|
||||
});
|
||||
mBodyBeautyDataFactory = new BodyBeautyDataFactory();
|
||||
mMakeupDataFactory = new MakeupDataFactory(0);
|
||||
mPropDataFactory = new PropDataFactory(new PropDataFactory.PropListener() {
|
||||
@Override
|
||||
public void onItemSelected(PropBean bean) {
|
||||
|
||||
}
|
||||
},0,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
switch (currentFunctionIndex) {
|
||||
case 0:
|
||||
mFaceBeautyDataFactory.bindCurrentRenderer();
|
||||
hasFaceBeautyLoaded = true;
|
||||
break;
|
||||
case 1:
|
||||
mPropDataFactory.bindCurrentRenderer();
|
||||
hasPropLoaded = true;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
mMakeupDataFactory.bindCurrentRenderer();
|
||||
hasMakeupLoaded = true;
|
||||
break;
|
||||
case 3:
|
||||
mBodyBeautyDataFactory.bindCurrentRenderer();
|
||||
hasBodyBeautyLoaded = true;
|
||||
break;
|
||||
}
|
||||
if (hasFaceBeautyLoaded && currentFunctionIndex != 0) {
|
||||
mFaceBeautyDataFactory.bindCurrentRenderer();
|
||||
}
|
||||
if (hasPropLoaded && currentFunctionIndex != 1) {
|
||||
mPropDataFactory.bindCurrentRenderer();
|
||||
}
|
||||
if (hasMakeupLoaded && currentFunctionIndex != 2) {
|
||||
mMakeupDataFactory.bindCurrentRenderer();
|
||||
}
|
||||
if (hasBodyBeautyLoaded && currentFunctionIndex != 3) {
|
||||
mBodyBeautyDataFactory.bindCurrentRenderer();
|
||||
}
|
||||
if (currentFunctionIndex == 3) {
|
||||
mFURenderKit.getFUAIController().setMaxFaces(1);
|
||||
mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.HUMAN_PROCESSOR);
|
||||
} else {
|
||||
mFURenderKit.getFUAIController().setMaxFaces(4);
|
||||
mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.FACE_PROCESSOR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 道具功能切换
|
||||
*/
|
||||
public void onFunctionSelected(int index) {
|
||||
currentFunctionIndex = index;
|
||||
switch (index) {
|
||||
case 0:
|
||||
if (!hasFaceBeautyLoaded) {
|
||||
mFaceBeautyDataFactory.bindCurrentRenderer();
|
||||
hasFaceBeautyLoaded = true;
|
||||
}
|
||||
mFURenderKit.getFUAIController().setMaxFaces(4);
|
||||
mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.FACE_PROCESSOR);
|
||||
break;
|
||||
case 1:
|
||||
if (!hasPropLoaded) {
|
||||
mPropDataFactory.bindCurrentRenderer();
|
||||
hasPropLoaded = true;
|
||||
}
|
||||
mFURenderKit.getFUAIController().setMaxFaces(4);
|
||||
mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.FACE_PROCESSOR);
|
||||
break;
|
||||
case 2:
|
||||
if (!hasMakeupLoaded) {
|
||||
mMakeupDataFactory.bindCurrentRenderer();
|
||||
hasMakeupLoaded = true;
|
||||
}
|
||||
mFURenderKit.getFUAIController().setMaxFaces(4);
|
||||
mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.FACE_PROCESSOR);
|
||||
break;
|
||||
case 3:
|
||||
if (!hasBodyBeautyLoaded) {
|
||||
mBodyBeautyDataFactory.bindCurrentRenderer();
|
||||
hasBodyBeautyLoaded = true;
|
||||
}
|
||||
mFURenderKit.getFUAIController().setMaxFaces(1);
|
||||
mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.HUMAN_PROCESSOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,405 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
|
||||
import com.faceunity.core.avatar.model.Avatar;
|
||||
import com.faceunity.core.avatar.model.Scene;
|
||||
import com.faceunity.core.avatar.scene.ProcessorConfig;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUTranslationScale;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.faceunity.FUSceneKit;
|
||||
import com.faceunity.core.model.antialiasing.Antialiasing;
|
||||
import com.faceunity.core.model.prop.sticker.FineSticker;
|
||||
import com.faceunity.core.utils.FileUtils;
|
||||
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerTagEntity;
|
||||
import com.yunbao.faceunity.infe.AbstractFineStickerDataFactory;
|
||||
import com.yunbao.faceunity.repo.AvatarSource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
import com.yunbao.faceunity.utils.net.StickerDownloadHelper;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created on 2021/3/31 0031 15:28.
|
||||
* Author: xloger
|
||||
* Email:phoenix@xloger.com
|
||||
*/
|
||||
public class FineStickerDataFactory extends AbstractFineStickerDataFactory {
|
||||
private static final String TAG = "FineStickerDataFactory";
|
||||
private static FineStickerDataFactory factory;
|
||||
public static FineStickerDataFactory getInstance(){
|
||||
if(factory==null){
|
||||
factory=new FineStickerDataFactory();
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*渲染控制器*/
|
||||
private final FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
private FUAIKit mFUAIKit = FUAIKit.getInstance();
|
||||
/*当前选中道具模型*/
|
||||
private FineSticker currentProp;
|
||||
/*菜单视图*/
|
||||
/*当前选中道具*/
|
||||
private FineStickerEntity.DocsBean currentSticker;
|
||||
/*当前道具的类型 普通单bundle,avatar 默认为普通单bundle*/
|
||||
private BundleType mCurrentBundleType = BundleType.NORMAL_SINGLE_BUNDLE;
|
||||
|
||||
//avatar相关
|
||||
/* 场景 */
|
||||
private Scene mSceneModel;
|
||||
/* 对象 */
|
||||
private Avatar mCurrentAvatarModel;
|
||||
/*3D抗锯齿*/
|
||||
public Antialiasing antialiasing;
|
||||
|
||||
//回调
|
||||
private List<StickerDownloadHelper.Callback> callbacks;
|
||||
|
||||
//avatar用于区分bundle类型的关键字
|
||||
private final String COMPONENTS_STR = "components";
|
||||
private final String ANIM_STR = "anim";
|
||||
private final String INFO = "info.json";
|
||||
private final String ZIP = ".zip";
|
||||
private final String AVATAR = "avatar";
|
||||
|
||||
private FineStickerDataFactory() {
|
||||
callbacks=new ArrayList<>();
|
||||
StickerDownloadHelper.getInstance().setCallback(downloadHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定菜单视图
|
||||
*
|
||||
*/
|
||||
public void bindView() {
|
||||
|
||||
}
|
||||
|
||||
public void addCallback(StickerDownloadHelper.Callback downloadHelper) {
|
||||
callbacks.add(downloadHelper);
|
||||
}
|
||||
public void removeCallback(StickerDownloadHelper.Callback downloadHelper){
|
||||
callbacks.remove(downloadHelper);
|
||||
}
|
||||
private void removeAllCallback(){
|
||||
callbacks.clear();
|
||||
}
|
||||
|
||||
public void refuseEvent() {
|
||||
StickerDownloadHelper.getInstance().setCallback(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换道具
|
||||
*
|
||||
* @param bean
|
||||
*/
|
||||
@Override
|
||||
public void onItemSelected(FineStickerEntity.DocsBean bean) {
|
||||
currentSticker = bean;
|
||||
if (bean != null && bean.getTool().getBundle().getUid().endsWith(ZIP)) {
|
||||
//复合道具
|
||||
if (AVATAR.equals(bean.getTool().getCategory())) {
|
||||
//avatar道具
|
||||
if (mCurrentBundleType == BundleType.NORMAL_SINGLE_BUNDLE) {
|
||||
//移除旧的道具
|
||||
mFURenderKit.getPropContainer().removeAllProp();
|
||||
currentProp = null;
|
||||
adapterMaxFace();
|
||||
}
|
||||
if (bean.getUnZipFilePaths() != null) {
|
||||
buildAvatarModel(bean);
|
||||
//当前为 avatar bundle
|
||||
mCurrentBundleType = BundleType.AVATAR_BUNDLE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//普通道具
|
||||
if (mCurrentBundleType == BundleType.NORMAL_SINGLE_BUNDLE) {
|
||||
mFURenderKit.getPropContainer().removeAllProp();
|
||||
currentProp = null;
|
||||
if (bean != null && bean.getFilePath() != null && bean.getFilePath().trim().length() > 0) {
|
||||
adapterMaxFace();
|
||||
FineSticker prop = adapterBean(bean.getFilePath());
|
||||
mFURenderKit.getPropContainer().addProp(prop);
|
||||
currentProp = prop;
|
||||
}
|
||||
} else if (mCurrentBundleType == BundleType.AVATAR_BUNDLE) {
|
||||
//关闭avatar 相关的东西
|
||||
if (mSceneModel != null && mCurrentAvatarModel != null) {
|
||||
mSceneModel.removeAvatar(mCurrentAvatarModel);
|
||||
FUSceneKit.getInstance().removeScene(mSceneModel);
|
||||
mSceneModel = null;
|
||||
mCurrentAvatarModel = null;
|
||||
}
|
||||
|
||||
//设置道具
|
||||
if (bean != null && bean.getFilePath() != null && bean.getFilePath().trim().length() > 0) {
|
||||
adapterMaxFace();
|
||||
FineSticker prop = adapterBean(bean.getFilePath());
|
||||
mFURenderKit.getPropContainer().addProp(prop);
|
||||
currentProp = prop;
|
||||
}
|
||||
}
|
||||
|
||||
//当前为普通bundle
|
||||
mCurrentBundleType = BundleType.NORMAL_SINGLE_BUNDLE;
|
||||
}
|
||||
|
||||
if (mBundleTypeListener != null) {
|
||||
mBundleTypeListener.bundleType(mCurrentBundleType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建avatar -> scene
|
||||
* @param bean
|
||||
*/
|
||||
private void buildAvatarModel(FineStickerEntity.DocsBean bean) {
|
||||
//启动avatar基本逻辑
|
||||
if (antialiasing == null)
|
||||
antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING));
|
||||
//3d抗锯齿
|
||||
mFURenderKit.setAntialiasing(antialiasing);
|
||||
//判断是avatar 控件 -> 查看是否有json文件
|
||||
ArrayList<String> unZipFilePaths = bean.getUnZipFilePaths();
|
||||
int hasJson = unZipFilePaths.indexOf(INFO);
|
||||
|
||||
ArrayList<String> strComponents = new ArrayList<>();//组件Bundle
|
||||
ArrayList<String> strAnimations = new ArrayList<>();//动画Bundle
|
||||
if (hasJson >= 0) {
|
||||
//用json的描述赋予每一个bundle自己的职责,还可以赋予其他参数
|
||||
String jsonPath = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + unZipFilePaths.get(hasJson);
|
||||
//解析json文件 ->
|
||||
String json = FileUtils.loadStringFromExternal(jsonPath);
|
||||
//解析avatar的json文件
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(json);
|
||||
JSONArray components = jsonObject.getJSONArray("components");
|
||||
for(int i =0 ;i < components.length();i++) {
|
||||
String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + components.get(i);
|
||||
strComponents.add(path);
|
||||
}
|
||||
|
||||
JSONArray anims = jsonObject.getJSONArray("anims");
|
||||
for(int i =0 ;i < anims.length();i++) {
|
||||
String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + anims.get(i);
|
||||
strAnimations.add(path);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
//根据bundle的命名赋予每一个bundle自己的职责
|
||||
for (String str:unZipFilePaths) {
|
||||
if (str.startsWith(COMPONENTS_STR)) {
|
||||
String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + str;
|
||||
strComponents.add(path);
|
||||
} else if (str.startsWith(ANIM_STR)){
|
||||
String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + str;
|
||||
strAnimations.add(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mSceneModel == null) {
|
||||
mCurrentAvatarModel = AvatarSource.buildAvatarData(strComponents,strAnimations);
|
||||
mSceneModel = AvatarSource.buildSceneModel(mCurrentAvatarModel);
|
||||
mSceneModel.processorConfig.setTrackScene(ProcessorConfig.TrackScene.SceneFull);
|
||||
mCurrentAvatarModel.transForm.setTranslationScale(new FUTranslationScale(0.5f, 0f, 0.1f));
|
||||
} else {
|
||||
if (mCurrentAvatarModel != null)
|
||||
mSceneModel.removeAvatar(mCurrentAvatarModel);
|
||||
mCurrentAvatarModel = AvatarSource.buildAvatarData(strComponents,strAnimations);
|
||||
mSceneModel.addAvatar(mCurrentAvatarModel);
|
||||
}
|
||||
FUSceneKit.getInstance().addScene(mSceneModel);
|
||||
FUSceneKit.getInstance().setCurrentScene(mSceneModel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据adpater 调整业务模型
|
||||
* 0:维持竖屏
|
||||
* 1:仅限一人
|
||||
* 2:美妆道具
|
||||
* 3:点击事件
|
||||
* 4:翻转
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
private FineSticker adapterBean(String path) {
|
||||
String adapter = currentSticker.getTool().getAdapter();
|
||||
if (adapter == null || !adapter.contains("1")) {
|
||||
mFUAIKit.setMaxFaces(4);
|
||||
} else {
|
||||
mFUAIKit.setMaxFaces(1);
|
||||
}
|
||||
if (adapter != null && adapter.trim().length() > 0) {
|
||||
boolean isFlipPoints = adapter.contains("2");
|
||||
boolean is3DFlipH = adapter.contains("4");
|
||||
boolean isClick = adapter.contains("3");
|
||||
return new FineSticker(new FUBundleData(path), isFlipPoints, is3DFlipH, isClick);
|
||||
} else {
|
||||
return new FineSticker(new FUBundleData(path));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 网络回调
|
||||
*/
|
||||
private StickerDownloadHelper.Callback downloadHelper = new StickerDownloadHelper.Callback() {
|
||||
@Override
|
||||
public void onGetTags(String[] tags) {
|
||||
for (StickerDownloadHelper.Callback callback : callbacks) {
|
||||
callback.onGetTags(tags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetList(String tag, FineStickerEntity fineSticker) {
|
||||
for (StickerDownloadHelper.Callback callback : callbacks) {
|
||||
callback.onGetList(tag, fineSticker);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownload(FineStickerEntity.DocsBean entity) {
|
||||
for (StickerDownloadHelper.Callback callback : callbacks) {
|
||||
callback.onDownload(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadError(FineStickerEntity.DocsBean entity, String msg) {
|
||||
for (StickerDownloadHelper.Callback callback : callbacks) {
|
||||
callback.onDownloadError(entity, msg);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 获取标签列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public List<FineStickerTagEntity> loadTagList() {
|
||||
String[] tags = StickerDownloadHelper.getInstance().tags();
|
||||
return formatTag(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签对应道具列表
|
||||
*
|
||||
* @param tag
|
||||
* @return
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public FineStickerEntity loadStickerList(@NotNull FineStickerTagEntity tag) {
|
||||
return StickerDownloadHelper.getInstance().tools(tag.getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载道具
|
||||
*
|
||||
* @param docsBean
|
||||
*/
|
||||
@Override
|
||||
public void downloadSticker(@NotNull FineStickerEntity.DocsBean docsBean) {
|
||||
try{
|
||||
StickerDownloadHelper.getInstance().download(docsBean);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG,"downloadSticker",e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 数据转换
|
||||
*
|
||||
* @param tags
|
||||
* @return
|
||||
*/
|
||||
public static List<FineStickerTagEntity> formatTag(String[] tags) {
|
||||
List<FineStickerTagEntity> tagEntityList = new ArrayList<>(tags.length);
|
||||
for (int i = 0; i < tags.length; i++) {
|
||||
tagEntityList.add(new FineStickerTagEntity(tags[i]));
|
||||
}
|
||||
return tagEntityList;
|
||||
}
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
mFUAIKit.loadAIProcessor(FaceUnityConfig.getAIHumanBundle(), FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||
mFUAIKit.loadAIProcessor(FaceUnityConfig.BUNDLE_AI_HAND, FUAITypeEnum.FUAITYPE_HANDGESTURE);
|
||||
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
mFUAIKit.setMaxFaces(1);
|
||||
onItemSelected(currentSticker);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 结束需要释放AI驱动
|
||||
*/
|
||||
public void releaseAIProcessor() {
|
||||
mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||
mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_HANDGESTURE);
|
||||
}
|
||||
|
||||
|
||||
private void adapterMaxFace() {
|
||||
if (currentSticker == null) return;
|
||||
String adapter = currentSticker.getTool().getAdapter();
|
||||
if (adapter == null || !adapter.contains("1")) {
|
||||
mFUAIKit.setMaxFaces(4);
|
||||
} else {
|
||||
mFUAIKit.setMaxFaces(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP && currentProp != null && currentProp.isClick()) {
|
||||
currentProp.onClick();
|
||||
}
|
||||
}
|
||||
|
||||
//通过枚举记录每一个bundle的类型
|
||||
public enum BundleType {
|
||||
NORMAL_SINGLE_BUNDLE,//普通的单bundle道具
|
||||
AVATAR_BUNDLE//avatar bundle 一般为多bundle
|
||||
}
|
||||
|
||||
private BundleTypeListener mBundleTypeListener;
|
||||
public interface BundleTypeListener {
|
||||
void bundleType(BundleType bundleType);
|
||||
}
|
||||
public void setBundleTypeListener (BundleTypeListener bundleTypeListener){
|
||||
mBundleTypeListener = bundleTypeListener;
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.prop.expression.ExpressionRecognition;
|
||||
import com.yunbao.faceunity.entity.LightMakeupBean;
|
||||
import com.yunbao.faceunity.infe.AbstractLightMakeupDataFactory;
|
||||
import com.yunbao.faceunity.repo.FaceBeautySource;
|
||||
import com.yunbao.faceunity.repo.LightMakeupSource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* DESC:轻美妆业务工厂
|
||||
* Created on 2021/3/3
|
||||
*/
|
||||
public class LightMakeupDataFactory extends AbstractLightMakeupDataFactory {
|
||||
|
||||
|
||||
/*渲染控制器*/
|
||||
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
|
||||
|
||||
/* 轻美妆队列 */
|
||||
private ArrayList<LightMakeupBean> lightMakeupBeans;
|
||||
/* 当前轻美妆选中下标 */
|
||||
private int currentLightMakeupIndex;
|
||||
|
||||
|
||||
public LightMakeupDataFactory(int index) {
|
||||
currentLightMakeupIndex = index;
|
||||
lightMakeupBeans = LightMakeupSource.buildLightMakeup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取轻美妆队列
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<LightMakeupBean> getLightMakeUpBeans() {
|
||||
return lightMakeupBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取轻美妆下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentLightMakeupIndex() {
|
||||
return currentLightMakeupIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置轻美妆下标
|
||||
*
|
||||
* @param currentLightMakeupIndex
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentLightMakeupIndex(int currentLightMakeupIndex) {
|
||||
this.currentLightMakeupIndex = currentLightMakeupIndex;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 切换轻美妆
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
@Override
|
||||
public void onLightMakeupSelected(LightMakeupBean data) {
|
||||
if (data.getKey() == null) {
|
||||
mFURenderKit.setLightMakeup(null);
|
||||
} else {
|
||||
Runnable runnable = LightMakeupSource.LightMakeupParams.get(data.getKey());
|
||||
if (runnable != null) {
|
||||
runnable.run();
|
||||
}
|
||||
onLightMakeupIntensityChanged(data.getIntensity());
|
||||
}
|
||||
if (mFURenderKit.getFaceBeauty() != null) {
|
||||
mFURenderKit.getFaceBeauty().setFilterName(data.getFilterName());
|
||||
mFURenderKit.getFaceBeauty().setFilterIntensity(data.getFilterIntensity());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改强度
|
||||
*
|
||||
* @param intensity
|
||||
*/
|
||||
@Override
|
||||
public void onLightMakeupIntensityChanged(double intensity) {
|
||||
if (mFURenderKit.getLightMakeup() != null) {
|
||||
mFURenderKit.getLightMakeup().setMakeupIntensity(intensity);
|
||||
}
|
||||
if (mFURenderKit.getFaceBeauty() != null) {
|
||||
mFURenderKit.getFaceBeauty().setFilterIntensity(intensity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
mFURenderKit.setFaceBeauty(FaceBeautySource.clone(FaceBeautyDataFactory.faceBeauty));
|
||||
FUAIKit.getInstance().setMaxFaces(4);
|
||||
LightMakeupBean lightMakeupBean = lightMakeupBeans.get(currentLightMakeupIndex);
|
||||
onLightMakeupSelected(lightMakeupBean);
|
||||
|
||||
if (FaceUnityConfig.IS_OPEN_LAND_MARK) {
|
||||
ExpressionRecognition expressionRecognition = new ExpressionRecognition(new FUBundleData(FaceUnityConfig.BUNDLE_LANDMARKS));
|
||||
expressionRecognition.setLandmarksType(FUAITypeEnum.FUAITYPE_FACELANDMARKS239);
|
||||
mFURenderKit.getPropContainer().addProp(expressionRecognition);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,853 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
|
||||
import static com.yunbao.faceunity.repo.MakeupSource.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUColorRGBData;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.makeup.Makeup;
|
||||
import com.faceunity.core.model.makeup.MakeupLipEnum;
|
||||
|
||||
import com.faceunity.core.model.prop.expression.ExpressionRecognition;
|
||||
import com.faceunity.core.utils.DecimalUtils;
|
||||
import com.yunbao.faceunity.entity.MakeupCombinationBean;
|
||||
import com.yunbao.faceunity.entity.MakeupCustomBean;
|
||||
import com.yunbao.faceunity.entity.MakeupCustomClassBean;
|
||||
import com.yunbao.faceunity.infe.AbstractMakeupDataFactory;
|
||||
import com.yunbao.faceunity.repo.FaceBeautySource;
|
||||
import com.yunbao.faceunity.repo.MakeupSource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* DESC:美妆业务工厂
|
||||
* Created on 2021/3/1
|
||||
*/
|
||||
public class MakeupDataFactory extends AbstractMakeupDataFactory {
|
||||
|
||||
|
||||
/*渲染控制器*/
|
||||
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
|
||||
/*组合妆容列表*/
|
||||
private ArrayList<MakeupCombinationBean> makeupCombinations;
|
||||
/*组合妆容当前下标*/
|
||||
private int currentCombinationIndex;//-1:自定义
|
||||
/*美妆数据模型*/
|
||||
private Makeup currentMakeup;
|
||||
/*当前滤镜*/
|
||||
private String currentFilterName;
|
||||
/*当前滤镜*/
|
||||
private Double currentFilterIntensity;
|
||||
|
||||
|
||||
private LinkedHashMap<String, ArrayList<double[]>> mMakeUpColorMap;//美妆颜色表
|
||||
|
||||
private HashMap<String, Integer> mCustomIndexMap = new HashMap<>();//key:美妆类别 value:当前美妆子项选中下标 默认0
|
||||
private HashMap<String, Double> mCustomIntensityMap = new HashMap<>();//key:美妆类别_子项下标 value:当前美妆选中子项的妆容强度 默认1.0
|
||||
private HashMap<String, Integer> mCustomColorIndexMap = new HashMap<>();//key:美妆类别_子项下标 value:当前美妆选中子项的颜色下标 默认3
|
||||
|
||||
|
||||
public MakeupDataFactory(int index) {
|
||||
makeupCombinations = MakeupSource.buildCombinations();
|
||||
mMakeUpColorMap = MakeupSource.buildMakeUpColorMap();
|
||||
currentCombinationIndex = index;
|
||||
currentFilterName = makeupCombinations.get(index).getFilterName();
|
||||
currentFilterIntensity = makeupCombinations.get(index).getFilterIntensity();
|
||||
currentMakeup = MakeupSource.getMakeupModel(makeupCombinations.get(currentCombinationIndex)); // 当前生效模型
|
||||
}
|
||||
|
||||
//region 组合妆
|
||||
|
||||
/**
|
||||
* 获取当前组合妆容列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@NonNull
|
||||
public ArrayList<MakeupCombinationBean> getMakeupCombinations() {
|
||||
return makeupCombinations;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前组合妆容下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentCombinationIndex() {
|
||||
return currentCombinationIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置组合妆容下标
|
||||
*
|
||||
* @param currentCombinationIndex
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentCombinationIndex(int currentCombinationIndex) {
|
||||
this.currentCombinationIndex = currentCombinationIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换组合妆容
|
||||
*
|
||||
* @param bean
|
||||
*/
|
||||
@Override
|
||||
public void onMakeupCombinationSelected(MakeupCombinationBean bean) {
|
||||
currentFilterName = bean.getFilterName();
|
||||
currentFilterIntensity = bean.getFilterIntensity();
|
||||
if (mFURenderKit.getFaceBeauty() != null) {
|
||||
mFURenderKit.getFaceBeauty().setFilterName(currentFilterName);
|
||||
mFURenderKit.getFaceBeauty().setFilterIntensity(currentFilterIntensity);
|
||||
}
|
||||
currentMakeup = MakeupSource.getMakeupModel(bean);
|
||||
mFURenderKit.setMakeup(currentMakeup);
|
||||
if (!currentMakeup.getControlBundle().getPath().equals(FaceUnityConfig.BUNDLE_FACE_MAKEUP))
|
||||
currentMakeup.setFilterIntensity(currentFilterIntensity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换美妆模型整体强度
|
||||
*
|
||||
* @param intensity
|
||||
*/
|
||||
@Override
|
||||
public void updateCombinationIntensity(double intensity) {
|
||||
currentMakeup.setMakeupIntensity(intensity);
|
||||
currentFilterIntensity = intensity;
|
||||
if (mFURenderKit.getFaceBeauty() != null) {
|
||||
mFURenderKit.getFaceBeauty().setFilterIntensity(currentFilterIntensity);
|
||||
}
|
||||
|
||||
if (!currentMakeup.getControlBundle().getPath().equals(FaceUnityConfig.BUNDLE_FACE_MAKEUP))
|
||||
currentMakeup.setFilterIntensity(currentFilterIntensity);
|
||||
}
|
||||
|
||||
|
||||
//endregion 组合妆
|
||||
|
||||
//region 子美妆
|
||||
|
||||
|
||||
/**
|
||||
* 获取子妆类别列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ArrayList<MakeupCustomClassBean> getMakeupCustomClass() {
|
||||
return MakeupSource.buildCustomClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取子妆列表参数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public LinkedHashMap<String, ArrayList<MakeupCustomBean>> getMakeupCustomItemParams() {
|
||||
return MakeupSource.buildCustomItemParams(mMakeUpColorMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置子妆强度
|
||||
*
|
||||
* @param key
|
||||
* @param current
|
||||
* @param intensity
|
||||
*/
|
||||
@Override
|
||||
public void updateCustomItemIntensity(String key, int current, double intensity) {
|
||||
if (key.equals(FACE_MAKEUP_TYPE_FOUNDATION)) {
|
||||
currentMakeup.setFoundationIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_LIP_STICK)) {
|
||||
currentMakeup.setLipIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_BLUSHER)) {
|
||||
currentMakeup.setBlusherIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_BROW)) {
|
||||
currentMakeup.setEyeBrowIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_SHADOW)) {
|
||||
currentMakeup.setEyeShadowIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_LINER)) {
|
||||
currentMakeup.setEyeLineIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_LASH)) {
|
||||
currentMakeup.setEyeLashIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_HIGH_LIGHT)) {
|
||||
currentMakeup.setHeightLightIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_SHADOW)) {
|
||||
currentMakeup.setShadowIntensity(intensity);
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_PUPIL)) {
|
||||
currentMakeup.setPupilIntensity(intensity);
|
||||
}
|
||||
mCustomIntensityMap.put(key + "_" + current, intensity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换子妆单项
|
||||
*
|
||||
* @param key 子妆类别
|
||||
* @param index 选中下标
|
||||
*/
|
||||
@Override
|
||||
public void onCustomBeanSelected(String key, int index) {
|
||||
String itemDir = FaceUnityConfig.MAKEUP_RESOURCE_ITEM_BUNDLE_DIR;
|
||||
mCustomIndexMap.put(key, index);
|
||||
if (key.equals(FACE_MAKEUP_TYPE_FOUNDATION)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setFoundationIntensity(0.0);
|
||||
} else {
|
||||
currentMakeup.setFoundationBundle(new FUBundleData(itemDir + "mu_style_foundation_01.bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_FOUNDATION + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_FOUNDATION + "_" + index);
|
||||
}
|
||||
currentMakeup.setFoundationIntensity((intensity));
|
||||
updateCustomColor(key, index + 2);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_foundation_01").get(index + 2);
|
||||
currentMakeup.setFoundationColor(buildFUColorRGBData(color));
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_LIP_STICK)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setLipIntensity(0.0);
|
||||
} else {
|
||||
currentMakeup.setLipBundle(new FUBundleData(itemDir + "mu_style_lip_0" + index + ".bundle"));
|
||||
switch (index) {
|
||||
case 1:
|
||||
currentMakeup.setLipType(MakeupLipEnum.FOG);
|
||||
currentMakeup.setEnableTwoLipColor(false);
|
||||
currentMakeup.setLipHighLightEnable(false);
|
||||
currentMakeup.setLipHighLightStrength(0.0);
|
||||
break;
|
||||
case 2:
|
||||
currentMakeup.setLipType(MakeupLipEnum.MOIST);
|
||||
currentMakeup.setEnableTwoLipColor(false);
|
||||
currentMakeup.setLipHighLightEnable(false);
|
||||
currentMakeup.setLipHighLightStrength(0.0);
|
||||
break;
|
||||
case 3:
|
||||
currentMakeup.setLipType(MakeupLipEnum.WATER);
|
||||
currentMakeup.setEnableTwoLipColor(false);
|
||||
currentMakeup.setLipHighLightEnable(true);
|
||||
currentMakeup.setLipHighLightStrength(0.8);
|
||||
break;
|
||||
case 4:
|
||||
currentMakeup.setLipType(MakeupLipEnum.PEARL);
|
||||
currentMakeup.setEnableTwoLipColor(false);
|
||||
currentMakeup.setLipHighLightEnable(false);
|
||||
currentMakeup.setLipHighLightStrength(0.0);
|
||||
break;
|
||||
case 5:
|
||||
currentMakeup.setLipType(MakeupLipEnum.FOG);
|
||||
currentMakeup.setEnableTwoLipColor(true);
|
||||
currentMakeup.setLipHighLightEnable(false);
|
||||
currentMakeup.setLipHighLightStrength(0.0);
|
||||
currentMakeup.setLipColor2(new FUColorRGBData(0.0, 0.0, 0.0, 0.0));
|
||||
break;
|
||||
}
|
||||
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_LIP_STICK + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_LIP_STICK + "_" + index);
|
||||
}
|
||||
currentMakeup.setLipIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_LIP_STICK + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_LIP_STICK + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_BLUSHER)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setBlusherIntensity(0.0);
|
||||
} else {
|
||||
currentMakeup.setBlusherBundle(new FUBundleData(itemDir + "mu_style_blush_0" + index + ".bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_BLUSHER + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_BLUSHER + "_" + index);
|
||||
}
|
||||
currentMakeup.setBlusherIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_BLUSHER + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_BLUSHER + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_BROW)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setEyeBrowIntensity(0.0);
|
||||
currentMakeup.setEnableBrowWarp(false);
|
||||
} else {
|
||||
currentMakeup.setEnableBrowWarp(false);
|
||||
currentMakeup.setEyeBrowBundle(new FUBundleData(itemDir + "mu_style_eyebrow_0" + index + ".bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_BROW + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_BROW + "_" + index);
|
||||
}
|
||||
currentMakeup.setEyeBrowIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_BROW + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_BROW + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_SHADOW)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setEyeShadowIntensity(0.0);
|
||||
} else {
|
||||
currentMakeup.setEyeShadowBundle(new FUBundleData(itemDir + "mu_style_eyeshadow_0" + index + ".bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + index);
|
||||
}
|
||||
currentMakeup.setEyeShadowIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_LINER)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setEyeLineIntensity(0.0);
|
||||
} else {
|
||||
currentMakeup.setEyeLinerBundle(new FUBundleData(itemDir + "mu_style_eyeliner_0" + index + ".bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_LINER + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_LINER + "_" + index);
|
||||
}
|
||||
currentMakeup.setEyeLineIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_LINER + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_LINER + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_LASH)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setEyeLashIntensity(0.0);
|
||||
} else {
|
||||
currentMakeup.setEyeLashBundle(new FUBundleData(itemDir + "mu_style_eyelash_0" + index + ".bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_LASH + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_LASH + "_" + index);
|
||||
}
|
||||
currentMakeup.setEyeLashIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_LASH + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_LASH + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_HIGH_LIGHT)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setHeightLightIntensity(0.0);
|
||||
} else {
|
||||
currentMakeup.setHighLightBundle(new FUBundleData(itemDir + "mu_style_highlight_0" + index + ".bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + index);
|
||||
}
|
||||
currentMakeup.setHeightLightIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_SHADOW)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setShadowIntensity(0.0);
|
||||
} else {
|
||||
currentMakeup.setShadowBundle(new FUBundleData(itemDir + "mu_style_contour_01.bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_SHADOW + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_SHADOW + "_" + index);
|
||||
}
|
||||
currentMakeup.setShadowIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_SHADOW + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_SHADOW + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
}
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_PUPIL)) {
|
||||
if (index == 0) {
|
||||
currentMakeup.setPupilIntensity(0.0);
|
||||
} else {
|
||||
if (index == 1) {
|
||||
currentMakeup.setPupilBundle(new FUBundleData(itemDir + "mu_style_eyepupil_01.bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index);
|
||||
}
|
||||
currentMakeup.setPupilIntensity((intensity));
|
||||
int colorIndex = 3;
|
||||
if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index)) {
|
||||
colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index);
|
||||
}
|
||||
updateCustomColor(key, colorIndex);
|
||||
} else {
|
||||
currentMakeup.setPupilBundle(new FUBundleData(itemDir + "mu_style_eyepupil_0" + (index + 1) + ".bundle"));
|
||||
double intensity = 1.0;
|
||||
if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index)) {
|
||||
intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index);
|
||||
}
|
||||
currentMakeup.setPupilIntensity((intensity));
|
||||
currentMakeup.setPupilColor(buildFUColorRGBData(new double[]{0.0, 0.0, 0.0, 0.0}));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置子妆颜色值
|
||||
*
|
||||
* @param key 类别关键字
|
||||
* @param index 颜色下标
|
||||
*/
|
||||
@Override
|
||||
public void updateCustomColor(String key, int index) {
|
||||
int current = mCustomIndexMap.containsKey(key) ? mCustomIndexMap.get(key) : 0;
|
||||
if (key.equals(FACE_MAKEUP_TYPE_LIP_STICK)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_LIP_STICK + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_lip_01").get(index);
|
||||
if (current == 3)
|
||||
currentMakeup.setLipColorV2(buildFUColorRGBData(color));
|
||||
else
|
||||
currentMakeup.setLipColor(buildFUColorRGBData(color));
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_BLUSHER)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_BLUSHER + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_blush_0" + current).get(index);
|
||||
currentMakeup.setBlusherColor(buildFUColorRGBData(color));
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_BROW)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_BROW + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_eyebrow_01").get(index);
|
||||
currentMakeup.setEyeBrowColor(buildFUColorRGBData(color));
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_SHADOW)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_eyeshadow_0" + current).get(index);
|
||||
currentMakeup.setEyeShadowColor(new FUColorRGBData(color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255));
|
||||
currentMakeup.setEyeShadowColor2(new FUColorRGBData(color[4] * 255, color[5] * 255, color[6] * 255, color[7] * 255));
|
||||
currentMakeup.setEyeShadowColor3(new FUColorRGBData(color[8] * 255, color[9] * 255, color[10] * 255, color[11] * 255));
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_LINER)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_LINER + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_eyeliner_0" + current).get(index);
|
||||
currentMakeup.setEyeLinerColor(buildFUColorRGBData(color));
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_LASH)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_LASH + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_eyelash_0" + current).get(index);
|
||||
currentMakeup.setEyeLashColor(buildFUColorRGBData(color));
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_HIGH_LIGHT)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_highlight_0" + current).get(index);
|
||||
currentMakeup.setHighLightColor(buildFUColorRGBData(color));
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_SHADOW)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_SHADOW + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_contour_01").get(index);
|
||||
currentMakeup.setShadowColor(buildFUColorRGBData(color));
|
||||
} else if (key.equals(FACE_MAKEUP_TYPE_EYE_PUPIL)) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + current, index);
|
||||
double[] color = mMakeUpColorMap.get("color_mu_style_eyepupil_01").get(index);
|
||||
currentMakeup.setPupilColor(buildFUColorRGBData(color));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//endregion 子美妆
|
||||
|
||||
//region 其他
|
||||
|
||||
/**
|
||||
* 进入自定义美妆,模型分析
|
||||
*/
|
||||
@Override
|
||||
public void enterCustomMakeup() {
|
||||
mCustomIndexMap.clear();
|
||||
mCustomColorIndexMap.clear();
|
||||
mCustomIntensityMap.clear();
|
||||
double makeupIntensity = currentMakeup.getMakeupIntensity();
|
||||
/*粉底*/
|
||||
if (currentMakeup.getFoundationIntensity() != 0.0) {
|
||||
double intensity = currentMakeup.getFoundationIntensity() * makeupIntensity;
|
||||
currentMakeup.setFoundationIntensity(intensity);
|
||||
double[] array = currentMakeup.getFoundationColor().toScaleColorArray();
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_foundation_01");
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(array, list.get(i))) {
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_FOUNDATION, i - 2);
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_FOUNDATION + "_" + (i - 2), intensity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*口红*/
|
||||
if (currentMakeup.getLipIntensity() != 0.0) {
|
||||
double intensity = currentMakeup.getLipIntensity() * makeupIntensity;
|
||||
currentMakeup.setLipIntensity(intensity);
|
||||
int current = 0;
|
||||
switch (currentMakeup.getLipType()) {
|
||||
case MakeupLipEnum.FOG:
|
||||
if (currentMakeup.getEnableTwoLipColor()) {
|
||||
current = 5;
|
||||
} else {
|
||||
current = 1;
|
||||
}
|
||||
break;
|
||||
case MakeupLipEnum.MOIST:
|
||||
current = 3;
|
||||
break;
|
||||
case MakeupLipEnum.PEARL:
|
||||
current = 4;
|
||||
break;
|
||||
case MakeupLipEnum.WATER:
|
||||
current = 2;
|
||||
break;
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_LIP_STICK, current);
|
||||
if (current != 0) {
|
||||
double[] colorArray;
|
||||
if (currentMakeup.getLipType() == MakeupLipEnum.WATER) {
|
||||
colorArray = currentMakeup.getLipColorV2().toScaleColorArray();
|
||||
} else {
|
||||
colorArray = currentMakeup.getLipColor().toScaleColorArray();
|
||||
}
|
||||
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_lip_01");
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_LIP_STICK + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_LIP_STICK + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
/*腮红*/
|
||||
if (currentMakeup.getBlusherIntensity() != 0.0 && currentMakeup.getBlusherBundle() != null) {
|
||||
double intensity = currentMakeup.getBlusherIntensity() * makeupIntensity;
|
||||
currentMakeup.setBlusherIntensity(intensity);
|
||||
String path = currentMakeup.getBlusherBundle().getPath();
|
||||
int current = 0;
|
||||
if (path.endsWith("mu_style_blush_01.bundle")) {
|
||||
current = 1;
|
||||
} else if (path.endsWith("mu_style_blush_02.bundle")) {
|
||||
current = 2;
|
||||
} else if (path.endsWith("mu_style_blush_03.bundle")) {
|
||||
current = 3;
|
||||
} else if (path.endsWith("mu_style_blush_04.bundle")) {
|
||||
current = 4;
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_BLUSHER, current);
|
||||
if (current != 0) {
|
||||
double[] colorArray = currentMakeup.getBlusherColor().toScaleColorArray();
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_blush_0" + current);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_BLUSHER + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_BLUSHER + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
/*眉毛*/
|
||||
if (currentMakeup.getEyeBrowIntensity() != 0.0) {
|
||||
double intensity = currentMakeup.getEyeBrowIntensity() * makeupIntensity;
|
||||
currentMakeup.setEyeBrowIntensity(intensity);
|
||||
int current = 0;
|
||||
if (currentMakeup.getEyeBrowBundle() != null && currentMakeup.getEyeBrowBundle().getPath() != null) {
|
||||
String bundlePath = currentMakeup.getEyeBrowBundle().getPath();
|
||||
int spotIndex = bundlePath.lastIndexOf(".");
|
||||
String index = bundlePath.substring(spotIndex - 1, spotIndex);
|
||||
current = Integer.valueOf(index);
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_BROW, current);
|
||||
if (current != 0) {
|
||||
double[] colorArray = currentMakeup.getEyeBrowColor().toScaleColorArray();
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_eyebrow_01");
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_BROW + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_BROW + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
/*眼影*/
|
||||
if (currentMakeup.getEyeShadowIntensity() != 0.0 && currentMakeup.getEyeShadowBundle() != null) {
|
||||
double intensity = currentMakeup.getEyeShadowIntensity() * makeupIntensity;
|
||||
currentMakeup.setEyeShadowIntensity(intensity);
|
||||
String path = currentMakeup.getEyeShadowBundle().getPath();
|
||||
int current = 0;
|
||||
if (path.endsWith("mu_style_eyeshadow_01.bundle")) {
|
||||
current = 1;
|
||||
} else if (path.endsWith("mu_style_eyeshadow_02.bundle")) {
|
||||
current = 2;
|
||||
} else if (path.endsWith("mu_style_eyeshadow_03.bundle")) {
|
||||
current = 3;
|
||||
} else if (path.endsWith("mu_style_eyeshadow_04.bundle")) {
|
||||
current = 4;
|
||||
} else if (path.endsWith("mu_style_eyeshadow_05.bundle")) {
|
||||
current = 5;
|
||||
} else if (path.endsWith("mu_style_eyeshadow_06.bundle")) {
|
||||
current = 6;
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_SHADOW, current);
|
||||
if (current != 0) {
|
||||
double[] array = new double[12];
|
||||
double[] color1 = currentMakeup.getEyeShadowColor().toScaleColorArray();
|
||||
double[] color2 = currentMakeup.getEyeShadowColor2().toScaleColorArray();
|
||||
double[] color3 = currentMakeup.getEyeShadowColor3().toScaleColorArray();
|
||||
System.arraycopy(color1, 0, array, 0, color1.length);
|
||||
System.arraycopy(color2, 0, array, 4, color2.length);
|
||||
System.arraycopy(color3, 0, array, 8, color3.length);
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_eyeshadow_0" + current);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(array, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
/*眼线*/
|
||||
if (currentMakeup.getEyeLineIntensity() != 0.0 && currentMakeup.getEyeLinerBundle() != null) {
|
||||
double intensity = currentMakeup.getEyeLineIntensity() * makeupIntensity;
|
||||
currentMakeup.setEyeLineIntensity(intensity);
|
||||
String path = currentMakeup.getEyeLinerBundle().getPath();
|
||||
int current = 0;
|
||||
if (path.endsWith("mu_style_eyeliner_01.bundle")) {
|
||||
current = 1;
|
||||
} else if (path.endsWith("mu_style_eyeliner_02.bundle")) {
|
||||
current = 2;
|
||||
} else if (path.endsWith("mu_style_eyeliner_03.bundle")) {
|
||||
current = 3;
|
||||
} else if (path.endsWith("mu_style_eyeliner_04.bundle")) {
|
||||
current = 4;
|
||||
} else if (path.endsWith("mu_style_eyeliner_05.bundle")) {
|
||||
current = 5;
|
||||
} else if (path.endsWith("mu_style_eyeliner_06.bundle")) {
|
||||
current = 6;
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_LINER, current);
|
||||
if (current != 0) {
|
||||
double[] colorArray = currentMakeup.getEyeLinerColor().toScaleColorArray();
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_eyeliner_0" + current);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_LINER + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_LINER + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
/* 睫毛*/
|
||||
if (currentMakeup.getEyeLashIntensity() != 0.0 && currentMakeup.getEyeLashBundle() != null) {
|
||||
double intensity = currentMakeup.getEyeLashIntensity() * makeupIntensity;
|
||||
currentMakeup.setEyeLashIntensity(intensity);
|
||||
String path = currentMakeup.getEyeLashBundle().getPath();
|
||||
int current = 0;
|
||||
if (path.endsWith("mu_style_eyelash_01.bundle")) {
|
||||
current = 1;
|
||||
} else if (path.endsWith("mu_style_eyelash_02.bundle")) {
|
||||
current = 2;
|
||||
} else if (path.endsWith("mu_style_eyelash_03.bundle")) {
|
||||
current = 3;
|
||||
} else if (path.endsWith("mu_style_eyelash_04.bundle")) {
|
||||
current = 4;
|
||||
} else if (path.endsWith("mu_style_eyelash_05.bundle")) {
|
||||
current = 5;
|
||||
} else if (path.endsWith("mu_style_eyelash_06.bundle")) {
|
||||
current = 6;
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_LASH, current);
|
||||
if (current != 0) {
|
||||
double[] colorArray = currentMakeup.getEyeLashColor().toScaleColorArray();
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_eyelash_0" + current);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_LASH + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_LASH + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
/* 高光*/
|
||||
if (currentMakeup.getHeightLightIntensity() != 0.0 && currentMakeup.getHighLightBundle() != null) {
|
||||
double intensity = currentMakeup.getHeightLightIntensity() * makeupIntensity;
|
||||
currentMakeup.setHeightLightIntensity(intensity);
|
||||
String path = currentMakeup.getHighLightBundle().getPath();
|
||||
int current = 0;
|
||||
if (path.endsWith("mu_style_highlight_01.bundle")) {
|
||||
current = 1;
|
||||
} else if (path.endsWith("mu_style_highlight_02.bundle")) {
|
||||
current = 2;
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_HIGH_LIGHT, current);
|
||||
if (current != 0) {
|
||||
double[] colorArray = currentMakeup.getHighLightColor().toScaleColorArray();
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_highlight_0" + current);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
/* 阴影*/
|
||||
if (currentMakeup.getShadowIntensity() != 0.0 && currentMakeup.getShadowBundle() != null) {
|
||||
double intensity = currentMakeup.getShadowIntensity() * makeupIntensity;
|
||||
currentMakeup.setShadowIntensity(intensity);
|
||||
String path = currentMakeup.getShadowBundle().getPath();
|
||||
int current = 0;
|
||||
if (path.endsWith("mu_style_contour_01.bundle")) {
|
||||
current = 1;
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_SHADOW, current);
|
||||
if (current != 0) {
|
||||
double[] colorArray = currentMakeup.getShadowColor().toScaleColorArray();
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_contour_01");
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_SHADOW + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_SHADOW + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
/* 美瞳*/
|
||||
if (currentMakeup.getPupilIntensity() != 0.0 && currentMakeup.getPupilBundle() != null) {
|
||||
double intensity = currentMakeup.getPupilIntensity() * makeupIntensity;
|
||||
currentMakeup.setPupilIntensity(intensity);
|
||||
String path = currentMakeup.getPupilBundle().getPath();
|
||||
int current = 0;
|
||||
if (path.endsWith("mu_style_eyepupil_01.bundle")) {
|
||||
current = 1;
|
||||
} else if (path.endsWith("mu_style_eyepupil_03.bundle")) {
|
||||
current = 2;
|
||||
} else if (path.endsWith("mu_style_eyepupil_04.bundle")) {
|
||||
current = 3;
|
||||
} else if (path.endsWith("mu_style_eyepupil_05.bundle")) {
|
||||
current = 4;
|
||||
} else if (path.endsWith("mu_style_eyepupil_06.bundle")) {
|
||||
current = 5;
|
||||
} else if (path.endsWith("mu_style_eyepupil_07.bundle")) {
|
||||
current = 6;
|
||||
} else if (path.endsWith("mu_style_eyepupil_08.bundle")) {
|
||||
current = 7;
|
||||
} else if (path.endsWith("mu_style_eyepupil_09.bundle")) {
|
||||
current = 8;
|
||||
}
|
||||
mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_PUPIL, current);
|
||||
if (current != 0) {
|
||||
double[] colorArray = currentMakeup.getPupilColor().toScaleColorArray();
|
||||
ArrayList<double[]> list = mMakeUpColorMap.get("color_mu_style_eyepupil_01");
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) {
|
||||
mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + current, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + current, intensity);
|
||||
}
|
||||
}
|
||||
currentMakeup.setMakeupIntensity(1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 或当单项列表当前下标
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentCustomItemIndex(String key) {
|
||||
if (mCustomIndexMap.containsKey(key)) {
|
||||
return mCustomIndexMap.get(key);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前单项颜色下标
|
||||
*
|
||||
* @param key
|
||||
* @param current
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentCustomColorIndex(String key, int current) {
|
||||
if (mCustomColorIndexMap.containsKey(key + "_" + current)) {
|
||||
return mCustomColorIndexMap.get(key + "_" + current);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前单项强度
|
||||
*
|
||||
* @param key
|
||||
* @param current
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public double getCurrentCustomIntensity(String key, int current) {
|
||||
if (mCustomIntensityMap.containsKey(key + "_" + current)) {
|
||||
return mCustomIntensityMap.get(key + "_" + current);
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
mFURenderKit.setFaceBeauty(FaceBeautySource.clone(FaceBeautyDataFactory.faceBeauty));
|
||||
mFURenderKit.getFaceBeauty().setFilterName(currentFilterName);
|
||||
mFURenderKit.getFaceBeauty().setFilterIntensity(currentFilterIntensity);
|
||||
if (!currentMakeup.getControlBundle().getPath().equals(FaceUnityConfig.BUNDLE_FACE_MAKEUP))
|
||||
currentMakeup.setFilterIntensity(currentFilterIntensity);
|
||||
FUAIKit.getInstance().setMaxFaces(4);
|
||||
mFURenderKit.setMakeup(currentMakeup);
|
||||
|
||||
//特殊有一些需要设置图层混合模式的 04双色眼影3(第2层眼影的混合模式 == 1) 06三色眼影2(第3层眼影的混合模式 == 1)
|
||||
if (currentMakeup.getEyeShadowBundle() != null && ("mu_style_eyeshadow_0" + 4).equals(currentMakeup.getEyeShadowBundle().getName()))
|
||||
currentMakeup.setEyeShadowTexBlend2(1);
|
||||
else if (currentMakeup.getEyeShadowBundle() != null && ("mu_style_eyeshadow_0" + 6).equals(currentMakeup.getEyeShadowBundle().getName()))
|
||||
currentMakeup.setEyeShadowTexBlend3(1);
|
||||
|
||||
if (FaceUnityConfig.IS_OPEN_LAND_MARK) {
|
||||
ExpressionRecognition expressionRecognition = new ExpressionRecognition(new FUBundleData(FaceUnityConfig.BUNDLE_LANDMARKS));
|
||||
expressionRecognition.setLandmarksType(FUAITypeEnum.FUAITYPE_FACELANDMARKS239);
|
||||
mFURenderKit.getPropContainer().addProp(expressionRecognition);
|
||||
}
|
||||
}
|
||||
public void clearAll(){
|
||||
currentMakeup = new Makeup(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_MAKEUP));
|
||||
mFURenderKit.setMakeup(currentMakeup);
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package com.yunbao.faceunity.data;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.prop.Prop;
|
||||
import com.faceunity.core.model.prop.arMask.ARMask;
|
||||
import com.faceunity.core.model.prop.bigHead.BigHead;
|
||||
import com.faceunity.core.model.prop.expression.ExpressionRecognition;
|
||||
import com.faceunity.core.model.prop.faceWarp.FaceWarp;
|
||||
import com.faceunity.core.model.prop.gesture.GestureRecognition;
|
||||
import com.faceunity.core.model.prop.sticker.Sticker;
|
||||
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||
import com.yunbao.faceunity.entity.PropBean;
|
||||
import com.yunbao.faceunity.infe.AbstractPropDataFactory;
|
||||
import com.yunbao.faceunity.repo.PropSource;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* DESC:道具业务工厂:道具贴图、AR面具、搞笑大头、表情识别、哈哈镜、手势识别
|
||||
* Created on 2021/3/2
|
||||
*/
|
||||
public class PropDataFactory extends AbstractPropDataFactory {
|
||||
|
||||
public interface PropListener {
|
||||
|
||||
void onItemSelected(PropBean bean);
|
||||
|
||||
}
|
||||
|
||||
/*渲染控制器*/
|
||||
private final FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||
/*道具列表*/
|
||||
private final ArrayList<PropBean> propBeans;
|
||||
|
||||
/*默认选中下标*/
|
||||
private int currentPropIndex;
|
||||
/*当前道具*/
|
||||
public Prop currentProp;
|
||||
/*回调接口*/
|
||||
private final PropListener mPropListener;
|
||||
/*道具类型*/
|
||||
private int propType;
|
||||
|
||||
|
||||
/**
|
||||
* @param listener 回调接口
|
||||
* @param type 道具类型
|
||||
* @param index 默认选中下标
|
||||
*/
|
||||
public PropDataFactory(PropListener listener, int type, int index) {
|
||||
mPropListener = listener;
|
||||
propType = type;
|
||||
currentPropIndex = index;
|
||||
propBeans = PropSource.buildPropBeans(type);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前选中下标
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int getCurrentPropIndex() {
|
||||
return currentPropIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前选中下标
|
||||
*
|
||||
* @param currentPropIndex
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentPropIndex(int currentPropIndex) {
|
||||
this.currentPropIndex = currentPropIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取道具队列
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@NonNull
|
||||
public ArrayList<PropBean> getPropBeans() {
|
||||
return propBeans;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置效果
|
||||
*/
|
||||
@Override
|
||||
public void onItemSelected(PropBean bean) {
|
||||
onPropSelected(bean);
|
||||
mPropListener.onItemSelected(bean);
|
||||
}
|
||||
|
||||
public void setPropType(int propType) {
|
||||
this.propType = propType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 其他道具
|
||||
*
|
||||
* @param bean
|
||||
*/
|
||||
private void onPropSelected(PropBean bean) {
|
||||
String path = bean.getPath();
|
||||
if (path == null || path.trim().length() == 0) {
|
||||
mFURenderKit.getPropContainer().removeAllProp();
|
||||
currentProp = null;
|
||||
return;
|
||||
}
|
||||
Prop prop = null;
|
||||
switch (propType) {
|
||||
case FunctionEnum.STICKER:
|
||||
prop = new Sticker(new FUBundleData(path));
|
||||
break;
|
||||
case FunctionEnum.AR_MASK:
|
||||
prop = new ARMask(new FUBundleData(path));
|
||||
break;
|
||||
case FunctionEnum.BIG_HEAD:
|
||||
prop = new BigHead(new FUBundleData(path));
|
||||
break;
|
||||
case FunctionEnum.EXPRESSION_RECOGNITION:
|
||||
prop = new ExpressionRecognition(new FUBundleData(path));
|
||||
break;
|
||||
case FunctionEnum.FACE_WARP:
|
||||
prop = new FaceWarp(new FUBundleData(path));
|
||||
break;
|
||||
case FunctionEnum.GESTURE_RECOGNITION:
|
||||
prop = new GestureRecognition(new FUBundleData(path));
|
||||
break;
|
||||
}
|
||||
mFURenderKit.getPropContainer().replaceProp(currentProp, prop);
|
||||
currentProp = prop;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* FURenderKit加载当前特效
|
||||
*/
|
||||
public void bindCurrentRenderer() {
|
||||
if (propType == FunctionEnum.GESTURE_RECOGNITION) {
|
||||
FUAIKit.getInstance().loadAIProcessor(FaceUnityConfig.BUNDLE_AI_HAND, FUAITypeEnum.FUAITYPE_HANDGESTURE);
|
||||
}
|
||||
if (propType == FunctionEnum.BIG_HEAD) {
|
||||
FUAIKit.getInstance().setMaxFaces(1);
|
||||
} else {
|
||||
FUAIKit.getInstance().setMaxFaces(4);
|
||||
}
|
||||
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
PropBean propBean = propBeans.get(currentPropIndex);
|
||||
onItemSelected(propBean);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束需要释放AI驱动
|
||||
*/
|
||||
public void releaseAIProcessor() {
|
||||
if (propType == FunctionEnum.GESTURE_RECOGNITION) {
|
||||
FUAIKit.getInstance().releaseAIProcessor(FUAITypeEnum.FUAITYPE_HANDGESTURE);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
public class AnimationFilterBean extends BaseBean {
|
||||
private int iconId;
|
||||
private int style=0;
|
||||
|
||||
public AnimationFilterBean(int iconId, int style) {
|
||||
this.iconId = iconId;
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
public int getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
public void setStyle(int style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
public int getIconId() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
public void setIconId(int iconId) {
|
||||
this.iconId = iconId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return style+"";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_ANIM;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
/**
|
||||
* 道具
|
||||
* @property iconId Int 图标
|
||||
* @property path String? Animoji 道具路径
|
||||
* @constructor
|
||||
*/
|
||||
public class AnimojiBean extends BaseBean{
|
||||
private int iconId;
|
||||
private String path;
|
||||
|
||||
public AnimojiBean(int iconId, String path) {
|
||||
this.iconId = iconId;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int getIconId() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
public void setIconId(int iconId) {
|
||||
this.iconId = iconId;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_ANIMOJI;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:
|
||||
* Created on 2020/12/4
|
||||
*
|
||||
*/
|
||||
data class AvatarBean(val iconId: Int, val des: String)
|
@ -0,0 +1,19 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
|
||||
abstract class BaseBean {
|
||||
abstract val key: String
|
||||
abstract val desRes: Int
|
||||
abstract val imageRes: Int
|
||||
abstract val beanType: Int
|
||||
|
||||
abstract fun getModelAttributeData(): ModelAttributeData
|
||||
|
||||
open fun getImageUrl():String {
|
||||
return "";
|
||||
}
|
||||
open fun getImageDrawable(): Drawable{
|
||||
return null!!
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:
|
||||
* Created on 2020/12/4
|
||||
*
|
||||
*/
|
||||
|
||||
data class BgSegGreenBackgroundBean(val desRes: Int, val iconRes: Int, val filePath: String? = null)
|
@ -0,0 +1,18 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:
|
||||
* Created on 2020/12/4
|
||||
*
|
||||
*/
|
||||
|
||||
data class BgSegGreenBean(val key: String, val desRes: Int, val closeRes: Int, val openRes: Int, val type: ButtonType) {
|
||||
enum class ButtonType{
|
||||
NORMAL1_BUTTON,//普通一号按钮
|
||||
NORMAL2_BUTTON,//普通二号按钮
|
||||
BACK_BUTTON,//返回按钮
|
||||
SWITCH_BUTTON//切换按钮,切换整个按钮功能
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:
|
||||
* Created on 2020/12/4
|
||||
*
|
||||
*/
|
||||
|
||||
data class BgSegGreenSafeAreaBean(val iconRes: Int, val type: ButtonType, val filePath: String? = null,val isAssetFile: Boolean = true) {
|
||||
|
||||
constructor(iconRes: Int, type: ButtonType) : this(
|
||||
iconRes,
|
||||
type,
|
||||
null,
|
||||
true
|
||||
)
|
||||
|
||||
constructor(iconRes: Int, type: ButtonType, filePath :String) : this(
|
||||
iconRes,
|
||||
type,
|
||||
filePath,
|
||||
true
|
||||
)
|
||||
enum class ButtonType{
|
||||
NORMAL1_BUTTON,//普通一号按钮,普通安全区域按钮
|
||||
NORMAL2_BUTTON,//普通二号按钮,用于自定义按钮
|
||||
BACK_BUTTON,//返回按钮
|
||||
NONE_BUTTON,//不选择按钮
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.repo.BodyBeautySource;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* DESC:美体
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public class BodyBeautyBean extends BaseBean {
|
||||
private String key;//名称标识
|
||||
private int desRes;//描述
|
||||
private int closeRes;//图片
|
||||
private int openRes;//图片
|
||||
|
||||
public BodyBeautyBean(String key, int desRes, int closeRes, int openRes) {
|
||||
this.key = key;
|
||||
this.desRes = desRes;
|
||||
this.closeRes = closeRes;
|
||||
this.openRes = openRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public int getDesRes() {
|
||||
return desRes;
|
||||
}
|
||||
|
||||
public void setDesRes(int desRes) {
|
||||
this.desRes = desRes;
|
||||
}
|
||||
|
||||
public int getCloseRes() {
|
||||
return closeRes;
|
||||
}
|
||||
|
||||
public void setCloseRes(int closeRes) {
|
||||
this.closeRes = closeRes;
|
||||
}
|
||||
|
||||
public int getOpenRes() {
|
||||
return openRes;
|
||||
}
|
||||
|
||||
public void setOpenRes(int openRes) {
|
||||
this.openRes = openRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return closeRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_BEAUTY_BODY;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return Objects.requireNonNull(BodyBeautySource.buildModelAttributeRange().get(key));
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam
|
||||
import com.yunbao.faceunity.repo.FaceBeautySource
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @property key String 名称标识
|
||||
* @property desRes Int 描述
|
||||
* @property closeRes Int 图片
|
||||
* @property openRes Int 图片
|
||||
* @property buttonType 按钮类型
|
||||
* @constructor
|
||||
*/
|
||||
data class FaceBeautyBean(
|
||||
override val key: String,
|
||||
override val desRes: Int,
|
||||
val closeRes: Int,
|
||||
val openRes: Int,
|
||||
val toastDesRes: Int,
|
||||
val canUseFunction: Boolean = true,
|
||||
val buttonType: ButtonType = ButtonType.NORMAL_BUTTON//定义一项按钮功能 普通按钮 返回按钮 子项按钮
|
||||
, override val beanType: Int
|
||||
, override val imageRes: Int
|
||||
) : BaseBean() {
|
||||
constructor(key: String, desRes: Int, closeRes: Int, openRes: Int) : this(
|
||||
key,
|
||||
desRes,
|
||||
closeRes,
|
||||
openRes,
|
||||
0,
|
||||
true,
|
||||
ButtonType.NORMAL_BUTTON,
|
||||
FaceParam.FACE_BEAUTY_SKIN,
|
||||
closeRes
|
||||
)
|
||||
|
||||
constructor(
|
||||
key: String,
|
||||
desRes: Int,
|
||||
closeRes: Int,
|
||||
openRes: Int,
|
||||
toastDesRes: Int,
|
||||
canUseFunction: Boolean
|
||||
) : this(
|
||||
key,
|
||||
desRes,
|
||||
closeRes,
|
||||
openRes,
|
||||
toastDesRes,
|
||||
canUseFunction,
|
||||
ButtonType.NORMAL_BUTTON,
|
||||
FaceParam.FACE_BEAUTY_SKIN,
|
||||
closeRes
|
||||
)
|
||||
constructor(
|
||||
key: String,
|
||||
desRes: Int,
|
||||
closeRes: Int,
|
||||
openRes: Int,
|
||||
toastDesRes: Int,
|
||||
canUseFunction: Boolean,
|
||||
type:Int
|
||||
):this(
|
||||
key,
|
||||
desRes,
|
||||
closeRes,
|
||||
openRes,
|
||||
toastDesRes,
|
||||
canUseFunction,
|
||||
ButtonType.NORMAL_BUTTON,
|
||||
type,
|
||||
closeRes
|
||||
)
|
||||
|
||||
enum class ButtonType {
|
||||
NORMAL_BUTTON,
|
||||
BACK_BUTTON,
|
||||
SUB_ITEM_BUTTON
|
||||
}
|
||||
|
||||
override fun getModelAttributeData(): ModelAttributeData {
|
||||
return FaceBeautySource.buildModelAttributeRange()?.get(key)!!
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
/**
|
||||
* DESC:美颜滤镜
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public class FaceBeautyFilterBean extends BaseBean {
|
||||
|
||||
private String key;//名称标识
|
||||
private int imageRes;//图片
|
||||
private int desRes;//描述
|
||||
private double intensity = 0.4;//强度
|
||||
|
||||
public FaceBeautyFilterBean(String key, int imageRes, int desRes) {
|
||||
this.key = key;
|
||||
this.imageRes = imageRes;
|
||||
this.desRes = desRes;
|
||||
}
|
||||
|
||||
public FaceBeautyFilterBean(String key, int imageRes, int desRes, double intensity) {
|
||||
this.key = key;
|
||||
this.imageRes = imageRes;
|
||||
this.desRes = desRes;
|
||||
this.intensity = intensity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return imageRes;
|
||||
}
|
||||
|
||||
public void setImageRes(int imageRes) {
|
||||
this.imageRes = imageRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return desRes;
|
||||
}
|
||||
|
||||
public void setDesRes(int desRes) {
|
||||
this.desRes = desRes;
|
||||
}
|
||||
|
||||
public double getIntensity() {
|
||||
return intensity;
|
||||
}
|
||||
|
||||
public void setIntensity(double intensity) {
|
||||
this.intensity = intensity;
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
|
||||
return FaceParam.FACE_BEAUTY_FILTER;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
/**
|
||||
* 滤镜
|
||||
* @property key String 名称标识
|
||||
* @property imageRes Int 图片
|
||||
* @property desRes Int 描述
|
||||
* @constructor
|
||||
*/
|
||||
data class FaceBeautyStyleBean(
|
||||
override val key: String,
|
||||
override val imageRes: Int,
|
||||
override val desRes: Int,
|
||||
override val beanType:Int,
|
||||
):
|
||||
BaseBean(){
|
||||
override fun getModelAttributeData(): ModelAttributeData {
|
||||
return null!!
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
public class FunctionEnum {
|
||||
public final static int FACE_BEAUTY = 1;
|
||||
public final static int MAKE_UP = 2;
|
||||
public final static int STICKER = 3;
|
||||
public final static int ANIMOJI = 4;
|
||||
public final static int HAIR_BEAUTY = 5;
|
||||
public final static int LIGHT_MAKEUP = 6;
|
||||
public final static int AR_MASK = 7;
|
||||
public final static int BIG_HEAD = 8;
|
||||
public final static int POSTER_CHANGE = 9;
|
||||
public final static int EXPRESSION_RECOGNITION = 10;
|
||||
public final static int MUSIC_FILTER = 11;
|
||||
public final static int FACE_WARP = 12;
|
||||
public final static int BODY_BEAUTY = 13;
|
||||
public final static int AVATAR = 14;
|
||||
public final static int ACTION_RECOGNITION = 15;
|
||||
public final static int PORTRAIT_SEGMENT = 16;
|
||||
public final static int GESTURE_RECOGNITION = 17;
|
||||
public final static int BG_SEG_GREEN = 18;
|
||||
public final static int HUMAN_OUTLINE = 19;
|
||||
public final static int BG_SEG_CUSTOM = 20;
|
||||
public final static int FINE_STICKER = 21;
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
public class LightMakeupBean {
|
||||
int nameRes;
|
||||
int iconRes;
|
||||
String key;
|
||||
double intensity;
|
||||
String filterName;
|
||||
double filterIntensity;
|
||||
|
||||
public LightMakeupBean(int nameRes, int iconRes, String key, double intensity, String filterName, double filterIntensity) {
|
||||
this.nameRes = nameRes;
|
||||
this.iconRes = iconRes;
|
||||
this.key = key;
|
||||
this.intensity = intensity;
|
||||
this.filterName = filterName;
|
||||
this.filterIntensity = filterIntensity;
|
||||
}
|
||||
|
||||
public int getNameRes() {
|
||||
return nameRes;
|
||||
}
|
||||
|
||||
public void setNameRes(int nameRes) {
|
||||
this.nameRes = nameRes;
|
||||
}
|
||||
|
||||
public int getIconRes() {
|
||||
return iconRes;
|
||||
}
|
||||
|
||||
public void setIconRes(int iconRes) {
|
||||
this.iconRes = iconRes;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public double getIntensity() {
|
||||
return intensity;
|
||||
}
|
||||
|
||||
public void setIntensity(double intensity) {
|
||||
this.intensity = intensity;
|
||||
}
|
||||
|
||||
public String getFilterName() {
|
||||
return filterName;
|
||||
}
|
||||
|
||||
public void setFilterName(String filterName) {
|
||||
this.filterName = filterName;
|
||||
}
|
||||
|
||||
public double getFilterIntensity() {
|
||||
return filterIntensity;
|
||||
}
|
||||
|
||||
public void setFilterIntensity(double filterIntensity) {
|
||||
this.filterIntensity = filterIntensity;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @property key String 名称标识
|
||||
* @property type TypeEnum 类型
|
||||
* @property imageRes Int 图片
|
||||
* @property desRes Int 描述
|
||||
* @property bundlePath FUBundleData 资源句柄
|
||||
* @property jsonPath String 参数配置路径
|
||||
* @property filterName Double 滤镜
|
||||
* @property filterIntensity Double 滤镜强度
|
||||
* @property filterScale Double scale 标准滤镜比率
|
||||
* @property intensity Double 强度
|
||||
* @property jsonPathParams Double 参数配置缓存
|
||||
* @constructor
|
||||
*/
|
||||
data class MakeupCombinationBean @JvmOverloads constructor(
|
||||
override val key: String,
|
||||
val type: TypeEnum,
|
||||
override val imageRes: Int,
|
||||
override val desRes: Int,
|
||||
val bundlePath: String?,
|
||||
val jsonPath: String,
|
||||
val filterName: String,
|
||||
var filterScale: Double = 1.0,
|
||||
var filterIntensity: Double = 0.7,
|
||||
var intensity: Double = 0.7,
|
||||
var jsonPathParams: LinkedHashMap<String, Any>? = null,
|
||||
override val beanType: Int
|
||||
): BaseBean() {
|
||||
enum class TypeEnum {
|
||||
TYPE_NONE, //无
|
||||
TYPE_DAILY,//日常妆,支持自定义
|
||||
TYPE_THEME_SUB,//主题妆_依附于face_makeup
|
||||
TYPE_THEME_MAIN,//主题妆_替换face_makeup
|
||||
}
|
||||
|
||||
override fun getModelAttributeData(): ModelAttributeData {
|
||||
return null!!
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
/**
|
||||
*
|
||||
* @property nameRes Int 名称
|
||||
* @property drawable Drawable 图片资源
|
||||
* @property doubleArray ArrayList<DoubleArray>? 颜色数组
|
||||
* @constructor
|
||||
*/
|
||||
public class MakeupCustomBean extends BaseBean{
|
||||
private int nameRes;
|
||||
private Drawable drawable;
|
||||
private ArrayList<double[]> doubleArray;
|
||||
private int beanType;
|
||||
|
||||
public MakeupCustomBean(int nameRes, Drawable drawable, ArrayList<double[]> doubleArray,int beanType) {
|
||||
this.nameRes = nameRes;
|
||||
this.drawable = drawable;
|
||||
this.doubleArray = doubleArray;
|
||||
this.beanType=beanType;
|
||||
}
|
||||
|
||||
|
||||
public MakeupCustomBean(int nameRes, Drawable drawable,int beanType) {
|
||||
this.nameRes = nameRes;
|
||||
this.drawable = drawable;
|
||||
this.beanType=beanType;
|
||||
}
|
||||
|
||||
public int getNameRes() {
|
||||
return nameRes;
|
||||
}
|
||||
|
||||
public void setNameRes(int nameRes) {
|
||||
this.nameRes = nameRes;
|
||||
}
|
||||
|
||||
public Drawable getDrawable() {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
public void setDrawable(Drawable drawable) {
|
||||
this.drawable = drawable;
|
||||
}
|
||||
|
||||
public ArrayList<double[]> getDoubleArray() {
|
||||
return doubleArray;
|
||||
}
|
||||
|
||||
public void setDoubleArray(ArrayList<double[]> doubleArray) {
|
||||
this.doubleArray = doubleArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return nameRes+"";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return nameRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Drawable getImageDrawable() {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return beanType;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
public class MakeupCustomClassBean extends BaseBean{
|
||||
private int nameRes;
|
||||
private String key;
|
||||
private int beanType;
|
||||
|
||||
public MakeupCustomClassBean(int nameRes, String key, int beanType) {
|
||||
this.nameRes = nameRes;
|
||||
this.key = key;
|
||||
this.beanType = beanType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return nameRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return beanType;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
data class MenuGroupBean(val titleId :Int,val iconId:Int)
|
@ -0,0 +1,12 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
|
||||
/**
|
||||
* 模型单项补充模型
|
||||
* @property default Double 默认值
|
||||
* @property stand Double 无变化时候的基准值
|
||||
* @property minRange Double 范围最小值
|
||||
* @property maxRange Double 范围最大值
|
||||
* @constructor
|
||||
*/
|
||||
data class ModelAttributeData(val default: Double=0.0, val stand: Double = 0.0, val minRange: Double = 0.0, val maxRange: Double = 1.0)
|
@ -0,0 +1,85 @@
|
||||
package com.yunbao.faceunity.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
|
||||
/**
|
||||
* 道具
|
||||
* @property iconId Int 图标
|
||||
* @property path String 道具路径
|
||||
* @property descId Int 道具提示
|
||||
* @constructor
|
||||
*/
|
||||
public class PropBean extends BaseBean {
|
||||
private int iconId;
|
||||
private String path;
|
||||
private int descId;
|
||||
private int beanType;
|
||||
|
||||
public PropBean(int iconId, String path,int beanType) {
|
||||
this.iconId = iconId;
|
||||
this.path = path;
|
||||
this.beanType=beanType;
|
||||
}
|
||||
|
||||
public PropBean(int iconId, String path, int descId,int beanType) {
|
||||
this.iconId = iconId;
|
||||
this.path = path;
|
||||
this.descId = descId;
|
||||
this.beanType=beanType;
|
||||
}
|
||||
|
||||
public int getIconId() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
public void setIconId(int iconId) {
|
||||
this.iconId = iconId;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int getDescId() {
|
||||
return descId;
|
||||
}
|
||||
|
||||
public void setDescId(int descId) {
|
||||
this.descId = descId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return descId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return beanType;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.yunbao.faceunity.entity
|
||||
|
||||
/**
|
||||
* 道具
|
||||
* @property iconId Int 图标
|
||||
* @property path String 道具路径
|
||||
* @property descId Int 道具提示
|
||||
* @property descId Int 类型 -2 为添加事件 -1为空 其他多道具类型
|
||||
* @property iconPath 图标路径
|
||||
* @constructor
|
||||
*/
|
||||
data class PropCustomBean @JvmOverloads constructor(
|
||||
val iconId: Int,
|
||||
val path: String?,
|
||||
val type: Int = -1,
|
||||
val descId: Int = 0,
|
||||
val iconPath: String? = null
|
||||
)
|
@ -0,0 +1,328 @@
|
||||
package com.yunbao.faceunity.entity.net;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Qinyu on 2021-03-17
|
||||
* @description
|
||||
*/
|
||||
public class FineStickerEntity {
|
||||
/**
|
||||
* count : 2
|
||||
* docs : [{"_id":"6051a0aa6d670000230030c7","index":1,"tool":{"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}},"platform":"mobile","tag":"中级道具"},{"_id":"6051a2d36d670000230030c8","index":2,"tool":{"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}},"platform":"mobile","tag":"中级道具"}]
|
||||
*/
|
||||
|
||||
private int count;
|
||||
private ArrayList<DocsBean> docs;
|
||||
private boolean isOnline; //手动设置
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public ArrayList<DocsBean> getDocs() {
|
||||
return docs;
|
||||
}
|
||||
|
||||
public void setDocs(ArrayList<DocsBean> docs) {
|
||||
this.docs = docs;
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
public void setOnline(boolean online) {
|
||||
isOnline = online;
|
||||
}
|
||||
|
||||
public static class DocsBean extends BaseBean {
|
||||
/**
|
||||
* _id : 6051a0aa6d670000230030c7
|
||||
* index : 1
|
||||
* tool : {"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}}
|
||||
* platform : mobile
|
||||
* tag : 中级道具
|
||||
*/
|
||||
|
||||
private String _id;
|
||||
private int index;
|
||||
private ToolBean tool;
|
||||
private String platform;
|
||||
private String tag;
|
||||
|
||||
private String filePath; //原始下载来的文件的存储地址,手动设置
|
||||
private ArrayList<String> upZipFilePath;//解压的文件位置(绝对路径),手动设置
|
||||
private boolean isDownloading; //手动设置
|
||||
|
||||
// public Effect cast2Effect() {
|
||||
// return new Effect(tool.bundle.name, 0, filePath, 1, Effect.EFFECT_TYPE_STICKER, 0);
|
||||
// }
|
||||
|
||||
public String get_id() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
public void set_id(String _id) {
|
||||
this._id = _id;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public ToolBean getTool() {
|
||||
return tool;
|
||||
}
|
||||
|
||||
public void setTool(ToolBean tool) {
|
||||
this.tool = tool;
|
||||
}
|
||||
|
||||
public String getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
public void setPlatform(String platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public ArrayList<String> getUnZipFilePaths() {
|
||||
return upZipFilePath;
|
||||
}
|
||||
|
||||
public void setUpZipFilePaths(ArrayList paths) {
|
||||
upZipFilePath = paths;
|
||||
}
|
||||
|
||||
public boolean isDownloading() {
|
||||
return isDownloading;
|
||||
}
|
||||
|
||||
public void setDownloading(boolean downloading) {
|
||||
isDownloading = downloading;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageUrl() {
|
||||
if(tool==null||tool.getIcon()==null){
|
||||
return "";
|
||||
}
|
||||
return tool.getIcon().getUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeanType() {
|
||||
return FaceParam.FACE_FINE_STICKER;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelAttributeData getModelAttributeData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class ToolBean {
|
||||
/**
|
||||
* _id : 5f6ae24e570100009e006547
|
||||
* bundle : {"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"}
|
||||
* icon : {"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}
|
||||
*/
|
||||
|
||||
private String _id;
|
||||
private BundleBean bundle;
|
||||
private IconBean icon;
|
||||
private String adapter;
|
||||
private String category;
|
||||
|
||||
public String get_id() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
public void set_id(String _id) {
|
||||
this._id = _id;
|
||||
}
|
||||
|
||||
public BundleBean getBundle() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public void setBundle(BundleBean bundle) {
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
public IconBean getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(IconBean icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public String getAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
public void setAdapter(String adapter) {
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public static class BundleBean {
|
||||
/**
|
||||
* remark : 优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持
|
||||
* uid : 0a176380-b33e-11e9-8e6a-35012f229fc1.bundle
|
||||
* size : 3872.85
|
||||
* name : hez_ztt_fu.bundle
|
||||
*/
|
||||
|
||||
private String remark;
|
||||
private String uid;
|
||||
private double size;
|
||||
private String name;
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public double getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(double size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class IconBean {
|
||||
/**
|
||||
* remark : v1.0
|
||||
* uid : 167f72e0-e173-11e8-b908-51298abcbcf5.png
|
||||
* size : 61.83
|
||||
* name : hez_ztt_fu.png
|
||||
* url : http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D
|
||||
*/
|
||||
|
||||
private String remark;
|
||||
private String uid;
|
||||
private double size;
|
||||
private String name;
|
||||
private String url;
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public double getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(double size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.yunbao.faceunity.entity.net;
|
||||
|
||||
/**
|
||||
* Created on 2021/3/31 0031 16:12.
|
||||
* Author: xloger
|
||||
* Email:phoenix@xloger.com
|
||||
*/
|
||||
public class FineStickerTagEntity {
|
||||
private String tag;
|
||||
|
||||
public FineStickerTagEntity(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FineStickerTagEntity{" +
|
||||
"tag='" + tag + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
import com.yunbao.faceunity.entity.AnimationFilterBean
|
||||
import com.yunbao.faceunity.entity.AnimojiBean
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:
|
||||
* Created on 2020/12/24
|
||||
*
|
||||
*/
|
||||
abstract class AbstractAnimojiDataFactory {
|
||||
|
||||
/* 当前选中动漫贴图下标 */
|
||||
abstract var currentAnimojiIndex: Int
|
||||
|
||||
/* 动漫贴图队列 */
|
||||
abstract val animojis: ArrayList<AnimojiBean>
|
||||
|
||||
/* 当前选中滤镜下标 */
|
||||
abstract var currentFilterIndex: Int
|
||||
|
||||
/* 滤镜队列 */
|
||||
abstract val filters: ArrayList<AnimationFilterBean>
|
||||
|
||||
abstract fun onAnimojiSelected(data: AnimojiBean)
|
||||
|
||||
abstract fun onFilterSelected(data: AnimationFilterBean)
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
import com.yunbao.faceunity.entity.AvatarBean
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:
|
||||
* Created on 2021/1/6
|
||||
*
|
||||
*/
|
||||
abstract class AbstractAvatarDataFactory {
|
||||
|
||||
/**
|
||||
* 人物队列
|
||||
*/
|
||||
abstract val members: ArrayList<AvatarBean>
|
||||
|
||||
/**
|
||||
* 默认选中人物下标
|
||||
*/
|
||||
abstract var currentMemberIndex: Int
|
||||
|
||||
/**
|
||||
* true 全身、 false 半身 驱动切换
|
||||
*/
|
||||
abstract var isHumanTrackSceneFull: Boolean
|
||||
|
||||
/**
|
||||
* 当前人物选中
|
||||
* @param bean AvatarBean
|
||||
*/
|
||||
abstract fun onMemberSelected(bean:AvatarBean)
|
||||
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
|
||||
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean
|
||||
import com.yunbao.faceunity.entity.BgSegGreenBean
|
||||
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:
|
||||
* Created on 2020/12/29
|
||||
*
|
||||
*/
|
||||
abstract class AbstractBgSegGreenDataFactory {
|
||||
|
||||
/* 绿幕抠像项目数据扩展模型 */
|
||||
abstract val modelAttributeRange: HashMap<String, ModelAttributeData>
|
||||
|
||||
/* 绿幕抠像功能列表 */
|
||||
abstract val bgSegGreenActions: ArrayList<BgSegGreenBean>
|
||||
|
||||
/* 绿幕抠图安全区域功能列表*/
|
||||
abstract val bgSegGreenSafeAreas: ArrayList<BgSegGreenSafeAreaBean>
|
||||
|
||||
/* 安全区域下标 */
|
||||
abstract var bgSafeAreaIndex: Int
|
||||
|
||||
/* 刷新安全区域UI */
|
||||
abstract fun updateSafeAreaBeansAndIndex() :Boolean
|
||||
|
||||
/* 绿幕抠像背景列表 */
|
||||
abstract val bgSegGreenBackgrounds: ArrayList<BgSegGreenBackgroundBean>
|
||||
|
||||
/* 绿幕抠像当前背景下标 */
|
||||
abstract var backgroundIndex: Int
|
||||
|
||||
|
||||
/**
|
||||
* 背景图片变更
|
||||
* @param data BgSegGreenBackgroundBean
|
||||
*/
|
||||
abstract fun onBackgroundSelected(data: BgSegGreenBackgroundBean)
|
||||
|
||||
/**
|
||||
* 自定义安全区域
|
||||
*/
|
||||
abstract fun onSafeAreaAdd()
|
||||
|
||||
/**
|
||||
* 安全区域变更
|
||||
* @param data BgSegGreenSafeAreaBean
|
||||
*/
|
||||
abstract fun onSafeAreaSelected(data: BgSegGreenSafeAreaBean?)
|
||||
|
||||
/**
|
||||
* 是否开启安全区域总开关
|
||||
*/
|
||||
abstract fun isUseTemplate():Boolean
|
||||
|
||||
/**
|
||||
* 取色锚点颜色变更
|
||||
* @param array DoubleArray
|
||||
*/
|
||||
abstract fun onColorRGBChanged(array: DoubleArray)
|
||||
|
||||
/**
|
||||
* 绿幕开关
|
||||
* @param enable Boolean
|
||||
*/
|
||||
abstract fun onBgSegGreenEnableChanged(enable: Boolean)
|
||||
|
||||
|
||||
/**
|
||||
* 根据名称标识获取对应的值
|
||||
* @param key String 标识
|
||||
* @return Double 值
|
||||
*/
|
||||
abstract fun getParamIntensity(key: String): Double
|
||||
|
||||
/**
|
||||
* 根据名称标识更新对应的值
|
||||
* @param key String 标识
|
||||
* @return Double 值
|
||||
*/
|
||||
abstract fun updateParamIntensity(key: String, value: Double)
|
||||
|
||||
/**
|
||||
* 是否调用取色器功能
|
||||
*
|
||||
* @param selected
|
||||
* @param color
|
||||
*/
|
||||
abstract fun onColorPickerStateChanged(selected: Boolean, color: Int)
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.yunbao.faceunity.infe;
|
||||
|
||||
|
||||
import com.yunbao.faceunity.entity.BodyBeautyBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* DESC:数据构造工厂抽象类
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public abstract class AbstractBodyBeautyDataFactory {
|
||||
|
||||
|
||||
/**
|
||||
* 获取美体参数集合
|
||||
* @return
|
||||
*/
|
||||
public abstract ArrayList<BodyBeautyBean> getBodyBeautyParam();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取美体项目数据扩展模型
|
||||
* @return
|
||||
*/
|
||||
public abstract HashMap<String, ModelAttributeData> getModelAttributeRange();
|
||||
|
||||
|
||||
/**
|
||||
* 根据名称标识获取对应的值
|
||||
*
|
||||
* @param key String 标识
|
||||
* @return Double 值
|
||||
*/
|
||||
public abstract double getParamIntensity(String key);
|
||||
|
||||
/**
|
||||
* 根据名称标识更新对应的值
|
||||
*
|
||||
* @param key String 标识
|
||||
* @return Double 值
|
||||
*/
|
||||
public abstract void updateParamIntensity(String key, double value);
|
||||
|
||||
/**
|
||||
* 美体开关
|
||||
*
|
||||
* @param enable Boolean
|
||||
*/
|
||||
public abstract void enableBodyBeauty(boolean enable);
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
|
||||
import com.yunbao.faceunity.entity.FaceBeautyBean
|
||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean
|
||||
import com.yunbao.faceunity.entity.FaceBeautyStyleBean
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:数据构造工厂接口类
|
||||
* Created on 2020/12/23
|
||||
*
|
||||
*/
|
||||
abstract class AbstractFaceBeautyDataFactory {
|
||||
|
||||
/*美肤底部菜单数据*/
|
||||
abstract val skinBeauty: ArrayList<FaceBeautyBean>
|
||||
|
||||
/*美型底部菜单数据*/
|
||||
abstract val shapeBeauty: ArrayList<FaceBeautyBean>
|
||||
|
||||
/*美型脸型子项数据*/
|
||||
abstract val shapeBeautySubItem: ArrayList<FaceBeautyBean>
|
||||
|
||||
/* 滤镜底部菜单数据*/
|
||||
abstract val beautyFilters: ArrayList<FaceBeautyFilterBean>
|
||||
|
||||
/* 风格底部菜单数据*/
|
||||
abstract val beautyStyles: ArrayList<FaceBeautyStyleBean>
|
||||
|
||||
/*系统推荐配置滤镜对应下标*/
|
||||
abstract var currentFilterIndex: Int
|
||||
|
||||
/* 美颜项目数据扩展模型 */
|
||||
abstract val modelAttributeRange: HashMap<String, ModelAttributeData>
|
||||
|
||||
/*系统风格对应下标*/
|
||||
abstract var currentStyleIndex: Int
|
||||
|
||||
/**
|
||||
* 切换滤镜
|
||||
* @param name String
|
||||
* @param intensity Double
|
||||
*/
|
||||
abstract fun onFilterSelected(name: String, intensity: Double, resDes: Int)
|
||||
|
||||
/**
|
||||
* 切换风格
|
||||
* @param name String
|
||||
*/
|
||||
abstract fun onStyleSelected(name: String?)
|
||||
|
||||
/**
|
||||
* 更改滤镜强度
|
||||
* @param intensity Double
|
||||
*/
|
||||
abstract fun updateFilterIntensity(intensity: Double)
|
||||
|
||||
/**
|
||||
* 美颜开关
|
||||
* @param enable Boolean
|
||||
*/
|
||||
abstract fun enableFaceBeauty(enable: Boolean)
|
||||
|
||||
/**
|
||||
* 获取单项强度
|
||||
* @param key String
|
||||
* @return Double
|
||||
*/
|
||||
abstract fun getParamIntensity(key: String): Double
|
||||
|
||||
/**
|
||||
* 获取one hot的脸型
|
||||
*/
|
||||
abstract fun getCurrentOneHotFaceShape(): String
|
||||
|
||||
/**
|
||||
* 设置当前one hot的脸型
|
||||
*/
|
||||
abstract fun setCurrentOneHotFaceShape(faceShape:String)
|
||||
|
||||
/**
|
||||
* 设置当前脸型的UI值
|
||||
*/
|
||||
abstract fun setCurrentFaceShapeUIValue(hashMap:HashMap<String,Double>)
|
||||
|
||||
/**
|
||||
* 获取当前脸型的UI值
|
||||
*/
|
||||
abstract fun getCurrentFaceShapeUIValue() :HashMap<String,Double>
|
||||
|
||||
/**
|
||||
* 设置单项强度
|
||||
* @param key String
|
||||
* @param value Double
|
||||
*/
|
||||
abstract fun updateParamIntensity(key: String, value: Double)
|
||||
|
||||
/**
|
||||
* 将所有效果置空 -> 变成标准值
|
||||
*/
|
||||
abstract fun resetParamIntensity()
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity
|
||||
import com.yunbao.faceunity.entity.net.FineStickerTagEntity
|
||||
|
||||
/**
|
||||
* Created on 2021/3/31 0031 15:27.
|
||||
* Author: xloger
|
||||
* Email:phoenix@xloger.com
|
||||
*/
|
||||
abstract class AbstractFineStickerDataFactory {
|
||||
/*切换道具*/
|
||||
abstract fun onItemSelected(bean: FineStickerEntity.DocsBean?)
|
||||
/*获取标签列表*/
|
||||
abstract fun loadTagList(): List<FineStickerTagEntity>
|
||||
/*获取道具列表*/
|
||||
abstract fun loadStickerList(tag: FineStickerTagEntity): FineStickerEntity?
|
||||
/*下载道具*/
|
||||
abstract fun downloadSticker(docsBean: FineStickerEntity.DocsBean)
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.yunbao.faceunity.infe;
|
||||
|
||||
import com.yunbao.faceunity.entity.LightMakeupBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class AbstractLightMakeupDataFactory {
|
||||
private int currentLightMakeupIndex;
|
||||
private ArrayList<LightMakeupBean> lightMakeUpBeans;
|
||||
public abstract void onLightMakeupSelected(LightMakeupBean data);
|
||||
public abstract void onLightMakeupIntensityChanged(double intensity);
|
||||
|
||||
public int getCurrentLightMakeupIndex() {
|
||||
return currentLightMakeupIndex;
|
||||
}
|
||||
|
||||
public void setCurrentLightMakeupIndex(int currentLightMakeupIndex) {
|
||||
this.currentLightMakeupIndex = currentLightMakeupIndex;
|
||||
}
|
||||
|
||||
public ArrayList<LightMakeupBean> getLightMakeUpBeans() {
|
||||
return lightMakeUpBeans;
|
||||
}
|
||||
|
||||
public void setLightMakeUpBeans(ArrayList<LightMakeupBean> lightMakeUpBeans) {
|
||||
this.lightMakeUpBeans = lightMakeUpBeans;
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
|
||||
import com.yunbao.faceunity.entity.MakeupCombinationBean
|
||||
import com.yunbao.faceunity.entity.MakeupCustomBean
|
||||
import com.yunbao.faceunity.entity.MakeupCustomClassBean
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:
|
||||
* Created on 2020/12/22
|
||||
*
|
||||
*/
|
||||
abstract class AbstractMakeupDataFactory {
|
||||
|
||||
/* 默认组合妆容下标 */
|
||||
abstract var currentCombinationIndex: Int
|
||||
|
||||
/* 美妆组合妆容配置 */
|
||||
abstract val makeupCombinations: ArrayList<MakeupCombinationBean>
|
||||
|
||||
/**
|
||||
* 组合妆容选中
|
||||
* @param bean MakeupCombinationBean
|
||||
*/
|
||||
abstract fun onMakeupCombinationSelected(bean: MakeupCombinationBean)
|
||||
|
||||
/**
|
||||
* 设置美妆整体强度
|
||||
* @param intensity Double
|
||||
*/
|
||||
abstract fun updateCombinationIntensity(intensity: Double)
|
||||
|
||||
/**
|
||||
* 进入自定义美妆
|
||||
*/
|
||||
abstract fun enterCustomMakeup()
|
||||
|
||||
/**
|
||||
* 设置美妆单项强度
|
||||
* @param key String 单项key
|
||||
* @param current Int 单项下标
|
||||
* @param intensity Double
|
||||
*/
|
||||
abstract fun updateCustomItemIntensity(key: String, current: Int, intensity: Double)
|
||||
|
||||
/**
|
||||
* 更换类别单项
|
||||
* @param key String
|
||||
* @param index Int
|
||||
*/
|
||||
abstract fun onCustomBeanSelected(key: String, index: Int)
|
||||
|
||||
/**
|
||||
* 设置单项颜色
|
||||
* @param key String
|
||||
* @param index Int
|
||||
*/
|
||||
abstract fun updateCustomColor(key: String, index: Int)
|
||||
|
||||
|
||||
/* 美妆功能菜单 */
|
||||
abstract val makeupCustomItemParams: LinkedHashMap<String, ArrayList<MakeupCustomBean>>
|
||||
|
||||
/* 美妆子项类别 */
|
||||
|
||||
abstract val makeupCustomClass: ArrayList<MakeupCustomClassBean>
|
||||
|
||||
|
||||
/**
|
||||
* 获取美妆单项当前下标
|
||||
* @param key String
|
||||
* @return Int
|
||||
*/
|
||||
abstract fun getCurrentCustomItemIndex(key: String): Int
|
||||
|
||||
/**
|
||||
* 获取美妆当前选中项颜色下标
|
||||
* @param key String
|
||||
* @param current Int
|
||||
* @return Int
|
||||
*/
|
||||
abstract fun getCurrentCustomColorIndex(key: String, current: Int): Int
|
||||
|
||||
/**
|
||||
* 获取美妆当前选中项强度
|
||||
* @param key String
|
||||
* @param current Int
|
||||
* @return Double
|
||||
*/
|
||||
abstract fun getCurrentCustomIntensity(key: String, current: Int): Double
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
import com.yunbao.faceunity.entity.PropCustomBean
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:贴图道具
|
||||
* Created on 2020/12/23
|
||||
*
|
||||
*/
|
||||
abstract class AbstractPropCustomDataFactory {
|
||||
|
||||
/**
|
||||
* 默认选中道具下标
|
||||
*/
|
||||
abstract var currentPropIndex: Int
|
||||
|
||||
|
||||
/**
|
||||
* 道具队列
|
||||
*/
|
||||
abstract val propCustomBeans: ArrayList<PropCustomBean>
|
||||
|
||||
|
||||
/**
|
||||
* 道具选中
|
||||
* @param bean StickerBean
|
||||
*/
|
||||
abstract fun onItemSelected(bean: PropCustomBean)
|
||||
|
||||
|
||||
/**
|
||||
* 道具选中
|
||||
*/
|
||||
abstract fun onAddPropCustomBeanClick()
|
||||
|
||||
|
||||
companion object {
|
||||
const val TYPE_NONE = -1
|
||||
const val TYPE_ADD = -99
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.yunbao.faceunity.infe
|
||||
|
||||
import com.yunbao.faceunity.entity.PropBean
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* DESC:贴图道具
|
||||
* Created on 2020/12/23
|
||||
*
|
||||
*/
|
||||
abstract class AbstractPropDataFactory {
|
||||
|
||||
/**
|
||||
* 默认选中道具下标
|
||||
*/
|
||||
abstract var currentPropIndex: Int
|
||||
|
||||
|
||||
/**
|
||||
* 道具队列
|
||||
*/
|
||||
abstract val propBeans: ArrayList<PropBean>
|
||||
|
||||
|
||||
/**
|
||||
* 道具选中
|
||||
* @param bean StickerBean
|
||||
*/
|
||||
abstract fun onItemSelected(bean: PropBean)
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.yunbao.faceunity.listener;
|
||||
|
||||
import com.faceunity.core.enumeration.FUAIProcessorEnum;
|
||||
|
||||
/**
|
||||
* DESC:FURenderer状态回调监听
|
||||
* Created on 2021/4/29
|
||||
*/
|
||||
public interface FURendererListener {
|
||||
|
||||
/**
|
||||
* prepare完成回调
|
||||
*/
|
||||
void onPrepare();
|
||||
|
||||
/**
|
||||
* 识别到的人脸或人体数量发生变化
|
||||
*
|
||||
* @param type 类型
|
||||
* @param status 数量
|
||||
*/
|
||||
void onTrackStatusChanged(FUAIProcessorEnum type, int status);
|
||||
|
||||
|
||||
/**
|
||||
* 统计每 10 帧的平均数据,FPS 和渲染函数调用时间
|
||||
*
|
||||
* @param fps FPS
|
||||
* @param callTime 渲染函数调用时间
|
||||
*/
|
||||
void onFpsChanged(double fps, double callTime);
|
||||
|
||||
|
||||
/**
|
||||
* release完成回调
|
||||
*/
|
||||
void onRelease();
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.yunbao.faceunity.listener;
|
||||
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FUAIKit;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
|
||||
/**
|
||||
* 模块配置
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class IFaceModel<T> {
|
||||
public abstract T Builder();
|
||||
|
||||
public void apply() {
|
||||
FUAIKit.getInstance().loadAIProcessor(FaceUnityConfig.BUNDLE_AI_FACE, FUAITypeEnum.FUAITYPE_FACEPROCESSOR);
|
||||
FUAIKit.getInstance().faceProcessorSetFaceLandmarkQuality(FaceUnityConfig.DEVICE_LEVEL);
|
||||
}
|
||||
public abstract void setEnable(boolean enable);
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
import com.faceunity.core.model.animationFilter.AnimationFilterTypeEnum;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.AnimationFilterBean;
|
||||
import com.yunbao.faceunity.entity.AnimojiBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* DESC:Animoji数据构造
|
||||
* Created on 2021/3/25
|
||||
*/
|
||||
public class AnimojiSource {
|
||||
|
||||
|
||||
/**
|
||||
* 构造贴图数据
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<AnimojiBean> buildAnimojis() {
|
||||
ArrayList<AnimojiBean> array = new ArrayList<>();
|
||||
array.add(new AnimojiBean(R.mipmap.icon_control_delete_all, null));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_cartoon_princess, "animoji/cartoon_princess_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_qgirl, "animoji/qgirl_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_kaola, "animoji/kaola_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_wuxia, "animoji/wuxia_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_baihu, "animoji/baihu_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_frog_st, "animoji/frog_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_huangya, "animoji/huangya_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_hetun, "animoji/hetun_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_douniuquan, "animoji/douniuquan_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_hashiqi, "animoji/hashiqi_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_baimao, "animoji/baimao_Animoji.bundle"));
|
||||
array.add(new AnimojiBean(R.mipmap.icon_animoji_kuloutou, "animoji/kuloutou_Animoji.bundle"));
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造滤镜数据
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<AnimationFilterBean> buildFilters() {
|
||||
ArrayList<AnimationFilterBean> filters = new ArrayList<>();
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_control_delete_all, AnimationFilterTypeEnum.Origin));
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_anime, AnimationFilterTypeEnum.Comic));
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_portrait_dynamiceffect, AnimationFilterTypeEnum.Portrait));
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_sketch, AnimationFilterTypeEnum.Sketch));
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_oilpainting, AnimationFilterTypeEnum.Oil));
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_sandlpainting, AnimationFilterTypeEnum.Sand));
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_penpainting, AnimationFilterTypeEnum.Pen));
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_pencilpainting, AnimationFilterTypeEnum.Pencil));
|
||||
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_graffiti, AnimationFilterTypeEnum.Granffiti));
|
||||
return filters;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
import com.faceunity.core.avatar.avatar.Color;
|
||||
import com.faceunity.core.avatar.avatar.TransForm;
|
||||
import com.faceunity.core.avatar.model.Avatar;
|
||||
import com.faceunity.core.avatar.model.Scene;
|
||||
import com.faceunity.core.entity.FUAnimationData;
|
||||
import com.faceunity.core.entity.FUAvatarAnimFilterParams;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUColorRGBData;
|
||||
import com.faceunity.core.entity.FUCoordinate3DData;
|
||||
import com.faceunity.core.entity.FUTranslationScale;
|
||||
import com.faceunity.core.entity.FUVisibleBundleData;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.AvatarBean;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* DESC:Avatar数据构造
|
||||
* Created on 2021/3/30
|
||||
*/
|
||||
public class AvatarSource {
|
||||
// Avatar
|
||||
private static String BUNDLE_AVATAR_CONTROLLER = "graphics" + File.separator + "controller_cpp.bundle";
|
||||
private static String BUNDLE_AVATAR_CONFIG = "pta" + File.separator + "controller_config.bundle";
|
||||
private static String BUNDLE_AVATAR_BACKGROUND = "pta" + File.separator + "default_bg.bundle";
|
||||
|
||||
public static String BOY = "boy";
|
||||
public static String GIRL = "girl";
|
||||
|
||||
/**
|
||||
* 构造成员列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<AvatarBean> buildMembers() {
|
||||
ArrayList<AvatarBean> avatarBeans = new ArrayList<>();
|
||||
avatarBeans.add(new AvatarBean(R.mipmap.icon_avatar_female, GIRL));
|
||||
avatarBeans.add(new AvatarBean(R.mipmap.icon_avatar_male, BOY));
|
||||
return avatarBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造场景
|
||||
*
|
||||
* @param avatar
|
||||
* @return
|
||||
*/
|
||||
public static Scene buildSceneModel(Avatar avatar) {
|
||||
FUBundleData controlBundle = new FUBundleData(BUNDLE_AVATAR_CONTROLLER);
|
||||
FUBundleData avatarConfig = new FUBundleData(BUNDLE_AVATAR_CONFIG);
|
||||
Scene sceneModel = new Scene(controlBundle, avatarConfig);
|
||||
sceneModel.addAvatar(avatar);
|
||||
sceneModel.processorConfig.setEnableHumanProcessor(true);
|
||||
return sceneModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取男孩对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Avatar buildBoyData(boolean isFull) {
|
||||
String ptaBoyDir = "pta/boy/";
|
||||
ArrayList<FUBundleData> components = new ArrayList();
|
||||
components.add(new FUBundleData(ptaBoyDir + "head.bundle"));
|
||||
components.add(new FUBundleData(ptaBoyDir + "midBody_male.bundle"));
|
||||
components.add(new FUBundleData(ptaBoyDir + "male_hair_5.bundle"));
|
||||
components.add(new FUBundleData(ptaBoyDir + "toushi_7.bundle"));
|
||||
components.add(new FUBundleData(ptaBoyDir + "peishi_erding_2.bundle"));
|
||||
components.add(new FUBundleData(ptaBoyDir + "waitao_3.bundle"));
|
||||
components.add(new FUBundleData(ptaBoyDir + "kuzi_changku_5.bundle"));
|
||||
components.add(new FUBundleData(ptaBoyDir + "xiezi_tuoxie_2.bundle"));
|
||||
int[] invisibleList = {2,3,4};
|
||||
components.add(new FUVisibleBundleData("",invisibleList,""));
|
||||
ArrayList<FUAnimationData> animations = buildAnimations();
|
||||
Avatar model = new Avatar(components);
|
||||
for (FUAnimationData animationData:animations){
|
||||
model.animation.addAnimation(animationData);
|
||||
}
|
||||
model.color.setColor(Color.Skin,new FUColorRGBData(227.0,158.0,132.0));
|
||||
TransForm avatarTransForm = model.transForm;
|
||||
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
|
||||
avatarTransForm.setPosition(isFull ? new FUCoordinate3DData(0.0, 58.14, -618.94) : new FUCoordinate3DData(0.0, 11.76, -183.89));
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取女孩对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Avatar buildGirlData(boolean isFull) {
|
||||
String ptaGirlDir = "pta/girl/";
|
||||
ArrayList<FUBundleData> components = new ArrayList();
|
||||
components.add(new FUBundleData(ptaGirlDir + "head.bundle"));
|
||||
components.add(new FUBundleData(ptaGirlDir + "midBody_female.bundle"));
|
||||
components.add(new FUBundleData(ptaGirlDir + "female_hair_23.bundle"));
|
||||
components.add(new FUBundleData(ptaGirlDir + "toushi_5.bundle"));
|
||||
components.add(new FUBundleData(ptaGirlDir + "taozhuang_12.bundle"));
|
||||
components.add(new FUBundleData(ptaGirlDir + "facemakeup_3.bundle"));
|
||||
components.add(new FUBundleData(ptaGirlDir + "xiezi_danxie.bundle"));
|
||||
int[] invisibleList = {2,3,4};
|
||||
components.add(new FUVisibleBundleData("",invisibleList,""));
|
||||
ArrayList<FUAnimationData> animations = buildAnimations();
|
||||
Avatar model = new Avatar(components );
|
||||
for (FUAnimationData animationData:animations){
|
||||
model.animation.addAnimation(animationData);
|
||||
}
|
||||
model.color.setColor(Color.Skin,new FUColorRGBData(255.0,202.0,186.0));
|
||||
TransForm avatarTransForm = model.transForm;
|
||||
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
|
||||
avatarTransForm.setPosition(isFull ? new FUCoordinate3DData(0.0, 58.14, -618.94) : new FUCoordinate3DData(0.0, 11.76, -183.89));
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* 外部传入组件和动画构建
|
||||
*
|
||||
* @param strComponents 组件bundle
|
||||
* @param strAnimations 动画bundle
|
||||
* @return
|
||||
*/
|
||||
public static Avatar buildAvatarData(ArrayList<String> strComponents, ArrayList<String> strAnimations) {
|
||||
ArrayList<FUBundleData> components = new ArrayList();
|
||||
for (String component : strComponents) {
|
||||
components.add(new FUBundleData(component));
|
||||
}
|
||||
|
||||
Avatar model = new Avatar(components);
|
||||
for (String animation : strAnimations) {
|
||||
model.animation.addAnimation(new FUAnimationData(new FUBundleData(animation)));
|
||||
}
|
||||
//位置等avatar基本参数构建
|
||||
TransForm avatarTransForm = model.transForm;
|
||||
avatarTransForm.setPosition(new FUCoordinate3DData(20, 45, -618.94));
|
||||
avatarTransForm.setTranslationScale(new FUTranslationScale(0.0f,0.0f,0.0f));
|
||||
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
|
||||
model.animation.setHumanProcessorSetAvatarAnimFilterParams(new FUAvatarAnimFilterParams(8, 0.09f, 0.120f));
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造动画参数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<FUAnimationData> buildAnimations() {
|
||||
String animDir = "pta/gesture/";
|
||||
ArrayList<FUAnimationData> animations = new ArrayList();
|
||||
animations.add(new FUAnimationData(new FUBundleData(animDir + "anim_idle.bundle")));
|
||||
return animations;
|
||||
}
|
||||
|
||||
public static void setSceneBackGround(Scene sceneModel, boolean hasBackGround) {
|
||||
sceneModel.setBackgroundBundle(hasBackGround ? new FUBundleData(BUNDLE_AVATAR_BACKGROUND) : null);
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
|
||||
import com.faceunity.core.controller.bgSegGreen.BgSegGreenParam;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.model.bgSegGreen.BgSegGreen;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean;
|
||||
import com.yunbao.faceunity.entity.BgSegGreenBean;
|
||||
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* DESC:绿幕抠像数据构造
|
||||
* Created on 2021/3/25
|
||||
*/
|
||||
public class BgSegGreenSource {
|
||||
private static final String GREEN_SAFE_AREA_CUSTOM = "green_safe_area_custom";
|
||||
|
||||
private static double SIMILARITY = 0.5;//相似度
|
||||
private static double SMOOTHNESS = 0.3;//平滑度
|
||||
private static double TRANSPARENCY = 0.67;//透明度
|
||||
|
||||
/**
|
||||
* 构造绿幕抠像对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static BgSegGreen buildBgSegGreen() {
|
||||
BgSegGreen bgSegGreen = new BgSegGreen(new FUBundleData(FaceUnityConfig.BUNDLE_BG_SEG_GREEN));
|
||||
bgSegGreen.setSimilarity(BgSegGreenSource.SIMILARITY);
|
||||
bgSegGreen.setSmoothness(BgSegGreenSource.SMOOTHNESS);
|
||||
bgSegGreen.setTransparency(BgSegGreenSource.TRANSPARENCY);
|
||||
return bgSegGreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型属性扩展数据
|
||||
*
|
||||
* @return HashMap<String, ModelAttributeData>
|
||||
*/
|
||||
public static HashMap<String, ModelAttributeData> buildModelAttributeRange() {
|
||||
HashMap<String, ModelAttributeData> params = new HashMap<String, ModelAttributeData>();
|
||||
params.put(BgSegGreenParam.SIMILARITY, new ModelAttributeData(SIMILARITY, 0.0, 0.0, 1.0));
|
||||
params.put(BgSegGreenParam.SMOOTHNESS, new ModelAttributeData(SMOOTHNESS, 0.0, 0.0, 1.0));
|
||||
params.put(BgSegGreenParam.TRANSPARENCY, new ModelAttributeData(TRANSPARENCY, 0.0, 0.0, 1.0));
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绿幕抠像功能列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<BgSegGreenBean> buildBgSegGreenAction() {
|
||||
ArrayList<BgSegGreenBean> actions = new ArrayList<BgSegGreenBean>();
|
||||
actions.add(new BgSegGreenBean(BgSegGreenParam.RGB_COLOR, R.string.bg_seg_green_key_color, R.drawable.icon_green_color_selector, R.drawable.icon_green_color_selector, BgSegGreenBean.ButtonType.NORMAL2_BUTTON));
|
||||
actions.add(new BgSegGreenBean(BgSegGreenParam.SIMILARITY, R.string.bg_seg_green_similarity, R.drawable.icon_green_similarityr_close_selector, R.drawable.icon_green_similarityr_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
|
||||
actions.add(new BgSegGreenBean(BgSegGreenParam.SMOOTHNESS, R.string.bg_seg_green_smooth, R.drawable.icon_green_smooth_close_selector, R.drawable.icon_green_similarityr_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
|
||||
actions.add(new BgSegGreenBean(BgSegGreenParam.TRANSPARENCY, R.string.bg_seg_green_alpha, R.drawable.icon_green_transparency_close_selector, R.drawable.icon_green_transparency_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
|
||||
actions.add(new BgSegGreenBean("", R.string.bg_seg_green_safe_area, R.drawable.icon_green_safe_area_close_selector, R.drawable.icon_green_safe_area_open_selector, BgSegGreenBean.ButtonType.SWITCH_BUTTON));
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绿幕抠像安全区域功能列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<BgSegGreenSafeAreaBean> buildBgSegGreenSafeArea() {
|
||||
String fileDir = "bg_seg_green" + File.separator + "sample" + File.separator;
|
||||
ArrayList<BgSegGreenSafeAreaBean> safeAreaBeans = new ArrayList<BgSegGreenSafeAreaBean>();
|
||||
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_return, BgSegGreenSafeAreaBean.ButtonType.BACK_BUTTON));//返回
|
||||
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_none, BgSegGreenSafeAreaBean.ButtonType.NONE_BUTTON));//不选
|
||||
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_square_add, BgSegGreenSafeAreaBean.ButtonType.NORMAL2_BUTTON));//自定义
|
||||
BgSegGreenSafeAreaBean customerBean = buildSafeAreaCustomBean(getCachePortraitSegment());
|
||||
if (customerBean != null) {
|
||||
safeAreaBeans.add(customerBean);
|
||||
}
|
||||
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_green_safe_area1, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON,fileDir + "safe_area1.jpg"));//区域一
|
||||
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_green_safe_area2, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON,fileDir + "safe_area2.jpg"));//区域二
|
||||
return safeAreaBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造自定义安全区域图片
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public static BgSegGreenSafeAreaBean buildSafeAreaCustomBean(String path) {
|
||||
if (path != null && path.trim().length() > 0 && new File(path).exists()) {
|
||||
saveCachePortraitSegment(path);
|
||||
return new BgSegGreenSafeAreaBean(0, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON, path,false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绿幕抠像背景列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<BgSegGreenBackgroundBean> buildBgSegGreenBackground() {
|
||||
ArrayList<BgSegGreenBackgroundBean> backgroundBeans = new ArrayList<>();
|
||||
String fileDir = "bg_seg_green" + File.separator + "sample" + File.separator;
|
||||
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.cancel, R.mipmap.icon_control_none, null));
|
||||
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_science, R.mipmap.icon_green_science, fileDir + "science.mp4"));
|
||||
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_beach, R.mipmap.icon_green_bg_beach, fileDir + "beach.mp4"));
|
||||
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_classroom, R.mipmap.icon_green_bg_classroom, fileDir + "classroom.mp4"));
|
||||
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_ink, R.mipmap.icon_green_ink_painting, fileDir + "ink_painting.mp4"));
|
||||
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_forest, R.mipmap.icon_green_bg_forest, fileDir + "forest.mp4"));
|
||||
return backgroundBeans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存自定义安全区域图片
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
public static void saveCachePortraitSegment(String path) {
|
||||
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(GREEN_SAFE_AREA_CUSTOM, MODE_PRIVATE);
|
||||
sp.edit().putString(GREEN_SAFE_AREA_CUSTOM, path).apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义安全区域图片
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getCachePortraitSegment() {
|
||||
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(GREEN_SAFE_AREA_CUSTOM, MODE_PRIVATE);
|
||||
return sp.getString(GREEN_SAFE_AREA_CUSTOM, "");
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
import com.faceunity.core.controller.bodyBeauty.BodyBeautyParam;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.BodyBeautyBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* DESC:美体数据构造
|
||||
* Created on 2021/3/26
|
||||
*/
|
||||
public class BodyBeautySource {
|
||||
|
||||
public static final String BUNDLE_BODY_BEAUTY = "graphics" + File.separator + "body_slim.bundle";
|
||||
|
||||
|
||||
/**
|
||||
* 构造美体
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<BodyBeautyBean> buildBodyBeauty() {
|
||||
ArrayList<BodyBeautyBean> params = new ArrayList<>();
|
||||
params.add(new BodyBeautyBean(BodyBeautyParam.BODY_SLIM_INTENSITY, R.string.slimming, R.drawable.icon_body_slimming_close_selector, R.drawable.icon_body_slimming_open_selector));
|
||||
params.add(new BodyBeautyBean(BodyBeautyParam.LEG_STRETCH_INTENSITY, R.string.long_legs, R.drawable.icon_body_stovepipe_close_selector, R.drawable.icon_body_stovepipe_open_selector));
|
||||
params.add(new BodyBeautyBean(BodyBeautyParam.WAIST_SLIM_INTENSITY, R.string.thin_waist, R.drawable.icon_body_waist_close_selector, R.drawable.icon_body_waist_open_selector));
|
||||
params.add(new BodyBeautyBean(BodyBeautyParam.SHOULDER_SLIM_INTENSITY, R.string.beautify_shoulder, R.drawable.icon_body_shoulder_close_selector, R.drawable.icon_body_shoulder_open_selector));
|
||||
params.add(new BodyBeautyBean(BodyBeautyParam.HIP_SLIM_INTENSITY, R.string.beautify_hip_slim, R.drawable.icon_body_hip_close_selector, R.drawable.icon_body_hip_open_selector));
|
||||
params.add(new BodyBeautyBean(BodyBeautyParam.HEAD_SLIM_INTENSITY, R.string.beautify_head_slim, R.drawable.icon_body_little_head_close_selector, R.drawable.icon_body_little_head_open_selector));
|
||||
params.add(new BodyBeautyBean(BodyBeautyParam.LEG_SLIM_INTENSITY, R.string.beautify_leg_thin_slim, R.drawable.icon_body_thin_leg_close_selector, R.drawable.icon_body_thin_leg_open_selector));
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型属性扩展数据
|
||||
*
|
||||
* @return HashMap<String, ModelAttributeData>
|
||||
*/
|
||||
public static HashMap<String, ModelAttributeData> buildModelAttributeRange() {
|
||||
HashMap<String, ModelAttributeData> params = new HashMap<>();
|
||||
params.put(BodyBeautyParam.BODY_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(BodyBeautyParam.LEG_STRETCH_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(BodyBeautyParam.WAIST_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(BodyBeautyParam.SHOULDER_SLIM_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0));
|
||||
params.put(BodyBeautyParam.HIP_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(BodyBeautyParam.HEAD_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(BodyBeautyParam.LEG_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
return params;
|
||||
}
|
||||
}
|
@ -0,0 +1,761 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
|
||||
import com.faceunity.core.controller.facebeauty.FaceBeautyParam;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.enumeration.FUFaceBeautyMultiModePropertyEnum;
|
||||
import com.faceunity.core.enumeration.FUFaceBeautyPropertyModeEnum;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.facebeauty.FaceBeauty;
|
||||
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.data.FaceBeautyData;
|
||||
import com.yunbao.faceunity.data.FaceBeautyDataFactory;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyStyleBean;
|
||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||
import com.yunbao.faceunity.utils.FUUtils;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
import com.yunbao.faceunity.utils.FuDeviceUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* DESC:美颜数据构造
|
||||
* Created on 2021/3/27
|
||||
*/
|
||||
public class FaceBeautySource {
|
||||
|
||||
private static ArrayList<FaceBeautyFilterBean> filters = new ArrayList<>();
|
||||
private static FaceBeautyData faceBeautyData;
|
||||
|
||||
/**
|
||||
* 获取默认推荐美颜模型
|
||||
* 一个app生命周期请求一次
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static FaceBeauty getDefaultFaceBeauty() {
|
||||
FaceBeauty recommendFaceBeauty = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||
if (FaceUnityConfig.OPEN_FACE_BEAUTY_TO_FILE)
|
||||
faceBeautyData = FUUtils.loadFaceBeautyData();
|
||||
if (faceBeautyData != null) {
|
||||
//有本地缓存
|
||||
FaceBeautyDataFactory.setDiskCurrentStyleIndex(faceBeautyData.styleTypeIndex);
|
||||
FUUtils.setFaceBeauty(faceBeautyData, recommendFaceBeauty);
|
||||
} else {
|
||||
//没有本地缓存
|
||||
recommendFaceBeauty.setFilterName(FaceBeautyFilterEnum.ZIRAN_2);
|
||||
recommendFaceBeauty.setFilterIntensity(0.4);
|
||||
/*美肤*/
|
||||
recommendFaceBeauty.setSharpenIntensity(0.2);
|
||||
recommendFaceBeauty.setColorIntensity(0.3);
|
||||
recommendFaceBeauty.setRedIntensity(0.3);
|
||||
recommendFaceBeauty.setBlurIntensity(4.2);
|
||||
/*美型*/
|
||||
recommendFaceBeauty.setFaceShapeIntensity(1.0);
|
||||
recommendFaceBeauty.setEyeEnlargingIntensity(0.4);
|
||||
recommendFaceBeauty.setCheekVIntensity(0.5);
|
||||
recommendFaceBeauty.setNoseIntensity(0.5);
|
||||
recommendFaceBeauty.setForHeadIntensity(0.3);
|
||||
recommendFaceBeauty.setMouthIntensity(0.4);
|
||||
recommendFaceBeauty.setChinIntensity(0.3);
|
||||
//性能最优策略
|
||||
if (FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID) {
|
||||
setFaceBeautyPropertyMode(recommendFaceBeauty);
|
||||
}
|
||||
}
|
||||
|
||||
return recommendFaceBeauty;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高端机的时候,开启4个相对吃性能的模式
|
||||
* 1.祛黑眼圈 MODE2
|
||||
* 2.祛法令纹 MODE2
|
||||
* 3.大眼 MODE3
|
||||
* 4.嘴型 MODE3
|
||||
*/
|
||||
private static void setFaceBeautyPropertyMode(FaceBeauty faceBeauty) {
|
||||
/*
|
||||
* 多模式属性
|
||||
* 属性名称|支持模式|默认模式|最早支持版本
|
||||
* 美白 colorIntensity|MODE1 MODE2|MODE2|MODE2 8.2.0;
|
||||
* 祛黑眼圈 removePouchIntensity|MODE1 MODE2|MODE2|MODE2 8.2.0;
|
||||
* 祛法令纹 removeLawPatternIntensity|MODE1 MODE1|MODE2|MODE2 8.2.0;
|
||||
* 窄脸程度 cheekNarrowIntensity|MODE1 MODE2|MODE2|MODE2 8.0.0;
|
||||
* 小脸程度 cheekSmallIntensity|MODE1 MODE2|MODE2|MODE2 8.0.0;
|
||||
* 大眼程度 eyeEnlargingIntensity|MODE1 MODE2 MODE3|MODE3|MODE2 8.0.0;MODE3 8.2.0;
|
||||
* 额头调整程度 forHeadIntensity|MODE1 MODE2|MODE2|MODE2 8.0.0;
|
||||
* 瘦鼻程度 noseIntensity|MODE1 MODE2|MODE2|MODE2 8.0.0;
|
||||
* 嘴巴调整程度 mouthIntensity|MODE1 MODE2 MODE3|MODE3|MODE2 8.0.0;MODE3 8.2.0;
|
||||
*/
|
||||
faceBeauty.addPropertyMode(FUFaceBeautyMultiModePropertyEnum.REMOVE_POUCH_INTENSITY, FUFaceBeautyPropertyModeEnum.MODE2);
|
||||
faceBeauty.addPropertyMode(FUFaceBeautyMultiModePropertyEnum.REMOVE_NASOLABIAL_FOLDS_INTENSITY, FUFaceBeautyPropertyModeEnum.MODE2);
|
||||
faceBeauty.addPropertyMode(FUFaceBeautyMultiModePropertyEnum.EYE_ENLARGING_INTENSITY, FUFaceBeautyPropertyModeEnum.MODE3);
|
||||
faceBeauty.addPropertyMode(FUFaceBeautyMultiModePropertyEnum.MOUTH_INTENSITY, FUFaceBeautyPropertyModeEnum.MODE3);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化美肤参数
|
||||
*
|
||||
* @return ArrayList<FaceBeautyBean>
|
||||
*/
|
||||
public static ArrayList<FaceBeautyBean> buildSkinParams() {
|
||||
ArrayList<FaceBeautyBean> params = new ArrayList<>();
|
||||
params.add(new FaceBeautyBean(
|
||||
FaceBeautyParam.BLUR_INTENSITY
|
||||
, R.string.beauty_box_heavy_blur_fine
|
||||
, R.drawable.icon_beauty_skin_buffing_close_selector
|
||||
, R.drawable.icon_beauty_skin_buffing_open_selector
|
||||
, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.COLOR_INTENSITY, R.string.beauty_box_color_level,
|
||||
R.drawable.icon_beauty_skin_color_close_selector, R.drawable.icon_beauty_skin_color_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.RED_INTENSITY, R.string.beauty_box_red_level,
|
||||
R.drawable.icon_beauty_skin_red_close_selector, R.drawable.icon_beauty_skin_red_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.SHARPEN_INTENSITY, R.string.beauty_box_sharpen,
|
||||
R.drawable.icon_beauty_skin_sharpen_close_selector, R.drawable.icon_beauty_skin_sharpen_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_BRIGHT_INTENSITY, R.string.beauty_box_eye_bright,
|
||||
R.drawable.icon_beauty_skin_eyes_bright_close_selector, R.drawable.icon_beauty_skin_eyes_bright_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.TOOTH_WHITEN_INTENSITY, R.string.beauty_box_tooth_whiten,
|
||||
R.drawable.icon_beauty_skin_teeth_close_selector, R.drawable.icon_beauty_skin_teeth_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.REMOVE_POUCH_INTENSITY, R.string.beauty_micro_pouch,
|
||||
R.drawable.icon_beauty_skin_dark_circles_close_selector, R.drawable.icon_beauty_skin_dark_circles_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, R.string.beauty_micro_nasolabial,
|
||||
R.drawable.icon_beauty_skin_wrinkle_close_selector, R.drawable.icon_beauty_skin_wrinkle_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SKIN)
|
||||
);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化美型参数
|
||||
*
|
||||
* @return ArrayList<FaceBeautyBean>
|
||||
*/
|
||||
public static ArrayList<FaceBeautyBean> buildShapeParams() {
|
||||
ArrayList<FaceBeautyBean> params = new ArrayList<>();
|
||||
// params.add(
|
||||
// new FaceBeautyBean(
|
||||
// "", R.string.avatar_face_face,
|
||||
// R.drawable.icon_beauty_shape_face_shape_close_selector, R.drawable.icon_beauty_shape_face_shape_open_selector, FaceBeautyBean.ButtonType.SUB_ITEM_BUTTON
|
||||
// )
|
||||
// );
|
||||
|
||||
//瘦脸
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_THINNING_INTENSITY, R.string.beauty_box_cheek_thinning,
|
||||
R.drawable.icon_beauty_shape_face_cheekthin_close_selector, R.drawable.icon_beauty_shape_face_cheekthin_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
|
||||
//V脸
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_V_INTENSITY, R.string.beauty_box_cheek_v,
|
||||
R.drawable.icon_beauty_shape_face_v_close_selector, R.drawable.icon_beauty_shape_face_v_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
|
||||
//窄脸
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_NARROW_INTENSITY, R.string.beauty_box_cheek_narrow,
|
||||
R.drawable.icon_beauty_shape_face_narrow_close_selector, R.drawable.icon_beauty_shape_face_narrow_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
|
||||
//小脸 -> 短脸 --使用的参数是以前小脸的
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_SHORT_INTENSITY, R.string.beauty_box_cheek_short,
|
||||
R.drawable.icon_beauty_shape_face_short_close_selector, R.drawable.icon_beauty_shape_face_short_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
|
||||
//小脸 -> 新增
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHEEK_SMALL_INTENSITY, R.string.beauty_box_cheek_small,
|
||||
R.drawable.icon_beauty_shape_face_little_close_selector, R.drawable.icon_beauty_shape_face_little_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, R.string.beauty_box_cheekbones,
|
||||
R.drawable.icon_beauty_shape_cheek_bones_close_selector, R.drawable.icon_beauty_shape_cheek_bones_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, R.string.beauty_box_lower_jaw,
|
||||
R.drawable.icon_beauty_shape_lower_jaw_close_selector, R.drawable.icon_beauty_shape_lower_jaw_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_ENLARGING_INTENSITY, R.string.beauty_box_eye_enlarge,
|
||||
R.drawable.icon_beauty_shape_enlarge_eye_close_selector, R.drawable.icon_beauty_shape_enlarge_eye_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_CIRCLE_INTENSITY, R.string.beauty_box_eye_circle,
|
||||
R.drawable.icon_beauty_shape_round_eye_close_selector, R.drawable.icon_beauty_shape_round_eye_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CHIN_INTENSITY, R.string.beauty_box_intensity_chin,
|
||||
R.drawable.icon_beauty_shape_chin_close_selector, R.drawable.icon_beauty_shape_chin_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.FOREHEAD_INTENSITY, R.string.beauty_box_intensity_forehead,
|
||||
R.drawable.icon_beauty_shape_forehead_close_selector, R.drawable.icon_beauty_shape_forehead_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.NOSE_INTENSITY, R.string.beauty_box_intensity_nose,
|
||||
R.drawable.icon_beauty_shape_thin_nose_close_selector, R.drawable.icon_beauty_shape_thin_nose_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.MOUTH_INTENSITY, R.string.beauty_box_intensity_mouth,
|
||||
R.drawable.icon_beauty_shape_mouth_close_selector, R.drawable.icon_beauty_shape_mouth_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.CANTHUS_INTENSITY, R.string.beauty_micro_canthus,
|
||||
R.drawable.icon_beauty_shape_open_eyes_close_selector, R.drawable.icon_beauty_shape_open_eyes_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_SPACE_INTENSITY, R.string.beauty_micro_eye_space,
|
||||
R.drawable.icon_beauty_shape_distance_close_selector, R.drawable.icon_beauty_shape_distance_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.EYE_ROTATE_INTENSITY, R.string.beauty_micro_eye_rotate,
|
||||
R.drawable.icon_beauty_shape_angle_close_selector, R.drawable.icon_beauty_shape_angle_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.LONG_NOSE_INTENSITY, R.string.beauty_micro_long_nose,
|
||||
R.drawable.icon_beauty_shape_proboscis_close_selector, R.drawable.icon_beauty_shape_proboscis_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.PHILTRUM_INTENSITY, R.string.beauty_micro_philtrum,
|
||||
R.drawable.icon_beauty_shape_shrinking_close_selector, R.drawable.icon_beauty_shape_shrinking_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.SMILE_INTENSITY, R.string.beauty_micro_smile,
|
||||
R.drawable.icon_beauty_shape_smile_close_selector, R.drawable.icon_beauty_shape_smile_open_selector, 0
|
||||
, true,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.BROW_HEIGHT_INTENSITY,
|
||||
R.string.beauty_brow_height,
|
||||
R.drawable.icon_beauty_shape_brow_height_close_selector,
|
||||
R.drawable.icon_beauty_shape_brow_height_open_selector,
|
||||
R.string.brow_height_tips,
|
||||
FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
|
||||
)
|
||||
);
|
||||
params.add(
|
||||
new FaceBeautyBean(
|
||||
FaceBeautyParam.BROW_SPACE_INTENSITY, R.string.beauty_brow_space,
|
||||
R.drawable.icon_beauty_shape_brow_space_close_selector, R.drawable.icon_beauty_shape_brow_space_open_selector,
|
||||
R.string.brow_space_tips, FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID,
|
||||
FaceParam.FACE_BEAUTY_SHAPE
|
||||
)
|
||||
);
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载脸型子项
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<FaceBeautyBean> buildFaceShapeSubItemParams() {
|
||||
return buildSubItemParams(FaceBeautyParam.FACE_SHAPE);
|
||||
}
|
||||
|
||||
public static ArrayList<FaceBeautyBean> buildSubItemParams(String key) {
|
||||
ArrayList<FaceBeautyBean> params = new ArrayList<>();
|
||||
// if (key != null && !key.isEmpty()) {
|
||||
// if (key.equals(FaceBeautyParam.FACE_SHAPE)) {
|
||||
// //返回
|
||||
// params.add(
|
||||
// new FaceBeautyBean(
|
||||
// "", R.string.back,
|
||||
// R.mipmap.icon_beauty_back, R.mipmap.icon_beauty_back, FaceBeautyBean.ButtonType.BACK_BUTTON
|
||||
// )
|
||||
// );
|
||||
//
|
||||
// //自然 V脸 -> 自然脸
|
||||
// params.add(
|
||||
// new FaceBeautyBean(
|
||||
// FaceBeautyParam.CHEEK_V_INTENSITY, R.string.beauty_box_cheek_natural,
|
||||
// R.drawable.icon_beauty_shape_face_natural_close_selector, R.drawable.icon_beauty_shape_face_natural_open_selector
|
||||
// )
|
||||
// );
|
||||
//
|
||||
// //女神 瘦脸 -> 女神脸
|
||||
// params.add(
|
||||
// new FaceBeautyBean(
|
||||
// FaceBeautyParam.CHEEK_THINNING_INTENSITY, R.string.beauty_box_cheek_goddess,
|
||||
// R.drawable.icon_beauty_shape_face_goddess_close_selector, R.drawable.icon_beauty_shape_face_goddess_open_selector
|
||||
// )
|
||||
// );
|
||||
//
|
||||
// //长脸
|
||||
// params.add(
|
||||
// new FaceBeautyBean(
|
||||
// FaceBeautyParam.CHEEK_LONG_INTENSITY, R.string.beauty_box_cheek_long_face,
|
||||
// R.drawable.icon_beauty_shape_face_long_close_selector, R.drawable.icon_beauty_shape_face_long_open_selector
|
||||
// )
|
||||
// );
|
||||
//
|
||||
// //圆脸
|
||||
// params.add(
|
||||
// new FaceBeautyBean(
|
||||
// FaceBeautyParam.CHEEK_CIRCLE_INTENSITY, R.string.beauty_box_cheek_round_face,
|
||||
// R.drawable.icon_beauty_shape_face_round_close_selector, R.drawable.icon_beauty_shape_face_round_open_selector
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化参数扩展列表
|
||||
*
|
||||
* @return HashMap<String, ModelAttributeData>
|
||||
*/
|
||||
public static HashMap<String, ModelAttributeData> buildModelAttributeRange() {
|
||||
HashMap<String, ModelAttributeData> params = new HashMap<>();
|
||||
/*美肤*/
|
||||
params.put(FaceBeautyParam.COLOR_INTENSITY, new ModelAttributeData(0.3, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.BLUR_INTENSITY, new ModelAttributeData(4.2, 0.0, 0.0, 6.0));
|
||||
params.put(FaceBeautyParam.RED_INTENSITY, new ModelAttributeData(0.3, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.SHARPEN_INTENSITY, new ModelAttributeData(0.2, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.EYE_BRIGHT_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.TOOTH_WHITEN_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.REMOVE_POUCH_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
/*美型*/
|
||||
params.put(FaceBeautyParam.FACE_SHAPE_INTENSITY, new ModelAttributeData(1.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CHEEK_THINNING_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CHEEK_LONG_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CHEEK_CIRCLE_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CHEEK_V_INTENSITY, new ModelAttributeData(0.5, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CHEEK_NARROW_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CHEEK_SHORT_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CHEEK_SMALL_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.EYE_ENLARGING_INTENSITY, new ModelAttributeData(0.4, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.EYE_CIRCLE_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CHIN_INTENSITY, new ModelAttributeData(0.3, 0.5, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.FOREHEAD_INTENSITY, new ModelAttributeData(0.3, 0.5, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.NOSE_INTENSITY, new ModelAttributeData(0.5, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.MOUTH_INTENSITY, new ModelAttributeData(0.4, 0.5, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.CANTHUS_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.EYE_SPACE_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.EYE_ROTATE_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.LONG_NOSE_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.PHILTRUM_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.SMILE_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.BROW_HEIGHT_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0));
|
||||
params.put(FaceBeautyParam.BROW_SPACE_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0));
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化滤镜参数
|
||||
*
|
||||
* @return ArrayList<FaceBeautyFilterBean>
|
||||
*/
|
||||
public static ArrayList<FaceBeautyFilterBean> buildFilters() {
|
||||
if (!filters.isEmpty()) {
|
||||
return filters;
|
||||
}
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ORIGIN, R.mipmap.icon_beauty_filter_cancel, R.string.origin, 0.0));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_1, R.mipmap.icon_beauty_filter_natural_1, R.string.ziran_1, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_2, R.mipmap.icon_beauty_filter_natural_2, R.string.ziran_2, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_2)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_3, R.mipmap.icon_beauty_filter_natural_3, R.string.ziran_3, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_4, R.mipmap.icon_beauty_filter_natural_4, R.string.ziran_4, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_4)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_5, R.mipmap.icon_beauty_filter_natural_5, R.string.ziran_5, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_5)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_6, R.mipmap.icon_beauty_filter_natural_6, R.string.ziran_6, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_6)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_7, R.mipmap.icon_beauty_filter_natural_7, R.string.ziran_7, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_7)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_8, R.mipmap.icon_beauty_filter_natural_8, R.string.ziran_8, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_8)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_1, R.mipmap.icon_beauty_filter_texture_gray_1, R.string.zhiganhui_1, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_2, R.mipmap.icon_beauty_filter_texture_gray_2, R.string.zhiganhui_2, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_2)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_3, R.mipmap.icon_beauty_filter_texture_gray_3, R.string.zhiganhui_3, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_4, R.mipmap.icon_beauty_filter_texture_gray_4, R.string.zhiganhui_4, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_4)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_5, R.mipmap.icon_beauty_filter_texture_gray_5, R.string.zhiganhui_5, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_5)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_6, R.mipmap.icon_beauty_filter_texture_gray_6, R.string.zhiganhui_6, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_6)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_7, R.mipmap.icon_beauty_filter_texture_gray_7, R.string.zhiganhui_7, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_7)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_8, R.mipmap.icon_beauty_filter_texture_gray_8, R.string.zhiganhui_8, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_8)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_1, R.mipmap.icon_beauty_filter_peach_1, R.string.mitao_1, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_2, R.mipmap.icon_beauty_filter_peach_2, R.string.mitao_2, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_2)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_3, R.mipmap.icon_beauty_filter_peach_3, R.string.mitao_3, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_4, R.mipmap.icon_beauty_filter_peach_4, R.string.mitao_4, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_4)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_5, R.mipmap.icon_beauty_filter_peach_5, R.string.mitao_5, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_5)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_6, R.mipmap.icon_beauty_filter_peach_6, R.string.mitao_6, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_6)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_7, R.mipmap.icon_beauty_filter_peach_7, R.string.mitao_7, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_7)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_8, R.mipmap.icon_beauty_filter_peach_8, R.string.mitao_8, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_8)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_1, R.mipmap.icon_beauty_filter_bailiang_1, R.string.bailiang_1, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_2, R.mipmap.icon_beauty_filter_bailiang_2, R.string.bailiang_2, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_2)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_3, R.mipmap.icon_beauty_filter_bailiang_3, R.string.bailiang_3, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_4, R.mipmap.icon_beauty_filter_bailiang_4, R.string.bailiang_4, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_4)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_5, R.mipmap.icon_beauty_filter_bailiang_5, R.string.bailiang_5, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_5)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_6, R.mipmap.icon_beauty_filter_bailiang_6, R.string.bailiang_6, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_6)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_7, R.mipmap.icon_beauty_filter_bailiang_7, R.string.bailiang_7, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_7)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_1, R.mipmap.icon_beauty_filter_fennen_1, R.string.fennen_1, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_2, R.mipmap.icon_beauty_filter_fennen_2, R.string.fennen_2, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_2)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_3, R.mipmap.icon_beauty_filter_fennen_3, R.string.fennen_3, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_5, R.mipmap.icon_beauty_filter_fennen_5, R.string.fennen_5, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_5)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_6, R.mipmap.icon_beauty_filter_fennen_6, R.string.fennen_6, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_6)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_7, R.mipmap.icon_beauty_filter_fennen_7, R.string.fennen_7, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_7)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_8, R.mipmap.icon_beauty_filter_fennen_8, R.string.fennen_8, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_8)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_1, R.mipmap.icon_beauty_filter_lengsediao_1, R.string.lengsediao_1, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_2, R.mipmap.icon_beauty_filter_lengsediao_2, R.string.lengsediao_2, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_2)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_3, R.mipmap.icon_beauty_filter_lengsediao_3, R.string.lengsediao_3, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_4, R.mipmap.icon_beauty_filter_lengsediao_4, R.string.lengsediao_4, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_4)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_7, R.mipmap.icon_beauty_filter_lengsediao_7, R.string.lengsediao_7, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_7)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_8, R.mipmap.icon_beauty_filter_lengsediao_8, R.string.lengsediao_8, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_8)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_11, R.mipmap.icon_beauty_filter_lengsediao_11, R.string.lengsediao_11, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_11)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.NUANSEDIAO_1, R.mipmap.icon_beauty_filter_nuansediao_1, R.string.nuansediao_1, getDiskFilterValue(FaceBeautyFilterEnum.NUANSEDIAO_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.NUANSEDIAO_2, R.mipmap.icon_beauty_filter_nuansediao_2, R.string.nuansediao_2, getDiskFilterValue(FaceBeautyFilterEnum.NUANSEDIAO_2)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_1, R.mipmap.icon_beauty_filter_gexing_1, R.string.gexing_1, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_2, R.mipmap.icon_beauty_filter_gexing_2, R.string.gexing_2, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_2)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_3, R.mipmap.icon_beauty_filter_gexing_3, R.string.gexing_3, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_4, R.mipmap.icon_beauty_filter_gexing_4, R.string.gexing_4, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_4)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_5, R.mipmap.icon_beauty_filter_gexing_5, R.string.gexing_5, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_5)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_7, R.mipmap.icon_beauty_filter_gexing_7, R.string.gexing_7, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_7)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_10, R.mipmap.icon_beauty_filter_gexing_10, R.string.gexing_10, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_10)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_11, R.mipmap.icon_beauty_filter_gexing_11, R.string.gexing_11, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_11)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.XIAOQINGXIN_1, R.mipmap.icon_beauty_filter_xiaoqingxin_1, R.string.xiaoqingxin_1, getDiskFilterValue(FaceBeautyFilterEnum.XIAOQINGXIN_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.XIAOQINGXIN_3, R.mipmap.icon_beauty_filter_xiaoqingxin_3, R.string.xiaoqingxin_3, getDiskFilterValue(FaceBeautyFilterEnum.XIAOQINGXIN_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.XIAOQINGXIN_4, R.mipmap.icon_beauty_filter_xiaoqingxin_4, R.string.xiaoqingxin_4, getDiskFilterValue(FaceBeautyFilterEnum.XIAOQINGXIN_4)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.XIAOQINGXIN_6, R.mipmap.icon_beauty_filter_xiaoqingxin_6, R.string.xiaoqingxin_6, getDiskFilterValue(FaceBeautyFilterEnum.XIAOQINGXIN_6)));
|
||||
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.HEIBAI_1, R.mipmap.icon_beauty_filter_heibai_1, R.string.heibai_1, getDiskFilterValue(FaceBeautyFilterEnum.HEIBAI_1)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.HEIBAI_2, R.mipmap.icon_beauty_filter_heibai_2, R.string.heibai_2, getDiskFilterValue(FaceBeautyFilterEnum.HEIBAI_2)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.HEIBAI_3, R.mipmap.icon_beauty_filter_heibai_3, R.string.heibai_3, getDiskFilterValue(FaceBeautyFilterEnum.HEIBAI_3)));
|
||||
filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.HEIBAI_4, R.mipmap.icon_beauty_filter_heibai_4, R.string.heibai_4, getDiskFilterValue(FaceBeautyFilterEnum.HEIBAI_4)));
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从磁盘获取所有项滤镜强度
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
private static double getDiskFilterValue(String key) {
|
||||
if (faceBeautyData != null) {
|
||||
return faceBeautyData.filterMap.get(key);
|
||||
} else {
|
||||
return 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String CONFIG_BIAOZHUN = "biaozhun";
|
||||
private static final String CONFIG_HUAJIAO = "huajiao";
|
||||
private static final String CONFIG_KUAISHOU = "kuaishou";
|
||||
private static final String CONFIG_QINGYAN = "qingyan";
|
||||
private static final String CONFIG_SHANGTANG = "shangtang";
|
||||
private static final String CONFIG_YINGKE = "yingke";
|
||||
private static final String CONFIG_ZIJIETIAODONG = "zijietiaodong";
|
||||
|
||||
|
||||
/**
|
||||
* 初始化风格推荐
|
||||
*
|
||||
* @return ArrayList<FaceBeautyBean>
|
||||
*/
|
||||
public static ArrayList<FaceBeautyStyleBean> buildStylesParams() {
|
||||
ArrayList<FaceBeautyStyleBean> params = new ArrayList<>();
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_KUAISHOU, R.drawable.icon_beauty_style_1_selector, R.string.beauty_face_style_1,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_QINGYAN, R.drawable.icon_beauty_style_2_selector, R.string.beauty_face_style_2,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_ZIJIETIAODONG, R.drawable.icon_beauty_style_3_selector, R.string.beauty_face_style_3,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_HUAJIAO, R.drawable.icon_beauty_style_4_selector, R.string.beauty_face_style_4,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_YINGKE, R.drawable.icon_beauty_style_5_selector, R.string.beauty_face_style_5,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_SHANGTANG, R.drawable.icon_beauty_style_6_selector, R.string.beauty_face_style_6,FaceParam.FACE_BEAUTY_STYLE));
|
||||
params.add(new FaceBeautyStyleBean(CONFIG_BIAOZHUN, R.drawable.icon_beauty_style_7_selector, R.string.beauty_face_style_7,FaceParam.FACE_BEAUTY_STYLE));
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 风格对应参数配置
|
||||
*/
|
||||
public static HashMap<String, Runnable> styleParams = new HashMap<String, Runnable>() {
|
||||
{
|
||||
put(CONFIG_KUAISHOU, () -> {
|
||||
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||
model.setFaceShapeIntensity(1.0);
|
||||
model.setColorIntensity(0.5);
|
||||
model.setBlurIntensity(3.6);
|
||||
model.setEyeBrightIntensity(0.35);
|
||||
model.setToothIntensity(0.25);
|
||||
model.setCheekThinningIntensity(0.45);
|
||||
model.setCheekVIntensity(0.08);
|
||||
model.setCheekSmallIntensity(0.05);
|
||||
model.setEyeEnlargingIntensity(0.3);
|
||||
FaceBeautyDataFactory.faceBeauty = model;
|
||||
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
|
||||
});
|
||||
put(CONFIG_QINGYAN, () -> {
|
||||
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||
model.setFaceShapeIntensity(1.0);
|
||||
model.setFilterName(FaceBeautyFilterEnum.ZIRAN_3);
|
||||
model.setFilterIntensity(0.3);
|
||||
model.setColorIntensity(0.4);
|
||||
model.setRedIntensity(0.2);
|
||||
model.setBlurIntensity(3.6);
|
||||
model.setEyeBrightIntensity(0.5);
|
||||
model.setToothIntensity(0.4);
|
||||
model.setCheekThinningIntensity(0.3);
|
||||
model.setNoseIntensity(0.5);
|
||||
model.setEyeEnlargingIntensity(0.25);
|
||||
FaceBeautyDataFactory.faceBeauty = model;
|
||||
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
});
|
||||
put(CONFIG_ZIJIETIAODONG, () -> {
|
||||
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||
model.setFaceShapeIntensity(1.0);
|
||||
model.setColorIntensity(0.4);
|
||||
model.setRedIntensity(0.3);
|
||||
model.setBlurIntensity(2.4);
|
||||
model.setCheekThinningIntensity(0.3);
|
||||
model.setCheekSmallIntensity(0.15);
|
||||
model.setEyeEnlargingIntensity(0.65);
|
||||
model.setNoseIntensity(0.3);
|
||||
FaceBeautyDataFactory.faceBeauty = model;
|
||||
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
});
|
||||
put(CONFIG_HUAJIAO, () -> {
|
||||
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||
model.setFaceShapeIntensity(1.0);
|
||||
model.setColorIntensity(0.7);
|
||||
model.setBlurIntensity(3.9);
|
||||
model.setCheekThinningIntensity(0.3);
|
||||
model.setCheekSmallIntensity(0.05);
|
||||
model.setEyeEnlargingIntensity(0.65);
|
||||
FaceBeautyDataFactory.faceBeauty = model;
|
||||
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
});
|
||||
put(CONFIG_YINGKE, () -> {
|
||||
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||
model.setFaceShapeIntensity(1.0);
|
||||
model.setFilterName(FaceBeautyFilterEnum.FENNEN_2);
|
||||
model.setFilterIntensity(0.5);
|
||||
model.setColorIntensity(0.6);
|
||||
model.setBlurIntensity(3.0);
|
||||
model.setCheekThinningIntensity(0.5);
|
||||
model.setEyeEnlargingIntensity(0.65);
|
||||
FaceBeautyDataFactory.faceBeauty = model;
|
||||
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
});
|
||||
put(CONFIG_SHANGTANG, () -> {
|
||||
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||
model.setFaceShapeIntensity(1.0);
|
||||
model.setFilterName(FaceBeautyFilterEnum.FENNEN_2);
|
||||
model.setFilterIntensity(0.8);
|
||||
model.setColorIntensity(0.7);
|
||||
model.setBlurIntensity(4.2);
|
||||
model.setEyeEnlargingIntensity(0.6);
|
||||
model.setCheekThinningIntensity(0.3);
|
||||
FaceBeautyDataFactory.faceBeauty = model;
|
||||
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
});
|
||||
put(CONFIG_BIAOZHUN, () -> {
|
||||
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||
model.setFaceShapeIntensity(1.0);
|
||||
model.setFilterName(FaceBeautyFilterEnum.ZIRAN_5);
|
||||
model.setFilterIntensity(0.55);
|
||||
model.setColorIntensity(0.2);
|
||||
model.setRedIntensity(0.65);
|
||||
model.setBlurIntensity(3.3);
|
||||
model.setCheekSmallIntensity(0.05);
|
||||
model.setCheekThinningIntensity(0.1);
|
||||
FaceBeautyDataFactory.faceBeauty = model;
|
||||
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 克隆模型
|
||||
*
|
||||
* @param faceBeauty
|
||||
* @return
|
||||
*/
|
||||
public static FaceBeauty clone(FaceBeauty faceBeauty) {
|
||||
FaceBeauty cloneFaceBeauty = new FaceBeauty(new FUBundleData(faceBeauty.getControlBundle().getPath()));
|
||||
/*滤镜*/
|
||||
cloneFaceBeauty.setFilterName(faceBeauty.getFilterName());
|
||||
cloneFaceBeauty.setFilterIntensity(faceBeauty.getFilterIntensity());
|
||||
/*美肤*/
|
||||
cloneFaceBeauty.setBlurIntensity(faceBeauty.getBlurIntensity());
|
||||
cloneFaceBeauty.setEnableHeavyBlur(faceBeauty.getEnableHeavyBlur());
|
||||
cloneFaceBeauty.setEnableSkinDetect(faceBeauty.getEnableSkinDetect());
|
||||
cloneFaceBeauty.setNonSkinBlurIntensity(faceBeauty.getNonSkinBlurIntensity());
|
||||
cloneFaceBeauty.setBlurType(faceBeauty.getBlurType());
|
||||
cloneFaceBeauty.setEnableBlurUseMask(faceBeauty.getEnableBlurUseMask());
|
||||
cloneFaceBeauty.setColorIntensity(faceBeauty.getColorIntensity());
|
||||
cloneFaceBeauty.setRedIntensity(faceBeauty.getRedIntensity());
|
||||
cloneFaceBeauty.setSharpenIntensity(faceBeauty.getSharpenIntensity());
|
||||
cloneFaceBeauty.setEyeBrightIntensity(faceBeauty.getEyeBrightIntensity());
|
||||
cloneFaceBeauty.setToothIntensity(faceBeauty.getToothIntensity());
|
||||
cloneFaceBeauty.setRemovePouchIntensity(faceBeauty.getRemovePouchIntensity());
|
||||
cloneFaceBeauty.setRemoveLawPatternIntensity(faceBeauty.getRemoveLawPatternIntensity());
|
||||
/*美型*/
|
||||
cloneFaceBeauty.setFaceShape(faceBeauty.getFaceShape());
|
||||
cloneFaceBeauty.setFaceShapeIntensity(faceBeauty.getFaceShapeIntensity());
|
||||
cloneFaceBeauty.setCheekThinningIntensity(faceBeauty.getCheekThinningIntensity());
|
||||
cloneFaceBeauty.setCheekVIntensity(faceBeauty.getCheekVIntensity());
|
||||
cloneFaceBeauty.setCheekLongIntensity(faceBeauty.getCheekLongIntensity());
|
||||
cloneFaceBeauty.setCheekCircleIntensity(faceBeauty.getCheekCircleIntensity());
|
||||
cloneFaceBeauty.setCheekNarrowIntensity(faceBeauty.getCheekNarrowIntensity());
|
||||
cloneFaceBeauty.setCheekShortIntensity(faceBeauty.getCheekShortIntensity());
|
||||
cloneFaceBeauty.setCheekSmallIntensity(faceBeauty.getCheekSmallIntensity());
|
||||
cloneFaceBeauty.setCheekBonesIntensity(faceBeauty.getCheekBonesIntensity());
|
||||
cloneFaceBeauty.setLowerJawIntensity(faceBeauty.getLowerJawIntensity());
|
||||
cloneFaceBeauty.setEyeEnlargingIntensity(faceBeauty.getEyeEnlargingIntensity());
|
||||
cloneFaceBeauty.setChinIntensity(faceBeauty.getChinIntensity());
|
||||
cloneFaceBeauty.setForHeadIntensity(faceBeauty.getForHeadIntensity());
|
||||
cloneFaceBeauty.setNoseIntensity(faceBeauty.getNoseIntensity());
|
||||
cloneFaceBeauty.setMouthIntensity(faceBeauty.getMouthIntensity());
|
||||
cloneFaceBeauty.setCanthusIntensity(faceBeauty.getCanthusIntensity());
|
||||
cloneFaceBeauty.setEyeSpaceIntensity(faceBeauty.getEyeSpaceIntensity());
|
||||
cloneFaceBeauty.setEyeRotateIntensity(faceBeauty.getEyeRotateIntensity());
|
||||
cloneFaceBeauty.setLongNoseIntensity(faceBeauty.getLongNoseIntensity());
|
||||
cloneFaceBeauty.setPhiltrumIntensity(faceBeauty.getPhiltrumIntensity());
|
||||
cloneFaceBeauty.setSmileIntensity(faceBeauty.getSmileIntensity());
|
||||
cloneFaceBeauty.setEyeCircleIntensity(faceBeauty.getEyeCircleIntensity());
|
||||
cloneFaceBeauty.setBrowHeightIntensity(faceBeauty.getBrowHeightIntensity());
|
||||
cloneFaceBeauty.setBrowSpaceIntensity(faceBeauty.getBrowSpaceIntensity());
|
||||
cloneFaceBeauty.setChangeFramesIntensity(faceBeauty.getChangeFramesIntensity());
|
||||
return cloneFaceBeauty;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,402 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUColorRGBData;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||
import com.faceunity.core.model.littleMakeup.LightMakeup;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.LightMakeupBean;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||
import com.yunbao.faceunity.utils.FileUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* DESC:轻美妆数据构造
|
||||
* Created on 2021/3/27
|
||||
*/
|
||||
public class LightMakeupSource {
|
||||
|
||||
/**
|
||||
* 构造轻美妆队列
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<LightMakeupBean> buildLightMakeup() {
|
||||
ArrayList<LightMakeupBean> makeups = new ArrayList<>();
|
||||
makeups.add(new LightMakeupBean(R.string.makeup_radio_remove, R.mipmap.icon_control_none, null, 0.0, FaceBeautyFilterEnum.ZIRAN_2, 0.4));
|
||||
/*桃花*/
|
||||
makeups.add(new LightMakeupBean(R.string.makeup_peach_blossom, R.mipmap.icon_light_makeup_peachblossom, "taohua", 0.9, FaceBeautyFilterEnum.FENNEN_3, 0.9));
|
||||
/*西柚*/
|
||||
makeups.add(new LightMakeupBean(R.string.makeup_grapefruit, R.mipmap.icon_light_makeup_grapefruit, "xiyou", 1.0, FaceBeautyFilterEnum.LENGSEDIAO_4, 1.0));
|
||||
/*清透*/
|
||||
makeups.add(new LightMakeupBean(R.string.makeup_clear, R.mipmap.icon_light_makeup_clear, "qingtou", 0.9, FaceBeautyFilterEnum.XIAOQINGXIN_1, 0.9));
|
||||
/*男友*/
|
||||
makeups.add(new LightMakeupBean(R.string.makeup_boyfriend, R.mipmap.icon_light_makeup_boyfriend, "nanyou", 1.0, FaceBeautyFilterEnum.XIAOQINGXIN_3, 1.0));
|
||||
return makeups;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 风格对应参数配置
|
||||
*/
|
||||
public static HashMap<String, Runnable> LightMakeupParams = new HashMap<String, Runnable>() {
|
||||
{
|
||||
put("taohua", () -> {
|
||||
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
|
||||
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_01.path);
|
||||
lightMakeup.setBlusherIntensity(0.9);
|
||||
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_01.path);
|
||||
lightMakeup.setEyeShadowIntensity(0.9);
|
||||
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_01.path);
|
||||
lightMakeup.setEyeBrowIntensity(0.5);
|
||||
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_01.getLipColorRGBData());
|
||||
lightMakeup.setLipIntensity(0.9);
|
||||
FURenderKit.getInstance().setLightMakeup(lightMakeup);
|
||||
});
|
||||
put("xiyou", () -> {
|
||||
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
|
||||
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_23.path);
|
||||
lightMakeup.setBlusherIntensity(1.0);
|
||||
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_21.path);
|
||||
lightMakeup.setEyeShadowIntensity(0.75);
|
||||
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_19.path);
|
||||
lightMakeup.setEyeBrowIntensity(0.6);
|
||||
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_21.getLipColorRGBData());
|
||||
lightMakeup.setLipIntensity(0.8);
|
||||
FURenderKit.getInstance().setLightMakeup(lightMakeup);
|
||||
});
|
||||
put("qingtou", () -> {
|
||||
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
|
||||
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_22.path);
|
||||
lightMakeup.setBlusherIntensity(0.9);
|
||||
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_20.path);
|
||||
lightMakeup.setEyeShadowIntensity(0.65);
|
||||
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_18.path);
|
||||
lightMakeup.setEyeBrowIntensity(0.45);
|
||||
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_20.getLipColorRGBData());
|
||||
lightMakeup.setLipIntensity(0.8);
|
||||
FURenderKit.getInstance().setLightMakeup(lightMakeup);
|
||||
});
|
||||
put("nanyou", () -> {
|
||||
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
|
||||
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_20.path);
|
||||
lightMakeup.setBlusherIntensity(0.8);
|
||||
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_18.path);
|
||||
lightMakeup.setEyeShadowIntensity(0.9);
|
||||
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_16.path);
|
||||
lightMakeup.setEyeBrowIntensity(0.65);
|
||||
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_18.getLipColorRGBData());
|
||||
lightMakeup.setLipIntensity(1.0);
|
||||
FURenderKit.getInstance().setLightMakeup(lightMakeup);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//region 轻美妆效果枚举
|
||||
public enum LightMakeUpEnum {
|
||||
/**
|
||||
* 美妆项,前几项是预置的效果
|
||||
* 排在列表最前方,顺序为桃花妆、雀斑妆、朋克妆(其中朋克没有腮红,3个妆容的眼线、眼睫毛共用1个的)
|
||||
*/
|
||||
// 腮红
|
||||
MAKEUP_BLUSHER_01("MAKEUP_BLUSHER_01", "light_makeup/blusher/mu_blush_01.png", R.mipmap.icon_light_makeup_blush_01, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_02("MAKEUP_BLUSHER_02", "light_makeup/blusher/mu_blush_02.png", R.mipmap.icon_light_makeup_blush_02, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_03("MAKEUP_BLUSHER_03", "light_makeup/blusher/mu_blush_03.png", R.mipmap.icon_light_makeup_blush_03, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_04("MAKEUP_BLUSHER_04", "light_makeup/blusher/mu_blush_04.png", R.mipmap.icon_light_makeup_blush_04, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_05("MAKEUP_BLUSHER_05", "light_makeup/blusher/mu_blush_05.png", R.mipmap.icon_light_makeup_blush_05, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_06("MAKEUP_BLUSHER_06", "light_makeup/blusher/mu_blush_06.png", R.mipmap.icon_light_makeup_blush_06, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_07("MAKEUP_BLUSHER_07", "light_makeup/blusher/mu_blush_07.png", R.mipmap.icon_light_makeup_blush_07, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_08("MAKEUP_BLUSHER_08", "light_makeup/blusher/mu_blush_08.png", R.mipmap.icon_light_makeup_blush_08, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_09("MAKEUP_BLUSHER_09", "light_makeup/blusher/mu_blush_09.png", R.mipmap.icon_light_makeup_blush_09, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_10("MAKEUP_BLUSHER_10", "light_makeup/blusher/mu_blush_10.png", R.mipmap.icon_light_makeup_blush_10, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_11("MAKEUP_BLUSHER_11", "light_makeup/blusher/mu_blush_11.png", R.mipmap.icon_light_makeup_blush_11, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_12("MAKEUP_BLUSHER_12", "light_makeup/blusher/mu_blush_12.png", R.mipmap.icon_light_makeup_blush_12, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_13("MAKEUP_BLUSHER_13", "light_makeup/blusher/mu_blush_13.png", R.mipmap.icon_light_makeup_blush_13, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_14("MAKEUP_BLUSHER_14", "light_makeup/blusher/mu_blush_14.png", R.mipmap.icon_light_makeup_blush_14, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_15("MAKEUP_BLUSHER_15", "light_makeup/blusher/mu_blush_15.png", R.mipmap.icon_light_makeup_blush_15, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_16("MAKEUP_BLUSHER_16", "light_makeup/blusher/mu_blush_16.png", R.mipmap.icon_light_makeup_blush_16, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_17("MAKEUP_BLUSHER_17", "light_makeup/blusher/mu_blush_17.png", R.mipmap.icon_light_makeup_blush_17, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_18("MAKEUP_BLUSHER_18", "light_makeup/blusher/mu_blush_18.png", R.mipmap.icon_light_makeup_blush_18, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_19("MAKEUP_BLUSHER_19", "light_makeup/blusher/mu_blush_19.png", R.mipmap.icon_light_makeup_blush_19, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_20("MAKEUP_BLUSHER_20", "light_makeup/blusher/mu_blush_20.png", R.mipmap.icon_light_makeup_blush_20, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_21("MAKEUP_BLUSHER_21", "light_makeup/blusher/mu_blush_21.png", R.mipmap.icon_light_makeup_blush_21, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_22("MAKEUP_BLUSHER_22", "light_makeup/blusher/mu_blush_22.png", R.mipmap.icon_light_makeup_blush_22, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_23("MAKEUP_BLUSHER_23", "light_makeup/blusher/mu_blush_23.png", R.mipmap.icon_light_makeup_blush_23, R.string.makeup_radio_blusher),
|
||||
|
||||
MAKEUP_BLUSHER_24("MAKEUP_BLUSHER_24", "light_makeup/blusher/mu_blush_24.png", R.mipmap.icon_light_makeup_blush_24, R.string.makeup_radio_blusher),
|
||||
|
||||
// 眉毛
|
||||
MAKEUP_EYEBROW_01("MAKEUP_EYEBROW_01", "light_makeup/eyebrow/mu_eyebrow_01.png", R.mipmap.icon_light_makeup_eyebrow_01, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_02("MAKEUP_EYEBROW_02", "light_makeup/eyebrow/mu_eyebrow_02.png", R.mipmap.icon_light_makeup_eyebrow_02, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_03("MAKEUP_EYEBROW_03", "light_makeup/eyebrow/mu_eyebrow_03.png", R.mipmap.icon_light_makeup_eyebrow_03, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_04("MAKEUP_EYEBROW_04", "light_makeup/eyebrow/mu_eyebrow_04.png", R.mipmap.icon_light_makeup_eyebrow_04, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_05("MAKEUP_EYEBROW_05", "light_makeup/eyebrow/mu_eyebrow_05.png", R.mipmap.icon_light_makeup_eyebrow_05, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_06("MAKEUP_EYEBROW_06", "light_makeup/eyebrow/mu_eyebrow_06.png", R.mipmap.icon_light_makeup_eyebrow_06, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_07("MAKEUP_EYEBROW_07", "light_makeup/eyebrow/mu_eyebrow_07.png", R.mipmap.icon_light_makeup_eyebrow_07, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_08("MAKEUP_EYEBROW_08", "light_makeup/eyebrow/mu_eyebrow_08.png", R.mipmap.icon_light_makeup_eyebrow_08, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_09("MAKEUP_EYEBROW_09", "light_makeup/eyebrow/mu_eyebrow_09.png", R.mipmap.icon_light_makeup_eyebrow_09, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_10("MAKEUP_EYEBROW_10", "light_makeup/eyebrow/mu_eyebrow_10.png", R.mipmap.icon_light_makeup_eyebrow_10, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_11("MAKEUP_EYEBROW_11", "light_makeup/eyebrow/mu_eyebrow_11.png", R.mipmap.icon_light_makeup_eyebrow_11, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_12("MAKEUP_EYEBROW_12", "light_makeup/eyebrow/mu_eyebrow_12.png", R.mipmap.icon_light_makeup_eyebrow_12, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_13("MAKEUP_EYEBROW_13", "light_makeup/eyebrow/mu_eyebrow_13.png", R.mipmap.icon_light_makeup_eyebrow_13, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_14("MAKEUP_EYEBROW_14", "light_makeup/eyebrow/mu_eyebrow_14.png", R.mipmap.icon_light_makeup_eyebrow_14, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_15("MAKEUP_EYEBROW_15", "light_makeup/eyebrow/mu_eyebrow_15.png", R.mipmap.icon_light_makeup_eyebrow_15, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_16("MAKEUP_EYEBROW_16", "light_makeup/eyebrow/mu_eyebrow_16.png", R.mipmap.icon_light_makeup_eyebrow_16, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_17("MAKEUP_EYEBROW_17", "light_makeup/eyebrow/mu_eyebrow_17.png", R.mipmap.icon_light_makeup_eyebrow_17, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_18("MAKEUP_EYEBROW_18", "light_makeup/eyebrow/mu_eyebrow_18.png", R.mipmap.icon_light_makeup_eyebrow_18, R.string.makeup_radio_eyebrow),
|
||||
|
||||
MAKEUP_EYEBROW_19("MAKEUP_EYEBROW_19", "light_makeup/eyebrow/mu_eyebrow_19.png", R.mipmap.icon_light_makeup_eyebrow_19, R.string.makeup_radio_eyebrow),
|
||||
|
||||
// 睫毛
|
||||
MAKEUP_EYELASH_01("MAKEUP_EYELASH_01", "light_makeup/eyelash/mu_eyelash_01.png", R.mipmap.icon_light_makeup_eyelash_01, R.string.makeup_radio_eyelash),
|
||||
|
||||
MAKEUP_EYELASH_02("MAKEUP_EYELASH_02", "light_makeup/eyelash/mu_eyelash_02.png", R.mipmap.icon_light_makeup_eyelash_02, R.string.makeup_radio_eyelash),
|
||||
|
||||
MAKEUP_EYELASH_03("MAKEUP_EYELASH_03", "light_makeup/eyelash/mu_eyelash_03.png", R.mipmap.icon_light_makeup_eyelash_03, R.string.makeup_radio_eyelash),
|
||||
|
||||
MAKEUP_EYELASH_04("MAKEUP_EYELASH_04", "light_makeup/eyelash/mu_eyelash_04.png", R.mipmap.icon_light_makeup_eyelash_04, R.string.makeup_radio_eyelash),
|
||||
|
||||
MAKEUP_EYELASH_05("MAKEUP_EYELASH_05", "light_makeup/eyelash/mu_eyelash_05.png", R.mipmap.icon_light_makeup_eyelash_05, R.string.makeup_radio_eyelash),
|
||||
|
||||
MAKEUP_EYELASH_06("MAKEUP_EYELASH_06", "light_makeup/eyelash/mu_eyelash_06.png", R.mipmap.icon_light_makeup_eyelash_06, R.string.makeup_radio_eyelash),
|
||||
|
||||
MAKEUP_EYELASH_07("MAKEUP_EYELASH_07", "light_makeup/eyelash/mu_eyelash_07.png", R.mipmap.icon_light_makeup_eyelash_07, R.string.makeup_radio_eyelash),
|
||||
|
||||
MAKEUP_EYELASH_08("MAKEUP_EYELASH_08", "light_makeup/eyelash/mu_eyelash_08.png", R.mipmap.icon_light_makeup_eyelash_08, R.string.makeup_radio_eyelash),
|
||||
|
||||
// 眼线
|
||||
MAKEUP_EYELINER_01("MAKEUP_EYELINER_01", "light_makeup/eyeliner/mu_eyeliner_01.png", R.mipmap.icon_light_makeup_eyeliner_01, R.string.makeup_radio_eye_liner),
|
||||
|
||||
MAKEUP_EYELINER_02("MAKEUP_EYELINER_02", "light_makeup/eyeliner/mu_eyeliner_02.png", R.mipmap.icon_light_makeup_eyeliner_02, R.string.makeup_radio_eye_liner),
|
||||
|
||||
MAKEUP_EYELINER_03("MAKEUP_EYELINER_03", "light_makeup/eyeliner/mu_eyeliner_03.png", R.mipmap.icon_light_makeup_eyeliner_03, R.string.makeup_radio_eye_liner),
|
||||
|
||||
MAKEUP_EYELINER_04("MAKEUP_EYELINER_04", "light_makeup/eyeliner/mu_eyeliner_04.png", R.mipmap.icon_light_makeup_eyeliner_04, R.string.makeup_radio_eye_liner),
|
||||
|
||||
MAKEUP_EYELINER_05("MAKEUP_EYELINER_05", "light_makeup/eyeliner/mu_eyeliner_05.png", R.mipmap.icon_light_makeup_eyeliner_05, R.string.makeup_radio_eye_liner),
|
||||
|
||||
MAKEUP_EYELINER_06("MAKEUP_EYELINER_06", "light_makeup/eyeliner/mu_eyeliner_06.png", R.mipmap.icon_light_makeup_eyeliner_06, R.string.makeup_radio_eye_liner),
|
||||
|
||||
MAKEUP_EYELINER_07("MAKEUP_EYELINER_07", "light_makeup/eyeliner/mu_eyeliner_07.png", R.mipmap.icon_light_makeup_eyeliner_07, R.string.makeup_radio_eye_liner),
|
||||
|
||||
MAKEUP_EYELINER_08("MAKEUP_EYELINER_08", "light_makeup/eyeliner/mu_eyeliner_08.png", R.mipmap.icon_light_makeup_eyeliner_08, R.string.makeup_radio_eye_liner),
|
||||
|
||||
// 美瞳
|
||||
MAKEUP_EYEPUPIL_01("MAKEUP_EYEPUPIL_01", "light_makeup/eyepupil/mu_eyepupil_01.png", R.mipmap.icon_light_makeup_eyepupil_01, R.string.makeup_radio_contact_lens),
|
||||
|
||||
MAKEUP_EYEPUPIL_02("MAKEUP_EYEPUPIL_02", "light_makeup/eyepupil/mu_eyepupil_02.png", R.mipmap.icon_light_makeup_eyepupil_02, R.string.makeup_radio_contact_lens),
|
||||
|
||||
MAKEUP_EYEPUPIL_03("MAKEUP_EYEPUPIL_03", "light_makeup/eyepupil/mu_eyepupil_03.png", R.mipmap.icon_light_makeup_eyepupil_03, R.string.makeup_radio_contact_lens),
|
||||
|
||||
MAKEUP_EYEPUPIL_04("MAKEUP_EYEPUPIL_04", "light_makeup/eyepupil/mu_eyepupil_04.png", R.mipmap.icon_light_makeup_eyepupil_04, R.string.makeup_radio_contact_lens),
|
||||
|
||||
MAKEUP_EYEPUPIL_05("MAKEUP_EYEPUPIL_05", "light_makeup/eyepupil/mu_eyepupil_05.png", R.mipmap.icon_light_makeup_eyepupil_05, R.string.makeup_radio_contact_lens),
|
||||
|
||||
MAKEUP_EYEPUPIL_06("MAKEUP_EYEPUPIL_06", "light_makeup/eyepupil/mu_eyepupil_06.png", R.mipmap.icon_light_makeup_eyepupil_06, R.string.makeup_radio_contact_lens),
|
||||
|
||||
MAKEUP_EYEPUPIL_07("MAKEUP_EYEPUPIL_07", "light_makeup/eyepupil/mu_eyepupil_07.png", R.mipmap.icon_light_makeup_eyepupil_07, R.string.makeup_radio_contact_lens),
|
||||
|
||||
MAKEUP_EYEPUPIL_08("MAKEUP_EYEPUPIL_08", "light_makeup/eyepupil/mu_eyepupil_08.png", R.mipmap.icon_light_makeup_eyepupil_08, R.string.makeup_radio_contact_lens),
|
||||
|
||||
MAKEUP_EYEPUPIL_09("MAKEUP_EYEPUPIL_09", "light_makeup/eyepupil/mu_eyepupil_09.png", R.mipmap.icon_light_makeup_eyepupil_09, R.string.makeup_radio_contact_lens),
|
||||
|
||||
// 眼影
|
||||
MAKEUP_EYE_SHADOW_01("MAKEUP_EYESHADOW_01", "light_makeup/eyeshadow/mu_eyeshadow_01.png", R.mipmap.icon_light_makeup_eyeshadow_01, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_02("MAKEUP_EYESHADOW_02", "light_makeup/eyeshadow/mu_eyeshadow_02.png", R.mipmap.icon_light_makeup_eyeshadow_02, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_03("MAKEUP_EYESHADOW_03", "light_makeup/eyeshadow/mu_eyeshadow_03.png", R.mipmap.icon_light_makeup_eyeshadow_03, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_04("MAKEUP_EYESHADOW_04", "light_makeup/eyeshadow/mu_eyeshadow_04.png", R.mipmap.icon_light_makeup_eyeshadow_04, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_05("MAKEUP_EYESHADOW_05", "light_makeup/eyeshadow/mu_eyeshadow_05.png", R.mipmap.icon_light_makeup_eyeshadow_05, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_06("MAKEUP_EYESHADOW_06", "light_makeup/eyeshadow/mu_eyeshadow_06.png", R.mipmap.icon_light_makeup_eyeshadow_06, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_07("MAKEUP_EYESHADOW_07", "light_makeup/eyeshadow/mu_eyeshadow_07.png", R.mipmap.icon_light_makeup_eyeshadow_07, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_08("MAKEUP_EYESHADOW_08", "light_makeup/eyeshadow/mu_eyeshadow_08.png", R.mipmap.icon_light_makeup_eyeshadow_08, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_09("MAKEUP_EYESHADOW_09", "light_makeup/eyeshadow/mu_eyeshadow_09.png", R.mipmap.icon_light_makeup_eyeshadow_09, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_10("MAKEUP_EYESHADOW_10", "light_makeup/eyeshadow/mu_eyeshadow_10.png", R.mipmap.icon_light_makeup_eyeshadow_10, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_11("MAKEUP_EYESHADOW_11", "light_makeup/eyeshadow/mu_eyeshadow_11.png", R.mipmap.icon_light_makeup_eyeshadow_11, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_12("MAKEUP_EYESHADOW_12", "light_makeup/eyeshadow/mu_eyeshadow_12.png", R.mipmap.icon_light_makeup_eyeshadow_12, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_13("MAKEUP_EYESHADOW_13", "light_makeup/eyeshadow/mu_eyeshadow_13.png", R.mipmap.icon_light_makeup_eyeshadow_13, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_14("MAKEUP_EYESHADOW_14", "light_makeup/eyeshadow/mu_eyeshadow_14.png", R.mipmap.icon_light_makeup_eyeshadow_14, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_15("MAKEUP_EYESHADOW_15", "light_makeup/eyeshadow/mu_eyeshadow_15.png", R.mipmap.icon_light_makeup_eyeshadow_15, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_16("MAKEUP_EYESHADOW_16", "light_makeup/eyeshadow/mu_eyeshadow_16.png", R.mipmap.icon_light_makeup_eyeshadow_16, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_17("MAKEUP_EYESHADOW_17", "light_makeup/eyeshadow/mu_eyeshadow_17.png", R.mipmap.icon_light_makeup_eyeshadow_17, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_18("MAKEUP_EYESHADOW_18", "light_makeup/eyeshadow/mu_eyeshadow_18.png", R.mipmap.icon_light_makeup_eyeshadow_18, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_19("MAKEUP_EYESHADOW_19", "light_makeup/eyeshadow/mu_eyeshadow_19.png", R.mipmap.icon_light_makeup_eyeshadow_19, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_20("MAKEUP_EYESHADOW_20", "light_makeup/eyeshadow/mu_eyeshadow_20.png", R.mipmap.icon_light_makeup_eyeshadow_20, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_21("MAKEUP_EYESHADOW_21", "light_makeup/eyeshadow/mu_eyeshadow_21.png", R.mipmap.icon_light_makeup_eyeshadow_21, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
MAKEUP_EYE_SHADOW_22("MAKEUP_EYESHADOW_22", "light_makeup/eyeshadow/mu_eyeshadow_22.png", R.mipmap.icon_light_makeup_eyeshadow_22, R.string.makeup_radio_eye_shadow),
|
||||
|
||||
// 口红
|
||||
MAKEUP_LIPSTICK_01("MAKEUP_LIPSTICK_01", "light_makeup/lipstick/mu_lip_01.json", R.mipmap.icon_light_makeup_lip_01, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_02("MAKEUP_LIPSTICK_02", "light_makeup/lipstick/mu_lip_02.json", R.mipmap.icon_light_makeup_lip_02, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_03("MAKEUP_LIPSTICK_03", "light_makeup/lipstick/mu_lip_03.json", R.mipmap.icon_light_makeup_lip_03, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_10("MAKEUP_LIPSTICK_10", "light_makeup/lipstick/mu_lip_10.json", R.mipmap.icon_light_makeup_lip_10, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_11("MAKEUP_LIPSTICK_11", "light_makeup/lipstick/mu_lip_11.json", R.mipmap.icon_light_makeup_lip_12, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_12("MAKEUP_LIPSTICK_12", "light_makeup/lipstick/mu_lip_12.json", R.mipmap.icon_light_makeup_lip_12, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_13("MAKEUP_LIPSTICK_13", "light_makeup/lipstick/mu_lip_13.json", R.mipmap.icon_light_makeup_lip_13, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_14("MAKEUP_LIPSTICK_14", "light_makeup/lipstick/mu_lip_14.json", R.mipmap.icon_light_makeup_lip_14, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_15("MAKEUP_LIPSTICK_15", "light_makeup/lipstick/mu_lip_15.json", R.mipmap.icon_light_makeup_lip_15, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_16("MAKEUP_LIPSTICK_16", "light_makeup/lipstick/mu_lip_16.json", R.mipmap.icon_light_makeup_lip_16, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_17("MAKEUP_LIPSTICK_17", "light_makeup/lipstick/mu_lip_17.json", R.mipmap.icon_light_makeup_lip_17, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_18("MAKEUP_LIPSTICK_18", "light_makeup/lipstick/mu_lip_18.json", R.mipmap.icon_light_makeup_lip_18, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_19("MAKEUP_LIPSTICK_19", "light_makeup/lipstick/mu_lip_19.json", R.mipmap.icon_light_makeup_lip_19, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_20("MAKEUP_LIPSTICK_20", "light_makeup/lipstick/mu_lip_20.json", R.mipmap.icon_light_makeup_lip_20, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_21("MAKEUP_LIPSTICK_21", "light_makeup/lipstick/mu_lip_21.json", R.mipmap.icon_light_makeup_lip_21, R.string.makeup_radio_lipstick),
|
||||
|
||||
MAKEUP_LIPSTICK_22("MAKEUP_LIPSTICK_22", "light_makeup/lipstick/mu_lip_22.json", R.mipmap.icon_light_makeup_lip_22, R.string.makeup_radio_lipstick);
|
||||
|
||||
|
||||
private final String key;
|
||||
private final String path;
|
||||
private final int iconRes;
|
||||
private final int strRes;
|
||||
|
||||
LightMakeUpEnum(String key, String path, int iconRes, int strRes) {
|
||||
this.key = key;
|
||||
this.path = path;
|
||||
this.iconRes = iconRes;
|
||||
this.strRes = strRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取口红颜色
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public FUColorRGBData getLipColorRGBData() {
|
||||
double[] colorArray = loadRgbaColorFromLocal(FaceUnityData.mApplication, path);
|
||||
if (colorArray != null && colorArray.length == 4) {
|
||||
return new FUColorRGBData(colorArray[0] * 255, colorArray[1] * 255, colorArray[2] * 255, colorArray[3] * 255);
|
||||
}
|
||||
return new FUColorRGBData(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
/**
|
||||
* 读取 RGBA 颜色数据
|
||||
*
|
||||
* @param context
|
||||
* @param path path
|
||||
* @return
|
||||
*/
|
||||
public static double[] loadRgbaColorFromLocal(Context context, String path) {
|
||||
InputStream inputStream = FileUtils.readInputStreamByPath(context, path);
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
byte[] bytes = new byte[inputStream.available()];
|
||||
inputStream.read(bytes);
|
||||
JSONObject jsonObject = new JSONObject(new String(bytes));
|
||||
JSONArray jsonArray = jsonObject.optJSONArray("rgba");
|
||||
double[] colorArray = new double[jsonArray.length()];
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
colorArray[i] = jsonArray.optDouble(i);
|
||||
}
|
||||
return colorArray;
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,489 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.faceunity.core.controller.makeup.MakeupParam;
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUColorRGBData;
|
||||
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||
import com.faceunity.core.model.makeup.Makeup;
|
||||
import com.faceunity.core.utils.FileUtils;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.MakeupCombinationBean;
|
||||
import com.yunbao.faceunity.entity.MakeupCustomBean;
|
||||
import com.yunbao.faceunity.entity.MakeupCustomClassBean;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||
import com.yunbao.faceunity.entity.MakeupCombinationBean.TypeEnum;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DESC:美妆数据构造
|
||||
* Created on 2021/3/28
|
||||
*/
|
||||
public class MakeupSource {
|
||||
public static String BUNDLE_FACE_MAKEUP = "graphics" + File.separator + "face_makeup.bundle";
|
||||
|
||||
|
||||
//region 组合妆容
|
||||
|
||||
/**
|
||||
* 构造美妆组合妆容配置
|
||||
*
|
||||
* @return ArrayList<MakeupCombinationBean>
|
||||
*/
|
||||
public static ArrayList<MakeupCombinationBean> buildCombinations() {
|
||||
ArrayList<MakeupCombinationBean> combinations = new ArrayList<MakeupCombinationBean>();
|
||||
String jsonDir = FaceUnityConfig.MAKEUP_RESOURCE_JSON_DIR;
|
||||
String bundleDir = FaceUnityConfig.MAKEUP_RESOURCE_COMBINATION_BUNDLE_DIR;
|
||||
combinations.add(new MakeupCombinationBean("origin", TypeEnum.TYPE_NONE, R.mipmap.icon_control_none, R.string.makeup_radio_remove, null, "", FaceBeautyFilterEnum.ZIRAN_2, 1.0,0.0,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("diadiatu", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_diadiatu, R.string.makeup_combination_diadiatu, bundleDir + "diadiatu.bundle", jsonDir + "diadiatu.json", FaceBeautyFilterEnum.ORIGIN, 0.68,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("dongling", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_freezing_age, R.string.makeup_combination_dongling, bundleDir + "dongling.bundle", jsonDir + "dongling.json", FaceBeautyFilterEnum.ORIGIN, 0.68,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("guofeng", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_guo_feng, R.string.makeup_combination_guofeng, bundleDir + "guofeng.bundle", jsonDir + "guofeng.json", FaceBeautyFilterEnum.ORIGIN, 0.6,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("hunxie", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_mixed_race, R.string.makeup_combination_hunxie, bundleDir + "hunxie.bundle", jsonDir + "hunxie.json", FaceBeautyFilterEnum.ORIGIN, 0.6,FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("jianling", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_age, R.string.makeup_combination_jianling, bundleDir + "jianling.bundle", jsonDir + "jianling.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("nuandong", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_warm_winter, R.string.makeup_combination_nuandong, bundleDir + "nuandong.bundle", jsonDir + "nuandong.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("hongfeng", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_red_maple, R.string.makeup_combination_hongfeng, bundleDir + "hongfeng.bundle", jsonDir + "hongfeng.json", FaceBeautyFilterEnum.ZHIGANHUI_3, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("rose", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_rose, R.string.makeup_combination_rose, bundleDir + "rose.bundle", jsonDir + "rose.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("shaonv", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_girl, R.string.makeup_combination_shaonv, bundleDir + "shaonv.bundle", jsonDir + "shaonv.json", FaceBeautyFilterEnum.ZHIGANHUI_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("ziyun", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_purple_rhyme, R.string.makeup_combination_ziyun, bundleDir + "ziyun.bundle", jsonDir + "ziyun.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("yanshimao", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_bored_cat, R.string.makeup_combination_yanshimao, bundleDir + "yanshimao.bundle", jsonDir + "yanshimao.json", FaceBeautyFilterEnum.ZHIGANHUI_5, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("renyu", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_mermaid, R.string.makeup_combination_renyu, bundleDir + "renyu.bundle", jsonDir + "renyu.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("chuqiu", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_early_autumn, R.string.makeup_combination_chuqiu, bundleDir + "chuqiu.bundle", jsonDir + "chuqiu.json", FaceBeautyFilterEnum.ZHIGANHUI_6, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("qianzhihe", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_paper_cranes, R.string.makeup_combination_qianzhihe, bundleDir + "qianzhihe.bundle", jsonDir + "qianzhihe.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("chaomo", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_supermodel, R.string.makeup_combination_chaomo, bundleDir + "chaomo.bundle", jsonDir + "chaomo.json", FaceBeautyFilterEnum.ZHIGANHUI_7, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("chuju", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_daisy, R.string.makeup_combination_chuju, bundleDir + "chuju.bundle", jsonDir + "chuju.json", FaceBeautyFilterEnum.ZHIGANHUI_8, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("gangfeng", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_harbour_wind, R.string.makeup_combination_gangfeng, bundleDir + "gangfeng.bundle", jsonDir + "gangfeng.json", FaceBeautyFilterEnum.ZIRAN_8, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("xinggan", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_sexy, R.string.makeup_combination_sexy, bundleDir + "xinggan.bundle", jsonDir + "xinggan.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("tianmei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_sweet, R.string.makeup_combination_sweet, bundleDir + "tianmei.bundle", jsonDir + "tianmei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("linjia", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_neighbor_girl, R.string.makeup_combination_neighbor, bundleDir + "linjia.bundle", jsonDir + "linjia.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("oumei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_occident, R.string.makeup_combination_occident, bundleDir + "oumei.bundle", jsonDir + "oumei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
combinations.add(new MakeupCombinationBean("wumei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_charming, R.string.makeup_combination_charming, bundleDir + "wumei.bundle", jsonDir + "wumei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP));
|
||||
return combinations;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造美妆模型
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Makeup getMakeupModel(MakeupCombinationBean bean) {
|
||||
Makeup makeupModel;
|
||||
if (TypeEnum.TYPE_THEME_MAIN == bean.getType() && bean.getBundlePath() != null && bean.getBundlePath().trim().length() > 0) {
|
||||
makeupModel = new Makeup(new FUBundleData(bean.getBundlePath()));
|
||||
//新的组合妆容设置滤镜scale
|
||||
makeupModel.setCurrentFilterScale(bean.getFilterScale());
|
||||
} else {
|
||||
makeupModel = new Makeup(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_MAKEUP));
|
||||
}
|
||||
|
||||
if (bean.getKey().equals("origin")) {
|
||||
return makeupModel;
|
||||
}
|
||||
|
||||
if ((TypeEnum.TYPE_THEME_SUB == bean.getType() || TypeEnum.TYPE_DAILY == bean.getType()) && bean.getBundlePath() != null && bean.getBundlePath().trim().length() > 0)
|
||||
makeupModel.setCombinedConfig(new FUBundleData(bean.getBundlePath()));
|
||||
|
||||
makeupModel.setMakeupIntensity(bean.getIntensity());
|
||||
if (bean.getJsonPathParams() == null) {
|
||||
bean.setJsonPathParams(getLocalParams(bean.getJsonPath()));
|
||||
}
|
||||
LinkedHashMap<String, Object> params = bean.getJsonPathParams();
|
||||
|
||||
//支持自定义,所以需要知道选中了妆容的哪一些项
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
String key = entry.getKey();
|
||||
if (value instanceof double[] && ((double[]) value).length > 4) {
|
||||
int count = ((double[]) value).length / 4;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i == 0) {
|
||||
if (makeupSetMapping.containsKey(key)) {
|
||||
makeupSetMapping.get(key).setValue(makeupModel, value);
|
||||
}
|
||||
} else {
|
||||
if (makeupSetMapping.containsKey(key + (i + 1))) {
|
||||
makeupSetMapping.get(key + (i + 1)).setValue(makeupModel, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (makeupSetMapping.containsKey(key)) {
|
||||
makeupSetMapping.get(key).setValue(makeupModel, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return makeupModel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 读取本地参数配置
|
||||
*
|
||||
* @param jsonPath String json文件路径
|
||||
* @return LinkedHashMap<String, Any>
|
||||
*/
|
||||
private static LinkedHashMap<String, Object> getLocalParams(String jsonPath) {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap(32);
|
||||
map.put(MakeupParam.LIP_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.EYE_LINER_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.BLUSHER_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.PUPIL_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.EYE_BROW_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.EYE_SHADOW_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.EYELASH_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.FOUNDATION_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.HIGHLIGHT_INTENSITY, 0.0);
|
||||
map.put(MakeupParam.SHADOW_INTENSITY, 0.0);
|
||||
LinkedHashMap<String, Object> jsonParam = FileUtils.INSTANCE.loadParamsFromLocal(FaceUnityData.mApplication, jsonPath);
|
||||
for (Map.Entry<String, Object> entry : jsonParam.entrySet()) {
|
||||
if (entry.getKey().startsWith("tex_")) {
|
||||
if (entry.getValue() instanceof String && ((String) entry.getValue()).contains(".bundle")) {
|
||||
map.put(entry.getKey(), FaceUnityConfig.MAKEUP_RESOURCE_ITEM_BUNDLE_DIR + entry.getValue());
|
||||
}
|
||||
} else {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
interface MakeupSetParam {
|
||||
/**
|
||||
* 模型属性赋值
|
||||
*
|
||||
* @param makeup
|
||||
* @param value
|
||||
*/
|
||||
void setValue(Makeup makeup, Object value);
|
||||
|
||||
}
|
||||
|
||||
/*美妆映射模型*/
|
||||
public static HashMap<String, MakeupSetParam> makeupSetMapping = new HashMap<String, MakeupSetParam>() {
|
||||
{
|
||||
put(MakeupParam.LIP_TYPE, (makeup, value) -> makeup.setLipType((int) value));
|
||||
put(MakeupParam.IS_TWO_COLOR, (makeup, value) -> makeup.setEnableTwoLipColor((int) value == 1));
|
||||
put(MakeupParam.MAKEUP_LIP_HIGH_LIGHT_ENABLE, (makeup, value) -> makeup.setLipHighLightEnable((int) value == 1));
|
||||
put(MakeupParam.MAKEUP_LIP_HIGH_LIGHT_STRENGTH, (makeup, value) -> makeup.setLipHighLightStrength((double) value));
|
||||
put(MakeupParam.BROW_WARP, (makeup, value) -> makeup.setEnableBrowWarp((double) value == 1.0));
|
||||
put(MakeupParam.BROW_WARP_TYPE, (makeup, value) -> makeup.setBrowWarpType((int) value));
|
||||
/*强度*/
|
||||
put(MakeupParam.MAKEUP_INTENSITY, (makeup, value) -> makeup.setMakeupIntensity((double) value));
|
||||
put(MakeupParam.LIP_INTENSITY, (makeup, value) -> makeup.setLipIntensity((double) value));
|
||||
put(MakeupParam.EYE_LINER_INTENSITY, (makeup, value) -> makeup.setEyeLineIntensity((double) value));
|
||||
put(MakeupParam.BLUSHER_INTENSITY, (makeup, value) -> makeup.setBlusherIntensity((double) value));
|
||||
put(MakeupParam.PUPIL_INTENSITY, (makeup, value) -> makeup.setPupilIntensity((double) value));
|
||||
put(MakeupParam.EYE_BROW_INTENSITY, (makeup, value) -> makeup.setEyeBrowIntensity((double) value));
|
||||
put(MakeupParam.EYE_SHADOW_INTENSITY, (makeup, value) -> makeup.setEyeShadowIntensity((double) value));
|
||||
put(MakeupParam.EYELASH_INTENSITY, (makeup, value) -> makeup.setEyeLashIntensity((double) value));
|
||||
put(MakeupParam.FOUNDATION_INTENSITY, (makeup, value) -> makeup.setFoundationIntensity((double) value));
|
||||
put(MakeupParam.HIGHLIGHT_INTENSITY, (makeup, value) -> makeup.setHeightLightIntensity((double) value));
|
||||
put(MakeupParam.SHADOW_INTENSITY, (makeup, value) -> makeup.setShadowIntensity((double) value));
|
||||
/*子项妆容贴图*/
|
||||
put(MakeupParam.TEX_LIP, (makeup, value) -> makeup.setLipBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_BROW, (makeup, value) -> makeup.setEyeBrowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_SHADOW, (makeup, value) -> makeup.setEyeShadowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_SHADOW2, (makeup, value) -> makeup.setEyeShadowBundle2(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_SHADOW3, (makeup, value) -> makeup.setEyeShadowBundle3(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_SHADOW4, (makeup, value) -> makeup.setEyeShadowBundle4(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_PUPIL, (makeup, value) -> makeup.setPupilBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_LASH, (makeup, value) -> makeup.setEyeLashBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_EYE_LINER, (makeup, value) -> makeup.setEyeLinerBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_BLUSHER, (makeup, value) -> makeup.setBlusherBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_BLUSHER2, (makeup, value) -> makeup.setBlusherBundle2(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_FOUNDATION, (makeup, value) -> makeup.setFoundationBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_HIGH_LIGHT, (makeup, value) -> makeup.setHighLightBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
put(MakeupParam.TEX_SHADOW, (makeup, value) -> makeup.setShadowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null));
|
||||
/*子项妆容颜色*/
|
||||
put(MakeupParam.MAKEUP_LIP_COLOR, (makeup, value) -> makeup.setLipColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_LIP_COLOR_V2, (makeup, value) -> makeup.setLipColorV2(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_LIP_COLOR2, (makeup, value) -> makeup.setLipColor2(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_LINER_COLOR, (makeup, value) -> makeup.setEyeLinerColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_LASH_COLOR, (makeup, value) -> makeup.setEyeLashColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_BLUSHER_COLOR, (makeup, value) -> makeup.setBlusherColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_BLUSHER_COLOR2, (makeup, value) -> makeup.setBlusherColor2(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_FOUNDATION_COLOR, (makeup, value) -> makeup.setFoundationColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_HIGH_LIGHT_COLOR, (makeup, value) -> makeup.setHighLightColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_SHADOW_COLOR, (makeup, value) -> makeup.setShadowColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_BROW_COLOR, (makeup, value) -> makeup.setEyeBrowColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_PUPIL_COLOR, (makeup, value) -> makeup.setPupilColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR, (makeup, value) -> makeup.setEyeShadowColor(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR2, (makeup, value) -> makeup.setEyeShadowColor2(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR3, (makeup, value) -> makeup.setEyeShadowColor3(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR4, (makeup, value) -> makeup.setEyeShadowColor4(buildFUColorRGBData(value)));
|
||||
put(MakeupParam.MAKEUP_EYE_BROW_COLOR, (makeup, value) -> makeup.setEyeBrowColor(buildFUColorRGBData(value)));
|
||||
/* 图层混合模式 */
|
||||
put(MakeupParam.BLEND_TEX_EYE_SHADOW, (makeup, value) -> makeup.setEyeShadowTexBlend((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_SHADOW2, (makeup, value) -> makeup.setEyeShadowTexBlend2((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_SHADOW3, (makeup, value) -> makeup.setEyeShadowTexBlend3((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_SHADOW4, (makeup, value) -> makeup.setEyeShadowTexBlend4((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_LASH, (makeup, value) -> makeup.setEyeLashTexBlend((int) value));
|
||||
put(MakeupParam.BLEND_TEX_EYE_LINER, (makeup, value) -> makeup.setEyeLinerTexBlend((int) value));
|
||||
put(MakeupParam.BLEND_TEX_BLUSHER, (makeup, value) -> makeup.setBlusherTexBlend((int) value));
|
||||
put(MakeupParam.BLEND_TEX_BLUSHER2, (makeup, value) -> makeup.setBlusherTexBlend2((int) value));
|
||||
put(MakeupParam.BLEND_TEX_PUPIL, (makeup, value) -> makeup.setPupilTexBlend((int) value));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 构造颜色模型
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
public static FUColorRGBData buildFUColorRGBData(Object object) {
|
||||
if (object instanceof double[]) {
|
||||
double[] array = (double[]) object;
|
||||
if (array.length == 4) {
|
||||
return new FUColorRGBData(array[0] * 255, array[1] * 255, array[2] * 255, array[3] * 255);
|
||||
}
|
||||
}
|
||||
return new FUColorRGBData(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
//endregion 组合妆容
|
||||
|
||||
// region 子妆容
|
||||
|
||||
/* 粉底 */
|
||||
public static String FACE_MAKEUP_TYPE_FOUNDATION = "FOUNDATION";
|
||||
/* 口红 */
|
||||
public static String FACE_MAKEUP_TYPE_LIP_STICK = "STICK";
|
||||
/* 腮红 */
|
||||
public static String FACE_MAKEUP_TYPE_BLUSHER = "BLUSHER";
|
||||
/* 眉毛 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_BROW = "EYE_BROW";
|
||||
/* 眼影 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_SHADOW = "EYE_SHADOW";
|
||||
/* 眼线 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_LINER = "EYE_LINER";
|
||||
/* 睫毛 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_LASH = "EYE_LASH";
|
||||
/* 高光 */
|
||||
public static String FACE_MAKEUP_TYPE_HIGH_LIGHT = "HIGHLIGHT";
|
||||
/* 阴影 */
|
||||
public static String FACE_MAKEUP_TYPE_SHADOW = "SHADOW";
|
||||
/* 美瞳 */
|
||||
public static String FACE_MAKEUP_TYPE_EYE_PUPIL = "EYE_PUPIL";
|
||||
|
||||
/**
|
||||
* 构造美妆子项类别
|
||||
*/
|
||||
public static ArrayList<MakeupCustomClassBean> buildCustomClasses() {
|
||||
ArrayList<MakeupCustomClassBean> classes = new ArrayList();
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_foundation, FACE_MAKEUP_TYPE_FOUNDATION,FaceParam.FACE_MAKEUP_TYPE_FOUNDATION));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_lipstick, FACE_MAKEUP_TYPE_LIP_STICK,FaceParam.FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_blusher, FACE_MAKEUP_TYPE_BLUSHER,FaceParam.FACE_MAKEUP_TYPE_BLUSHER));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eyebrow, FACE_MAKEUP_TYPE_EYE_BROW,FaceParam.FACE_MAKEUP_TYPE_EYE_BROW));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eye_shadow, FACE_MAKEUP_TYPE_EYE_SHADOW,FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eye_liner, FACE_MAKEUP_TYPE_EYE_LINER,FaceParam.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eyelash, FACE_MAKEUP_TYPE_EYE_LASH,FaceParam.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_highlight, FACE_MAKEUP_TYPE_HIGH_LIGHT,FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_shadow, FACE_MAKEUP_TYPE_SHADOW,FaceParam.FACE_MAKEUP_TYPE_SHADOW));
|
||||
classes.add(new MakeupCustomClassBean(R.string.makeup_radio_contact_lens, FACE_MAKEUP_TYPE_EYE_PUPIL,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
return classes;
|
||||
}
|
||||
|
||||
public static LinkedHashMap<String,ArrayList<MakeupCustomBean>> buildCustomItemParams(){
|
||||
return buildCustomItemParams(MakeupSource.buildMakeUpColorMap());
|
||||
}
|
||||
/**
|
||||
* 美妆单项妆容配置参数
|
||||
*
|
||||
* @return LinkedHashMap<String, ArrayList < MakeupCustomBean>>
|
||||
*/
|
||||
public static LinkedHashMap<String, ArrayList<MakeupCustomBean>> buildCustomItemParams(LinkedHashMap<String, ArrayList<double[]>> colorMap) {
|
||||
LinkedHashMap<String, ArrayList<MakeupCustomBean>> mCustomItems = new LinkedHashMap<>();
|
||||
/*粉底*/
|
||||
ArrayList<MakeupCustomBean> makeupItems = new ArrayList(6);
|
||||
makeupItems.add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_FOUNDATION));
|
||||
ArrayList<double[]> list = colorMap.get("color_mu_style_foundation_01");
|
||||
for (int i = 3; i < 8; i++) {
|
||||
double[] colors = list.get(i);
|
||||
ColorDrawable drawable = new ColorDrawable(Color.argb((int) (colors[3] * 255), (int) (colors[0] * 255), (int) (colors[1] * 255), (int) (colors[2] * 255)));
|
||||
makeupItems.add(new MakeupCustomBean(0, drawable,FaceParam.FACE_MAKEUP_TYPE_FOUNDATION));
|
||||
}
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_FOUNDATION, makeupItems);
|
||||
|
||||
|
||||
/*口红*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_LIP_STICK, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_fog, getDrawable(R.mipmap.icon_makeup_lip_fog), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_moist1, getDrawable(R.mipmap.icon_makeup_lip_moist), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_moist2, getDrawable(R.mipmap.icon_makeup_lip_water), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_pearl, getDrawable(R.mipmap.icon_makeup_lip_pearl), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
add(new MakeupCustomBean(R.string.makeup_lip_bitelip, getDrawable(R.mipmap.icon_makeup_lip_beitelip), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
}
|
||||
});
|
||||
|
||||
/*腮红*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_BLUSHER, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_BLUSHER));
|
||||
add(new MakeupCustomBean(R.string.makeup_blusher_apple, getDrawable(R.mipmap.icon_makeup_blush_01), colorMap.get("color_mu_style_blush_01"),FaceParam.FACE_MAKEUP_TYPE_BLUSHER));
|
||||
add(new MakeupCustomBean(R.string.makeup_blusher_fan, getDrawable(R.mipmap.icon_makeup_blush_02), colorMap.get("color_mu_style_blush_02"),FaceParam.FACE_MAKEUP_TYPE_BLUSHER));
|
||||
add(new MakeupCustomBean(R.string.makeup_blusher_eye_corner, getDrawable(R.mipmap.icon_makeup_blush_03), colorMap.get("color_mu_style_blush_03"),FaceParam.FACE_MAKEUP_TYPE_BLUSHER));
|
||||
add(new MakeupCustomBean(R.string.makeup_blusher_slight_drunk, getDrawable(R.mipmap.icon_makeup_blush_04), colorMap.get("color_mu_style_blush_04"),FaceParam.FACE_MAKEUP_TYPE_BLUSHER));
|
||||
}
|
||||
});
|
||||
/*眉毛*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_BROW, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyebrow_willow, getDrawable(R.mipmap.icon_makeup_eyebrow_01), colorMap.get("color_mu_style_eyebrow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyebrow_wild, getDrawable(R.mipmap.icon_makeup_eyebrow_02), colorMap.get("color_mu_style_eyebrow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyebrow_classical, getDrawable(R.mipmap.icon_makeup_eyebrow_03), colorMap.get("color_mu_style_eyebrow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyebrow_standard, getDrawable(R.mipmap.icon_makeup_eyebrow_04), colorMap.get("color_mu_style_eyebrow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW));
|
||||
}
|
||||
});
|
||||
|
||||
/*眼影*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_SHADOW, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_single, getDrawable(R.mipmap.icon_makeup_eyeshadow_01), colorMap.get("color_mu_style_eyeshadow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_double1, getDrawable(R.mipmap.icon_makeup_eyeshadow_02), colorMap.get("color_mu_style_eyeshadow_02"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_double2, getDrawable(R.mipmap.icon_makeup_eyeshadow_03), colorMap.get("color_mu_style_eyeshadow_03"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_double3, getDrawable(R.mipmap.icon_makeup_eyeshadow_04), colorMap.get("color_mu_style_eyeshadow_04"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_triple1, getDrawable(R.mipmap.icon_makeup_eyeshadow_05), colorMap.get("color_mu_style_eyeshadow_05"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_shadow_triple2, getDrawable(R.mipmap.icon_makeup_eyeshadow_06), colorMap.get("color_mu_style_eyeshadow_06"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
}
|
||||
});
|
||||
|
||||
/*眼线*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_LINER, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_cat, getDrawable(R.mipmap.icon_makeup_eyeliner_01), colorMap.get("color_mu_style_eyeliner_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_drooping, getDrawable(R.mipmap.icon_makeup_eyeliner_02), colorMap.get("color_mu_style_eyeliner_02"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_pull_open, getDrawable(R.mipmap.icon_makeup_eyeliner_03), colorMap.get("color_mu_style_eyeliner_03"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_pull_close, getDrawable(R.mipmap.icon_makeup_eyeliner_04), colorMap.get("color_mu_style_eyeliner_04"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_long, getDrawable(R.mipmap.icon_makeup_eyeliner_05), colorMap.get("color_mu_style_eyeliner_05"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
add(new MakeupCustomBean(R.string.makeup_eye_linear_circular, getDrawable(R.mipmap.icon_makeup_eyeliner_06), colorMap.get("color_mu_style_eyeliner_06"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
}
|
||||
});
|
||||
/*睫毛*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_LASH, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_natural1, getDrawable(R.mipmap.icon_makeup_eyelash_01), colorMap.get("color_mu_style_eyelash_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_natural2, getDrawable(R.mipmap.icon_makeup_eyelash_02), colorMap.get("color_mu_style_eyelash_02"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_thick1, getDrawable(R.mipmap.icon_makeup_eyelash_03), colorMap.get("color_mu_style_eyelash_03"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_thick2, getDrawable(R.mipmap.icon_makeup_eyelash_04), colorMap.get("color_mu_style_eyelash_04"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_exaggerate1, getDrawable(R.mipmap.icon_makeup_eyelash_05), colorMap.get("color_mu_style_eyelash_05"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
add(new MakeupCustomBean(R.string.makeup_eyelash_exaggerate2, getDrawable(R.mipmap.icon_makeup_eyelash_06), colorMap.get("color_mu_style_eyelash_06"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
}
|
||||
});
|
||||
|
||||
/*高光*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_HIGH_LIGHT, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT));
|
||||
add(new MakeupCustomBean(R.string.makeup_highlight_one, getDrawable(R.mipmap.icon_makeup_highlight_01), colorMap.get("color_mu_style_highlight_01"),FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT));
|
||||
add(new MakeupCustomBean(R.string.makeup_highlight_two, getDrawable(R.mipmap.icon_makeup_highlight_02), colorMap.get("color_mu_style_highlight_02"),FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT));
|
||||
}
|
||||
});
|
||||
/*阴影*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_SHADOW, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_SHADOW));
|
||||
add(new MakeupCustomBean(R.string.makeup_shadow_one, getDrawable(R.mipmap.icon_makeup_contour_01), colorMap.get("color_mu_style_contour_01"),FaceParam.FACE_MAKEUP_TYPE_SHADOW));
|
||||
}
|
||||
});
|
||||
/*美瞳*/
|
||||
mCustomItems.put(FACE_MAKEUP_TYPE_EYE_PUPIL, new ArrayList<MakeupCustomBean>() {
|
||||
{
|
||||
add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_1, getDrawable(R.mipmap.icon_makeup_eyepupil_01), colorMap.get("color_mu_style_eyepupil_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_2, getDrawable(R.mipmap.icon_makeup_eyepupil_03), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_3, getDrawable(R.mipmap.icon_makeup_eyepupil_04), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_4, getDrawable(R.mipmap.icon_makeup_eyepupil_05), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_5, getDrawable(R.mipmap.icon_makeup_eyepupil_06), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_6, getDrawable(R.mipmap.icon_makeup_eyepupil_07), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_7, getDrawable(R.mipmap.icon_makeup_eyepupil_08), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
add(new MakeupCustomBean(R.string.makeup_pupil_8, getDrawable(R.mipmap.icon_makeup_eyepupil_09), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
}
|
||||
});
|
||||
return mCustomItems;
|
||||
}
|
||||
|
||||
|
||||
//endregion 子妆容
|
||||
|
||||
|
||||
//region 其他
|
||||
|
||||
/**
|
||||
* 获取颜色值配置
|
||||
*
|
||||
* @return LinkedHashMap<String, ArrayList < DoubleArray>>
|
||||
*/
|
||||
public static LinkedHashMap<String, ArrayList<double[]>> buildMakeUpColorMap() {
|
||||
LinkedHashMap<String, ArrayList<double[]>> makeupColorMap = new LinkedHashMap<>(32);
|
||||
String colorJson = FileUtils.INSTANCE.loadStringFromLocal(FaceUnityData.mApplication, FaceUnityConfig.MAKEUP_RESOURCE_COLOR_SETUP_JSON);
|
||||
if (colorJson != null && colorJson.trim().length() > 0) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(colorJson);
|
||||
Iterator<String> keys = jsonObject.keys();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
ArrayList<double[]> colorList = new ArrayList(12);
|
||||
// add additional transparent to fit ui
|
||||
//增加透明色,兼容ColorRecycleView展示
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
JSONObject colorObject = jsonObject.optJSONObject(key);
|
||||
for (int i = 1; i < 6; i++) {
|
||||
JSONArray jsonArray = colorObject.optJSONArray("color" + i);
|
||||
int length = jsonArray.length();
|
||||
double[] colors = new double[length];
|
||||
for (int j = 0; j < length; j++) {
|
||||
colors[j] = jsonArray.optDouble(j, 0.0);
|
||||
}
|
||||
colorList.add(colors);
|
||||
}
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
colorList.add(new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
makeupColorMap.put(key, colorList);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
return makeupColorMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取Drawable对象
|
||||
*
|
||||
* @param res Int
|
||||
* @return Drawable
|
||||
*/
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
private static Drawable getDrawable(int res) {
|
||||
return FaceUnityData.mApplication.getResources().getDrawable(res);
|
||||
}
|
||||
//endregion
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
|
||||
import com.faceunity.core.entity.FUBundleData;
|
||||
import com.faceunity.core.entity.FUColorRGBData;
|
||||
import com.faceunity.core.model.prop.humanOutline.HumanOutline;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||
import com.yunbao.faceunity.entity.PropCustomBean;
|
||||
import com.yunbao.faceunity.infe.AbstractPropCustomDataFactory;
|
||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* DESC:人像分割数据构造
|
||||
* Created on 2021/3/28
|
||||
*/
|
||||
public class PortraitSegmentSource {
|
||||
|
||||
private static final String BG_SEG_CUSTOM_FILEPATH = "bg_seg_custom";
|
||||
|
||||
/**
|
||||
* 缓存自定义添加人像
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
public static void saveCachePortraitSegment(String path) {
|
||||
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(BG_SEG_CUSTOM_FILEPATH, MODE_PRIVATE);
|
||||
sp.edit().putString(BG_SEG_CUSTOM_FILEPATH, path).apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义添加人像
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getCachePortraitSegment() {
|
||||
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(BG_SEG_CUSTOM_FILEPATH, MODE_PRIVATE);
|
||||
return sp.getString(BG_SEG_CUSTOM_FILEPATH, "");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造道具队列
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<PropCustomBean> buildPropBeans() {
|
||||
ArrayList<PropCustomBean> propBeans = new ArrayList<>();
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_control_delete_all, null, AbstractPropCustomDataFactory.TYPE_NONE));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_control_add, null, AbstractPropCustomDataFactory.TYPE_ADD));
|
||||
PropCustomBean customBean = buildPropCustomBean(getCachePortraitSegment());
|
||||
if (customBean != null) {
|
||||
propBeans.add(customBean);
|
||||
}
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_human_outline, "effect/segment/human_outline.bundle", FunctionEnum.HUMAN_OUTLINE));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_boyfriend_1, "effect/segment/boyfriend1.bundle", FunctionEnum.PORTRAIT_SEGMENT));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_boyfriend_2, "effect/segment/boyfriend3.bundle", FunctionEnum.PORTRAIT_SEGMENT));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_boyfriend_3, "effect/segment/boyfriend2.bundle", FunctionEnum.PORTRAIT_SEGMENT));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_hez_ztt_fu, "effect/segment/hez_ztt_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT, R.string.hez_ztt_fu));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_gufeng_zh_fu, "effect/segment/gufeng_zh_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_xiandai_ztt_fu, "effect/segment/xiandai_ztt_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_sea_lm_fu, "effect/segment/sea_lm_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT));
|
||||
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_ice_lm_fu, "effect/segment/ice_lm_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT));
|
||||
return propBeans;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造自定义人像分割
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public static PropCustomBean buildPropCustomBean(String path) {
|
||||
if (path != null && path.trim().length() > 0 && new File(path).exists()) {
|
||||
saveCachePortraitSegment(path);
|
||||
return new PropCustomBean(0, FaceUnityConfig.BUNDLE_BG_SEG_CUSTOM, FunctionEnum.BG_SEG_CUSTOM, 0, path );
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造人像分割线模型
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public static HumanOutline getHumanOutline(String path) {
|
||||
HumanOutline humanOutline = new HumanOutline(new FUBundleData(path));
|
||||
humanOutline.setLineSize(2.8);
|
||||
humanOutline.setLineGap(2.8);
|
||||
humanOutline.setLineColor(new FUColorRGBData(255.0, 196.0, 0.0));
|
||||
return humanOutline;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package com.yunbao.faceunity.repo;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||
import com.yunbao.faceunity.entity.PropBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* DESC:道具数据构造:道具贴图、AR面具、搞笑大头、表情识别、哈哈镜、手势识别、游戏
|
||||
* Created on 2021/3/28
|
||||
*/
|
||||
public class PropSource {
|
||||
|
||||
public static ArrayList<PropBean> buildPropBeans(int propType) {
|
||||
ArrayList<PropBean> propBeans = new ArrayList<>();
|
||||
switch (propType) {
|
||||
case FunctionEnum.STICKER:
|
||||
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null, FaceParam.FACE_STICKER));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_cat_sparks, "effect/normal/cat_sparks.bundle", FaceParam.FACE_STICKER));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_fu_zh_fenshu, "effect/normal/fu_zh_fenshu.bundle", FaceParam.FACE_STICKER));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_sdlr, "effect/normal/sdlr.bundle", FaceParam.FACE_STICKER));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_xlong_zh_fu, "effect/normal/xlong_zh_fu.bundle", FaceParam.FACE_STICKER));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_newy1, "effect/normal/newy1.bundle", FaceParam.FACE_STICKER));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_redribbt, "effect/normal/redribbt.bundle", FaceParam.FACE_STICKER));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_daisypig, "effect/normal/daisypig.bundle", FaceParam.FACE_STICKER));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_sdlu, "effect/normal/sdlu.bundle", FaceParam.FACE_STICKER));
|
||||
break;
|
||||
case FunctionEnum.AR_MASK:
|
||||
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null, FaceParam.FACE_ANIM_AR_MASK));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_ar_bluebird, "effect/ar/bluebird.bundle", FaceParam.FACE_ANIM_AR_MASK));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_ar_lanhudie, "effect/ar/lanhudie.bundle", FaceParam.FACE_ANIM_AR_MASK));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_ar_fenhudie, "effect/ar/fenhudie.bundle", FaceParam.FACE_ANIM_AR_MASK));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_ar_tiger_huang, "effect/ar/tiger_huang.bundle", FaceParam.FACE_ANIM_AR_MASK));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_ar_tiger_bai, "effect/ar/tiger_bai.bundle", FaceParam.FACE_ANIM_AR_MASK));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_ar_baozi, "effect/ar/baozi.bundle", FaceParam.FACE_ANIM_AR_MASK));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_ar_tiger, "effect/ar/tiger.bundle", FaceParam.FACE_ANIM_AR_MASK));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_ar_xiongmao, "effect/ar/xiongmao.bundle", FaceParam.FACE_ANIM_AR_MASK));
|
||||
break;
|
||||
case FunctionEnum.BIG_HEAD:
|
||||
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null, FaceParam.FACE_BIG_HEAD));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_big_head, "effect/big_head/big_head.bundle", FaceParam.FACE_BIG_HEAD));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_big_head_husky_face, "effect/big_head/big_head_facewarp2.bundle", FaceParam.FACE_BIG_HEAD));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_big_head_sausage_mouth, "effect/big_head/big_head_facewarp4.bundle", FaceParam.FACE_BIG_HEAD));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_big_head_blush, "effect/big_head/big_head_facewarp5.bundle", FaceParam.FACE_BIG_HEAD));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_big_head_dark_circles, "effect/big_head/big_head_facewarp6.bundle", FaceParam.FACE_BIG_HEAD));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_big_head_smiling_head, "effect/big_head/big_head_smile.bundle", R.string.xiaobianzi_zh_fu, FaceParam.FACE_BIG_HEAD));
|
||||
break;
|
||||
case FunctionEnum.EXPRESSION_RECOGNITION:
|
||||
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null,FaceParam.FACE_EXPRESSION_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_expression_future_warrior, "effect/expression/future_warrior.bundle", R.string.future_warrior,FaceParam.FACE_EXPRESSION_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_expression_jet_mask, "effect/expression/jet_mask.bundle", R.string.jet_mask,FaceParam.FACE_EXPRESSION_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_expression_sdx2, "effect/expression/sdx2.bundle", R.string.sdx2,FaceParam.FACE_EXPRESSION_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_expression_luhantongkuan_ztt_fu, "effect/expression/luhantongkuan_ztt_fu.bundle", R.string.luhantongkuan_ztt_fu,FaceParam.FACE_EXPRESSION_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_expression_qingqing_ztt_fu, "effect/expression/qingqing_ztt_fu.bundle", R.string.qingqing_ztt_fu,FaceParam.FACE_EXPRESSION_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_expression_xiaobianzi_zh_fu, "effect/expression/xiaobianzi_zh_fu.bundle", R.string.xiaobianzi_zh_fu,FaceParam.FACE_EXPRESSION_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_expression_xiaoxueshen_ztt_fu, "effect/expression/xiaoxueshen_ztt_fu.bundle", R.string.xiaoxueshen_ztt_fu,FaceParam.FACE_EXPRESSION_RECOGNITION));
|
||||
break;
|
||||
case FunctionEnum.FACE_WARP:
|
||||
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null,FaceParam.FACE_FACE_WARP));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_face_warp_2, "effect/facewarp/facewarp2.bundle",FaceParam.FACE_FACE_WARP));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_face_warp_3, "effect/facewarp/facewarp3.bundle",FaceParam.FACE_FACE_WARP));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_face_warp_4, "effect/facewarp/facewarp4.bundle",FaceParam.FACE_FACE_WARP));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_face_warp_5, "effect/facewarp/facewarp5.bundle",FaceParam.FACE_FACE_WARP));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_face_warp_6, "effect/facewarp/facewarp6.bundle",FaceParam.FACE_FACE_WARP));
|
||||
break;
|
||||
case FunctionEnum.GESTURE_RECOGNITION:
|
||||
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null,FaceParam.FACE_GESTURE_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_gesture_rain, "effect/gesture/ctrl_rain.bundle", R.string.push_hand,FaceParam.FACE_GESTURE_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_gesture_snow, "effect/gesture/ctrl_snow.bundle", R.string.push_hand,FaceParam.FACE_GESTURE_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_gesture_flower, "effect/gesture/ctrl_flower.bundle", R.string.push_hand,FaceParam.FACE_GESTURE_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_gesture_koreaheart, "effect/gesture/ssd_thread_korheart.bundle", R.string.fu_lm_koreaheart,FaceParam.FACE_GESTURE_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_gesture_six, "effect/gesture/ssd_thread_six.bundle", R.string.ssd_thread_six,FaceParam.FACE_GESTURE_RECOGNITION));
|
||||
propBeans.add(new PropBean(R.mipmap.icon_gesture_cute, "effect/gesture/ssd_thread_cute.bundle", R.string.ssd_thread_cute,FaceParam.FACE_GESTURE_RECOGNITION));
|
||||
break;
|
||||
}
|
||||
return propBeans;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,196 @@
|
||||
package com.yunbao.faceunity.seekbar.internal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.seekbar.internal.compat.SeekBarCompat;
|
||||
import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable;
|
||||
|
||||
|
||||
/**
|
||||
* {@link ViewGroup} to be used as the real indicator.
|
||||
* <p>
|
||||
* I've used this to be able to accommodate the TextView
|
||||
* and the {@link MarkerDrawable}
|
||||
* with the required positions and offsets
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class Marker extends ViewGroup implements MarkerDrawable.MarkerAnimationListener {
|
||||
private static final int PADDING_DP = 1;
|
||||
private static final int ELEVATION_DP = 8;
|
||||
//The TextView to show the info
|
||||
private TextView mNumber;
|
||||
//The max width of this View
|
||||
private int mWidth;
|
||||
//some distance between the thumb and our bubble marker.
|
||||
//This will be added to our measured height
|
||||
private int mSeparation;
|
||||
MarkerDrawable mMarkerDrawable;
|
||||
|
||||
public Marker(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
//as we're reading the parent DiscreteSeekBar attributes, it may wrongly set this view's visibility.
|
||||
setVisibility(View.VISIBLE);
|
||||
|
||||
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DiscreteSeekBar,
|
||||
R.attr.discreteSeekBarStyle, R.style.Widget_DiscreteSeekBar);
|
||||
|
||||
int padding = (int) (PADDING_DP * displayMetrics.density) * 2;
|
||||
int textAppearanceId = a.getResourceId(R.styleable.DiscreteSeekBar_dsb_indicatorTextAppearance,
|
||||
R.style.Widget_DiscreteIndicatorTextAppearance);
|
||||
mNumber = new TextView(context);
|
||||
//Add some padding to this textView so the bubble has some space to breath
|
||||
mNumber.setPadding(padding, 0, padding, 0);
|
||||
mNumber.setTextAppearance(context, textAppearanceId);
|
||||
mNumber.setGravity(Gravity.CENTER);
|
||||
mNumber.setText(maxValue);
|
||||
mNumber.setMaxLines(1);
|
||||
mNumber.setSingleLine(true);
|
||||
SeekBarCompat.setTextDirection(mNumber, TEXT_DIRECTION_LOCALE);
|
||||
mNumber.setVisibility(View.INVISIBLE);
|
||||
|
||||
//add some padding for the elevation shadow not to be clipped
|
||||
//I'm sure there are better ways of doing this...
|
||||
setPadding(padding, padding, padding, padding);
|
||||
|
||||
resetSizes(maxValue);
|
||||
|
||||
mSeparation = separation;
|
||||
ColorStateList color = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_indicatorColor);
|
||||
mMarkerDrawable = new MarkerDrawable(color, thumbSize);
|
||||
mMarkerDrawable.setCallback(this);
|
||||
mMarkerDrawable.setMarkerListener(this);
|
||||
mMarkerDrawable.setExternalOffset(padding);
|
||||
|
||||
//Elevation for anroid 5+
|
||||
float elevation = a.getDimension(R.styleable.DiscreteSeekBar_dsb_indicatorElevation, ELEVATION_DP * displayMetrics.density);
|
||||
ViewCompat.setElevation(this, elevation);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
SeekBarCompat.setOutlineProvider(this, mMarkerDrawable);
|
||||
}
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public void resetSizes(String maxValue) {
|
||||
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
|
||||
//Account for negative numbers... is there any proper way of getting the biggest string between our range????
|
||||
mNumber.setText("-" + maxValue);
|
||||
//Do a first forced measure call for the TextView (with the biggest text content),
|
||||
//to calculate the max width and use always the same.
|
||||
//this avoids the TextView from shrinking and growing when the text content changes
|
||||
int wSpec = MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, MeasureSpec.AT_MOST);
|
||||
int hSpec = MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels, MeasureSpec.AT_MOST);
|
||||
mNumber.measure(wSpec, hSpec);
|
||||
mWidth = Math.max(mNumber.getMeasuredWidth(), mNumber.getMeasuredHeight());
|
||||
removeView(mNumber);
|
||||
addView(mNumber, new FrameLayout.LayoutParams(mWidth, mWidth, Gravity.LEFT | Gravity.TOP));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
mMarkerDrawable.draw(canvas);
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
measureChildren(widthMeasureSpec, heightMeasureSpec);
|
||||
int widthSize = mWidth + getPaddingLeft() + getPaddingRight();
|
||||
int heightSize = mWidth + getPaddingTop() + getPaddingBottom();
|
||||
//This diff is the basic calculation of the difference between
|
||||
//a square side size and its diagonal
|
||||
//this helps us account for the visual offset created by MarkerDrawable
|
||||
//when leaving one of the corners un-rounded
|
||||
int diff = (int) ((1.41f * mWidth) - mWidth) / 2;
|
||||
setMeasuredDimension(widthSize, heightSize + diff + mSeparation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
int left = getPaddingLeft();
|
||||
int top = getPaddingTop();
|
||||
int right = getWidth() - getPaddingRight();
|
||||
int bottom = getHeight() - getPaddingBottom();
|
||||
//the TetView is always layout at the top
|
||||
mNumber.layout(left, top, left + mWidth, top + mWidth);
|
||||
//the MarkerDrawable uses the whole view, it will adapt itself...
|
||||
// or it seems so...
|
||||
mMarkerDrawable.setBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean verifyDrawable(Drawable who) {
|
||||
return who == mMarkerDrawable || super.verifyDrawable(who);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
//HACK: Sometimes, the animateOpen() call is made before the View is attached
|
||||
//so the drawable cannot schedule itself to run the animation
|
||||
//I think we can call it here safely.
|
||||
//I've seen it happen in android 2.3.7
|
||||
animateOpen();
|
||||
}
|
||||
|
||||
public void setValue(CharSequence value) {
|
||||
mNumber.setText(value);
|
||||
}
|
||||
|
||||
public CharSequence getValue() {
|
||||
return mNumber.getText();
|
||||
}
|
||||
|
||||
public void animateOpen() {
|
||||
mMarkerDrawable.stop();
|
||||
mMarkerDrawable.animateToPressed();
|
||||
}
|
||||
|
||||
public void animateClose() {
|
||||
mMarkerDrawable.stop();
|
||||
mNumber.setVisibility(View.INVISIBLE);
|
||||
mMarkerDrawable.animateToNormal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpeningComplete() {
|
||||
mNumber.setVisibility(View.VISIBLE);
|
||||
if (getParent() instanceof MarkerDrawable.MarkerAnimationListener) {
|
||||
((MarkerDrawable.MarkerAnimationListener) getParent()).onOpeningComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosingComplete() {
|
||||
if (getParent() instanceof MarkerDrawable.MarkerAnimationListener) {
|
||||
((MarkerDrawable.MarkerAnimationListener) getParent()).onClosingComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mMarkerDrawable.stop();
|
||||
}
|
||||
|
||||
public void setColors(int startColor, int endColor) {
|
||||
mMarkerDrawable.setColors(startColor, endColor);
|
||||
}
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
package com.yunbao.faceunity.seekbar.internal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.IBinder;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.core.view.GravityCompat;
|
||||
|
||||
import com.yunbao.faceunity.seekbar.internal.compat.SeekBarCompat;
|
||||
import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable;
|
||||
|
||||
|
||||
/**
|
||||
* Class to manage the floating bubble thing, similar (but quite worse tested than {@link android.widget.PopupWindow}
|
||||
* <p/>
|
||||
* <p>
|
||||
* This will attach a View to the Window (full-width, measured-height, positioned just under the thumb)
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
* @see #showIndicator(View, Rect)
|
||||
* @see #dismiss()
|
||||
* @see #dismissComplete()
|
||||
* @see Floater
|
||||
*/
|
||||
public class PopupIndicator {
|
||||
|
||||
private final WindowManager mWindowManager;
|
||||
private boolean mShowing;
|
||||
private Floater mPopupView;
|
||||
//Outside listener for the DiscreteSeekBar to get MarkerDrawable animation events.
|
||||
//The whole chain of events goes this way:
|
||||
//MarkerDrawable->Marker->Floater->mListener->DiscreteSeekBar....
|
||||
//... phew!
|
||||
private MarkerDrawable.MarkerAnimationListener mListener;
|
||||
private int[] mDrawingLocation = new int[2];
|
||||
Point screenSize = new Point();
|
||||
|
||||
public PopupIndicator(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) {
|
||||
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
mPopupView = new Floater(context, attrs, defStyleAttr, maxValue, thumbSize, separation);
|
||||
}
|
||||
|
||||
public void updateSizes(String maxValue) {
|
||||
dismissComplete();
|
||||
if (mPopupView != null) {
|
||||
mPopupView.mMarker.resetSizes(maxValue);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener(MarkerDrawable.MarkerAnimationListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* We want the Floater to be full-width because the contents will be moved from side to side.
|
||||
* We may/should change this in the future to use just the PARENT View width and/or pass it in the constructor
|
||||
*/
|
||||
private void measureFloater() {
|
||||
int specWidth = View.MeasureSpec.makeMeasureSpec(screenSize.x, View.MeasureSpec.EXACTLY);
|
||||
int specHeight = View.MeasureSpec.makeMeasureSpec(screenSize.y, View.MeasureSpec.AT_MOST);
|
||||
mPopupView.measure(specWidth, specHeight);
|
||||
}
|
||||
|
||||
public void setValue(CharSequence value) {
|
||||
mPopupView.mMarker.setValue(value);
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return mShowing;
|
||||
}
|
||||
|
||||
public void showIndicator(View parent, Rect touchBounds) {
|
||||
if (isShowing()) {
|
||||
mPopupView.mMarker.animateOpen();
|
||||
return;
|
||||
}
|
||||
|
||||
IBinder windowToken = parent.getWindowToken();
|
||||
if (windowToken != null) {
|
||||
WindowManager.LayoutParams p = createPopupLayout(windowToken);
|
||||
|
||||
p.gravity = Gravity.TOP | GravityCompat.START;
|
||||
updateLayoutParamsForPosiion(parent, p, touchBounds.bottom);
|
||||
mShowing = true;
|
||||
|
||||
translateViewIntoPosition(touchBounds.centerX());
|
||||
invokePopup(p);
|
||||
}
|
||||
}
|
||||
|
||||
public void move(int x) {
|
||||
if (!isShowing()) {
|
||||
return;
|
||||
}
|
||||
translateViewIntoPosition(x);
|
||||
}
|
||||
|
||||
public void setColors(int startColor, int endColor) {
|
||||
mPopupView.setColors(startColor, endColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will start the closing animation of the Marker and call onClosingComplete when finished
|
||||
*/
|
||||
public void dismiss() {
|
||||
mPopupView.mMarker.animateClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* FORCE the popup window to be removed.
|
||||
* You typically calls this when the parent view is being removed from the window to avoid a Window Leak
|
||||
*/
|
||||
public void dismissComplete() {
|
||||
if (isShowing()) {
|
||||
mShowing = false;
|
||||
try {
|
||||
mWindowManager.removeViewImmediate(mPopupView);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateLayoutParamsForPosiion(View anchor, WindowManager.LayoutParams p, int yOffset) {
|
||||
DisplayMetrics displayMetrics = anchor.getResources().getDisplayMetrics();
|
||||
screenSize.set(displayMetrics.widthPixels, displayMetrics.heightPixels);
|
||||
|
||||
measureFloater();
|
||||
int measuredHeight = mPopupView.getMeasuredHeight();
|
||||
int paddingBottom = mPopupView.mMarker.getPaddingBottom();
|
||||
anchor.getLocationInWindow(mDrawingLocation);
|
||||
p.x = 0;
|
||||
p.y = mDrawingLocation[1] - measuredHeight + yOffset + paddingBottom;
|
||||
p.width = screenSize.x;
|
||||
p.height = measuredHeight;
|
||||
}
|
||||
|
||||
private void translateViewIntoPosition(final int x) {
|
||||
mPopupView.setFloatOffset(x + mDrawingLocation[0]);
|
||||
}
|
||||
|
||||
private void invokePopup(WindowManager.LayoutParams p) {
|
||||
mWindowManager.addView(mPopupView, p);
|
||||
mPopupView.mMarker.animateOpen();
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams createPopupLayout(IBinder token) {
|
||||
WindowManager.LayoutParams p = new WindowManager.LayoutParams();
|
||||
p.gravity = Gravity.START | Gravity.TOP;
|
||||
p.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
p.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
p.format = PixelFormat.TRANSLUCENT;
|
||||
p.flags = computeFlags(p.flags);
|
||||
p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
|
||||
p.token = token;
|
||||
p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
|
||||
p.setTitle("DiscreteSeekBar Indicator:" + Integer.toHexString(hashCode()));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* I'm NOT completely sure how all this bitwise things work...
|
||||
*
|
||||
* @param curFlags
|
||||
* @return
|
||||
*/
|
||||
private int computeFlags(int curFlags) {
|
||||
curFlags &= ~(
|
||||
WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES |
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
|
||||
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
|
||||
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
|
||||
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||
curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
|
||||
curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
|
||||
return curFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Small FrameLayout class to hold and move the bubble around when requested
|
||||
* I wanted to use the {@link Marker} directly
|
||||
* but doing so would make some things harder to implement
|
||||
* (like moving the marker around, having the Marker's outline to work, etc)
|
||||
*/
|
||||
private class Floater extends FrameLayout implements MarkerDrawable.MarkerAnimationListener {
|
||||
private Marker mMarker;
|
||||
private int mOffset;
|
||||
|
||||
public Floater(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) {
|
||||
super(context);
|
||||
mMarker = new Marker(context, attrs, defStyleAttr, maxValue, thumbSize, separation);
|
||||
addView(mMarker, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
measureChildren(widthMeasureSpec, heightMeasureSpec);
|
||||
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int heightSie = mMarker.getMeasuredHeight();
|
||||
setMeasuredDimension(widthSize, heightSie);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
int centerDiffX = mMarker.getMeasuredWidth() / 2;
|
||||
int offset = (mOffset - centerDiffX);
|
||||
mMarker.layout(offset, 0, offset + mMarker.getMeasuredWidth(), mMarker.getMeasuredHeight());
|
||||
}
|
||||
|
||||
public void setFloatOffset(int x) {
|
||||
mOffset = x;
|
||||
int centerDiffX = mMarker.getMeasuredWidth() / 2;
|
||||
int offset = (x - centerDiffX);
|
||||
mMarker.offsetLeftAndRight(offset - mMarker.getLeft());
|
||||
//Without hardware acceleration (or API levels<11), offsetting a view seems to NOT invalidate the proper area.
|
||||
//We should calc the proper invalidate Rect but this will be for now...
|
||||
if (!SeekBarCompat.isHardwareAccelerated(this)) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosingComplete() {
|
||||
if (mListener != null) {
|
||||
mListener.onClosingComplete();
|
||||
}
|
||||
dismissComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpeningComplete() {
|
||||
if (mListener != null) {
|
||||
mListener.onOpeningComplete();
|
||||
}
|
||||
}
|
||||
|
||||
public void setColors(int startColor, int endColor) {
|
||||
mMarker.setColors(startColor, endColor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.compat;
|
||||
|
||||
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
|
||||
/**
|
||||
* Currently, there's no {@link android.animation.ValueAnimator} compatibility version
|
||||
* and as we didn't want to throw in external dependencies, we made this small class.
|
||||
* <p/>
|
||||
* <p>
|
||||
* This will work like {@link android.support.v4.view.ViewPropertyAnimatorCompat}, that is,
|
||||
* not doing anything on API<11 and using the default {@link android.animation.ValueAnimator}
|
||||
* on API>=11
|
||||
* </p>
|
||||
* <p>
|
||||
* This class is used to provide animation to the {@link DiscreteSeekBar}
|
||||
* when navigating with the Keypad
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract class AnimatorCompat {
|
||||
public interface AnimationFrameUpdateListener {
|
||||
public void onAnimationFrame(float currentValue);
|
||||
}
|
||||
|
||||
AnimatorCompat() {
|
||||
|
||||
}
|
||||
|
||||
public abstract void cancel();
|
||||
|
||||
public abstract boolean isRunning();
|
||||
|
||||
public abstract void setDuration(int progressAnimationDuration);
|
||||
|
||||
public abstract void start();
|
||||
|
||||
public static final AnimatorCompat create(float start, float end, AnimationFrameUpdateListener listener) {
|
||||
return new AnimatorCompatBase(start, end, listener);
|
||||
}
|
||||
|
||||
private static class AnimatorCompatBase extends AnimatorCompat {
|
||||
|
||||
private final AnimationFrameUpdateListener mListener;
|
||||
private final float mEndValue;
|
||||
|
||||
public AnimatorCompatBase(float start, float end, AnimationFrameUpdateListener listener) {
|
||||
mListener = listener;
|
||||
mEndValue = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDuration(int progressAnimationDuration) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
mListener.onAnimationFrame(mEndValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.compat;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.RippleDrawable;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
import com.yunbao.faceunity.seekbar.internal.drawable.AlmostRippleDrawable;
|
||||
import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable;
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper compatibility class to call some API-Specific methods
|
||||
* And offer alternate procedures when possible
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class SeekBarCompat {
|
||||
|
||||
/**
|
||||
* Sets the custom Outline provider on API>=21.
|
||||
* Does nothing on API<21
|
||||
*
|
||||
* @param view
|
||||
* @param markerDrawable
|
||||
*/
|
||||
public static void setOutlineProvider(View view, final MarkerDrawable markerDrawable) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
SeekBarCompatDontCrash.setOutlineProvider(view, markerDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Our DiscreteSeekBar implementation uses a circular drawable on API < 21
|
||||
* because we don't set it as Background, but draw it ourselves
|
||||
*
|
||||
* @param colorStateList
|
||||
* @return
|
||||
*/
|
||||
public static Drawable getRipple(ColorStateList colorStateList) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
return SeekBarCompatDontCrash.getRipple(colorStateList);
|
||||
} else {
|
||||
return new AlmostRippleDrawable(colorStateList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the seekbar ripple
|
||||
*
|
||||
* @param drawable
|
||||
* @param colorStateList The ColorStateList the track ripple will be changed to
|
||||
*/
|
||||
public static void setRippleColor(@NonNull Drawable drawable, ColorStateList colorStateList) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
((RippleDrawable) drawable).setColor(colorStateList);
|
||||
} else {
|
||||
((AlmostRippleDrawable) drawable).setColor(colorStateList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* As our DiscreteSeekBar implementation uses a circular drawable on API < 21
|
||||
* we want to use the same method to set its bounds as the Ripple's hotspot bounds.
|
||||
*
|
||||
* @param drawable
|
||||
* @param left
|
||||
* @param top
|
||||
* @param right
|
||||
* @param bottom
|
||||
*/
|
||||
public static void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
//We don't want the full size rect, Lollipop ripple would be too big
|
||||
int size = (right - left) / 8;
|
||||
DrawableCompat.setHotspotBounds(drawable, left + size, top + size, right - size, bottom - size);
|
||||
} else {
|
||||
drawable.setBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* android.support.v4.view.ViewCompat SHOULD include this once and for all!!
|
||||
* But it doesn't...
|
||||
*
|
||||
* @param view
|
||||
* @param background
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void setBackground(View view, Drawable background) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
SeekBarCompatDontCrash.setBackground(view, background);
|
||||
} else {
|
||||
view.setBackgroundDrawable(background);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the TextView text direction attribute when possible
|
||||
*
|
||||
* @param textView
|
||||
* @param textDirection
|
||||
* @see TextView#setTextDirection(int)
|
||||
*/
|
||||
public static void setTextDirection(TextView textView, int textDirection) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
SeekBarCompatDontCrash.setTextDirection(textView, textDirection);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isInScrollingContainer(ViewParent p) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
return SeekBarCompatDontCrash.isInScrollingContainer(p);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isHardwareAccelerated(View view) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
return SeekBarCompatDontCrash.isHardwareAccelerated(view);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.compat;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.RippleDrawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable;
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper compatibility class to call some API-Specific methods
|
||||
* And offer alternate procedures when possible
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TargetApi(21)
|
||||
class SeekBarCompatDontCrash {
|
||||
public static void setOutlineProvider(View marker, final MarkerDrawable markerDrawable) {
|
||||
marker.setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
outline.setConvexPath(markerDrawable.getPath());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Drawable getRipple(ColorStateList colorStateList) {
|
||||
return new RippleDrawable(colorStateList, null, null);
|
||||
}
|
||||
|
||||
public static void setBackground(View view, Drawable background) {
|
||||
view.setBackground(background);
|
||||
}
|
||||
|
||||
public static void setTextDirection(TextView number, int textDirection) {
|
||||
number.setTextDirection(textDirection);
|
||||
}
|
||||
|
||||
public static boolean isInScrollingContainer(ViewParent p) {
|
||||
while (p != null && p instanceof ViewGroup) {
|
||||
if (((ViewGroup) p).shouldDelayChildPressedState()) {
|
||||
return true;
|
||||
}
|
||||
p = p.getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isHardwareAccelerated(View view) {
|
||||
return view.isHardwareAccelerated();
|
||||
}
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.drawable;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.os.SystemClock;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
public class AlmostRippleDrawable extends StateDrawable implements Animatable {
|
||||
private static final long FRAME_DURATION = 1000 / 60;
|
||||
private static final int ANIMATION_DURATION = 250;
|
||||
|
||||
private static final float INACTIVE_SCALE = 0f;
|
||||
private static final float ACTIVE_SCALE = 1f;
|
||||
private float mCurrentScale = INACTIVE_SCALE;
|
||||
private Interpolator mInterpolator;
|
||||
private long mStartTime;
|
||||
private boolean mReverse = false;
|
||||
private boolean mRunning = false;
|
||||
private int mDuration = ANIMATION_DURATION;
|
||||
private float mAnimationInitialValue;
|
||||
//We don't use colors just with our drawable state because of animations
|
||||
private int mPressedColor;
|
||||
private int mFocusedColor;
|
||||
private int mDisabledColor;
|
||||
private int mRippleColor;
|
||||
private int mRippleBgColor;
|
||||
|
||||
public AlmostRippleDrawable(@NonNull ColorStateList tintStateList) {
|
||||
super(tintStateList);
|
||||
mInterpolator = new AccelerateDecelerateInterpolator();
|
||||
setColor(tintStateList);
|
||||
}
|
||||
|
||||
public void setColor(@NonNull ColorStateList tintStateList) {
|
||||
int defaultColor = tintStateList.getDefaultColor();
|
||||
mFocusedColor = tintStateList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}, defaultColor);
|
||||
mPressedColor = tintStateList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, defaultColor);
|
||||
mDisabledColor = tintStateList.getColorForState(new int[]{-android.R.attr.state_enabled}, defaultColor);
|
||||
|
||||
//The ripple should be partially transparent
|
||||
mFocusedColor = getModulatedAlphaColor(130, mFocusedColor);
|
||||
mPressedColor = getModulatedAlphaColor(130, mPressedColor);
|
||||
mDisabledColor = getModulatedAlphaColor(130, mDisabledColor);
|
||||
}
|
||||
|
||||
private static int getModulatedAlphaColor(int alphaValue, int originalColor) {
|
||||
int alpha = Color.alpha(originalColor);
|
||||
int scale = alphaValue + (alphaValue >> 7);
|
||||
alpha = alpha * scale >> 8;
|
||||
return Color.argb(alpha, Color.red(originalColor), Color.green(originalColor), Color.blue(originalColor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDraw(Canvas canvas, Paint paint) {
|
||||
Rect bounds = getBounds();
|
||||
int size = Math.min(bounds.width(), bounds.height());
|
||||
float scale = mCurrentScale;
|
||||
int rippleColor = mRippleColor;
|
||||
int bgColor = mRippleBgColor;
|
||||
float radius = (size / 2);
|
||||
float radiusAnimated = radius * scale;
|
||||
if (scale > INACTIVE_SCALE) {
|
||||
if (bgColor != 0) {
|
||||
paint.setColor(bgColor);
|
||||
paint.setAlpha(decreasedAlpha(Color.alpha(bgColor)));
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), radius, paint);
|
||||
}
|
||||
if (rippleColor != 0) {
|
||||
paint.setColor(rippleColor);
|
||||
paint.setAlpha(modulateAlpha(Color.alpha(rippleColor)));
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), radiusAnimated, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int decreasedAlpha(int alpha) {
|
||||
int scale = 100 + (100 >> 7);
|
||||
return alpha * scale >> 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setState(int[] stateSet) {
|
||||
int[] oldState = getState();
|
||||
boolean oldPressed = false;
|
||||
for (int i : oldState) {
|
||||
if (i == android.R.attr.state_pressed) {
|
||||
oldPressed = true;
|
||||
}
|
||||
}
|
||||
super.setState(stateSet);
|
||||
boolean focused = false;
|
||||
boolean pressed = false;
|
||||
boolean disabled = true;
|
||||
for (int i : stateSet) {
|
||||
if (i == android.R.attr.state_focused) {
|
||||
focused = true;
|
||||
} else if (i == android.R.attr.state_pressed) {
|
||||
pressed = true;
|
||||
} else if (i == android.R.attr.state_enabled) {
|
||||
disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
unscheduleSelf(mUpdater);
|
||||
mRippleColor = mDisabledColor;
|
||||
mRippleBgColor = 0;
|
||||
mCurrentScale = ACTIVE_SCALE / 2;
|
||||
invalidateSelf();
|
||||
} else {
|
||||
if (pressed) {
|
||||
animateToPressed();
|
||||
mRippleColor = mRippleBgColor = mPressedColor;
|
||||
} else if (oldPressed) {
|
||||
mRippleColor = mRippleBgColor = mPressedColor;
|
||||
animateToNormal();
|
||||
} else if (focused) {
|
||||
mRippleColor = mFocusedColor;
|
||||
mRippleBgColor = 0;
|
||||
mCurrentScale = ACTIVE_SCALE;
|
||||
invalidateSelf();
|
||||
} else {
|
||||
mRippleColor = 0;
|
||||
mRippleBgColor = 0;
|
||||
mCurrentScale = INACTIVE_SCALE;
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void animateToPressed() {
|
||||
unscheduleSelf(mUpdater);
|
||||
if (mCurrentScale < ACTIVE_SCALE) {
|
||||
mReverse = false;
|
||||
mRunning = true;
|
||||
mAnimationInitialValue = mCurrentScale;
|
||||
float durationFactor = 1f - ((mAnimationInitialValue - INACTIVE_SCALE) / (ACTIVE_SCALE - INACTIVE_SCALE));
|
||||
mDuration = (int) (ANIMATION_DURATION * durationFactor);
|
||||
mStartTime = SystemClock.uptimeMillis();
|
||||
scheduleSelf(mUpdater, mStartTime + FRAME_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
public void animateToNormal() {
|
||||
unscheduleSelf(mUpdater);
|
||||
if (mCurrentScale > INACTIVE_SCALE) {
|
||||
mReverse = true;
|
||||
mRunning = true;
|
||||
mAnimationInitialValue = mCurrentScale;
|
||||
float durationFactor = 1f - ((mAnimationInitialValue - ACTIVE_SCALE) / (INACTIVE_SCALE - ACTIVE_SCALE));
|
||||
mDuration = (int) (ANIMATION_DURATION * durationFactor);
|
||||
mStartTime = SystemClock.uptimeMillis();
|
||||
scheduleSelf(mUpdater, mStartTime + FRAME_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAnimation(float factor) {
|
||||
float initial = mAnimationInitialValue;
|
||||
float destination = mReverse ? INACTIVE_SCALE : ACTIVE_SCALE;
|
||||
mCurrentScale = initial + (destination - initial) * factor;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
private final Runnable mUpdater = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
long currentTime = SystemClock.uptimeMillis();
|
||||
long diff = currentTime - mStartTime;
|
||||
if (diff < mDuration) {
|
||||
float interpolation = mInterpolator.getInterpolation((float) diff / (float) mDuration);
|
||||
scheduleSelf(mUpdater, currentTime + FRAME_DURATION);
|
||||
updateAnimation(interpolation);
|
||||
} else {
|
||||
unscheduleSelf(mUpdater);
|
||||
mRunning = false;
|
||||
updateAnimation(1f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
//No-Op. We control our own animation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
//No-Op. We control our own animation
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return mRunning;
|
||||
}
|
||||
}
|
@ -0,0 +1,235 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.drawable;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.os.SystemClock;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@link StateDrawable} to draw a morphing marker symbol.
|
||||
* <p>
|
||||
* It's basically an implementation of an {@link Animatable} Drawable with the following details:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Animates from a circle shape to a "marker" shape just using a RoundRect</li>
|
||||
* <li>Animates color change from the normal state color to the pressed state color</li>
|
||||
* <li>Uses a {@link Path} to also serve as Outline for API>=21</li>
|
||||
* </ul>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class MarkerDrawable extends StateDrawable implements Animatable {
|
||||
private static final long FRAME_DURATION = 1000 / 60;
|
||||
private static final int ANIMATION_DURATION = 250;
|
||||
|
||||
private float mCurrentScale = 0f;
|
||||
private Interpolator mInterpolator;
|
||||
private long mStartTime;
|
||||
private boolean mReverse = false;
|
||||
private boolean mRunning = false;
|
||||
private int mDuration = ANIMATION_DURATION;
|
||||
//size of the actual thumb drawable to use as circle state size
|
||||
private float mClosedStateSize;
|
||||
//value to store que current scale when starting an animation and interpolate from it
|
||||
private float mAnimationInitialValue;
|
||||
//extra offset directed from the View to account
|
||||
//for its internal padding between circle state and marker state
|
||||
private int mExternalOffset;
|
||||
//colors for interpolation
|
||||
private int mStartColor;//Color when the Marker is OPEN
|
||||
private int mEndColor;//Color when the arker is CLOSED
|
||||
|
||||
Path mPath = new Path();
|
||||
RectF mRect = new RectF();
|
||||
Matrix mMatrix = new Matrix();
|
||||
private MarkerAnimationListener mMarkerListener;
|
||||
|
||||
public MarkerDrawable(@NonNull ColorStateList tintList, int closedSize) {
|
||||
super(tintList);
|
||||
mInterpolator = new AccelerateDecelerateInterpolator();
|
||||
mClosedStateSize = closedSize;
|
||||
mStartColor = tintList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, tintList.getDefaultColor());
|
||||
mEndColor = tintList.getDefaultColor();
|
||||
|
||||
}
|
||||
|
||||
public void setExternalOffset(int offset) {
|
||||
mExternalOffset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* The two colors that will be used for the seek thumb.
|
||||
*
|
||||
* @param startColor Color used for the seek thumb
|
||||
* @param endColor Color used for popup indicator
|
||||
*/
|
||||
public void setColors(int startColor, int endColor) {
|
||||
mStartColor = startColor;
|
||||
mEndColor = endColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
void doDraw(Canvas canvas, Paint paint) {
|
||||
if (!mPath.isEmpty()) {
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
int color = blendColors(mStartColor, mEndColor, mCurrentScale);
|
||||
paint.setColor(color);
|
||||
canvas.drawPath(mPath, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public Path getPath() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
computePath(bounds);
|
||||
}
|
||||
|
||||
private void computePath(Rect bounds) {
|
||||
final float currentScale = mCurrentScale;
|
||||
final Path path = mPath;
|
||||
final RectF rect = mRect;
|
||||
final Matrix matrix = mMatrix;
|
||||
|
||||
path.reset();
|
||||
int totalSize = Math.min(bounds.width(), bounds.height());
|
||||
|
||||
float initial = mClosedStateSize;
|
||||
float destination = totalSize;
|
||||
float currentSize = initial + (destination - initial) * currentScale;
|
||||
|
||||
float halfSize = currentSize / 2f;
|
||||
float inverseScale = 1f - currentScale;
|
||||
float cornerSize = halfSize * inverseScale;
|
||||
float[] corners = new float[]{halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize};
|
||||
rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize);
|
||||
path.addRoundRect(rect, corners, Path.Direction.CCW);
|
||||
matrix.reset();
|
||||
matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize);
|
||||
matrix.postTranslate((bounds.width() - currentSize) / 2, 0);
|
||||
float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale;
|
||||
matrix.postTranslate(0, hDiff);
|
||||
path.transform(matrix);
|
||||
}
|
||||
|
||||
private void updateAnimation(float factor) {
|
||||
float initial = mAnimationInitialValue;
|
||||
float destination = mReverse ? 0f : 1f;
|
||||
mCurrentScale = initial + (destination - initial) * factor;
|
||||
computePath(getBounds());
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
public void animateToPressed() {
|
||||
unscheduleSelf(mUpdater);
|
||||
mReverse = false;
|
||||
if (mCurrentScale < 1) {
|
||||
mRunning = true;
|
||||
mAnimationInitialValue = mCurrentScale;
|
||||
float durationFactor = 1f - mCurrentScale;
|
||||
mDuration = (int) (ANIMATION_DURATION * durationFactor);
|
||||
mStartTime = SystemClock.uptimeMillis();
|
||||
scheduleSelf(mUpdater, mStartTime + FRAME_DURATION);
|
||||
} else {
|
||||
notifyFinishedToListener();
|
||||
}
|
||||
}
|
||||
|
||||
public void animateToNormal() {
|
||||
mReverse = true;
|
||||
unscheduleSelf(mUpdater);
|
||||
if (mCurrentScale > 0) {
|
||||
mRunning = true;
|
||||
mAnimationInitialValue = mCurrentScale;
|
||||
float durationFactor = 1f - mCurrentScale;
|
||||
mDuration = ANIMATION_DURATION - (int) (ANIMATION_DURATION * durationFactor);
|
||||
mStartTime = SystemClock.uptimeMillis();
|
||||
scheduleSelf(mUpdater, mStartTime + FRAME_DURATION);
|
||||
} else {
|
||||
notifyFinishedToListener();
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable mUpdater = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
long currentTime = SystemClock.uptimeMillis();
|
||||
long diff = currentTime - mStartTime;
|
||||
if (diff < mDuration) {
|
||||
float interpolation = mInterpolator.getInterpolation((float) diff / (float) mDuration);
|
||||
scheduleSelf(mUpdater, currentTime + FRAME_DURATION);
|
||||
updateAnimation(interpolation);
|
||||
} else {
|
||||
unscheduleSelf(mUpdater);
|
||||
mRunning = false;
|
||||
updateAnimation(1f);
|
||||
notifyFinishedToListener();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void setMarkerListener(MarkerAnimationListener listener) {
|
||||
mMarkerListener = listener;
|
||||
}
|
||||
|
||||
private void notifyFinishedToListener() {
|
||||
if (mMarkerListener != null) {
|
||||
if (mReverse) {
|
||||
mMarkerListener.onClosingComplete();
|
||||
} else {
|
||||
mMarkerListener.onOpeningComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
//No-Op. We control our own animation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
unscheduleSelf(mUpdater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return mRunning;
|
||||
}
|
||||
|
||||
private static int blendColors(int color1, int color2, float factor) {
|
||||
final float inverseFactor = 1f - factor;
|
||||
float a = (Color.alpha(color1) * factor) + (Color.alpha(color2) * inverseFactor);
|
||||
float r = (Color.red(color1) * factor) + (Color.red(color2) * inverseFactor);
|
||||
float g = (Color.green(color1) * factor) + (Color.green(color2) * inverseFactor);
|
||||
float b = (Color.blue(color1) * factor) + (Color.blue(color2) * inverseFactor);
|
||||
return Color.argb((int) a, (int) r, (int) g, (int) b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A listener interface to porpagate animation events
|
||||
* This is the "poor's man" AnimatorListener for this Drawable
|
||||
*/
|
||||
public interface MarkerAnimationListener {
|
||||
public void onClosingComplete();
|
||||
|
||||
public void onOpeningComplete();
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.drawable;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
/**
|
||||
* A drawable that changes it's Paint color depending on the Drawable State
|
||||
* <p>
|
||||
* Subclasses should implement {@link #doDraw(Canvas, Paint)}
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract class StateDrawable extends Drawable {
|
||||
private ColorStateList mTintStateList;
|
||||
private final Paint mPaint;
|
||||
private int mCurrentColor;
|
||||
private int mAlpha = 255;
|
||||
|
||||
public StateDrawable(@NonNull ColorStateList tintStateList) {
|
||||
super();
|
||||
setColorStateList(tintStateList);
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return (mTintStateList.isStateful()) || super.isStateful();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setState(int[] stateSet) {
|
||||
boolean handled = super.setState(stateSet);
|
||||
handled = updateTint(stateSet) || handled;
|
||||
return handled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
|
||||
private boolean updateTint(int[] state) {
|
||||
final int color = mTintStateList.getColorForState(state, mCurrentColor);
|
||||
if (color != mCurrentColor) {
|
||||
mCurrentColor = color;
|
||||
//We've changed states
|
||||
invalidateSelf();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
mPaint.setColor(mCurrentColor);
|
||||
int alpha = modulateAlpha(Color.alpha(mCurrentColor));
|
||||
mPaint.setAlpha(alpha);
|
||||
doDraw(canvas, mPaint);
|
||||
}
|
||||
|
||||
public void setColorStateList(@NonNull ColorStateList tintStateList) {
|
||||
mTintStateList = tintStateList;
|
||||
mCurrentColor = tintStateList.getDefaultColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method to do the actual drawing
|
||||
*
|
||||
* @param canvas The current {@link Canvas} to draw into
|
||||
* @param paint The {@link Paint} preconfigurred with the current
|
||||
* {@link ColorStateList} color
|
||||
*/
|
||||
abstract void doDraw(Canvas canvas, Paint paint);
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mAlpha = alpha;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
int modulateAlpha(int alpha) {
|
||||
int scale = mAlpha + (mAlpha >> 7);
|
||||
return alpha * scale >> 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlpha() {
|
||||
return mAlpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mPaint.setColorFilter(cf);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.drawable;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.yunbao.faceunity.seekbar.internal.Marker;
|
||||
|
||||
|
||||
/**
|
||||
* <h1>HACK</h1>
|
||||
* <p>
|
||||
* Special {@link StateDrawable} implementation
|
||||
* to draw the Thumb circle.
|
||||
* </p>
|
||||
* <p>
|
||||
* It's special because it will stop drawing once the state is pressed/focused BUT only after a small delay.
|
||||
* </p>
|
||||
* <p>
|
||||
* This special delay is meant to help avoiding frame glitches while the {@link Marker} is added to the Window
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ThumbDrawable extends StateDrawable implements Animatable {
|
||||
//The current size for this drawable. Must be converted to real DPs
|
||||
public static final int DEFAULT_SIZE_DP = 12;
|
||||
private final int mSize;
|
||||
private boolean mOpen;
|
||||
private boolean mRunning;
|
||||
|
||||
public ThumbDrawable(@NonNull ColorStateList tintStateList, int size) {
|
||||
super(tintStateList);
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDraw(Canvas canvas, Paint paint) {
|
||||
if (!mOpen) {
|
||||
Rect bounds = getBounds();
|
||||
float radius = (mSize / 2);
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), radius, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public void animateToPressed() {
|
||||
scheduleSelf(opener, SystemClock.uptimeMillis() + 100);
|
||||
mRunning = true;
|
||||
}
|
||||
|
||||
public void animateToNormal() {
|
||||
mOpen = false;
|
||||
mRunning = false;
|
||||
unscheduleSelf(opener);
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
private Runnable opener = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mOpen = true;
|
||||
invalidateSelf();
|
||||
mRunning = false;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
//NOOP
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
animateToNormal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return mRunning;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.drawable;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
/**
|
||||
* Simple {@link StateDrawable} implementation
|
||||
* to draw circles/ovals
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class TrackOvalDrawable extends StateDrawable {
|
||||
private RectF mRectF = new RectF();
|
||||
|
||||
public TrackOvalDrawable(@NonNull ColorStateList tintStateList) {
|
||||
super(tintStateList);
|
||||
}
|
||||
|
||||
@Override
|
||||
void doDraw(Canvas canvas, Paint paint) {
|
||||
mRectF.set(getBounds());
|
||||
canvas.drawOval(mRectF, paint);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.yunbao.faceunity.seekbar.internal.drawable;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
/**
|
||||
* Simple {@link StateDrawable} implementation
|
||||
* to draw rectangles
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class TrackRectDrawable extends StateDrawable {
|
||||
public TrackRectDrawable(@NonNull ColorStateList tintStateList) {
|
||||
super(tintStateList);
|
||||
}
|
||||
|
||||
@Override
|
||||
void doDraw(Canvas canvas, Paint paint) {
|
||||
canvas.drawRect(getBounds(), paint);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,479 @@
|
||||
package com.yunbao.faceunity.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
import com.yunbao.common.utils.WordUtil;
|
||||
import com.yunbao.faceunity.R;
|
||||
import com.yunbao.faceunity.adapters.ContainerRecyclerAdapter;
|
||||
import com.yunbao.faceunity.adapters.MenuGroupRecyclerAdapter;
|
||||
import com.yunbao.faceunity.adapters.vh.StyleViewHolder;
|
||||
import com.yunbao.faceunity.data.FaceParam;
|
||||
import com.yunbao.faceunity.data.FineStickerDataFactory;
|
||||
import com.yunbao.faceunity.entity.BaseBean;
|
||||
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||
import com.yunbao.faceunity.entity.MakeupCustomClassBean;
|
||||
import com.yunbao.faceunity.entity.MenuGroupBean;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerEntity;
|
||||
import com.yunbao.faceunity.entity.net.FineStickerTagEntity;
|
||||
import com.yunbao.faceunity.repo.AnimojiSource;
|
||||
import com.yunbao.faceunity.repo.BodyBeautySource;
|
||||
import com.yunbao.faceunity.repo.FaceBeautySource;
|
||||
import com.yunbao.faceunity.repo.MakeupSource;
|
||||
import com.yunbao.faceunity.repo.PropSource;
|
||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
||||
import com.yunbao.faceunity.utils.FaceSPUtils;
|
||||
import com.yunbao.faceunity.utils.net.StickerDownloadHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DESC:
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public class FaceUnityView extends LinearLayout implements StickerDownloadHelper.Callback {
|
||||
|
||||
private Context mContext;
|
||||
private RecyclerView menuGroup;
|
||||
private RecyclerView containerRecycler;
|
||||
private ContainerRecyclerAdapter containerAdapter;
|
||||
private TabLayout tabLayout;
|
||||
private TextView title;
|
||||
private LinearLayout menu2, menuDiy, reset, menu2Reset;
|
||||
private ImageView menu2Back, back, close, contrast;
|
||||
private DiscreteSeekBar seekBar;
|
||||
private IFaceUnityInter iFaceUnityInter;
|
||||
private ConstraintLayout titleLayout;
|
||||
private static final String TAG = "美颜";
|
||||
|
||||
public FaceUnityView(Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
init();
|
||||
}
|
||||
|
||||
public FaceUnityView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
init();
|
||||
}
|
||||
|
||||
public FaceUnityView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mContext = context;
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
private void init() {
|
||||
LayoutInflater.from(mContext).inflate(R.layout.layout_faceunity, this);
|
||||
initView();
|
||||
FineStickerDataFactory.getInstance().addCallback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化View
|
||||
*/
|
||||
private void initView() {
|
||||
menuGroup = findViewById(R.id.menu_group);
|
||||
containerRecycler = findViewById(R.id.menu2_container_view);
|
||||
tabLayout = findViewById(R.id.menu2_tab);
|
||||
title = findViewById(R.id.menu_title);
|
||||
menu2 = findViewById(R.id.layout_faceunity_menu2);
|
||||
back = findViewById(R.id.menu_back);
|
||||
menu2Back = findViewById(R.id.menu2_back);
|
||||
close = findViewById(R.id.menu_close);
|
||||
reset = findViewById(R.id.menu_reset);
|
||||
menu2Reset = findViewById(R.id.menu2_reset);
|
||||
menuDiy = findViewById(R.id.menu_diy);
|
||||
seekBar = findViewById(R.id.item_seekBar);
|
||||
contrast = findViewById(R.id.item_contrast);
|
||||
titleLayout = findViewById(R.id.titleLayout);
|
||||
initMenuGroup();
|
||||
setContainerRecycler(new ArrayList<>());
|
||||
initViewClick();
|
||||
gotoFaceBeauty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化配置点击事件
|
||||
*/
|
||||
private void initViewClick() {
|
||||
menu2Back.setOnClickListener(v -> {
|
||||
Object tag = menu2Back.getTag();
|
||||
if (tag == null) {
|
||||
goBackMainMenu();
|
||||
} else if (tag.equals("makeup")) {
|
||||
title.setText(R.string.home_function_name_makeup);
|
||||
title.setVisibility(VISIBLE);
|
||||
menuDiy.setVisibility(VISIBLE);
|
||||
tabLayout.removeAllTabs();
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCombinations());
|
||||
menu2Back.setTag(null);
|
||||
}
|
||||
});
|
||||
menuDiy.setOnClickListener(v -> {
|
||||
menu2Back.setTag("makeup");
|
||||
changeRecyclerItemCount(5);
|
||||
menuDiy.setVisibility(GONE);
|
||||
ArrayList<MakeupCustomClassBean> list = MakeupSource.buildCustomClasses();
|
||||
setTab(createTabs(list));
|
||||
});
|
||||
menu2Reset.setOnClickListener(view -> {
|
||||
containerAdapter.reset();
|
||||
});
|
||||
|
||||
contrast.setOnTouchListener((v, event) -> {
|
||||
if (iFaceUnityInter == null) {
|
||||
return false;
|
||||
}
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
iFaceUnityInter.onPause();
|
||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
iFaceUnityInter.onStart();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 对比接口
|
||||
*/
|
||||
public void setIFaceUnityInter(IFaceUnityInter iFaceUnityInter) {
|
||||
this.iFaceUnityInter = iFaceUnityInter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回到默认界面
|
||||
*/
|
||||
private void goBackMainMenu() {
|
||||
setContainerRecycler(new ArrayList<>());
|
||||
title.setText("美顏特效選擇");
|
||||
titleLayout.setVisibility(VISIBLE);
|
||||
title.setVisibility(VISIBLE);
|
||||
menu2.setVisibility(GONE);
|
||||
menuGroup.setVisibility(VISIBLE);
|
||||
menuDiy.setVisibility(GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 目前只需要美颜功能,进入后直奔美颜
|
||||
*/
|
||||
private void gotoFaceBeauty() {
|
||||
LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>();
|
||||
map.put(R.string.beauty_radio_skin_beauty, FaceParam.FACE_BEAUTY_SKIN);
|
||||
map.put(R.string.beauty_radio_face_shape, FaceParam.FACE_BEAUTY_SHAPE);
|
||||
map.put(R.string.beauty_radio_filter, FaceParam.FACE_BEAUTY_FILTER);
|
||||
map.put(R.string.beauty_radio_style, FaceParam.FACE_BEAUTY_STYLE);
|
||||
setContainerRecycler(FaceBeautySource.buildSkinParams());
|
||||
changeRecyclerItemCount(2);
|
||||
setTab(createTabs(map));
|
||||
menuGroup.setVisibility(GONE);
|
||||
titleLayout.setVisibility(GONE);
|
||||
back.setVisibility(GONE);
|
||||
menu2Back.setVisibility(GONE);
|
||||
menu2.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置主菜单
|
||||
*/
|
||||
private void initMenuGroup() {
|
||||
MenuGroupRecyclerAdapter adapter = new MenuGroupRecyclerAdapter(mContext);
|
||||
menuGroup.setLayoutManager(new GridLayoutManager(mContext, 4));
|
||||
List<MenuGroupBean> layoutItem = new ArrayList<>();
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_beauty, R.mipmap.ico_home_beauty));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_makeup, R.mipmap.ico_home_makeup));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_beauty_body, R.mipmap.ico_home_beauty_body));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_big_head, R.mipmap.ico_home_big_head));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_animoji, R.mipmap.ico_home_animoji));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_sticker, R.mipmap.ico_home_sticker));
|
||||
layoutItem.add(new MenuGroupBean(R.string.home_function_name_fine_sticker, R.mipmap.ico_home_fine_sticker));
|
||||
adapter.setList(layoutItem);
|
||||
adapter.setOnItemClickListener(position -> {
|
||||
LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>();
|
||||
title.setVisibility(GONE);
|
||||
switch (position) {
|
||||
case 0:
|
||||
map.put(R.string.beauty_radio_skin_beauty, FaceParam.FACE_BEAUTY_SKIN);
|
||||
map.put(R.string.beauty_radio_face_shape, FaceParam.FACE_BEAUTY_SHAPE);
|
||||
map.put(R.string.beauty_radio_filter, FaceParam.FACE_BEAUTY_FILTER);
|
||||
map.put(R.string.beauty_radio_style, FaceParam.FACE_BEAUTY_STYLE);
|
||||
setContainerRecycler(FaceBeautySource.buildSkinParams());
|
||||
break;
|
||||
case 1:
|
||||
title.setText(R.string.home_function_name_makeup);
|
||||
title.setVisibility(VISIBLE);
|
||||
menuDiy.setVisibility(VISIBLE);
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCombinations());
|
||||
break;
|
||||
case 2:
|
||||
title.setText(R.string.home_function_name_beauty_body);
|
||||
title.setVisibility(VISIBLE);
|
||||
changeRecyclerItemCount(2);
|
||||
setContainerRecycler(BodyBeautySource.buildBodyBeauty());
|
||||
break;
|
||||
case 3:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(PropSource.buildPropBeans(FunctionEnum.BIG_HEAD));
|
||||
break;
|
||||
case 4:
|
||||
changeRecyclerItemCount(5);
|
||||
map.put(R.string.animoji_filter, FaceParam.FACE_ANIMOJI);
|
||||
map.put(R.string.cartoon_filter, FaceParam.FACE_ANIM);
|
||||
setContainerRecycler(AnimojiSource.buildAnimojis());
|
||||
break;
|
||||
case 5:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(PropSource.buildPropBeans(FunctionEnum.STICKER));
|
||||
break;
|
||||
case 6:
|
||||
List<FineStickerTagEntity> tagList = FineStickerDataFactory.getInstance().loadTagList();
|
||||
if (!tagList.isEmpty()) {
|
||||
setTab(createTabs(tagList));
|
||||
}
|
||||
break;
|
||||
}
|
||||
setTab(createTabs(map));
|
||||
menuGroup.setVisibility(GONE);
|
||||
menu2.setVisibility(VISIBLE);
|
||||
});
|
||||
menuGroup.setAdapter(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Tab
|
||||
*/
|
||||
private List<TabLayout.Tab> createTabs(Map<Integer, Integer> map) {
|
||||
List<TabLayout.Tab> list = new ArrayList<>();
|
||||
for (Integer key : map.keySet()) {
|
||||
TabLayout.Tab tab = tabLayout.newTab().setText(key);
|
||||
tab.setTag(map.get(key));
|
||||
list.add(tab);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建菜单
|
||||
*/
|
||||
private List<TabLayout.Tab> createTabs(List<FineStickerTagEntity> tags) {
|
||||
List<TabLayout.Tab> list = new ArrayList<>();
|
||||
for (FineStickerTagEntity tag : tags) {
|
||||
TabLayout.Tab tab;
|
||||
if (WordUtil.isZh()) {
|
||||
tab = tabLayout.newTab().setText(tag.getTag().split("/")[0]);
|
||||
} else {
|
||||
tab = tabLayout.newTab().setText(tag.getTag().split("/")[1]);
|
||||
}
|
||||
tab.setTag(tag);
|
||||
list.add(tab);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建菜单
|
||||
*/
|
||||
private List<TabLayout.Tab> createTabs(ArrayList<MakeupCustomClassBean> tags) {
|
||||
List<TabLayout.Tab> list = new ArrayList<>();
|
||||
for (MakeupCustomClassBean tag : tags) {
|
||||
TabLayout.Tab tab;
|
||||
tab = tabLayout.newTab().setText(tag.getDesRes());
|
||||
tab.setTag(tag.getBeanType());
|
||||
list.add(tab);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置菜单
|
||||
*/
|
||||
private void setTab(List<TabLayout.Tab> tabs) {
|
||||
tabLayout.removeAllTabs();
|
||||
for (TabLayout.Tab tab : tabs) {
|
||||
tabLayout.addTab(tab);
|
||||
if (tab.getTag() instanceof Integer) {
|
||||
if (FaceSPUtils.getInstance().getString(StyleViewHolder.class.getSimpleName() + "_") != null && (int) tab.getTag() == FaceParam.FACE_BEAUTY_STYLE) {
|
||||
ToastUtil.show("请先重置风格推荐");
|
||||
tab.select();
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(FaceBeautySource.buildStylesParams());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
Object tabTag = tab.getTag();
|
||||
if (tabTag instanceof Integer) {
|
||||
if (FaceSPUtils.getInstance().getString(StyleViewHolder.class.getSimpleName() + "_") != null && (int) tab.getTag() < FaceParam.FACE_BEAUTY_STYLE) {
|
||||
ToastUtil.show("请先重置风格推荐");
|
||||
tabLayout.getTabAt(3).select();
|
||||
return;
|
||||
}
|
||||
switch ((int) tab.getTag()) {
|
||||
case FaceParam.FACE_BEAUTY_SKIN:
|
||||
changeRecyclerItemCount(2);
|
||||
setContainerRecycler(FaceBeautySource.buildSkinParams());
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_SHAPE:
|
||||
changeRecyclerItemCount(2);
|
||||
setContainerRecycler(FaceBeautySource.buildShapeParams());
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_FILTER:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(FaceBeautySource.buildFilters());
|
||||
break;
|
||||
case FaceParam.FACE_BEAUTY_STYLE:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(FaceBeautySource.buildStylesParams());
|
||||
break;
|
||||
case FaceParam.FACE_ANIMOJI:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(AnimojiSource.buildAnimojis());
|
||||
break;
|
||||
case FaceParam.FACE_ANIM:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(AnimojiSource.buildFilters());
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_FOUNDATION:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_FOUNDATION));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_LIP_STICK:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_LIP_STICK));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_BLUSHER:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_BLUSHER));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_BROW:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_BROW));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_SHADOW));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_LINER:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_LINER));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_LASH:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_LASH));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_HIGH_LIGHT));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_SHADOW:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_SHADOW));
|
||||
break;
|
||||
case FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL:
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_PUPIL));
|
||||
break;
|
||||
default:
|
||||
setContainerRecycler(new ArrayList<>());
|
||||
}
|
||||
} else if (tabTag instanceof FineStickerTagEntity) {
|
||||
FineStickerTagEntity tag = (FineStickerTagEntity) tabTag;
|
||||
FineStickerEntity sticker = FineStickerDataFactory.getInstance().loadStickerList(tag);
|
||||
ArrayList<FineStickerEntity.DocsBean> list = new ArrayList<>();
|
||||
FineStickerEntity.DocsBean docsBean = new FineStickerEntity.DocsBean();
|
||||
docsBean.set_id("-1");
|
||||
list.add(docsBean);
|
||||
list.addAll(sticker.getDocs());
|
||||
changeRecyclerItemCount(5);
|
||||
setContainerRecycler(list);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置美颜选项配置行数,图标为5个,拖动条为2个
|
||||
*
|
||||
* @param count
|
||||
*/
|
||||
private void changeRecyclerItemCount(int count) {
|
||||
containerRecycler.setLayoutManager(new GridLayoutManager(mContext, count));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置美颜Recycler内容
|
||||
*
|
||||
* @param list
|
||||
*/
|
||||
private void setContainerRecycler(ArrayList<? extends BaseBean> list) {
|
||||
if (containerAdapter == null) {
|
||||
containerAdapter = new ContainerRecyclerAdapter(mContext);
|
||||
containerAdapter.setSeekBar(seekBar);
|
||||
containerRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));
|
||||
containerRecycler.setAdapter(containerAdapter);
|
||||
}
|
||||
// titleLayout.setVisibility(title.getVisibility()==GONE?INVISIBLE:VISIBLE);
|
||||
// Log.i(TAG, "setContainerRecycler: " + list.size());
|
||||
containerAdapter.setList(list);
|
||||
containerAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetTags(String[] tags) {
|
||||
List<FineStickerTagEntity> list = FineStickerDataFactory.formatTag(tags);
|
||||
setTab(createTabs(list));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetList(String tag, FineStickerEntity fineSticker) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownload(FineStickerEntity.DocsBean entity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadError(FineStickerEntity.DocsBean entity, String msg) {
|
||||
|
||||
}
|
||||
|
||||
public interface IFaceUnityInter {
|
||||
void onPause();
|
||||
|
||||
void onStart();
|
||||
}
|
||||
}
|
1259
FaceUnity/src/main/java/com/yunbao/faceunity/utils/Authpack.java
Normal file
1259
FaceUnity/src/main/java/com/yunbao/faceunity/utils/Authpack.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,172 @@
|
||||
package com.yunbao.faceunity.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
/**
|
||||
* cpu使用率获取工具类
|
||||
* Created by lirui on 2017/8/2.
|
||||
*/
|
||||
|
||||
public class CPUInfoUtil {
|
||||
private long lastTotalCpu = 0;
|
||||
private long lastProcessCpu = 0;
|
||||
|
||||
private final String PackageName;
|
||||
|
||||
private volatile boolean isRunningCPU = false;
|
||||
private volatile double cpuRate = 0;
|
||||
|
||||
public CPUInfoUtil(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
final String pn = context.getPackageName();
|
||||
if (pn.length() <= 16) {
|
||||
PackageName = pn;
|
||||
} else {
|
||||
PackageName = pn.substring(0, 15) + "+";
|
||||
}
|
||||
// Log.e(TAG, "CSVUtils PackageName " + PackageName);
|
||||
isRunningCPU = true;
|
||||
CPUInfoThread cpuinfothread = new CPUInfoThread();
|
||||
cpuinfothread.start();
|
||||
} else {
|
||||
PackageName = null;
|
||||
}
|
||||
}
|
||||
|
||||
public double getProcessCpuUsed() {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
return cpuRate;
|
||||
} else {
|
||||
double pcpu = 0;
|
||||
double tmp = 1.0;
|
||||
long nowTotalCpu = getTotalCpu();
|
||||
long nowProcessCpu = getMyProcessCpu();
|
||||
if (nowTotalCpu != 0 && (nowTotalCpu - lastTotalCpu) != 0) {
|
||||
// Log.e(TAG, "cpu used nowProcessCpu " + nowProcessCpu + " lastProcessCpu " + lastProcessCpu + " nowTotalCpu " + nowTotalCpu + " lastTotalCpu " + lastTotalCpu);
|
||||
pcpu = 100 * (tmp * (nowProcessCpu - lastProcessCpu) / (nowTotalCpu - lastTotalCpu));
|
||||
}
|
||||
lastProcessCpu = nowProcessCpu;
|
||||
lastTotalCpu = nowTotalCpu;
|
||||
return pcpu < 0 ? 0 : pcpu;
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
isRunningCPU = false;
|
||||
}
|
||||
}
|
||||
|
||||
private long getTotalCpu() {
|
||||
String[] cpuInfos = null;
|
||||
try {
|
||||
RandomAccessFile reader = null;
|
||||
reader = new RandomAccessFile("/proc/stat", "r");
|
||||
String load = reader.readLine();
|
||||
reader.close();
|
||||
cpuInfos = load.split(" ");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
long totalCpu = 0;
|
||||
try {
|
||||
totalCpu = Long.parseLong(cpuInfos[2])
|
||||
+ Long.parseLong(cpuInfos[3]) + Long.parseLong(cpuInfos[4])
|
||||
+ Long.parseLong(cpuInfos[6]) + Long.parseLong(cpuInfos[5])
|
||||
+ Long.parseLong(cpuInfos[7]) + Long.parseLong(cpuInfos[8]);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
return totalCpu;
|
||||
}
|
||||
|
||||
private long getMyProcessCpu() {
|
||||
String[] cpuInfos = null;
|
||||
try {
|
||||
int pid = android.os.Process.myPid();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream("/proc/" + pid + "/stat")), 1000);
|
||||
String load = reader.readLine();
|
||||
reader.close();
|
||||
cpuInfos = load.split(" ");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
long appCpuTime = 0;
|
||||
try {
|
||||
appCpuTime = Long.parseLong(cpuInfos[13])
|
||||
+ Long.parseLong(cpuInfos[14]) + Long.parseLong(cpuInfos[15])
|
||||
+ Long.parseLong(cpuInfos[16]);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
return appCpuTime;
|
||||
}
|
||||
|
||||
class CPUInfoThread extends Thread {
|
||||
|
||||
private double allCPU = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
String line = null;
|
||||
InputStream is = null;
|
||||
try {
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
Process proc = runtime.exec("top -d 1");
|
||||
is = proc.getInputStream();
|
||||
|
||||
// 换成BufferedReader
|
||||
BufferedReader buf = new BufferedReader(new InputStreamReader(is));
|
||||
do {
|
||||
line = buf.readLine();
|
||||
if (allCPU == 0 && line.contains("user") && line.contains("nice") && line.contains("sys") && line.contains("idle") && line.contains("iow") && line.contains("irq") && line.contains("sirq") && line.contains("host")) {
|
||||
if (line.indexOf("%cpu ") > 0)
|
||||
allCPU = Double.parseDouble(line.split("%cpu ")[0]);
|
||||
if (allCPU == 0) {
|
||||
String[] s = line.split("%,");
|
||||
for (String st : s) {
|
||||
String[] sts = st.split(" ");
|
||||
if (sts.length > 0)
|
||||
allCPU += Double.parseDouble(sts[sts.length - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 读取到相应pkgName跳出循环(或者未找到)
|
||||
if (line == null || line.endsWith(PackageName)) {
|
||||
// Log.e(TAG, "cpu line : " + line);
|
||||
String str[] = line.split(" ");
|
||||
int t = 0;
|
||||
for (int i = str.length - 1; i > 0; i--) {
|
||||
if (!str[i].isEmpty() && ++t == 4) {
|
||||
// Log.e(TAG, "cpu : " + str[i] + " allCPU " + allCPU);
|
||||
cpuRate = 100 * Double.parseDouble(str[i]) / allCPU;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} while (isRunningCPU);
|
||||
|
||||
if (is != null) {
|
||||
buf.close();
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
168
FaceUnity/src/main/java/com/yunbao/faceunity/utils/CSVUtils.java
Normal file
168
FaceUnity/src/main/java/com/yunbao/faceunity/utils/CSVUtils.java
Normal file
@ -0,0 +1,168 @@
|
||||
package com.yunbao.faceunity.utils;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by tujh on 2017/11/2.
|
||||
*/
|
||||
public class CSVUtils {
|
||||
public static final String TAG = CSVUtils.class.getSimpleName();
|
||||
/* 每 100 帧统计一次 */
|
||||
public static final int FRAME_STEP = 100;
|
||||
|
||||
public static final String COMMA = ",";
|
||||
|
||||
private OutputStreamWriter mStreamWriter;
|
||||
|
||||
private ActivityManager mActivityManager;
|
||||
|
||||
private Handler mHandler;
|
||||
|
||||
private CPUInfoUtil mCPUInfoUtil;
|
||||
|
||||
private int mFrameRate;
|
||||
private volatile double mCpuUsed;
|
||||
private volatile double mAverageFps;
|
||||
private volatile double mAverageRenderTime;
|
||||
private volatile double mMemory;
|
||||
private long mSumRenderTimeInNano;
|
||||
private volatile long mTimestamp;
|
||||
|
||||
public CSVUtils(Context context) {
|
||||
mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
mCPUInfoUtil = new CPUInfoUtil(context);
|
||||
|
||||
HandlerThread handlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
|
||||
handlerThread.start();
|
||||
mHandler = new Handler(handlerThread.getLooper());
|
||||
}
|
||||
|
||||
public void initHeader(String folderName, StringBuilder headerInfo) {
|
||||
Log.d(TAG, "initHeader() called with: folderName = [" + folderName + "], headerInfo = [" + headerInfo + "]");
|
||||
StringBuilder stringBuilder = new StringBuilder().append("时间").append(COMMA)
|
||||
.append("帧率").append(COMMA)
|
||||
.append("渲染耗时").append(COMMA)
|
||||
.append("CPU").append(COMMA)
|
||||
.append("内存").append(COMMA);
|
||||
if (headerInfo != null) {
|
||||
stringBuilder.append(headerInfo);
|
||||
}
|
||||
stringBuilder.append("\n");
|
||||
|
||||
File file = new File(folderName);
|
||||
File parentFile = file.getParentFile();
|
||||
if (!parentFile.exists()) {
|
||||
parentFile.mkdirs();
|
||||
}
|
||||
try {
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
mStreamWriter = new OutputStreamWriter(new FileOutputStream(file, false), "GBK");
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "CSVUtils: ", e);
|
||||
}
|
||||
flush(stringBuilder);
|
||||
mTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void writeCsv(final StringBuilder extraInfo, long renderTimeInNano) {
|
||||
if (mStreamWriter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSumRenderTimeInNano += renderTimeInNano;
|
||||
if (mFrameRate % FRAME_STEP == FRAME_STEP - 1) {
|
||||
mTimestamp = System.currentTimeMillis();
|
||||
mAverageFps = FPSUtil.fpsAVG(FRAME_STEP);
|
||||
mAverageRenderTime = (double) mSumRenderTimeInNano / FRAME_STEP / 1_000_000;
|
||||
mSumRenderTimeInNano = 0;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCpuUsed = mCPUInfoUtil.getProcessCpuUsed();
|
||||
mMemory = MemoryInfoUtil.getMemory(mActivityManager.getProcessMemoryInfo(new int[]{Process.myPid()}));
|
||||
String strCPU = String.format(Locale.getDefault(), "%.2f", mCpuUsed);
|
||||
String strMemory = String.format(Locale.getDefault(), "%.2f", mMemory);
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS", Locale.getDefault());
|
||||
|
||||
stringBuilder.append(dateFormat.format(new Date(mTimestamp))).append(COMMA)
|
||||
.append(String.format(Locale.getDefault(), "%.2f", mAverageFps)).append(COMMA)
|
||||
.append(String.format(Locale.getDefault(), "%.2f", mAverageRenderTime)).append(COMMA)
|
||||
.append(strCPU).append(COMMA)
|
||||
.append(strMemory).append(COMMA);
|
||||
|
||||
if (extraInfo != null) {
|
||||
stringBuilder.append(extraInfo);
|
||||
}
|
||||
stringBuilder.append("\n");
|
||||
flush(stringBuilder);
|
||||
}
|
||||
});
|
||||
}
|
||||
mFrameRate++;
|
||||
}
|
||||
|
||||
private void flush(StringBuilder stringBuilder) {
|
||||
if (mStreamWriter == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mStreamWriter.write(stringBuilder.toString());
|
||||
mStreamWriter.flush();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "flush: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
Log.d(TAG, "close: ");
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mStreamWriter != null) {
|
||||
try {
|
||||
mStreamWriter.close();
|
||||
mStreamWriter = null;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "close: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
mHandler.getLooper().quitSafely();
|
||||
mHandler = null;
|
||||
mCPUInfoUtil.close();
|
||||
}
|
||||
|
||||
public double getCpuUsed() {
|
||||
return mCpuUsed;
|
||||
}
|
||||
|
||||
public double getMemory() {
|
||||
return mMemory;
|
||||
}
|
||||
|
||||
public double getAverageRenderTime() {
|
||||
return mAverageRenderTime;
|
||||
}
|
||||
|
||||
public double getAverageFps() {
|
||||
return mAverageFps;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.yunbao.faceunity.utils;
|
||||
|
||||
/**
|
||||
* FPS工具类
|
||||
* Created by tujh on 2018/5/24.
|
||||
*/
|
||||
public class FPSUtil {
|
||||
private static final int NANO_IN_ONE_MILLI_SECOND = 1000000;
|
||||
private static final int NANO_IN_ONE_SECOND = 1000 * NANO_IN_ONE_MILLI_SECOND;
|
||||
|
||||
private static long sLastFrameTimeStamp = 0;
|
||||
|
||||
/**
|
||||
* 每帧都计算
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static double fps() {
|
||||
long tmp = System.nanoTime();
|
||||
double fps = ((double) NANO_IN_ONE_SECOND) / (tmp - sLastFrameTimeStamp);
|
||||
sLastFrameTimeStamp = tmp;
|
||||
// Log.e(TAG, "FPS : " + fps);
|
||||
return fps;
|
||||
}
|
||||
|
||||
private static long mStartTime = 0;
|
||||
|
||||
/**
|
||||
* 平均值
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static double fpsAVG(int time) {
|
||||
long tmp = System.nanoTime();
|
||||
double fps = ((double) NANO_IN_ONE_SECOND) * time / (tmp - mStartTime);
|
||||
mStartTime = tmp;
|
||||
// Log.e(TAG, "FPS : " + fps);
|
||||
return fps;
|
||||
}
|
||||
|
||||
private long mLimitMinTime = 33333333;
|
||||
private long mLimitStartTime;
|
||||
private int mLimitFrameRate;
|
||||
|
||||
public void setLimitMinTime(long limitMinTime) {
|
||||
mLimitMinTime = limitMinTime;
|
||||
}
|
||||
|
||||
public void limit() {
|
||||
try {
|
||||
if (mLimitFrameRate == 0 || mLimitFrameRate > 600000) {
|
||||
mLimitStartTime = System.nanoTime();
|
||||
mLimitFrameRate = 0;
|
||||
}
|
||||
long sleepTime = mLimitMinTime * mLimitFrameRate++ - (System.nanoTime() - mLimitStartTime);
|
||||
if (sleepTime > 0) {
|
||||
Thread.sleep(sleepTime / NANO_IN_ONE_MILLI_SECOND, (int) (sleepTime % NANO_IN_ONE_MILLI_SECOND));
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,326 @@
|
||||
package com.yunbao.faceunity.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Camera;
|
||||
|
||||
import com.faceunity.core.callback.OperateCallback;
|
||||
import com.faceunity.core.entity.FURenderInputData;
|
||||
import com.faceunity.core.entity.FURenderOutputData;
|
||||
import com.faceunity.core.enumeration.CameraFacingEnum;
|
||||
import com.faceunity.core.enumeration.FUAIProcessorEnum;
|
||||
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||
import com.faceunity.core.faceunity.FURenderConfig;
|
||||
import com.faceunity.core.faceunity.FURenderKit;
|
||||
import com.faceunity.core.faceunity.FURenderManager;
|
||||
import com.faceunity.core.utils.CameraUtils;
|
||||
import com.faceunity.core.utils.FULogger;
|
||||
import com.yunbao.faceunity.listener.FURendererListener;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* DESC:
|
||||
* Created on 2021/4/26
|
||||
*/
|
||||
public class FURenderer extends IFURenderer {
|
||||
|
||||
private static final String TAG = "FURenderer";
|
||||
|
||||
public volatile static FURenderer INSTANCE;
|
||||
|
||||
public static FURenderer getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (FURenderer.class) {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new FURenderer();
|
||||
INSTANCE.mFURenderKit = FURenderKit.getInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态回调监听
|
||||
*/
|
||||
private FURendererListener mFURendererListener;
|
||||
|
||||
|
||||
/* 特效FURenderKit*/
|
||||
private FURenderKit mFURenderKit;
|
||||
|
||||
/* AI道具*/
|
||||
public static String BUNDLE_AI_FACE = "model" + File.separator + "ai_face_processor_lite.bundle";
|
||||
public static String BUNDLE_AI_HUMAN = "model" + File.separator + "ai_human_processor.bundle";
|
||||
|
||||
/* GL 线程 ID */
|
||||
private Long mGlThreadId = 0L;
|
||||
/* 任务队列 */
|
||||
private ArrayList<Runnable> mEventQueue = new ArrayList<>(16);
|
||||
private final Object queueLock = new Object();
|
||||
/* 渲染开关标识 */
|
||||
private volatile boolean mRendererSwitch = false;
|
||||
/* 清除队列标识 */
|
||||
private volatile boolean mClearQueue = false;
|
||||
|
||||
/* 相机角度-朝向映射 */
|
||||
private HashMap<Integer, CameraFacingEnum> cameraOrientationMap = new HashMap<>();
|
||||
|
||||
/*检测类型*/
|
||||
private FUAIProcessorEnum aIProcess = FUAIProcessorEnum.FACE_PROCESSOR;
|
||||
/*检测标识*/
|
||||
private int aIProcessTrackStatus = -1;
|
||||
|
||||
public String getVersion() {
|
||||
return mFURenderKit.getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化鉴权
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
@Override
|
||||
public void setup(Context context) {
|
||||
FURenderManager.setKitDebug(FULogger.LogLevel.INFO);
|
||||
FURenderManager.setCoreDebug(FULogger.LogLevel.INFO);
|
||||
FURenderManager.registerFURender(context, Authpack.A(), new OperateCallback() {
|
||||
@Override
|
||||
public void onSuccess(int i, @NotNull String s) {
|
||||
if (i == FURenderConfig.OPERATE_SUCCESS_AUTH) {
|
||||
mFURenderKit.getFUAIController().loadAIProcessor(BUNDLE_AI_FACE, FUAITypeEnum.FUAITYPE_FACEPROCESSOR);
|
||||
mFURenderKit.getFUAIController().loadAIProcessor(BUNDLE_AI_HUMAN, FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||
mFURenderKit.setReadBackSync(true);
|
||||
int cameraFrontOrientation = CameraUtils.INSTANCE.getCameraOrientation(Camera.CameraInfo.CAMERA_FACING_FRONT);
|
||||
int cameraBackOrientation = CameraUtils.INSTANCE.getCameraOrientation(Camera.CameraInfo.CAMERA_FACING_BACK);
|
||||
cameraOrientationMap.put(cameraFrontOrientation, CameraFacingEnum.CAMERA_FRONT);
|
||||
cameraOrientationMap.put(cameraBackOrientation, CameraFacingEnum.CAMERA_BACK);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(int i, @NotNull String s) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启合成状态
|
||||
*/
|
||||
@Override
|
||||
public void prepareRenderer(FURendererListener mFURendererListener) {
|
||||
this.mFURendererListener = mFURendererListener;
|
||||
mRendererSwitch = true;
|
||||
mClearQueue = false;
|
||||
queueEvent(() -> mGlThreadId = Thread.currentThread().getId());
|
||||
mFURendererListener.onPrepare();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 双输入接口,输入 buffer 和 texture,必须在具有 GL 环境的线程调用
|
||||
* 由于省去数据拷贝,性能相对最优,优先推荐使用。
|
||||
* 缺点是无法保证 buffer 和纹理对齐,可能出现点位和效果对不上的情况。
|
||||
*
|
||||
* @param img NV21 buffer
|
||||
* @param texId 纹理 ID
|
||||
* @param width 宽
|
||||
* @param height 高
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int onDrawFrameDualInput(byte[] img, int texId, int width, int height) {
|
||||
prepareDrawFrame();
|
||||
if (!mRendererSwitch) {
|
||||
return texId;
|
||||
}
|
||||
FURenderInputData inputData = new FURenderInputData(width, height);
|
||||
if (img != null) {
|
||||
inputData.setImageBuffer(new FURenderInputData.FUImageBuffer(inputBufferType, img));
|
||||
}
|
||||
if (texId != -1) {
|
||||
inputData.setTexture(new FURenderInputData.FUTexture(inputTextureType, texId));
|
||||
}
|
||||
FURenderInputData.FURenderConfig config = inputData.getRenderConfig();
|
||||
config.setExternalInputType(externalInputType);
|
||||
config.setInputOrientation(inputOrientation);
|
||||
config.setDeviceOrientation(deviceOrientation);
|
||||
config.setInputBufferMatrix(inputBufferMatrix);
|
||||
config.setInputTextureMatrix(inputTextureMatrix);
|
||||
config.setOutputMatrix(outputMatrix);
|
||||
config.setCameraFacing(cameraFacing);
|
||||
FURenderOutputData outputData = mFURenderKit.renderWithInput(inputData);
|
||||
if (outputData.getTexture() != null && outputData.getTexture().getTexId() > 0) {
|
||||
return outputData.getTexture().getTexId();
|
||||
}
|
||||
return texId;
|
||||
}
|
||||
|
||||
public FURenderOutputData onDrawFrameInputWithReturn(byte[] img, int width, int height) {
|
||||
prepareDrawFrame();
|
||||
if (!mRendererSwitch) {
|
||||
return null ;
|
||||
}
|
||||
FURenderInputData inputData = new FURenderInputData(width, height);
|
||||
if (img != null) {
|
||||
inputData.setImageBuffer(new FURenderInputData.FUImageBuffer(inputBufferType, img));
|
||||
}
|
||||
FURenderInputData.FURenderConfig config = inputData.getRenderConfig();
|
||||
config.setExternalInputType(externalInputType);
|
||||
config.setInputOrientation(inputOrientation);
|
||||
config.setDeviceOrientation(deviceOrientation);
|
||||
config.setInputBufferMatrix(inputBufferMatrix);
|
||||
config.setInputTextureMatrix(inputTextureMatrix);
|
||||
config.setCameraFacing(cameraFacing);
|
||||
config.setNeedBufferReturn(true);
|
||||
config.setOutputMatrix(outputMatrix);
|
||||
return mFURenderKit.renderWithInput(inputData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 类似 GLSurfaceView 的 queueEvent 机制,把任务抛到 GL 线程执行。
|
||||
*
|
||||
* @param runnable
|
||||
*/
|
||||
@Override
|
||||
public void queueEvent(Runnable runnable) {
|
||||
if (runnable == null) {
|
||||
return;
|
||||
}
|
||||
if (mGlThreadId == Thread.currentThread().getId()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
synchronized (queueLock) {
|
||||
mEventQueue.add(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
@Override
|
||||
public void release() {
|
||||
mRendererSwitch = false;
|
||||
mClearQueue = true;
|
||||
mGlThreadId = 0L;
|
||||
synchronized (queueLock) {
|
||||
mEventQueue.clear();
|
||||
mClearQueue = false;
|
||||
mFURenderKit.release();
|
||||
aIProcessTrackStatus = -1;
|
||||
if (mFURendererListener != null) {
|
||||
mFURendererListener.onRelease();
|
||||
mFURendererListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 渲染前置执行
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private void prepareDrawFrame() {
|
||||
benchmarkFPS();
|
||||
|
||||
// 执行任务队列中的任务
|
||||
synchronized (queueLock) {
|
||||
while (!mEventQueue.isEmpty() && !mClearQueue) {
|
||||
mEventQueue.remove(0).run();
|
||||
}
|
||||
}
|
||||
// AI检测
|
||||
trackStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置检测类型
|
||||
*
|
||||
* @param type
|
||||
*/
|
||||
@Override
|
||||
public void setAIProcessTrackType(FUAIProcessorEnum type) {
|
||||
aIProcess = type;
|
||||
aIProcessTrackStatus = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置FPS检测
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
@Override
|
||||
public void setMarkFPSEnable(boolean enable) {
|
||||
mIsRunBenchmark = enable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputOrientation(int inputOrientation) {
|
||||
if (cameraOrientationMap.containsKey(inputOrientation)) {
|
||||
setCameraFacing(cameraOrientationMap.get(inputOrientation));
|
||||
}
|
||||
super.setInputOrientation(inputOrientation);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI识别数目检测
|
||||
*/
|
||||
private void trackStatus() {
|
||||
int trackCount;
|
||||
if (aIProcess == FUAIProcessorEnum.HAND_GESTURE_PROCESSOR) {
|
||||
trackCount = mFURenderKit.getFUAIController().handProcessorGetNumResults();
|
||||
} else if (aIProcess == FUAIProcessorEnum.HUMAN_PROCESSOR) {
|
||||
trackCount = mFURenderKit.getFUAIController().humanProcessorGetNumResults();
|
||||
} else {
|
||||
trackCount = mFURenderKit.getFUAIController().isTracking();
|
||||
}
|
||||
if (trackCount != aIProcessTrackStatus) {
|
||||
aIProcessTrackStatus = trackCount;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (mFURendererListener != null) {
|
||||
mFURendererListener.onTrackStatusChanged(aIProcess, trackCount);
|
||||
}
|
||||
}
|
||||
//endregion AI识别
|
||||
|
||||
//------------------------------FPS 渲染时长回调相关定义------------------------------------
|
||||
|
||||
private static final int NANO_IN_ONE_MILLI_SECOND = 1_000_000;
|
||||
private static final int NANO_IN_ONE_SECOND = 1_000_000_000;
|
||||
private static final int FRAME_COUNT = 20;
|
||||
private boolean mIsRunBenchmark = false;
|
||||
private int mCurrentFrameCount;
|
||||
private long mLastFrameTimestamp;
|
||||
private long mSumCallTime;
|
||||
private long mCallStartTime;
|
||||
|
||||
private void benchmarkFPS() {
|
||||
if (!mIsRunBenchmark) {
|
||||
return;
|
||||
}
|
||||
if (++mCurrentFrameCount == FRAME_COUNT) {
|
||||
long tmp = System.nanoTime();
|
||||
double fps = (double) NANO_IN_ONE_SECOND / ((double) (tmp - mLastFrameTimestamp) / FRAME_COUNT);
|
||||
double renderTime = (double) mSumCallTime / FRAME_COUNT / NANO_IN_ONE_MILLI_SECOND;
|
||||
mLastFrameTimestamp = tmp;
|
||||
mSumCallTime = 0;
|
||||
mCurrentFrameCount = 0;
|
||||
|
||||
if (mFURendererListener != null) {
|
||||
mFURendererListener.onFpsChanged(fps, renderTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
271
FaceUnity/src/main/java/com/yunbao/faceunity/utils/FUUtils.java
Normal file
271
FaceUnity/src/main/java/com/yunbao/faceunity/utils/FUUtils.java
Normal file
@ -0,0 +1,271 @@
|
||||
package com.yunbao.faceunity.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.faceunity.core.model.facebeauty.FaceBeauty;
|
||||
import com.google.gson.Gson;
|
||||
import com.yunbao.faceunity.data.FaceBeautyData;
|
||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* 将FaceBeauty FaceBeautyData 互相设置
|
||||
*/
|
||||
public class FUUtils {
|
||||
private static final String SP_NAME = "FaceBeauty";
|
||||
private static final String SP_KEY_NAME = "faceBeautyData";
|
||||
|
||||
/**
|
||||
* 将FaceBeauty 转 FaceBeautyData
|
||||
*
|
||||
* @param faceBeautyData
|
||||
*/
|
||||
public static void buildFaceBeautyData(FaceBeautyData faceBeautyData, FaceBeauty faceBeauty, ArrayList<FaceBeautyFilterBean> filterList, int styleTypeIndex) {
|
||||
if (faceBeauty != null) {
|
||||
/* 美肤 */
|
||||
/* 磨皮类型 */
|
||||
faceBeautyData.blurType = faceBeauty.getBlurType();
|
||||
/* 磨皮程度 */
|
||||
faceBeautyData.blurIntensity = faceBeauty.getBlurIntensity();
|
||||
/* 美白程度 */
|
||||
faceBeautyData.colorIntensity = faceBeauty.getColorIntensity();
|
||||
/* 红润程度 */
|
||||
faceBeautyData.redIntensity = faceBeauty.getRedIntensity();
|
||||
/* 锐化程度 */
|
||||
faceBeautyData.sharpenIntensity = faceBeauty.getSharpenIntensity();
|
||||
/* 亮眼程度 */
|
||||
faceBeautyData.eyeBrightIntensity = faceBeauty.getEyeBrightIntensity();
|
||||
/* 美牙程度 */
|
||||
faceBeautyData.toothIntensity = faceBeauty.getToothIntensity();
|
||||
/* 去黑眼圈强度*/
|
||||
faceBeautyData.removePouchIntensity = faceBeauty.getRemovePouchIntensity();
|
||||
/* 去法令纹强度*/
|
||||
faceBeautyData.removeLawPatternIntensity = faceBeauty.getRemoveLawPatternIntensity();
|
||||
|
||||
/* 美型 */
|
||||
/* 瘦脸程度 */
|
||||
faceBeautyData.cheekThinningIntensity = faceBeauty.getCheekThinningIntensity();
|
||||
/* V脸程度 */
|
||||
faceBeautyData.cheekVIntensity = faceBeauty.getCheekVIntensity();
|
||||
/* 窄脸程度 */
|
||||
faceBeautyData.cheekNarrowIntensity = faceBeauty.getCheekNarrowIntensity();
|
||||
/* 短脸程度 */
|
||||
faceBeautyData.cheekShortIntensity = faceBeauty.getCheekShortIntensity();
|
||||
/* 小脸程度 */
|
||||
faceBeautyData.cheekSmallIntensity = faceBeauty.getCheekSmallIntensity();
|
||||
/* 瘦颧骨 */
|
||||
faceBeautyData.cheekBonesIntensity = faceBeauty.getCheekBonesIntensity();
|
||||
/* 瘦下颌骨 */
|
||||
faceBeautyData.lowerJawIntensity = faceBeauty.getLowerJawIntensity();
|
||||
/* 大眼程度 */
|
||||
faceBeautyData.eyeEnlargingIntensity = faceBeauty.getEyeEnlargingIntensity();
|
||||
/* 圆眼程度 */
|
||||
faceBeautyData.eyeCircleIntensity = faceBeauty.getEyeCircleIntensity();
|
||||
/* 下巴调整程度 */
|
||||
faceBeautyData.chinIntensity = faceBeauty.getChinIntensity();
|
||||
/* 额头调整程度 */
|
||||
faceBeautyData.forHeadIntensity = faceBeauty.getForHeadIntensity();
|
||||
/* 瘦鼻程度 */
|
||||
faceBeautyData.noseIntensity = faceBeauty.getNoseIntensity();
|
||||
/* 嘴巴调整程度 */
|
||||
faceBeautyData.mouthIntensity = faceBeauty.getMouthIntensity();
|
||||
/* 开眼角强度 */
|
||||
faceBeautyData.canthusIntensity = faceBeauty.getCanthusIntensity();
|
||||
/* 眼睛间距 */
|
||||
faceBeautyData.eyeSpaceIntensity = faceBeauty.getEyeSpaceIntensity();
|
||||
/* 眼睛角度 */
|
||||
faceBeautyData.eyeRotateIntensity = faceBeauty.getEyeRotateIntensity();
|
||||
/* 鼻子长度 */
|
||||
faceBeautyData.longNoseIntensity = faceBeauty.getLongNoseIntensity();
|
||||
/* 调节人中 */
|
||||
faceBeautyData.philtrumIntensity = faceBeauty.getPhiltrumIntensity();
|
||||
/* 微笑嘴角强度 */
|
||||
faceBeautyData.smileIntensity = faceBeauty.getSmileIntensity();
|
||||
/* 眉毛上下 */
|
||||
faceBeautyData.browHeightIntensity = faceBeauty.getBrowHeightIntensity();
|
||||
/* 眉毛间距 */
|
||||
faceBeautyData.browSpaceIntensity = faceBeauty.getBrowSpaceIntensity();
|
||||
|
||||
/* 滤镜相关 */
|
||||
if (filterList != null) {
|
||||
for (FaceBeautyFilterBean filterBean:filterList) {
|
||||
faceBeautyData.filterMap.put(filterBean.getKey(),filterBean.getIntensity());
|
||||
}
|
||||
}
|
||||
/* 滤镜名称 */
|
||||
faceBeautyData.filterName = faceBeauty.getFilterName();
|
||||
/* 滤镜强度 */
|
||||
faceBeautyData.filterIntensity = faceBeauty.getFilterIntensity();
|
||||
|
||||
/* 是否开启风格 */
|
||||
faceBeautyData.styleTypeIndex = styleTypeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将FaceBeauty 转 FaceBeautyData
|
||||
*
|
||||
* @param faceBeautyData
|
||||
*/
|
||||
public static boolean setFaceBeauty(FaceBeautyData faceBeautyData ,FaceBeauty faceBeauty) {
|
||||
if (faceBeautyData == null) {
|
||||
return false;
|
||||
}
|
||||
if (faceBeauty != null) {
|
||||
/* 如果用户开启了风格推荐 */
|
||||
//下面是否则
|
||||
/* 美肤 */
|
||||
/* 磨皮类型 */
|
||||
if (faceBeautyData.blurType != faceBeauty.getBlurType())
|
||||
faceBeauty.setBlurType(faceBeautyData.blurType);
|
||||
/* 磨皮程度 */
|
||||
if (faceBeautyData.blurIntensity != faceBeauty.getBlurIntensity())
|
||||
faceBeauty.setBlurIntensity(faceBeautyData.blurIntensity);
|
||||
/* 美白程度 */
|
||||
if (faceBeautyData.colorIntensity != faceBeauty.getColorIntensity())
|
||||
faceBeauty.setColorIntensity(faceBeautyData.colorIntensity);
|
||||
/* 红润程度 */
|
||||
if (faceBeautyData.redIntensity != faceBeauty.getRedIntensity())
|
||||
faceBeauty.setRedIntensity(faceBeautyData.redIntensity);
|
||||
/* 锐化程度 */
|
||||
if (faceBeautyData.sharpenIntensity != faceBeauty.getSharpenIntensity())
|
||||
faceBeauty.setSharpenIntensity(faceBeautyData.sharpenIntensity);
|
||||
/* 亮眼程度 */
|
||||
if (faceBeautyData.eyeBrightIntensity != faceBeauty.getEyeBrightIntensity())
|
||||
faceBeauty.setEyeBrightIntensity(faceBeautyData.eyeBrightIntensity);
|
||||
/* 美牙程度 */
|
||||
if (faceBeautyData.toothIntensity != faceBeauty.getToothIntensity())
|
||||
faceBeauty.setToothIntensity(faceBeautyData.toothIntensity);
|
||||
/* 去黑眼圈强度*/
|
||||
if (faceBeautyData.removePouchIntensity != faceBeauty.getRemovePouchIntensity())
|
||||
faceBeauty.setRemovePouchIntensity(faceBeautyData.removePouchIntensity);
|
||||
/* 去法令纹强度*/
|
||||
if (faceBeautyData.removeLawPatternIntensity != faceBeauty.getRemoveLawPatternIntensity())
|
||||
faceBeauty.setRemoveLawPatternIntensity(faceBeautyData.removeLawPatternIntensity);
|
||||
|
||||
/* 美型 */
|
||||
/* 瘦脸程度 */
|
||||
if (faceBeautyData.cheekThinningIntensity != faceBeauty.getCheekThinningIntensity())
|
||||
faceBeauty.setCheekThinningIntensity(faceBeautyData.cheekThinningIntensity);
|
||||
/* V脸程度 */
|
||||
if (faceBeautyData.cheekVIntensity != faceBeauty.getCheekVIntensity())
|
||||
faceBeauty.setCheekVIntensity(faceBeautyData.cheekVIntensity);
|
||||
/* 窄脸程度 */
|
||||
/* V脸程度 */
|
||||
if (faceBeautyData.cheekNarrowIntensity != faceBeauty.getCheekNarrowIntensity())
|
||||
faceBeauty.setCheekNarrowIntensity(faceBeautyData.cheekNarrowIntensity);
|
||||
/* 短脸程度 */
|
||||
if (faceBeautyData.cheekShortIntensity != faceBeauty.getCheekShortIntensity())
|
||||
faceBeauty.setCheekShortIntensity(faceBeautyData.cheekShortIntensity);
|
||||
/* 小脸程度 */
|
||||
if (faceBeautyData.cheekSmallIntensity != faceBeauty.getCheekSmallIntensity())
|
||||
faceBeauty.setCheekSmallIntensity(faceBeautyData.cheekSmallIntensity);
|
||||
/* 瘦颧骨 */
|
||||
if (faceBeautyData.cheekBonesIntensity != faceBeauty.getCheekBonesIntensity())
|
||||
faceBeauty.setCheekBonesIntensity(faceBeautyData.cheekBonesIntensity);
|
||||
/* 瘦下颌骨 */
|
||||
if (faceBeautyData.lowerJawIntensity != faceBeauty.getLowerJawIntensity())
|
||||
faceBeauty.setLowerJawIntensity(faceBeautyData.lowerJawIntensity);
|
||||
/* 大眼程度 */
|
||||
if (faceBeautyData.eyeEnlargingIntensity != faceBeauty.getEyeEnlargingIntensity())
|
||||
faceBeauty.setEyeEnlargingIntensity(faceBeautyData.eyeEnlargingIntensity);
|
||||
/* 圆眼程度 */
|
||||
if (faceBeautyData.eyeCircleIntensity != faceBeauty.getEyeCircleIntensity())
|
||||
faceBeauty.setEyeCircleIntensity(faceBeautyData.eyeCircleIntensity);
|
||||
/* 下巴调整程度 */
|
||||
if (faceBeautyData.chinIntensity != faceBeauty.getChinIntensity())
|
||||
faceBeauty.setChinIntensity(faceBeautyData.chinIntensity);
|
||||
/* 额头调整程度 */
|
||||
if (faceBeautyData.forHeadIntensity != faceBeauty.getForHeadIntensity())
|
||||
faceBeauty.setForHeadIntensity(faceBeautyData.forHeadIntensity);
|
||||
/* 瘦鼻程度 */
|
||||
if (faceBeautyData.noseIntensity != faceBeauty.getNoseIntensity())
|
||||
faceBeauty.setNoseIntensity(faceBeautyData.noseIntensity);
|
||||
/* 嘴巴调整程度 */
|
||||
if (faceBeautyData.mouthIntensity != faceBeauty.getMouthIntensity())
|
||||
faceBeauty.setMouthIntensity(faceBeautyData.mouthIntensity);
|
||||
/* 开眼角强度 */
|
||||
if (faceBeautyData.canthusIntensity != faceBeauty.getCanthusIntensity())
|
||||
faceBeauty.setCanthusIntensity(faceBeautyData.canthusIntensity);
|
||||
/* 眼睛间距 */
|
||||
if (faceBeautyData.eyeSpaceIntensity != faceBeauty.getEyeSpaceIntensity())
|
||||
faceBeauty.setEyeSpaceIntensity(faceBeautyData.eyeSpaceIntensity);
|
||||
/* 眼睛角度 */
|
||||
if (faceBeautyData.eyeRotateIntensity != faceBeauty.getEyeRotateIntensity())
|
||||
faceBeauty.setEyeRotateIntensity(faceBeautyData.eyeRotateIntensity);
|
||||
/* 鼻子长度 */
|
||||
if (faceBeautyData.longNoseIntensity != faceBeauty.getLongNoseIntensity())
|
||||
faceBeauty.setLongNoseIntensity(faceBeautyData.longNoseIntensity);
|
||||
/* 调节人中 */
|
||||
if (faceBeautyData.philtrumIntensity != faceBeauty.getPhiltrumIntensity())
|
||||
faceBeauty.setPhiltrumIntensity(faceBeautyData.philtrumIntensity);
|
||||
/* 微笑嘴角强度 */
|
||||
if (faceBeautyData.smileIntensity != faceBeauty.getSmileIntensity())
|
||||
faceBeauty.setSmileIntensity(faceBeautyData.smileIntensity);
|
||||
/* 眉毛上下 */
|
||||
if (faceBeautyData.browHeightIntensity != faceBeauty.getBrowHeightIntensity())
|
||||
faceBeauty.setBrowHeightIntensity(faceBeautyData.browHeightIntensity);
|
||||
/* 眉毛间距 */
|
||||
if (faceBeautyData.browSpaceIntensity != faceBeauty.getBrowSpaceIntensity())
|
||||
faceBeauty.setBrowSpaceIntensity(faceBeautyData.browSpaceIntensity);
|
||||
|
||||
/* 滤镜相关 */
|
||||
/* 滤镜名称 */
|
||||
if (!faceBeautyData.filterName.equals(faceBeauty.getFilterName()))
|
||||
faceBeauty.setFilterName(faceBeautyData.filterName);
|
||||
if (faceBeautyData.filterIntensity != faceBeauty.getFilterIntensity())
|
||||
faceBeauty.setFilterIntensity(faceBeautyData.filterIntensity);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将FaceBeautyData保存到文件
|
||||
*
|
||||
* @param faceBeautyData
|
||||
*/
|
||||
public static void saveFaceBeautyData2File(FaceBeautyData faceBeautyData, FaceBeauty faceBeauty, ArrayList<FaceBeautyFilterBean> filterList, int styleTypeIndex) {
|
||||
buildFaceBeautyData(faceBeautyData,faceBeauty,filterList,styleTypeIndex);
|
||||
saveFaceBeautyData2File(faceBeautyData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将FaceBeautyData保存到文件
|
||||
*
|
||||
* @param faceBeautyData
|
||||
*/
|
||||
public static void saveFaceBeautyData2File(FaceBeautyData faceBeautyData) {
|
||||
Gson gson = new Gson();
|
||||
String faceBeautyString = gson.toJson(faceBeautyData);
|
||||
saveToSp(SP_KEY_NAME, faceBeautyString);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取bean对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static FaceBeautyData loadFaceBeautyData() {
|
||||
String faceBeautyData = loadFormSp(SP_KEY_NAME);
|
||||
if (faceBeautyData != null && !faceBeautyData.isEmpty()) {
|
||||
Gson gson = new Gson();
|
||||
FaceBeautyData faceBeautyDataBean = gson.fromJson(faceBeautyData, FaceBeautyData.class);
|
||||
return faceBeautyDataBean;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void saveToSp(String key, String value) {
|
||||
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||
sp.edit().putString(key, value).apply();
|
||||
}
|
||||
|
||||
private static String loadFormSp(String key) {
|
||||
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||
return sp.getString(key, "");
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.yunbao.faceunity.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.yunbao.common.CommonAppContext;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class FaceSPUtils {
|
||||
private static FaceSPUtils utils;
|
||||
private SharedPreferences mSharedPreferences;
|
||||
private FaceSPUtils(){
|
||||
mSharedPreferences = CommonAppContext.sInstance.getSharedPreferences("FaceUnityConfig", Context.MODE_PRIVATE);
|
||||
}
|
||||
public static FaceSPUtils getInstance(){
|
||||
if(utils==null){
|
||||
utils=new FaceSPUtils();
|
||||
}
|
||||
return utils;
|
||||
}
|
||||
public void saveString(String key,String value){
|
||||
mSharedPreferences.edit().putString(key,value).apply();
|
||||
}
|
||||
public String getString(String key){
|
||||
return mSharedPreferences.getString(key,null);
|
||||
}
|
||||
public boolean saveBool(String key,boolean value){
|
||||
return mSharedPreferences.getBoolean(key,false);
|
||||
}
|
||||
|
||||
public void del(String key) {
|
||||
mSharedPreferences.edit().remove(key).apply();
|
||||
}
|
||||
|
||||
public void delStart(String key){
|
||||
for (String _key : mSharedPreferences.getAll().keySet()) {
|
||||
if(_key.startsWith(key)){
|
||||
mSharedPreferences.edit().remove(key).apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
public Map<String, ?> getAll(){
|
||||
return mSharedPreferences.getAll();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user