补充美颜模型和美颜配置

This commit is contained in:
zlzw 2022-09-19 15:43:06 +08:00
parent 8ef917ebb6
commit c634d29e79
365 changed files with 5751 additions and 1296 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
/**
* DESCAnimoji业务工厂
* Created on 2021/3/3
*/
public class AnimojiDataFactory extends AbstractAnimojiDataFactory {
/*渲染控制器*/
private FURenderKit mFURenderKit = FURenderKit.getInstance();
private FUAIKit mFUAIKit = FUAIKit.getInstance();
/*3D抗锯齿*/
public final Antialiasing antialiasing;
/*动漫滤镜模型*/
public final AnimationFilter animationFilter;
/*当前选中贴图模型*/
private Prop currentAnimoji;
/*当前选中下标*/
private int currentAnimojiIndex;
/*当前滤镜下标*/
private int currentFilterIndex;
/*Animoji数据*/
private ArrayList<AnimojiBean> animojiBeans;
/*Animoji滤镜数据*/
private ArrayList<AnimationFilterBean> animationFilterBeans;
/**
* 构造 AnimojiDataFactory
*
* @param animojiIndex 贴图下标
* @param filterIndex 滤镜下标
*/
public AnimojiDataFactory(int animojiIndex, int filterIndex) {
antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING));
animationFilter = new AnimationFilter(new FUBundleData(FaceUnityConfig.BUNDLE_ANIMATION_FILTER));
currentAnimojiIndex = animojiIndex;
currentFilterIndex = filterIndex;
animojiBeans = AnimojiSource.buildAnimojis();
animationFilterBeans = AnimojiSource.buildFilters();
}
/**
* 动漫贴图列表
*
* @return
*/
@Override
public ArrayList<AnimojiBean> getAnimojis() {
return animojiBeans;
}
/**
* 动漫滤镜列表
*
* @return
*/
@Override
public ArrayList<AnimationFilterBean> getFilters() {
return animationFilterBeans;
}
/**
* 当前选中动漫贴图下标
*
* @return
*/
@Override
public int getCurrentAnimojiIndex() {
return currentAnimojiIndex;
}
/**
* 设置当前选中动漫贴图下标
*
* @return
*/
@Override
public void setCurrentAnimojiIndex(int currentAnimojiIndex) {
this.currentAnimojiIndex = currentAnimojiIndex;
}
/**
* 当前选中滤镜下标
*
* @return
*/
@Override
public int getCurrentFilterIndex() {
return currentFilterIndex;
}
/**
* 设置当前选中动漫贴图下标
*
* @return
*/
@Override
public void setCurrentFilterIndex(int currentFilterIndex) {
this.currentFilterIndex = currentFilterIndex;
}
/**
* 设置选中贴图
*
* @param bean
*/
@Override
public void onAnimojiSelected(AnimojiBean bean) {
PropContainer propContainer = mFURenderKit.getPropContainer();
String path = bean.getPath();
Prop prop = null;
if (path != null && path.trim().length() > 0) {
prop = new Animoji(new FUBundleData(path));
}
propContainer.replaceProp(currentAnimoji, prop);
currentAnimoji = prop;
}
/**
* 设置选中滤镜
*
* @param data
*/
@Override
public void onFilterSelected(AnimationFilterBean data) {
animationFilter.setStyle(data.getStyle());
}
/**
* FURenderKit加载当前特效
*/
public void bindCurrentRenderer() {
mFUAIKit.loadAIProcessor(FaceUnityConfig.BUNDLE_AI_TONGUE, FUAITypeEnum.FUAITYPE_TONGUETRACKING);
mFUAIKit.setMaxFaces(4);
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
mFURenderKit.setAntialiasing(antialiasing);
mFURenderKit.setAnimationFilter(animationFilter);
animationFilter.setStyle(animationFilterBeans.get(currentFilterIndex).getStyle());
onAnimojiSelected(animojiBeans.get(currentAnimojiIndex));
}
/**
* 结束需要释放AI驱动
*/
public void releaseAIProcessor() {
mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_TONGUETRACKING);
}
}

View File

@ -0,0 +1,158 @@
package com.yunbao.faceunity.data;
import com.faceunity.core.avatar.model.Avatar;
import com.faceunity.core.avatar.model.Scene;
import com.faceunity.core.avatar.scene.ProcessorConfig;
import com.faceunity.core.entity.FUBundleData;
import com.faceunity.core.entity.FUCoordinate3DData;
import com.faceunity.core.enumeration.FUAITypeEnum;
import com.faceunity.core.faceunity.FUAIKit;
import com.faceunity.core.faceunity.FURenderKit;
import com.faceunity.core.faceunity.FUSceneKit;
import com.faceunity.core.model.antialiasing.Antialiasing;
import com.yunbao.faceunity.entity.AvatarBean;
import com.yunbao.faceunity.infe.AbstractAvatarDataFactory;
import com.yunbao.faceunity.repo.AvatarSource;
import com.yunbao.faceunity.utils.FaceUnityConfig;
import java.util.ArrayList;
/**
* DESC
* Created on 2021/3/30
*/
public class AvatarDataFactory extends AbstractAvatarDataFactory {
/*渲染控制器*/
private FURenderKit mFURenderKit = FURenderKit.getInstance();
private FUAIKit mFUAIKit = FUAIKit.getInstance();
/*3D抗锯齿*/
public final Antialiasing antialiasing;
/* 人物队列 */
private ArrayList<AvatarBean> members;
/* 当前选中人物下标 */
private int currentMemberIndex;
/* 驱动类型是否为全身 */
private Boolean isHumanTrackSceneFull;
/* 场景 */
private Scene sceneModel;
/* 男孩对象 */
private Avatar boyAvatarModel;
/* 女孩对象 */
private Avatar girlAvatarModel;
/*当前对象*/
private Avatar currentAvatarModel;
public AvatarDataFactory(int index, boolean isFull) {
isHumanTrackSceneFull = isFull;
currentMemberIndex = index;
members = AvatarSource.buildMembers();
antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING));
boyAvatarModel = AvatarSource.buildBoyData(isFull);
girlAvatarModel = AvatarSource.buildGirlData(isFull);
if (index == 0) {
currentAvatarModel = girlAvatarModel;
} else if (index == 1) {
currentAvatarModel = boyAvatarModel;
}
sceneModel = AvatarSource.buildSceneModel(currentAvatarModel);
AvatarSource.setSceneBackGround(sceneModel, true);
}
/**
* 获取人物队列
*
* @return
*/
@Override
public ArrayList<AvatarBean> getMembers() {
return members;
}
/**
* 获取当前选中人物下标
*
* @return
*/
@Override
public int getCurrentMemberIndex() {
return currentMemberIndex;
}
/**
* 设置当前人物选中下标
*
* @param index
*/
@Override
public void setCurrentMemberIndex(int index) {
currentMemberIndex = index;
}
/**
* 获取当前驱动类型
*
* @return
*/
@Override
public boolean isHumanTrackSceneFull() {
return isHumanTrackSceneFull;
}
/**
* 设置当前驱动类型
*
* @param isFull
*/
@Override
public void setHumanTrackSceneFull(boolean isFull) {
isHumanTrackSceneFull = isFull;
sceneModel.processorConfig.setTrackScene(isFull ? ProcessorConfig.TrackScene.SceneFull : ProcessorConfig.TrackScene.SceneHalf);
if (isFull) {
boyAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 58.14, -618.94));
girlAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 58.14, -618.94));
} else {
boyAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 11.76, -183.89));
girlAvatarModel.transForm.setPosition(new FUCoordinate3DData(0.0, 11.76, -183.89));
}
}
/**
* 人物切换
*
* @param bean
*/
@Override
public void onMemberSelected(AvatarBean bean) {
if (mAvatarChoiceListener != null)
mAvatarChoiceListener.choiceAvatar(bean);
sceneModel.replaceAvatar(currentAvatarModel, bean.getDes().equals(AvatarSource.GIRL) ? girlAvatarModel : boyAvatarModel);
currentAvatarModel = bean.getDes().equals(AvatarSource.GIRL) ? girlAvatarModel : boyAvatarModel;
}
public void bindCurrentRenderer() {
mFUAIKit.loadAIProcessor(FaceUnityConfig.getAIHumanBundle(), FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR);
mFUAIKit.setMaxFaces(1);
mFURenderKit.setAntialiasing(antialiasing);
FUSceneKit.getInstance().addSceneGL(sceneModel);
FUSceneKit.getInstance().setCurrentSceneGL(sceneModel);
setHumanTrackSceneFull(isHumanTrackSceneFull);
}
public AvatarChoiceListener mAvatarChoiceListener;
public interface AvatarChoiceListener {
void choiceAvatar(AvatarBean avatarBean);
}
public void setAvatarChoiceListener(AvatarChoiceListener avatarChoiceListener) {
this.mAvatarChoiceListener = avatarChoiceListener;
}
}

View File

