补充美颜模型和美颜配置
@ -1,5 +1,7 @@
|
|||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: 'img-optimizer'
|
apply plugin: 'img-optimizer'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -59,6 +61,7 @@ dependencies {
|
|||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation rootProject.ext.dependencies["appcompat-androidx"]
|
implementation rootProject.ext.dependencies["appcompat-androidx"]
|
||||||
implementation rootProject.ext.dependencies["recyclerview-androidx"]
|
implementation rootProject.ext.dependencies["recyclerview-androidx"]
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
//common
|
//common
|
||||||
implementation project(path: ':common')
|
implementation project(path: ':common')
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ import com.yunbao.faceunity.utils.Authpack;
|
|||||||
import com.yunbao.faceunity.utils.CSVUtils;
|
import com.yunbao.faceunity.utils.CSVUtils;
|
||||||
import com.yunbao.faceunity.utils.FURenderer;
|
import com.yunbao.faceunity.utils.FURenderer;
|
||||||
import com.yunbao.faceunity.utils.FaceCameraConfig;
|
import com.yunbao.faceunity.utils.FaceCameraConfig;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -69,6 +70,7 @@ public class FaceManager implements SensorEventListener {
|
|||||||
if (isInit) {
|
if (isInit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
FaceUnityData.mApplication=context;
|
||||||
FURenderManager.setCoreDebug(FULogger.LogLevel.OFF);
|
FURenderManager.setCoreDebug(FULogger.LogLevel.OFF);
|
||||||
FURenderManager.setKitDebug(FULogger.LogLevel.OFF);
|
FURenderManager.setKitDebug(FULogger.LogLevel.OFF);
|
||||||
FURenderManager.registerFURender(context, Authpack.A(), new OperateCallback() {
|
FURenderManager.registerFURender(context, Authpack.A(), new OperateCallback() {
|
||||||
|
@ -0,0 +1,149 @@
|
|||||||
|
package com.yunbao.faceunity.control
|
||||||
|
|
||||||
|
import android.animation.ValueAnimator
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.yunbao.faceunity.R
|
||||||
|
import com.yunbao.faceunity.base.BaseDelegate
|
||||||
|
import com.yunbao.faceunity.base.BaseListAdapter
|
||||||
|
import com.yunbao.faceunity.base.BaseViewHolder
|
||||||
|
import com.yunbao.faceunity.entity.AnimationFilterBean
|
||||||
|
import com.yunbao.faceunity.entity.AnimojiBean
|
||||||
|
import com.yunbao.faceunity.infe.AbstractAnimojiDataFactory
|
||||||
|
import kotlinx.android.synthetic.main.layout_animo_control.view.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:
|
||||||
|
* Created on 2020/12/10
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class AnimojiControlView @JvmOverloads constructor(private val mContext: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||||
|
BaseControlView(mContext, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
|
||||||
|
private lateinit var mDataFactory: AbstractAnimojiDataFactory
|
||||||
|
|
||||||
|
private lateinit var mAnimojiAdapter: BaseListAdapter<AnimojiBean>
|
||||||
|
private lateinit var mAnimationFilterAdapter: BaseListAdapter<AnimationFilterBean>
|
||||||
|
|
||||||
|
|
||||||
|
// region init
|
||||||
|
init {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.layout_animo_control, this)
|
||||||
|
initView()
|
||||||
|
initAdapter()
|
||||||
|
bindListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给控制绑定AnimojiController,数据工厂
|
||||||
|
*/
|
||||||
|
fun bindDataFactory(dataFactory: AbstractAnimojiDataFactory) {
|
||||||
|
mDataFactory = dataFactory
|
||||||
|
mAnimojiAdapter.setData(dataFactory.animojis)
|
||||||
|
mAnimationFilterAdapter.setData(dataFactory.filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收回菜单栏
|
||||||
|
*/
|
||||||
|
fun hideControlView() {
|
||||||
|
rg_anim.check(View.NO_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
isBottomShow = true
|
||||||
|
initHorizontalRecycleView(recycler_view)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initAdapter() {
|
||||||
|
mAnimojiAdapter = BaseListAdapter(ArrayList(), object : BaseDelegate<AnimojiBean>() {
|
||||||
|
override fun convert(viewType: Int, helper: BaseViewHolder, data: AnimojiBean, position: Int) {
|
||||||
|
helper.setImageResource(R.id.iv_control, data.iconId)
|
||||||
|
helper.itemView.isSelected = position == mDataFactory.currentAnimojiIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClickListener(view: View, data: AnimojiBean, position: Int) {
|
||||||
|
if (mDataFactory.currentAnimojiIndex != position) {
|
||||||
|
changeAdapterSelected(mAnimojiAdapter, mDataFactory.currentAnimojiIndex, position)
|
||||||
|
mDataFactory.currentAnimojiIndex = position
|
||||||
|
mDataFactory.onAnimojiSelected(data)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, R.layout.list_item_control_image_circle)
|
||||||
|
recycler_view.adapter = mAnimojiAdapter
|
||||||
|
|
||||||
|
mAnimationFilterAdapter = BaseListAdapter(ArrayList(), object : BaseDelegate<AnimationFilterBean>() {
|
||||||
|
override fun convert(viewType: Int, helper: BaseViewHolder, data: AnimationFilterBean, position: Int) {
|
||||||
|
helper.setImageResource(R.id.iv_control, data.iconId)
|
||||||
|
helper.itemView.isSelected = position == mDataFactory.currentFilterIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClickListener(view: View, data: AnimationFilterBean, position: Int) {
|
||||||
|
if (mDataFactory.currentFilterIndex != position) {
|
||||||
|
changeAdapterSelected(mAnimationFilterAdapter, mDataFactory.currentFilterIndex, position)
|
||||||
|
mDataFactory.currentFilterIndex = position
|
||||||
|
mDataFactory.onFilterSelected(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, R.layout.list_item_control_image_circle)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindListener() {
|
||||||
|
rg_anim.setOnCheckedChangeListener { _, checkedId ->
|
||||||
|
when (checkedId) {
|
||||||
|
R.id.cb_animoji -> {
|
||||||
|
changeBottomLayoutAnimator(true)
|
||||||
|
recycler_view.adapter = mAnimojiAdapter
|
||||||
|
}
|
||||||
|
R.id.cb_filter -> {
|
||||||
|
changeBottomLayoutAnimator(true)
|
||||||
|
recycler_view.adapter = mAnimationFilterAdapter
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
changeBottomLayoutAnimator(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 底部动画处理
|
||||||
|
* @param isOpen Boolean
|
||||||
|
*/
|
||||||
|
private fun changeBottomLayoutAnimator(isOpen: Boolean) {
|
||||||
|
if (isOpen == isBottomShow) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val start = if (isOpen) resources.getDimensionPixelSize(R.dimen.x98) else resources.getDimensionPixelSize(R.dimen.x266)
|
||||||
|
val end = if (isOpen) resources.getDimensionPixelSize(R.dimen.x266) else resources.getDimensionPixelSize(R.dimen.x98)
|
||||||
|
|
||||||
|
if (bottomLayoutAnimator != null && bottomLayoutAnimator!!.isRunning) {
|
||||||
|
bottomLayoutAnimator!!.end()
|
||||||
|
}
|
||||||
|
bottomLayoutAnimator = ValueAnimator.ofInt(start, end).setDuration(150)
|
||||||
|
bottomLayoutAnimator!!.addUpdateListener { animation ->
|
||||||
|
val height = animation.animatedValue as Int
|
||||||
|
val params = lyt_bottom.layoutParams as ViewGroup.LayoutParams
|
||||||
|
params.height = height
|
||||||
|
lyt_bottom.layoutParams = params
|
||||||
|
if (onBottomAnimatorChangeListener != null) {
|
||||||
|
val showRate = 1.0f * (height - start) / (end - start)
|
||||||
|
onBottomAnimatorChangeListener?.onBottomAnimatorChangeListener(if (!isOpen) 1 - showRate else showRate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bottomLayoutAnimator!!.start()
|
||||||
|
isBottomShow = isOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,242 +0,0 @@
|
|||||||
package com.yunbao.faceunity.control;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.faceunity.core.utils.DecimalUtils;
|
|
||||||
|
|
||||||
import com.yunbao.faceunity.R;
|
|
||||||
import com.yunbao.faceunity.base.BaseDelegate;
|
|
||||||
import com.yunbao.faceunity.base.BaseListAdapter;
|
|
||||||
import com.yunbao.faceunity.base.BaseViewHolder;
|
|
||||||
import com.yunbao.faceunity.entity.BodyBeautyBean;
|
|
||||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
|
||||||
import com.yunbao.faceunity.infe.AbstractBodyBeautyDataFactory;
|
|
||||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DESC:
|
|
||||||
* Created on 2021/4/26
|
|
||||||
*/
|
|
||||||
public class BodyBeautyControlView extends BaseControlView {
|
|
||||||
|
|
||||||
private RecyclerView recyclerView;
|
|
||||||
private DiscreteSeekBar discreteSeekBar;
|
|
||||||
private LinearLayout recoverLayout;
|
|
||||||
private ImageView recoverImageView;
|
|
||||||
private TextView recoverTextView;
|
|
||||||
private SwitchCompat switchCompat;
|
|
||||||
|
|
||||||
private AbstractBodyBeautyDataFactory mDataFactory;
|
|
||||||
private HashMap<String, ModelAttributeData> mModelAttributeRange;
|
|
||||||
private ArrayList<BodyBeautyBean> mBodyBeautyBeans;
|
|
||||||
private BaseListAdapter<BodyBeautyBean> mBodyAdapter;
|
|
||||||
private int mBodyIndex = 0;
|
|
||||||
|
|
||||||
|
|
||||||
public BodyBeautyControlView(@NonNull Context context) {
|
|
||||||
super(context);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BodyBeautyControlView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BodyBeautyControlView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
LayoutInflater.from(mContext).inflate(R.layout.layout_body_beauty_control, this);
|
|
||||||
initView();
|
|
||||||
initAdapter();
|
|
||||||
bindListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void bindDataFactory(AbstractBodyBeautyDataFactory dataFactory) {
|
|
||||||
mDataFactory = dataFactory;
|
|
||||||
mBodyBeautyBeans = mDataFactory.getBodyBeautyParam();
|
|
||||||
mBodyAdapter.setData(mBodyBeautyBeans);
|
|
||||||
mModelAttributeRange = mDataFactory.getModelAttributeRange();
|
|
||||||
BodyBeautyBean data = mBodyBeautyBeans.get(mBodyIndex);
|
|
||||||
double value = mDataFactory.getParamIntensity(data.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(data.getKey()).getStandV();
|
|
||||||
double maxRange = mModelAttributeRange.get(data.getKey()).getMaxRange();
|
|
||||||
seekToSeekBar(value, stand, maxRange);
|
|
||||||
setRecoverEnable(checkParamsChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void initView() {
|
|
||||||
recyclerView = findViewById(R.id.recycler_view);
|
|
||||||
discreteSeekBar = findViewById(R.id.seek_bar);
|
|
||||||
recoverLayout = findViewById(R.id.lyt_beauty_recover);
|
|
||||||
recoverImageView = findViewById(R.id.iv_beauty_recover);
|
|
||||||
recoverTextView = findViewById(R.id.tv_beauty_recover);
|
|
||||||
switchCompat = findViewById(R.id.switch_compat);
|
|
||||||
initHorizontalRecycleView(recyclerView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initAdapter() {
|
|
||||||
mBodyAdapter = new BaseListAdapter<>(new ArrayList<>(), new BaseDelegate<BodyBeautyBean>() {
|
|
||||||
@Override
|
|
||||||
public void convert(int viewType, BaseViewHolder helper, BodyBeautyBean data, int position) {
|
|
||||||
helper.setText(R.id.tv_control, data.getDesRes());
|
|
||||||
double value = mDataFactory.getParamIntensity(data.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(data.getKey()).getStandV();
|
|
||||||
if (DecimalUtils.doubleEquals(value, stand)) {
|
|
||||||
helper.setImageResource(R.id.iv_control, data.getCloseRes());
|
|
||||||
} else {
|
|
||||||
helper.setImageResource(R.id.iv_control, data.getOpenRes());
|
|
||||||
}
|
|
||||||
helper.itemView.setSelected(position == mBodyIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemClickListener(View view, BodyBeautyBean data, int position) {
|
|
||||||
if (mBodyIndex != position) {
|
|
||||||
changeAdapterSelected(mBodyAdapter, mBodyIndex, position);
|
|
||||||
mBodyIndex = position;
|
|
||||||
double value = mDataFactory.getParamIntensity(data.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(data.getKey()).getStandV();
|
|
||||||
double maxRange = mModelAttributeRange.get(data.getKey()).getMaxRange();
|
|
||||||
seekToSeekBar(value, stand, maxRange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}, R.layout.list_item_control_title_image_circle);
|
|
||||||
recyclerView.setAdapter(mBodyAdapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindListener() {
|
|
||||||
findViewById(R.id.cyt_main).setOnTouchListener((v, event) -> true);
|
|
||||||
discreteSeekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
|
|
||||||
if (!fromUser) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
double valueF = 1.0 * (value - seekBar.getMin()) / 100;
|
|
||||||
BodyBeautyBean data = mBodyBeautyBeans.get(mBodyIndex);
|
|
||||||
double intensity = mDataFactory.getParamIntensity(data.getKey());
|
|
||||||
double range = mModelAttributeRange.get(data.getKey()).getMaxRange();
|
|
||||||
double res = valueF * range;
|
|
||||||
if (!DecimalUtils.doubleEquals(res, intensity)) {
|
|
||||||
mDataFactory.updateParamIntensity(data.getKey(), res);
|
|
||||||
setRecoverEnable(checkParamsChanged());
|
|
||||||
updateBeautyItemUI(mBodyAdapter.getViewHolderByPosition(mBodyIndex), data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
findViewById(R.id.lyt_beauty_recover).setOnClickListener((view) -> showDialog(mContext.getString(R.string.dialog_reset_avatar_model), () -> recoverData()));
|
|
||||||
switchCompat.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
|
||||||
mDataFactory.enableBodyBeauty(isChecked);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置滚动条数值
|
|
||||||
*/
|
|
||||||
private void seekToSeekBar(double value, double stand, double range) {
|
|
||||||
if (stand == 0.5) {
|
|
||||||
discreteSeekBar.setMin(-50);
|
|
||||||
discreteSeekBar.setMax(50);
|
|
||||||
discreteSeekBar.setProgress((int) (value * 100 / range - 50));
|
|
||||||
} else {
|
|
||||||
discreteSeekBar.setMin(0);
|
|
||||||
discreteSeekBar.setMax(100);
|
|
||||||
discreteSeekBar.setProgress((int) (value * 100 / range));
|
|
||||||
}
|
|
||||||
discreteSeekBar.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新单项是否为基准值显示
|
|
||||||
*/
|
|
||||||
private void updateBeautyItemUI(BaseViewHolder viewHolder, BodyBeautyBean bean) {
|
|
||||||
double value = mDataFactory.getParamIntensity(bean.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(bean.getKey()).getStandV();
|
|
||||||
if (viewHolder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (DecimalUtils.doubleEquals(value, stand)) {
|
|
||||||
viewHolder.setImageResource(R.id.iv_control, bean.getCloseRes());
|
|
||||||
} else {
|
|
||||||
viewHolder.setImageResource(R.id.iv_control, bean.getOpenRes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置数据
|
|
||||||
*/
|
|
||||||
private void recoverData() {
|
|
||||||
for (BodyBeautyBean bean : mBodyBeautyBeans) {
|
|
||||||
double intensity = mModelAttributeRange.get(bean.getKey()).getDefaultV();
|
|
||||||
mDataFactory.updateParamIntensity(bean.getKey(), intensity);
|
|
||||||
}
|
|
||||||
BodyBeautyBean data = mBodyBeautyBeans.get(mBodyIndex);
|
|
||||||
double value = mDataFactory.getParamIntensity(data.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(data.getKey()).getStandV();
|
|
||||||
double maxRange = mModelAttributeRange.get(data.getKey()).getMaxRange();
|
|
||||||
seekToSeekBar(value, stand, maxRange);
|
|
||||||
mBodyAdapter.notifyDataSetChanged();
|
|
||||||
setRecoverEnable(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 遍历数据确认还原按钮是否可以点击
|
|
||||||
*
|
|
||||||
* @return Boolean
|
|
||||||
*/
|
|
||||||
private boolean checkParamsChanged() {
|
|
||||||
BodyBeautyBean bean = mBodyBeautyBeans.get(mBodyIndex);
|
|
||||||
double value = mDataFactory.getParamIntensity(bean.getKey());
|
|
||||||
double defaultV = mModelAttributeRange.get(bean.getKey()).getDefaultV();
|
|
||||||
if (!DecimalUtils.doubleEquals(value, defaultV)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (BodyBeautyBean beautyBean : mBodyBeautyBeans) {
|
|
||||||
value = mDataFactory.getParamIntensity(beautyBean.getKey());
|
|
||||||
defaultV = mModelAttributeRange.get(beautyBean.getKey()).getDefaultV();
|
|
||||||
if (!DecimalUtils.doubleEquals(value, defaultV)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置还原按钮状态
|
|
||||||
*
|
|
||||||
* @param enable Boolean
|
|
||||||
*/
|
|
||||||
private void setRecoverEnable(Boolean enable) {
|
|
||||||
if (enable) {
|
|
||||||
recoverImageView.setAlpha(1f);
|
|
||||||
recoverTextView.setAlpha(1f);
|
|
||||||
} else {
|
|
||||||
recoverImageView.setAlpha(0.6f);
|
|
||||||
recoverTextView.setAlpha(0.6f);
|
|
||||||
}
|
|
||||||
recoverLayout.setEnabled(enable);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,205 @@
|
|||||||
|
package com.yunbao.faceunity.control
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import com.faceunity.core.utils.DecimalUtils
|
||||||
|
import com.yunbao.faceunity.R
|
||||||
|
import com.yunbao.faceunity.base.BaseDelegate
|
||||||
|
import com.yunbao.faceunity.base.BaseListAdapter
|
||||||
|
import com.yunbao.faceunity.base.BaseViewHolder
|
||||||
|
import com.yunbao.faceunity.entity.BodyBeautyBean
|
||||||
|
import com.yunbao.faceunity.entity.ModelAttributeData
|
||||||
|
import com.yunbao.faceunity.infe.AbstractBodyBeautyDataFactory
|
||||||
|
import com.yunbao.faceunity.seekbar.DiscreteSeekBar
|
||||||
|
|
||||||
|
import kotlinx.android.synthetic.main.layout_body_beauty_control.view.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:美体
|
||||||
|
* Created on 2020/12/11
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class BodyBeautyControlView @JvmOverloads constructor(private val mContext: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||||
|
BaseControlView(mContext, attrs, defStyleAttr) {
|
||||||
|
private lateinit var mDataFactory: AbstractBodyBeautyDataFactory
|
||||||
|
private lateinit var mModelAttributeRange: HashMap<String, ModelAttributeData>
|
||||||
|
private lateinit var mBodyBeautyBeans: ArrayList<BodyBeautyBean>
|
||||||
|
private lateinit var mBodyAdapter: BaseListAdapter<BodyBeautyBean>
|
||||||
|
private var mBodyIndex = 0
|
||||||
|
|
||||||
|
// region init
|
||||||
|
|
||||||
|
init {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.layout_body_beauty_control, this)
|
||||||
|
initView()
|
||||||
|
initAdapter()
|
||||||
|
bindListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun bindDataFactory(dataFactory: AbstractBodyBeautyDataFactory) {
|
||||||
|
mDataFactory = dataFactory
|
||||||
|
mBodyBeautyBeans = mDataFactory.bodyBeautyParam
|
||||||
|
mBodyAdapter.setData(mBodyBeautyBeans)
|
||||||
|
mModelAttributeRange = mDataFactory.modelAttributeRange
|
||||||
|
val data = mBodyBeautyBeans[mBodyIndex]
|
||||||
|
val value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
val stand = mModelAttributeRange[data.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[data.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
setRecoverEnable(checkParamsChanged())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
initHorizontalRecycleView(recycler_view)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initAdapter() {
|
||||||
|
mBodyAdapter = BaseListAdapter(ArrayList(), object : BaseDelegate<BodyBeautyBean>() {
|
||||||
|
override fun convert(viewType: Int, helper: BaseViewHolder, data: BodyBeautyBean, position: Int) {
|
||||||
|
helper.setText(R.id.tv_control, data.desRes)
|
||||||
|
val value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
val stand = mModelAttributeRange[data.key]!!.stand
|
||||||
|
if (DecimalUtils.doubleEquals(value, stand)) {
|
||||||
|
helper.setImageResource(R.id.iv_control, data.closeRes)
|
||||||
|
} else {
|
||||||
|
helper.setImageResource(R.id.iv_control, data.openRes)
|
||||||
|
}
|
||||||
|
helper.itemView.isSelected = position == mBodyIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClickListener(view: View, data: BodyBeautyBean, position: Int) {
|
||||||
|
if (mBodyIndex != position) {
|
||||||
|
changeAdapterSelected(mBodyAdapter, mBodyIndex, position)
|
||||||
|
mBodyIndex = position
|
||||||
|
val value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
val stand = mModelAttributeRange[data.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[data.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, R.layout.list_item_control_title_image_circle)
|
||||||
|
recycler_view.adapter = mBodyAdapter
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindListener() {
|
||||||
|
cyt_main.setOnTouchListener { _, _ -> true }
|
||||||
|
beauty_seek_bar.setOnProgressChangeListener(object : DiscreteSeekBar.OnSimpleProgressChangeListener() {
|
||||||
|
override fun onProgressChanged(seekBar: DiscreteSeekBar?, value: Int, fromUser: Boolean) {
|
||||||
|
if (!fromUser) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val valueF = 1.0 * (value - seekBar!!.min) / 100
|
||||||
|
val data = mBodyBeautyBeans[mBodyIndex]
|
||||||
|
val value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
val range = mModelAttributeRange[data.key]!!.maxRange
|
||||||
|
val res = valueF * range
|
||||||
|
if (!DecimalUtils.doubleEquals(res, value)) {
|
||||||
|
mDataFactory.updateParamIntensity(data.key, res)
|
||||||
|
setRecoverEnable(checkParamsChanged())
|
||||||
|
updateBeautyItemUI(mBodyAdapter.getViewHolderByPosition(mBodyIndex), data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
lyt_beauty_recover.setOnClickListener {
|
||||||
|
showDialog(mContext.getString(R.string.dialog_reset_avatar_model)) {
|
||||||
|
recoverData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置滚动条数值
|
||||||
|
*/
|
||||||
|
private fun seekToSeekBar(value: Double, stand: Double, range: Double) {
|
||||||
|
if (stand == 0.5) {
|
||||||
|
beauty_seek_bar.min = -50
|
||||||
|
beauty_seek_bar.max = 50
|
||||||
|
beauty_seek_bar.progress = (value * 100 / range - 50).toInt()
|
||||||
|
} else {
|
||||||
|
beauty_seek_bar.min = 0
|
||||||
|
beauty_seek_bar.max = 100
|
||||||
|
beauty_seek_bar.progress = (value * 100 / range).toInt()
|
||||||
|
}
|
||||||
|
beauty_seek_bar.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新单项是否为基准值显示
|
||||||
|
*/
|
||||||
|
private fun updateBeautyItemUI(viewHolder: BaseViewHolder?, data: BodyBeautyBean) {
|
||||||
|
val value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
val stand = mModelAttributeRange[data.key]!!.stand
|
||||||
|
if (DecimalUtils.doubleEquals(value, stand)) {
|
||||||
|
viewHolder?.setImageResource(R.id.iv_control, data.closeRes)
|
||||||
|
} else {
|
||||||
|
viewHolder?.setImageResource(R.id.iv_control, data.openRes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun recoverData() {
|
||||||
|
mBodyBeautyBeans.forEach {
|
||||||
|
val default = mModelAttributeRange[it.key]!!.default
|
||||||
|
mDataFactory.updateParamIntensity(it.key, default)
|
||||||
|
}
|
||||||
|
val data = mBodyBeautyBeans[mBodyIndex]
|
||||||
|
val value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
val stand = mModelAttributeRange[data.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[data.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
mBodyAdapter.notifyDataSetChanged()
|
||||||
|
setRecoverEnable(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历数据确认还原按钮是否可以点击
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
private fun checkParamsChanged(): Boolean {
|
||||||
|
var item = mBodyBeautyBeans[mBodyIndex]
|
||||||
|
var value = mDataFactory.getParamIntensity(item.key)
|
||||||
|
var default = mModelAttributeRange[item.key]!!.default
|
||||||
|
if (!DecimalUtils.doubleEquals(value, default)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
mBodyBeautyBeans.forEach {
|
||||||
|
value = mDataFactory.getParamIntensity(it.key)
|
||||||
|
default = mModelAttributeRange[it.key]!!.default
|
||||||
|
if (!DecimalUtils.doubleEquals(value, default)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置还原按钮状态
|
||||||
|
* @param enable Boolean
|
||||||
|
*/
|
||||||
|
private fun setRecoverEnable(enable: Boolean) {
|
||||||
|
if (enable) {
|
||||||
|
tv_beauty_recover.alpha = 1f
|
||||||
|
iv_beauty_recover.alpha = 1f
|
||||||
|
} else {
|
||||||
|
tv_beauty_recover.alpha = 0.6f
|
||||||
|
iv_beauty_recover.alpha = 0.6f
|
||||||
|
}
|
||||||
|
lyt_beauty_recover.isEnabled = enable
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,463 +0,0 @@
|
|||||||
package com.yunbao.faceunity.control;
|
|
||||||
|
|
||||||
import android.animation.ValueAnimator;
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.faceunity.core.utils.DecimalUtils;
|
|
||||||
import com.yunbao.faceunity.R;
|
|
||||||
import com.yunbao.faceunity.base.BaseDelegate;
|
|
||||||
import com.yunbao.faceunity.base.BaseListAdapter;
|
|
||||||
import com.yunbao.faceunity.base.BaseViewHolder;
|
|
||||||
import com.yunbao.faceunity.checkbox.CheckGroup;
|
|
||||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
|
||||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
|
||||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
|
||||||
import com.yunbao.faceunity.infe.AbstractFaceBeautyDataFactory;
|
|
||||||
import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DESC:
|
|
||||||
* Created on 2021/4/26
|
|
||||||
*/
|
|
||||||
public class FaceBeautyControlView extends BaseControlView {
|
|
||||||
|
|
||||||
private AbstractFaceBeautyDataFactory mDataFactory;
|
|
||||||
|
|
||||||
/* 美颜、美型 */
|
|
||||||
private HashMap<String, ModelAttributeData> mModelAttributeRange;
|
|
||||||
private ArrayList<FaceBeautyBean> mSkinBeauty;
|
|
||||||
private ArrayList<FaceBeautyBean> mShapeBeauty;
|
|
||||||
private int mSkinIndex = 0;
|
|
||||||
private int mShapeIndex = 1;
|
|
||||||
private BaseListAdapter<FaceBeautyBean> mBeautyAdapter;
|
|
||||||
|
|
||||||
/* 滤镜 */
|
|
||||||
private ArrayList<FaceBeautyFilterBean> mFilters;
|
|
||||||
private BaseListAdapter<FaceBeautyFilterBean> mFiltersAdapter;
|
|
||||||
|
|
||||||
|
|
||||||
private RecyclerView recyclerView;
|
|
||||||
private DiscreteSeekBar discreteSeekBar;
|
|
||||||
private CheckGroup checkGroup;
|
|
||||||
private LinearLayout recoverLayout;
|
|
||||||
private ImageView recoverImageView;
|
|
||||||
private TextView recoverTextView;
|
|
||||||
private View lineView;
|
|
||||||
private LinearLayout bottomLayout;
|
|
||||||
private SwitchCompat switchCompat;
|
|
||||||
|
|
||||||
public FaceBeautyControlView(@NonNull Context context) {
|
|
||||||
super(context);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FaceBeautyControlView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FaceBeautyControlView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 给控制绑定FaceBeautyController,数据工厂
|
|
||||||
*
|
|
||||||
* @param dataFactory IFaceBeautyDataFactory
|
|
||||||
*/
|
|
||||||
public void bindDataFactory(AbstractFaceBeautyDataFactory dataFactory) {
|
|
||||||
mDataFactory = dataFactory;
|
|
||||||
mModelAttributeRange = dataFactory.getModelAttributeRange();
|
|
||||||
mSkinBeauty = dataFactory.getSkinBeauty();
|
|
||||||
mShapeBeauty = dataFactory.getShapeBeauty();
|
|
||||||
mFilters = dataFactory.getBeautyFilters();
|
|
||||||
mFiltersAdapter.setData(mFilters);
|
|
||||||
checkGroup.check(View.NO_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
LayoutInflater.from(mContext).inflate(R.layout.layout_face_beauty_control, this);
|
|
||||||
initView();
|
|
||||||
initAdapter();
|
|
||||||
bindListener();
|
|
||||||
|
|
||||||
}
|
|
||||||
// region init
|
|
||||||
|
|
||||||
private void initView() {
|
|
||||||
recyclerView = findViewById(R.id.recycler_view);
|
|
||||||
discreteSeekBar = findViewById(R.id.seek_bar);
|
|
||||||
checkGroup = findViewById(R.id.beauty_radio_group);
|
|
||||||
recoverLayout = findViewById(R.id.lyt_beauty_recover);
|
|
||||||
recoverImageView = findViewById(R.id.iv_beauty_recover);
|
|
||||||
recoverTextView = findViewById(R.id.tv_beauty_recover);
|
|
||||||
lineView = findViewById(R.id.iv_line);
|
|
||||||
bottomLayout = findViewById(R.id.fyt_bottom_view);
|
|
||||||
switchCompat = findViewById(R.id.switch_compat);
|
|
||||||
initHorizontalRecycleView(recyclerView);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造Adapter
|
|
||||||
*/
|
|
||||||
private void initAdapter() {
|
|
||||||
mFiltersAdapter = new BaseListAdapter<>(
|
|
||||||
new ArrayList<>(), new BaseDelegate<FaceBeautyFilterBean>() {
|
|
||||||
@Override
|
|
||||||
public void convert(int viewType, BaseViewHolder helper, FaceBeautyFilterBean data, int position) {
|
|
||||||
helper.setText(R.id.tv_control, data.getDesRes());
|
|
||||||
helper.setImageResource(R.id.iv_control, data.getImageRes());
|
|
||||||
helper.itemView.setSelected(mDataFactory.getCurrentFilterIndex() == position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemClickListener(View view, FaceBeautyFilterBean data, int position) {
|
|
||||||
if (mDataFactory.getCurrentFilterIndex() != position) {
|
|
||||||
changeAdapterSelected(mFiltersAdapter, mDataFactory.getCurrentFilterIndex(), position);
|
|
||||||
mDataFactory.setCurrentFilterIndex(position);
|
|
||||||
mDataFactory.onFilterSelected(data.getKey(), data.getIntensity(), data.getDesRes());
|
|
||||||
if (position == 0) {
|
|
||||||
discreteSeekBar.setVisibility(View.INVISIBLE);
|
|
||||||
} else {
|
|
||||||
seekToSeekBar(data.getIntensity(), 0.0, 1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}, R.layout.list_item_control_title_image_square);
|
|
||||||
|
|
||||||
|
|
||||||
mBeautyAdapter = new BaseListAdapter<>(new ArrayList<>(), new BaseDelegate<FaceBeautyBean>() {
|
|
||||||
@Override
|
|
||||||
public void convert(int viewType, BaseViewHolder helper, FaceBeautyBean data, int position) {
|
|
||||||
helper.setText(R.id.tv_control, data.getDesRes());
|
|
||||||
double value = mDataFactory.getParamIntensity(data.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(data.getKey()).getStandV();
|
|
||||||
if (DecimalUtils.doubleEquals(value, stand)) {
|
|
||||||
helper.setImageResource(R.id.iv_control, data.getCloseRes());
|
|
||||||
} else {
|
|
||||||
helper.setImageResource(R.id.iv_control, data.getOpenRes());
|
|
||||||
}
|
|
||||||
boolean isShinSelected = checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_skin_beauty;
|
|
||||||
helper.itemView.setSelected(isShinSelected ? mSkinIndex == position : mShapeIndex == position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemClickListener(View view, FaceBeautyBean data, int position) {
|
|
||||||
boolean isShinSelected = checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_skin_beauty;
|
|
||||||
if ((isShinSelected && position == mSkinIndex) || (!isShinSelected && position == mShapeIndex)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isShinSelected) {
|
|
||||||
changeAdapterSelected(mBeautyAdapter, mSkinIndex, position);
|
|
||||||
mSkinIndex = position;
|
|
||||||
} else {
|
|
||||||
changeAdapterSelected(mBeautyAdapter, mShapeIndex, position);
|
|
||||||
mShapeIndex = position;
|
|
||||||
}
|
|
||||||
double value = mDataFactory.getParamIntensity(data.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(data.getKey()).getStandV();
|
|
||||||
double maxRange = mModelAttributeRange.get(data.getKey()).getMaxRange();
|
|
||||||
seekToSeekBar(value, stand, maxRange);
|
|
||||||
}
|
|
||||||
}, R.layout.list_item_control_title_image_circle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 绑定监听事件
|
|
||||||
*/
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
private void bindListener() {
|
|
||||||
/*拦截触碰事件*/
|
|
||||||
findViewById(R.id.fyt_bottom_view).setOnTouchListener((v, event) -> true);
|
|
||||||
/*菜单控制*/
|
|
||||||
bindBottomRadioListener();
|
|
||||||
/*滑动条控制*/
|
|
||||||
bindSeekBarListener();
|
|
||||||
/*还原数据*/
|
|
||||||
recoverLayout.setOnClickListener((view) -> showDialog(mContext.getString(R.string.dialog_reset_avatar_model), () -> recoverData()));
|
|
||||||
/*渲染开关*/
|
|
||||||
switchCompat.setOnCheckedChangeListener((buttonView, isChecked) -> mDataFactory.enableFaceBeauty(isChecked));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 滚动条绑定事件
|
|
||||||
*/
|
|
||||||
private void bindSeekBarListener() {
|
|
||||||
discreteSeekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
|
|
||||||
if (!fromUser) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
double valueF = 1.0 * (value - seekBar.getMin()) / 100;
|
|
||||||
if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_skin_beauty) {
|
|
||||||
FaceBeautyBean bean = mSkinBeauty.get(mSkinIndex);
|
|
||||||
double range = mModelAttributeRange.get(bean.getKey()).getMaxRange();
|
|
||||||
double res = valueF * range;
|
|
||||||
double intensity = mDataFactory.getParamIntensity(bean.getKey());
|
|
||||||
if (!DecimalUtils.doubleEquals(res, intensity)) {
|
|
||||||
mDataFactory.updateParamIntensity(bean.getKey(), res);
|
|
||||||
setRecoverEnable(checkFaceSkinChanged());
|
|
||||||
updateBeautyItemUI(mBeautyAdapter.getViewHolderByPosition(mSkinIndex), bean);
|
|
||||||
}
|
|
||||||
} else if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_face_shape) {
|
|
||||||
FaceBeautyBean bean = mShapeBeauty.get(mShapeIndex);
|
|
||||||
double range = mModelAttributeRange.get(bean.getKey()).getMaxRange();
|
|
||||||
double res = valueF * range;
|
|
||||||
double intensity = mDataFactory.getParamIntensity(bean.getKey());
|
|
||||||
if (!DecimalUtils.doubleEquals(res, intensity)) {
|
|
||||||
mDataFactory.updateParamIntensity(bean.getKey(), res);
|
|
||||||
setRecoverEnable(checkFaceShapeChanged());
|
|
||||||
updateBeautyItemUI(mBeautyAdapter.getViewHolderByPosition(mShapeIndex), bean);
|
|
||||||
}
|
|
||||||
} else if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_filter) {
|
|
||||||
FaceBeautyFilterBean bean = mFilters.get(mDataFactory.getCurrentFilterIndex());
|
|
||||||
if (!DecimalUtils.doubleEquals(bean.getIntensity(), valueF)) {
|
|
||||||
bean.setIntensity(valueF);
|
|
||||||
mDataFactory.updateFilterIntensity(valueF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 底部导航栏绑定监听事件,处理RecycleView等相关布局变更
|
|
||||||
*/
|
|
||||||
private void bindBottomRadioListener() {
|
|
||||||
checkGroup.setOnCheckedChangeListener((group, checkedId) -> {
|
|
||||||
if (checkedId == R.id.beauty_radio_skin_beauty || checkedId == R.id.beauty_radio_face_shape) {
|
|
||||||
discreteSeekBar.setVisibility(View.VISIBLE);
|
|
||||||
recoverLayout.setVisibility(View.VISIBLE);
|
|
||||||
lineView.setVisibility(View.VISIBLE);
|
|
||||||
switchCompat.setVisibility(View.VISIBLE);
|
|
||||||
} else if (checkedId == R.id.beauty_radio_filter) {
|
|
||||||
discreteSeekBar.setVisibility((mDataFactory.getCurrentFilterIndex() == 0) ? View.INVISIBLE : View.VISIBLE);
|
|
||||||
recoverLayout.setVisibility(View.GONE);
|
|
||||||
lineView.setVisibility(View.GONE);
|
|
||||||
switchCompat.setVisibility(View.VISIBLE);
|
|
||||||
} else if (checkedId == View.NO_ID) {
|
|
||||||
mDataFactory.enableFaceBeauty(true);
|
|
||||||
switchCompat.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
if (checkedId == R.id.beauty_radio_skin_beauty) {
|
|
||||||
mBeautyAdapter.setData(mSkinBeauty);
|
|
||||||
recyclerView.setAdapter(mBeautyAdapter);
|
|
||||||
FaceBeautyBean item = mSkinBeauty.get(mSkinIndex);
|
|
||||||
double value = mDataFactory.getParamIntensity(item.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(item.getKey()).getStandV();
|
|
||||||
double maxRange = mModelAttributeRange.get(item.getKey()).getMaxRange();
|
|
||||||
seekToSeekBar(value, stand, maxRange);
|
|
||||||
setRecoverEnable(checkFaceSkinChanged());
|
|
||||||
changeBottomLayoutAnimator(true);
|
|
||||||
} else if (checkedId == R.id.beauty_radio_face_shape) {
|
|
||||||
mBeautyAdapter.setData(mShapeBeauty);
|
|
||||||
recyclerView.setAdapter(mBeautyAdapter);
|
|
||||||
FaceBeautyBean item = mShapeBeauty.get(mShapeIndex);
|
|
||||||
double value = mDataFactory.getParamIntensity(item.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(item.getKey()).getStandV();
|
|
||||||
double maxRange = mModelAttributeRange.get(item.getKey()).getMaxRange();
|
|
||||||
seekToSeekBar(value, stand, maxRange);
|
|
||||||
setRecoverEnable(checkFaceShapeChanged());
|
|
||||||
changeBottomLayoutAnimator(true);
|
|
||||||
} else if (checkedId == R.id.beauty_radio_filter) {
|
|
||||||
recyclerView.setAdapter(mFiltersAdapter);
|
|
||||||
recyclerView.scrollToPosition(mDataFactory.getCurrentFilterIndex());
|
|
||||||
if (mDataFactory.getCurrentFilterIndex() == 0) {
|
|
||||||
discreteSeekBar.setVisibility(View.INVISIBLE);
|
|
||||||
} else {
|
|
||||||
seekToSeekBar(mFilters.get(mDataFactory.getCurrentFilterIndex()).getIntensity(), 0.0, 1.0);
|
|
||||||
}
|
|
||||||
changeBottomLayoutAnimator(true);
|
|
||||||
} else if (checkedId == View.NO_ID) {
|
|
||||||
changeBottomLayoutAnimator(false);
|
|
||||||
mDataFactory.enableFaceBeauty(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
// region 业务处理
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置滚动条数值
|
|
||||||
*
|
|
||||||
* @param value Double 结果值
|
|
||||||
* @param stand Double 标准值
|
|
||||||
* @param range Double 范围区间
|
|
||||||
*/
|
|
||||||
private void seekToSeekBar(double value, double stand, double range) {
|
|
||||||
if (stand == 0.5) {
|
|
||||||
discreteSeekBar.setMin(-50);
|
|
||||||
discreteSeekBar.setMax(50);
|
|
||||||
discreteSeekBar.setProgress((int) (value * 100 / range - 50));
|
|
||||||
} else {
|
|
||||||
discreteSeekBar.setMin(0);
|
|
||||||
discreteSeekBar.setMax(100);
|
|
||||||
discreteSeekBar.setProgress((int) (value * 100 / range));
|
|
||||||
}
|
|
||||||
discreteSeekBar.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新单项是否为基准值显示
|
|
||||||
*/
|
|
||||||
private void updateBeautyItemUI(BaseViewHolder viewHolder, FaceBeautyBean bean) {
|
|
||||||
double value = mDataFactory.getParamIntensity(bean.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(bean.getKey()).getStandV();
|
|
||||||
if (viewHolder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (DecimalUtils.doubleEquals(value, stand)) {
|
|
||||||
viewHolder.setImageResource(R.id.iv_control, bean.getCloseRes());
|
|
||||||
} else {
|
|
||||||
viewHolder.setImageResource(R.id.iv_control, bean.getOpenRes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置还原按钮状态
|
|
||||||
*
|
|
||||||
* @param enable Boolean
|
|
||||||
*/
|
|
||||||
private void setRecoverEnable(Boolean enable) {
|
|
||||||
if (enable) {
|
|
||||||
recoverImageView.setAlpha(1f);
|
|
||||||
recoverTextView.setAlpha(1f);
|
|
||||||
} else {
|
|
||||||
recoverImageView.setAlpha(0.6f);
|
|
||||||
recoverTextView.setAlpha(0.6f);
|
|
||||||
}
|
|
||||||
recoverLayout.setEnabled(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 遍历美肤数据确认还原按钮是否可以点击
|
|
||||||
*
|
|
||||||
* @return Boolean
|
|
||||||
*/
|
|
||||||
private boolean checkFaceSkinChanged() {
|
|
||||||
FaceBeautyBean bean = mSkinBeauty.get(mSkinIndex);
|
|
||||||
double value = mDataFactory.getParamIntensity(bean.getKey());
|
|
||||||
double defaultV = mModelAttributeRange.get(bean.getKey()).getDefaultV();
|
|
||||||
if (!DecimalUtils.doubleEquals(value, defaultV)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (FaceBeautyBean beautyBean : mSkinBeauty) {
|
|
||||||
value = mDataFactory.getParamIntensity(beautyBean.getKey());
|
|
||||||
defaultV = mModelAttributeRange.get(beautyBean.getKey()).getDefaultV();
|
|
||||||
if (!DecimalUtils.doubleEquals(value, defaultV)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 遍历美型数据确认还原按钮是否可以点击
|
|
||||||
*
|
|
||||||
* @return Boolean
|
|
||||||
*/
|
|
||||||
private boolean checkFaceShapeChanged() {
|
|
||||||
FaceBeautyBean bean = mShapeBeauty.get(mShapeIndex);
|
|
||||||
double value = mDataFactory.getParamIntensity(bean.getKey());
|
|
||||||
double defaultV = mModelAttributeRange.get(bean.getKey()).getDefaultV();
|
|
||||||
if (!DecimalUtils.doubleEquals(value, defaultV)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (FaceBeautyBean beautyBean : mShapeBeauty) {
|
|
||||||
value = mDataFactory.getParamIntensity(beautyBean.getKey());
|
|
||||||
defaultV = mModelAttributeRange.get(beautyBean.getKey()).getDefaultV();
|
|
||||||
if (!DecimalUtils.doubleEquals(value, defaultV)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 还原 美型、美肤数据
|
|
||||||
*/
|
|
||||||
private void recoverData() {
|
|
||||||
if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_skin_beauty) {
|
|
||||||
recoverData(mSkinBeauty, mSkinIndex);
|
|
||||||
} else if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_face_shape) {
|
|
||||||
recoverData(mShapeBeauty, mShapeIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置数据
|
|
||||||
*
|
|
||||||
* @param beautyBeans
|
|
||||||
* @param currentIndex
|
|
||||||
*/
|
|
||||||
private void recoverData(ArrayList<FaceBeautyBean> beautyBeans, int currentIndex) {
|
|
||||||
for (FaceBeautyBean bean : beautyBeans) {
|
|
||||||
double intensity = mModelAttributeRange.get(bean.getKey()).getDefaultV();
|
|
||||||
mDataFactory.updateParamIntensity(bean.getKey(), intensity);
|
|
||||||
}
|
|
||||||
FaceBeautyBean data = beautyBeans.get(currentIndex);
|
|
||||||
double value = mDataFactory.getParamIntensity(data.getKey());
|
|
||||||
double stand = mModelAttributeRange.get(data.getKey()).getStandV();
|
|
||||||
double maxRange = mModelAttributeRange.get(data.getKey()).getMaxRange();
|
|
||||||
seekToSeekBar(value, stand, maxRange);
|
|
||||||
mBeautyAdapter.notifyDataSetChanged();
|
|
||||||
setRecoverEnable(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 底部动画处理
|
|
||||||
*
|
|
||||||
* @param isOpen Boolean
|
|
||||||
*/
|
|
||||||
private void changeBottomLayoutAnimator(boolean isOpen) {
|
|
||||||
if (isBottomShow == isOpen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int start = isOpen ? getResources().getDimensionPixelSize(R.dimen.x1) : getResources().getDimensionPixelSize(R.dimen.x268);
|
|
||||||
int end = isOpen ? getResources().getDimensionPixelSize(R.dimen.x268) : getResources().getDimensionPixelSize(R.dimen.x1);
|
|
||||||
if (bottomLayoutAnimator != null && bottomLayoutAnimator.isRunning()) {
|
|
||||||
bottomLayoutAnimator.end();
|
|
||||||
}
|
|
||||||
bottomLayoutAnimator = ValueAnimator.ofInt(start, end).setDuration(150);
|
|
||||||
bottomLayoutAnimator.addUpdateListener(animation -> {
|
|
||||||
int height = (int) animation.getAnimatedValue();
|
|
||||||
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) bottomLayout.getLayoutParams();
|
|
||||||
params.height = height;
|
|
||||||
bottomLayout.setLayoutParams(params);
|
|
||||||
if (onBottomAnimatorChangeListener != null) {
|
|
||||||
float showRate = 1.0f * (height - start) / (end - start);
|
|
||||||
onBottomAnimatorChangeListener.onBottomAnimatorChangeListener(isOpen ? showRate : 1 - showRate);
|
|
||||||
}
|
|
||||||
if (DecimalUtils.floatEquals(animation.getAnimatedFraction(), 1.0f) && isOpen) {
|
|
||||||
switchCompat.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
bottomLayoutAnimator.start();
|
|
||||||
isBottomShow = isOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,826 @@
|
|||||||
|
package com.yunbao.faceunity.control
|
||||||
|
|
||||||
|
import android.animation.ValueAnimator
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.animation.AlphaAnimation
|
||||||
|
import android.view.animation.Animation
|
||||||
|
import android.view.animation.AnimationSet
|
||||||
|
import android.view.animation.TranslateAnimation
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.faceunity.core.utils.DecimalUtils
|
||||||
|
import com.yunbao.faceunity.R
|
||||||
|
import com.yunbao.faceunity.base.BaseDelegate
|
||||||
|
import com.yunbao.faceunity.base.BaseListAdapter
|
||||||
|
import com.yunbao.faceunity.base.BaseViewHolder
|
||||||
|
import com.yunbao.faceunity.dialog.ToastHelper
|
||||||
|
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.seekbar.DiscreteSeekBar
|
||||||
|
import kotlinx.android.synthetic.main.layout_face_beauty_control.view.*
|
||||||
|
import kotlin.collections.set
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:美颜
|
||||||
|
* Created on 2020/11/17
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class FaceBeautyControlView @JvmOverloads constructor(private val mContext: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||||
|
BaseControlView(mContext, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private lateinit var mDataFactory: AbstractFaceBeautyDataFactory
|
||||||
|
|
||||||
|
/* 美颜、美型 */
|
||||||
|
private lateinit var mModelAttributeRange: HashMap<String, ModelAttributeData>
|
||||||
|
private var mSkinBeauty = ArrayList<FaceBeautyBean>()
|
||||||
|
private var mShapeBeauty = ArrayList<FaceBeautyBean>()
|
||||||
|
private var mShapeBeautySubItem = ArrayList<FaceBeautyBean>()
|
||||||
|
private var mSubItemUIValueCache: HashMap<String,Double> = HashMap()//美型子项脸型的UI缓存值
|
||||||
|
private var mSkinIndex = 0
|
||||||
|
private var mShapeIndex = 1
|
||||||
|
private var mIsOnBeautyShapeMain = true//美型是否在主项上
|
||||||
|
|
||||||
|
private lateinit var mBeautyAdapter: BaseListAdapter<FaceBeautyBean>
|
||||||
|
|
||||||
|
/* 滤镜 */
|
||||||
|
private var mFilters = ArrayList<FaceBeautyFilterBean>()
|
||||||
|
private lateinit var mFiltersAdapter: BaseListAdapter<FaceBeautyFilterBean>
|
||||||
|
|
||||||
|
/* 风格 */
|
||||||
|
private var mStyles = ArrayList<FaceBeautyStyleBean>()
|
||||||
|
private lateinit var mStylesAdapter: BaseListAdapter<FaceBeautyStyleBean>
|
||||||
|
private var mEnableBottomRationClick = true
|
||||||
|
// region init
|
||||||
|
|
||||||
|
init {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.layout_face_beauty_control, this)
|
||||||
|
initView()
|
||||||
|
initAdapter()
|
||||||
|
bindListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给控制绑定FaceBeautyController,数据工厂
|
||||||
|
* @param dataFactory IFaceBeautyDataFactory
|
||||||
|
*/
|
||||||
|
fun bindDataFactory(dataFactory: AbstractFaceBeautyDataFactory) {
|
||||||
|
mDataFactory = dataFactory
|
||||||
|
mModelAttributeRange = dataFactory.modelAttributeRange
|
||||||
|
mSkinBeauty = dataFactory.skinBeauty
|
||||||
|
mShapeBeauty = dataFactory.shapeBeauty
|
||||||
|
mShapeBeautySubItem = dataFactory.shapeBeautySubItem
|
||||||
|
mFilters = dataFactory.beautyFilters
|
||||||
|
mStyles = dataFactory.beautyStyles
|
||||||
|
mFiltersAdapter.setData(mFilters)
|
||||||
|
mStylesAdapter.setData(mStyles)
|
||||||
|
if (dataFactory.currentStyleIndex > -1) {
|
||||||
|
lyt_style_recover.isSelected = false
|
||||||
|
setBottomCheckRatioEnable(false)
|
||||||
|
var data = mStyles[dataFactory.currentStyleIndex]
|
||||||
|
mDataFactory.onStyleSelected(data.key)
|
||||||
|
} else {
|
||||||
|
lyt_style_recover.isSelected = true
|
||||||
|
setBottomCheckRatioEnable(true)
|
||||||
|
}
|
||||||
|
beauty_radio_group.check(View.NO_ID)
|
||||||
|
|
||||||
|
//恢复上一次脸型选项的UI值
|
||||||
|
mSubItemUIValueCache = mDataFactory.getCurrentFaceShapeUIValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收回菜单栏
|
||||||
|
*/
|
||||||
|
fun hideControlView() {
|
||||||
|
beauty_radio_group.check(View.NO_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View初始化
|
||||||
|
*/
|
||||||
|
private fun initView() {
|
||||||
|
initHorizontalRecycleView(recycler_view)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造Adapter
|
||||||
|
*/
|
||||||
|
private fun initAdapter() {
|
||||||
|
mStylesAdapter = BaseListAdapter(
|
||||||
|
ArrayList(), object : BaseDelegate<FaceBeautyStyleBean>() {
|
||||||
|
override fun convert(viewType: Int, helper: BaseViewHolder, data: FaceBeautyStyleBean, position: Int) {
|
||||||
|
helper.setText(R.id.tv_control, data.desRes)
|
||||||
|
helper.setImageResource(R.id.iv_control, data.imageRes)
|
||||||
|
helper.itemView.isSelected = mDataFactory.currentStyleIndex == position
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClickListener(view: View, data: FaceBeautyStyleBean, position: Int) {
|
||||||
|
super.onItemClickListener(view, data, position)
|
||||||
|
if (mDataFactory.currentStyleIndex != position) {
|
||||||
|
lyt_style_recover.isSelected = false
|
||||||
|
setBottomCheckRatioEnable(false)
|
||||||
|
changeAdapterSelected(mStylesAdapter, mDataFactory.currentStyleIndex, position)
|
||||||
|
mDataFactory.currentStyleIndex = position
|
||||||
|
mDataFactory.onStyleSelected(data.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, R.layout.list_item_control_title_image_circle
|
||||||
|
)
|
||||||
|
|
||||||
|
mFiltersAdapter = BaseListAdapter(
|
||||||
|
ArrayList(), object : BaseDelegate<FaceBeautyFilterBean>() {
|
||||||
|
override fun convert(viewType: Int, helper: BaseViewHolder, data: FaceBeautyFilterBean, position: Int) {
|
||||||
|
helper.setText(R.id.tv_control, data.desRes)
|
||||||
|
helper.setImageResource(R.id.iv_control, data.imageRes)
|
||||||
|
helper.itemView.isSelected = mDataFactory.currentFilterIndex == position
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClickListener(view: View, data: FaceBeautyFilterBean, position: Int) {
|
||||||
|
super.onItemClickListener(view, data, position)
|
||||||
|
if (mDataFactory.currentFilterIndex != position) {
|
||||||
|
changeAdapterSelected(mFiltersAdapter, mDataFactory.currentFilterIndex, position)
|
||||||
|
mDataFactory.currentFilterIndex = position
|
||||||
|
mDataFactory.onFilterSelected(data.key, data.intensity, data.desRes)
|
||||||
|
if (position == 0) {
|
||||||
|
beauty_seek_bar.visibility = View.INVISIBLE
|
||||||
|
} else {
|
||||||
|
seekToSeekBar(data.intensity, 0.0, 1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, R.layout.list_item_control_title_image_square
|
||||||
|
)
|
||||||
|
|
||||||
|
mBeautyAdapter = BaseListAdapter(ArrayList(), object : BaseDelegate<FaceBeautyBean>() {
|
||||||
|
override fun convert(viewType: Int, helper: BaseViewHolder, data: FaceBeautyBean, position: Int) {
|
||||||
|
val isShinSelected = beauty_radio_group.checkedCheckBoxId == R.id.beauty_radio_skin_beauty
|
||||||
|
helper.itemView.isSelected = if (isShinSelected) mSkinIndex == position else mShapeIndex == position
|
||||||
|
helper.setText(R.id.tv_control, data.desRes)
|
||||||
|
//主项的时候才需要显示
|
||||||
|
// helper.setVisible(R.id.iv_oval_spot, !isShinSelected && mIsOnBeautyShapeMain && position ==0)
|
||||||
|
val value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
when (data.buttonType) {
|
||||||
|
FaceBeautyBean.ButtonType.BACK_BUTTON -> {
|
||||||
|
helper.setImageResource(R.id.iv_control, data.closeRes)
|
||||||
|
}
|
||||||
|
FaceBeautyBean.ButtonType.SUB_ITEM_BUTTON -> {
|
||||||
|
//判断当前UI值 和 真实值是否全是空的如果是空的则不选中
|
||||||
|
//先过UI值
|
||||||
|
var choose = false
|
||||||
|
run outside@{
|
||||||
|
mSubItemUIValueCache.forEach {
|
||||||
|
if (it.value > 0) {
|
||||||
|
choose = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mShapeBeautySubItem.forEach {
|
||||||
|
if (it.buttonType == FaceBeautyBean.ButtonType.NORMAL_BUTTON) {
|
||||||
|
if (mDataFactory.getParamIntensity(it.key) > 0) {
|
||||||
|
choose = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.setImageResource(R.id.iv_control, if (choose) data.openRes else data.closeRes)
|
||||||
|
}
|
||||||
|
//普通按钮
|
||||||
|
else -> {
|
||||||
|
val stand = mModelAttributeRange[data.key]!!.stand
|
||||||
|
if (DecimalUtils.doubleEquals(value, stand)) {
|
||||||
|
helper.setImageResource(R.id.iv_control, data.closeRes)
|
||||||
|
} else {
|
||||||
|
helper.setImageResource(R.id.iv_control, data.openRes)
|
||||||
|
}
|
||||||
|
if (!data.canUseFunction) {
|
||||||
|
val ivControl = helper.getView<ImageView>(R.id.iv_control)
|
||||||
|
ivControl?.imageAlpha = 154
|
||||||
|
} else {
|
||||||
|
val ivControl = helper.getView<ImageView>(R.id.iv_control)
|
||||||
|
ivControl?.imageAlpha = 255
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openEnterAnimation && needEnterAnimation && position != 0) {
|
||||||
|
enterAnimation(helper.itemView)
|
||||||
|
if (position >=4 || (mBeautyAdapter.itemCount < 5 && position == mBeautyAdapter.itemCount - 1)) {
|
||||||
|
needEnterAnimation = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClickListener(view: View, data: FaceBeautyBean, position: Int) {
|
||||||
|
val isShinSelected = beauty_radio_group.checkedCheckBoxId == R.id.beauty_radio_skin_beauty
|
||||||
|
if ((isShinSelected && position == mSkinIndex) || (!isShinSelected && position == mShapeIndex)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!data.canUseFunction) {
|
||||||
|
ToastHelper.showNormalToast(mContext,data.toastDesRes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (isShinSelected) {
|
||||||
|
changeAdapterSelected(mBeautyAdapter, mSkinIndex, position)
|
||||||
|
val value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
val stand = mModelAttributeRange[data.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[data.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
mSkinIndex = position
|
||||||
|
} else {
|
||||||
|
when (data.buttonType) {
|
||||||
|
FaceBeautyBean.ButtonType.BACK_BUTTON -> {
|
||||||
|
//返回按钮
|
||||||
|
mBeautyAdapter.setData(mShapeBeauty)
|
||||||
|
//没有按钮被选中,需要隐藏进度条
|
||||||
|
beauty_seek_bar.visibility = View.INVISIBLE
|
||||||
|
changeAdapterSelected(mBeautyAdapter, mShapeIndex, -1)
|
||||||
|
mShapeIndex = -1
|
||||||
|
mIsOnBeautyShapeMain = true
|
||||||
|
needEnterAnimation = true
|
||||||
|
}
|
||||||
|
FaceBeautyBean.ButtonType.SUB_ITEM_BUTTON -> {
|
||||||
|
//子项按钮
|
||||||
|
//选中的是哪一个子项 -> 在FaceBeauty中有记录
|
||||||
|
run outside@{
|
||||||
|
mShapeBeautySubItem.forEachIndexed{ index, value ->
|
||||||
|
if (mDataFactory.getCurrentOneHotFaceShape() == value.key) {//获取当前作用的脸型
|
||||||
|
mShapeIndex = index
|
||||||
|
return@outside
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mBeautyAdapter.setData(mShapeBeautySubItem)
|
||||||
|
if (mShapeBeautySubItem.size >= 1) {
|
||||||
|
beauty_seek_bar.visibility = View.VISIBLE
|
||||||
|
val faceBeautyBean = mShapeBeautySubItem[mShapeIndex]
|
||||||
|
if (faceBeautyBean.buttonType == FaceBeautyBean.ButtonType.NORMAL_BUTTON) {
|
||||||
|
val value = mDataFactory.getParamIntensity(faceBeautyBean.key)
|
||||||
|
val stand = mModelAttributeRange[faceBeautyBean.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[faceBeautyBean.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mIsOnBeautyShapeMain = false
|
||||||
|
needEnterAnimation = true
|
||||||
|
}
|
||||||
|
//普通按钮
|
||||||
|
else -> {
|
||||||
|
//点击的是子项普通按钮还是主项普通按钮1.子项普通之间按钮效果One Hot 2.主项普通按钮之间效果可叠加
|
||||||
|
beauty_seek_bar.visibility = View.VISIBLE
|
||||||
|
changeAdapterSelected(mBeautyAdapter, mShapeIndex, position)
|
||||||
|
//判断一下是子项还是主项,1.主项直接设置改点击对象的值,2.子项需要获取之前的缓存如果存在缓存设置回之前的值,然后还要将上一个点击过的子项sdk值设置为零,UI值进行缓存
|
||||||
|
var value:Double
|
||||||
|
if (mIsOnBeautyShapeMain) {
|
||||||
|
value = mDataFactory.getParamIntensity(data.key)
|
||||||
|
} else {
|
||||||
|
//子项 one hot + 如果有UI值显示UI值 -> 并将UI缓存值设置到SDK
|
||||||
|
value = if (mSubItemUIValueCache.contains(data.key)) {
|
||||||
|
var value = mSubItemUIValueCache[data.key]!!
|
||||||
|
mDataFactory.updateParamIntensity(data.key, value)
|
||||||
|
mSubItemUIValueCache.remove(data.key)!!
|
||||||
|
} else
|
||||||
|
mDataFactory.getParamIntensity(data.key)
|
||||||
|
//将上一个点击的有效项设置为空
|
||||||
|
if (mShapeIndex >= 0) {
|
||||||
|
var beforeData = mBeautyAdapter.getData(mShapeIndex)
|
||||||
|
when (beforeData.buttonType) {
|
||||||
|
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
|
||||||
|
//算法值要设置为零,但是点击回来的时候需要根据UI值(缓存值)重新设置回算法值
|
||||||
|
mSubItemUIValueCache[beforeData.key] = mDataFactory.getParamIntensity(beforeData.key)
|
||||||
|
mDataFactory.updateParamIntensity(beforeData.key,0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDataFactory.setCurrentOneHotFaceShape(data.key)
|
||||||
|
mBeautyAdapter.notifyItemChanged(mShapeIndex)
|
||||||
|
mBeautyAdapter.notifyItemChanged(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置当前点击bean的进度值
|
||||||
|
val stand = mModelAttributeRange[data.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[data.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
mShapeIndex = position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}, R.layout.list_item_control_title_image_circle)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定监听事件
|
||||||
|
*/
|
||||||
|
private fun bindListener() {
|
||||||
|
/*拦截触碰事件*/
|
||||||
|
fyt_bottom_view.setOnTouchListener { _, _ -> true }
|
||||||
|
/*菜单控制*/
|
||||||
|
bindBottomRadioListener()
|
||||||
|
/*滑动条控制*/
|
||||||
|
bindSeekBarListener()
|
||||||
|
/*比对开关*/
|
||||||
|
iv_compare.setOnTouchStateListener { v, event ->
|
||||||
|
val action = event.action
|
||||||
|
if (action == MotionEvent.ACTION_DOWN) {
|
||||||
|
v.alpha = 0.7f
|
||||||
|
mDataFactory.enableFaceBeauty(false)
|
||||||
|
} else if (action == MotionEvent.ACTION_UP) {
|
||||||
|
v.alpha = 1f
|
||||||
|
mDataFactory.enableFaceBeauty(true)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
/*还原数据*/
|
||||||
|
lyt_beauty_recover.setOnClickListener {
|
||||||
|
showDialog(mContext.getString(R.string.dialog_reset_avatar_model)) { recoverData() }
|
||||||
|
|
||||||
|
}
|
||||||
|
lyt_style_recover.setOnClickListener {
|
||||||
|
if (it.isSelected) {
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
changeAdapterSelected(mStylesAdapter, mDataFactory.currentStyleIndex, -1)
|
||||||
|
mDataFactory.currentStyleIndex = -1
|
||||||
|
it.isSelected = true
|
||||||
|
setBottomCheckRatioEnable(true)
|
||||||
|
mDataFactory.onStyleSelected(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
iv_reset.setOnClickListener {
|
||||||
|
mDataFactory.resetParamIntensity()
|
||||||
|
var item:FaceBeautyBean? = null
|
||||||
|
when (beauty_radio_group.checkedCheckBoxId) {
|
||||||
|
R.id.beauty_radio_skin_beauty -> {
|
||||||
|
mBeautyAdapter.notifyDataSetChanged()
|
||||||
|
item = mSkinBeauty[mSkinIndex]
|
||||||
|
setRecoverFaceSkinEnable(true)
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_face_shape -> {
|
||||||
|
mBeautyAdapter.notifyDataSetChanged()
|
||||||
|
item = mShapeBeauty[mShapeIndex]
|
||||||
|
setRecoverFaceSkinEnable(true)
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_filter -> {
|
||||||
|
mFiltersAdapter.notifyDataSetChanged()
|
||||||
|
beauty_seek_bar.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_style -> {
|
||||||
|
mStylesAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item?.let {
|
||||||
|
val value = mDataFactory.getParamIntensity(it.key)
|
||||||
|
val stand = mModelAttributeRange[it.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[it.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 滚动条绑定事件
|
||||||
|
*/
|
||||||
|
private fun bindSeekBarListener() {
|
||||||
|
beauty_seek_bar.setOnProgressChangeListener(object : DiscreteSeekBar.OnSimpleProgressChangeListener() {
|
||||||
|
override fun onProgressChanged(seekBar: DiscreteSeekBar?, value: Int, fromUser: Boolean) {
|
||||||
|
if (!fromUser) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val valueF = 1.0 * (value - seekBar!!.min) / 100
|
||||||
|
when (beauty_radio_group.checkedCheckBoxId) {
|
||||||
|
R.id.beauty_radio_skin_beauty -> {
|
||||||
|
val bean = mSkinBeauty[mSkinIndex]
|
||||||
|
val range = mModelAttributeRange[bean.key]!!.maxRange
|
||||||
|
val res = valueF * range
|
||||||
|
val value = mDataFactory.getParamIntensity(bean.key)
|
||||||
|
if (!DecimalUtils.doubleEquals(res, value)) {
|
||||||
|
mDataFactory.updateParamIntensity(bean.key, res)
|
||||||
|
setRecoverFaceSkinEnable(checkFaceSkinChanged())
|
||||||
|
updateBeautyItemUI(mBeautyAdapter.getViewHolderByPosition(mSkinIndex), bean)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_face_shape -> {
|
||||||
|
if (mShapeIndex < 0) return
|
||||||
|
val bean = mBeautyAdapter.getData(mShapeIndex)
|
||||||
|
when (bean.buttonType) {
|
||||||
|
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
|
||||||
|
//判断一下这个按钮的类型
|
||||||
|
val range = mModelAttributeRange[bean.key]!!.maxRange
|
||||||
|
val res = valueF * range
|
||||||
|
val value = mDataFactory.getParamIntensity(bean.key)
|
||||||
|
if (!DecimalUtils.doubleEquals(res, value)) {
|
||||||
|
mDataFactory.updateParamIntensity(bean.key, res)
|
||||||
|
setRecoverFaceSkinEnable(checkFaceShapeChanged())
|
||||||
|
updateBeautyItemUI(mBeautyAdapter.getViewHolderByPosition(mShapeIndex), bean)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_filter -> {
|
||||||
|
val bean = mFilters[mDataFactory.currentFilterIndex]
|
||||||
|
if (!DecimalUtils.doubleEquals(bean.intensity, valueF)) {
|
||||||
|
bean.intensity = valueF
|
||||||
|
mDataFactory.updateFilterIntensity(valueF)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 底部导航栏绑定监听事件,处理RecycleView等相关布局变更
|
||||||
|
*/
|
||||||
|
private fun bindBottomRadioListener() {
|
||||||
|
beauty_radio_group.setOnDispatchActionUpListener { x ->
|
||||||
|
if (!mEnableBottomRationClick) {
|
||||||
|
val width = beauty_radio_group.measuredWidth
|
||||||
|
when {
|
||||||
|
x < width * 0.25 -> {
|
||||||
|
val toastStr = mContext.getString(R.string.beauty_face_style_toast, mContext.getString(R.string.beauty_radio_skin_beauty))
|
||||||
|
ToastHelper.showNormalToast(mContext, toastStr)
|
||||||
|
}
|
||||||
|
x < width * 0.5 -> {
|
||||||
|
val toastStr = mContext.getString(R.string.beauty_face_style_toast, mContext.getString(R.string.beauty_radio_face_shape))
|
||||||
|
ToastHelper.showNormalToast(mContext, toastStr)
|
||||||
|
}
|
||||||
|
x < width * 0.75f -> {
|
||||||
|
val toastStr = mContext.getString(R.string.beauty_face_style_toast, mContext.getString(R.string.beauty_radio_filter))
|
||||||
|
ToastHelper.showNormalToast(mContext, toastStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beauty_radio_group.setOnCheckedChangeListener { _, checkedId ->
|
||||||
|
//视图变化
|
||||||
|
when (checkedId) {
|
||||||
|
R.id.beauty_radio_skin_beauty, R.id.beauty_radio_face_shape -> {
|
||||||
|
iv_compare.visibility = View.VISIBLE
|
||||||
|
beauty_seek_bar.visibility = View.VISIBLE
|
||||||
|
lyt_style_recover.visibility = View.GONE
|
||||||
|
lyt_beauty_recover.visibility = View.VISIBLE
|
||||||
|
iv_line.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_filter -> {
|
||||||
|
iv_compare.visibility = View.VISIBLE
|
||||||
|
beauty_seek_bar.visibility = if (mDataFactory.currentFilterIndex == 0) View.INVISIBLE else View.VISIBLE
|
||||||
|
lyt_style_recover.visibility = View.GONE
|
||||||
|
lyt_beauty_recover.visibility = View.GONE
|
||||||
|
iv_line.visibility = View.GONE
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_style -> {
|
||||||
|
iv_compare.visibility = View.VISIBLE
|
||||||
|
beauty_seek_bar.visibility = View.INVISIBLE
|
||||||
|
lyt_beauty_recover.visibility = View.GONE
|
||||||
|
lyt_style_recover.visibility = View.VISIBLE
|
||||||
|
iv_line.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
View.NO_ID -> {
|
||||||
|
iv_compare.visibility = View.INVISIBLE
|
||||||
|
mDataFactory.enableFaceBeauty(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//数据变化
|
||||||
|
when (checkedId) {
|
||||||
|
R.id.beauty_radio_skin_beauty -> {
|
||||||
|
mBeautyAdapter.setData(mSkinBeauty)
|
||||||
|
recycler_view.adapter = mBeautyAdapter
|
||||||
|
val item = mSkinBeauty[mSkinIndex]
|
||||||
|
val value = mDataFactory.getParamIntensity(item.key)
|
||||||
|
val stand = mModelAttributeRange[item.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[item.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
setRecoverFaceSkinEnable(checkFaceSkinChanged())
|
||||||
|
changeBottomLayoutAnimator(true)
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_face_shape -> {
|
||||||
|
mBeautyAdapter.setData(mShapeBeauty)
|
||||||
|
recycler_view.adapter = mBeautyAdapter
|
||||||
|
if (mShapeIndex >= 0) {
|
||||||
|
val item = mShapeBeauty[mShapeIndex]
|
||||||
|
val value = mDataFactory.getParamIntensity(item.key)
|
||||||
|
val stand = mModelAttributeRange[item.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[item.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
setRecoverFaceSkinEnable(checkFaceShapeChanged())
|
||||||
|
changeBottomLayoutAnimator(true)
|
||||||
|
} else {
|
||||||
|
beauty_seek_bar.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_filter -> {
|
||||||
|
recycler_view.adapter = mFiltersAdapter
|
||||||
|
recycler_view.scrollToPosition(mDataFactory.currentFilterIndex)
|
||||||
|
if (mDataFactory.currentFilterIndex == 0) {
|
||||||
|
beauty_seek_bar.visibility = View.INVISIBLE
|
||||||
|
} else {
|
||||||
|
seekToSeekBar(mFilters[mDataFactory.currentFilterIndex].intensity, 0.0, 1.0)
|
||||||
|
}
|
||||||
|
changeBottomLayoutAnimator(true)
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_style -> {
|
||||||
|
recycler_view.adapter = mStylesAdapter
|
||||||
|
if (mDataFactory.currentStyleIndex > -1) {
|
||||||
|
recycler_view.scrollToPosition(mDataFactory.currentStyleIndex)
|
||||||
|
lyt_style_recover.isSelected = false
|
||||||
|
} else {
|
||||||
|
lyt_style_recover.isSelected = true
|
||||||
|
}
|
||||||
|
changeBottomLayoutAnimator(true)
|
||||||
|
}
|
||||||
|
View.NO_ID -> {
|
||||||
|
changeBottomLayoutAnimator(false)
|
||||||
|
mDataFactory.enableFaceBeauty(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun setBottomCheckRatioEnable(enable: Boolean) {
|
||||||
|
mEnableBottomRationClick = enable
|
||||||
|
var i = 0
|
||||||
|
val childCount: Int = beauty_radio_group.getChildCount()
|
||||||
|
while (i < childCount) {
|
||||||
|
val view: View = beauty_radio_group.getChildAt(i)
|
||||||
|
if (view.id != R.id.beauty_radio_style) {
|
||||||
|
view.alpha = if (enable) 1f else 0.6f
|
||||||
|
view.isEnabled = enable
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
// region 业务处理
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置滚动条数值
|
||||||
|
* @param value Double 结果值
|
||||||
|
* @param stand Double 标准值
|
||||||
|
* @param range Double 范围区间
|
||||||
|
*/
|
||||||
|
private fun seekToSeekBar(value: Double, stand: Double, range: Double) {
|
||||||
|
if (stand == 0.5) {
|
||||||
|
beauty_seek_bar.min = -50
|
||||||
|
beauty_seek_bar.max = 50
|
||||||
|
beauty_seek_bar.progress = (value * 100 / range - 50).toInt()
|
||||||
|
} else {
|
||||||
|
beauty_seek_bar.min = 0
|
||||||
|
beauty_seek_bar.max = 100
|
||||||
|
beauty_seek_bar.progress = (value * 100 / range).toInt()
|
||||||
|
}
|
||||||
|
beauty_seek_bar.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新单项是否为基准值显示
|
||||||
|
*/
|
||||||
|
private fun updateBeautyItemUI(viewHolder: BaseViewHolder?, item: FaceBeautyBean) {
|
||||||
|
val value = mDataFactory.getParamIntensity(item.key)
|
||||||
|
val stand = mModelAttributeRange[item.key]!!.stand
|
||||||
|
if (DecimalUtils.doubleEquals(value, stand)) {
|
||||||
|
viewHolder?.setImageResource(R.id.iv_control, item.closeRes)
|
||||||
|
} else {
|
||||||
|
viewHolder?.setImageResource(R.id.iv_control, item.openRes)
|
||||||
|
}
|
||||||
|
mBeautyAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置还原按钮状态
|
||||||
|
*/
|
||||||
|
private fun setRecoverFaceSkinEnable(enable: Boolean) {
|
||||||
|
if (enable) {
|
||||||
|
tv_beauty_recover.alpha = 1f
|
||||||
|
iv_beauty_recover.alpha = 1f
|
||||||
|
} else {
|
||||||
|
tv_beauty_recover.alpha = 0.6f
|
||||||
|
iv_beauty_recover.alpha = 0.6f
|
||||||
|
}
|
||||||
|
lyt_beauty_recover.isEnabled = enable
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历美肤数据确认还原按钮是否可以点击
|
||||||
|
*/
|
||||||
|
private fun checkFaceSkinChanged(): Boolean {
|
||||||
|
val item = mSkinBeauty[mSkinIndex]
|
||||||
|
var value = mDataFactory.getParamIntensity(item.key)
|
||||||
|
var default = mModelAttributeRange[item.key]!!.default
|
||||||
|
if (!DecimalUtils.doubleEquals(value, default)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
mSkinBeauty.forEach {
|
||||||
|
value = mDataFactory.getParamIntensity(it.key)
|
||||||
|
default = mModelAttributeRange[it.key]!!.default
|
||||||
|
if (!DecimalUtils.doubleEquals(value, default)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历美型数据确认还原按钮是否可以点击
|
||||||
|
*/
|
||||||
|
private fun checkFaceShapeChanged(): Boolean {
|
||||||
|
if (checkFaceShapeChanged(mShapeBeauty) || checkFaceShapeChanged(mShapeBeautySubItem))
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历美型数据确认还原按钮是否可以点击
|
||||||
|
*/
|
||||||
|
private fun checkFaceShapeChanged(shapeBeauty: ArrayList<FaceBeautyBean>): Boolean {
|
||||||
|
var value: Double
|
||||||
|
var default: Double
|
||||||
|
if (shapeBeauty.size > mShapeIndex) {
|
||||||
|
var item = shapeBeauty[mShapeIndex]
|
||||||
|
item?.let {
|
||||||
|
value = mDataFactory.getParamIntensity(item.key)
|
||||||
|
default = mModelAttributeRange[item.key]!!.default
|
||||||
|
if (!DecimalUtils.doubleEquals(value, default)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shapeBeauty.forEach {
|
||||||
|
when (it.buttonType) {
|
||||||
|
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
|
||||||
|
value = mDataFactory.getParamIntensity(it.key)
|
||||||
|
default = mModelAttributeRange[it.key]!!.default
|
||||||
|
if (!DecimalUtils.doubleEquals(value, default)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 还原 美型、美肤数据
|
||||||
|
*/
|
||||||
|
private fun recoverData() {
|
||||||
|
when (beauty_radio_group.checkedCheckBoxId) {
|
||||||
|
R.id.beauty_radio_skin_beauty -> {
|
||||||
|
mSkinBeauty.forEach {
|
||||||
|
val default = mModelAttributeRange[it.key]!!.default
|
||||||
|
mDataFactory.updateParamIntensity(it.key, default)
|
||||||
|
}
|
||||||
|
val item = mSkinBeauty[mSkinIndex]
|
||||||
|
val value = mDataFactory.getParamIntensity(item.key)
|
||||||
|
val stand = mModelAttributeRange[item.key]!!.stand
|
||||||
|
val maxRange = mModelAttributeRange[item.key]!!.maxRange
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
mBeautyAdapter.notifyDataSetChanged()
|
||||||
|
setRecoverFaceSkinEnable(false)
|
||||||
|
}
|
||||||
|
R.id.beauty_radio_face_shape -> {
|
||||||
|
//还原主项和子项
|
||||||
|
mShapeBeauty.forEach {
|
||||||
|
when (it.buttonType) {
|
||||||
|
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
|
||||||
|
val default = mModelAttributeRange[it.key]!!.default
|
||||||
|
mDataFactory.updateParamIntensity(it.key, default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//还原子项
|
||||||
|
mShapeBeautySubItem.forEach {
|
||||||
|
when (it.buttonType) {
|
||||||
|
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
|
||||||
|
val default = mModelAttributeRange[it.key]!!.default
|
||||||
|
mDataFactory.updateParamIntensity(it.key, default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取当前shapeAdapter中被选中的项
|
||||||
|
var value = 0.0
|
||||||
|
var stand = 0.0
|
||||||
|
var maxRange = 1.0
|
||||||
|
if (mShapeIndex > 0) {
|
||||||
|
val item = mBeautyAdapter.getData(mShapeIndex)
|
||||||
|
when (item.buttonType) {
|
||||||
|
FaceBeautyBean.ButtonType.NORMAL_BUTTON -> {
|
||||||
|
value = mDataFactory.getParamIntensity(item.key)
|
||||||
|
stand = mModelAttributeRange[item.key]!!.stand
|
||||||
|
maxRange = mModelAttributeRange[item.key]!!.maxRange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seekToSeekBar(value, stand, maxRange)
|
||||||
|
mBeautyAdapter.notifyDataSetChanged()
|
||||||
|
setRecoverFaceSkinEnable(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 底部动画处理
|
||||||
|
* @param isOpen Boolean
|
||||||
|
*/
|
||||||
|
private fun changeBottomLayoutAnimator(isOpen: Boolean) {
|
||||||
|
if (isBottomShow == isOpen) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val start = if (isOpen) resources.getDimension(R.dimen.x1).toInt() else resources.getDimension(R.dimen.x268).toInt()
|
||||||
|
val end = if (isOpen) resources.getDimension(R.dimen.x268).toInt() else resources.getDimension(R.dimen.x1).toInt()
|
||||||
|
|
||||||
|
if (bottomLayoutAnimator != null && bottomLayoutAnimator!!.isRunning) {
|
||||||
|
bottomLayoutAnimator!!.end()
|
||||||
|
}
|
||||||
|
bottomLayoutAnimator = ValueAnimator.ofInt(start, end).setDuration(150)
|
||||||
|
bottomLayoutAnimator!!.addUpdateListener { animation ->
|
||||||
|
val height = animation.animatedValue as Int
|
||||||
|
val params = fyt_bottom_view.layoutParams as LinearLayout.LayoutParams
|
||||||
|
params.height = height
|
||||||
|
fyt_bottom_view.layoutParams = params
|
||||||
|
if (onBottomAnimatorChangeListener != null) {
|
||||||
|
val showRate = 1.0f * (height - start) / (end - start)
|
||||||
|
onBottomAnimatorChangeListener?.onBottomAnimatorChangeListener(if (!isOpen) 1 - showRate else showRate)
|
||||||
|
}
|
||||||
|
if (DecimalUtils.floatEquals(animation.animatedFraction, 1.0f) && isOpen) {
|
||||||
|
iv_compare.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bottomLayoutAnimator!!.start()
|
||||||
|
isBottomShow = isOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromWindow() {
|
||||||
|
//被销毁前,记录此时的UI值,用于下一次启动的时候恢复
|
||||||
|
mSubItemUIValueCache.forEach {
|
||||||
|
//应该要将UI值保存用于后续恢复
|
||||||
|
|
||||||
|
}
|
||||||
|
super.onDetachedFromWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* item入场动画总开关 */
|
||||||
|
val openEnterAnimation = false
|
||||||
|
|
||||||
|
/* 是否需要对该子项进行入场动画 */
|
||||||
|
var needEnterAnimation = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recycleView ITEM 子项入场动画
|
||||||
|
*/
|
||||||
|
fun enterAnimation(view:View){
|
||||||
|
//动画集合
|
||||||
|
val animSet = AnimationSet(false)
|
||||||
|
//位移动画
|
||||||
|
val translateAnim = TranslateAnimation(
|
||||||
|
Animation.ABSOLUTE, 0f, Animation.ABSOLUTE, 0f,
|
||||||
|
Animation.ABSOLUTE, 100f, Animation.ABSOLUTE, 0f)
|
||||||
|
//渐变动画
|
||||||
|
val alphaAnim = AlphaAnimation(0.0f, 1.0f)
|
||||||
|
animSet.addAnimation(translateAnim)
|
||||||
|
animSet.addAnimation(alphaAnim)
|
||||||
|
animSet.duration = 300
|
||||||
|
animSet.fillAfter = true
|
||||||
|
animSet.addAnimation(alphaAnim)
|
||||||
|
view.startAnimation(animSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否展示还原按钮
|
||||||
|
*/
|
||||||
|
fun setResetButton(isVisible:Boolean) {
|
||||||
|
if (isVisible)
|
||||||
|
iv_reset.visibility = View.VISIBLE
|
||||||
|
else
|
||||||
|
iv_reset.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ import com.yunbao.faceunity.seekbar.DiscreteSeekBar;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DESC:
|
* DESC:美妆
|
||||||
* Created on 2021/4/26
|
* Created on 2021/4/26
|
||||||
*/
|
*/
|
||||||
public class MakeupControlView extends BaseControlView {
|
public class MakeupControlView extends BaseControlView {
|
||||||
|
@ -20,7 +20,7 @@ import com.yunbao.faceunity.infe.AbstractPropDataFactory;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DESC:
|
* DESC:贴图、AR面具
|
||||||
* Created on 2021/4/26
|
* Created on 2021/4/26
|
||||||
*/
|
*/
|
||||||
public class PropControlView extends BaseControlView {
|
public class PropControlView extends BaseControlView {
|
||||||
|
@ -0,0 +1,166 @@
|
|||||||
|
package com.yunbao.faceunity.data;
|
||||||
|
|
||||||
|
import com.faceunity.core.entity.FUBundleData;
|
||||||
|
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||||
|
import com.faceunity.core.faceunity.FUAIKit;
|
||||||
|
import com.faceunity.core.faceunity.FURenderKit;
|
||||||
|
import com.faceunity.core.model.animationFilter.AnimationFilter;
|
||||||
|
import com.faceunity.core.model.antialiasing.Antialiasing;
|
||||||
|
import com.faceunity.core.model.prop.Prop;
|
||||||
|
import com.faceunity.core.model.prop.PropContainer;
|
||||||
|
import com.faceunity.core.model.prop.animoji.Animoji;
|
||||||
|
import com.yunbao.faceunity.entity.AnimationFilterBean;
|
||||||
|
import com.yunbao.faceunity.entity.AnimojiBean;
|
||||||
|
import com.yunbao.faceunity.infe.AbstractAnimojiDataFactory;
|
||||||
|
import com.yunbao.faceunity.repo.AnimojiSource;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DESC:Animoji业务工厂
|
||||||
|
* Created on 2021/3/3
|
||||||
|
*/
|
||||||
|
public class AnimojiDataFactory extends AbstractAnimojiDataFactory {
|
||||||
|
|
||||||
|
/*渲染控制器*/
|
||||||
|
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||||
|
private FUAIKit mFUAIKit = FUAIKit.getInstance();
|
||||||
|
/*3D抗锯齿*/
|
||||||
|
public final Antialiasing antialiasing;
|
||||||
|
/*动漫滤镜模型*/
|
||||||
|
public final AnimationFilter animationFilter;
|
||||||
|
/*当前选中贴图模型*/
|
||||||
|
private Prop currentAnimoji;
|
||||||
|
/*当前选中下标*/
|
||||||
|
private int currentAnimojiIndex;
|
||||||
|
/*当前滤镜下标*/
|
||||||
|
private int currentFilterIndex;
|
||||||
|
/*Animoji数据*/
|
||||||
|
private ArrayList<AnimojiBean> animojiBeans;
|
||||||
|
/*Animoji滤镜数据*/
|
||||||
|
private ArrayList<AnimationFilterBean> animationFilterBeans;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 AnimojiDataFactory
|
||||||
|
*
|
||||||
|
* @param animojiIndex 贴图下标
|
||||||
|
* @param filterIndex 滤镜下标
|
||||||
|
*/
|
||||||
|
public AnimojiDataFactory(int animojiIndex, int filterIndex) {
|
||||||
|
antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING));
|
||||||
|
animationFilter = new AnimationFilter(new FUBundleData(FaceUnityConfig.BUNDLE_ANIMATION_FILTER));
|
||||||
|
currentAnimojiIndex = animojiIndex;
|
||||||
|
currentFilterIndex = filterIndex;
|
||||||
|
animojiBeans = AnimojiSource.buildAnimojis();
|
||||||
|
animationFilterBeans = AnimojiSource.buildFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动漫贴图列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ArrayList<AnimojiBean> getAnimojis() {
|
||||||
|
return animojiBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动漫滤镜列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ArrayList<AnimationFilterBean> getFilters() {
|
||||||
|
return animationFilterBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前选中动漫贴图下标
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getCurrentAnimojiIndex() {
|
||||||
|
return currentAnimojiIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前选中动漫贴图下标
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setCurrentAnimojiIndex(int currentAnimojiIndex) {
|
||||||
|
this.currentAnimojiIndex = currentAnimojiIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前选中滤镜下标
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getCurrentFilterIndex() {
|
||||||
|
return currentFilterIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前选中动漫贴图下标
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setCurrentFilterIndex(int currentFilterIndex) {
|
||||||
|
this.currentFilterIndex = currentFilterIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置选中贴图
|
||||||
|
*
|
||||||
|
* @param bean
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onAnimojiSelected(AnimojiBean bean) {
|
||||||
|
PropContainer propContainer = mFURenderKit.getPropContainer();
|
||||||
|
String path = bean.getPath();
|
||||||
|
Prop prop = null;
|
||||||
|
if (path != null && path.trim().length() > 0) {
|
||||||
|
prop = new Animoji(new FUBundleData(path));
|
||||||
|
}
|
||||||
|
propContainer.replaceProp(currentAnimoji, prop);
|
||||||
|
currentAnimoji = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置选中滤镜
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onFilterSelected(AnimationFilterBean data) {
|
||||||
|
animationFilter.setStyle(data.getStyle());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FURenderKit加载当前特效
|
||||||
|
*/
|
||||||
|
public void bindCurrentRenderer() {
|
||||||
|
mFUAIKit.loadAIProcessor(FaceUnityConfig.BUNDLE_AI_TONGUE, FUAITypeEnum.FUAITYPE_TONGUETRACKING);
|
||||||
|
mFUAIKit.setMaxFaces(4);
|
||||||
|
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
mFURenderKit.setAntialiasing(antialiasing);
|
||||||
|
mFURenderKit.setAnimationFilter(animationFilter);
|
||||||
|
animationFilter.setStyle(animationFilterBeans.get(currentFilterIndex).getStyle());
|
||||||
|
onAnimojiSelected(animojiBeans.get(currentAnimojiIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束需要释放AI驱动
|
||||||
|
*/
|
||||||
|
public void releaseAIProcessor() {
|
||||||
|
mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_TONGUETRACKING);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
package com.yunbao.faceunity.data;
|
||||||
|
|
||||||
|
import com.faceunity.core.avatar.model.Avatar;
|
||||||
|
import com.faceunity.core.avatar.model.Scene;
|
||||||
|
import com.faceunity.core.avatar.scene.ProcessorConfig;
|
||||||
|
import com.faceunity.core.entity.FUBundleData;
|
||||||
|
import com.faceunity.core.entity.FUCoordinate3DData;
|
||||||
|
import com.faceunity.core.enumeration.FUAITypeEnum;
|
||||||
|
import com.faceunity.core.faceunity.FUAIKit;
|
||||||
|
import com.faceunity.core.faceunity.FURenderKit;
|
||||||
|
import com.faceunity.core.faceunity.FUSceneKit;
|
||||||
|
import com.faceunity.core.model.antialiasing.Antialiasing;
|
||||||
|
import com.yunbao.faceunity.entity.AvatarBean;
|
||||||
|
import com.yunbao.faceunity.infe.AbstractAvatarDataFactory;
|
||||||
|
import com.yunbao.faceunity.repo.AvatarSource;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DESC:
|
||||||
|
* Created on 2021/3/30
|
||||||
|
*/
|
||||||
|
public class AvatarDataFactory extends AbstractAvatarDataFactory {
|
||||||
|
|
||||||
|
/*渲染控制器*/
|
||||||
|
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||||
|
private FUAIKit mFUAIKit = FUAIKit.getInstance();
|
||||||
|
/*3D抗锯齿*/
|
||||||
|
public final Antialiasing antialiasing;
|
||||||
|
|
||||||
|
/* 人物队列 */
|
||||||
|
private ArrayList<AvatarBean> members;
|
||||||
|
/* 当前选中人物下标 */
|
||||||
|
private int currentMemberIndex;
|
||||||
|
/* 驱动类型是否为全身 */
|
||||||
|
private Boolean isHumanTrackSceneFull;
|
||||||
|
|
||||||
|
/* 场景 */
|
||||||
|
private Scene sceneModel;
|
||||||
|
/* 男孩对象 */
|
||||||
|
private Avatar boyAvatarModel;
|
||||||
|
/* 女孩对象 */
|
||||||
|
private Avatar girlAvatarModel;
|
||||||
|
/*当前对象*/
|
||||||
|
private Avatar currentAvatarModel;
|
||||||
|
|
||||||
|
|
||||||
|
public AvatarDataFactory(int index, boolean isFull) {
|
||||||
|
isHumanTrackSceneFull = isFull;
|
||||||
|
currentMemberIndex = index;
|
||||||
|
members = AvatarSource.buildMembers();
|
||||||
|
antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING));
|
||||||
|
boyAvatarModel = AvatarSource.buildBoyData(isFull);
|
||||||
|
girlAvatarModel = AvatarSource.buildGirlData(isFull);
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
currentAvatarModel = girlAvatarModel;
|
||||||
|
} else if (index == 1) {
|
||||||
|
currentAvatarModel = boyAvatarModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneModel = AvatarSource.buildSceneModel(currentAvatarModel);
|
||||||
|
AvatarSource.setSceneBackGround(sceneModel, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取人物队列
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ArrayList<AvatarBean> getMembers() {
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前选中人物下标
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getCurrentMemberIndex() {
|
||||||
|
return currentMemberIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前人物选中下标
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setCurrentMemberIndex(int index) {
|
||||||
|
currentMemberIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前驱动类型
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isHumanTrackSceneFull() {
|
||||||
|
return isHumanTrackSceneFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前驱动类型
|
||||||
|
*
|
||||||
|
* @param isFull
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setHumanTrackSceneFull(boolean isFull) {
|
||||||
|
isHumanTrackSceneFull = isFull;
|
||||||
|
sceneModel.processorConfig.setTrackScene(isFull ? ProcessorConfig.TrackScene.SceneFull : ProcessorConfig.TrackScene.SceneHalf);
|
||||||
|
if (isFull) {
|
||||||
|
boyAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 58.14, -618.94));
|
||||||
|
girlAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 58.14, -618.94));
|
||||||
|
} else {
|
||||||
|
boyAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 11.76, -183.89));
|
||||||
|
girlAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 11.76, -183.89));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人物切换
|
||||||
|
*
|
||||||
|
* @param bean
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onMemberSelected(AvatarBean bean) {
|
||||||
|
if (mAvatarChoiceListener != null)
|
||||||
|
mAvatarChoiceListener.choiceAvatar(bean);
|
||||||
|
|
||||||
|
sceneModel.replaceAvatar(currentAvatarModel, bean.getDes().equals(AvatarSource.GIRL) ? girlAvatarModel : boyAvatarModel);
|
||||||
|
currentAvatarModel = bean.getDes().equals(AvatarSource.GIRL) ? girlAvatarModel : boyAvatarModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindCurrentRenderer() {
|
||||||
|
mFUAIKit.loadAIProcessor(FaceUnityConfig.getAIHumanBundle(), FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
|
||||||
|
mFUAIKit.setMaxFaces(1);
|
||||||
|
mFURenderKit.setAntialiasing(antialiasing);
|
||||||
|
FUSceneKit.getInstance().addSceneGL(sceneModel);
|
||||||
|
FUSceneKit.getInstance().setCurrentSceneGL(sceneModel);
|
||||||
|
setHumanTrackSceneFull(isHumanTrackSceneFull);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AvatarChoiceListener mAvatarChoiceListener;
|
||||||
|
|
||||||
|
public interface AvatarChoiceListener {
|
||||||
|
void choiceAvatar(AvatarBean avatarBean);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatarChoiceListener(AvatarChoiceListener avatarChoiceListener) {
|
||||||
|
this.mAvatarChoiceListener = avatarChoiceListener;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,347 @@
|
|||||||
|
package com.yunbao.faceunity.data;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.faceunity.core.controller.bgSegGreen.BgSegGreenParam;
|
||||||
|
import com.faceunity.core.entity.FUColorRGBData;
|
||||||
|
import com.faceunity.core.faceunity.FUAIKit;
|
||||||
|
import com.faceunity.core.faceunity.FURenderKit;
|
||||||
|
import com.faceunity.core.model.bgSegGreen.BgSegGreen;
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean;
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenBean;
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean;
|
||||||
|
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||||
|
import com.yunbao.faceunity.infe.AbstractBgSegGreenDataFactory;
|
||||||
|
import com.yunbao.faceunity.repo.BgSegGreenSource;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DESC:绿幕抠像业务工厂
|
||||||
|
* Created on 2021/3/4
|
||||||
|
*/
|
||||||
|
public class BgSegGreenDataFactory extends AbstractBgSegGreenDataFactory {
|
||||||
|
public interface BgSegGreenListener {
|
||||||
|
/**
|
||||||
|
* 取色状态回调
|
||||||
|
*
|
||||||
|
* @param isSelected 是否选中
|
||||||
|
* @param color 默认颜色
|
||||||
|
*/
|
||||||
|
void onColorPickerStateChanged(boolean isSelected, int color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换背景道具
|
||||||
|
*
|
||||||
|
* @param bean
|
||||||
|
*/
|
||||||
|
void onBackgroundSelected(BgSegGreenBackgroundBean bean);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加自定义安全区域图片
|
||||||
|
*/
|
||||||
|
void onSafeAreaAdd();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换安全区域图片
|
||||||
|
*
|
||||||
|
* @param bean
|
||||||
|
*/
|
||||||
|
void onSafeAreaSelected(BgSegGreenSafeAreaBean bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*渲染控制器*/
|
||||||
|
private final FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||||
|
|
||||||
|
/*绿幕抠像特效模型*/
|
||||||
|
private final BgSegGreen mBgSegGreen;
|
||||||
|
|
||||||
|
/*绿幕抠像背景列表*/
|
||||||
|
private final ArrayList<BgSegGreenBackgroundBean> mBgSegGreenBackgroundBeans;
|
||||||
|
/* 绿幕抠像当前背景下标 */
|
||||||
|
private int mCurrentBackgroundIndex;
|
||||||
|
|
||||||
|
/*绿幕抠像安全区域列表*/
|
||||||
|
private ArrayList<BgSegGreenSafeAreaBean> mBgSegGreenSafeAreaBeans;
|
||||||
|
/* 绿幕抠像当前安全区域下标 */
|
||||||
|
private int mCurrentSafeAreaIndex;
|
||||||
|
|
||||||
|
/* 回调 */
|
||||||
|
private final BgSegGreenListener mBgSegGreenListener;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造绿幕抠像
|
||||||
|
*
|
||||||
|
* @param listener 回调
|
||||||
|
* @param index 背景下标
|
||||||
|
*/
|
||||||
|
public BgSegGreenDataFactory(BgSegGreenListener listener, int index) {
|
||||||
|
mBgSegGreenListener = listener;
|
||||||
|
mBgSegGreen = BgSegGreenSource.buildBgSegGreen();
|
||||||
|
mBgSegGreenBackgroundBeans = BgSegGreenSource.buildBgSegGreenBackground();
|
||||||
|
mBgSegGreenSafeAreaBeans = BgSegGreenSource.buildBgSegGreenSafeArea();
|
||||||
|
mCurrentBackgroundIndex = index;
|
||||||
|
mCurrentSafeAreaIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取绿幕抠像当前背景下标
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public int getBackgroundIndex() {
|
||||||
|
return mCurrentBackgroundIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置绿幕抠像当前背景下标
|
||||||
|
*
|
||||||
|
* @param backgroundIndex
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setBackgroundIndex(int backgroundIndex) {
|
||||||
|
this.mCurrentBackgroundIndex = backgroundIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取绿幕抠像当前安全区域下标
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getBgSafeAreaIndex() {
|
||||||
|
return mCurrentSafeAreaIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置绿幕抠像安全区域下标
|
||||||
|
*
|
||||||
|
* @param currentSafeAreaIndex
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setBgSafeAreaIndex(int currentSafeAreaIndex) {
|
||||||
|
this.mCurrentSafeAreaIndex = currentSafeAreaIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新安全区UI
|
||||||
|
*/
|
||||||
|
public boolean updateSafeAreaBeansAndIndex() {
|
||||||
|
ArrayList<BgSegGreenSafeAreaBean> bgSegGreenSafeAreaBeans = BgSegGreenSource.buildBgSegGreenSafeArea();
|
||||||
|
if (!bgSegGreenSafeAreaBeans.equals(mBgSegGreenSafeAreaBeans)) {
|
||||||
|
//需要刷新数据
|
||||||
|
//比对数据 1、数据增加 or 自定义数据修改 -> 当前应该选中的角标
|
||||||
|
if (bgSegGreenSafeAreaBeans.size() > mBgSegGreenSafeAreaBeans.size()) {
|
||||||
|
//数据增加
|
||||||
|
if (mCurrentSafeAreaIndex > 2) {
|
||||||
|
mCurrentSafeAreaIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mBgSegGreenSafeAreaBeans = bgSegGreenSafeAreaBeans;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取绿幕抠像项目数据扩展模型
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public HashMap<String, ModelAttributeData> getModelAttributeRange() {
|
||||||
|
return BgSegGreenSource.buildModelAttributeRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取绿幕抠像功能列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ArrayList<BgSegGreenBean> getBgSegGreenActions() {
|
||||||
|
return BgSegGreenSource.buildBgSegGreenAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取绿幕抠像安全区域功能列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ArrayList<BgSegGreenSafeAreaBean> getBgSegGreenSafeAreas() {
|
||||||
|
return mBgSegGreenSafeAreaBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取绿幕抠像背景列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ArrayList<BgSegGreenBackgroundBean> getBgSegGreenBackgrounds() {
|
||||||
|
return mBgSegGreenBackgroundBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 背景图片变更
|
||||||
|
*
|
||||||
|
* @param data BgSegGreenBackgroundBean
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onBackgroundSelected(BgSegGreenBackgroundBean data) {
|
||||||
|
mBgSegGreenListener.onBackgroundSelected(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义安全区域
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onSafeAreaAdd() {
|
||||||
|
mBgSegGreenListener.onSafeAreaAdd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全区域变更
|
||||||
|
*
|
||||||
|
* @param data BgSegGreenBackgroundBean
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onSafeAreaSelected(BgSegGreenSafeAreaBean data) {
|
||||||
|
mBgSegGreenListener.onSafeAreaSelected(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUseTemplate() {
|
||||||
|
return getCurrentBgSegGreenModel().isUseTemplate() == 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取色锚点颜色变更
|
||||||
|
*
|
||||||
|
* @param array DoubleArray
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onColorRGBChanged(double[] array) {
|
||||||
|
mBgSegGreen.setColorRGB(new FUColorRGBData(array[0], array[1], array[2]));
|
||||||
|
mBgSegGreen.setEnable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绿幕开关
|
||||||
|
*
|
||||||
|
* @param enable Boolean
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onBgSegGreenEnableChanged(boolean enable) {
|
||||||
|
mBgSegGreen.setEnable(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据名称标识获取对应的值
|
||||||
|
*
|
||||||
|
* @param key String 标识
|
||||||
|
* @return Double 值
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public double getParamIntensity(@NonNull String key) {
|
||||||
|
if (bgSegGreenGetMapping.containsKey(key)) {
|
||||||
|
return bgSegGreenGetMapping.get(key).getValue();
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据名称标识更新对应的值
|
||||||
|
*
|
||||||
|
* @param key String 标识
|
||||||
|
* @return Double 值
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateParamIntensity(@NonNull String key, double value) {
|
||||||
|
if (bgSegGreenSetMapping.containsKey(key)) {
|
||||||
|
Objects.requireNonNull(bgSegGreenSetMapping.get(key)).setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用取色器功能状态变更
|
||||||
|
*
|
||||||
|
* @param selected
|
||||||
|
* @param color
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onColorPickerStateChanged(boolean selected, int color) {
|
||||||
|
mBgSegGreenListener.onColorPickerStateChanged(selected, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
//region 业务映射
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数设置
|
||||||
|
*/
|
||||||
|
interface BgSegGreenSetParam {
|
||||||
|
void setValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型参数获取
|
||||||
|
*/
|
||||||
|
interface BgSegGreenGetParam {
|
||||||
|
double getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前绿幕对象
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private BgSegGreen getCurrentBgSegGreenModel() {
|
||||||
|
return mBgSegGreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 模型映射 */
|
||||||
|
private final HashMap<String, BgSegGreenSetParam> bgSegGreenSetMapping = new HashMap<String, BgSegGreenSetParam>() {
|
||||||
|
{
|
||||||
|
put(BgSegGreenParam.SIMILARITY, value -> getCurrentBgSegGreenModel().setSimilarity(value));
|
||||||
|
put(BgSegGreenParam.SMOOTHNESS, value -> getCurrentBgSegGreenModel().setSmoothness(value));
|
||||||
|
put(BgSegGreenParam.TRANSPARENCY, value -> getCurrentBgSegGreenModel().setTransparency(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*模型映射获取模型值*/
|
||||||
|
private final HashMap<String, BgSegGreenGetParam> bgSegGreenGetMapping = new HashMap<String, BgSegGreenGetParam>() {
|
||||||
|
{
|
||||||
|
put(BgSegGreenParam.SIMILARITY, () -> getCurrentBgSegGreenModel().getSimilarity());
|
||||||
|
put(BgSegGreenParam.SMOOTHNESS, () -> getCurrentBgSegGreenModel().getSmoothness());
|
||||||
|
put(BgSegGreenParam.TRANSPARENCY, () -> getCurrentBgSegGreenModel().getTransparency());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//endregion 业务映射
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FURenderKit加载当前特效
|
||||||
|
*/
|
||||||
|
public void bindCurrentRenderer() {
|
||||||
|
FUAIKit.getInstance().setMaxFaces(1);
|
||||||
|
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
mFURenderKit.setBgSegGreen(mBgSegGreen);
|
||||||
|
mBgSegGreenListener.onBackgroundSelected(mBgSegGreenBackgroundBeans.get(mCurrentBackgroundIndex));
|
||||||
|
mBgSegGreenListener.onSafeAreaSelected(mBgSegGreenSafeAreaBeans.get(mCurrentSafeAreaIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,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;
|
||||||
|
}
|
@ -4,13 +4,20 @@ package com.yunbao.faceunity.data;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.faceunity.core.controller.facebeauty.FaceBeautyParam;
|
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.faceunity.FURenderKit;
|
||||||
import com.faceunity.core.model.facebeauty.FaceBeauty;
|
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.FaceBeautyBean;
|
||||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||||
|
import com.yunbao.faceunity.entity.FaceBeautyStyleBean;
|
||||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||||
import com.yunbao.faceunity.infe.AbstractFaceBeautyDataFactory;
|
import com.yunbao.faceunity.infe.AbstractFaceBeautyDataFactory;
|
||||||
import com.yunbao.faceunity.repo.FaceBeautySource;
|
import com.yunbao.faceunity.repo.FaceBeautySource;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -22,6 +29,21 @@ import java.util.HashMap;
|
|||||||
*/
|
*/
|
||||||
public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
||||||
|
|
||||||
|
public interface FaceBeautyListener {
|
||||||
|
/**
|
||||||
|
* 风格切换
|
||||||
|
*
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
|
void onFilterSelected(int res);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 美颜开关
|
||||||
|
*
|
||||||
|
* @param enable
|
||||||
|
*/
|
||||||
|
void onFaceBeautyEnable(boolean enable);
|
||||||
|
}
|
||||||
|
|
||||||
interface FaceBeautySetParamInterface {
|
interface FaceBeautySetParamInterface {
|
||||||
/**
|
/**
|
||||||
@ -44,11 +66,26 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
/*渲染控制器*/
|
/*渲染控制器*/
|
||||||
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
private FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||||
|
|
||||||
/*当前生效美颜数据模型*/
|
/*推荐风格标识*/
|
||||||
public FaceBeauty defaultFaceBeauty = FaceBeautySource.getDefaultFaceBeauty();
|
private static int currentStyleIndex = -1;
|
||||||
|
|
||||||
|
/*美颜缓存数据模型 用于普通美颜*/
|
||||||
|
public static final FaceBeauty defaultFaceBeauty = FaceBeautySource.getDefaultFaceBeauty();
|
||||||
|
|
||||||
|
/*当前生效美颜数据模型 普通 or 风格的*/
|
||||||
|
public static FaceBeauty faceBeauty = defaultFaceBeauty;
|
||||||
|
|
||||||
|
|
||||||
/*默认滤镜选中下标*/
|
/*默认滤镜选中下标*/
|
||||||
private int currentFilterIndex = 0;
|
private int currentFilterIndex = 0;
|
||||||
|
/*业务回调*/
|
||||||
|
private final FaceBeautyListener mFaceBeautyListener;
|
||||||
|
|
||||||
|
|
||||||
|
public FaceBeautyDataFactory(FaceBeautyListener listener) {
|
||||||
|
mFaceBeautyListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取美肤参数列表
|
* 获取美肤参数列表
|
||||||
@ -72,6 +109,17 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
return FaceBeautySource.buildShapeParams();
|
return FaceBeautySource.buildShapeParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取美型参数列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ArrayList<FaceBeautyBean> getShapeBeautySubItem() {
|
||||||
|
return FaceBeautySource.buildFaceShapeSubItemParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取美肤、美型扩展参数
|
* 获取美肤、美型扩展参数
|
||||||
@ -99,7 +147,6 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
filterBeans.get(i).setIntensity(defaultFaceBeauty.getFilterIntensity());
|
filterBeans.get(i).setIntensity(defaultFaceBeauty.getFilterIntensity());
|
||||||
currentFilterIndex = i;
|
currentFilterIndex = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return filterBeans;
|
return filterBeans;
|
||||||
}
|
}
|
||||||
@ -124,6 +171,46 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
this.currentFilterIndex = 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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 美颜开关设置
|
* 美颜开关设置
|
||||||
@ -132,9 +219,7 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void enableFaceBeauty(boolean enable) {
|
public void enableFaceBeauty(boolean enable) {
|
||||||
if (mFURenderKit.getFaceBeauty() != null) {
|
mFaceBeautyListener.onFaceBeautyEnable(enable);
|
||||||
mFURenderKit.getFaceBeauty().setEnable(enable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,6 +249,69 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将所有效果制空
|
||||||
|
*/
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切换滤镜
|
* 切换滤镜
|
||||||
*
|
*
|
||||||
@ -175,6 +323,7 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
public void onFilterSelected(@NonNull String name, double intensity, int resID) {
|
public void onFilterSelected(@NonNull String name, double intensity, int resID) {
|
||||||
defaultFaceBeauty.setFilterName(name);
|
defaultFaceBeauty.setFilterName(name);
|
||||||
defaultFaceBeauty.setFilterIntensity(intensity);
|
defaultFaceBeauty.setFilterIntensity(intensity);
|
||||||
|
mFaceBeautyListener.onFilterSelected(resID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,6 +336,23 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
defaultFaceBeauty.setFilterIntensity(intensity);
|
defaultFaceBeauty.setFilterIntensity(intensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置推荐风格
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
@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>() {{
|
private final HashMap<String, FaceBeautySetParamInterface> faceBeautySetMapping = new HashMap<String, FaceBeautySetParamInterface>() {{
|
||||||
@ -270,6 +436,22 @@ public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory {
|
|||||||
* FURenderKit加载当前特效
|
* FURenderKit加载当前特效
|
||||||
*/
|
*/
|
||||||
public void bindCurrentRenderer() {
|
public void bindCurrentRenderer() {
|
||||||
mFURenderKit.setFaceBeauty(defaultFaceBeauty);
|
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<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.yunbao.faceunity.data;
|
|||||||
|
|
||||||
import com.faceunity.core.enumeration.FUAIProcessorEnum;
|
import com.faceunity.core.enumeration.FUAIProcessorEnum;
|
||||||
import com.faceunity.core.faceunity.FURenderKit;
|
import com.faceunity.core.faceunity.FURenderKit;
|
||||||
|
import com.yunbao.faceunity.entity.PropBean;
|
||||||
import com.yunbao.faceunity.utils.FURenderer;
|
import com.yunbao.faceunity.utils.FURenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,10 +51,25 @@ public class FaceUnityDataFactory {
|
|||||||
|
|
||||||
public FaceUnityDataFactory(int index) {
|
public FaceUnityDataFactory(int index) {
|
||||||
currentFunctionIndex = index;
|
currentFunctionIndex = index;
|
||||||
mFaceBeautyDataFactory = new FaceBeautyDataFactory();
|
mFaceBeautyDataFactory = new FaceBeautyDataFactory(new FaceBeautyDataFactory.FaceBeautyListener() {
|
||||||
|
@Override
|
||||||
|
public void onFilterSelected(int res) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFaceBeautyEnable(boolean enable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
mBodyBeautyDataFactory = new BodyBeautyDataFactory();
|
mBodyBeautyDataFactory = new BodyBeautyDataFactory();
|
||||||
mMakeupDataFactory = new MakeupDataFactory(0);
|
mMakeupDataFactory = new MakeupDataFactory(0);
|
||||||
mPropDataFactory = new PropDataFactory(0);
|
mPropDataFactory = new PropDataFactory(new PropDataFactory.PropListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(PropBean bean) {
|
||||||
|
|
||||||
|
}
|
||||||
|
},0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,38 +1,59 @@
|
|||||||
package com.yunbao.faceunity.data;
|
package com.yunbao.faceunity.data;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.faceunity.core.entity.FUBundleData;
|
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.faceunity.FURenderKit;
|
||||||
import com.faceunity.core.model.prop.Prop;
|
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.faceunity.core.model.prop.sticker.Sticker;
|
||||||
|
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||||
import com.yunbao.faceunity.entity.PropBean;
|
import com.yunbao.faceunity.entity.PropBean;
|
||||||
import com.yunbao.faceunity.infe.AbstractPropDataFactory;
|
import com.yunbao.faceunity.infe.AbstractPropDataFactory;
|
||||||
import com.yunbao.faceunity.repo.PropSource;
|
import com.yunbao.faceunity.repo.PropSource;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DESC:道具业务工厂
|
* DESC:道具业务工厂:道具贴图、AR面具、搞笑大头、表情识别、哈哈镜、手势识别
|
||||||
* Created on 2021/3/2
|
* Created on 2021/3/2
|
||||||
*/
|
*/
|
||||||
public class PropDataFactory extends AbstractPropDataFactory {
|
public class PropDataFactory extends AbstractPropDataFactory {
|
||||||
|
|
||||||
|
public interface PropListener {
|
||||||
|
|
||||||
|
void onItemSelected(PropBean bean);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*渲染控制器*/
|
/*渲染控制器*/
|
||||||
private final FURenderKit mFURenderKit = FURenderKit.getInstance();
|
private final FURenderKit mFURenderKit = FURenderKit.getInstance();
|
||||||
/*道具列表*/
|
/*道具列表*/
|
||||||
private final ArrayList<PropBean> propBeans;
|
private final ArrayList<PropBean> propBeans;
|
||||||
|
|
||||||
/*默认选中下标*/
|
/*默认选中下标*/
|
||||||
private int currentPropIndex;
|
private int currentPropIndex;
|
||||||
/*当前道具*/
|
/*当前道具*/
|
||||||
public Prop currentProp;
|
public Prop currentProp;
|
||||||
|
/*回调接口*/
|
||||||
|
private final PropListener mPropListener;
|
||||||
|
/*道具类型*/
|
||||||
|
private final int propType;
|
||||||
|
|
||||||
public PropDataFactory(int index) {
|
|
||||||
|
public PropDataFactory(PropListener listener, int type, int index) {
|
||||||
|
mPropListener = listener;
|
||||||
|
propType = type;
|
||||||
currentPropIndex = index;
|
currentPropIndex = index;
|
||||||
propBeans = PropSource.buildPropBeans();
|
propBeans = PropSource.buildPropBeans(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -67,20 +88,47 @@ public class PropDataFactory extends AbstractPropDataFactory {
|
|||||||
return propBeans;
|
return propBeans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(PropBean bean) {
|
||||||
|
onPropSelected(bean);
|
||||||
|
mPropListener.onItemSelected(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 道具选中
|
* 其他道具
|
||||||
*
|
*
|
||||||
* @param bean
|
* @param bean
|
||||||
*/
|
*/
|
||||||
@Override
|
private void onPropSelected(PropBean bean) {
|
||||||
public void onItemSelected(PropBean bean) {
|
|
||||||
String path = bean.getPath();
|
String path = bean.getPath();
|
||||||
if (path == null || path.trim().length() == 0) {
|
if (path == null || path.trim().length() == 0) {
|
||||||
mFURenderKit.getPropContainer().removeAllProp();
|
mFURenderKit.getPropContainer().removeAllProp();
|
||||||
currentProp = null;
|
currentProp = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Prop prop = new Sticker(new FUBundleData(path));
|
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);
|
mFURenderKit.getPropContainer().replaceProp(currentProp, prop);
|
||||||
currentProp = prop;
|
currentProp = prop;
|
||||||
}
|
}
|
||||||
@ -90,7 +138,25 @@ public class PropDataFactory extends AbstractPropDataFactory {
|
|||||||
* FURenderKit加载当前特效
|
* FURenderKit加载当前特效
|
||||||
*/
|
*/
|
||||||
public void bindCurrentRenderer() {
|
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);
|
PropBean propBean = propBeans.get(currentPropIndex);
|
||||||
onItemSelected(propBean);
|
onItemSelected(propBean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束需要释放AI驱动
|
||||||
|
*/
|
||||||
|
public void releaseAIProcessor() {
|
||||||
|
if (propType == FunctionEnum.GESTURE_RECOGNITION) {
|
||||||
|
FUAIKit.getInstance().releaseAIProcessor(FUAITypeEnum.FUAITYPE_HANDGESTURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.yunbao.faceunity.entity;
|
||||||
|
|
||||||
|
public class AnimationFilterBean {
|
||||||
|
private int style=0;
|
||||||
|
private int iconId;
|
||||||
|
|
||||||
|
public AnimationFilterBean(int style, int iconId) {
|
||||||
|
this.style = style;
|
||||||
|
this.iconId = iconId;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 道具
|
||||||
|
* @property iconId Int 图标
|
||||||
|
* @property path String? Animoji 道具路径
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
data class AnimojiBean(val iconId: Int, val path: String?)
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:
|
||||||
|
* Created on 2020/12/4
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
data class AvatarBean(val iconId: Int, val des: String)
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:
|
||||||
|
* Created on 2020/12/4
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
data class BgSegGreenBackgroundBean(val desRes: Int, val iconRes: Int, val filePath: String? = null)
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:
|
||||||
|
* Created on 2020/12/4
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
data class BgSegGreenBean(val key: String, val desRes: Int, val closeRes: Int, val openRes: Int, val type: ButtonType) {
|
||||||
|
enum class ButtonType{
|
||||||
|
NORMAL1_BUTTON,//普通一号按钮
|
||||||
|
NORMAL2_BUTTON,//普通二号按钮
|
||||||
|
BACK_BUTTON,//返回按钮
|
||||||
|
SWITCH_BUTTON//切换按钮,切换整个按钮功能
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:
|
||||||
|
* Created on 2020/12/4
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
data class BgSegGreenSafeAreaBean(val iconRes: Int, val type: ButtonType, val filePath: String? = null,val isAssetFile: Boolean = true) {
|
||||||
|
|
||||||
|
constructor(iconRes: Int, type: ButtonType) : this(
|
||||||
|
iconRes,
|
||||||
|
type,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
constructor(iconRes: Int, type: ButtonType, filePath :String) : this(
|
||||||
|
iconRes,
|
||||||
|
type,
|
||||||
|
filePath,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
enum class ButtonType{
|
||||||
|
NORMAL1_BUTTON,//普通一号按钮,普通安全区域按钮
|
||||||
|
NORMAL2_BUTTON,//普通二号按钮,用于自定义按钮
|
||||||
|
BACK_BUTTON,//返回按钮
|
||||||
|
NONE_BUTTON,//不选择按钮
|
||||||
|
}
|
||||||
|
}
|
@ -1,70 +0,0 @@
|
|||||||
package com.yunbao.faceunity.entity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DESC:美颜
|
|
||||||
* Created on 2021/4/26
|
|
||||||
*/
|
|
||||||
public class FaceBeautyBean {
|
|
||||||
|
|
||||||
private String key;//名称标识
|
|
||||||
private int desRes;//描述
|
|
||||||
private int closeRes;//图片
|
|
||||||
private int openRes;//图片
|
|
||||||
private int toastDesRes;
|
|
||||||
private boolean canUseFunction;
|
|
||||||
private ButtonType buttonType=ButtonType.NORMAL_BUTTON;
|
|
||||||
|
|
||||||
public FaceBeautyBean(String key, int desRes, int closeRes, int openRes) {
|
|
||||||
this.key = key;
|
|
||||||
this.desRes = desRes;
|
|
||||||
this.closeRes = closeRes;
|
|
||||||
this.openRes = openRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FaceBeautyBean(String key, int desRes, int closeRes, int openRes, int toastDesRes, boolean canUseFunction) {
|
|
||||||
this.key = key;
|
|
||||||
this.desRes = desRes;
|
|
||||||
this.closeRes = closeRes;
|
|
||||||
this.openRes = openRes;
|
|
||||||
this.toastDesRes = toastDesRes;
|
|
||||||
this.canUseFunction = canUseFunction;
|
|
||||||
this.buttonType = buttonType;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
enum ButtonType{
|
|
||||||
NORMAL_BUTTON,
|
|
||||||
BACK_BUTTON,
|
|
||||||
SUB_ITEM_BUTTON
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @property key String 名称标识
|
||||||
|
* @property desRes Int 描述
|
||||||
|
* @property closeRes Int 图片
|
||||||
|
* @property openRes Int 图片
|
||||||
|
* @property buttonType 按钮类型
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
data class FaceBeautyBean(
|
||||||
|
val key: String,
|
||||||
|
val desRes: Int,
|
||||||
|
val closeRes: Int,
|
||||||
|
val openRes: Int,
|
||||||
|
val toastDesRes: Int,
|
||||||
|
val canUseFunction:Boolean = true,
|
||||||
|
val buttonType: ButtonType = ButtonType.NORMAL_BUTTON//定义一项按钮功能 普通按钮 返回按钮 子项按钮
|
||||||
|
) {
|
||||||
|
constructor(key: String, desRes: Int, closeRes: Int, openRes: Int) : this(
|
||||||
|
key,
|
||||||
|
desRes,
|
||||||
|
closeRes,
|
||||||
|
openRes,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
ButtonType.NORMAL_BUTTON
|
||||||
|
)
|
||||||
|
|
||||||
|
constructor(key: String, desRes: Int, closeRes: Int, openRes: Int,toastDesRes: Int,canUseFunction: Boolean) : this(
|
||||||
|
key,
|
||||||
|
desRes,
|
||||||
|
closeRes,
|
||||||
|
openRes,
|
||||||
|
toastDesRes,
|
||||||
|
canUseFunction,
|
||||||
|
ButtonType.NORMAL_BUTTON
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class ButtonType{
|
||||||
|
NORMAL_BUTTON,
|
||||||
|
BACK_BUTTON,
|
||||||
|
SUB_ITEM_BUTTON
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 滤镜
|
||||||
|
* @property key String 名称标识
|
||||||
|
* @property imageRes Int 图片
|
||||||
|
* @property desRes Int 描述
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
data class FaceBeautyStyleBean @JvmOverloads constructor(val key: String, val imageRes: Int, val desRes: Int)
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.yunbao.faceunity.entity;
|
||||||
|
|
||||||
|
public class FunctionEnum {
|
||||||
|
public final static int FACE_BEAUTY = 1;
|
||||||
|
public final static int MAKE_UP = 2;
|
||||||
|
public final static int STICKER = 3;
|
||||||
|
public final static int ANIMOJI = 4;
|
||||||
|
public final static int HAIR_BEAUTY = 5;
|
||||||
|
public final static int LIGHT_MAKEUP = 6;
|
||||||
|
public final static int AR_MASK = 7;
|
||||||
|
public final static int BIG_HEAD = 8;
|
||||||
|
public final static int POSTER_CHANGE = 9;
|
||||||
|
public final static int EXPRESSION_RECOGNITION = 10;
|
||||||
|
public final static int MUSIC_FILTER = 11;
|
||||||
|
public final static int FACE_WARP = 12;
|
||||||
|
public final static int BODY_BEAUTY = 13;
|
||||||
|
public final static int AVATAR = 14;
|
||||||
|
public final static int ACTION_RECOGNITION = 15;
|
||||||
|
public final static int PORTRAIT_SEGMENT = 16;
|
||||||
|
public final static int GESTURE_RECOGNITION = 17;
|
||||||
|
public final static int BG_SEG_GREEN = 18;
|
||||||
|
public final static int HUMAN_OUTLINE = 19;
|
||||||
|
public final static int BG_SEG_CUSTOM = 20;
|
||||||
|
public final static int FINE_STICKER = 21;
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.yunbao.faceunity.entity;
|
||||||
|
|
||||||
|
public class LightMakeupBean {
|
||||||
|
int nameRes;
|
||||||
|
int iconRes;
|
||||||
|
String key;
|
||||||
|
double intensity;
|
||||||
|
String filterName;
|
||||||
|
double filterIntensity;
|
||||||
|
|
||||||
|
public LightMakeupBean(int nameRes, int iconRes, String key, double intensity, String filterName, double filterIntensity) {
|
||||||
|
this.nameRes = nameRes;
|
||||||
|
this.iconRes = iconRes;
|
||||||
|
this.key = key;
|
||||||
|
this.intensity = intensity;
|
||||||
|
this.filterName = filterName;
|
||||||
|
this.filterIntensity = filterIntensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNameRes() {
|
||||||
|
return nameRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNameRes(int nameRes) {
|
||||||
|
this.nameRes = nameRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconRes() {
|
||||||
|
return iconRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIconRes(int iconRes) {
|
||||||
|
this.iconRes = iconRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getIntensity() {
|
||||||
|
return intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntensity(double intensity) {
|
||||||
|
this.intensity = intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilterName() {
|
||||||
|
return filterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilterName(String filterName) {
|
||||||
|
this.filterName = filterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getFilterIntensity() {
|
||||||
|
return filterIntensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilterIntensity(double filterIntensity) {
|
||||||
|
this.filterIntensity = filterIntensity;
|
||||||
|
}
|
||||||
|
}
|
@ -1,51 +0,0 @@
|
|||||||
package com.yunbao.faceunity.entity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模型单项补充模型
|
|
||||||
*/
|
|
||||||
public class ModelAttributeData {
|
|
||||||
private double defaultV = 0.0;//默认值
|
|
||||||
private double standV = 0.0;//无变化时候的基准值
|
|
||||||
private double minRange = 0.0;//范围最小值
|
|
||||||
private double maxRange = 1.0;//范围最大值
|
|
||||||
|
|
||||||
public ModelAttributeData(double defaultV, double standV, double minRange, double maxRange) {
|
|
||||||
this.defaultV = defaultV;
|
|
||||||
this.standV = standV;
|
|
||||||
this.minRange = minRange;
|
|
||||||
this.maxRange = maxRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public double getDefaultV() {
|
|
||||||
return defaultV;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultV(double defaultV) {
|
|
||||||
this.defaultV = defaultV;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getStandV() {
|
|
||||||
return standV;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStandV(double standV) {
|
|
||||||
this.standV = standV;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getMinRange() {
|
|
||||||
return minRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinRange(double minRange) {
|
|
||||||
this.minRange = minRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getMaxRange() {
|
|
||||||
return maxRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMaxRange(double maxRange) {
|
|
||||||
this.maxRange = maxRange;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
@ -1,32 +0,0 @@
|
|||||||
package com.yunbao.faceunity.entity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DESC:道具
|
|
||||||
* Created on 2021/4/26
|
|
||||||
*/
|
|
||||||
public class PropBean {
|
|
||||||
private int iconId;
|
|
||||||
private String path;
|
|
||||||
|
|
||||||
|
|
||||||
public PropBean(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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 道具
|
||||||
|
* @property iconId Int 图标
|
||||||
|
* @property path String 道具路径
|
||||||
|
* @property descId Int 道具提示
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
data class PropBean @JvmOverloads constructor(
|
||||||
|
val iconId: Int,
|
||||||
|
val path: String?,
|
||||||
|
val descId: Int = 0
|
||||||
|
)
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.yunbao.faceunity.entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 道具
|
||||||
|
* @property iconId Int 图标
|
||||||
|
* @property path String 道具路径
|
||||||
|
* @property descId Int 道具提示
|
||||||
|
* @property descId Int 类型 -2 为添加事件 -1为空 其他多道具类型
|
||||||
|
* @property iconPath 图标路径
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
data class PropCustomBean @JvmOverloads constructor(
|
||||||
|
val iconId: Int,
|
||||||
|
val path: String?,
|
||||||
|
val type: Int = -1,
|
||||||
|
val descId: Int = 0,
|
||||||
|
val iconPath: String? = null
|
||||||
|
)
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.yunbao.faceunity.infe
|
||||||
|
|
||||||
|
import com.yunbao.faceunity.entity.AnimationFilterBean
|
||||||
|
import com.yunbao.faceunity.entity.AnimojiBean
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:
|
||||||
|
* Created on 2020/12/24
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract class AbstractAnimojiDataFactory {
|
||||||
|
|
||||||
|
/* 当前选中动漫贴图下标 */
|
||||||
|
abstract var currentAnimojiIndex: Int
|
||||||
|
|
||||||
|
/* 动漫贴图队列 */
|
||||||
|
abstract val animojis: ArrayList<AnimojiBean>
|
||||||
|
|
||||||
|
/* 当前选中滤镜下标 */
|
||||||
|
abstract var currentFilterIndex: Int
|
||||||
|
|
||||||
|
/* 滤镜队列 */
|
||||||
|
abstract val filters: ArrayList<AnimationFilterBean>
|
||||||
|
|
||||||
|
abstract fun onAnimojiSelected(data: AnimojiBean)
|
||||||
|
|
||||||
|
abstract fun onFilterSelected(data: AnimationFilterBean)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.yunbao.faceunity.infe
|
||||||
|
|
||||||
|
import com.yunbao.faceunity.entity.AvatarBean
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:
|
||||||
|
* Created on 2021/1/6
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract class AbstractAvatarDataFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人物队列
|
||||||
|
*/
|
||||||
|
abstract val members: ArrayList<AvatarBean>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认选中人物下标
|
||||||
|
*/
|
||||||
|
abstract var currentMemberIndex: Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true 全身、 false 半身 驱动切换
|
||||||
|
*/
|
||||||
|
abstract var isHumanTrackSceneFull: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前人物选中
|
||||||
|
* @param bean AvatarBean
|
||||||
|
*/
|
||||||
|
abstract fun onMemberSelected(bean:AvatarBean)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package com.yunbao.faceunity.infe
|
||||||
|
|
||||||
|
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenBean
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean
|
||||||
|
import com.yunbao.faceunity.entity.ModelAttributeData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:
|
||||||
|
* Created on 2020/12/29
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract class AbstractBgSegGreenDataFactory {
|
||||||
|
|
||||||
|
/* 绿幕抠像项目数据扩展模型 */
|
||||||
|
abstract val modelAttributeRange: HashMap<String, ModelAttributeData>
|
||||||
|
|
||||||
|
/* 绿幕抠像功能列表 */
|
||||||
|
abstract val bgSegGreenActions: ArrayList<BgSegGreenBean>
|
||||||
|
|
||||||
|
/* 绿幕抠图安全区域功能列表*/
|
||||||
|
abstract val bgSegGreenSafeAreas: ArrayList<BgSegGreenSafeAreaBean>
|
||||||
|
|
||||||
|
/* 安全区域下标 */
|
||||||
|
abstract var bgSafeAreaIndex: Int
|
||||||
|
|
||||||
|
/* 刷新安全区域UI */
|
||||||
|
abstract fun updateSafeAreaBeansAndIndex() :Boolean
|
||||||
|
|
||||||
|
/* 绿幕抠像背景列表 */
|
||||||
|
abstract val bgSegGreenBackgrounds: ArrayList<BgSegGreenBackgroundBean>
|
||||||
|
|
||||||
|
/* 绿幕抠像当前背景下标 */
|
||||||
|
abstract var backgroundIndex: Int
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 背景图片变更
|
||||||
|
* @param data BgSegGreenBackgroundBean
|
||||||
|
*/
|
||||||
|
abstract fun onBackgroundSelected(data: BgSegGreenBackgroundBean)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义安全区域
|
||||||
|
*/
|
||||||
|
abstract fun onSafeAreaAdd()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全区域变更
|
||||||
|
* @param data BgSegGreenSafeAreaBean
|
||||||
|
*/
|
||||||
|
abstract fun onSafeAreaSelected(data: BgSegGreenSafeAreaBean?)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否开启安全区域总开关
|
||||||
|
*/
|
||||||
|
abstract fun isUseTemplate():Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取色锚点颜色变更
|
||||||
|
* @param array DoubleArray
|
||||||
|
*/
|
||||||
|
abstract fun onColorRGBChanged(array: DoubleArray)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绿幕开关
|
||||||
|
* @param enable Boolean
|
||||||
|
*/
|
||||||
|
abstract fun onBgSegGreenEnableChanged(enable: Boolean)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据名称标识获取对应的值
|
||||||
|
* @param key String 标识
|
||||||
|
* @return Double 值
|
||||||
|
*/
|
||||||
|
abstract fun getParamIntensity(key: String): Double
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据名称标识更新对应的值
|
||||||
|
* @param key String 标识
|
||||||
|
* @return Double 值
|
||||||
|
*/
|
||||||
|
abstract fun updateParamIntensity(key: String, value: Double)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否调用取色器功能
|
||||||
|
*
|
||||||
|
* @param selected
|
||||||
|
* @param color
|
||||||
|
*/
|
||||||
|
abstract fun onColorPickerStateChanged(selected: Boolean, color: Int)
|
||||||
|
|
||||||
|
}
|
@ -1,103 +0,0 @@
|
|||||||
package com.yunbao.faceunity.infe;
|
|
||||||
|
|
||||||
|
|
||||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
|
||||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
|
||||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DESC:数据构造工厂抽象类
|
|
||||||
* Created on 2021/4/26
|
|
||||||
*/
|
|
||||||
public abstract class AbstractFaceBeautyDataFactory {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 美肤底部菜单数据
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract ArrayList<FaceBeautyBean> getSkinBeauty();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 美型底部菜单数据
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract ArrayList<FaceBeautyBean> getShapeBeauty();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 滤镜底部菜单数据
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract ArrayList<FaceBeautyFilterBean> getBeautyFilters();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前滤镜下标
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract int getCurrentFilterIndex();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置当前滤镜下标
|
|
||||||
*
|
|
||||||
* @param currentFilterIndex
|
|
||||||
*/
|
|
||||||
public abstract void setCurrentFilterIndex(int currentFilterIndex);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 美颜项目数据扩展模型
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract HashMap<String, ModelAttributeData> getModelAttributeRange();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换滤镜
|
|
||||||
*
|
|
||||||
* @param name String
|
|
||||||
* @param intensity Double
|
|
||||||
*/
|
|
||||||
public abstract void onFilterSelected(String name, double intensity, int resDes);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更改滤镜强度
|
|
||||||
*
|
|
||||||
* @param intensity Double
|
|
||||||
*/
|
|
||||||
public abstract void updateFilterIntensity(double intensity);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 美颜开关
|
|
||||||
*
|
|
||||||
* @param enable Boolean
|
|
||||||
*/
|
|
||||||
public abstract void enableFaceBeauty(boolean enable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取单项强度
|
|
||||||
*
|
|
||||||
* @param key String
|
|
||||||
* @return Double
|
|
||||||
*/
|
|
||||||
public abstract double getParamIntensity(String key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置单项强度
|
|
||||||
*
|
|
||||||
* @param key String
|
|
||||||
* @param value Double
|
|
||||||
*/
|
|
||||||
public abstract void updateParamIntensity(String key, double value);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.yunbao.faceunity.infe
|
||||||
|
|
||||||
|
|
||||||
|
import com.yunbao.faceunity.entity.FaceBeautyBean
|
||||||
|
import com.yunbao.faceunity.entity.FaceBeautyFilterBean
|
||||||
|
import com.yunbao.faceunity.entity.FaceBeautyStyleBean
|
||||||
|
import com.yunbao.faceunity.entity.ModelAttributeData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:数据构造工厂接口类
|
||||||
|
* Created on 2020/12/23
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract class AbstractFaceBeautyDataFactory {
|
||||||
|
|
||||||
|
/*美肤底部菜单数据*/
|
||||||
|
abstract val skinBeauty: ArrayList<FaceBeautyBean>
|
||||||
|
|
||||||
|
/*美型底部菜单数据*/
|
||||||
|
abstract val shapeBeauty: ArrayList<FaceBeautyBean>
|
||||||
|
|
||||||
|
/*美型脸型子项数据*/
|
||||||
|
abstract val shapeBeautySubItem: ArrayList<FaceBeautyBean>
|
||||||
|
|
||||||
|
/* 滤镜底部菜单数据*/
|
||||||
|
abstract val beautyFilters: ArrayList<FaceBeautyFilterBean>
|
||||||
|
|
||||||
|
/* 风格底部菜单数据*/
|
||||||
|
abstract val beautyStyles: ArrayList<FaceBeautyStyleBean>
|
||||||
|
|
||||||
|
/*系统推荐配置滤镜对应下标*/
|
||||||
|
abstract var currentFilterIndex: Int
|
||||||
|
|
||||||
|
/* 美颜项目数据扩展模型 */
|
||||||
|
abstract val modelAttributeRange: HashMap<String, ModelAttributeData>
|
||||||
|
|
||||||
|
/*系统风格对应下标*/
|
||||||
|
abstract var currentStyleIndex: Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换滤镜
|
||||||
|
* @param name String
|
||||||
|
* @param intensity Double
|
||||||
|
*/
|
||||||
|
abstract fun onFilterSelected(name: String, intensity: Double, resDes: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换风格
|
||||||
|
* @param name String
|
||||||
|
*/
|
||||||
|
abstract fun onStyleSelected(name: String?)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更改滤镜强度
|
||||||
|
* @param intensity Double
|
||||||
|
*/
|
||||||
|
abstract fun updateFilterIntensity(intensity: Double)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 美颜开关
|
||||||
|
* @param enable Boolean
|
||||||
|
*/
|
||||||
|
abstract fun enableFaceBeauty(enable: Boolean)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单项强度
|
||||||
|
* @param key String
|
||||||
|
* @return Double
|
||||||
|
*/
|
||||||
|
abstract fun getParamIntensity(key: String): Double
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取one hot的脸型
|
||||||
|
*/
|
||||||
|
abstract fun getCurrentOneHotFaceShape(): String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前one hot的脸型
|
||||||
|
*/
|
||||||
|
abstract fun setCurrentOneHotFaceShape(faceShape:String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前脸型的UI值
|
||||||
|
*/
|
||||||
|
abstract fun setCurrentFaceShapeUIValue(hashMap:HashMap<String,Double>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前脸型的UI值
|
||||||
|
*/
|
||||||
|
abstract fun getCurrentFaceShapeUIValue() :HashMap<String,Double>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置单项强度
|
||||||
|
* @param key String
|
||||||
|
* @param value Double
|
||||||
|
*/
|
||||||
|
abstract fun updateParamIntensity(key: String, value: Double)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将所有效果置空 -> 变成标准值
|
||||||
|
*/
|
||||||
|
abstract fun resetParamIntensity()
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.yunbao.faceunity.infe;
|
||||||
|
|
||||||
|
import com.yunbao.faceunity.entity.LightMakeupBean;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public abstract class AbstractLightMakeupDataFactory {
|
||||||
|
private int currentLightMakeupIndex;
|
||||||
|
private ArrayList<LightMakeupBean> lightMakeUpBeans;
|
||||||
|
public abstract void onLightMakeupSelected(LightMakeupBean data);
|
||||||
|
public abstract void onLightMakeupIntensityChanged(double intensity);
|
||||||
|
|
||||||
|
public int getCurrentLightMakeupIndex() {
|
||||||
|
return currentLightMakeupIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentLightMakeupIndex(int currentLightMakeupIndex) {
|
||||||
|
this.currentLightMakeupIndex = currentLightMakeupIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<LightMakeupBean> getLightMakeUpBeans() {
|
||||||
|
return lightMakeUpBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLightMakeUpBeans(ArrayList<LightMakeupBean> lightMakeUpBeans) {
|
||||||
|
this.lightMakeUpBeans = lightMakeUpBeans;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,42 +0,0 @@
|
|||||||
package com.yunbao.faceunity.infe;
|
|
||||||
|
|
||||||
import com.yunbao.faceunity.entity.PropBean;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DESC:数据构造工厂抽象类
|
|
||||||
* Created on 2021/4/26
|
|
||||||
*/
|
|
||||||
public abstract class AbstractPropDataFactory {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前选中下标
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract int getCurrentPropIndex();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置当前选中下标
|
|
||||||
*
|
|
||||||
* @param currentPropIndex
|
|
||||||
*/
|
|
||||||
public abstract void setCurrentPropIndex(int currentPropIndex);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取道具队列
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public abstract ArrayList<PropBean> getPropBeans();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 道具选中
|
|
||||||
*
|
|
||||||
* @param bean StickerBean
|
|
||||||
*/
|
|
||||||
public abstract void onItemSelected(PropBean bean);
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.yunbao.faceunity.infe
|
||||||
|
|
||||||
|
import com.yunbao.faceunity.entity.PropBean
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* DESC:贴图道具
|
||||||
|
* Created on 2020/12/23
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract class AbstractPropDataFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认选中道具下标
|
||||||
|
*/
|
||||||
|
abstract var currentPropIndex: Int
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 道具队列
|
||||||
|
*/
|
||||||
|
abstract val propBeans: ArrayList<PropBean>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 道具选中
|
||||||
|
* @param bean StickerBean
|
||||||
|
*/
|
||||||
|
abstract fun onItemSelected(bean: PropBean)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.yunbao.faceunity.repo;
|
||||||
|
|
||||||
|
import com.faceunity.core.model.animationFilter.AnimationFilterTypeEnum;
|
||||||
|
import com.yunbao.faceunity.R;
|
||||||
|
import com.yunbao.faceunity.entity.AnimationFilterBean;
|
||||||
|
import com.yunbao.faceunity.entity.AnimojiBean;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DESC:Animoji数据构造
|
||||||
|
* Created on 2021/3/25
|
||||||
|
*/
|
||||||
|
public class AnimojiSource {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造贴图数据
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<AnimojiBean> buildAnimojis() {
|
||||||
|
ArrayList<AnimojiBean> array = new ArrayList<>();
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_control_delete_all, null));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_cartoon_princess, "animoji/cartoon_princess_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_qgirl, "animoji/qgirl_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_kaola, "animoji/kaola_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_wuxia, "animoji/wuxia_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_baihu, "animoji/baihu_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_frog_st, "animoji/frog_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_huangya, "animoji/huangya_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_hetun, "animoji/hetun_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_douniuquan, "animoji/douniuquan_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_hashiqi, "animoji/hashiqi_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_baimao, "animoji/baimao_Animoji.bundle"));
|
||||||
|
array.add(new AnimojiBean(R.mipmap.icon_animoji_kuloutou, "animoji/kuloutou_Animoji.bundle"));
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造滤镜数据
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<AnimationFilterBean> buildFilters() {
|
||||||
|
ArrayList<AnimationFilterBean> filters = new ArrayList<>();
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_control_delete_all, AnimationFilterTypeEnum.Origin));
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_anime, AnimationFilterTypeEnum.Comic));
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_portrait_dynamiceffect, AnimationFilterTypeEnum.Portrait));
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_sketch, AnimationFilterTypeEnum.Sketch));
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_oilpainting, AnimationFilterTypeEnum.Oil));
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_sandlpainting, AnimationFilterTypeEnum.Sand));
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_penpainting, AnimationFilterTypeEnum.Pen));
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_pencilpainting, AnimationFilterTypeEnum.Pencil));
|
||||||
|
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_graffiti, AnimationFilterTypeEnum.Granffiti));
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
package com.yunbao.faceunity.repo;
|
||||||
|
|
||||||
|
import com.faceunity.core.avatar.avatar.Color;
|
||||||
|
import com.faceunity.core.avatar.avatar.TransForm;
|
||||||
|
import com.faceunity.core.avatar.model.Avatar;
|
||||||
|
import com.faceunity.core.avatar.model.Scene;
|
||||||
|
import com.faceunity.core.entity.FUAnimationData;
|
||||||
|
import com.faceunity.core.entity.FUAvatarAnimFilterParams;
|
||||||
|
import com.faceunity.core.entity.FUBundleData;
|
||||||
|
import com.faceunity.core.entity.FUColorRGBData;
|
||||||
|
import com.faceunity.core.entity.FUCoordinate3DData;
|
||||||
|
import com.faceunity.core.entity.FUTranslationScale;
|
||||||
|
import com.faceunity.core.entity.FUVisibleBundleData;
|
||||||
|
import com.yunbao.faceunity.R;
|
||||||
|
import com.yunbao.faceunity.entity.AvatarBean;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DESC:Avatar数据构造
|
||||||
|
* Created on 2021/3/30
|
||||||
|
*/
|
||||||
|
public class AvatarSource {
|
||||||
|
// Avatar
|
||||||
|
private static String BUNDLE_AVATAR_CONTROLLER = "graphics" + File.separator + "controller_cpp.bundle";
|
||||||
|
private static String BUNDLE_AVATAR_CONFIG = "pta" + File.separator + "controller_config.bundle";
|
||||||
|
private static String BUNDLE_AVATAR_BACKGROUND = "pta" + File.separator + "default_bg.bundle";
|
||||||
|
|
||||||
|
public static String BOY = "boy";
|
||||||
|
public static String GIRL = "girl";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造成员列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<AvatarBean> buildMembers() {
|
||||||
|
ArrayList<AvatarBean> avatarBeans = new ArrayList<>();
|
||||||
|
avatarBeans.add(new AvatarBean(R.mipmap.icon_avatar_female, GIRL));
|
||||||
|
avatarBeans.add(new AvatarBean(R.mipmap.icon_avatar_male, BOY));
|
||||||
|
return avatarBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造场景
|
||||||
|
*
|
||||||
|
* @param avatar
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Scene buildSceneModel(Avatar avatar) {
|
||||||
|
FUBundleData controlBundle = new FUBundleData(BUNDLE_AVATAR_CONTROLLER);
|
||||||
|
FUBundleData avatarConfig = new FUBundleData(BUNDLE_AVATAR_CONFIG);
|
||||||
|
Scene sceneModel = new Scene(controlBundle, avatarConfig);
|
||||||
|
sceneModel.addAvatar(avatar);
|
||||||
|
sceneModel.processorConfig.setEnableHumanProcessor(true);
|
||||||
|
return sceneModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取男孩对象
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Avatar buildBoyData(boolean isFull) {
|
||||||
|
String ptaBoyDir = "pta/boy/";
|
||||||
|
ArrayList<FUBundleData> components = new ArrayList();
|
||||||
|
components.add(new FUBundleData(ptaBoyDir + "head.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaBoyDir + "midBody_male.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaBoyDir + "male_hair_5.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaBoyDir + "toushi_7.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaBoyDir + "peishi_erding_2.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaBoyDir + "waitao_3.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaBoyDir + "kuzi_changku_5.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaBoyDir + "xiezi_tuoxie_2.bundle"));
|
||||||
|
int[] invisibleList = {2,3,4};
|
||||||
|
components.add(new FUVisibleBundleData("",invisibleList,""));
|
||||||
|
ArrayList<FUAnimationData> animations = buildAnimations();
|
||||||
|
Avatar model = new Avatar(components);
|
||||||
|
for (FUAnimationData animationData:animations){
|
||||||
|
model.animation.addAnimation(animationData);
|
||||||
|
}
|
||||||
|
model.color.setColor(Color.Skin,new FUColorRGBData(227.0,158.0,132.0));
|
||||||
|
TransForm avatarTransForm = model.transForm;
|
||||||
|
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
|
||||||
|
avatarTransForm.setPosition(isFull ? new FUCoordinate3DData(0.0, 58.14, -618.94) : new FUCoordinate3DData(0.0, 11.76, -183.89));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取女孩对象
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Avatar buildGirlData(boolean isFull) {
|
||||||
|
String ptaGirlDir = "pta/girl/";
|
||||||
|
ArrayList<FUBundleData> components = new ArrayList();
|
||||||
|
components.add(new FUBundleData(ptaGirlDir + "head.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaGirlDir + "midBody_female.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaGirlDir + "female_hair_23.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaGirlDir + "toushi_5.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaGirlDir + "taozhuang_12.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaGirlDir + "facemakeup_3.bundle"));
|
||||||
|
components.add(new FUBundleData(ptaGirlDir + "xiezi_danxie.bundle"));
|
||||||
|
int[] invisibleList = {2,3,4};
|
||||||
|
components.add(new FUVisibleBundleData("",invisibleList,""));
|
||||||
|
ArrayList<FUAnimationData> animations = buildAnimations();
|
||||||
|
Avatar model = new Avatar(components );
|
||||||
|
for (FUAnimationData animationData:animations){
|
||||||
|
model.animation.addAnimation(animationData);
|
||||||
|
}
|
||||||
|
model.color.setColor(Color.Skin,new FUColorRGBData(255.0,202.0,186.0));
|
||||||
|
TransForm avatarTransForm = model.transForm;
|
||||||
|
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
|
||||||
|
avatarTransForm.setPosition(isFull ? new FUCoordinate3DData(0.0, 58.14, -618.94) : new FUCoordinate3DData(0.0, 11.76, -183.89));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部传入组件和动画构建
|
||||||
|
*
|
||||||
|
* @param strComponents 组件bundle
|
||||||
|
* @param strAnimations 动画bundle
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Avatar buildAvatarData(ArrayList<String> strComponents, ArrayList<String> strAnimations) {
|
||||||
|
ArrayList<FUBundleData> components = new ArrayList();
|
||||||
|
for (String component : strComponents) {
|
||||||
|
components.add(new FUBundleData(component));
|
||||||
|
}
|
||||||
|
|
||||||
|
Avatar model = new Avatar(components);
|
||||||
|
for (String animation : strAnimations) {
|
||||||
|
model.animation.addAnimation(new FUAnimationData(new FUBundleData(animation)));
|
||||||
|
}
|
||||||
|
//位置等avatar基本参数构建
|
||||||
|
TransForm avatarTransForm = model.transForm;
|
||||||
|
avatarTransForm.setPosition(new FUCoordinate3DData(20, 45, -618.94));
|
||||||
|
avatarTransForm.setTranslationScale(new FUTranslationScale(0.0f,0.0f,0.0f));
|
||||||
|
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
|
||||||
|
model.animation.setHumanProcessorSetAvatarAnimFilterParams(new FUAvatarAnimFilterParams(8, 0.09f, 0.120f));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造动画参数
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<FUAnimationData> buildAnimations() {
|
||||||
|
String animDir = "pta/gesture/";
|
||||||
|
ArrayList<FUAnimationData> animations = new ArrayList();
|
||||||
|
animations.add(new FUAnimationData(new FUBundleData(animDir + "anim_idle.bundle")));
|
||||||
|
return animations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSceneBackGround(Scene sceneModel, boolean hasBackGround) {
|
||||||
|
sceneModel.setBackgroundBundle(hasBackGround ? new FUBundleData(BUNDLE_AVATAR_BACKGROUND) : null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
package com.yunbao.faceunity.repo;
|
||||||
|
|
||||||
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
|
||||||
|
import com.faceunity.core.controller.bgSegGreen.BgSegGreenParam;
|
||||||
|
import com.faceunity.core.entity.FUBundleData;
|
||||||
|
import com.faceunity.core.model.bgSegGreen.BgSegGreen;
|
||||||
|
import com.yunbao.faceunity.R;
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean;
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenBean;
|
||||||
|
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean;
|
||||||
|
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DESC:绿幕抠像数据构造
|
||||||
|
* Created on 2021/3/25
|
||||||
|
*/
|
||||||
|
public class BgSegGreenSource {
|
||||||
|
private static final String GREEN_SAFE_AREA_CUSTOM = "green_safe_area_custom";
|
||||||
|
|
||||||
|
private static double SIMILARITY = 0.5;//相似度
|
||||||
|
private static double SMOOTHNESS = 0.3;//平滑度
|
||||||
|
private static double TRANSPARENCY = 0.67;//透明度
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造绿幕抠像对象
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static BgSegGreen buildBgSegGreen() {
|
||||||
|
BgSegGreen bgSegGreen = new BgSegGreen(new FUBundleData(FaceUnityConfig.BUNDLE_BG_SEG_GREEN));
|
||||||
|
bgSegGreen.setSimilarity(BgSegGreenSource.SIMILARITY);
|
||||||
|
bgSegGreen.setSmoothness(BgSegGreenSource.SMOOTHNESS);
|
||||||
|
bgSegGreen.setTransparency(BgSegGreenSource.TRANSPARENCY);
|
||||||
|
return bgSegGreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取模型属性扩展数据
|
||||||
|
*
|
||||||
|
* @return HashMap<String, ModelAttributeData>
|
||||||
|
*/
|
||||||
|
public static HashMap<String, ModelAttributeData> buildModelAttributeRange() {
|
||||||
|
HashMap<String, ModelAttributeData> params = new HashMap<String, ModelAttributeData>();
|
||||||
|
params.put(BgSegGreenParam.SIMILARITY, new ModelAttributeData(SIMILARITY, 0.0, 0.0, 1.0));
|
||||||
|
params.put(BgSegGreenParam.SMOOTHNESS, new ModelAttributeData(SMOOTHNESS, 0.0, 0.0, 1.0));
|
||||||
|
params.put(BgSegGreenParam.TRANSPARENCY, new ModelAttributeData(TRANSPARENCY, 0.0, 0.0, 1.0));
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绿幕抠像功能列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<BgSegGreenBean> buildBgSegGreenAction() {
|
||||||
|
ArrayList<BgSegGreenBean> actions = new ArrayList<BgSegGreenBean>();
|
||||||
|
actions.add(new BgSegGreenBean(BgSegGreenParam.RGB_COLOR, R.string.bg_seg_green_key_color, R.drawable.icon_green_color_selector, R.drawable.icon_green_color_selector, BgSegGreenBean.ButtonType.NORMAL2_BUTTON));
|
||||||
|
actions.add(new BgSegGreenBean(BgSegGreenParam.SIMILARITY, R.string.bg_seg_green_similarity, R.drawable.icon_green_similarityr_close_selector, R.drawable.icon_green_similarityr_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
|
||||||
|
actions.add(new BgSegGreenBean(BgSegGreenParam.SMOOTHNESS, R.string.bg_seg_green_smooth, R.drawable.icon_green_smooth_close_selector, R.drawable.icon_green_similarityr_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
|
||||||
|
actions.add(new BgSegGreenBean(BgSegGreenParam.TRANSPARENCY, R.string.bg_seg_green_alpha, R.drawable.icon_green_transparency_close_selector, R.drawable.icon_green_transparency_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
|
||||||
|
actions.add(new BgSegGreenBean("", R.string.bg_seg_green_safe_area, R.drawable.icon_green_safe_area_close_selector, R.drawable.icon_green_safe_area_open_selector, BgSegGreenBean.ButtonType.SWITCH_BUTTON));
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绿幕抠像安全区域功能列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<BgSegGreenSafeAreaBean> buildBgSegGreenSafeArea() {
|
||||||
|
String fileDir = "bg_seg_green" + File.separator + "sample" + File.separator;
|
||||||
|
ArrayList<BgSegGreenSafeAreaBean> safeAreaBeans = new ArrayList<BgSegGreenSafeAreaBean>();
|
||||||
|
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_return, BgSegGreenSafeAreaBean.ButtonType.BACK_BUTTON));//返回
|
||||||
|
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_none, BgSegGreenSafeAreaBean.ButtonType.NONE_BUTTON));//不选
|
||||||
|
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_square_add, BgSegGreenSafeAreaBean.ButtonType.NORMAL2_BUTTON));//自定义
|
||||||
|
BgSegGreenSafeAreaBean customerBean = buildSafeAreaCustomBean(getCachePortraitSegment());
|
||||||
|
if (customerBean != null) {
|
||||||
|
safeAreaBeans.add(customerBean);
|
||||||
|
}
|
||||||
|
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_green_safe_area1, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON,fileDir + "safe_area1.jpg"));//区域一
|
||||||
|
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_green_safe_area2, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON,fileDir + "safe_area2.jpg"));//区域二
|
||||||
|
return safeAreaBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造自定义安全区域图片
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static BgSegGreenSafeAreaBean buildSafeAreaCustomBean(String path) {
|
||||||
|
if (path != null && path.trim().length() > 0 && new File(path).exists()) {
|
||||||
|
saveCachePortraitSegment(path);
|
||||||
|
return new BgSegGreenSafeAreaBean(0, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON, path,false);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绿幕抠像背景列表
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<BgSegGreenBackgroundBean> buildBgSegGreenBackground() {
|
||||||
|
ArrayList<BgSegGreenBackgroundBean> backgroundBeans = new ArrayList<>();
|
||||||
|
String fileDir = "bg_seg_green" + File.separator + "sample" + File.separator;
|
||||||
|
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.cancel, R.mipmap.icon_control_none, null));
|
||||||
|
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_science, R.mipmap.icon_green_science, fileDir + "science.mp4"));
|
||||||
|
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_beach, R.mipmap.icon_green_bg_beach, fileDir + "beach.mp4"));
|
||||||
|
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_classroom, R.mipmap.icon_green_bg_classroom, fileDir + "classroom.mp4"));
|
||||||
|
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_ink, R.mipmap.icon_green_ink_painting, fileDir + "ink_painting.mp4"));
|
||||||
|
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_forest, R.mipmap.icon_green_bg_forest, fileDir + "forest.mp4"));
|
||||||
|
return backgroundBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存自定义安全区域图片
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
*/
|
||||||
|
public static void saveCachePortraitSegment(String path) {
|
||||||
|
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(GREEN_SAFE_AREA_CUSTOM, MODE_PRIVATE);
|
||||||
|
sp.edit().putString(GREEN_SAFE_AREA_CUSTOM, path).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取自定义安全区域图片
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getCachePortraitSegment() {
|
||||||
|
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(GREEN_SAFE_AREA_CUSTOM, MODE_PRIVATE);
|
||||||
|
return sp.getString(GREEN_SAFE_AREA_CUSTOM, "");
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,24 @@
|
|||||||
package com.yunbao.faceunity.repo;
|
package com.yunbao.faceunity.repo;
|
||||||
|
|
||||||
|
|
||||||
import com.faceunity.core.controller.facebeauty.FaceBeautyParam;
|
import com.faceunity.core.controller.facebeauty.FaceBeautyParam;
|
||||||
import com.faceunity.core.entity.FUBundleData;
|
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.FaceBeauty;
|
||||||
import com.faceunity.core.model.facebeauty.FaceBeautyBlurTypeEnum;
|
|
||||||
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||||
import com.yunbao.faceunity.R;
|
import com.yunbao.faceunity.R;
|
||||||
|
import com.yunbao.faceunity.data.FaceBeautyData;
|
||||||
|
import com.yunbao.faceunity.data.FaceBeautyDataFactory;
|
||||||
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
import com.yunbao.faceunity.entity.FaceBeautyBean;
|
||||||
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||||
|
import com.yunbao.faceunity.entity.FaceBeautyStyleBean;
|
||||||
import com.yunbao.faceunity.entity.ModelAttributeData;
|
import com.yunbao.faceunity.entity.ModelAttributeData;
|
||||||
|
import com.yunbao.faceunity.utils.FUUtils;
|
||||||
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||||
import com.yunbao.faceunity.utils.FuDeviceUtils;
|
import com.yunbao.faceunity.utils.FuDeviceUtils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
@ -22,36 +28,76 @@ import java.util.HashMap;
|
|||||||
*/
|
*/
|
||||||
public class FaceBeautySource {
|
public class FaceBeautySource {
|
||||||
|
|
||||||
public static String BUNDLE_FACE_BEAUTIFICATION = "graphics" + File.separator + "face_beautification.bundle";
|
private static ArrayList<FaceBeautyFilterBean> filters = new ArrayList<>();
|
||||||
|
private static FaceBeautyData faceBeautyData;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取默认推荐美颜模型
|
* 获取默认推荐美颜模型
|
||||||
|
* 一个app生命周期请求一次
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static FaceBeauty getDefaultFaceBeauty() {
|
public static FaceBeauty getDefaultFaceBeauty() {
|
||||||
FaceBeauty recommendFaceBeauty = new FaceBeauty(new FUBundleData(BUNDLE_FACE_BEAUTIFICATION));
|
FaceBeauty recommendFaceBeauty = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||||
recommendFaceBeauty.setFilterName(FaceBeautyFilterEnum.ZIRAN_1);
|
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.setFilterIntensity(0.4);
|
||||||
/*美肤*/
|
/*美肤*/
|
||||||
recommendFaceBeauty.setBlurType(FaceBeautyBlurTypeEnum.FineSkin);
|
|
||||||
recommendFaceBeauty.setSharpenIntensity(0.2);
|
recommendFaceBeauty.setSharpenIntensity(0.2);
|
||||||
recommendFaceBeauty.setColorIntensity(0.3);
|
recommendFaceBeauty.setColorIntensity(0.3);
|
||||||
recommendFaceBeauty.setRedIntensity(0.3);
|
recommendFaceBeauty.setRedIntensity(0.3);
|
||||||
recommendFaceBeauty.setBlurIntensity(4.2);
|
recommendFaceBeauty.setBlurIntensity(4.2);
|
||||||
/*美型*/
|
/*美型*/
|
||||||
recommendFaceBeauty.setFaceShapeIntensity(1.0);
|
recommendFaceBeauty.setFaceShapeIntensity(1.0);
|
||||||
recommendFaceBeauty.setEyeEnlargingIntensityV2(0.4);
|
recommendFaceBeauty.setEyeEnlargingIntensity(0.4);
|
||||||
recommendFaceBeauty.setCheekVIntensity(0.5);
|
recommendFaceBeauty.setCheekVIntensity(0.5);
|
||||||
recommendFaceBeauty.setNoseIntensityV2(0.5);
|
recommendFaceBeauty.setNoseIntensity(0.5);
|
||||||
recommendFaceBeauty.setForHeadIntensityV2(0.3);
|
recommendFaceBeauty.setForHeadIntensity(0.3);
|
||||||
recommendFaceBeauty.setMouthIntensityV2(0.4);
|
recommendFaceBeauty.setMouthIntensity(0.4);
|
||||||
recommendFaceBeauty.setChinIntensity(0.3);
|
recommendFaceBeauty.setChinIntensity(0.3);
|
||||||
|
//性能最优策略
|
||||||
|
if (FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID) {
|
||||||
|
setFaceBeautyPropertyMode(recommendFaceBeauty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化美肤参数
|
* 初始化美肤参数
|
||||||
@ -98,15 +144,14 @@ public class FaceBeautySource {
|
|||||||
params.add(
|
params.add(
|
||||||
new FaceBeautyBean(
|
new FaceBeautyBean(
|
||||||
FaceBeautyParam.REMOVE_POUCH_INTENSITY, R.string.beauty_micro_pouch,
|
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
|
R.drawable.icon_beauty_skin_dark_circles_close_selector, R.drawable.icon_beauty_skin_dark_circles_open_selector)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
params.add(
|
params.add(
|
||||||
new FaceBeautyBean(
|
new FaceBeautyBean(
|
||||||
FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, R.string.beauty_micro_nasolabial,
|
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
|
R.drawable.icon_beauty_skin_wrinkle_close_selector, R.drawable.icon_beauty_skin_wrinkle_open_selector)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +162,13 @@ public class FaceBeautySource {
|
|||||||
*/
|
*/
|
||||||
public static ArrayList<FaceBeautyBean> buildShapeParams() {
|
public static ArrayList<FaceBeautyBean> buildShapeParams() {
|
||||||
ArrayList<FaceBeautyBean> params = new ArrayList<>();
|
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(
|
params.add(
|
||||||
new FaceBeautyBean(
|
new FaceBeautyBean(
|
||||||
@ -257,6 +309,64 @@ public class FaceBeautySource {
|
|||||||
return params;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化参数扩展列表
|
* 初始化参数扩展列表
|
||||||
*
|
*
|
||||||
@ -308,14 +418,279 @@ public class FaceBeautySource {
|
|||||||
* @return ArrayList<FaceBeautyFilterBean>
|
* @return ArrayList<FaceBeautyFilterBean>
|
||||||
*/
|
*/
|
||||||
public static ArrayList<FaceBeautyFilterBean> buildFilters() {
|
public static ArrayList<FaceBeautyFilterBean> buildFilters() {
|
||||||
ArrayList<FaceBeautyFilterBean> filters = new ArrayList<>();
|
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.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));
|
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.ZHIGANHUI_1, R.mipmap.icon_beauty_filter_texture_gray_1, R.string.zhiganhui_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.BAILIANG_1, R.mipmap.icon_beauty_filter_bailiang_1, R.string.bailiang_1));
|
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.FENNEN_1, R.mipmap.icon_beauty_filter_fennen_1, R.string.fennen_1));
|
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.LENGSEDIAO_1, R.mipmap.icon_beauty_filter_lengsediao_1, R.string.lengsediao_1));
|
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;
|
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));
|
||||||
|
params.add(new FaceBeautyStyleBean(CONFIG_QINGYAN, R.drawable.icon_beauty_style_2_selector, R.string.beauty_face_style_2));
|
||||||
|
params.add(new FaceBeautyStyleBean(CONFIG_ZIJIETIAODONG, R.drawable.icon_beauty_style_3_selector, R.string.beauty_face_style_3));
|
||||||
|
params.add(new FaceBeautyStyleBean(CONFIG_HUAJIAO, R.drawable.icon_beauty_style_4_selector, R.string.beauty_face_style_4));
|
||||||
|
params.add(new FaceBeautyStyleBean(CONFIG_YINGKE, R.drawable.icon_beauty_style_5_selector, R.string.beauty_face_style_5));
|
||||||
|
params.add(new FaceBeautyStyleBean(CONFIG_SHANGTANG, R.drawable.icon_beauty_style_6_selector, R.string.beauty_face_style_6));
|
||||||
|
params.add(new FaceBeautyStyleBean(CONFIG_BIAOZHUN, R.drawable.icon_beauty_style_7_selector, R.string.beauty_face_style_7));
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 风格对应参数配置
|
||||||
|
*/
|
||||||
|
public static HashMap<String, Runnable> styleParams = new HashMap<String, Runnable>() {
|
||||||
|
{
|
||||||
|
put(CONFIG_KUAISHOU, () -> {
|
||||||
|
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||||
|
model.setFaceShapeIntensity(1.0);
|
||||||
|
model.setColorIntensity(0.5);
|
||||||
|
model.setBlurIntensity(3.6);
|
||||||
|
model.setEyeBrightIntensity(0.35);
|
||||||
|
model.setToothIntensity(0.25);
|
||||||
|
model.setCheekThinningIntensity(0.45);
|
||||||
|
model.setCheekVIntensity(0.08);
|
||||||
|
model.setCheekSmallIntensity(0.05);
|
||||||
|
model.setEyeEnlargingIntensity(0.3);
|
||||||
|
FaceBeautyDataFactory.faceBeauty = model;
|
||||||
|
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
|
||||||
|
});
|
||||||
|
put(CONFIG_QINGYAN, () -> {
|
||||||
|
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||||
|
model.setFaceShapeIntensity(1.0);
|
||||||
|
model.setFilterName(FaceBeautyFilterEnum.ZIRAN_3);
|
||||||
|
model.setFilterIntensity(0.3);
|
||||||
|
model.setColorIntensity(0.4);
|
||||||
|
model.setRedIntensity(0.2);
|
||||||
|
model.setBlurIntensity(3.6);
|
||||||
|
model.setEyeBrightIntensity(0.5);
|
||||||
|
model.setToothIntensity(0.4);
|
||||||
|
model.setCheekThinningIntensity(0.3);
|
||||||
|
model.setNoseIntensity(0.5);
|
||||||
|
model.setEyeEnlargingIntensity(0.25);
|
||||||
|
FaceBeautyDataFactory.faceBeauty = model;
|
||||||
|
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
});
|
||||||
|
put(CONFIG_ZIJIETIAODONG, () -> {
|
||||||
|
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||||
|
model.setFaceShapeIntensity(1.0);
|
||||||
|
model.setColorIntensity(0.4);
|
||||||
|
model.setRedIntensity(0.3);
|
||||||
|
model.setBlurIntensity(2.4);
|
||||||
|
model.setCheekThinningIntensity(0.3);
|
||||||
|
model.setCheekSmallIntensity(0.15);
|
||||||
|
model.setEyeEnlargingIntensity(0.65);
|
||||||
|
model.setNoseIntensity(0.3);
|
||||||
|
FaceBeautyDataFactory.faceBeauty = model;
|
||||||
|
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
});
|
||||||
|
put(CONFIG_HUAJIAO, () -> {
|
||||||
|
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||||
|
model.setFaceShapeIntensity(1.0);
|
||||||
|
model.setColorIntensity(0.7);
|
||||||
|
model.setBlurIntensity(3.9);
|
||||||
|
model.setCheekThinningIntensity(0.3);
|
||||||
|
model.setCheekSmallIntensity(0.05);
|
||||||
|
model.setEyeEnlargingIntensity(0.65);
|
||||||
|
FaceBeautyDataFactory.faceBeauty = model;
|
||||||
|
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
});
|
||||||
|
put(CONFIG_YINGKE, () -> {
|
||||||
|
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||||
|
model.setFaceShapeIntensity(1.0);
|
||||||
|
model.setFilterName(FaceBeautyFilterEnum.FENNEN_2);
|
||||||
|
model.setFilterIntensity(0.5);
|
||||||
|
model.setColorIntensity(0.6);
|
||||||
|
model.setBlurIntensity(3.0);
|
||||||
|
model.setCheekThinningIntensity(0.5);
|
||||||
|
model.setEyeEnlargingIntensity(0.65);
|
||||||
|
FaceBeautyDataFactory.faceBeauty = model;
|
||||||
|
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
});
|
||||||
|
put(CONFIG_SHANGTANG, () -> {
|
||||||
|
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||||
|
model.setFaceShapeIntensity(1.0);
|
||||||
|
model.setFilterName(FaceBeautyFilterEnum.FENNEN_2);
|
||||||
|
model.setFilterIntensity(0.8);
|
||||||
|
model.setColorIntensity(0.7);
|
||||||
|
model.setBlurIntensity(4.2);
|
||||||
|
model.setEyeEnlargingIntensity(0.6);
|
||||||
|
model.setCheekThinningIntensity(0.3);
|
||||||
|
FaceBeautyDataFactory.faceBeauty = model;
|
||||||
|
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
});
|
||||||
|
put(CONFIG_BIAOZHUN, () -> {
|
||||||
|
FaceBeauty model = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION));
|
||||||
|
model.setFaceShapeIntensity(1.0);
|
||||||
|
model.setFilterName(FaceBeautyFilterEnum.ZIRAN_5);
|
||||||
|
model.setFilterIntensity(0.55);
|
||||||
|
model.setColorIntensity(0.2);
|
||||||
|
model.setRedIntensity(0.65);
|
||||||
|
model.setBlurIntensity(3.3);
|
||||||
|
model.setCheekSmallIntensity(0.05);
|
||||||
|
model.setCheekThinningIntensity(0.1);
|
||||||
|
FaceBeautyDataFactory.faceBeauty = model;
|
||||||
|
FURenderKit.getInstance().setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 克隆模型
|
||||||
|
*
|
||||||
|
* @param faceBeauty
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static FaceBeauty clone(FaceBeauty faceBeauty) {
|
||||||
|
FaceBeauty cloneFaceBeauty = new FaceBeauty(new FUBundleData(faceBeauty.getControlBundle().getPath()));
|
||||||
|
/*滤镜*/
|
||||||
|
cloneFaceBeauty.setFilterName(faceBeauty.getFilterName());
|
||||||
|
cloneFaceBeauty.setFilterIntensity(faceBeauty.getFilterIntensity());
|
||||||
|
/*美肤*/
|
||||||
|
cloneFaceBeauty.setBlurIntensity(faceBeauty.getBlurIntensity());
|
||||||
|
cloneFaceBeauty.setEnableHeavyBlur(faceBeauty.getEnableHeavyBlur());
|
||||||
|
cloneFaceBeauty.setEnableSkinDetect(faceBeauty.getEnableSkinDetect());
|
||||||
|
cloneFaceBeauty.setNonSkinBlurIntensity(faceBeauty.getNonSkinBlurIntensity());
|
||||||
|
cloneFaceBeauty.setBlurType(faceBeauty.getBlurType());
|
||||||
|
cloneFaceBeauty.setEnableBlurUseMask(faceBeauty.getEnableBlurUseMask());
|
||||||
|
cloneFaceBeauty.setColorIntensity(faceBeauty.getColorIntensity());
|
||||||
|
cloneFaceBeauty.setRedIntensity(faceBeauty.getRedIntensity());
|
||||||
|
cloneFaceBeauty.setSharpenIntensity(faceBeauty.getSharpenIntensity());
|
||||||
|
cloneFaceBeauty.setEyeBrightIntensity(faceBeauty.getEyeBrightIntensity());
|
||||||
|
cloneFaceBeauty.setToothIntensity(faceBeauty.getToothIntensity());
|
||||||
|
cloneFaceBeauty.setRemovePouchIntensity(faceBeauty.getRemovePouchIntensity());
|
||||||
|
cloneFaceBeauty.setRemoveLawPatternIntensity(faceBeauty.getRemoveLawPatternIntensity());
|
||||||
|
/*美型*/
|
||||||
|
cloneFaceBeauty.setFaceShape(faceBeauty.getFaceShape());
|
||||||
|
cloneFaceBeauty.setFaceShapeIntensity(faceBeauty.getFaceShapeIntensity());
|
||||||
|
cloneFaceBeauty.setCheekThinningIntensity(faceBeauty.getCheekThinningIntensity());
|
||||||
|
cloneFaceBeauty.setCheekVIntensity(faceBeauty.getCheekVIntensity());
|
||||||
|
cloneFaceBeauty.setCheekLongIntensity(faceBeauty.getCheekLongIntensity());
|
||||||
|
cloneFaceBeauty.setCheekCircleIntensity(faceBeauty.getCheekCircleIntensity());
|
||||||
|
cloneFaceBeauty.setCheekNarrowIntensity(faceBeauty.getCheekNarrowIntensity());
|
||||||
|
cloneFaceBeauty.setCheekShortIntensity(faceBeauty.getCheekShortIntensity());
|
||||||
|
cloneFaceBeauty.setCheekSmallIntensity(faceBeauty.getCheekSmallIntensity());
|
||||||
|
cloneFaceBeauty.setCheekBonesIntensity(faceBeauty.getCheekBonesIntensity());
|
||||||
|
cloneFaceBeauty.setLowerJawIntensity(faceBeauty.getLowerJawIntensity());
|
||||||
|
cloneFaceBeauty.setEyeEnlargingIntensity(faceBeauty.getEyeEnlargingIntensity());
|
||||||
|
cloneFaceBeauty.setChinIntensity(faceBeauty.getChinIntensity());
|
||||||
|
cloneFaceBeauty.setForHeadIntensity(faceBeauty.getForHeadIntensity());
|
||||||
|
cloneFaceBeauty.setNoseIntensity(faceBeauty.getNoseIntensity());
|
||||||
|
cloneFaceBeauty.setMouthIntensity(faceBeauty.getMouthIntensity());
|
||||||
|
cloneFaceBeauty.setCanthusIntensity(faceBeauty.getCanthusIntensity());
|
||||||
|
cloneFaceBeauty.setEyeSpaceIntensity(faceBeauty.getEyeSpaceIntensity());
|
||||||
|
cloneFaceBeauty.setEyeRotateIntensity(faceBeauty.getEyeRotateIntensity());
|
||||||
|
cloneFaceBeauty.setLongNoseIntensity(faceBeauty.getLongNoseIntensity());
|
||||||
|
cloneFaceBeauty.setPhiltrumIntensity(faceBeauty.getPhiltrumIntensity());
|
||||||
|
cloneFaceBeauty.setSmileIntensity(faceBeauty.getSmileIntensity());
|
||||||
|
cloneFaceBeauty.setEyeCircleIntensity(faceBeauty.getEyeCircleIntensity());
|
||||||
|
cloneFaceBeauty.setBrowHeightIntensity(faceBeauty.getBrowHeightIntensity());
|
||||||
|
cloneFaceBeauty.setBrowSpaceIntensity(faceBeauty.getBrowSpaceIntensity());
|
||||||
|
cloneFaceBeauty.setChangeFramesIntensity(faceBeauty.getChangeFramesIntensity());
|
||||||
|
return cloneFaceBeauty;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,402 @@
|
|||||||
|
package com.yunbao.faceunity.repo;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
|
||||||
|
import com.faceunity.core.entity.FUBundleData;
|
||||||
|
import com.faceunity.core.entity.FUColorRGBData;
|
||||||
|
import com.faceunity.core.faceunity.FURenderKit;
|
||||||
|
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
|
||||||
|
import com.faceunity.core.model.littleMakeup.LightMakeup;
|
||||||
|
import com.yunbao.faceunity.R;
|
||||||
|
import com.yunbao.faceunity.entity.LightMakeupBean;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityConfig;
|
||||||
|
import com.yunbao.faceunity.utils.FaceUnityData;
|
||||||
|
import com.yunbao.faceunity.utils.FileUtils;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DESC:轻美妆数据构造
|
||||||
|
* Created on 2021/3/27
|
||||||
|
*/
|
||||||
|
public class LightMakeupSource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造轻美妆队列
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<LightMakeupBean> buildLightMakeup() {
|
||||||
|
ArrayList<LightMakeupBean> makeups = new ArrayList<>();
|
||||||
|
makeups.add(new LightMakeupBean(R.string.makeup_radio_remove, R.mipmap.icon_control_none, null, 0.0, FaceBeautyFilterEnum.ZIRAN_2, 0.4));
|
||||||
|
/*桃花*/
|
||||||
|
makeups.add(new LightMakeupBean(R.string.makeup_peach_blossom, R.mipmap.icon_light_makeup_peachblossom, "taohua", 0.9, FaceBeautyFilterEnum.FENNEN_3, 0.9));
|
||||||
|
/*西柚*/
|
||||||
|
makeups.add(new LightMakeupBean(R.string.makeup_grapefruit, R.mipmap.icon_light_makeup_grapefruit, "xiyou", 1.0, FaceBeautyFilterEnum.LENGSEDIAO_4, 1.0));
|
||||||
|
/*清透*/
|
||||||
|
makeups.add(new LightMakeupBean(R.string.makeup_clear, R.mipmap.icon_light_makeup_clear, "qingtou", 0.9, FaceBeautyFilterEnum.XIAOQINGXIN_1, 0.9));
|
||||||
|
/*男友*/
|
||||||
|
makeups.add(new LightMakeupBean(R.string.makeup_boyfriend, R.mipmap.icon_light_makeup_boyfriend, "nanyou", 1.0, FaceBeautyFilterEnum.XIAOQINGXIN_3, 1.0));
|
||||||
|
return makeups;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 风格对应参数配置
|
||||||
|
*/
|
||||||
|
public static HashMap<String, Runnable> LightMakeupParams = new HashMap<String, Runnable>() {
|
||||||
|
{
|
||||||
|
put("taohua", () -> {
|
||||||
|
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
|
||||||
|
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_01.path);
|
||||||
|
lightMakeup.setBlusherIntensity(0.9);
|
||||||
|
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_01.path);
|
||||||
|
lightMakeup.setEyeShadowIntensity(0.9);
|
||||||
|
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_01.path);
|
||||||
|
lightMakeup.setEyeBrowIntensity(0.5);
|
||||||
|
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_01.getLipColorRGBData());
|
||||||
|
lightMakeup.setLipIntensity(0.9);
|
||||||
|
FURenderKit.getInstance().setLightMakeup(lightMakeup);
|
||||||
|
});
|
||||||
|
put("xiyou", () -> {
|
||||||
|
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
|
||||||
|
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_23.path);
|
||||||
|
lightMakeup.setBlusherIntensity(1.0);
|
||||||
|
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_21.path);
|
||||||
|
lightMakeup.setEyeShadowIntensity(0.75);
|
||||||
|
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_19.path);
|
||||||
|
lightMakeup.setEyeBrowIntensity(0.6);
|
||||||
|
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_21.getLipColorRGBData());
|
||||||
|
lightMakeup.setLipIntensity(0.8);
|
||||||
|
FURenderKit.getInstance().setLightMakeup(lightMakeup);
|
||||||
|
});
|
||||||
|
put("qingtou", () -> {
|
||||||
|
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
|
||||||
|
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_22.path);
|
||||||
|
lightMakeup.setBlusherIntensity(0.9);
|
||||||
|
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_20.path);
|
||||||
|
lightMakeup.setEyeShadowIntensity(0.65);
|
||||||
|
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_18.path);
|
||||||
|
lightMakeup.setEyeBrowIntensity(0.45);
|
||||||
|
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_20.getLipColorRGBData());
|
||||||
|
lightMakeup.setLipIntensity(0.8);
|
||||||
|
FURenderKit.getInstance().setLightMakeup(lightMakeup);
|
||||||
|
});
|
||||||
|
put("nanyou", () -> {
|
||||||
|
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
|
||||||
|
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_20.path);
|
||||||
|
lightMakeup.setBlusherIntensity(0.8);
|
||||||
|
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_18.path);
|
||||||
|
lightMakeup.setEyeShadowIntensity(0.9);
|
||||||
|
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_16.path);
|
||||||
|
lightMakeup.setEyeBrowIntensity(0.65);
|
||||||
|
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_18.getLipColorRGBData());
|
||||||
|
lightMakeup.setLipIntensity(1.0);
|
||||||
|
FURenderKit.getInstance().setLightMakeup(lightMakeup);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//region 轻美妆效果枚举
|
||||||
|
public enum LightMakeUpEnum {
|
||||||
|
/**
|
||||||
|
* 美妆项,前几项是预置的效果
|
||||||
|
* 排在列表最前方,顺序为桃花妆、雀斑妆、朋克妆(其中朋克没有腮红,3个妆容的眼线、眼睫毛共用1个的)
|
||||||
|
*/
|
||||||
|
// 腮红
|
||||||
|
MAKEUP_BLUSHER_01("MAKEUP_BLUSHER_01", "light_makeup/blusher/mu_blush_01.png", R.mipmap.icon_light_makeup_blush_01, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_02("MAKEUP_BLUSHER_02", "light_makeup/blusher/mu_blush_02.png", R.mipmap.icon_light_makeup_blush_02, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_03("MAKEUP_BLUSHER_03", "light_makeup/blusher/mu_blush_03.png", R.mipmap.icon_light_makeup_blush_03, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_04("MAKEUP_BLUSHER_04", "light_makeup/blusher/mu_blush_04.png", R.mipmap.icon_light_makeup_blush_04, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_05("MAKEUP_BLUSHER_05", "light_makeup/blusher/mu_blush_05.png", R.mipmap.icon_light_makeup_blush_05, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_06("MAKEUP_BLUSHER_06", "light_makeup/blusher/mu_blush_06.png", R.mipmap.icon_light_makeup_blush_06, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_07("MAKEUP_BLUSHER_07", "light_makeup/blusher/mu_blush_07.png", R.mipmap.icon_light_makeup_blush_07, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_08("MAKEUP_BLUSHER_08", "light_makeup/blusher/mu_blush_08.png", R.mipmap.icon_light_makeup_blush_08, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_09("MAKEUP_BLUSHER_09", "light_makeup/blusher/mu_blush_09.png", R.mipmap.icon_light_makeup_blush_09, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_10("MAKEUP_BLUSHER_10", "light_makeup/blusher/mu_blush_10.png", R.mipmap.icon_light_makeup_blush_10, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_11("MAKEUP_BLUSHER_11", "light_makeup/blusher/mu_blush_11.png", R.mipmap.icon_light_makeup_blush_11, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_12("MAKEUP_BLUSHER_12", "light_makeup/blusher/mu_blush_12.png", R.mipmap.icon_light_makeup_blush_12, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_13("MAKEUP_BLUSHER_13", "light_makeup/blusher/mu_blush_13.png", R.mipmap.icon_light_makeup_blush_13, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_14("MAKEUP_BLUSHER_14", "light_makeup/blusher/mu_blush_14.png", R.mipmap.icon_light_makeup_blush_14, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_15("MAKEUP_BLUSHER_15", "light_makeup/blusher/mu_blush_15.png", R.mipmap.icon_light_makeup_blush_15, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_16("MAKEUP_BLUSHER_16", "light_makeup/blusher/mu_blush_16.png", R.mipmap.icon_light_makeup_blush_16, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_17("MAKEUP_BLUSHER_17", "light_makeup/blusher/mu_blush_17.png", R.mipmap.icon_light_makeup_blush_17, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_18("MAKEUP_BLUSHER_18", "light_makeup/blusher/mu_blush_18.png", R.mipmap.icon_light_makeup_blush_18, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_19("MAKEUP_BLUSHER_19", "light_makeup/blusher/mu_blush_19.png", R.mipmap.icon_light_makeup_blush_19, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_20("MAKEUP_BLUSHER_20", "light_makeup/blusher/mu_blush_20.png", R.mipmap.icon_light_makeup_blush_20, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_21("MAKEUP_BLUSHER_21", "light_makeup/blusher/mu_blush_21.png", R.mipmap.icon_light_makeup_blush_21, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_22("MAKEUP_BLUSHER_22", "light_makeup/blusher/mu_blush_22.png", R.mipmap.icon_light_makeup_blush_22, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_23("MAKEUP_BLUSHER_23", "light_makeup/blusher/mu_blush_23.png", R.mipmap.icon_light_makeup_blush_23, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
MAKEUP_BLUSHER_24("MAKEUP_BLUSHER_24", "light_makeup/blusher/mu_blush_24.png", R.mipmap.icon_light_makeup_blush_24, R.string.makeup_radio_blusher),
|
||||||
|
|
||||||
|
// 眉毛
|
||||||
|
MAKEUP_EYEBROW_01("MAKEUP_EYEBROW_01", "light_makeup/eyebrow/mu_eyebrow_01.png", R.mipmap.icon_light_makeup_eyebrow_01, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_02("MAKEUP_EYEBROW_02", "light_makeup/eyebrow/mu_eyebrow_02.png", R.mipmap.icon_light_makeup_eyebrow_02, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_03("MAKEUP_EYEBROW_03", "light_makeup/eyebrow/mu_eyebrow_03.png", R.mipmap.icon_light_makeup_eyebrow_03, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_04("MAKEUP_EYEBROW_04", "light_makeup/eyebrow/mu_eyebrow_04.png", R.mipmap.icon_light_makeup_eyebrow_04, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_05("MAKEUP_EYEBROW_05", "light_makeup/eyebrow/mu_eyebrow_05.png", R.mipmap.icon_light_makeup_eyebrow_05, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_06("MAKEUP_EYEBROW_06", "light_makeup/eyebrow/mu_eyebrow_06.png", R.mipmap.icon_light_makeup_eyebrow_06, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_07("MAKEUP_EYEBROW_07", "light_makeup/eyebrow/mu_eyebrow_07.png", R.mipmap.icon_light_makeup_eyebrow_07, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_08("MAKEUP_EYEBROW_08", "light_makeup/eyebrow/mu_eyebrow_08.png", R.mipmap.icon_light_makeup_eyebrow_08, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_09("MAKEUP_EYEBROW_09", "light_makeup/eyebrow/mu_eyebrow_09.png", R.mipmap.icon_light_makeup_eyebrow_09, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_10("MAKEUP_EYEBROW_10", "light_makeup/eyebrow/mu_eyebrow_10.png", R.mipmap.icon_light_makeup_eyebrow_10, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_11("MAKEUP_EYEBROW_11", "light_makeup/eyebrow/mu_eyebrow_11.png", R.mipmap.icon_light_makeup_eyebrow_11, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_12("MAKEUP_EYEBROW_12", "light_makeup/eyebrow/mu_eyebrow_12.png", R.mipmap.icon_light_makeup_eyebrow_12, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_13("MAKEUP_EYEBROW_13", "light_makeup/eyebrow/mu_eyebrow_13.png", R.mipmap.icon_light_makeup_eyebrow_13, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_14("MAKEUP_EYEBROW_14", "light_makeup/eyebrow/mu_eyebrow_14.png", R.mipmap.icon_light_makeup_eyebrow_14, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_15("MAKEUP_EYEBROW_15", "light_makeup/eyebrow/mu_eyebrow_15.png", R.mipmap.icon_light_makeup_eyebrow_15, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_16("MAKEUP_EYEBROW_16", "light_makeup/eyebrow/mu_eyebrow_16.png", R.mipmap.icon_light_makeup_eyebrow_16, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_17("MAKEUP_EYEBROW_17", "light_makeup/eyebrow/mu_eyebrow_17.png", R.mipmap.icon_light_makeup_eyebrow_17, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_18("MAKEUP_EYEBROW_18", "light_makeup/eyebrow/mu_eyebrow_18.png", R.mipmap.icon_light_makeup_eyebrow_18, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
MAKEUP_EYEBROW_19("MAKEUP_EYEBROW_19", "light_makeup/eyebrow/mu_eyebrow_19.png", R.mipmap.icon_light_makeup_eyebrow_19, R.string.makeup_radio_eyebrow),
|
||||||
|
|
||||||
|
// 睫毛
|
||||||
|
MAKEUP_EYELASH_01("MAKEUP_EYELASH_01", "light_makeup/eyelash/mu_eyelash_01.png", R.mipmap.icon_light_makeup_eyelash_01, R.string.makeup_radio_eyelash),
|
||||||
|
|
||||||
|
MAKEUP_EYELASH_02("MAKEUP_EYELASH_02", "light_makeup/eyelash/mu_eyelash_02.png", R.mipmap.icon_light_makeup_eyelash_02, R.string.makeup_radio_eyelash),
|
||||||
|
|
||||||
|
MAKEUP_EYELASH_03("MAKEUP_EYELASH_03", "light_makeup/eyelash/mu_eyelash_03.png", R.mipmap.icon_light_makeup_eyelash_03, R.string.makeup_radio_eyelash),
|
||||||
|
|
||||||
|
MAKEUP_EYELASH_04("MAKEUP_EYELASH_04", "light_makeup/eyelash/mu_eyelash_04.png", R.mipmap.icon_light_makeup_eyelash_04, R.string.makeup_radio_eyelash),
|
||||||
|
|
||||||
|
MAKEUP_EYELASH_05("MAKEUP_EYELASH_05", "light_makeup/eyelash/mu_eyelash_05.png", R.mipmap.icon_light_makeup_eyelash_05, R.string.makeup_radio_eyelash),
|
||||||
|
|
||||||
|
MAKEUP_EYELASH_06("MAKEUP_EYELASH_06", "light_makeup/eyelash/mu_eyelash_06.png", R.mipmap.icon_light_makeup_eyelash_06, R.string.makeup_radio_eyelash),
|
||||||
|
|
||||||
|
MAKEUP_EYELASH_07("MAKEUP_EYELASH_07", "light_makeup/eyelash/mu_eyelash_07.png", R.mipmap.icon_light_makeup_eyelash_07, R.string.makeup_radio_eyelash),
|
||||||
|
|
||||||
|
MAKEUP_EYELASH_08("MAKEUP_EYELASH_08", "light_makeup/eyelash/mu_eyelash_08.png", R.mipmap.icon_light_makeup_eyelash_08, R.string.makeup_radio_eyelash),
|
||||||
|
|
||||||
|
// 眼线
|
||||||
|
MAKEUP_EYELINER_01("MAKEUP_EYELINER_01", "light_makeup/eyeliner/mu_eyeliner_01.png", R.mipmap.icon_light_makeup_eyeliner_01, R.string.makeup_radio_eye_liner),
|
||||||
|
|
||||||
|
MAKEUP_EYELINER_02("MAKEUP_EYELINER_02", "light_makeup/eyeliner/mu_eyeliner_02.png", R.mipmap.icon_light_makeup_eyeliner_02, R.string.makeup_radio_eye_liner),
|
||||||
|
|
||||||
|
MAKEUP_EYELINER_03("MAKEUP_EYELINER_03", "light_makeup/eyeliner/mu_eyeliner_03.png", R.mipmap.icon_light_makeup_eyeliner_03, R.string.makeup_radio_eye_liner),
|
||||||
|
|
||||||
|
MAKEUP_EYELINER_04("MAKEUP_EYELINER_04", "light_makeup/eyeliner/mu_eyeliner_04.png", R.mipmap.icon_light_makeup_eyeliner_04, R.string.makeup_radio_eye_liner),
|
||||||
|
|
||||||
|
MAKEUP_EYELINER_05("MAKEUP_EYELINER_05", "light_makeup/eyeliner/mu_eyeliner_05.png", R.mipmap.icon_light_makeup_eyeliner_05, R.string.makeup_radio_eye_liner),
|
||||||
|
|
||||||
|
MAKEUP_EYELINER_06("MAKEUP_EYELINER_06", "light_makeup/eyeliner/mu_eyeliner_06.png", R.mipmap.icon_light_makeup_eyeliner_06, R.string.makeup_radio_eye_liner),
|
||||||
|
|
||||||
|
MAKEUP_EYELINER_07("MAKEUP_EYELINER_07", "light_makeup/eyeliner/mu_eyeliner_07.png", R.mipmap.icon_light_makeup_eyeliner_07, R.string.makeup_radio_eye_liner),
|
||||||
|
|
||||||
|
MAKEUP_EYELINER_08("MAKEUP_EYELINER_08", "light_makeup/eyeliner/mu_eyeliner_08.png", R.mipmap.icon_light_makeup_eyeliner_08, R.string.makeup_radio_eye_liner),
|
||||||
|
|
||||||
|
// 美瞳
|
||||||
|
MAKEUP_EYEPUPIL_01("MAKEUP_EYEPUPIL_01", "light_makeup/eyepupil/mu_eyepupil_01.png", R.mipmap.icon_light_makeup_eyepupil_01, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
MAKEUP_EYEPUPIL_02("MAKEUP_EYEPUPIL_02", "light_makeup/eyepupil/mu_eyepupil_02.png", R.mipmap.icon_light_makeup_eyepupil_02, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
MAKEUP_EYEPUPIL_03("MAKEUP_EYEPUPIL_03", "light_makeup/eyepupil/mu_eyepupil_03.png", R.mipmap.icon_light_makeup_eyepupil_03, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
MAKEUP_EYEPUPIL_04("MAKEUP_EYEPUPIL_04", "light_makeup/eyepupil/mu_eyepupil_04.png", R.mipmap.icon_light_makeup_eyepupil_04, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
MAKEUP_EYEPUPIL_05("MAKEUP_EYEPUPIL_05", "light_makeup/eyepupil/mu_eyepupil_05.png", R.mipmap.icon_light_makeup_eyepupil_05, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
MAKEUP_EYEPUPIL_06("MAKEUP_EYEPUPIL_06", "light_makeup/eyepupil/mu_eyepupil_06.png", R.mipmap.icon_light_makeup_eyepupil_06, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
MAKEUP_EYEPUPIL_07("MAKEUP_EYEPUPIL_07", "light_makeup/eyepupil/mu_eyepupil_07.png", R.mipmap.icon_light_makeup_eyepupil_07, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
MAKEUP_EYEPUPIL_08("MAKEUP_EYEPUPIL_08", "light_makeup/eyepupil/mu_eyepupil_08.png", R.mipmap.icon_light_makeup_eyepupil_08, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
MAKEUP_EYEPUPIL_09("MAKEUP_EYEPUPIL_09", "light_makeup/eyepupil/mu_eyepupil_09.png", R.mipmap.icon_light_makeup_eyepupil_09, R.string.makeup_radio_contact_lens),
|
||||||
|
|
||||||
|
// 眼影
|
||||||
|
MAKEUP_EYE_SHADOW_01("MAKEUP_EYESHADOW_01", "light_makeup/eyeshadow/mu_eyeshadow_01.png", R.mipmap.icon_light_makeup_eyeshadow_01, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_02("MAKEUP_EYESHADOW_02", "light_makeup/eyeshadow/mu_eyeshadow_02.png", R.mipmap.icon_light_makeup_eyeshadow_02, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_03("MAKEUP_EYESHADOW_03", "light_makeup/eyeshadow/mu_eyeshadow_03.png", R.mipmap.icon_light_makeup_eyeshadow_03, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_04("MAKEUP_EYESHADOW_04", "light_makeup/eyeshadow/mu_eyeshadow_04.png", R.mipmap.icon_light_makeup_eyeshadow_04, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_05("MAKEUP_EYESHADOW_05", "light_makeup/eyeshadow/mu_eyeshadow_05.png", R.mipmap.icon_light_makeup_eyeshadow_05, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_06("MAKEUP_EYESHADOW_06", "light_makeup/eyeshadow/mu_eyeshadow_06.png", R.mipmap.icon_light_makeup_eyeshadow_06, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_07("MAKEUP_EYESHADOW_07", "light_makeup/eyeshadow/mu_eyeshadow_07.png", R.mipmap.icon_light_makeup_eyeshadow_07, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_08("MAKEUP_EYESHADOW_08", "light_makeup/eyeshadow/mu_eyeshadow_08.png", R.mipmap.icon_light_makeup_eyeshadow_08, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_09("MAKEUP_EYESHADOW_09", "light_makeup/eyeshadow/mu_eyeshadow_09.png", R.mipmap.icon_light_makeup_eyeshadow_09, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_10("MAKEUP_EYESHADOW_10", "light_makeup/eyeshadow/mu_eyeshadow_10.png", R.mipmap.icon_light_makeup_eyeshadow_10, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_11("MAKEUP_EYESHADOW_11", "light_makeup/eyeshadow/mu_eyeshadow_11.png", R.mipmap.icon_light_makeup_eyeshadow_11, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_12("MAKEUP_EYESHADOW_12", "light_makeup/eyeshadow/mu_eyeshadow_12.png", R.mipmap.icon_light_makeup_eyeshadow_12, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_13("MAKEUP_EYESHADOW_13", "light_makeup/eyeshadow/mu_eyeshadow_13.png", R.mipmap.icon_light_makeup_eyeshadow_13, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_14("MAKEUP_EYESHADOW_14", "light_makeup/eyeshadow/mu_eyeshadow_14.png", R.mipmap.icon_light_makeup_eyeshadow_14, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_15("MAKEUP_EYESHADOW_15", "light_makeup/eyeshadow/mu_eyeshadow_15.png", R.mipmap.icon_light_makeup_eyeshadow_15, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_16("MAKEUP_EYESHADOW_16", "light_makeup/eyeshadow/mu_eyeshadow_16.png", R.mipmap.icon_light_makeup_eyeshadow_16, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_17("MAKEUP_EYESHADOW_17", "light_makeup/eyeshadow/mu_eyeshadow_17.png", R.mipmap.icon_light_makeup_eyeshadow_17, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_18("MAKEUP_EYESHADOW_18", "light_makeup/eyeshadow/mu_eyeshadow_18.png", R.mipmap.icon_light_makeup_eyeshadow_18, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_19("MAKEUP_EYESHADOW_19", "light_makeup/eyeshadow/mu_eyeshadow_19.png", R.mipmap.icon_light_makeup_eyeshadow_19, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_20("MAKEUP_EYESHADOW_20", "light_makeup/eyeshadow/mu_eyeshadow_20.png", R.mipmap.icon_light_makeup_eyeshadow_20, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_21("MAKEUP_EYESHADOW_21", "light_makeup/eyeshadow/mu_eyeshadow_21.png", R.mipmap.icon_light_makeup_eyeshadow_21, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
MAKEUP_EYE_SHADOW_22("MAKEUP_EYESHADOW_22", "light_makeup/eyeshadow/mu_eyeshadow_22.png", R.mipmap.icon_light_makeup_eyeshadow_22, R.string.makeup_radio_eye_shadow),
|
||||||
|
|
||||||
|
// 口红
|
||||||
|
MAKEUP_LIPSTICK_01("MAKEUP_LIPSTICK_01", "light_makeup/lipstick/mu_lip_01.json", R.mipmap.icon_light_makeup_lip_01, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_02("MAKEUP_LIPSTICK_02", "light_makeup/lipstick/mu_lip_02.json", R.mipmap.icon_light_makeup_lip_02, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_03("MAKEUP_LIPSTICK_03", "light_makeup/lipstick/mu_lip_03.json", R.mipmap.icon_light_makeup_lip_03, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_10("MAKEUP_LIPSTICK_10", "light_makeup/lipstick/mu_lip_10.json", R.mipmap.icon_light_makeup_lip_10, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_11("MAKEUP_LIPSTICK_11", "light_makeup/lipstick/mu_lip_11.json", R.mipmap.icon_light_makeup_lip_12, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_12("MAKEUP_LIPSTICK_12", "light_makeup/lipstick/mu_lip_12.json", R.mipmap.icon_light_makeup_lip_12, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_13("MAKEUP_LIPSTICK_13", "light_makeup/lipstick/mu_lip_13.json", R.mipmap.icon_light_makeup_lip_13, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_14("MAKEUP_LIPSTICK_14", "light_makeup/lipstick/mu_lip_14.json", R.mipmap.icon_light_makeup_lip_14, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_15("MAKEUP_LIPSTICK_15", "light_makeup/lipstick/mu_lip_15.json", R.mipmap.icon_light_makeup_lip_15, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_16("MAKEUP_LIPSTICK_16", "light_makeup/lipstick/mu_lip_16.json", R.mipmap.icon_light_makeup_lip_16, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_17("MAKEUP_LIPSTICK_17", "light_makeup/lipstick/mu_lip_17.json", R.mipmap.icon_light_makeup_lip_17, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_18("MAKEUP_LIPSTICK_18", "light_makeup/lipstick/mu_lip_18.json", R.mipmap.icon_light_makeup_lip_18, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_19("MAKEUP_LIPSTICK_19", "light_makeup/lipstick/mu_lip_19.json", R.mipmap.icon_light_makeup_lip_19, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_20("MAKEUP_LIPSTICK_20", "light_makeup/lipstick/mu_lip_20.json", R.mipmap.icon_light_makeup_lip_20, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_21("MAKEUP_LIPSTICK_21", "light_makeup/lipstick/mu_lip_21.json", R.mipmap.icon_light_makeup_lip_21, R.string.makeup_radio_lipstick),
|
||||||
|
|
||||||
|
MAKEUP_LIPSTICK_22("MAKEUP_LIPSTICK_22", "light_makeup/lipstick/mu_lip_22.json", R.mipmap.icon_light_makeup_lip_22, R.string.makeup_radio_lipstick);
|
||||||
|
|
||||||
|
|
||||||
|
private final String key;
|
||||||
|
private final String path;
|
||||||
|
private final int iconRes;
|
||||||
|
private final int strRes;
|
||||||
|
|
||||||
|
LightMakeUpEnum(String key, String path, int iconRes, int strRes) {
|
||||||
|
this.key = key;
|
||||||
|
this.path = path;
|
||||||
|
this.iconRes = iconRes;
|
||||||
|
this.strRes = strRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取口红颜色
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public FUColorRGBData getLipColorRGBData() {
|
||||||
|
double[] colorArray = loadRgbaColorFromLocal(FaceUnityData.mApplication, path);
|
||||||
|
if (colorArray != null && colorArray.length == 4) {
|
||||||
|
return new FUColorRGBData(colorArray[0] * 255, colorArray[1] * 255, colorArray[2] * 255, colorArray[3] * 255);
|
||||||
|
}
|
||||||
|
return new FUColorRGBData(0.0, 0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取 RGBA 颜色数据
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param path path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double[] loadRgbaColorFromLocal(Context context, String path) {
|
||||||
|
InputStream inputStream = FileUtils.readInputStreamByPath(context, path);
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
byte[] bytes = new byte[inputStream.available()];
|
||||||
|
inputStream.read(bytes);
|
||||||
|
JSONObject jsonObject = new JSONObject(new String(bytes));
|
||||||
|
JSONArray jsonArray = jsonObject.optJSONArray("rgba");
|
||||||
|
double[] colorArray = new double[jsonArray.length()];
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
colorArray[i] = jsonArray.optDouble(i);
|
||||||
|
}
|
||||||
|
return colorArray;
|
||||||
|
} catch (IOException | JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,28 +1,79 @@
|
|||||||
package com.yunbao.faceunity.repo;
|
package com.yunbao.faceunity.repo;
|
||||||
|
|
||||||
|
|
||||||
import com.yunbao.faceunity.R;
|
import com.yunbao.faceunity.R;
|
||||||
|
import com.yunbao.faceunity.entity.FunctionEnum;
|
||||||
import com.yunbao.faceunity.entity.PropBean;
|
import com.yunbao.faceunity.entity.PropBean;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DESC:道具数据构造
|
* DESC:道具数据构造:道具贴图、AR面具、搞笑大头、表情识别、哈哈镜、手势识别、游戏
|
||||||
* Created on 2021/3/28
|
* Created on 2021/3/28
|
||||||
*/
|
*/
|
||||||
public class PropSource {
|
public class PropSource {
|
||||||
|
|
||||||
/**
|
public static ArrayList<PropBean> buildPropBeans(int propType) {
|
||||||
* 构造贴纸列表
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static ArrayList<PropBean> buildPropBeans() {
|
|
||||||
ArrayList<PropBean> propBeans = new ArrayList<>();
|
ArrayList<PropBean> propBeans = new ArrayList<>();
|
||||||
|
switch (propType) {
|
||||||
|
case FunctionEnum.STICKER:
|
||||||
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null));
|
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null));
|
||||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_sdlu, "sticker/sdlu.bundle"));
|
propBeans.add(new PropBean(R.mipmap.icon_sticker_cat_sparks, "effect/normal/cat_sparks.bundle"));
|
||||||
propBeans.add(new PropBean(R.mipmap.icon_sticker_fashi, "sticker/fashi.bundle"));
|
propBeans.add(new PropBean(R.mipmap.icon_sticker_fu_zh_fenshu, "effect/normal/fu_zh_fenshu.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_sticker_sdlr, "effect/normal/sdlr.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_sticker_xlong_zh_fu, "effect/normal/xlong_zh_fu.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_sticker_newy1, "effect/normal/newy1.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_sticker_redribbt, "effect/normal/redribbt.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_sticker_daisypig, "effect/normal/daisypig.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_sticker_sdlu, "effect/normal/sdlu.bundle"));
|
||||||
|
break;
|
||||||
|
case FunctionEnum.AR_MASK:
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_ar_bluebird, "effect/ar/bluebird.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_ar_lanhudie, "effect/ar/lanhudie.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_ar_fenhudie, "effect/ar/fenhudie.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_ar_tiger_huang, "effect/ar/tiger_huang.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_ar_tiger_bai, "effect/ar/tiger_bai.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_ar_baozi, "effect/ar/baozi.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_ar_tiger, "effect/ar/tiger.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_ar_xiongmao, "effect/ar/xiongmao.bundle"));
|
||||||
|
break;
|
||||||
|
case FunctionEnum.BIG_HEAD:
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_big_head, "effect/big_head/big_head.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_big_head_husky_face, "effect/big_head/big_head_facewarp2.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_big_head_sausage_mouth, "effect/big_head/big_head_facewarp4.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_big_head_blush, "effect/big_head/big_head_facewarp5.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_big_head_dark_circles, "effect/big_head/big_head_facewarp6.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_big_head_smiling_head, "effect/big_head/big_head_smile.bundle", R.string.xiaobianzi_zh_fu));
|
||||||
|
break;
|
||||||
|
case FunctionEnum.EXPRESSION_RECOGNITION:
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_expression_future_warrior, "effect/expression/future_warrior.bundle", R.string.future_warrior));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_expression_jet_mask, "effect/expression/jet_mask.bundle", R.string.jet_mask));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_expression_sdx2, "effect/expression/sdx2.bundle", R.string.sdx2));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_expression_luhantongkuan_ztt_fu, "effect/expression/luhantongkuan_ztt_fu.bundle", R.string.luhantongkuan_ztt_fu));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_expression_qingqing_ztt_fu, "effect/expression/qingqing_ztt_fu.bundle", R.string.qingqing_ztt_fu));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_expression_xiaobianzi_zh_fu, "effect/expression/xiaobianzi_zh_fu.bundle", R.string.xiaobianzi_zh_fu));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_expression_xiaoxueshen_ztt_fu, "effect/expression/xiaoxueshen_ztt_fu.bundle", R.string.xiaoxueshen_ztt_fu));
|
||||||
|
break;
|
||||||
|
case FunctionEnum.FACE_WARP:
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_face_warp_2, "effect/facewarp/facewarp2.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_face_warp_3, "effect/facewarp/facewarp3.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_face_warp_4, "effect/facewarp/facewarp4.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_face_warp_5, "effect/facewarp/facewarp5.bundle"));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_face_warp_6, "effect/facewarp/facewarp6.bundle"));
|
||||||
|
break;
|
||||||
|
case FunctionEnum.GESTURE_RECOGNITION:
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_gesture_rain, "effect/gesture/ctrl_rain.bundle", R.string.push_hand));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_gesture_snow, "effect/gesture/ctrl_snow.bundle", R.string.push_hand));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_gesture_flower, "effect/gesture/ctrl_flower.bundle", R.string.push_hand));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_gesture_koreaheart, "effect/gesture/ssd_thread_korheart.bundle", R.string.fu_lm_koreaheart));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_gesture_six, "effect/gesture/ssd_thread_six.bundle", R.string.ssd_thread_six));
|
||||||
|
propBeans.add(new PropBean(R.mipmap.icon_gesture_cute, "effect/gesture/ssd_thread_cute.bundle", R.string.ssd_thread_cute));
|
||||||
|
break;
|
||||||
|
}
|
||||||
return propBeans;
|
return propBeans;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import android.view.View;
|
|||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
|
||||||
import com.yunbao.faceunity.R;
|
import com.yunbao.faceunity.R;
|
||||||
@ -17,6 +19,9 @@ import com.yunbao.faceunity.control.MakeupControlView;
|
|||||||
import com.yunbao.faceunity.control.PropControlView;
|
import com.yunbao.faceunity.control.PropControlView;
|
||||||
import com.yunbao.faceunity.data.FaceUnityDataFactory;
|
import com.yunbao.faceunity.data.FaceUnityDataFactory;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DESC:
|
* DESC:
|
||||||
* Created on 2021/4/26
|
* Created on 2021/4/26
|
||||||
@ -24,6 +29,7 @@ import com.yunbao.faceunity.data.FaceUnityDataFactory;
|
|||||||
public class FaceUnityView extends LinearLayout {
|
public class FaceUnityView extends LinearLayout {
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
private RecyclerView menuGroup;
|
||||||
|
|
||||||
public FaceUnityView(Context context) {
|
public FaceUnityView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -67,36 +73,15 @@ public class FaceUnityView extends LinearLayout {
|
|||||||
*/
|
*/
|
||||||
public void bindDataFactory(FaceUnityDataFactory dataFactory) {
|
public void bindDataFactory(FaceUnityDataFactory dataFactory) {
|
||||||
mDataFactory = dataFactory;
|
mDataFactory = dataFactory;
|
||||||
mFaceBeautyControlView.bindDataFactory(dataFactory.mFaceBeautyDataFactory);
|
|
||||||
mMakeupControlView.bindDataFactory(dataFactory.mMakeupDataFactory);
|
|
||||||
mPropControlView.bindDataFactory(dataFactory.mPropDataFactory);
|
|
||||||
mBodyBeautyControlView.bindDataFactory(dataFactory.mBodyBeautyDataFactory);
|
|
||||||
switch (dataFactory.currentFunctionIndex) {
|
|
||||||
case 0:
|
|
||||||
mCheckGroupView.check(R.id.radio_beauty);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
mCheckGroupView.check(R.id.radio_sticker);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
mCheckGroupView.check(R.id.radio_makeup);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
mCheckGroupView.check(R.id.radio_body);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化View
|
* 初始化View
|
||||||
*/
|
*/
|
||||||
private void initView() {
|
private void initView() {
|
||||||
mCheckGroupView = findViewById(R.id.group_function);
|
menuGroup=findViewById(R.id.menu_group);
|
||||||
mFaceBeautyControlView = findViewById(R.id.control_beauty);
|
initMenuGroup();
|
||||||
mMakeupControlView = findViewById(R.id.control_makeup);
|
|
||||||
mPropControlView = findViewById(R.id.control_prop);
|
|
||||||
mBodyBeautyControlView = findViewById(R.id.control_body);
|
|
||||||
lineView = findViewById(R.id.line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -104,23 +89,7 @@ public class FaceUnityView extends LinearLayout {
|
|||||||
* 底部功能菜单切换
|
* 底部功能菜单切换
|
||||||
*/
|
*/
|
||||||
private void bindBottomView() {
|
private void bindBottomView() {
|
||||||
mCheckGroupView.setOnCheckedChangeListener((group, checkedId) -> {
|
|
||||||
if (checkedId == R.id.radio_beauty) {
|
|
||||||
showFunction(0);
|
|
||||||
mDataFactory.onFunctionSelected(0);
|
|
||||||
} else if (checkedId == R.id.radio_sticker) {
|
|
||||||
showFunction(1);
|
|
||||||
mDataFactory.onFunctionSelected(1);
|
|
||||||
} else if (checkedId == R.id.radio_makeup) {
|
|
||||||
showFunction(2);
|
|
||||||
mDataFactory.onFunctionSelected(2);
|
|
||||||
} else if (checkedId == R.id.radio_body) {
|
|
||||||
showFunction(3);
|
|
||||||
mDataFactory.onFunctionSelected(3);
|
|
||||||
} else {
|
|
||||||
showFunction(-1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,12 +98,19 @@ public class FaceUnityView extends LinearLayout {
|
|||||||
* @param index Int
|
* @param index Int
|
||||||
*/
|
*/
|
||||||
private void showFunction(int index) {
|
private void showFunction(int index) {
|
||||||
mFaceBeautyControlView.setVisibility((index == 0) ? View.VISIBLE : View.GONE);
|
|
||||||
mPropControlView.setVisibility((index == 1) ? View.VISIBLE : View.GONE);
|
}
|
||||||
mMakeupControlView.setVisibility((index == 2) ? View.VISIBLE : View.GONE);
|
private void initMenuGroup(){
|
||||||
mBodyBeautyControlView.setVisibility((index == 3) ? View.VISIBLE : View.GONE);
|
menuGroup.setLayoutManager(new GridLayoutManager(mContext,4));
|
||||||
lineView.setVisibility((index != -1) ? View.VISIBLE : View.GONE);
|
Map<Integer,Integer> layoutItem=new HashMap<>();
|
||||||
|
layoutItem.put(R.string.home_function_name_beauty,R.mipmap.ico_home_beauty);
|
||||||
|
layoutItem.put(R.string.home_function_name_makeup,R.mipmap.ico_home_makeup);
|
||||||
|
layoutItem.put(R.string.home_function_name_beauty_body,R.mipmap.ico_home_beauty_body);
|
||||||
|
layoutItem.put(R.string.home_function_name_beauty_body,R.mipmap.ico_home_beauty_body);
|
||||||
|
layoutItem.put(R.string.home_function_name_big_head,R.mipmap.ico_home_big_head);
|
||||||
|
layoutItem.put(R.string.home_function_name_animoji,R.mipmap.ico_home_animoji);
|
||||||
|
layoutItem.put(R.string.home_function_name_sticker,R.mipmap.ico_home_sticker);
|
||||||
|
layoutItem.put(R.string.home_function_name_fine_sticker,R.mipmap.ico_home_fine_sticker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.yunbao.faceunity.ui.fragments;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.yunbao.faceunity.dialog.BaseDialogFragment;
|
||||||
|
|
||||||
|
public class FaceContainerFragment extends BaseDialogFragment {
|
||||||
|
@Override
|
||||||
|
protected View createDialogView(LayoutInflater inflater, @Nullable ViewGroup container) {
|
||||||
|
return new LinearLayout(inflater.getContext());
|
||||||
|
}
|
||||||
|
}
|
271
FaceUnity/src/main/java/com/yunbao/faceunity/utils/FUUtils.java
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
package com.yunbao.faceunity.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import com.faceunity.core.model.facebeauty.FaceBeauty;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.yunbao.faceunity.data.FaceBeautyData;
|
||||||
|
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将FaceBeauty FaceBeautyData 互相设置
|
||||||
|
*/
|
||||||
|
public class FUUtils {
|
||||||
|
private static final String SP_NAME = "FaceBeauty";
|
||||||
|
private static final String SP_KEY_NAME = "faceBeautyData";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将FaceBeauty 转 FaceBeautyData
|
||||||
|
*
|
||||||
|
* @param faceBeautyData
|
||||||
|
*/
|
||||||
|
public static void buildFaceBeautyData(FaceBeautyData faceBeautyData, FaceBeauty faceBeauty, ArrayList<FaceBeautyFilterBean> filterList, int styleTypeIndex) {
|
||||||
|
if (faceBeauty != null) {
|
||||||
|
/* 美肤 */
|
||||||
|
/* 磨皮类型 */
|
||||||
|
faceBeautyData.blurType = faceBeauty.getBlurType();
|
||||||
|
/* 磨皮程度 */
|
||||||
|
faceBeautyData.blurIntensity = faceBeauty.getBlurIntensity();
|
||||||
|
/* 美白程度 */
|
||||||
|
faceBeautyData.colorIntensity = faceBeauty.getColorIntensity();
|
||||||
|
/* 红润程度 */
|
||||||
|
faceBeautyData.redIntensity = faceBeauty.getRedIntensity();
|
||||||
|
/* 锐化程度 */
|
||||||
|
faceBeautyData.sharpenIntensity = faceBeauty.getSharpenIntensity();
|
||||||
|
/* 亮眼程度 */
|
||||||
|
faceBeautyData.eyeBrightIntensity = faceBeauty.getEyeBrightIntensity();
|
||||||
|
/* 美牙程度 */
|
||||||
|
faceBeautyData.toothIntensity = faceBeauty.getToothIntensity();
|
||||||
|
/* 去黑眼圈强度*/
|
||||||
|
faceBeautyData.removePouchIntensity = faceBeauty.getRemovePouchIntensity();
|
||||||
|
/* 去法令纹强度*/
|
||||||
|
faceBeautyData.removeLawPatternIntensity = faceBeauty.getRemoveLawPatternIntensity();
|
||||||
|
|
||||||
|
/* 美型 */
|
||||||
|
/* 瘦脸程度 */
|
||||||
|
faceBeautyData.cheekThinningIntensity = faceBeauty.getCheekThinningIntensity();
|
||||||
|
/* V脸程度 */
|
||||||
|
faceBeautyData.cheekVIntensity = faceBeauty.getCheekVIntensity();
|
||||||
|
/* 窄脸程度 */
|
||||||
|
faceBeautyData.cheekNarrowIntensity = faceBeauty.getCheekNarrowIntensity();
|
||||||
|
/* 短脸程度 */
|
||||||
|
faceBeautyData.cheekShortIntensity = faceBeauty.getCheekShortIntensity();
|
||||||
|
/* 小脸程度 */
|
||||||
|
faceBeautyData.cheekSmallIntensity = faceBeauty.getCheekSmallIntensity();
|
||||||
|
/* 瘦颧骨 */
|
||||||
|
faceBeautyData.cheekBonesIntensity = faceBeauty.getCheekBonesIntensity();
|
||||||
|
/* 瘦下颌骨 */
|
||||||
|
faceBeautyData.lowerJawIntensity = faceBeauty.getLowerJawIntensity();
|
||||||
|
/* 大眼程度 */
|
||||||
|
faceBeautyData.eyeEnlargingIntensity = faceBeauty.getEyeEnlargingIntensity();
|
||||||
|
/* 圆眼程度 */
|
||||||
|
faceBeautyData.eyeCircleIntensity = faceBeauty.getEyeCircleIntensity();
|
||||||
|
/* 下巴调整程度 */
|
||||||
|
faceBeautyData.chinIntensity = faceBeauty.getChinIntensity();
|
||||||
|
/* 额头调整程度 */
|
||||||
|
faceBeautyData.forHeadIntensity = faceBeauty.getForHeadIntensity();
|
||||||
|
/* 瘦鼻程度 */
|
||||||
|
faceBeautyData.noseIntensity = faceBeauty.getNoseIntensity();
|
||||||
|
/* 嘴巴调整程度 */
|
||||||
|
faceBeautyData.mouthIntensity = faceBeauty.getMouthIntensity();
|
||||||
|
/* 开眼角强度 */
|
||||||
|
faceBeautyData.canthusIntensity = faceBeauty.getCanthusIntensity();
|
||||||
|
/* 眼睛间距 */
|
||||||
|
faceBeautyData.eyeSpaceIntensity = faceBeauty.getEyeSpaceIntensity();
|
||||||
|
/* 眼睛角度 */
|
||||||
|
faceBeautyData.eyeRotateIntensity = faceBeauty.getEyeRotateIntensity();
|
||||||
|
/* 鼻子长度 */
|
||||||
|
faceBeautyData.longNoseIntensity = faceBeauty.getLongNoseIntensity();
|
||||||
|
/* 调节人中 */
|
||||||
|
faceBeautyData.philtrumIntensity = faceBeauty.getPhiltrumIntensity();
|
||||||
|
/* 微笑嘴角强度 */
|
||||||
|
faceBeautyData.smileIntensity = faceBeauty.getSmileIntensity();
|
||||||
|
/* 眉毛上下 */
|
||||||
|
faceBeautyData.browHeightIntensity = faceBeauty.getBrowHeightIntensity();
|
||||||
|
/* 眉毛间距 */
|
||||||
|
faceBeautyData.browSpaceIntensity = faceBeauty.getBrowSpaceIntensity();
|
||||||
|
|
||||||
|
/* 滤镜相关 */
|
||||||
|
if (filterList != null) {
|
||||||
|
for (FaceBeautyFilterBean filterBean:filterList) {
|
||||||
|
faceBeautyData.filterMap.put(filterBean.getKey(),filterBean.getIntensity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 滤镜名称 */
|
||||||
|
faceBeautyData.filterName = faceBeauty.getFilterName();
|
||||||
|
/* 滤镜强度 */
|
||||||
|
faceBeautyData.filterIntensity = faceBeauty.getFilterIntensity();
|
||||||
|
|
||||||
|
/* 是否开启风格 */
|
||||||
|
faceBeautyData.styleTypeIndex = styleTypeIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将FaceBeauty 转 FaceBeautyData
|
||||||
|
*
|
||||||
|
* @param faceBeautyData
|
||||||
|
*/
|
||||||
|
public static boolean setFaceBeauty(FaceBeautyData faceBeautyData ,FaceBeauty faceBeauty) {
|
||||||
|
if (faceBeautyData == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (faceBeauty != null) {
|
||||||
|
/* 如果用户开启了风格推荐 */
|
||||||
|
//下面是否则
|
||||||
|
/* 美肤 */
|
||||||
|
/* 磨皮类型 */
|
||||||
|
if (faceBeautyData.blurType != faceBeauty.getBlurType())
|
||||||
|
faceBeauty.setBlurType(faceBeautyData.blurType);
|
||||||
|
/* 磨皮程度 */
|
||||||
|
if (faceBeautyData.blurIntensity != faceBeauty.getBlurIntensity())
|
||||||
|
faceBeauty.setBlurIntensity(faceBeautyData.blurIntensity);
|
||||||
|
/* 美白程度 */
|
||||||
|
if (faceBeautyData.colorIntensity != faceBeauty.getColorIntensity())
|
||||||
|
faceBeauty.setColorIntensity(faceBeautyData.colorIntensity);
|
||||||
|
/* 红润程度 */
|
||||||
|
if (faceBeautyData.redIntensity != faceBeauty.getRedIntensity())
|
||||||
|
faceBeauty.setRedIntensity(faceBeautyData.redIntensity);
|
||||||
|
/* 锐化程度 */
|
||||||
|
if (faceBeautyData.sharpenIntensity != faceBeauty.getSharpenIntensity())
|
||||||
|
faceBeauty.setSharpenIntensity(faceBeautyData.sharpenIntensity);
|
||||||
|
/* 亮眼程度 */
|
||||||
|
if (faceBeautyData.eyeBrightIntensity != faceBeauty.getEyeBrightIntensity())
|
||||||
|
faceBeauty.setEyeBrightIntensity(faceBeautyData.eyeBrightIntensity);
|
||||||
|
/* 美牙程度 */
|
||||||
|
if (faceBeautyData.toothIntensity != faceBeauty.getToothIntensity())
|
||||||
|
faceBeauty.setToothIntensity(faceBeautyData.toothIntensity);
|
||||||
|
/* 去黑眼圈强度*/
|
||||||
|
if (faceBeautyData.removePouchIntensity != faceBeauty.getRemovePouchIntensity())
|
||||||
|
faceBeauty.setRemovePouchIntensity(faceBeautyData.removePouchIntensity);
|
||||||
|
/* 去法令纹强度*/
|
||||||
|
if (faceBeautyData.removeLawPatternIntensity != faceBeauty.getRemoveLawPatternIntensity())
|
||||||
|
faceBeauty.setRemoveLawPatternIntensity(faceBeautyData.removeLawPatternIntensity);
|
||||||
|
|
||||||
|
/* 美型 */
|
||||||
|
/* 瘦脸程度 */
|
||||||
|
if (faceBeautyData.cheekThinningIntensity != faceBeauty.getCheekThinningIntensity())
|
||||||
|
faceBeauty.setCheekThinningIntensity(faceBeautyData.cheekThinningIntensity);
|
||||||
|
/* V脸程度 */
|
||||||
|
if (faceBeautyData.cheekVIntensity != faceBeauty.getCheekVIntensity())
|
||||||
|
faceBeauty.setCheekVIntensity(faceBeautyData.cheekVIntensity);
|
||||||
|
/* 窄脸程度 */
|
||||||
|
/* V脸程度 */
|
||||||
|
if (faceBeautyData.cheekNarrowIntensity != faceBeauty.getCheekNarrowIntensity())
|
||||||
|
faceBeauty.setCheekNarrowIntensity(faceBeautyData.cheekNarrowIntensity);
|
||||||
|
/* 短脸程度 */
|
||||||
|
if (faceBeautyData.cheekShortIntensity != faceBeauty.getCheekShortIntensity())
|
||||||
|
faceBeauty.setCheekShortIntensity(faceBeautyData.cheekShortIntensity);
|
||||||
|
/* 小脸程度 */
|
||||||
|
if (faceBeautyData.cheekSmallIntensity != faceBeauty.getCheekSmallIntensity())
|
||||||
|
faceBeauty.setCheekSmallIntensity(faceBeautyData.cheekSmallIntensity);
|
||||||
|
/* 瘦颧骨 */
|
||||||
|
if (faceBeautyData.cheekBonesIntensity != faceBeauty.getCheekBonesIntensity())
|
||||||
|
faceBeauty.setCheekBonesIntensity(faceBeautyData.cheekBonesIntensity);
|
||||||
|
/* 瘦下颌骨 */
|
||||||
|
if (faceBeautyData.lowerJawIntensity != faceBeauty.getLowerJawIntensity())
|
||||||
|
faceBeauty.setLowerJawIntensity(faceBeautyData.lowerJawIntensity);
|
||||||
|
/* 大眼程度 */
|
||||||
|
if (faceBeautyData.eyeEnlargingIntensity != faceBeauty.getEyeEnlargingIntensity())
|
||||||
|
faceBeauty.setEyeEnlargingIntensity(faceBeautyData.eyeEnlargingIntensity);
|
||||||
|
/* 圆眼程度 */
|
||||||
|
if (faceBeautyData.eyeCircleIntensity != faceBeauty.getEyeCircleIntensity())
|
||||||
|
faceBeauty.setEyeCircleIntensity(faceBeautyData.eyeCircleIntensity);
|
||||||
|
/* 下巴调整程度 */
|
||||||
|
if (faceBeautyData.chinIntensity != faceBeauty.getChinIntensity())
|
||||||
|
faceBeauty.setChinIntensity(faceBeautyData.chinIntensity);
|
||||||
|
/* 额头调整程度 */
|
||||||
|
if (faceBeautyData.forHeadIntensity != faceBeauty.getForHeadIntensity())
|
||||||
|
faceBeauty.setForHeadIntensity(faceBeautyData.forHeadIntensity);
|
||||||
|
/* 瘦鼻程度 */
|
||||||
|
if (faceBeautyData.noseIntensity != faceBeauty.getNoseIntensity())
|
||||||
|
faceBeauty.setNoseIntensity(faceBeautyData.noseIntensity);
|
||||||
|
/* 嘴巴调整程度 */
|
||||||
|
if (faceBeautyData.mouthIntensity != faceBeauty.getMouthIntensity())
|
||||||
|
faceBeauty.setMouthIntensity(faceBeautyData.mouthIntensity);
|
||||||
|
/* 开眼角强度 */
|
||||||
|
if (faceBeautyData.canthusIntensity != faceBeauty.getCanthusIntensity())
|
||||||
|
faceBeauty.setCanthusIntensity(faceBeautyData.canthusIntensity);
|
||||||
|
/* 眼睛间距 */
|
||||||
|
if (faceBeautyData.eyeSpaceIntensity != faceBeauty.getEyeSpaceIntensity())
|
||||||
|
faceBeauty.setEyeSpaceIntensity(faceBeautyData.eyeSpaceIntensity);
|
||||||
|
/* 眼睛角度 */
|
||||||
|
if (faceBeautyData.eyeRotateIntensity != faceBeauty.getEyeRotateIntensity())
|
||||||
|
faceBeauty.setEyeRotateIntensity(faceBeautyData.eyeRotateIntensity);
|
||||||
|
/* 鼻子长度 */
|
||||||
|
if (faceBeautyData.longNoseIntensity != faceBeauty.getLongNoseIntensity())
|
||||||
|
faceBeauty.setLongNoseIntensity(faceBeautyData.longNoseIntensity);
|
||||||
|
/* 调节人中 */
|
||||||
|
if (faceBeautyData.philtrumIntensity != faceBeauty.getPhiltrumIntensity())
|
||||||
|
faceBeauty.setPhiltrumIntensity(faceBeautyData.philtrumIntensity);
|
||||||
|
/* 微笑嘴角强度 */
|
||||||
|
if (faceBeautyData.smileIntensity != faceBeauty.getSmileIntensity())
|
||||||
|
faceBeauty.setSmileIntensity(faceBeautyData.smileIntensity);
|
||||||
|
/* 眉毛上下 */
|
||||||
|
if (faceBeautyData.browHeightIntensity != faceBeauty.getBrowHeightIntensity())
|
||||||
|
faceBeauty.setBrowHeightIntensity(faceBeautyData.browHeightIntensity);
|
||||||
|
/* 眉毛间距 */
|
||||||
|
if (faceBeautyData.browSpaceIntensity != faceBeauty.getBrowSpaceIntensity())
|
||||||
|
faceBeauty.setBrowSpaceIntensity(faceBeautyData.browSpaceIntensity);
|
||||||
|
|
||||||
|
/* 滤镜相关 */
|
||||||
|
/* 滤镜名称 */
|
||||||
|
if (!faceBeautyData.filterName.equals(faceBeauty.getFilterName()))
|
||||||
|
faceBeauty.setFilterName(faceBeautyData.filterName);
|
||||||
|
if (faceBeautyData.filterIntensity != faceBeauty.getFilterIntensity())
|
||||||
|
faceBeauty.setFilterIntensity(faceBeautyData.filterIntensity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将FaceBeautyData保存到文件
|
||||||
|
*
|
||||||
|
* @param faceBeautyData
|
||||||
|
*/
|
||||||
|
public static void saveFaceBeautyData2File(FaceBeautyData faceBeautyData, FaceBeauty faceBeauty, ArrayList<FaceBeautyFilterBean> filterList, int styleTypeIndex) {
|
||||||
|
buildFaceBeautyData(faceBeautyData,faceBeauty,filterList,styleTypeIndex);
|
||||||
|
saveFaceBeautyData2File(faceBeautyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将FaceBeautyData保存到文件
|
||||||
|
*
|
||||||
|
* @param faceBeautyData
|
||||||
|
*/
|
||||||
|
public static void saveFaceBeautyData2File(FaceBeautyData faceBeautyData) {
|
||||||
|
Gson gson = new Gson();
|
||||||
|
String faceBeautyString = gson.toJson(faceBeautyData);
|
||||||
|
saveToSp(SP_KEY_NAME, faceBeautyString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取bean对象
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static FaceBeautyData loadFaceBeautyData() {
|
||||||
|
String faceBeautyData = loadFormSp(SP_KEY_NAME);
|
||||||
|
if (faceBeautyData != null && !faceBeautyData.isEmpty()) {
|
||||||
|
Gson gson = new Gson();
|
||||||
|
FaceBeautyData faceBeautyDataBean = gson.fromJson(faceBeautyData, FaceBeautyData.class);
|
||||||
|
return faceBeautyDataBean;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void saveToSp(String key, String value) {
|
||||||
|
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||||
|
sp.edit().putString(key, value).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String loadFormSp(String key) {
|
||||||
|
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
|
||||||
|
return sp.getString(key, "");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.yunbao.faceunity.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class FaceUnityData {
|
||||||
|
public static Context mApplication;
|
||||||
|
}
|
@ -0,0 +1,580 @@
|
|||||||
|
package com.yunbao.faceunity.utils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.ImageFormat;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.YuvImage;
|
||||||
|
import android.media.ExifInterface;
|
||||||
|
import android.media.MediaMetadataRetriever;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DESC:
|
||||||
|
* Created on 2021/3/12
|
||||||
|
*/
|
||||||
|
public class FileUtils {
|
||||||
|
public static final String DCIM_FILE_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath();
|
||||||
|
public static final String photoFilePath;
|
||||||
|
public static final String videoFilePath;
|
||||||
|
public static final String exportVideoDir;
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (Build.FINGERPRINT.contains("Flyme")
|
||||||
|
|| Pattern.compile("Flyme", Pattern.CASE_INSENSITIVE).matcher(Build.DISPLAY).find()
|
||||||
|
|| Build.MANUFACTURER.contains("Meizu")
|
||||||
|
|| Build.MANUFACTURER.contains("MeiZu")) {
|
||||||
|
photoFilePath = DCIM_FILE_PATH + File.separator + "Camera" + File.separator;
|
||||||
|
videoFilePath = DCIM_FILE_PATH + File.separator + "Video" + File.separator;
|
||||||
|
} else if (Build.FINGERPRINT.contains("vivo")
|
||||||
|
|| Pattern.compile("vivo", Pattern.CASE_INSENSITIVE).matcher(Build.DISPLAY).find()
|
||||||
|
|| Build.MANUFACTURER.contains("vivo")
|
||||||
|
|| Build.MANUFACTURER.contains("Vivo")) {
|
||||||
|
photoFilePath = videoFilePath = Environment.getExternalStoragePublicDirectory("") + File.separator + "相机" + File.separator;
|
||||||
|
} else {
|
||||||
|
photoFilePath = videoFilePath = DCIM_FILE_PATH + File.separator + "Camera" + File.separator;
|
||||||
|
}
|
||||||
|
exportVideoDir = DCIM_FILE_PATH + File.separator + "FaceUnity" + File.separator;
|
||||||
|
createFileDir(photoFilePath);
|
||||||
|
createFileDir(videoFilePath);
|
||||||
|
createFileDir(exportVideoDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String IMAGE_FORMAT_JPG = ".jpg";
|
||||||
|
public static final String IMAGE_FORMAT_JPEG = ".jpeg";
|
||||||
|
public static final String IMAGE_FORMAT_PNG = ".png";
|
||||||
|
public static final String VIDEO_FORMAT_MP4 = ".mp4";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建文件夹
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
*/
|
||||||
|
public static void createFileDir(String path) {
|
||||||
|
File dir = new File(path);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkdirs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用外部文件目录
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static File getExternalFileDir(Context context) {
|
||||||
|
File fileDir = context.getExternalFilesDir(null);
|
||||||
|
if (fileDir == null) {
|
||||||
|
fileDir = context.getFilesDir();
|
||||||
|
}
|
||||||
|
return fileDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用下缓存文件目录
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static File getCacheFileDir(Context context) {
|
||||||
|
File fileDir = context.getCacheDir();
|
||||||
|
if (fileDir == null) {
|
||||||
|
fileDir = context.getFilesDir();
|
||||||
|
}
|
||||||
|
return fileDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前时间日期
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getDateTimeString() {
|
||||||
|
GregorianCalendar now = new GregorianCalendar();
|
||||||
|
return new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.US).format(now.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取视频缓存文件
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @return File
|
||||||
|
*/
|
||||||
|
public static File getCacheVideoFile(Context context) {
|
||||||
|
File fileDir = new File(getExternalFileDir(context).getPath() + File.separator + "video");
|
||||||
|
if (!fileDir.exists()) {
|
||||||
|
fileDir.mkdirs();
|
||||||
|
}
|
||||||
|
File file = new File(fileDir, getCurrentVideoFileName());
|
||||||
|
if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造视频文件名称
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getCurrentVideoFileName() {
|
||||||
|
return getDateTimeString() + VIDEO_FORMAT_MP4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造图片文件名称
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getCurrentPhotoFileName() {
|
||||||
|
return getDateTimeString() + IMAGE_FORMAT_JPG;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitmap保存到本地
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param bitmap Bitmap
|
||||||
|
* @return String?
|
||||||
|
*/
|
||||||
|
public static String addBitmapToExternal(Context context, Bitmap bitmap) {
|
||||||
|
if (bitmap == null) return null;
|
||||||
|
File fileDir = new File(getExternalFileDir(context).getPath() + File.separator + "photo");
|
||||||
|
if (!fileDir.exists()) {
|
||||||
|
fileDir.mkdirs();
|
||||||
|
}
|
||||||
|
File file = new File(fileDir, getCurrentPhotoFileName());
|
||||||
|
if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FileOutputStream fos = new FileOutputStream(file);
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
return file.getAbsolutePath();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将Bitmap文件保存到相册
|
||||||
|
*
|
||||||
|
* @param bitmap Bitmap
|
||||||
|
*/
|
||||||
|
public static String addBitmapToAlbum(Context context, Bitmap bitmap) {
|
||||||
|
if (bitmap == null) return null;
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
File dcimFile;
|
||||||
|
|
||||||
|
File fileDir = new File(exportVideoDir);
|
||||||
|
if (fileDir.exists()) {
|
||||||
|
dcimFile = new File(exportVideoDir, getCurrentPhotoFileName());
|
||||||
|
} else {
|
||||||
|
dcimFile = new File(photoFilePath, getCurrentPhotoFileName());
|
||||||
|
}
|
||||||
|
if (dcimFile.exists()) {
|
||||||
|
dcimFile.delete();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fos = new FileOutputStream(dcimFile);
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
|
||||||
|
fos.flush();
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
if (fos != null) {
|
||||||
|
try {
|
||||||
|
fos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(dcimFile)));
|
||||||
|
return dcimFile.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将视频文件保存到相册
|
||||||
|
*
|
||||||
|
* @param videoFile File
|
||||||
|
* @return Uri?
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static String addVideoToAlbum(Context context, File videoFile) {
|
||||||
|
if (videoFile == null) return null;
|
||||||
|
File fileDir = new File(exportVideoDir);
|
||||||
|
File dcimFile;
|
||||||
|
if (fileDir.exists()) {
|
||||||
|
dcimFile = new File(exportVideoDir, getCurrentVideoFileName());
|
||||||
|
} else {
|
||||||
|
dcimFile = new File(videoFilePath, getCurrentVideoFileName());
|
||||||
|
}
|
||||||
|
if (dcimFile.exists()) {
|
||||||
|
dcimFile.delete();
|
||||||
|
}
|
||||||
|
BufferedInputStream bis = null;
|
||||||
|
BufferedOutputStream bos = null;
|
||||||
|
try {
|
||||||
|
bis = new BufferedInputStream(new FileInputStream(videoFile));
|
||||||
|
bos = new BufferedOutputStream(new FileOutputStream(dcimFile));
|
||||||
|
byte[] bytes = new byte[1024 * 10];
|
||||||
|
int length;
|
||||||
|
while ((length = bis.read(bytes)) != -1) {
|
||||||
|
bos.write(bytes, 0, length);
|
||||||
|
}
|
||||||
|
bos.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
if (bis != null) {
|
||||||
|
try {
|
||||||
|
bis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bos != null) {
|
||||||
|
try {
|
||||||
|
bos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(dcimFile)));
|
||||||
|
return dcimFile.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将Assets文件拷贝到应用作用域存储
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param assetsPath String
|
||||||
|
* @param fileName String
|
||||||
|
*/
|
||||||
|
public static String copyAssetsToExternalFilesDir(Context context, String assetsPath, String fileName) {
|
||||||
|
File fileDir = new File(getExternalFileDir(context).getPath() + File.separator + "assets");
|
||||||
|
if (!fileDir.exists()) {
|
||||||
|
fileDir.mkdirs();
|
||||||
|
}
|
||||||
|
File file = new File(fileDir, fileName);
|
||||||
|
if (file.exists()) {
|
||||||
|
return file.getAbsolutePath();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
InputStream inputStream = context.getAssets().open(assetsPath);
|
||||||
|
FileOutputStream fos = new FileOutputStream(file);
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(inputStream);
|
||||||
|
BufferedOutputStream bos = new BufferedOutputStream(fos);
|
||||||
|
byte[] byteArray = new byte[1024];
|
||||||
|
int bytes = bis.read(byteArray);
|
||||||
|
while (bytes > 0) {
|
||||||
|
bos.write(byteArray, 0, bytes);
|
||||||
|
bos.flush();
|
||||||
|
bytes = bis.read(byteArray);
|
||||||
|
}
|
||||||
|
bos.close();
|
||||||
|
fos.close();
|
||||||
|
return file.getAbsolutePath();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Uri文件绝对路径
|
||||||
|
*
|
||||||
|
* @param context: Context
|
||||||
|
* @param uri Uri
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String getFilePathByUri(Context context, Uri uri) {
|
||||||
|
if (uri == null) return null;
|
||||||
|
return Uri2PathUtil.getRealPathFromUri(context, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
|
||||||
|
Cursor cursor = null;
|
||||||
|
String[] projection = new String[]{MediaStore.Images.Media.DATA};
|
||||||
|
try {
|
||||||
|
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
int index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
|
||||||
|
return cursor.getString(index);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load本地图片
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @param screenWidth
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap loadBitmapFromExternal(String path, int screenWidth) {
|
||||||
|
BitmapFactory.Options opt = new BitmapFactory.Options();
|
||||||
|
opt.inJustDecodeBounds = true;
|
||||||
|
BitmapFactory.decodeFile(path, opt);
|
||||||
|
int picWidth = opt.outWidth;
|
||||||
|
int picHeight = opt.outHeight;
|
||||||
|
opt.inSampleSize = 1;
|
||||||
|
// 根据屏的大小和图片大小计算出缩放比例
|
||||||
|
if (picWidth > picHeight) {
|
||||||
|
if (picHeight > screenWidth) {
|
||||||
|
opt.inSampleSize = picHeight / screenWidth;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (picWidth > screenWidth) {
|
||||||
|
opt.inSampleSize = picWidth / screenWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt.inJustDecodeBounds = false;
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeFile(path, opt);
|
||||||
|
int orientation = getPhotoOrientation(path);
|
||||||
|
bitmap = rotateBitmap(bitmap, orientation);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load本地图片
|
||||||
|
*
|
||||||
|
* @param path String
|
||||||
|
* @param screenWidth Int
|
||||||
|
* @param screenHeight Int
|
||||||
|
* @return Bitmap
|
||||||
|
*/
|
||||||
|
public static Bitmap loadBitmapFromExternal(String path, int screenWidth, int screenHeight) {
|
||||||
|
BitmapFactory.Options opt = new BitmapFactory.Options();
|
||||||
|
opt.inJustDecodeBounds = true;
|
||||||
|
BitmapFactory.decodeFile(path, opt);
|
||||||
|
int picWidth = opt.outWidth;
|
||||||
|
int picHeight = opt.outHeight;
|
||||||
|
int inSampleSize = 1;
|
||||||
|
// 根据屏的大小和图片大小计算出缩放比例
|
||||||
|
if (picHeight > screenHeight || picWidth > screenWidth) {
|
||||||
|
int halfHeight = picHeight / 2;
|
||||||
|
int halfWidth = picWidth / 2;
|
||||||
|
while (halfHeight / inSampleSize >= screenHeight && halfWidth / inSampleSize >= screenWidth) {
|
||||||
|
inSampleSize *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt.inSampleSize = inSampleSize;
|
||||||
|
opt.inJustDecodeBounds = false;
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeFile(path, opt);
|
||||||
|
int orientation = getPhotoOrientation(path);
|
||||||
|
bitmap = rotateBitmap(bitmap, orientation);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 旋转 Bitmap
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
* @param orientation
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {
|
||||||
|
if (orientation == 90 || orientation == 180 || orientation == 270) {
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.postRotate((float) orientation);
|
||||||
|
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||||
|
}
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图片的方向
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int getPhotoOrientation(String path) {
|
||||||
|
int orientation = 0;
|
||||||
|
int tagOrientation = 0;
|
||||||
|
try {
|
||||||
|
tagOrientation = new ExifInterface(path).getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
switch (tagOrientation) {
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
|
orientation = 90;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
|
orientation = 180;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
orientation = 270;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选中图片
|
||||||
|
*
|
||||||
|
* @param activity Activity
|
||||||
|
*/
|
||||||
|
public static void pickImageFile(Activity activity, int requestCode) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
|
intent.setType("image/*");
|
||||||
|
activity.startActivityForResult(intent, requestCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选中视频
|
||||||
|
*
|
||||||
|
* @param activity Activity
|
||||||
|
* 回调可参考下方
|
||||||
|
*/
|
||||||
|
public static void pickVideoFile(Activity activity, int requestCode) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
|
intent.setType("video/*");
|
||||||
|
activity.startActivityForResult(intent, requestCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据路径获取InputStream
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param path String
|
||||||
|
* @return InputStream?
|
||||||
|
*/
|
||||||
|
public static InputStream readInputStreamByPath(Context context, String path) {
|
||||||
|
if (path == null || path.trim().length() == 0)
|
||||||
|
return null;
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = context.getAssets().open(path);
|
||||||
|
} catch (IOException e1) {
|
||||||
|
try {
|
||||||
|
inputStream = new FileInputStream(path);
|
||||||
|
} catch (IOException e2) {
|
||||||
|
e2.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 相机byte转bitmap
|
||||||
|
*
|
||||||
|
* @param buffer
|
||||||
|
* @param width
|
||||||
|
* @param height
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap bytes2Bitmap(byte[] buffer, int width, int height) {
|
||||||
|
YuvImage yuvimage = new YuvImage(buffer, ImageFormat.NV21, width, height, null);//20、20分别是图的宽度与高度
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
yuvimage.compressToJpeg(new Rect(0, 0, width, height), 80, baos);//80--JPG图片的质量[0-100],100最高
|
||||||
|
byte[] jdata = baos.toByteArray();
|
||||||
|
return BitmapFactory.decodeByteArray(baos.toByteArray(), 0, jdata.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历一个文件夹获取改文件夹下所有文件名
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ArrayList<String> getFileList(String path) {
|
||||||
|
ArrayList<String> fileList = new ArrayList<>();
|
||||||
|
File dir = new File(path);
|
||||||
|
// 该文件目录下文件全部放入数组
|
||||||
|
File[] files = dir.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
// 判断是文件还是文件夹
|
||||||
|
if (files[i].isDirectory()) {
|
||||||
|
// 获取文件绝对路径
|
||||||
|
getFileList(files[i].getAbsolutePath());
|
||||||
|
// 判断文件名是否以.jpg结尾
|
||||||
|
} else {
|
||||||
|
fileList.add(files[i].getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验文件是否是图片
|
||||||
|
*
|
||||||
|
* @param path String
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public static Boolean checkIsImage(String path) {
|
||||||
|
String name = new File(path).getName().toLowerCase();
|
||||||
|
return (name.endsWith(IMAGE_FORMAT_PNG) || name.endsWith(IMAGE_FORMAT_JPG)
|
||||||
|
|| name.endsWith(IMAGE_FORMAT_JPEG));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验文件是否是视频
|
||||||
|
*
|
||||||
|
* @param path String
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public static Boolean checkIsVideo(Context context,String path) {
|
||||||
|
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||||
|
try {
|
||||||
|
retriever.setDataSource(context, Uri.fromFile(new File(path)));
|
||||||
|
String hasVideo = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO);
|
||||||
|
return "yes".equals(hasVideo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,161 @@
|
|||||||
|
package com.yunbao.faceunity.utils;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.provider.DocumentsContract;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
|
||||||
|
import androidx.loader.content.CursorLoader;
|
||||||
|
|
||||||
|
public class Uri2PathUtil {
|
||||||
|
|
||||||
|
//复杂版处理 (适配多种API)
|
||||||
|
public static String getRealPathFromUri(Context context, Uri uri) {
|
||||||
|
int sdkVersion = Build.VERSION.SDK_INT;
|
||||||
|
if (sdkVersion < 11) return getRealPathFromUri_BelowApi11(context, uri);
|
||||||
|
if (sdkVersion < 19) return getRealPathFromUri_Api11To18(context, uri);
|
||||||
|
else return getRealPathFromUri_AboveApi19(context, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 适配api19以上,根据uri获取图片的绝对路径
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||||
|
private static String getRealPathFromUri_AboveApi19(Context context, Uri uri) {
|
||||||
|
if (DocumentsContract.isDocumentUri(context, uri)) {
|
||||||
|
if (isExternalStorageDocument(uri)) {
|
||||||
|
final String docId = DocumentsContract.getDocumentId(uri);
|
||||||
|
final String[] split = docId.split(":");
|
||||||
|
final String type = split[0];
|
||||||
|
if ("primary".equalsIgnoreCase(type)) {
|
||||||
|
return Environment.getExternalStorageDirectory() + "/" + split[1];
|
||||||
|
}
|
||||||
|
} else if (isDownloadsDocument(uri)) {
|
||||||
|
final String id = DocumentsContract.getDocumentId(uri);
|
||||||
|
final Uri contentUri = ContentUris.withAppendedId(
|
||||||
|
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
|
||||||
|
|
||||||
|
return getDataColumn(context, contentUri, null, null);
|
||||||
|
} else if (isMediaDocument(uri)) {
|
||||||
|
final String docId = DocumentsContract.getDocumentId(uri);
|
||||||
|
final String[] split = docId.split(":");
|
||||||
|
final String type = split[0];
|
||||||
|
|
||||||
|
Uri contentUri;
|
||||||
|
if ("image".equals(type)) {
|
||||||
|
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
} else if ("video".equals(type)) {
|
||||||
|
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
} else if ("audio".equals(type)) {
|
||||||
|
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
} else {
|
||||||
|
contentUri = MediaStore.Files.getContentUri("external");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String selection = "_id=?";
|
||||||
|
final String[] selectionArgs = new String[]{split[1]};
|
||||||
|
return getDataColumn(context, contentUri, selection, selectionArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
|
||||||
|
return getDataColumn(context, uri, null, null);
|
||||||
|
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||||
|
return uri.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 适配api11-api18,根据uri获取图片的绝对路径
|
||||||
|
*/
|
||||||
|
private static String getRealPathFromUri_Api11To18(Context context, Uri uri) {
|
||||||
|
String filePath = null;
|
||||||
|
String[] projection = {MediaStore.Images.Media.DATA};
|
||||||
|
//这个有两个包不知道是哪个。。。。不过这个复杂版一般用不到
|
||||||
|
CursorLoader loader = new CursorLoader(context, uri, projection, null, null, null);
|
||||||
|
Cursor cursor = loader.loadInBackground();
|
||||||
|
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.moveToFirst();
|
||||||
|
filePath = cursor.getString(cursor.getColumnIndex(projection[0]));
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 适配api11以下(不包括api11),根据uri获取图片的绝对路径
|
||||||
|
*/
|
||||||
|
private static String getRealPathFromUri_BelowApi11(Context context, Uri uri) {
|
||||||
|
String filePath = null;
|
||||||
|
String[] projection = {MediaStore.Images.Media.DATA};
|
||||||
|
Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
filePath = cursor.getString(cursor.getColumnIndex(projection[0]));
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the data column for this Uri. This is useful for
|
||||||
|
* MediaStore Uris, and other file-based ContentProviders.
|
||||||
|
*
|
||||||
|
* @param context The context.
|
||||||
|
* @param uri The Uri to query.
|
||||||
|
* @param selection (Optional) Filter used in the query.
|
||||||
|
* @param selectionArgs (Optional) Selection arguments used in the query.
|
||||||
|
* @return The value of the _data column, which is typically a file path.
|
||||||
|
*/
|
||||||
|
public static String getDataColumn(Context context, Uri uri, String selection,
|
||||||
|
String[] selectionArgs) {
|
||||||
|
Cursor cursor = null;
|
||||||
|
String column = MediaStore.MediaColumns.DATA;
|
||||||
|
String[] projection = {column};
|
||||||
|
try {
|
||||||
|
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
|
||||||
|
null);
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
int column_index = cursor.getColumnIndexOrThrow(column);
|
||||||
|
return cursor.getString(column_index);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (cursor != null)
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uri The Uri to check.
|
||||||
|
* @return Whether the Uri authority is ExternalStorageProvider.
|
||||||
|
*/
|
||||||
|
public static boolean isExternalStorageDocument(Uri uri) {
|
||||||
|
return "com.android.externalstorage.documents".equals(uri.getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uri The Uri to check.
|
||||||
|
* @return Whether the Uri authority is DownloadsProvider.
|
||||||
|
*/
|
||||||
|
public static boolean isDownloadsDocument(Uri uri) {
|
||||||
|
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uri The Uri to check.
|
||||||
|
* @return Whether the Uri authority is MediaProvider.
|
||||||
|
*/
|
||||||
|
public static boolean isMediaDocument(Uri uri) {
|
||||||
|
return "com.android.providers.media.documents".equals(uri.getAuthority());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_1_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_1_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_2_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_2_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_3_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_3_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_4_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_4_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_5_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_5_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_6_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_6_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_7_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_7_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_none_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_beauty_box_style_none_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_color_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_color_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_safe_area_close_normal" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_safe_area_close_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_safe_area_open_normal" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_safe_area_open_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_similarityr_close_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_similarityr_close_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_similarityr_open_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_similarityr_open_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_smooth_close_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_smooth_close_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_smooth_open_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_smooth_open_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_transparency_close_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_transparency_close_normal" />
|
||||||
|
</selector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@mipmap/icon_green_transparency_open_checked" android:state_selected="true" />
|
||||||
|
<item android:drawable="@mipmap/icon_green_transparency_open_normal" />
|
||||||
|
</selector>
|
64
FaceUnity/src/main/res/layout/layout_animo_control.xml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/lyt_bottom"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/x266"
|
||||||
|
android:background="@color/primary_list"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/x167"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:background="@color/primary_list"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="none" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/x1"
|
||||||
|
android:background="@color/divider_line_color" />
|
||||||
|
|
||||||
|
<com.yunbao.faceunity.checkbox.CheckGroup
|
||||||
|
android:id="@+id/rg_anim"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/x98"
|
||||||
|
android:background="@color/primary_list">
|
||||||
|
|
||||||
|
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
||||||
|
android:id="@+id/cb_animoji"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@color/transparent"
|
||||||
|
android:button="@null"
|
||||||
|
android:checked="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/animoji_filter"
|
||||||
|
android:textColor="@color/bottom_radio_color"
|
||||||
|
android:textSize="@dimen/text_size_26" />
|
||||||
|
|
||||||
|
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
||||||
|
android:id="@+id/cb_filter"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@color/transparent"
|
||||||
|
android:button="@null"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/cartoon_filter"
|
||||||
|
android:textColor="@color/bottom_radio_color"
|
||||||
|
android:textSize="@dimen/text_size_26" />
|
||||||
|
|
||||||
|
</com.yunbao.faceunity.checkbox.CheckGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -2,30 +2,15 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/cyt_main"
|
android:id="@+id/cyt_main"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/switch_compat"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/x20"
|
|
||||||
android:layout_marginBottom="@dimen/x20"
|
|
||||||
android:checked="true"
|
|
||||||
android:theme="@style/SwitchCompat"
|
|
||||||
android:layout_marginStart="@dimen/x10" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/x268"
|
android:layout_height="@dimen/x268"
|
||||||
android:background="#BD050F14"
|
android:background="#BD050F14"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
<com.yunbao.faceunity.seekbar.DiscreteSeekBar
|
<com.yunbao.faceunity.seekbar.DiscreteSeekBar
|
||||||
android:id="@+id/seek_bar"
|
android:id="@+id/beauty_seek_bar"
|
||||||
android:layout_width="@dimen/x528"
|
android:layout_width="@dimen/x528"
|
||||||
android:layout_height="@dimen/x48"
|
android:layout_height="@dimen/x48"
|
||||||
android:layout_marginTop="@dimen/x24"
|
android:layout_marginTop="@dimen/x24"
|
||||||
@ -44,6 +29,7 @@
|
|||||||
app:dsb_trackHeight="@dimen/x4"
|
app:dsb_trackHeight="@dimen/x4"
|
||||||
app:dsb_value="0" />
|
app:dsb_value="0" />
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/x180"
|
android:layout_height="@dimen/x180"
|
||||||
@ -92,7 +78,4 @@
|
|||||||
android:layout_height="@dimen/x180" />
|
android:layout_height="@dimen/x180" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -2,20 +2,33 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/x472"
|
||||||
android:gravity="bottom"
|
android:gravity="bottom"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<com.yunbao.faceunity.widget.TouchStateImageView
|
||||||
android:id="@+id/switch_compat"
|
android:id="@+id/iv_compare"
|
||||||
|
android:layout_width="@dimen/x72"
|
||||||
|
android:layout_height="@dimen/x72"
|
||||||
|
android:layout_marginStart="@dimen/x34"
|
||||||
|
android:layout_marginBottom="@dimen/x34"
|
||||||
|
android:src="@mipmap/icon_beauty_face_contrast"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/iv_reset"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/x20"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_marginBottom="@dimen/x20"
|
android:layout_marginEnd="@dimen/x34"
|
||||||
android:checked="true"
|
android:text="去除效果"
|
||||||
android:theme="@style/SwitchCompat"
|
android:visibility="gone" />
|
||||||
android:layout_marginLeft="@dimen/x10" />
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/fyt_bottom_view"
|
android:id="@+id/fyt_bottom_view"
|
||||||
@ -25,7 +38,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.yunbao.faceunity.seekbar.DiscreteSeekBar
|
<com.yunbao.faceunity.seekbar.DiscreteSeekBar
|
||||||
android:id="@+id/seek_bar"
|
android:id="@+id/beauty_seek_bar"
|
||||||
android:layout_width="@dimen/x528"
|
android:layout_width="@dimen/x528"
|
||||||
android:layout_height="@dimen/x48"
|
android:layout_height="@dimen/x48"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
@ -45,6 +58,7 @@
|
|||||||
app:dsb_trackHeight="@dimen/x4"
|
app:dsb_trackHeight="@dimen/x4"
|
||||||
app:dsb_value="0" />
|
app:dsb_value="0" />
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/x180"
|
android:layout_height="@dimen/x180"
|
||||||
@ -70,14 +84,41 @@
|
|||||||
android:id="@+id/tv_beauty_recover"
|
android:id="@+id/tv_beauty_recover"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:layout_marginBottom="@dimen/x30"
|
android:layout_marginBottom="@dimen/x30"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:text="@string/recover"
|
android:text="@string/recover"
|
||||||
android:textColor="@color/tv_main_color_selector"
|
android:textColor="@color/tv_main_color_selector"
|
||||||
android:textSize="@dimen/text_size_20" />
|
android:textSize="@dimen/text_size_20" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/lyt_style_recover"
|
||||||
|
android:layout_width="@dimen/x132"
|
||||||
|
android:layout_height="@dimen/x180"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="@dimen/x88"
|
||||||
|
android:layout_height="@dimen/x88"
|
||||||
|
android:layout_marginBottom="@dimen/x18"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:src="@drawable/icon_beauty_style_none_selector" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="@dimen/x30"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="@string/beauty_face_style_none"
|
||||||
|
android:textColor="@color/tv_main_color_selector"
|
||||||
|
android:textSize="@dimen/text_size_20" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/iv_line"
|
android:id="@+id/iv_line"
|
||||||
android:layout_width="@dimen/x1"
|
android:layout_width="@dimen/x1"
|
||||||
@ -104,7 +145,7 @@
|
|||||||
android:id="@+id/beauty_radio_group"
|
android:id="@+id/beauty_radio_group"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/x98"
|
android:layout_height="@dimen/x98"
|
||||||
android:background="@color/primary_list"
|
android:background="#BD050F14"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
||||||
@ -117,7 +158,7 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/beauty_radio_skin_beauty"
|
android:text="@string/beauty_radio_skin_beauty"
|
||||||
android:textColor="@color/bottom_radio_color"
|
android:textColor="@color/bottom_radio_color"
|
||||||
android:textSize="@dimen/text_size_26"/>
|
android:textSize="@dimen/text_size_26" />
|
||||||
|
|
||||||
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
||||||
android:id="@+id/beauty_radio_face_shape"
|
android:id="@+id/beauty_radio_face_shape"
|
||||||
@ -129,7 +170,7 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/beauty_radio_face_shape"
|
android:text="@string/beauty_radio_face_shape"
|
||||||
android:textColor="@color/bottom_radio_color"
|
android:textColor="@color/bottom_radio_color"
|
||||||
android:textSize="@dimen/text_size_26"/>
|
android:textSize="@dimen/text_size_26" />
|
||||||
|
|
||||||
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
||||||
android:id="@+id/beauty_radio_filter"
|
android:id="@+id/beauty_radio_filter"
|
||||||
@ -142,5 +183,18 @@
|
|||||||
android:text="@string/beauty_radio_filter"
|
android:text="@string/beauty_radio_filter"
|
||||||
android:textColor="@color/bottom_radio_color"
|
android:textColor="@color/bottom_radio_color"
|
||||||
android:textSize="@dimen/text_size_26" />
|
android:textSize="@dimen/text_size_26" />
|
||||||
|
|
||||||
|
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
||||||
|
android:id="@+id/beauty_radio_style"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@color/transparent"
|
||||||
|
android:button="@null"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/beauty_radio_style"
|
||||||
|
android:textColor="@color/bottom_radio_color"
|
||||||
|
android:textSize="@dimen/text_size_26" />
|
||||||
|
|
||||||
</com.yunbao.faceunity.checkbox.CheckGroup>
|
</com.yunbao.faceunity.checkbox.CheckGroup>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -3,107 +3,41 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_faceunity_menu1"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/menu_group"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_faceunity_menu2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabItem
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom"
|
android:text="Monday" />
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabItem
|
||||||
|
android:layout_width="wrap_content"
|
||||||
<com.yunbao.faceunity.control.BodyBeautyControlView
|
|
||||||
android:id="@+id/control_body"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom"
|
android:text="Tuesday" />
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<com.yunbao.faceunity.control.FaceBeautyControlView
|
<com.google.android.material.tabs.TabItem
|
||||||
android:id="@+id/control_beauty"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom" />
|
android:text="Wednesday" />
|
||||||
|
</com.google.android.material.tabs.TabLayout>
|
||||||
<com.yunbao.faceunity.control.MakeupControlView
|
|
||||||
android:id="@+id/control_makeup"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<com.yunbao.faceunity.control.PropControlView
|
|
||||||
android:id="@+id/control_prop"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/line"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/x1"
|
|
||||||
android:background="@color/primary_list"
|
|
||||||
android:src="@color/divider_line_color" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.yunbao.faceunity.checkbox.CheckGroup
|
|
||||||
android:id="@+id/group_function"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/x98"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:background="@color/primary_list"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
|
||||||
android:id="@+id/radio_beauty"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@color/transparent"
|
|
||||||
android:button="@null"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/home_function_name_beauty"
|
|
||||||
android:textColor="@color/bottom_radio_color"
|
|
||||||
android:textSize="@dimen/text_size_26" />
|
|
||||||
|
|
||||||
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
|
||||||
android:id="@+id/radio_sticker"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@color/transparent"
|
|
||||||
android:button="@null"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/home_function_name_sticker"
|
|
||||||
android:textColor="@color/bottom_radio_color"
|
|
||||||
android:textSize="@dimen/text_size_26" />
|
|
||||||
|
|
||||||
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
|
||||||
android:id="@+id/radio_makeup"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@color/transparent"
|
|
||||||
android:button="@null"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/home_function_name_makeup"
|
|
||||||
android:textColor="@color/bottom_radio_color"
|
|
||||||
android:textSize="@dimen/text_size_26" />
|
|
||||||
|
|
||||||
<com.yunbao.faceunity.checkbox.CheckBoxCompat
|
|
||||||
android:id="@+id/radio_body"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@color/transparent"
|
|
||||||
android:button="@null"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/home_function_name_beauty_body"
|
|
||||||
android:textColor="@color/bottom_radio_color"
|
|
||||||
android:textSize="@dimen/text_size_26" />
|
|
||||||
|
|
||||||
</com.yunbao.faceunity.checkbox.CheckGroup>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/ico_home_animoji.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/ico_home_beauty.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/ico_home_beauty_body.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/ico_home_big_head.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/ico_home_fine_sticker.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/ico_home_makeup.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/ico_home_sticker.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_baihu.png
Normal file
After Width: | Height: | Size: 941 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_baimao.png
Normal file
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 442 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_douniuquan.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_frog_st.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_hashiqi.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_hetun.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_huangya.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_kaola.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_kuloutou.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_qgirl.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_animoji_wuxia.png
Normal file
After Width: | Height: | Size: 413 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_ar_baozi.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_ar_bluebird.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_ar_fenhudie.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_ar_lanhudie.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
FaceUnity/src/main/res/mipmap-xxhdpi/icon_ar_tiger.png
Normal file
After Width: | Height: | Size: 20 KiB |