This commit is contained in:
18142669586 2024-02-23 16:07:50 +08:00
commit a02f7b2e22
5737 changed files with 438436 additions and 0 deletions

16
.gitignore vendored Normal file
View 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
View File

@ -0,0 +1 @@
/build

73
FaceUnity/build.gradle Normal file
View 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' //-
}

View File

21
FaceUnity/proguard-rules.pro vendored Normal file
View 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

View File

@ -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());
}
}

View 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>

View 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);
}
}

View File

@ -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);
}
}
}

View File

@ -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());
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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;
/**
* DESCAnimoji业务工厂
* 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);
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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<>();
}
}

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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;
/*当前道具的类型 普通单bundleavatar 默认为普通单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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,10 @@
package com.yunbao.faceunity.entity
/**
*
* DESC
* Created on 2020/12/4
*
*/
data class AvatarBean(val iconId: Int, val des: String)

View File

@ -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!!
}
}

View File

@ -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)

View File

@ -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//切换按钮,切换整个按钮功能
}
}

View File

@ -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,//不选择按钮
}
}

View File

@ -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));
}
}

View File

@ -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)!!
}
}

View File

@ -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;
}
}

View File

@ -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!!
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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!!
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,3 @@
package com.yunbao.faceunity.entity
data class MenuGroupBean(val titleId :Int,val iconId:Int)

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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
)

View File

@ -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;
}
}
}
}
}

View File

@ -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 + '\'' +
'}';
}
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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);
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -0,0 +1,40 @@
package com.yunbao.faceunity.listener;
import com.faceunity.core.enumeration.FUAIProcessorEnum;
/**
* DESCFURenderer状态回调监听
* 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();
}

View File

@ -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);
}

View File

@ -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;
/**
* DESCAnimoji数据构造
* 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;
}
}

View File

@ -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;
/**
* DESCAvatar数据构造
* 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);
}
}

View File

@ -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, "");
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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();
}
}
}
}

View 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;
}
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}
}
}

View 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, "");
}
}

View File

@ -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