@ -0,0 +1,347 @@
package com.yunbao.faceunity.data;
import androidx.annotation.NonNull;
import com.faceunity.core.controller.bgSegGreen.BgSegGreenParam;
import com.faceunity.core.entity.FUColorRGBData;
import com.faceunity.core.faceunity.FUAIKit;
import com.faceunity.core.faceunity.FURenderKit;
import com.faceunity.core.model.bgSegGreen.BgSegGreen;
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean;
import com.yunbao.faceunity.entity.BgSegGreenBean;
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean;
import com.yunbao.faceunity.entity.ModelAttributeData;
import com.yunbao.faceunity.infe.AbstractBgSegGreenDataFactory;
import com.yunbao.faceunity.repo.BgSegGreenSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
/**
* DESC绿幕抠像业务工厂
* Created on 2021/3/4
*/
public class BgSegGreenDataFactory extends AbstractBgSegGreenDataFactory {
public interface BgSegGreenListener {
/**
* 取色状态回调
*
* @param isSelected 是否选中
* @param color 默认颜色
*/
void onColorPickerStateChanged(boolean isSelected, int color);
/**
* 切换背景道具
*
* @param bean
*/
void onBackgroundSelected(BgSegGreenBackgroundBean bean);
/**
* 添加自定义安全区域图片
*/
void onSafeAreaAdd();
/**
* 切换安全区域图片
*
* @param bean
*/
void onSafeAreaSelected(BgSegGreenSafeAreaBean bean);
}
/*渲染控制器*/
private final FURenderKit mFURenderKit = FURenderKit.getInstance();
/*绿幕抠像特效模型*/
private final BgSegGreen mBgSegGreen;
/*绿幕抠像背景列表*/
private final ArrayList<BgSegGreenBackgroundBean> mBgSegGreenBackgroundBeans;
/* 绿幕抠像当前背景下标 */
private int mCurrentBackgroundIndex;
/*绿幕抠像安全区域列表*/
private ArrayList<BgSegGreenSafeAreaBean> mBgSegGreenSafeAreaBeans;
/* 绿幕抠像当前安全区域下标 */
private int mCurrentSafeAreaIndex;
/* 回调 */
private final BgSegGreenListener mBgSegGreenListener;
/**
* 构造绿幕抠像
*
* @param listener 回调
* @param index 背景下标
*/
public BgSegGreenDataFactory(BgSegGreenListener listener, int index) {
mBgSegGreenListener = listener;
mBgSegGreen = BgSegGreenSource.buildBgSegGreen();
mBgSegGreenBackgroundBeans = BgSegGreenSource.buildBgSegGreenBackground();
mBgSegGreenSafeAreaBeans = BgSegGreenSource.buildBgSegGreenSafeArea();
mCurrentBackgroundIndex = index;
mCurrentSafeAreaIndex = 1;
}
/**
* 获取绿幕抠像当前背景下标
*
* @return
*/
@Override
public int getBackgroundIndex() {
return mCurrentBackgroundIndex;
}
/**
* 设置绿幕抠像当前背景下标
*
* @param backgroundIndex
*/
@Override
public void setBackgroundIndex(int backgroundIndex) {
this.mCurrentBackgroundIndex = backgroundIndex;
}
/**
* 获取绿幕抠像当前安全区域下标
*
* @return
*/
@Override
public int getBgSafeAreaIndex() {
return mCurrentSafeAreaIndex;
}
/**
* 设置绿幕抠像安全区域下标
*
* @param currentSafeAreaIndex
*/
@Override
public void setBgSafeAreaIndex(int currentSafeAreaIndex) {
this.mCurrentSafeAreaIndex = currentSafeAreaIndex;
}
/**
* 更新安全区UI
*/
public boolean updateSafeAreaBeansAndIndex() {
ArrayList<BgSegGreenSafeAreaBean> bgSegGreenSafeAreaBeans = BgSegGreenSource.buildBgSegGreenSafeArea();
if (!bgSegGreenSafeAreaBeans.equals(mBgSegGreenSafeAreaBeans)) {
//需要刷新数据
//比对数据 1数据增加 or 自定义数据修改 -> 当前应该选中的角标
if (bgSegGreenSafeAreaBeans.size() > mBgSegGreenSafeAreaBeans.size()) {
//数据增加
if (mCurrentSafeAreaIndex > 2) {
mCurrentSafeAreaIndex++;
}
}
mBgSegGreenSafeAreaBeans = bgSegGreenSafeAreaBeans;
return true;
}
return false;
}
/**
* 获取绿幕抠像项目数据扩展模型
*
* @return
*/
@Override
public HashMap<String, ModelAttributeData> getModelAttributeRange() {
return BgSegGreenSource.buildModelAttributeRange();
}
/**
* 获取绿幕抠像功能列表
*
* @return
*/
@Override
public ArrayList<BgSegGreenBean> getBgSegGreenActions() {
return BgSegGreenSource.buildBgSegGreenAction();
}
/**
* 获取绿幕抠像安全区域功能列表
*
* @return
*/
@Override
public ArrayList<BgSegGreenSafeAreaBean> getBgSegGreenSafeAreas() {
return mBgSegGreenSafeAreaBeans;
}
/**
* 获取绿幕抠像背景列表
*
* @return
*/
@Override
public ArrayList<BgSegGreenBackgroundBean> getBgSegGreenBackgrounds() {
return mBgSegGreenBackgroundBeans;
}
/**
* 背景图片变更
*
* @param data BgSegGreenBackgroundBean
*/
@Override
public void onBackgroundSelected(BgSegGreenBackgroundBean data) {
mBgSegGreenListener.onBackgroundSelected(data);
}
/**
* 自定义安全区域
*/
@Override
public void onSafeAreaAdd() {
mBgSegGreenListener.onSafeAreaAdd();
}
/**
* 安全区域变更
*
* @param data BgSegGreenBackgroundBean
*/
@Override
public void onSafeAreaSelected(BgSegGreenSafeAreaBean data) {
mBgSegGreenListener.onSafeAreaSelected(data);
}
@Override
public boolean isUseTemplate() {
return getCurrentBgSegGreenModel().isUseTemplate() == 1.0;
}
/**
* 取色锚点颜色变更
*
* @param array DoubleArray
*/
@Override
public void onColorRGBChanged(double[] array) {
mBgSegGreen.setColorRGB(new FUColorRGBData(array[0], array[1], array[2]));
mBgSegGreen.setEnable(true);
}
/**
* 绿幕开关
*
* @param enable Boolean
*/
@Override
public void onBgSegGreenEnableChanged(boolean enable) {
mBgSegGreen.setEnable(enable);
}
/**
* 根据名称标识获取对应的值
*
* @param key String 标识
* @return Double
*/
@Override
public double getParamIntensity(@NonNull String key) {
if (bgSegGreenGetMapping.containsKey(key)) {
return bgSegGreenGetMapping.get(key).getValue();
}
return 0.0;
}
/**
* 根据名称标识更新对应的值
*
* @param key String 标识
* @return Double
*/
@Override
public void updateParamIntensity(@NonNull String key, double value) {
if (bgSegGreenSetMapping.containsKey(key)) {
Objects.requireNonNull(bgSegGreenSetMapping.get(key)).setValue(value);
}
}
/**
* 调用取色器功能状态变更
*
* @param selected
* @param color
*/
@Override
public void onColorPickerStateChanged(boolean selected, int color) {
mBgSegGreenListener.onColorPickerStateChanged(selected, color);
}
//region 业务映射
/**
* 参数设置
*/
interface BgSegGreenSetParam {
void setValue(double value);
}
/**
* 模型参数获取
*/
interface BgSegGreenGetParam {
double getValue();
}
/**
* 获取当前绿幕对象
*
* @return
*/
private BgSegGreen getCurrentBgSegGreenModel() {
return mBgSegGreen;
}
/* 模型映射 */
private final HashMap<String, BgSegGreenSetParam> bgSegGreenSetMapping = new HashMap<String, BgSegGreenSetParam>() {
{
put(BgSegGreenParam.SIMILARITY, value -> getCurrentBgSegGreenModel().setSimilarity(value));
put(BgSegGreenParam.SMOOTHNESS, value -> getCurrentBgSegGreenModel().setSmoothness(value));
put(BgSegGreenParam.TRANSPARENCY, value -> getCurrentBgSegGreenModel().setTransparency(value));
}
};
/*模型映射获取模型值*/
private final HashMap<String, BgSegGreenGetParam> bgSegGreenGetMapping = new HashMap<String, BgSegGreenGetParam>() {
{
put(BgSegGreenParam.SIMILARITY, () -> getCurrentBgSegGreenModel().getSimilarity());
put(BgSegGreenParam.SMOOTHNESS, () -> getCurrentBgSegGreenModel().getSmoothness());
put(BgSegGreenParam.TRANSPARENCY, () -> getCurrentBgSegGreenModel().getTransparency());
}
};
//endregion 业务映射
/**
* FURenderKit加载当前特效
*/
public void bindCurrentRenderer() {
FUAIKit.getInstance().setMaxFaces(1);
mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty);
mFURenderKit.setBgSegGreen(mBgSegGreen);
mBgSegGreenListener.onBackgroundSelected(mBgSegGreenBackgroundBeans.get(mCurrentBackgroundIndex));
mBgSegGreenListener.onSafeAreaSelected(mBgSegGreenSafeAreaBeans.get(mCurrentSafeAreaIndex));
}
}

View File

@ -0,0 +1,101 @@
package com.yunbao.faceunity.data;
import com.faceunity.core.model.facebeauty.FaceBeautyBlurTypeEnum;
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
import java.io.Serializable;
import java.util.HashMap;
/**
* 保存到磁盘的对象
* 该例只保存特效demo展示出来的美颜功能
*/
public class FaceBeautyData implements Serializable {
/* 美肤 */
/* 磨皮类型 */
public int blurType = FaceBeautyBlurTypeEnum.FineSkin;
/* 磨皮程度 */
public double blurIntensity = 0.0;
/* 美白程度 */
public double colorIntensity = 0.0;
/* 红润程度 */
public double redIntensity = 0.0;
/* 锐化程度 */
public double sharpenIntensity = 0.0;
/* 亮眼程度 */
public double eyeBrightIntensity = 0.0;
/* 美牙程度 */
public double toothIntensity = 0.0;
/* 去黑眼圈强度*/
public double removePouchIntensity = 0.0;
/* 去法令纹强度*/
public double removeLawPatternIntensity = 0.0;
/*美型*/
/* 瘦脸程度 */
public double cheekThinningIntensity = 0.0;
/* V脸程度 */
public double cheekVIntensity = 0.0;
/* 窄脸程度 */
public double cheekNarrowIntensity = 0.0;
/* 短脸程度 */
public double cheekShortIntensity = 0.0;
/* 小脸程度 */
public double cheekSmallIntensity = 0.0;
/* 瘦颧骨 */
public double cheekBonesIntensity = 0.0;
/* 瘦下颌骨 */
public double lowerJawIntensity = 0.0;
/* 大眼程度 */
public double eyeEnlargingIntensity = 0.0;
/* 圆眼程度 */
public double eyeCircleIntensity = 0.0;
/* 下巴调整程度 */
public double chinIntensity = 0.5;
/* 额头调整程度 */
public double forHeadIntensity = 0.5;
/* 瘦鼻程度 */
public double noseIntensity = 0.0;
/* 嘴巴调整程度 */
public double mouthIntensity = 0.5;
/* 开眼角强度 */
public double canthusIntensity = 0.0;
/* 眼睛间距 */
public double eyeSpaceIntensity = 0.5;
/* 眼睛角度 */
public double eyeRotateIntensity = 0.5;
/* 鼻子长度 */
public double longNoseIntensity = 0.5;
/* 调节人中 */
public double philtrumIntensity = 0.5;
/* 微笑嘴角强度 */
public double smileIntensity = 0.0;
/* 眉毛上下 */
public double browHeightIntensity = 0.5;
/* 眉毛间距 */
public double browSpaceIntensity = 0.5;
/* 眼睑 */
public double eyeLidIntensity = 0.0;
/* 眼睛高度 */
public double eyeHeightIntensity = 0.5;
/* 眉毛粗细 */
public double browThickIntensity = 0.5;
/* 嘴巴厚度 */
public double lipThickIntensity = 0.5;
/* 五官立体 */
public double faceThreeIntensity = 0.5;
/* 风格推荐 */
/* 是否开启风格推荐 */
/* 风格推荐类型 */
public int styleTypeIndex = -1;
//所有滤镜
public HashMap<String,Double> filterMap = new HashMap<>();
/* 滤镜相关 */
/* 滤镜名称 */
public String filterName = FaceBeautyFilterEnum.ORIGIN;
/* 滤镜程度 */
public double filterIntensity = 0.0f;
}

View File

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

View File

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

View File

@ -0,0 +1,127 @@
package com.yunbao.faceunity.data;
import com.faceunity.core.entity.FUBundleData;
import com.faceunity.core.enumeration.FUAITypeEnum;
import com.faceunity.core.faceunity.FUAIKit;
import com.faceunity.core.faceunity.FURenderKit;
import com.faceunity.core.model.prop.expression.ExpressionRecognition;
import com.yunbao.faceunity.entity.LightMakeupBean;
import com.yunbao.faceunity.infe.AbstractLightMakeupDataFactory;
import com.yunbao.faceunity.repo.FaceBeautySource;
import com.yunbao.faceunity.repo.LightMakeupSource;
import com.yunbao.faceunity.utils.FaceUnityConfig;
import java.util.ArrayList;
/**
* DESC轻美妆业务工厂
* Created on 2021/3/3
*/
public class LightMakeupDataFactory extends AbstractLightMakeupDataFactory {
/*渲染控制器*/
private FURenderKit mFURenderKit = FURenderKit.getInstance();
/* 轻美妆队列 */
private ArrayList<LightMakeupBean> lightMakeupBeans;
/* 当前轻美妆选中下标 */
private int currentLightMakeupIndex;
public LightMakeupDataFactory(int index) {
currentLightMakeupIndex = index;
lightMakeupBeans = LightMakeupSource.buildLightMakeup();
}
/**
* 获取轻美妆队列
*
* @return
*/
@Override
public ArrayList<LightMakeupBean> getLightMakeUpBeans() {
return lightMakeupBeans;
}
/**
* 获取轻美妆下标
*
* @return
*/
@Override
public int getCurrentLightMakeupIndex() {
return currentLightMakeupIndex;
}
/**
* 设置轻美妆下标
*
* @param currentLightMakeupIndex
*/
@Override
public void setCurrentLightMakeupIndex(int currentLightMakeupIndex) {
this.currentLightMakeupIndex = currentLightMakeupIndex;
}
/**
* 切换轻美妆
*
* @param data
*/
@Override
public void onLightMakeupSelected(LightMakeupBean data) {
if (data.getKey() == null) {
mFURenderKit.setLightMakeup(null);
} else {
Runnable runnable = LightMakeupSource.LightMakeupParams.get(data.getKey());
if (runnable != null) {
runnable.run();
}
onLightMakeupIntensityChanged(data.getIntensity());
}
if (mFURenderKit.getFaceBeauty() != null) {
mFURenderKit.getFaceBeauty().setFilterName(data.getFilterName());
mFURenderKit.getFaceBeauty().setFilterIntensity(data.getFilterIntensity());
}
}
/**
* 修改强度
*
* @param intensity
*/
@Override
public void onLightMakeupIntensityChanged(double intensity) {
if (mFURenderKit.getLightMakeup() != null) {
mFURenderKit.getLightMakeup().setMakeupIntensity(intensity);
}
if (mFURenderKit.getFaceBeauty() != null) {
mFURenderKit.getFaceBeauty().setFilterIntensity(intensity);
}
}
/**
* FURenderKit加载当前特效
*/
public void bindCurrentRenderer() {
mFURenderKit.setFaceBeauty(FaceBeautySource.clone(FaceBeautyDataFactory.faceBeauty));
FUAIKit.getInstance().setMaxFaces(4);
LightMakeupBean lightMakeupBean = lightMakeupBeans.get(currentLightMakeupIndex);
onLightMakeupSelected(lightMakeupBean);
if (FaceUnityConfig.IS_OPEN_LAND_MARK) {
ExpressionRecognition expressionRecognition = new ExpressionRecognition(new FUBundleData(FaceUnityConfig.BUNDLE_LANDMARKS));
expressionRecognition.setLandmarksType(FUAITypeEnum.FUAITYPE_FACELANDMARKS239);
mFURenderKit.getPropContainer().addProp(expressionRecognition);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,11 @@
package com.yunbao.faceunity.entity
/**
*
* DESC
* Created on 2020/12/4
*
*/
data class BgSegGreenBackgroundBean(val desRes: Int, val iconRes: Int, val filePath: String? = null)

View File

@ -0,0 +1,18 @@
package com.yunbao.faceunity.entity
/**
*
* DESC
* Created on 2020/12/4
*
*/
data class BgSegGreenBean(val key: String, val desRes: Int, val closeRes: Int, val openRes: Int, val type: ButtonType) {
enum class ButtonType{
NORMAL1_BUTTON,//普通一号按钮
NORMAL2_BUTTON,//普通二号按钮
BACK_BUTTON,//返回按钮
SWITCH_BUTTON//切换按钮,切换整个按钮功能
}
}

View File

@ -0,0 +1,32 @@
package com.yunbao.faceunity.entity
/**
*
* DESC
* Created on 2020/12/4
*
*/
data class BgSegGreenSafeAreaBean(val iconRes: Int, val type: ButtonType, val filePath: String? = null,val isAssetFile: Boolean = true) {
constructor(iconRes: Int, type: ButtonType) : this(
iconRes,
type,
null,
true
)
constructor(iconRes: Int, type: ButtonType, filePath :String) : this(
iconRes,
type,
filePath,
true
)
enum class ButtonType{
NORMAL1_BUTTON,//普通一号按钮,普通安全区域按钮
NORMAL2_BUTTON,//普通二号按钮,用于自定义按钮
BACK_BUTTON,//返回按钮
NONE_BUTTON,//不选择按钮
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,25 @@
package com.yunbao.faceunity.entity;
public class FunctionEnum {
public final static int FACE_BEAUTY = 1;
public final static int MAKE_UP = 2;
public final static int STICKER = 3;
public final static int ANIMOJI = 4;
public final static int HAIR_BEAUTY = 5;
public final static int LIGHT_MAKEUP = 6;
public final static int AR_MASK = 7;
public final static int BIG_HEAD = 8;
public final static int POSTER_CHANGE = 9;
public final static int EXPRESSION_RECOGNITION = 10;
public final static int MUSIC_FILTER = 11;
public final static int FACE_WARP = 12;
public final static int BODY_BEAUTY = 13;
public final static int AVATAR = 14;
public final static int ACTION_RECOGNITION = 15;
public final static int PORTRAIT_SEGMENT = 16;
public final static int GESTURE_RECOGNITION = 17;
public final static int BG_SEG_GREEN = 18;
public final static int HUMAN_OUTLINE = 19;
public final static int BG_SEG_CUSTOM = 20;
public final static int FINE_STICKER = 21;
}

View File

@ -0,0 +1,67 @@
package com.yunbao.faceunity.entity;
public class LightMakeupBean {
int nameRes;
int iconRes;
String key;
double intensity;
String filterName;
double filterIntensity;
public LightMakeupBean(int nameRes, int iconRes, String key, double intensity, String filterName, double filterIntensity) {
this.nameRes = nameRes;
this.iconRes = iconRes;
this.key = key;
this.intensity = intensity;
this.filterName = filterName;
this.filterIntensity = filterIntensity;
}
public int getNameRes() {
return nameRes;
}
public void setNameRes(int nameRes) {
this.nameRes = nameRes;
}
public int getIconRes() {
return iconRes;
}
public void setIconRes(int iconRes) {
this.iconRes = iconRes;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public double getIntensity() {
return intensity;
}
public void setIntensity(double intensity) {
this.intensity = intensity;
}
public String getFilterName() {
return filterName;
}
public void setFilterName(String filterName) {
this.filterName = filterName;
}
public double getFilterIntensity() {
return filterIntensity;
}
public void setFilterIntensity(double filterIntensity) {
this.filterIntensity = filterIntensity;
}
}

View File

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

View File

@ -0,0 +1,12 @@
package com.yunbao.faceunity.entity
/**
* 模型单项补充模型
* @property default Double 默认值
* @property stand Double 无变化时候的基准值
* @property minRange Double 范围最小值
* @property maxRange Double 范围最大值
* @constructor
*/
data class ModelAttributeData(val default: Double=0.0, val stand: Double = 0.0, val minRange: Double = 0.0, val maxRange: Double = 1.0)

View File

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

View File

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

View File

@ -0,0 +1,18 @@
package com.yunbao.faceunity.entity
/**
* 道具
* @property iconId Int 图标
* @property path String 道具路径
* @property descId Int 道具提示
* @property descId Int 类型 -2 为添加事件 -1为空 其他多道具类型
* @property iconPath 图标路径
* @constructor
*/
data class PropCustomBean @JvmOverloads constructor(
val iconId: Int,
val path: String?,
val type: Int = -1,
val descId: Int = 0,
val iconPath: String? = null
)

View File

@ -0,0 +1,31 @@
package com.yunbao.faceunity.infe
import com.yunbao.faceunity.entity.AnimationFilterBean
import com.yunbao.faceunity.entity.AnimojiBean
/**
*
* DESC
* Created on 2020/12/24
*
*/
abstract class AbstractAnimojiDataFactory {
/* 当前选中动漫贴图下标 */
abstract var currentAnimojiIndex: Int
/* 动漫贴图队列 */
abstract val animojis: ArrayList<AnimojiBean>
/* 当前选中滤镜下标 */
abstract var currentFilterIndex: Int
/* 滤镜队列 */
abstract val filters: ArrayList<AnimationFilterBean>
abstract fun onAnimojiSelected(data: AnimojiBean)
abstract fun onFilterSelected(data: AnimationFilterBean)
}

View File

@ -0,0 +1,35 @@
package com.yunbao.faceunity.infe
import com.yunbao.faceunity.entity.AvatarBean
/**
*
* DESC
* Created on 2021/1/6
*
*/
abstract class AbstractAvatarDataFactory {
/**
* 人物队列
*/
abstract val members: ArrayList<AvatarBean>
/**
* 默认选中人物下标
*/
abstract var currentMemberIndex: Int
/**
* true 全身 false 半身 驱动切换
*/
abstract var isHumanTrackSceneFull: Boolean
/**
* 当前人物选中
* @param bean AvatarBean
*/
abstract fun onMemberSelected(bean:AvatarBean)
}

View File

@ -0,0 +1,97 @@
package com.yunbao.faceunity.infe
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean
import com.yunbao.faceunity.entity.BgSegGreenBean
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean
import com.yunbao.faceunity.entity.ModelAttributeData
/**
*
* DESC
* Created on 2020/12/29
*
*/
abstract class AbstractBgSegGreenDataFactory {
/* 绿幕抠像项目数据扩展模型 */
abstract val modelAttributeRange: HashMap<String, ModelAttributeData>
/* 绿幕抠像功能列表 */
abstract val bgSegGreenActions: ArrayList<BgSegGreenBean>
/* 绿幕抠图安全区域功能列表*/
abstract val bgSegGreenSafeAreas: ArrayList<BgSegGreenSafeAreaBean>
/* 安全区域下标 */
abstract var bgSafeAreaIndex: Int
/* 刷新安全区域UI */
abstract fun updateSafeAreaBeansAndIndex() :Boolean
/* 绿幕抠像背景列表 */
abstract val bgSegGreenBackgrounds: ArrayList<BgSegGreenBackgroundBean>
/* 绿幕抠像当前背景下标 */
abstract var backgroundIndex: Int
/**
* 背景图片变更
* @param data BgSegGreenBackgroundBean
*/
abstract fun onBackgroundSelected(data: BgSegGreenBackgroundBean)
/**
* 自定义安全区域
*/
abstract fun onSafeAreaAdd()
/**
* 安全区域变更
* @param data BgSegGreenSafeAreaBean
*/
abstract fun onSafeAreaSelected(data: BgSegGreenSafeAreaBean?)
/**
* 是否开启安全区域总开关
*/
abstract fun isUseTemplate():Boolean
/**
* 取色锚点颜色变更
* @param array DoubleArray
*/
abstract fun onColorRGBChanged(array: DoubleArray)
/**
* 绿幕开关
* @param enable Boolean
*/
abstract fun onBgSegGreenEnableChanged(enable: Boolean)
/**
* 根据名称标识获取对应的值
* @param key String 标识
* @return Double
*/
abstract fun getParamIntensity(key: String): Double
/**
* 根据名称标识更新对应的值
* @param key String 标识
* @return Double
*/
abstract fun updateParamIntensity(key: String, value: Double)
/**
* 是否调用取色器功能
*
* @param selected
* @param color
*/
abstract fun onColorPickerStateChanged(selected: Boolean, color: Int)
}

View File

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

View File

@ -0,0 +1,105 @@
package com.yunbao.faceunity.infe
import com.yunbao.faceunity.entity.FaceBeautyBean
import com.yunbao.faceunity.entity.FaceBeautyFilterBean
import com.yunbao.faceunity.entity.FaceBeautyStyleBean
import com.yunbao.faceunity.entity.ModelAttributeData
/**
*
* DESC数据构造工厂接口类
* Created on 2020/12/23
*
*/
abstract class AbstractFaceBeautyDataFactory {
/*美肤底部菜单数据*/
abstract val skinBeauty: ArrayList<FaceBeautyBean>
/*美型底部菜单数据*/
abstract val shapeBeauty: ArrayList<FaceBeautyBean>
/*美型脸型子项数据*/
abstract val shapeBeautySubItem: ArrayList<FaceBeautyBean>
/* 滤镜底部菜单数据*/
abstract val beautyFilters: ArrayList<FaceBeautyFilterBean>
/* 风格底部菜单数据*/
abstract val beautyStyles: ArrayList<FaceBeautyStyleBean>
/*系统推荐配置滤镜对应下标*/
abstract var currentFilterIndex: Int
/* 美颜项目数据扩展模型 */
abstract val modelAttributeRange: HashMap<String, ModelAttributeData>
/*系统风格对应下标*/
abstract var currentStyleIndex: Int
/**
* 切换滤镜
* @param name String
* @param intensity Double
*/
abstract fun onFilterSelected(name: String, intensity: Double, resDes: Int)
/**
* 切换风格
* @param name String
*/
abstract fun onStyleSelected(name: String?)
/**
* 更改滤镜强度
* @param intensity Double
*/
abstract fun updateFilterIntensity(intensity: Double)
/**
* 美颜开关
* @param enable Boolean
*/
abstract fun enableFaceBeauty(enable: Boolean)
/**
* 获取单项强度
* @param key String
* @return Double
*/
abstract fun getParamIntensity(key: String): Double
/**
* 获取one hot的脸型
*/
abstract fun getCurrentOneHotFaceShape(): String
/**
* 设置当前one hot的脸型
*/
abstract fun setCurrentOneHotFaceShape(faceShape:String)
/**
* 设置当前脸型的UI值
*/
abstract fun setCurrentFaceShapeUIValue(hashMap:HashMap<String,Double>)
/**
* 获取当前脸型的UI值
*/
abstract fun getCurrentFaceShapeUIValue() :HashMap<String,Double>
/**
* 设置单项强度
* @param key String
* @param value Double
*/
abstract fun updateParamIntensity(key: String, value: Double)
/**
* 将所有效果置空 -> 变成标准值
*/
abstract fun resetParamIntensity()
}

View File

@ -0,0 +1,28 @@
package com.yunbao.faceunity.infe;
import com.yunbao.faceunity.entity.LightMakeupBean;
import java.util.ArrayList;
public abstract class AbstractLightMakeupDataFactory {
private int currentLightMakeupIndex;
private ArrayList<LightMakeupBean> lightMakeUpBeans;
public abstract void onLightMakeupSelected(LightMakeupBean data);
public abstract void onLightMakeupIntensityChanged(double intensity);
public int getCurrentLightMakeupIndex() {
return currentLightMakeupIndex;
}
public void setCurrentLightMakeupIndex(int currentLightMakeupIndex) {
this.currentLightMakeupIndex = currentLightMakeupIndex;
}
public ArrayList<LightMakeupBean> getLightMakeUpBeans() {
return lightMakeUpBeans;
}
public void setLightMakeUpBeans(ArrayList<LightMakeupBean> lightMakeUpBeans) {
this.lightMakeUpBeans = lightMakeUpBeans;
}
}

View File

@ -0,0 +1,45 @@
package com.yunbao.faceunity.infe
import com.yunbao.faceunity.entity.PropCustomBean
/**
*
* DESC贴图道具
* Created on 2020/12/23
*
*/
abstract class AbstractPropCustomDataFactory {
/**
* 默认选中道具下标
*/
abstract var currentPropIndex: Int
/**
* 道具队列
*/
abstract val propCustomBeans: ArrayList<PropCustomBean>
/**
* 道具选中
* @param bean StickerBean
*/
abstract fun onItemSelected(bean: PropCustomBean)
/**
* 道具选中
*/
abstract fun onAddPropCustomBeanClick()
companion object {
const val TYPE_NONE = -1
const val TYPE_ADD = -99
}
}

View File

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

View File

@ -0,0 +1,33 @@
package com.yunbao.faceunity.infe
import com.yunbao.faceunity.entity.PropBean
/**
*
* DESC贴图道具
* Created on 2020/12/23
*
*/
abstract class AbstractPropDataFactory {
/**
* 默认选中道具下标
*/
abstract var currentPropIndex: Int
/**
* 道具队列
*/
abstract val propBeans: ArrayList<PropBean>
/**
* 道具选中
* @param bean StickerBean
*/
abstract fun onItemSelected(bean: PropBean)
}

View File

@ -0,0 +1,59 @@
package com.yunbao.faceunity.repo;
import com.faceunity.core.model.animationFilter.AnimationFilterTypeEnum;
import com.yunbao.faceunity.R;
import com.yunbao.faceunity.entity.AnimationFilterBean;
import com.yunbao.faceunity.entity.AnimojiBean;
import java.util.ArrayList;
/**
* DESCAnimoji数据构造
* Created on 2021/3/25
*/
public class AnimojiSource {
/**
* 构造贴图数据
*
* @return
*/
public static ArrayList<AnimojiBean> buildAnimojis() {
ArrayList<AnimojiBean> array = new ArrayList<>();
array.add(new AnimojiBean(R.mipmap.icon_control_delete_all, null));
array.add(new AnimojiBean(R.mipmap.icon_animoji_cartoon_princess, "animoji/cartoon_princess_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_qgirl, "animoji/qgirl_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_kaola, "animoji/kaola_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_wuxia, "animoji/wuxia_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_baihu, "animoji/baihu_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_frog_st, "animoji/frog_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_huangya, "animoji/huangya_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_hetun, "animoji/hetun_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_douniuquan, "animoji/douniuquan_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_hashiqi, "animoji/hashiqi_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_baimao, "animoji/baimao_Animoji.bundle"));
array.add(new AnimojiBean(R.mipmap.icon_animoji_kuloutou, "animoji/kuloutou_Animoji.bundle"));
return array;
}
/**
* 构造滤镜数据
*
* @return
*/
public static ArrayList<AnimationFilterBean> buildFilters() {
ArrayList<AnimationFilterBean> filters = new ArrayList<>();
filters.add(new AnimationFilterBean(R.mipmap.icon_control_delete_all, AnimationFilterTypeEnum.Origin));
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_anime, AnimationFilterTypeEnum.Comic));
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_portrait_dynamiceffect, AnimationFilterTypeEnum.Portrait));
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_sketch, AnimationFilterTypeEnum.Sketch));
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_oilpainting, AnimationFilterTypeEnum.Oil));
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_sandlpainting, AnimationFilterTypeEnum.Sand));
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_penpainting, AnimationFilterTypeEnum.Pen));
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_pencilpainting, AnimationFilterTypeEnum.Pencil));
filters.add(new AnimationFilterBean(R.mipmap.icon_cartoon_graffiti, AnimationFilterTypeEnum.Granffiti));
return filters;
}
}

View File

@ -0,0 +1,160 @@
package com.yunbao.faceunity.repo;
import com.faceunity.core.avatar.avatar.Color;
import com.faceunity.core.avatar.avatar.TransForm;
import com.faceunity.core.avatar.model.Avatar;
import com.faceunity.core.avatar.model.Scene;
import com.faceunity.core.entity.FUAnimationData;
import com.faceunity.core.entity.FUAvatarAnimFilterParams;
import com.faceunity.core.entity.FUBundleData;
import com.faceunity.core.entity.FUColorRGBData;
import com.faceunity.core.entity.FUCoordinate3DData;
import com.faceunity.core.entity.FUTranslationScale;
import com.faceunity.core.entity.FUVisibleBundleData;
import com.yunbao.faceunity.R;
import com.yunbao.faceunity.entity.AvatarBean;
import java.io.File;
import java.util.ArrayList;
/**
* DESCAvatar数据构造
* Created on 2021/3/30
*/
public class AvatarSource {
// Avatar
private static String BUNDLE_AVATAR_CONTROLLER = "graphics" + File.separator + "controller_cpp.bundle";
private static String BUNDLE_AVATAR_CONFIG = "pta" + File.separator + "controller_config.bundle";
private static String BUNDLE_AVATAR_BACKGROUND = "pta" + File.separator + "default_bg.bundle";
public static String BOY = "boy";
public static String GIRL = "girl";
/**
* 构造成员列表
*
* @return
*/
public static ArrayList<AvatarBean> buildMembers() {
ArrayList<AvatarBean> avatarBeans = new ArrayList<>();
avatarBeans.add(new AvatarBean(R.mipmap.icon_avatar_female, GIRL));
avatarBeans.add(new AvatarBean(R.mipmap.icon_avatar_male, BOY));
return avatarBeans;
}
/**
* 构造场景
*
* @param avatar
* @return
*/
public static Scene buildSceneModel(Avatar avatar) {
FUBundleData controlBundle = new FUBundleData(BUNDLE_AVATAR_CONTROLLER);
FUBundleData avatarConfig = new FUBundleData(BUNDLE_AVATAR_CONFIG);
Scene sceneModel = new Scene(controlBundle, avatarConfig);
sceneModel.addAvatar(avatar);
sceneModel.processorConfig.setEnableHumanProcessor(true);
return sceneModel;
}
/**
* 获取男孩对象
*
* @return
*/
public static Avatar buildBoyData(boolean isFull) {
String ptaBoyDir = "pta/boy/";
ArrayList<FUBundleData> components = new ArrayList();
components.add(new FUBundleData(ptaBoyDir + "head.bundle"));
components.add(new FUBundleData(ptaBoyDir + "midBody_male.bundle"));
components.add(new FUBundleData(ptaBoyDir + "male_hair_5.bundle"));
components.add(new FUBundleData(ptaBoyDir + "toushi_7.bundle"));
components.add(new FUBundleData(ptaBoyDir + "peishi_erding_2.bundle"));
components.add(new FUBundleData(ptaBoyDir + "waitao_3.bundle"));
components.add(new FUBundleData(ptaBoyDir + "kuzi_changku_5.bundle"));
components.add(new FUBundleData(ptaBoyDir + "xiezi_tuoxie_2.bundle"));
int[] invisibleList = {2,3,4};
components.add(new FUVisibleBundleData("",invisibleList,""));
ArrayList<FUAnimationData> animations = buildAnimations();
Avatar model = new Avatar(components);
for (FUAnimationData animationData:animations){
model.animation.addAnimation(animationData);
}
model.color.setColor(Color.Skin,new FUColorRGBData(227.0,158.0,132.0));
TransForm avatarTransForm = model.transForm;
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
avatarTransForm.setPosition(isFull ? new FUCoordinate3DData(0.0, 58.14, -618.94) : new FUCoordinate3DData(0.0, 11.76, -183.89));
return model;
}
/**
* 获取女孩对象
*
* @return
*/
public static Avatar buildGirlData(boolean isFull) {
String ptaGirlDir = "pta/girl/";
ArrayList<FUBundleData> components = new ArrayList();
components.add(new FUBundleData(ptaGirlDir + "head.bundle"));
components.add(new FUBundleData(ptaGirlDir + "midBody_female.bundle"));
components.add(new FUBundleData(ptaGirlDir + "female_hair_23.bundle"));
components.add(new FUBundleData(ptaGirlDir + "toushi_5.bundle"));
components.add(new FUBundleData(ptaGirlDir + "taozhuang_12.bundle"));
components.add(new FUBundleData(ptaGirlDir + "facemakeup_3.bundle"));
components.add(new FUBundleData(ptaGirlDir + "xiezi_danxie.bundle"));
int[] invisibleList = {2,3,4};
components.add(new FUVisibleBundleData("",invisibleList,""));
ArrayList<FUAnimationData> animations = buildAnimations();
Avatar model = new Avatar(components );
for (FUAnimationData animationData:animations){
model.animation.addAnimation(animationData);
}
model.color.setColor(Color.Skin,new FUColorRGBData(255.0,202.0,186.0));
TransForm avatarTransForm = model.transForm;
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
avatarTransForm.setPosition(isFull ? new FUCoordinate3DData(0.0, 58.14, -618.94) : new FUCoordinate3DData(0.0, 11.76, -183.89));
return model;
}
/**
* 外部传入组件和动画构建
*
* @param strComponents 组件bundle
* @param strAnimations 动画bundle
* @return
*/
public static Avatar buildAvatarData(ArrayList<String> strComponents, ArrayList<String> strAnimations) {
ArrayList<FUBundleData> components = new ArrayList();
for (String component : strComponents) {
components.add(new FUBundleData(component));
}
Avatar model = new Avatar(components);
for (String animation : strAnimations) {
model.animation.addAnimation(new FUAnimationData(new FUBundleData(animation)));
}
//位置等avatar基本参数构建
TransForm avatarTransForm = model.transForm;
avatarTransForm.setPosition(new FUCoordinate3DData(20, 45, -618.94));
avatarTransForm.setTranslationScale(new FUTranslationScale(0.0f,0.0f,0.0f));
avatarTransForm.setInstanceEnableHumanAnimDriver(true);
model.animation.setHumanProcessorSetAvatarAnimFilterParams(new FUAvatarAnimFilterParams(8, 0.09f, 0.120f));
return model;
}
/**
* 构造动画参数
*
* @return
*/
public static ArrayList<FUAnimationData> buildAnimations() {
String animDir = "pta/gesture/";
ArrayList<FUAnimationData> animations = new ArrayList();
animations.add(new FUAnimationData(new FUBundleData(animDir + "anim_idle.bundle")));
return animations;
}
public static void setSceneBackGround(Scene sceneModel, boolean hasBackGround) {
sceneModel.setBackgroundBundle(hasBackGround ? new FUBundleData(BUNDLE_AVATAR_BACKGROUND) : null);
}
}

View File

@ -0,0 +1,145 @@
package com.yunbao.faceunity.repo;
import static android.content.Context.MODE_PRIVATE;
import android.content.SharedPreferences;
import com.faceunity.core.controller.bgSegGreen.BgSegGreenParam;
import com.faceunity.core.entity.FUBundleData;
import com.faceunity.core.model.bgSegGreen.BgSegGreen;
import com.yunbao.faceunity.R;
import com.yunbao.faceunity.entity.BgSegGreenBackgroundBean;
import com.yunbao.faceunity.entity.BgSegGreenBean;
import com.yunbao.faceunity.entity.BgSegGreenSafeAreaBean;
import com.yunbao.faceunity.entity.ModelAttributeData;
import com.yunbao.faceunity.utils.FaceUnityConfig;
import com.yunbao.faceunity.utils.FaceUnityData;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
/**
* DESC绿幕抠像数据构造
* Created on 2021/3/25
*/
public class BgSegGreenSource {
private static final String GREEN_SAFE_AREA_CUSTOM = "green_safe_area_custom";
private static double SIMILARITY = 0.5;//相似度
private static double SMOOTHNESS = 0.3;//平滑度
private static double TRANSPARENCY = 0.67;//透明度
/**
* 构造绿幕抠像对象
*
* @return
*/
public static BgSegGreen buildBgSegGreen() {
BgSegGreen bgSegGreen = new BgSegGreen(new FUBundleData(FaceUnityConfig.BUNDLE_BG_SEG_GREEN));
bgSegGreen.setSimilarity(BgSegGreenSource.SIMILARITY);
bgSegGreen.setSmoothness(BgSegGreenSource.SMOOTHNESS);
bgSegGreen.setTransparency(BgSegGreenSource.TRANSPARENCY);
return bgSegGreen;
}
/**
* 获取模型属性扩展数据
*
* @return HashMap<String, ModelAttributeData>
*/
public static HashMap<String, ModelAttributeData> buildModelAttributeRange() {
HashMap<String, ModelAttributeData> params = new HashMap<String, ModelAttributeData>();
params.put(BgSegGreenParam.SIMILARITY, new ModelAttributeData(SIMILARITY, 0.0, 0.0, 1.0));
params.put(BgSegGreenParam.SMOOTHNESS, new ModelAttributeData(SMOOTHNESS, 0.0, 0.0, 1.0));
params.put(BgSegGreenParam.TRANSPARENCY, new ModelAttributeData(TRANSPARENCY, 0.0, 0.0, 1.0));
return params;
}
/**
* 绿幕抠像功能列表
*
* @return
*/
public static ArrayList<BgSegGreenBean> buildBgSegGreenAction() {
ArrayList<BgSegGreenBean> actions = new ArrayList<BgSegGreenBean>();
actions.add(new BgSegGreenBean(BgSegGreenParam.RGB_COLOR, R.string.bg_seg_green_key_color, R.drawable.icon_green_color_selector, R.drawable.icon_green_color_selector, BgSegGreenBean.ButtonType.NORMAL2_BUTTON));
actions.add(new BgSegGreenBean(BgSegGreenParam.SIMILARITY, R.string.bg_seg_green_similarity, R.drawable.icon_green_similarityr_close_selector, R.drawable.icon_green_similarityr_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
actions.add(new BgSegGreenBean(BgSegGreenParam.SMOOTHNESS, R.string.bg_seg_green_smooth, R.drawable.icon_green_smooth_close_selector, R.drawable.icon_green_similarityr_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
actions.add(new BgSegGreenBean(BgSegGreenParam.TRANSPARENCY, R.string.bg_seg_green_alpha, R.drawable.icon_green_transparency_close_selector, R.drawable.icon_green_transparency_open_selector, BgSegGreenBean.ButtonType.NORMAL1_BUTTON));
actions.add(new BgSegGreenBean("", R.string.bg_seg_green_safe_area, R.drawable.icon_green_safe_area_close_selector, R.drawable.icon_green_safe_area_open_selector, BgSegGreenBean.ButtonType.SWITCH_BUTTON));
return actions;
}
/**
* 绿幕抠像安全区域功能列表
*
* @return
*/
public static ArrayList<BgSegGreenSafeAreaBean> buildBgSegGreenSafeArea() {
String fileDir = "bg_seg_green" + File.separator + "sample" + File.separator;
ArrayList<BgSegGreenSafeAreaBean> safeAreaBeans = new ArrayList<BgSegGreenSafeAreaBean>();
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_return, BgSegGreenSafeAreaBean.ButtonType.BACK_BUTTON));//返回
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_none, BgSegGreenSafeAreaBean.ButtonType.NONE_BUTTON));//不选
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_control_square_add, BgSegGreenSafeAreaBean.ButtonType.NORMAL2_BUTTON));//自定义
BgSegGreenSafeAreaBean customerBean = buildSafeAreaCustomBean(getCachePortraitSegment());
if (customerBean != null) {
safeAreaBeans.add(customerBean);
}
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_green_safe_area1, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON,fileDir + "safe_area1.jpg"));//区域一
safeAreaBeans.add(new BgSegGreenSafeAreaBean(R.mipmap.icon_green_safe_area2, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON,fileDir + "safe_area2.jpg"));//区域二
return safeAreaBeans;
}
/**
* 构造自定义安全区域图片
*
* @param path
* @return
*/
public static BgSegGreenSafeAreaBean buildSafeAreaCustomBean(String path) {
if (path != null && path.trim().length() > 0 && new File(path).exists()) {
saveCachePortraitSegment(path);
return new BgSegGreenSafeAreaBean(0, BgSegGreenSafeAreaBean.ButtonType.NORMAL1_BUTTON, path,false);
}
return null;
}
/**
* 绿幕抠像背景列表
*
* @return
*/
public static ArrayList<BgSegGreenBackgroundBean> buildBgSegGreenBackground() {
ArrayList<BgSegGreenBackgroundBean> backgroundBeans = new ArrayList<>();
String fileDir = "bg_seg_green" + File.separator + "sample" + File.separator;
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.cancel, R.mipmap.icon_control_none, null));
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_science, R.mipmap.icon_green_science, fileDir + "science.mp4"));
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_beach, R.mipmap.icon_green_bg_beach, fileDir + "beach.mp4"));
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_classroom, R.mipmap.icon_green_bg_classroom, fileDir + "classroom.mp4"));
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_ink, R.mipmap.icon_green_ink_painting, fileDir + "ink_painting.mp4"));
backgroundBeans.add(new BgSegGreenBackgroundBean(R.string.bg_seg_green_forest, R.mipmap.icon_green_bg_forest, fileDir + "forest.mp4"));
return backgroundBeans;
}
/**
* 缓存自定义安全区域图片
*
* @param path
*/
public static void saveCachePortraitSegment(String path) {
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(GREEN_SAFE_AREA_CUSTOM, MODE_PRIVATE);
sp.edit().putString(GREEN_SAFE_AREA_CUSTOM, path).apply();
}
/**
* 获取自定义安全区域图片
*
* @return
*/
public static String getCachePortraitSegment() {
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(GREEN_SAFE_AREA_CUSTOM, MODE_PRIVATE);
return sp.getString(GREEN_SAFE_AREA_CUSTOM, "");
}
}

View File

@ -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)
recommendFaceBeauty.setFilterIntensity(0.4); faceBeautyData = FUUtils.loadFaceBeautyData();
/*美肤*/ if (faceBeautyData != null) {
recommendFaceBeauty.setBlurType(FaceBeautyBlurTypeEnum.FineSkin); //有本地缓存
recommendFaceBeauty.setSharpenIntensity(0.2); FaceBeautyDataFactory.setDiskCurrentStyleIndex(faceBeautyData.styleTypeIndex);
recommendFaceBeauty.setColorIntensity(0.3); FUUtils.setFaceBeauty(faceBeautyData, recommendFaceBeauty);
recommendFaceBeauty.setRedIntensity(0.3); } else {
recommendFaceBeauty.setBlurIntensity(4.2); //没有本地缓存
/*美型*/ recommendFaceBeauty.setFilterName(FaceBeautyFilterEnum.ZIRAN_2);
recommendFaceBeauty.setFaceShapeIntensity(1.0); recommendFaceBeauty.setFilterIntensity(0.4);
recommendFaceBeauty.setEyeEnlargingIntensityV2(0.4); /*美肤*/
recommendFaceBeauty.setCheekVIntensity(0.5); recommendFaceBeauty.setSharpenIntensity(0.2);
recommendFaceBeauty.setNoseIntensityV2(0.5); recommendFaceBeauty.setColorIntensity(0.3);
recommendFaceBeauty.setForHeadIntensityV2(0.3); recommendFaceBeauty.setRedIntensity(0.3);
recommendFaceBeauty.setMouthIntensityV2(0.4); recommendFaceBeauty.setBlurIntensity(4.2);
recommendFaceBeauty.setChinIntensity(0.3); /*美型*/
recommendFaceBeauty.setFaceShapeIntensity(1.0);
recommendFaceBeauty.setEyeEnlargingIntensity(0.4);
recommendFaceBeauty.setCheekVIntensity(0.5);
recommendFaceBeauty.setNoseIntensity(0.5);
recommendFaceBeauty.setForHeadIntensity(0.3);
recommendFaceBeauty.setMouthIntensity(0.4);
recommendFaceBeauty.setChinIntensity(0.3);
//性能最优策略
if (FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID) {
setFaceBeautyPropertyMode(recommendFaceBeauty);
}
}
return recommendFaceBeauty; 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;
}
} }

View File

@ -0,0 +1,402 @@
package com.yunbao.faceunity.repo;
import android.content.Context;
import com.faceunity.core.entity.FUBundleData;
import com.faceunity.core.entity.FUColorRGBData;
import com.faceunity.core.faceunity.FURenderKit;
import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum;
import com.faceunity.core.model.littleMakeup.LightMakeup;
import com.yunbao.faceunity.R;
import com.yunbao.faceunity.entity.LightMakeupBean;
import com.yunbao.faceunity.utils.FaceUnityConfig;
import com.yunbao.faceunity.utils.FaceUnityData;
import com.yunbao.faceunity.utils.FileUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
/**
* DESC轻美妆数据构造
* Created on 2021/3/27
*/
public class LightMakeupSource {
/**
* 构造轻美妆队列
*
* @return
*/
public static ArrayList<LightMakeupBean> buildLightMakeup() {
ArrayList<LightMakeupBean> makeups = new ArrayList<>();
makeups.add(new LightMakeupBean(R.string.makeup_radio_remove, R.mipmap.icon_control_none, null, 0.0, FaceBeautyFilterEnum.ZIRAN_2, 0.4));
/*桃花*/
makeups.add(new LightMakeupBean(R.string.makeup_peach_blossom, R.mipmap.icon_light_makeup_peachblossom, "taohua", 0.9, FaceBeautyFilterEnum.FENNEN_3, 0.9));
/*西柚*/
makeups.add(new LightMakeupBean(R.string.makeup_grapefruit, R.mipmap.icon_light_makeup_grapefruit, "xiyou", 1.0, FaceBeautyFilterEnum.LENGSEDIAO_4, 1.0));
/*清透*/
makeups.add(new LightMakeupBean(R.string.makeup_clear, R.mipmap.icon_light_makeup_clear, "qingtou", 0.9, FaceBeautyFilterEnum.XIAOQINGXIN_1, 0.9));
/*男友*/
makeups.add(new LightMakeupBean(R.string.makeup_boyfriend, R.mipmap.icon_light_makeup_boyfriend, "nanyou", 1.0, FaceBeautyFilterEnum.XIAOQINGXIN_3, 1.0));
return makeups;
}
/**
* 风格对应参数配置
*/
public static HashMap<String, Runnable> LightMakeupParams = new HashMap<String, Runnable>() {
{
put("taohua", () -> {
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_01.path);
lightMakeup.setBlusherIntensity(0.9);
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_01.path);
lightMakeup.setEyeShadowIntensity(0.9);
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_01.path);
lightMakeup.setEyeBrowIntensity(0.5);
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_01.getLipColorRGBData());
lightMakeup.setLipIntensity(0.9);
FURenderKit.getInstance().setLightMakeup(lightMakeup);
});
put("xiyou", () -> {
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_23.path);
lightMakeup.setBlusherIntensity(1.0);
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_21.path);
lightMakeup.setEyeShadowIntensity(0.75);
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_19.path);
lightMakeup.setEyeBrowIntensity(0.6);
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_21.getLipColorRGBData());
lightMakeup.setLipIntensity(0.8);
FURenderKit.getInstance().setLightMakeup(lightMakeup);
});
put("qingtou", () -> {
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_22.path);
lightMakeup.setBlusherIntensity(0.9);
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_20.path);
lightMakeup.setEyeShadowIntensity(0.65);
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_18.path);
lightMakeup.setEyeBrowIntensity(0.45);
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_20.getLipColorRGBData());
lightMakeup.setLipIntensity(0.8);
FURenderKit.getInstance().setLightMakeup(lightMakeup);
});
put("nanyou", () -> {
LightMakeup lightMakeup = new LightMakeup(new FUBundleData(FaceUnityConfig.BUNDLE_LIGHT_MAKEUP));
lightMakeup.setBlusherTex(LightMakeUpEnum.MAKEUP_BLUSHER_20.path);
lightMakeup.setBlusherIntensity(0.8);
lightMakeup.setEyeShadowTex(LightMakeUpEnum.MAKEUP_EYE_SHADOW_18.path);
lightMakeup.setEyeShadowIntensity(0.9);
lightMakeup.setEyeBrowTex(LightMakeUpEnum.MAKEUP_EYEBROW_16.path);
lightMakeup.setEyeBrowIntensity(0.65);
lightMakeup.setLipColor(LightMakeUpEnum.MAKEUP_LIPSTICK_18.getLipColorRGBData());
lightMakeup.setLipIntensity(1.0);
FURenderKit.getInstance().setLightMakeup(lightMakeup);
});
}
};
//region 轻美妆效果枚举
public enum LightMakeUpEnum {
/**
* 美妆项前几项是预置的效果
* 排在列表最前方顺序为桃花妆雀斑妆朋克妆其中朋克没有腮红3个妆容的眼线眼睫毛共用1个的
*/
// 腮红
MAKEUP_BLUSHER_01("MAKEUP_BLUSHER_01", "light_makeup/blusher/mu_blush_01.png", R.mipmap.icon_light_makeup_blush_01, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_02("MAKEUP_BLUSHER_02", "light_makeup/blusher/mu_blush_02.png", R.mipmap.icon_light_makeup_blush_02, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_03("MAKEUP_BLUSHER_03", "light_makeup/blusher/mu_blush_03.png", R.mipmap.icon_light_makeup_blush_03, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_04("MAKEUP_BLUSHER_04", "light_makeup/blusher/mu_blush_04.png", R.mipmap.icon_light_makeup_blush_04, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_05("MAKEUP_BLUSHER_05", "light_makeup/blusher/mu_blush_05.png", R.mipmap.icon_light_makeup_blush_05, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_06("MAKEUP_BLUSHER_06", "light_makeup/blusher/mu_blush_06.png", R.mipmap.icon_light_makeup_blush_06, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_07("MAKEUP_BLUSHER_07", "light_makeup/blusher/mu_blush_07.png", R.mipmap.icon_light_makeup_blush_07, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_08("MAKEUP_BLUSHER_08", "light_makeup/blusher/mu_blush_08.png", R.mipmap.icon_light_makeup_blush_08, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_09("MAKEUP_BLUSHER_09", "light_makeup/blusher/mu_blush_09.png", R.mipmap.icon_light_makeup_blush_09, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_10("MAKEUP_BLUSHER_10", "light_makeup/blusher/mu_blush_10.png", R.mipmap.icon_light_makeup_blush_10, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_11("MAKEUP_BLUSHER_11", "light_makeup/blusher/mu_blush_11.png", R.mipmap.icon_light_makeup_blush_11, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_12("MAKEUP_BLUSHER_12", "light_makeup/blusher/mu_blush_12.png", R.mipmap.icon_light_makeup_blush_12, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_13("MAKEUP_BLUSHER_13", "light_makeup/blusher/mu_blush_13.png", R.mipmap.icon_light_makeup_blush_13, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_14("MAKEUP_BLUSHER_14", "light_makeup/blusher/mu_blush_14.png", R.mipmap.icon_light_makeup_blush_14, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_15("MAKEUP_BLUSHER_15", "light_makeup/blusher/mu_blush_15.png", R.mipmap.icon_light_makeup_blush_15, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_16("MAKEUP_BLUSHER_16", "light_makeup/blusher/mu_blush_16.png", R.mipmap.icon_light_makeup_blush_16, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_17("MAKEUP_BLUSHER_17", "light_makeup/blusher/mu_blush_17.png", R.mipmap.icon_light_makeup_blush_17, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_18("MAKEUP_BLUSHER_18", "light_makeup/blusher/mu_blush_18.png", R.mipmap.icon_light_makeup_blush_18, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_19("MAKEUP_BLUSHER_19", "light_makeup/blusher/mu_blush_19.png", R.mipmap.icon_light_makeup_blush_19, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_20("MAKEUP_BLUSHER_20", "light_makeup/blusher/mu_blush_20.png", R.mipmap.icon_light_makeup_blush_20, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_21("MAKEUP_BLUSHER_21", "light_makeup/blusher/mu_blush_21.png", R.mipmap.icon_light_makeup_blush_21, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_22("MAKEUP_BLUSHER_22", "light_makeup/blusher/mu_blush_22.png", R.mipmap.icon_light_makeup_blush_22, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_23("MAKEUP_BLUSHER_23", "light_makeup/blusher/mu_blush_23.png", R.mipmap.icon_light_makeup_blush_23, R.string.makeup_radio_blusher),
MAKEUP_BLUSHER_24("MAKEUP_BLUSHER_24", "light_makeup/blusher/mu_blush_24.png", R.mipmap.icon_light_makeup_blush_24, R.string.makeup_radio_blusher),
// 眉毛
MAKEUP_EYEBROW_01("MAKEUP_EYEBROW_01", "light_makeup/eyebrow/mu_eyebrow_01.png", R.mipmap.icon_light_makeup_eyebrow_01, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_02("MAKEUP_EYEBROW_02", "light_makeup/eyebrow/mu_eyebrow_02.png", R.mipmap.icon_light_makeup_eyebrow_02, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_03("MAKEUP_EYEBROW_03", "light_makeup/eyebrow/mu_eyebrow_03.png", R.mipmap.icon_light_makeup_eyebrow_03, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_04("MAKEUP_EYEBROW_04", "light_makeup/eyebrow/mu_eyebrow_04.png", R.mipmap.icon_light_makeup_eyebrow_04, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_05("MAKEUP_EYEBROW_05", "light_makeup/eyebrow/mu_eyebrow_05.png", R.mipmap.icon_light_makeup_eyebrow_05, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_06("MAKEUP_EYEBROW_06", "light_makeup/eyebrow/mu_eyebrow_06.png", R.mipmap.icon_light_makeup_eyebrow_06, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_07("MAKEUP_EYEBROW_07", "light_makeup/eyebrow/mu_eyebrow_07.png", R.mipmap.icon_light_makeup_eyebrow_07, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_08("MAKEUP_EYEBROW_08", "light_makeup/eyebrow/mu_eyebrow_08.png", R.mipmap.icon_light_makeup_eyebrow_08, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_09("MAKEUP_EYEBROW_09", "light_makeup/eyebrow/mu_eyebrow_09.png", R.mipmap.icon_light_makeup_eyebrow_09, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_10("MAKEUP_EYEBROW_10", "light_makeup/eyebrow/mu_eyebrow_10.png", R.mipmap.icon_light_makeup_eyebrow_10, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_11("MAKEUP_EYEBROW_11", "light_makeup/eyebrow/mu_eyebrow_11.png", R.mipmap.icon_light_makeup_eyebrow_11, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_12("MAKEUP_EYEBROW_12", "light_makeup/eyebrow/mu_eyebrow_12.png", R.mipmap.icon_light_makeup_eyebrow_12, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_13("MAKEUP_EYEBROW_13", "light_makeup/eyebrow/mu_eyebrow_13.png", R.mipmap.icon_light_makeup_eyebrow_13, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_14("MAKEUP_EYEBROW_14", "light_makeup/eyebrow/mu_eyebrow_14.png", R.mipmap.icon_light_makeup_eyebrow_14, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_15("MAKEUP_EYEBROW_15", "light_makeup/eyebrow/mu_eyebrow_15.png", R.mipmap.icon_light_makeup_eyebrow_15, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_16("MAKEUP_EYEBROW_16", "light_makeup/eyebrow/mu_eyebrow_16.png", R.mipmap.icon_light_makeup_eyebrow_16, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_17("MAKEUP_EYEBROW_17", "light_makeup/eyebrow/mu_eyebrow_17.png", R.mipmap.icon_light_makeup_eyebrow_17, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_18("MAKEUP_EYEBROW_18", "light_makeup/eyebrow/mu_eyebrow_18.png", R.mipmap.icon_light_makeup_eyebrow_18, R.string.makeup_radio_eyebrow),
MAKEUP_EYEBROW_19("MAKEUP_EYEBROW_19", "light_makeup/eyebrow/mu_eyebrow_19.png", R.mipmap.icon_light_makeup_eyebrow_19, R.string.makeup_radio_eyebrow),
// 睫毛
MAKEUP_EYELASH_01("MAKEUP_EYELASH_01", "light_makeup/eyelash/mu_eyelash_01.png", R.mipmap.icon_light_makeup_eyelash_01, R.string.makeup_radio_eyelash),
MAKEUP_EYELASH_02("MAKEUP_EYELASH_02", "light_makeup/eyelash/mu_eyelash_02.png", R.mipmap.icon_light_makeup_eyelash_02, R.string.makeup_radio_eyelash),
MAKEUP_EYELASH_03("MAKEUP_EYELASH_03", "light_makeup/eyelash/mu_eyelash_03.png", R.mipmap.icon_light_makeup_eyelash_03, R.string.makeup_radio_eyelash),
MAKEUP_EYELASH_04("MAKEUP_EYELASH_04", "light_makeup/eyelash/mu_eyelash_04.png", R.mipmap.icon_light_makeup_eyelash_04, R.string.makeup_radio_eyelash),
MAKEUP_EYELASH_05("MAKEUP_EYELASH_05", "light_makeup/eyelash/mu_eyelash_05.png", R.mipmap.icon_light_makeup_eyelash_05, R.string.makeup_radio_eyelash),
MAKEUP_EYELASH_06("MAKEUP_EYELASH_06", "light_makeup/eyelash/mu_eyelash_06.png", R.mipmap.icon_light_makeup_eyelash_06, R.string.makeup_radio_eyelash),
MAKEUP_EYELASH_07("MAKEUP_EYELASH_07", "light_makeup/eyelash/mu_eyelash_07.png", R.mipmap.icon_light_makeup_eyelash_07, R.string.makeup_radio_eyelash),
MAKEUP_EYELASH_08("MAKEUP_EYELASH_08", "light_makeup/eyelash/mu_eyelash_08.png", R.mipmap.icon_light_makeup_eyelash_08, R.string.makeup_radio_eyelash),
// 眼线
MAKEUP_EYELINER_01("MAKEUP_EYELINER_01", "light_makeup/eyeliner/mu_eyeliner_01.png", R.mipmap.icon_light_makeup_eyeliner_01, R.string.makeup_radio_eye_liner),
MAKEUP_EYELINER_02("MAKEUP_EYELINER_02", "light_makeup/eyeliner/mu_eyeliner_02.png", R.mipmap.icon_light_makeup_eyeliner_02, R.string.makeup_radio_eye_liner),
MAKEUP_EYELINER_03("MAKEUP_EYELINER_03", "light_makeup/eyeliner/mu_eyeliner_03.png", R.mipmap.icon_light_makeup_eyeliner_03, R.string.makeup_radio_eye_liner),
MAKEUP_EYELINER_04("MAKEUP_EYELINER_04", "light_makeup/eyeliner/mu_eyeliner_04.png", R.mipmap.icon_light_makeup_eyeliner_04, R.string.makeup_radio_eye_liner),
MAKEUP_EYELINER_05("MAKEUP_EYELINER_05", "light_makeup/eyeliner/mu_eyeliner_05.png", R.mipmap.icon_light_makeup_eyeliner_05, R.string.makeup_radio_eye_liner),
MAKEUP_EYELINER_06("MAKEUP_EYELINER_06", "light_makeup/eyeliner/mu_eyeliner_06.png", R.mipmap.icon_light_makeup_eyeliner_06, R.string.makeup_radio_eye_liner),
MAKEUP_EYELINER_07("MAKEUP_EYELINER_07", "light_makeup/eyeliner/mu_eyeliner_07.png", R.mipmap.icon_light_makeup_eyeliner_07, R.string.makeup_radio_eye_liner),
MAKEUP_EYELINER_08("MAKEUP_EYELINER_08", "light_makeup/eyeliner/mu_eyeliner_08.png", R.mipmap.icon_light_makeup_eyeliner_08, R.string.makeup_radio_eye_liner),
// 美瞳
MAKEUP_EYEPUPIL_01("MAKEUP_EYEPUPIL_01", "light_makeup/eyepupil/mu_eyepupil_01.png", R.mipmap.icon_light_makeup_eyepupil_01, R.string.makeup_radio_contact_lens),
MAKEUP_EYEPUPIL_02("MAKEUP_EYEPUPIL_02", "light_makeup/eyepupil/mu_eyepupil_02.png", R.mipmap.icon_light_makeup_eyepupil_02, R.string.makeup_radio_contact_lens),
MAKEUP_EYEPUPIL_03("MAKEUP_EYEPUPIL_03", "light_makeup/eyepupil/mu_eyepupil_03.png", R.mipmap.icon_light_makeup_eyepupil_03, R.string.makeup_radio_contact_lens),
MAKEUP_EYEPUPIL_04("MAKEUP_EYEPUPIL_04", "light_makeup/eyepupil/mu_eyepupil_04.png", R.mipmap.icon_light_makeup_eyepupil_04, R.string.makeup_radio_contact_lens),
MAKEUP_EYEPUPIL_05("MAKEUP_EYEPUPIL_05", "light_makeup/eyepupil/mu_eyepupil_05.png", R.mipmap.icon_light_makeup_eyepupil_05, R.string.makeup_radio_contact_lens),
MAKEUP_EYEPUPIL_06("MAKEUP_EYEPUPIL_06", "light_makeup/eyepupil/mu_eyepupil_06.png", R.mipmap.icon_light_makeup_eyepupil_06, R.string.makeup_radio_contact_lens),
MAKEUP_EYEPUPIL_07("MAKEUP_EYEPUPIL_07", "light_makeup/eyepupil/mu_eyepupil_07.png", R.mipmap.icon_light_makeup_eyepupil_07, R.string.makeup_radio_contact_lens),
MAKEUP_EYEPUPIL_08("MAKEUP_EYEPUPIL_08", "light_makeup/eyepupil/mu_eyepupil_08.png", R.mipmap.icon_light_makeup_eyepupil_08, R.string.makeup_radio_contact_lens),
MAKEUP_EYEPUPIL_09("MAKEUP_EYEPUPIL_09", "light_makeup/eyepupil/mu_eyepupil_09.png", R.mipmap.icon_light_makeup_eyepupil_09, R.string.makeup_radio_contact_lens),
// 眼影
MAKEUP_EYE_SHADOW_01("MAKEUP_EYESHADOW_01", "light_makeup/eyeshadow/mu_eyeshadow_01.png", R.mipmap.icon_light_makeup_eyeshadow_01, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_02("MAKEUP_EYESHADOW_02", "light_makeup/eyeshadow/mu_eyeshadow_02.png", R.mipmap.icon_light_makeup_eyeshadow_02, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_03("MAKEUP_EYESHADOW_03", "light_makeup/eyeshadow/mu_eyeshadow_03.png", R.mipmap.icon_light_makeup_eyeshadow_03, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_04("MAKEUP_EYESHADOW_04", "light_makeup/eyeshadow/mu_eyeshadow_04.png", R.mipmap.icon_light_makeup_eyeshadow_04, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_05("MAKEUP_EYESHADOW_05", "light_makeup/eyeshadow/mu_eyeshadow_05.png", R.mipmap.icon_light_makeup_eyeshadow_05, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_06("MAKEUP_EYESHADOW_06", "light_makeup/eyeshadow/mu_eyeshadow_06.png", R.mipmap.icon_light_makeup_eyeshadow_06, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_07("MAKEUP_EYESHADOW_07", "light_makeup/eyeshadow/mu_eyeshadow_07.png", R.mipmap.icon_light_makeup_eyeshadow_07, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_08("MAKEUP_EYESHADOW_08", "light_makeup/eyeshadow/mu_eyeshadow_08.png", R.mipmap.icon_light_makeup_eyeshadow_08, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_09("MAKEUP_EYESHADOW_09", "light_makeup/eyeshadow/mu_eyeshadow_09.png", R.mipmap.icon_light_makeup_eyeshadow_09, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_10("MAKEUP_EYESHADOW_10", "light_makeup/eyeshadow/mu_eyeshadow_10.png", R.mipmap.icon_light_makeup_eyeshadow_10, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_11("MAKEUP_EYESHADOW_11", "light_makeup/eyeshadow/mu_eyeshadow_11.png", R.mipmap.icon_light_makeup_eyeshadow_11, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_12("MAKEUP_EYESHADOW_12", "light_makeup/eyeshadow/mu_eyeshadow_12.png", R.mipmap.icon_light_makeup_eyeshadow_12, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_13("MAKEUP_EYESHADOW_13", "light_makeup/eyeshadow/mu_eyeshadow_13.png", R.mipmap.icon_light_makeup_eyeshadow_13, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_14("MAKEUP_EYESHADOW_14", "light_makeup/eyeshadow/mu_eyeshadow_14.png", R.mipmap.icon_light_makeup_eyeshadow_14, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_15("MAKEUP_EYESHADOW_15", "light_makeup/eyeshadow/mu_eyeshadow_15.png", R.mipmap.icon_light_makeup_eyeshadow_15, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_16("MAKEUP_EYESHADOW_16", "light_makeup/eyeshadow/mu_eyeshadow_16.png", R.mipmap.icon_light_makeup_eyeshadow_16, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_17("MAKEUP_EYESHADOW_17", "light_makeup/eyeshadow/mu_eyeshadow_17.png", R.mipmap.icon_light_makeup_eyeshadow_17, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_18("MAKEUP_EYESHADOW_18", "light_makeup/eyeshadow/mu_eyeshadow_18.png", R.mipmap.icon_light_makeup_eyeshadow_18, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_19("MAKEUP_EYESHADOW_19", "light_makeup/eyeshadow/mu_eyeshadow_19.png", R.mipmap.icon_light_makeup_eyeshadow_19, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_20("MAKEUP_EYESHADOW_20", "light_makeup/eyeshadow/mu_eyeshadow_20.png", R.mipmap.icon_light_makeup_eyeshadow_20, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_21("MAKEUP_EYESHADOW_21", "light_makeup/eyeshadow/mu_eyeshadow_21.png", R.mipmap.icon_light_makeup_eyeshadow_21, R.string.makeup_radio_eye_shadow),
MAKEUP_EYE_SHADOW_22("MAKEUP_EYESHADOW_22", "light_makeup/eyeshadow/mu_eyeshadow_22.png", R.mipmap.icon_light_makeup_eyeshadow_22, R.string.makeup_radio_eye_shadow),
// 口红
MAKEUP_LIPSTICK_01("MAKEUP_LIPSTICK_01", "light_makeup/lipstick/mu_lip_01.json", R.mipmap.icon_light_makeup_lip_01, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_02("MAKEUP_LIPSTICK_02", "light_makeup/lipstick/mu_lip_02.json", R.mipmap.icon_light_makeup_lip_02, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_03("MAKEUP_LIPSTICK_03", "light_makeup/lipstick/mu_lip_03.json", R.mipmap.icon_light_makeup_lip_03, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_10("MAKEUP_LIPSTICK_10", "light_makeup/lipstick/mu_lip_10.json", R.mipmap.icon_light_makeup_lip_10, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_11("MAKEUP_LIPSTICK_11", "light_makeup/lipstick/mu_lip_11.json", R.mipmap.icon_light_makeup_lip_12, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_12("MAKEUP_LIPSTICK_12", "light_makeup/lipstick/mu_lip_12.json", R.mipmap.icon_light_makeup_lip_12, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_13("MAKEUP_LIPSTICK_13", "light_makeup/lipstick/mu_lip_13.json", R.mipmap.icon_light_makeup_lip_13, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_14("MAKEUP_LIPSTICK_14", "light_makeup/lipstick/mu_lip_14.json", R.mipmap.icon_light_makeup_lip_14, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_15("MAKEUP_LIPSTICK_15", "light_makeup/lipstick/mu_lip_15.json", R.mipmap.icon_light_makeup_lip_15, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_16("MAKEUP_LIPSTICK_16", "light_makeup/lipstick/mu_lip_16.json", R.mipmap.icon_light_makeup_lip_16, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_17("MAKEUP_LIPSTICK_17", "light_makeup/lipstick/mu_lip_17.json", R.mipmap.icon_light_makeup_lip_17, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_18("MAKEUP_LIPSTICK_18", "light_makeup/lipstick/mu_lip_18.json", R.mipmap.icon_light_makeup_lip_18, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_19("MAKEUP_LIPSTICK_19", "light_makeup/lipstick/mu_lip_19.json", R.mipmap.icon_light_makeup_lip_19, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_20("MAKEUP_LIPSTICK_20", "light_makeup/lipstick/mu_lip_20.json", R.mipmap.icon_light_makeup_lip_20, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_21("MAKEUP_LIPSTICK_21", "light_makeup/lipstick/mu_lip_21.json", R.mipmap.icon_light_makeup_lip_21, R.string.makeup_radio_lipstick),
MAKEUP_LIPSTICK_22("MAKEUP_LIPSTICK_22", "light_makeup/lipstick/mu_lip_22.json", R.mipmap.icon_light_makeup_lip_22, R.string.makeup_radio_lipstick);
private final String key;
private final String path;
private final int iconRes;
private final int strRes;
LightMakeUpEnum(String key, String path, int iconRes, int strRes) {
this.key = key;
this.path = path;
this.iconRes = iconRes;
this.strRes = strRes;
}
/**
* 获取口红颜色
*
* @return
*/
public FUColorRGBData getLipColorRGBData() {
double[] colorArray = loadRgbaColorFromLocal(FaceUnityData.mApplication, path);
if (colorArray != null && colorArray.length == 4) {
return new FUColorRGBData(colorArray[0] * 255, colorArray[1] * 255, colorArray[2] * 255, colorArray[3] * 255);
}
return new FUColorRGBData(0.0, 0.0, 0.0, 0.0);
}
}
//endregion
/**
* 读取 RGBA 颜色数据
*
* @param context
* @param path path
* @return
*/
public static double[] loadRgbaColorFromLocal(Context context, String path) {
InputStream inputStream = FileUtils.readInputStreamByPath(context, path);
if (inputStream != null) {
try {
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
JSONObject jsonObject = new JSONObject(new String(bytes));
JSONArray jsonArray = jsonObject.optJSONArray("rgba");
double[] colorArray = new double[jsonArray.length()];
for (int i = 0; i < jsonArray.length(); i++) {
colorArray[i] = jsonArray.optDouble(i);
}
return colorArray;
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
}

View File

@ -0,0 +1,107 @@
package com.yunbao.faceunity.repo;
import static android.content.Context.MODE_PRIVATE;
import android.content.SharedPreferences;
import com.faceunity.core.entity.FUBundleData;
import com.faceunity.core.entity.FUColorRGBData;
import com.faceunity.core.model.prop.humanOutline.HumanOutline;
import com.yunbao.faceunity.R;
import com.yunbao.faceunity.entity.FunctionEnum;
import com.yunbao.faceunity.entity.PropCustomBean;
import com.yunbao.faceunity.infe.AbstractPropCustomDataFactory;
import com.yunbao.faceunity.utils.FaceUnityConfig;
import com.yunbao.faceunity.utils.FaceUnityData;
import java.io.File;
import java.util.ArrayList;
/**
* DESC人像分割数据构造
* Created on 2021/3/28
*/
public class PortraitSegmentSource {
private static final String BG_SEG_CUSTOM_FILEPATH = "bg_seg_custom";
/**
* 缓存自定义添加人像
*
* @param path
*/
public static void saveCachePortraitSegment(String path) {
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(BG_SEG_CUSTOM_FILEPATH, MODE_PRIVATE);
sp.edit().putString(BG_SEG_CUSTOM_FILEPATH, path).apply();
}
/**
* 获取自定义添加人像
*
* @return
*/
public static String getCachePortraitSegment() {
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(BG_SEG_CUSTOM_FILEPATH, MODE_PRIVATE);
return sp.getString(BG_SEG_CUSTOM_FILEPATH, "");
}
/**
* 构造道具队列
*
* @return
*/
public static ArrayList<PropCustomBean> buildPropBeans() {
ArrayList<PropCustomBean> propBeans = new ArrayList<>();
propBeans.add(new PropCustomBean(R.mipmap.icon_control_delete_all, null, AbstractPropCustomDataFactory.TYPE_NONE));
propBeans.add(new PropCustomBean(R.mipmap.icon_control_add, null, AbstractPropCustomDataFactory.TYPE_ADD));
PropCustomBean customBean = buildPropCustomBean(getCachePortraitSegment());
if (customBean != null) {
propBeans.add(customBean);
}
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_human_outline, "effect/segment/human_outline.bundle", FunctionEnum.HUMAN_OUTLINE));
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_boyfriend_1, "effect/segment/boyfriend1.bundle", FunctionEnum.PORTRAIT_SEGMENT));
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_boyfriend_2, "effect/segment/boyfriend3.bundle", FunctionEnum.PORTRAIT_SEGMENT));
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_boyfriend_3, "effect/segment/boyfriend2.bundle", FunctionEnum.PORTRAIT_SEGMENT));
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_hez_ztt_fu, "effect/segment/hez_ztt_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT, R.string.hez_ztt_fu));
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_gufeng_zh_fu, "effect/segment/gufeng_zh_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT));
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_xiandai_ztt_fu, "effect/segment/xiandai_ztt_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT));
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_sea_lm_fu, "effect/segment/sea_lm_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT));
propBeans.add(new PropCustomBean(R.mipmap.icon_segment_ice_lm_fu, "effect/segment/ice_lm_fu.bundle", FunctionEnum.PORTRAIT_SEGMENT));
return propBeans;
}
/**
* 构造自定义人像分割
*
* @param path
* @return
*/
public static PropCustomBean buildPropCustomBean(String path) {
if (path != null && path.trim().length() > 0 && new File(path).exists()) {
saveCachePortraitSegment(path);
return new PropCustomBean(0, FaceUnityConfig.BUNDLE_BG_SEG_CUSTOM, FunctionEnum.BG_SEG_CUSTOM, 0, path );
}
return null;
}
/**
* 构造人像分割线模型
*
* @param path
* @return
*/
public static HumanOutline getHumanOutline(String path) {
HumanOutline humanOutline = new HumanOutline(new FUBundleData(path));
humanOutline.setLineSize(2.8);
humanOutline.setLineGap(2.8);
humanOutline.setLineColor(new FUColorRGBData(255.0, 196.0, 0.0));
return humanOutline;
}
}

View File

@ -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<>();
propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null)); switch (propType) {
propBeans.add(new PropBean(R.mipmap.icon_sticker_sdlu, "sticker/sdlu.bundle")); case FunctionEnum.STICKER:
propBeans.add(new PropBean(R.mipmap.icon_sticker_fashi, "sticker/fashi.bundle")); propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null));
propBeans.add(new PropBean(R.mipmap.icon_sticker_cat_sparks, "effect/normal/cat_sparks.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;
} }
} }

View File

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

View File

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

View File

@ -0,0 +1,271 @@
package com.yunbao.faceunity.utils;
import android.content.Context;
import android.content.SharedPreferences;
import com.faceunity.core.model.facebeauty.FaceBeauty;
import com.google.gson.Gson;
import com.yunbao.faceunity.data.FaceBeautyData;
import com.yunbao.faceunity.entity.FaceBeautyFilterBean;
import java.util.ArrayList;
/**
* 将FaceBeauty FaceBeautyData 互相设置
*/
public class FUUtils {
private static final String SP_NAME = "FaceBeauty";
private static final String SP_KEY_NAME = "faceBeautyData";
/**
* 将FaceBeauty FaceBeautyData
*
* @param faceBeautyData
*/
public static void buildFaceBeautyData(FaceBeautyData faceBeautyData, FaceBeauty faceBeauty, ArrayList<FaceBeautyFilterBean> filterList, int styleTypeIndex) {
if (faceBeauty != null) {
/* 美肤 */
/* 磨皮类型 */
faceBeautyData.blurType = faceBeauty.getBlurType();
/* 磨皮程度 */
faceBeautyData.blurIntensity = faceBeauty.getBlurIntensity();
/* 美白程度 */
faceBeautyData.colorIntensity = faceBeauty.getColorIntensity();
/* 红润程度 */
faceBeautyData.redIntensity = faceBeauty.getRedIntensity();
/* 锐化程度 */
faceBeautyData.sharpenIntensity = faceBeauty.getSharpenIntensity();
/* 亮眼程度 */
faceBeautyData.eyeBrightIntensity = faceBeauty.getEyeBrightIntensity();
/* 美牙程度 */
faceBeautyData.toothIntensity = faceBeauty.getToothIntensity();
/* 去黑眼圈强度*/
faceBeautyData.removePouchIntensity = faceBeauty.getRemovePouchIntensity();
/* 去法令纹强度*/
faceBeautyData.removeLawPatternIntensity = faceBeauty.getRemoveLawPatternIntensity();
/* 美型 */
/* 瘦脸程度 */
faceBeautyData.cheekThinningIntensity = faceBeauty.getCheekThinningIntensity();
/* V脸程度 */
faceBeautyData.cheekVIntensity = faceBeauty.getCheekVIntensity();
/* 窄脸程度 */
faceBeautyData.cheekNarrowIntensity = faceBeauty.getCheekNarrowIntensity();
/* 短脸程度 */
faceBeautyData.cheekShortIntensity = faceBeauty.getCheekShortIntensity();
/* 小脸程度 */
faceBeautyData.cheekSmallIntensity = faceBeauty.getCheekSmallIntensity();
/* 瘦颧骨 */
faceBeautyData.cheekBonesIntensity = faceBeauty.getCheekBonesIntensity();
/* 瘦下颌骨 */
faceBeautyData.lowerJawIntensity = faceBeauty.getLowerJawIntensity();
/* 大眼程度 */
faceBeautyData.eyeEnlargingIntensity = faceBeauty.getEyeEnlargingIntensity();
/* 圆眼程度 */
faceBeautyData.eyeCircleIntensity = faceBeauty.getEyeCircleIntensity();
/* 下巴调整程度 */
faceBeautyData.chinIntensity = faceBeauty.getChinIntensity();
/* 额头调整程度 */
faceBeautyData.forHeadIntensity = faceBeauty.getForHeadIntensity();
/* 瘦鼻程度 */
faceBeautyData.noseIntensity = faceBeauty.getNoseIntensity();
/* 嘴巴调整程度 */
faceBeautyData.mouthIntensity = faceBeauty.getMouthIntensity();
/* 开眼角强度 */
faceBeautyData.canthusIntensity = faceBeauty.getCanthusIntensity();
/* 眼睛间距 */
faceBeautyData.eyeSpaceIntensity = faceBeauty.getEyeSpaceIntensity();
/* 眼睛角度 */
faceBeautyData.eyeRotateIntensity = faceBeauty.getEyeRotateIntensity();
/* 鼻子长度 */
faceBeautyData.longNoseIntensity = faceBeauty.getLongNoseIntensity();
/* 调节人中 */
faceBeautyData.philtrumIntensity = faceBeauty.getPhiltrumIntensity();
/* 微笑嘴角强度 */
faceBeautyData.smileIntensity = faceBeauty.getSmileIntensity();
/* 眉毛上下 */
faceBeautyData.browHeightIntensity = faceBeauty.getBrowHeightIntensity();
/* 眉毛间距 */
faceBeautyData.browSpaceIntensity = faceBeauty.getBrowSpaceIntensity();
/* 滤镜相关 */
if (filterList != null) {
for (FaceBeautyFilterBean filterBean:filterList) {
faceBeautyData.filterMap.put(filterBean.getKey(),filterBean.getIntensity());
}
}
/* 滤镜名称 */
faceBeautyData.filterName = faceBeauty.getFilterName();
/* 滤镜强度 */
faceBeautyData.filterIntensity = faceBeauty.getFilterIntensity();
/* 是否开启风格 */
faceBeautyData.styleTypeIndex = styleTypeIndex;
}
}
/**
* 将FaceBeauty FaceBeautyData
*
* @param faceBeautyData
*/
public static boolean setFaceBeauty(FaceBeautyData faceBeautyData ,FaceBeauty faceBeauty) {
if (faceBeautyData == null) {
return false;
}
if (faceBeauty != null) {
/* 如果用户开启了风格推荐 */
//下面是否则
/* 美肤 */
/* 磨皮类型 */
if (faceBeautyData.blurType != faceBeauty.getBlurType())
faceBeauty.setBlurType(faceBeautyData.blurType);
/* 磨皮程度 */
if (faceBeautyData.blurIntensity != faceBeauty.getBlurIntensity())
faceBeauty.setBlurIntensity(faceBeautyData.blurIntensity);
/* 美白程度 */
if (faceBeautyData.colorIntensity != faceBeauty.getColorIntensity())
faceBeauty.setColorIntensity(faceBeautyData.colorIntensity);
/* 红润程度 */
if (faceBeautyData.redIntensity != faceBeauty.getRedIntensity())
faceBeauty.setRedIntensity(faceBeautyData.redIntensity);
/* 锐化程度 */
if (faceBeautyData.sharpenIntensity != faceBeauty.getSharpenIntensity())
faceBeauty.setSharpenIntensity(faceBeautyData.sharpenIntensity);
/* 亮眼程度 */
if (faceBeautyData.eyeBrightIntensity != faceBeauty.getEyeBrightIntensity())
faceBeauty.setEyeBrightIntensity(faceBeautyData.eyeBrightIntensity);
/* 美牙程度 */
if (faceBeautyData.toothIntensity != faceBeauty.getToothIntensity())
faceBeauty.setToothIntensity(faceBeautyData.toothIntensity);
/* 去黑眼圈强度*/
if (faceBeautyData.removePouchIntensity != faceBeauty.getRemovePouchIntensity())
faceBeauty.setRemovePouchIntensity(faceBeautyData.removePouchIntensity);
/* 去法令纹强度*/
if (faceBeautyData.removeLawPatternIntensity != faceBeauty.getRemoveLawPatternIntensity())
faceBeauty.setRemoveLawPatternIntensity(faceBeautyData.removeLawPatternIntensity);
/* 美型 */
/* 瘦脸程度 */
if (faceBeautyData.cheekThinningIntensity != faceBeauty.getCheekThinningIntensity())
faceBeauty.setCheekThinningIntensity(faceBeautyData.cheekThinningIntensity);
/* V脸程度 */
if (faceBeautyData.cheekVIntensity != faceBeauty.getCheekVIntensity())
faceBeauty.setCheekVIntensity(faceBeautyData.cheekVIntensity);
/* 窄脸程度 */
/* V脸程度 */
if (faceBeautyData.cheekNarrowIntensity != faceBeauty.getCheekNarrowIntensity())
faceBeauty.setCheekNarrowIntensity(faceBeautyData.cheekNarrowIntensity);
/* 短脸程度 */
if (faceBeautyData.cheekShortIntensity != faceBeauty.getCheekShortIntensity())
faceBeauty.setCheekShortIntensity(faceBeautyData.cheekShortIntensity);
/* 小脸程度 */
if (faceBeautyData.cheekSmallIntensity != faceBeauty.getCheekSmallIntensity())
faceBeauty.setCheekSmallIntensity(faceBeautyData.cheekSmallIntensity);
/* 瘦颧骨 */
if (faceBeautyData.cheekBonesIntensity != faceBeauty.getCheekBonesIntensity())
faceBeauty.setCheekBonesIntensity(faceBeautyData.cheekBonesIntensity);
/* 瘦下颌骨 */
if (faceBeautyData.lowerJawIntensity != faceBeauty.getLowerJawIntensity())
faceBeauty.setLowerJawIntensity(faceBeautyData.lowerJawIntensity);
/* 大眼程度 */
if (faceBeautyData.eyeEnlargingIntensity != faceBeauty.getEyeEnlargingIntensity())
faceBeauty.setEyeEnlargingIntensity(faceBeautyData.eyeEnlargingIntensity);
/* 圆眼程度 */
if (faceBeautyData.eyeCircleIntensity != faceBeauty.getEyeCircleIntensity())
faceBeauty.setEyeCircleIntensity(faceBeautyData.eyeCircleIntensity);
/* 下巴调整程度 */
if (faceBeautyData.chinIntensity != faceBeauty.getChinIntensity())
faceBeauty.setChinIntensity(faceBeautyData.chinIntensity);
/* 额头调整程度 */
if (faceBeautyData.forHeadIntensity != faceBeauty.getForHeadIntensity())
faceBeauty.setForHeadIntensity(faceBeautyData.forHeadIntensity);
/* 瘦鼻程度 */
if (faceBeautyData.noseIntensity != faceBeauty.getNoseIntensity())
faceBeauty.setNoseIntensity(faceBeautyData.noseIntensity);
/* 嘴巴调整程度 */
if (faceBeautyData.mouthIntensity != faceBeauty.getMouthIntensity())
faceBeauty.setMouthIntensity(faceBeautyData.mouthIntensity);
/* 开眼角强度 */
if (faceBeautyData.canthusIntensity != faceBeauty.getCanthusIntensity())
faceBeauty.setCanthusIntensity(faceBeautyData.canthusIntensity);
/* 眼睛间距 */
if (faceBeautyData.eyeSpaceIntensity != faceBeauty.getEyeSpaceIntensity())
faceBeauty.setEyeSpaceIntensity(faceBeautyData.eyeSpaceIntensity);
/* 眼睛角度 */
if (faceBeautyData.eyeRotateIntensity != faceBeauty.getEyeRotateIntensity())
faceBeauty.setEyeRotateIntensity(faceBeautyData.eyeRotateIntensity);
/* 鼻子长度 */
if (faceBeautyData.longNoseIntensity != faceBeauty.getLongNoseIntensity())
faceBeauty.setLongNoseIntensity(faceBeautyData.longNoseIntensity);
/* 调节人中 */
if (faceBeautyData.philtrumIntensity != faceBeauty.getPhiltrumIntensity())
faceBeauty.setPhiltrumIntensity(faceBeautyData.philtrumIntensity);
/* 微笑嘴角强度 */
if (faceBeautyData.smileIntensity != faceBeauty.getSmileIntensity())
faceBeauty.setSmileIntensity(faceBeautyData.smileIntensity);
/* 眉毛上下 */
if (faceBeautyData.browHeightIntensity != faceBeauty.getBrowHeightIntensity())
faceBeauty.setBrowHeightIntensity(faceBeautyData.browHeightIntensity);
/* 眉毛间距 */
if (faceBeautyData.browSpaceIntensity != faceBeauty.getBrowSpaceIntensity())
faceBeauty.setBrowSpaceIntensity(faceBeautyData.browSpaceIntensity);
/* 滤镜相关 */
/* 滤镜名称 */
if (!faceBeautyData.filterName.equals(faceBeauty.getFilterName()))
faceBeauty.setFilterName(faceBeautyData.filterName);
if (faceBeautyData.filterIntensity != faceBeauty.getFilterIntensity())
faceBeauty.setFilterIntensity(faceBeautyData.filterIntensity);
return true;
}
return false;
}
/**
* 将FaceBeautyData保存到文件
*
* @param faceBeautyData
*/
public static void saveFaceBeautyData2File(FaceBeautyData faceBeautyData, FaceBeauty faceBeauty, ArrayList<FaceBeautyFilterBean> filterList, int styleTypeIndex) {
buildFaceBeautyData(faceBeautyData,faceBeauty,filterList,styleTypeIndex);
saveFaceBeautyData2File(faceBeautyData);
}
/**
* 将FaceBeautyData保存到文件
*
* @param faceBeautyData
*/
public static void saveFaceBeautyData2File(FaceBeautyData faceBeautyData) {
Gson gson = new Gson();
String faceBeautyString = gson.toJson(faceBeautyData);
saveToSp(SP_KEY_NAME, faceBeautyString);
}
/**
* 获取bean对象
*
* @return
*/
public static FaceBeautyData loadFaceBeautyData() {
String faceBeautyData = loadFormSp(SP_KEY_NAME);
if (faceBeautyData != null && !faceBeautyData.isEmpty()) {
Gson gson = new Gson();
FaceBeautyData faceBeautyDataBean = gson.fromJson(faceBeautyData, FaceBeautyData.class);
return faceBeautyDataBean;
}
return null;
}
private static void saveToSp(String key, String value) {
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
sp.edit().putString(key, value).apply();
}
private static String loadFormSp(String key) {
SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
return sp.getString(key, "");
}
}

View File

@ -0,0 +1,7 @@
package com.yunbao.faceunity.utils;
import android.content.Context;
public class FaceUnityData {
public static Context mApplication;
}

View File

@ -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);//2020分别是图的宽度与高度
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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

@ -3,96 +3,79 @@
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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="@dimen/x268"
android:background="#BD050F14"
android:gravity="center_horizontal"
android:orientation="vertical"> android:orientation="vertical">
<androidx.appcompat.widget.SwitchCompat <com.yunbao.faceunity.seekbar.DiscreteSeekBar
android:id="@+id/switch_compat" android:id="@+id/beauty_seek_bar"
android:layout_width="wrap_content" android:layout_width="@dimen/x528"
android:layout_height="wrap_content" android:layout_height="@dimen/x48"
android:layout_marginTop="@dimen/x20" android:layout_marginTop="@dimen/x24"
android:layout_marginBottom="@dimen/x20" android:layout_marginBottom="@dimen/x16"
android:checked="true" app:dsb_indicatorColor="@color/main_color"
android:theme="@style/SwitchCompat" app:dsb_indicatorElevation="0dp"
android:layout_marginStart="@dimen/x10" /> app:dsb_indicatorPopupEnabled="true"
app:dsb_max="100"
app:dsb_min="0"
app:dsb_progressColor="@color/main_color"
app:dsb_rippleColor="@color/main_color"
app:dsb_scrubberHeight="@dimen/x4"
app:dsb_thumbSize="@dimen/x32"
app:dsb_trackBaseHeight="@dimen/x16"
app:dsb_trackColor="@color/colorWhite"
app:dsb_trackHeight="@dimen/x4"
app:dsb_value="0" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/x268" android:layout_height="@dimen/x180"
android:background="#BD050F14" android:layout_gravity="bottom"
android:gravity="center_horizontal" android:orientation="horizontal">
android:orientation="vertical">
<com.yunbao.faceunity.seekbar.DiscreteSeekBar
android:id="@+id/seek_bar"
android:layout_width="@dimen/x528"
android:layout_height="@dimen/x48"
android:layout_marginTop="@dimen/x24"
android:layout_marginBottom="@dimen/x16"
app:dsb_indicatorColor="@color/main_color"
app:dsb_indicatorElevation="0dp"
app:dsb_indicatorPopupEnabled="true"
app:dsb_max="100"
app:dsb_min="0"
app:dsb_progressColor="@color/main_color"
app:dsb_rippleColor="@color/main_color"
app:dsb_scrubberHeight="@dimen/x4"
app:dsb_thumbSize="@dimen/x32"
app:dsb_trackBaseHeight="@dimen/x16"
app:dsb_trackColor="@color/colorWhite"
app:dsb_trackHeight="@dimen/x4"
app:dsb_value="0" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:id="@+id/lyt_beauty_recover"
android:layout_width="@dimen/x132"
android:layout_height="@dimen/x180" android:layout_height="@dimen/x180"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:orientation="horizontal"> android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout <ImageView
android:id="@+id/lyt_beauty_recover" android:id="@+id/iv_beauty_recover"
android:layout_width="@dimen/x132" android:layout_width="@dimen/x88"
android:layout_height="@dimen/x180" android:layout_height="@dimen/x88"
android:layout_gravity="bottom" android:layout_marginBottom="@dimen/x18"
android:gravity="center_horizontal" android:scaleType="centerInside"
android:orientation="vertical"> android:src="@mipmap/icon_control_recover" />
<ImageView
android:id="@+id/iv_beauty_recover"
android:layout_width="@dimen/x88"
android:layout_height="@dimen/x88"
android:layout_marginBottom="@dimen/x18"
android:scaleType="centerInside"
android:src="@mipmap/icon_control_recover" />
<TextView <TextView
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:layout_marginBottom="@dimen/x30" android:layout_marginBottom="@dimen/x30"
android:gravity="center_vertical" 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>
<View
android:id="@+id/iv_line"
android:layout_width="@dimen/x1"
android:layout_height="@dimen/x40"
android:layout_marginTop="@dimen/x40"
android:background="@color/divider_line_color" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="@dimen/x180" />
</LinearLayout> </LinearLayout>
<View
android:id="@+id/iv_line"
android:layout_width="@dimen/x1"
android:layout_height="@dimen/x40"
android:layout_marginTop="@dimen/x40"
android:background="@color/divider_line_color" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="@dimen/x180" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -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
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switch_compat"
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_marginBottom="@dimen/x20" <com.yunbao.faceunity.widget.TouchStateImageView
android:checked="true" android:id="@+id/iv_compare"
android:theme="@style/SwitchCompat" android:layout_width="@dimen/x72"
android:layout_marginLeft="@dimen/x10" /> 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_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginEnd="@dimen/x34"
android:text="去除效果"
android:visibility="gone" />
</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>

View File

@ -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" android:layout_height="wrap_content">
android:layout_gravity="bottom"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/menu_group"
<com.yunbao.faceunity.control.BodyBeautyControlView
android:id="@+id/control_body"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent" />
android:layout_gravity="bottom" </LinearLayout>
android:visibility="gone" /> <LinearLayout
android:id="@+id/layout_faceunity_menu2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.yunbao.faceunity.control.FaceBeautyControlView
android:id="@+id/control_beauty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
<com.yunbao.faceunity.control.MakeupControlView <com.google.android.material.tabs.TabLayout
android:id="@+id/control_makeup"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent">
android:layout_gravity="bottom"
android:visibility="gone" />
<com.yunbao.faceunity.control.PropControlView <com.google.android.material.tabs.TabItem
android:id="@+id/control_prop" android:layout_width="wrap_content"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:text="Monday" />
android:layout_gravity="bottom"
android:visibility="gone" />
<ImageView <com.google.android.material.tabs.TabItem
android:id="@+id/line" android:layout_width="wrap_content"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="@dimen/x1" android:text="Tuesday" />
android:background="@color/primary_list"
android:src="@color/divider_line_color" /> <com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wednesday" />
</com.google.android.material.tabs.TabLayout>
</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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Some files were not shown because too many files have changed in this diff Show More