diff --git a/FaceUnity/.gitignore b/FaceUnity/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/FaceUnity/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/FaceUnity/build.gradle b/FaceUnity/build.gradle new file mode 100644 index 000000000..23ed7d11f --- /dev/null +++ b/FaceUnity/build.gradle @@ -0,0 +1,73 @@ +apply plugin: 'com.android.library' +apply plugin: 'img-optimizer' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + + +android { + compileSdkVersion rootProject.ext.android.compileSdkVersion + buildToolsVersion rootProject.ext.android.buildToolsVersion + packagingOptions { + pickFirst "lib/armeabi/libyuvutils.so" + pickFirst "lib/arm64-v8a/libyuvutils.so" + pickFirst "lib/armeabi-v7a/libyuvutils.so" + pickFirst "lib/armeabi/libyuvtools.so" + pickFirst "lib/arm64-v8a/libyuvtools.so" + pickFirst "lib/armeabi-v7a/libyuvtools.so" + exclude "lib/arm64-v8a/libmmcv_api_handgesture.so" + exclude "lib/arm64-v8a/libmmcv_api_express.so" + exclude "lib/arm64-v8a/libMediaEncoder.so" + exclude "lib/arm64-v8a/libarcore_sdk_c.so" + exclude "lib/arm64-v8a/libmediadecoder.so" + exclude "lib/arm64-v8a/libMediaMuxer.so" + exclude "lib/arm64-v8a/libarcore_sdk_jni.so" + exclude "lib/arm64-v8a/libMediaUtils.so" + exclude "lib/arm64-v8a/libcosmosffmpeg.so" + + } + + defaultConfig { + minSdkVersion rootProject.ext.android.minSdkVersion + targetSdkVersion rootProject.ext.android.targetSdkVersion + versionCode rootProject.ext.android.versionCode + versionName rootProject.ext.android.versionName + manifestPlaceholders = rootProject.ext.manifestPlaceholders + ndk { + abiFilters "armeabi-v7a","arm64-v8a" + } + } + aaptOptions { + cruncherEnabled = false + useNewCruncher = false + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} +repositories { + flatDir { + dirs 'libs','../libs' + } +} +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation rootProject.ext.dependencies["appcompat-androidx"] + implementation rootProject.ext.dependencies["recyclerview-androidx"] + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + //common + implementation project(path: ':common') + + implementation 'com.faceunity:core:8.3.1' + implementation 'com.faceunity:model:8.3.1' + //implementation 'com.faceunity:nama:8.3.1' //底层库-标准版 + + +} diff --git a/FaceUnity/consumer-rules.pro b/FaceUnity/consumer-rules.pro new file mode 100644 index 000000000..e69de29bb diff --git a/FaceUnity/proguard-rules.pro b/FaceUnity/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/FaceUnity/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/FaceUnity/src/androidTest/java/com/yunbao/faceunity/ExampleInstrumentedTest.java b/FaceUnity/src/androidTest/java/com/yunbao/faceunity/ExampleInstrumentedTest.java new file mode 100644 index 000000000..d54eb1cba --- /dev/null +++ b/FaceUnity/src/androidTest/java/com/yunbao/faceunity/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.yunbao.faceunity; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.yunbao.faceunity.test", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/AndroidManifest.xml b/FaceUnity/src/main/AndroidManifest.xml new file mode 100644 index 000000000..7d49364e3 --- /dev/null +++ b/FaceUnity/src/main/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/assets/animation/animation_data.json b/FaceUnity/src/main/assets/animation/animation_data.json new file mode 100644 index 000000000..b7a3af2a2 --- /dev/null +++ b/FaceUnity/src/main/assets/animation/animation_data.json @@ -0,0 +1,6469 @@ +{ + "v": "5.7.3", + "fr": 30, + "ip": 0, + "op": 83, + "w": 202, + "h": 244, + "nm": "精品贴纸- icon", + "ddd": 0, + "assets": [ + { + "id": "imgSeq_0", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAA1klEQVR4nO3BgQAAAADDoPlTn+AGVQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AwDQQABuUTdfAAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "imgSeq_1", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAABHklEQVR4nO3VMQ7CQAxFwe+IFNz/tBTEFHCBNOtEzEjun2ytNgEAAAAAAABgre6u7q7pDtZ4TAfcTXdvSeo3R5KeLWKFbTrghrYke5K9qo7pGNbwUM7rJM/Y3V9x7JOq6p3vj/KabgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBr+wBxwA8aMZdeyAAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "imgSeq_2", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAACiklEQVR4nO3avW5cVRQF4LUNjo3/I9HwBPTpaBAVT5GXyAulTeOC1qRLkwhEkSIIgURBDYWhi2LvFPcOM3JACkhwxr7fJx1pfpqlK63Z59y5CQAAAAAAAMC/VKMD3Hbd/ec1rKoemYX/jqL8Q5vFyLvXr5XlblKU9/A35ejEFFmKD0cHuEVqY10pyLLsjA6wbbp758YESaZyfJDph8X2aoEUZUN372Qqw19N2t0kqaqr/zUUW0FRZvMU2Z/X0Y27WdeZJsrrQfEYzBllbS/JQZJ7mcpyleT31ZdV9cegXGwBd72SdPdeko+TfDSvgyTXSb6bpwkLt9iizOeR/SQnSY4yleMwyfHGepPk2yQ/OsAv2+KKMhdkVYjV9Dia359mKs7JxuvjJL8l+aqqXozIzHhLLEolOUvySdalWBXjbF6bn6+mzUGSZ1X1aEBsBltcUVa6ezfJp0keZDqf3M9UktOst15HmbZnL5OcJ7moKne+FmixRVnp7uMkD5N8lvUUOcx06/xJkvOq+mVcQtgS3X3a3Rfd/U13v+run7v7y9G52B7+cExSVZdJvs96C/ZTVX09NhVsoe7+ort/7e7L7v58dB7YSvPDkD9099PRWdg+HmGZVdV1dz9O8nx0FgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4694CTRODih0VhXQAAAAASUVORK5CYII=", + "e": 1 + }, + { + "id": "imgSeq_3", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAADfElEQVR4nO3au6odVRwG8G/OxRPvIMRLZ28pKBLRzsIUgtoKvoLPYNDeSnwDG5/AwgcQwSLaBYKKIeQiXjCXk/NZ7DnnDNvEWJ3Zyfx+sJi9157iz8DH+q9ZOwEAAAAAAAAAgFkNcxfwoGl79MyGYeictXByBOV/mIZjNA3LwQmXwwwE5T+sBWT98zQs+ydWFLPYmbuAB8AwuR6uHp3Otx20YQ83QVnTdis5aqm2DueHYbizfutJ1sW8tu5/y3KMIXkkyfbYdh2GZj0kLMz23AVsijEkjybZHaf2k9RmnUTrleQoJI9n9Tx2kmwPw/B3tFeMFheUsaU6HNvjOJXVs9gdr/tJrs9VI5tnUUEZV47dHAdkZzJ2JyNtf/Umi0OLO0dpu5NVmzUNxk5Wm/jpqnItyQVhIVlgUJKk7W6SZ5Ps5d+BOdqnJLma5LwNPYsMSpK03UvyYo7fdE0Dsp3Vq+GtrPYq3zl9X7bFnqMMw3AzqxCcGsdeVu3XemhOJ3ntLv/3YkEWtZm/i9tZBWQnxyvIb1kF6EaSm+P1hr3Ksi0qKG2fTrI3DMPlcepWVqvIYUguDsPww1z1sbmW1np9lOTdyfdbOd6TXBIS7mUxQWn7RpJ3krx9ODcMw+3x45Uk389RF2yMtk+0/abtxbaX2z43+e2ltv7zBm0/bvtL26tt/2j7wdw1wUZou9325baftr3U9nrbv9rebPvV3PXxYHmozgbaPpnklSRvJnkryQtJHsvxK+DpQeK5JJ+M5ymwHG3PtP267Y9tf257ZWy1brS91Xa/7Z22B+M43/bM3HXDiWt7uu0Xba+1/XNstW6PAZmG5KDHPh/PWGBZ2p5te2ESkoN7hKRtv2373tw1wyzG1eXiXULye9sv237Y9vm564TZtT23FpLzbZ+Zuy7YKG1fn7RaB21fnbsm2Djjecr1MSifzV0PbKxxP/JT26fmrgU2Vtv3256duw4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOB+/gGp78J5A6UmWgAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "imgSeq_4", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFNklEQVR4nO3cu6tlVx0H8O+688xDwqhRCAo24gttjCE+IBFHfBQ+QASFWFmI2AgKFlqI/4FoI6YQBK1sLFSwEQ1ICtMNFikMaKeJUZPBzNz5Wux9kjN37tyZCHP3ued8PrA5z+K3D/u711p7rbMTAAAAAAAAAAAAAHZL29F2LF0Hx+/00gVsOsEgSRwEN3FIQK57Pca4dozlLK7tGGN06TqWokU54BYtyE6eWObfZLTNroZFUI5w4KDo6oBJstd2b8dalb0k+0sXwYZoe6rtqdv43la0LvP+3nJf2u4dRz2baqd3/qC2Z5KczW38LlvUBflckkdv9aUdaz1vsFNdr/Uz5/qBPrcgZzIFZC/JleOv7vjN+/1Ykv+0/f0Y4+rSNW2qXWtRRpJTSU63Pdv2XNvzSc5lOmmcmrddOXt+NMk7krwnyScWrmWj7VpQmnkwnldCsR6QU0l2aZD+lST3JbmQ5Btz15ND7FRQ5u5WMwfikMe9+fOt1nav7VeTfDzJXUnuSfLuJD9p+65Fi9tQW3Hl5tVqe3emlmQv02+wviXJs9vYqsxXrj6f5DtJ3p7ppHBtftyfn19J8mSSx5P8coxxeZlqN8uuBuVsprPoYSEZSf47xnh+ofLuiLYfTvLDTAG57qMD236Sq/P24zHGN4+zzk21U12vNatxys1alPNtzy1U253ypyQ/SvLnXH+CXP8tVmO23yS5KCSv2NUW5Z5MffP1cOTA8/0k/9ii+ZKXtX00ydeTfCrXj8meSvLlMcZTS9S1yXY1KPdlmlhc7f+LmfrmqzPqars8xvj3IkUeg7a/SPLZ+eW1JG8bYzy9YElsgran27657evavqHthbY3nXTdlmUqN9P2nW2vdfKrpethA8yTix9s+3Db+9vetXRNm6Dtz+egfGbpWlhY27vbPtL2k3NQdvUixg3mVuWZo1pWdmCt1zweeTDTMpWRZGzjHMn/a4xxqe0j1nkdbWuC0vZCkgcyDdJXy1JW8yWrFmRkWvzImjHGX5auYdNtTVCS/DPJmzKtW3p53VZuvASs28WrtjUHzTzfcSnTpd7DQrJ6fm/b1y5SJCfW1gQlScYY+5lmoC/nxpBk7flDbV9zzOVxgm1VUJJkjPFSpkV9qxnnw+ZCziR52CVibtfWBSVJ5hWvz+folQfnk7x/XiAJR9qmwfxBB9do7Sd5NtffSWQ/yf1J/nZcRXEybU1Q5pbhsTHG44d8/GKSP44xXjjmstgS29T1+l6S7669Xt0g4l9JnhASdl7bi2335wV+b5nfe9+8tssEI7R9fdu/ziG51vYL8/tvvJ0b2cHWmxc7/notJNfa/mDputg+J2owP/8z8cEkH5i3D2W63c66izt4X2CYtP1i2+faXm77Utura+OS1bby07b3Ll0zLKLtl+awHBWSlafbPrR0zbCItm9t++QtQrJype23/FGLndT2TNvv3yIkK5fafmzpmjnZTuzNE+ZW4plM/0FZ94ckv0vyRKbZ+OeOuzbYKG1/dqD1+PbSNcHGafu1tZD81lgEDtH2vXNI/t72gaXrgY3U6YZ2L7T99NK1wEZr+5GlawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADuvP8Bl+6iPXcFJh8AAAAASUVORK5CYII=", + "e": 1 + }, + { + "id": "imgSeq_5", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGU0lEQVR4nO3dwYtdVx0H8N+ZTNq0CTGmlliKFlqRqqDG1iCitepCRIpupHShIPgHuBJxIQZxIy5ExJ0LwY0giCDoRlRUurEt6EJQJIjagEKthdYkk5mvi3tf8nzJTFLbvPPefZ8PXOa9mxn43Zn3e79zfu/ckyoAAAAAAAAAAAAAAABuJEnrHcOq2O4dACutJRketJbOsXS11TsAVtNYTa4cm15dJAoH2RqPqChwfbNqsrfpSQL7SrLxw62N5Q9/rSSHe8ewDjZu6JVkazzadc4fSnI4yaFe8S1TkhNVdaZ3HOtgU9vDs07O7PnW3Plqre32CGqZxkryrqo6kmS7tXa5d0yrbOMqSs21POtqV2f2vKpqr1Ncy3a6qu6s4bqPd45l5W16otTc15lJV5MkR5O8vapO1dXfw4m+Ua2+jRp6tdYyN9xaTJBWVbtTa4UmOV5V91bVa2pIiMXJe6uqe5Kcm9q1v5o2qqKME/jZUGtmvrpM8YVyqapOVtXddW2SzJysqnfrgO1vo9qlYzdr1tG63rXvtdZ2lhjSUiTZqqoHq+qBG3zrf6rqt6215299VOtl0xLltvHhvtfdWru4pHCWLsnra+h0HdT+3quqZ1przy4nqvWwMYkyVpP5OVnGY37oVVW101qbbOcryVuq6k0Lp1+oqufH499V9cKUfwf/j02azB+q4d1yrxbWL80NyWZzmCm/SJ5beP50a+3vXSJZIxszmW+tXRrnH9uL3Z3W2m5r7VJV7dT0q+z8/OPPkuTmTKaiJNk6aLiQ5EhVHauhWlx3HjL+/JSrSbXWLia5UFUvVdUfesezLiaTKFV1bBxCXR6PnRo+PLythgSZXeuFPuGtlGdrqCZTbIffEpMZZowdreN17eR88Rr/NQ6z4KZNZo4yvvh36+AkqRoqzSQlOZPk073jmKLJVJSqK1XlRO1/XTuttcWuz2Qk+UVVnWitvbN3LFMzmYpSdaWqHLRcfFJvDPOSPFpVH6iqdyR5qHM4kzOpRBkdlCjbc5/OT83Zucef7RbFRE0xUW60sO/YUqJYkiR3JDlbVY/Mnf5UksVP33kFJpUo4+K/G7W8Dye5fRnx3EpJTif5VlWdr6ovLfzz0ap6KsmXx9t94aokR5KcmjtOjOfuHB/fPZ6/q3esr0SS7+fmPZfkC0mO9o6bFTBuCvFIknuTvHa/eyuSbI+Js7YT+3G49bkk528yWX6V5D2946azDLe3fjDJJ8elKhshybGxWrx4neT4R5KvJ3mwd5ysgCSvS/KRJI8leax3PD0keWIhSX6TZFJNi97WYvgx/tHvqiHeyzXcR7Jbw4eLD9TVpsTl1tpPugTZ0TjM/GsNG0ZUVT3UWnu6Y0iTsy6LIi9W1X01tHYP2kFlIxf5tdZ2kny3qj5fVT+SJK++tWgPj/eRPFX/u5ZrLarhEn2nhlsEzt7oG3n51iJRqqpaay9W1eydcr8kOZzkjUsKaaW01v5YVY+31p7pHcsUrd27cpL7q+ptB3zLXlU9OeXFjyzf2lSUOedq2KtqP1tV9XCSO5YUDxtg7RJlvCvvRhtK315VZ5KsS7OCFbc2L6QkH26t/Wx8urgv1fkadhfZrmE4Oft6vK7ddQRetrVIlAybSv84yVtba+fqaiVMVf2+tfaXftGxCVZ+6DUuSfleDcOp946nt2u4pfdJSQJVleSbSfbG49vjuUethoVRko8n2Z1LlN/1jonNtFKfo4xrlk5X1fuq6v1V9bG6Oo9qNcxJTrXW/tknQugoyX1JfjDeX/FSkktJLi9Uk5mfJjnZO2boIsnjY6JcSLKzT5LM/C3Jh3rHDF0kuT/Jrw+oJvP2knwt091VBfaX4Vbdr8wlykH2knyjd8zQTYYNFBYT5UKSnyf5apKPxg4jbLokn1lIkj8luad3XLBSkrx5Lkl2kjzcOyZYSRl2EkmSL/aOBVZWkh8m+WWG/yAIuJ4kn0jyht5xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAmvsv5qWgrSeSe80AAAAASUVORK5CYII=", + "e": 1 + }, + { + "id": "imgSeq_6", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAHMklEQVR4nO3dX4icVx3G8ee3uyZNk6b/VIJijbWmfyhWaGlFhaKIFkFB6YXipb0QShWhXueiFEopFOxVL9RbW/Cu0NpeiVRcFKGYG9FaEYvYJjZZm2YzuzOPF+dM9p13d2c2Nfueec98PzBMduZd+O1mn/ec855z3pEAAAAAAAAAAAAAAAAAAAAAAACwE9tRuoZ5xC8FE5pBiQiXrGWeEBRM2KlFITAEBS22l5pfNt9b5MAszT4ECyZ2eEha7PELQcElOQjNcFitVmVRw7JSugDMlfGJc7jI3SwAAAAA3bMdto/aXi5dSx9w1WsB5XBcL+lQ6Vr6gqteFbO9onR5dzS+imX7oKSj2jpJjgqV1ysEpW7XSDogSXbKiVqrMbgMvDd0vep2TpMtRnuykJDsEUGpWESMlMKy6yG2P9BVPX1GUCoXEQNJ70455NpFXZZyOQjKYlif8t6ypGu7KqSvCMpimNViHLR9uJNKeqqaq162gys4u2oGxZL+K2mQX18S+5JmqiYoklacroGy8nW7cc9hU9LZiBiWLKaPagqKlP4glm0P1QhMHqxeOnNGxGa5EosIpXHKGieR96eaJjcvy2gHf9sEm6SNfNkU2LOaBvM7nSnbIRkRErwftQelrdouV14NfKJ0HbWqKSiz1D7I/7SkE0we7o+agjJrX0W1XS7bt0m6SamrebBwOVWqIij5LDorKNWdaW2v2L5V0qcaL7PHZB/Ucnl4Lz9H74Ni+2ZJH5Z0VX7stKDxkKR3uqxrEfS+Rcl3Nhz/HFbqYg3zo6n3P6ukf0m6WmmfyW6rfo+37vaIK6CGs+x4InHUHqznLtmKckgi4mL3FV5Ztg9Iuk/SdVMOe1vS75mBv3J6H5SxHJirJV1o/4Hk91YkbdYwj5K3+N4r6cYph52VtJqX2eP/1Iug2D6iVOtA0qDZcuQZ+cNKfXZFxFtFiuxY/p18ccZhZyPiN13UU7u+DOYHSl2NQ5JkeyO/tqIckGzavovanNfkEp2Lkv6itElrXdJ6RGwUqq06vQhKRAxsb2prAHsgP9oWppsREbZ9UelEMZD0akScL1xWtfp0deS9PRzT+8H6ZVpXWpazSkj2V2+CEhHr2n7Jt6mKgfplOi/pDxFxtnQhtevFYH7M9jVKV7Z2MpJ0uvL1XBPY1dmd3rQo2bQx1ZImB/a9lpen3DPtGELSnd4EJU8ezroHVU03SHhU0lOli0DSm65XvmduezZ6pO1hP5fHM71l+5OSTim1oDdGxFrhkhZeb1oUSXdIuiH/e13SmYh4W2m5xlp+zdp9DNMLueV8VqkbuSLpy2UrQi/YXrL9GdvftX3LrM/zyGuhesn2VbYf86Sfla4Lc971yvfFvUfSB5Vq/V1tS1Ty0vmvSXpA0pe0fT/JuqRvRsRLXdeGLcWDkrsa47HH+KObh0pdj9slHWkc/tuIONNthfvH9sclvSrpo3s4/OeSHo2I/+xvVdjJvATlLqUNScuavHNhu76qgiJJto9KelzSw5r9//GWpB9ExHP7XhgmFB/M57mAU0pLVGb9oVT3eYMRsRYRj0j6vKQ/Tzl0mN8/3kVdmFS8RRmzfUjSFzR5c4R2faeVxilVTrTZ/oikv2nyd/CiUrfrFZaqlDM3QZEk29dJ+pym3zj67xHxp+6q6pbtX0n6Sv7yZUkP1Hpi6JPiXa+mfMb8x4zDjucrRbV6MT9fkPR9QjIf5iIoeUA7tpexyh22j+1jSSW9kJ9PRsQbRSvBJfOycet52ycjYlXbaxootTLjJfTje3gdUYUi4q+2fyrp6dK1YEvxoNj+hqT7JT0oabX19prSpqRer926XBHxUOkaMEdsH7R9yvZF26/n107Y/rrte/PdRoDFZvtHtt+1PbC9aftu27fZvpObTQOSbN9n+03b79neyEF5klYEC8/2Mdvfsf0L2/+0fc72eg7KMIfm26XrBNo66d7YvklphexnlT6e4JjS3pLDSrcdWtbWgsiQ9GtJP4yI17qoD5ilq3mUf0t6U2kr74H83F4A2XS/pD/aftb2hzqqEZgPtj9m+xnbb9g+Y/tCY3wytD1qbVp63fb3StcNFGH7q3mM0hyfjBrheML23aXrBIqz/eM8fzJuTTZsf6t0XcBcsf2JxvzJ0PZPStcEzCXbqzkop23fMPs7gDJKrx7+ZX4+yV5wYBe2b7b9GrPxwAx5VyMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHPqf7dG01YJ2bpsAAAAAElFTkSuQmCC", + "e": 1 + }, + { + "id": "imgSeq_7", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAHqElEQVR4nO3dy4tkVx3A8e+vn07PTJhJGENUgg98ER9ETUiiC0XEhdsguBRDVoIuXIj+E+paia5cCOIDQdAsFGOEaHwGJRHRLDREGZmM0zOZ6e6fi3Nud01PV1U6Xbdu3VvfD1ymu+4d6nRV/eqc3zm/ey9IkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJSya6boBmLzMDWAN2I2LviP2rwCqwc9R+3cpAGajMXAdW6q97dQtKgAAQES930LReWuu6AWrNHgeBsjLy8+h+vUKHXzwNRETsAjnhkN15tWUIDJRhG9trmJscj4GypGrCr1fIQBm2Se/v6oR9OsRAGajMXGHyrKaBcgzOeg1X8yWYlFylSd5X677IzNWa9GsKA2XYdo4IhB3Y73EkSZIkqRWZGa6NtMeEbgAycwO4AydnWuML2wO1p9jg0CxWnbk6C7ymPrTTQfOWgoHSAxGRmXkGWMtMKAGxSwmeZri1FxGTiiB1Ag69+uOlkZ/XgE1uXnm3N2mRgdITEXED2J5wiNXALepFoGTmej19ddn9j/EBseGsV3t6ESiUeqW1zNyYVHox9A9KzUFujNm9ApyZY3OWSl+S+SZJDWA9M5sivxjZVupx1ztp4fxM6lm3MvNaHaZphvrSoxwebqwA65RAb6phYTkS2tFA2QWuUr4cmmnj2+beoiXQix6lTo9OO2xv6Ke31jwtKD3nNnBldEp45DJFmrE+vajJ5BORlqE3WaPkKC9FxC1/75QcRifQi+S3JvDrEw7ZPeqDI81KX3KUaT3foIdc6t7CB8rIuHySXvSMx5GZm123QQcWOlCOkZwu9N9xXJl5DvhwvSyqFsCiJ/MrHFw3N4GsM2BNADUBMpgeJTMvAB9g8d+bpbLQb0YtKd+tyfxpyszW1WZ2pz6+xkACJTPfALyXgfWQQ9B5oNSTjjYo05o3RtdCaiBs1S2Ai6P/tx57PTNXMzP6VGaemfdz8+LgBreuuq/idO9C6DxQKB+Es8ApyrWmdupjQTkhqektclxpRk+vTfUM8CFKgIyzCVybT3M0SeddfO0FrnEQEOuUHuQUNw+pBlXDFRFXgF8xeaH0Hq+/tRgW5U3YZvrK+6ACBSAiLgFPMf72DHcA7xt6VXQfLESg1F5l0klJMNCxekT8B3hxwiF3Ae+eU3M0xkIESjVtLD7kNYXDveUO5dTfZrstM8/PvVXatwjJfGNa0J7OzKt9mtl6lf4J/K6nExSDtUg9yqTZHyht3ZpHQzr0d+Bpg2TxLESgZOZdwJsPPTx6q4LG1kAT2xvAsxHxxyXoMXup8w9dLdm4H7gEPEcJkCvUFfhaFLkxsl2JiGmJf69k5pqnCSy2TnOUWvz3fkqivglc5qBEBdhfTLxat95eQCIz742I3x61zyBZfJ0NvTLzLHAfpUxjlxIg29OGHn0cmmTmJ4Afd90OvXqt9yh1ZXmzbqcoCfkZ4MLI8yfTk/leysw7gceAC5n51oh4rus26fjmMfRaoawwn+GgNGWT0pOMDqO2hnZPwTpM/BblSwHgQUoepp5pfehVx98vUpL0/RttHtqattw7hNqmWs38HuCbwMdHdn2wmxbppOaWGNdy+ncC57j5mlxNG5p//w081beeJTPvBh4BHqD0HEddtfEicF9E/G2ebdPJze3bOyKuA3/moFJ4XJBeAB7o4Wmwl4B3AB9j/KVNbwd+k5kPz61VmonWAyUz78nMU7AfLM8zvSe7HXioT8OwiLgUEZ8EPkNZBxrnHPCdzPx6Zp6eT+t0Uq0OvWoy+yngckT8sD52nrLA2Ay7gjLcugi8TOlxrgPXIqKXJy1l5tuAHwBvn3DYNvCViPjyfFqlk2h71us85Vz3d2XmM3VsPlopG8BfI+IvLbdjriLi2cz8LPCTQ7u+BzwOPAn83oXG/mg7UO6sz7EOPJqZX6L0Gk1P8o+hBcmIJyjl8s1r/PmI+GqH7dEJtJ0DvI7yQVmjJLoP12/RPUo5+Z9afv7ORMRV4On664+Ar3XYHJ1Qa4FSc5EzlFykmQr+YmZ+gzJN/Hwfy1GO6UngBeDTS/C3DtrMk/mawJ+nlM3fDbwJeAvwRuD1lFX6s5Tg+QXwfeCx+g08KJn5USAi4qddt0UnM9McZeS+52cpvdUKB6vxh1fk14CPMOCSjoh4vOs2aDZmFigjlzltbhM3bmt6sV8Cn4uIP8yqDVJbZhYo9SSrXQ7OSjx8f8Xm50vAF4BvO25XX8x06FXrsy5n5jblRKvXcmsB5CMR8cQsn1dqWyuzXhGxGxEvAD8ffRj4l0GiPmp1HSUi/gv8moO8xNkf9dI8ig5/RrmIG5TyDUlHycyHMvO79Yoqko6SmZGZD3bdDkmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEm99H+gtxfU1CcREgAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "imgSeq_8", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAHpUlEQVR4nO3dy49b5RnH8d8zM3EyyZCLUpQoTVMuSsWlbURFC+KyaYToqkskJCQ2rCuBqi76H7BkCysWSNBd1UXpqlLV0EWQEBEICRRgkSKgoUDDJTOZmV8X73viE3t8PFLOxcf+fiTLsWPZj8bnOc97PZYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuRnQdAKrZDkkrkrYiYrviNYoItxnbIiFResD2QOm7sqTNiNjOybEkaTn/37VJiYSbR6L0gO0VpYSYZDsirrUVzyJa6joA7Mq0SrHVShQLjETpgSlNKtPkah6J0n8kSQtIlB6wXdU/oZ/ZAhKlH6oShe+wBfyRZ1yuJkXVsFLHfWvkNXyPDVvpOgDsyqbSEHB5QnEzJ1Fxo68CVClm5gEAAACgCbb32d7TdRwY6nzUqzT8ubUIy8TzUO6qpI3RhYy290paU/pevuggPEzQeaIozQ0sS1qyvR0Rm2MvSAdXaHyItHfyEvl9ktZsW9KG0vDvQFJRRXb8O6A7MzGsWNpvUSgm1Io9F+lBxHqbcTUlV47DFS+5GhFftxUPppuVGd3RKlFMopXjm5szbE74qv0jG23Fgt2Z1UQZ+/+ImLc9F992HQB2ry+JMm9JIlVXyP2tRYFdmZVEqYxjDquJNOy472Ql92MwIzpPlDyi1XkcHRiMPB6tqmttBYLpZmF4uGqvhaS06K/vw8I7KCrKpqRvImI9L24cFDfbe+dlpK/vOk2UkWqyonTQWOPD1kuao35Kaf/I1xFxtXg+nwzW8w0zpNN5lLxMY1mpmbEVEV/m50PDIWKJy/GgY133DZYl3ZLvrydCRDjPTG8obUiaiYlRLK7Gm165aoRu3M4qpfVOe0vPjzWtclPkWt83JhUXh5jT0buF0EZF2VZKyIFScqxJOqjxUZ+JB1GfO/K290t6VNVLVjDjGq8oEbFle0vD/kaM3Bfm7mxr+6ik+5VOCnOzBGcRtTXqtaF0sExKkknP9YLtolpsKyVESDom6W4Nq3ZvqyJaSpSIsO2rGp9EKyfHmqSv2oinAScl3T7lNVSUHmtl1CtPGBajWpMqx17bq23E04B3JV2e8pqpE6uYXY0niu2Dko7kkatpzatbplw+dCblwYY3Vb0i+CcthQPVfwmnRhMlz0AfzredPmv0qoehNCLWO7lintfkvsgJ26dbDGnh2D6Z72vv7zbdRzmg1ORY1Y1Lxy3pSnn5Rvmqh31d2xURV2x/ozSJupO7bF+JiE/bjGsR2D4h6Xbb/2lifVxjFSVXkwMaTjbemu+vSfpvOUmkNIwcERsR8X0fk6TCd5KuSPpe0lVJP8tbn1Gve5ROtEebePMmK8qqhkkSkn4g6ZPRBJlDxd90W9LbEXGpy2AWQZ6vOiXpY0mHbH9W9yqI2iuK7eV8lZFiGXmRKEuSTuXfI5xnS0qrf8+RJK15SMNrLIRSS6ZWtSZKadl8EfDoBOMJSY/YPtX39VsVvpT0j4jo65xQr9g+IOmXuvG4W637+Grj7D4a8EDSvZLusP1eRHzWQgy1sr0y6bpbEXG+7XgWle0zkp7U8CfEy7dV27X1d5scHh6dNxl9PJB0rG8/gpPPVH+x/dOuY1lEtsP2Wdt/kvSSpNMaT5Lrzf26KkutFSVfBdEV77uldKnQTyVd7umv2f5O0m8k/VnSOx3HsjDyAf+EpOeUJm//J+lz7Zwgtav9bJ5L3ejIVii13d+IiAsR8Xkfk8T2zyU9nx8+3GUsC2gg6UFJd2j3yVBb0tSWKLkkhjTccKUU6H6l2faLfb6ebp7QelVps5lEorQqItYj4lmlRPmDpA9b/fy63ij3NfYoHUiHJP1Y0hlJdyrNJ7xc12e1IY/NP6SUEA9L+pXGN5v9IiLeajs2XG+KPSjpt0rfy0VJH0m6pLRA9SulazjX0pmvs49SBLSslDBWmnT7t6RXavyctrwm6eyU1/zV9tMR8bc2AsJQToB/2X5T0u+Vjrfybb3OFR5191Fcut9WWk37ak+bXI9L+qOq95Eck/S67RfyJCtalhej/l3DBJFSksxmHzj3UQa2D9u+zfYDtk91HdfNsn2/7Q883YW8pQAts71i+ynbj9m+p4m1dHX2UUKpKbdfaVn9ICI+qOv9u2T7uFIbeHQF9DuSzkn6p9KI3kcdhAddH5G8VdLHEXGx63gq2d5j+6DtH9n+Ydfx1Mn266Xq8YXt+7qOCUP52HvU9pEm3r+JPkrRP+ndTsUpzpX+/QyjXbMl91XelzT7v1SW24prtk/YnnaxhV6x/etcTV7sOhb0XO7Qr9o+bvvOruOpk+0Dtt/Nq1WBm5OT5ZDncH+4+e131M02P4QDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABK/g9vk79KaSbX1AAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "imgSeq_9", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAHLUlEQVR4nO3dTagkVxmH8f+Z+zUxQnQUNYofRNEoBMXoKAZUMAsXulCXanDpPnHhUgR3IgiiS5cRXQhuFFzoTje6iB9xEXASFZkwJplJbu7346JO5fbtubfvHaarqqv7+UFz6eqe7rer+q1zzntO9SSSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJK0uYBO4NHQcujPrQwewojaAoyQHpRSSBChJSpJLSY5KKUdDBqiTytABrBpgPcna5Kb6tz0WlFL2+o1K57FF6R9T96dPVod9BaKLs6/cv+lEOfFYKcVEWUAmSv9mdXcPeotCd8RE6d/a+U/RojFRegSsZXaLYnFlQZkoPanl38niyVG9TfJ4LCirXv06SDNH8tqAvibQWr3ZouhsQFn12eq6DzaGjkOn6/wMNpkA07PN9bG1NF2Ow1KKVR8tpL66XiVJqYPZtttxKScT1fkDLaw+EoWcTIi2hZncxmS/XVo0nY8LLpgAS9uaAFvA1tBx6O701fUis5NytCtlgTcl2U+ym2SvlEKtZF1O8ro0+/jFAUNcKXXfX/QEfWF9Jsqy2k1yb5J7kgAc5LhAkTSf3dXAPagrs0lyBJR5JktfJdl22UaZ+tt3HF3Yzsml8hs5+Xn2HX/1o1ZNO+mddP4FrZWue8552mjXP9WS96sznrLbVyxqulztbZ6v22mi1HmSy6e8z23XZIx8wnFWotiaLIHOvpx1ULWR48tbSTOpuFev4NtLs6Sj/SKNtlXJ7Inb81pTzRGw2cXrdjmYb9culdQFgJMz87VpPExyWJNqzC3KrPLvBrDp5b3dA16fpncy93Hh3L+cdc3S5AK/ozStxpktRu1TjnkuZTJR2irX5KDy3n7DWT3AlXTYes+1RZn4JZHTbKaZb1gq9aSwniYxtpNsT/yyymaaz70FrI38ZLCQ6nfu7WmOwXbdXDLnsWGfy+w3gZRSXunxPftQktxMsjPd3E+MxV4eIrBlM/ELNu1tPcmb04yFt3Pc1Z+7vq9HuVw/7M1lmVuotXtXPXcIeGOSR9q7aca2B2lK7zs5bkk6M9cxygW//JtJrtQuyyi1yyTUj1LKC0n+nIt3p+Z+fLqoNJ33YdqzQSdlvK4B70ny0NBxrJpSyr+TPHXBp6/P+2TW1zL7V9PMoYx58WNJ8qEkDyS5NnA4K6mU8mw9Dh8876mpFwPO6727qHqd2JRmkDvaBEmSeonuR5K8rW6yejWQUsq1uorjvXUTOdmLee3+PBdGzrtFaX8oYSvN0pW1NM3gjVLKzpzfqxPAW5J8tL2bJim2Mu4J0WXzzyTvnto2nTBz1dXBb+vYa2lalFEkSZKUUq4neS5NyXEzzSTW9H4abSFiGdRWYj/HydF5BbWrRDmst1ullBsdvUeX/pbkvzMevx+43FcwOtXkOkHSlIr/V0q5VUrZLaUcLvr1KG2G75RSbnXw+p2rO/hPaSYST7OZ5OqYS9xLoB0nkmYe5XqXKx/mnShtBh+Mqbt1mrrTn5nxlPuSPOycynwATwDvv4N/0rYot5L8q+uCUZddr2Vw3oz7W5PcycHV2T6W5GngF8DV054AbACfBb6b5JNJXkryzOiqqu3K4WU5ywLvAL5Yb4/WFaqTj18a+QVnCwP4Kif9DvgC8ADwNeBJ4HngJvAs8OBo9/0SJso7a5J82sF7t4ArwCG3O6rbD4Ad4CXgh0PHe1eW7TeEa6J83EF7P4Dfz0iU/ZooLwAPDh3rXRtbotQz2eNnPLY0reMYAN86JUkmE2Ub+NnQcd61MX6pgB8B1201hle7uGd1u/aBV4BHzn+lEaC53mQUgIfqQQD43NDxrDqaEvFZibIHvMyy/NcYdZwyipYF+O3EQfnJ0PGsMmATeG5GouzSVLw+MXSsKwN4F/DjqYNyA3jD0LGtKuAb54xP2oH8t4eOdanV5Hgc+ANn+wvwmaFjXTW1F/LXGa1JO5C/Afxm6HiXGvDLGQky7ec0VzKqBzQTi63ngZ8CXwHeB3wTeJpmfHId+Adw/9AxLzXg88DfL5gsLwIfGDrmVQB8B/ge8ClOmV6gWQHxZeDXwFPAl4aIc6XQrBd6gqaKMm0X+BXwdeC+oWPV7YCrwKNDx7EygB9MJcmTOJiXTgIenkiS/9D8bq2kacC1miiPDR2LtLCA7wN/ZCQTpNIgaK5p+PDQcUiSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmr7v8z3v2HEJrFcgAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "imgSeq_10", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAHSklEQVR4nO3dy48c1RnG4ffrscdjGwxxkB2Li4BIEVKCjDFRwgoJWAASGyQW7LhJ7NiGdSQEUrIJIko24W9AUbLPKgpYKFEWgBQS7iANCJC5zMUz87I4pzLlct/G7lM13fV7pFbPTFWPv+lT37lXWwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA/Si6DgC4UrYvuo4jwrP+Nwaz/oV9Ypv3b/8IFaz4aVGugO2DSu/hVkTsdB1P31UtS4kWhUS5ArYPSFrK327nh7Rbuw0k7UTE9pCXo4BSyXJglr+sh+qFsaTdpKnbaikWqExrIrUwRrEdtoddQItgUndrq1TBoV1FEyU3gwP1s4tnulyLo1ii5CSpEmRRa9VxLSVdrgVSJFEaSbKQ8t+4qF1KNLAOcPkmTYQsdEXRJttLe1mzai5AzgKzXpchF9pAaTDv2mNJu5XPQLvTxbgyByRda3tD0rqkjeYkSZ4wGiiVQ1UuMw2gDWE7FmUGKC8ubgw5tJMLbEm0KDMTERu2dyQdkrQsybbXlcpgoPR+W7trWXO9heVAiSZxv4mI7YjY1OSpY+zNWu3rUEqaqyStqHEdL8Jer9509SKCWa/ZWpt8iqRCM6xtJ0rkbR/AnuQ1qWHd3Uo1TizSkpdMlHrgVd9xS3O8ppJnX67uOo4eW8/PzWvo/9+XGgcXq92HBLzvE8T2YaX3ZFPSZvU35AH6UUmH8zF0Y9gYtzn7VWTSaOaJUm1bsS2lP2xnjragb0o6JumIJNm+oFQQy41z0I2VKc4JzdmsVzVtNzeLmrkfXB80HtTFSSKRKJ3IrfrBKU4tMrNa6iKuxiebczj78+2YY46IC61FgroVXZoE1XWm2nORlfliiRIRc7nFfNLsSh/Wgrpi+8yYWzLq3a4Lkr6OiC8lfa00yJ/5anzdzMco85gcQ4waU4VSgU07p48p5QS5QdKy7XP1cW1eUhgotfZr9dsX8vW2lc8rVonNzfihZc1xSd1RWpUiDuXnE5LuaLzH25I+j4hvxt3jExGuHrMOjkRpqO3Vquzo4ntLlpSmiTFb9a7V9ZJ+Vn1T6uLfC1bJL1W1JttKTf16RDjXcMu1x3cdxbeomlO/NzutMfxPqbvVaaLQhWiwfVRpUNh54fSJ7VtUa0Xqh/LzhtLYcE2pkno3ItaHnF9E71sU24P6wDEixk0Po5wfTji+rLSOckTS+TaTROr5GCWPR35p+9quY+kz2z+RdGqaUyW9ExH/KRzSJXrbouQxx1mlmuzQhNNRiO2fSrp1ytPfjIj3S8YzSm8TRdIZSSfz19PsIcIM5YrqtKQbx51We/5XRHxcPLARFj5RcvfqsFKrsZKfT0q6rnYaLUqL8mcOnJX0oylf8mmXSSL1IFGUulY/1/jxGPeYtGsgaVXSee1WXiu1r5vOtxfacAufKBGxavucpLs0+nO4Ttk+FRGfthhaL9k+KenXEfHMiOOnJN2pi5cuxt3Z2IpezHpFxKqkf2j0pzeGpLO2b2ovqt56QdLjto8NO5grq3/WfmTt3tnYmV4kiiRFxBeSXht3iqTTtn/cUki9Y/sXkp5QWhN5aNR5EfGJpH/XfkSL0qacLMO2nmwqbdf+TNIx2+M2ReIy5AH8y7UfPTru/Ij4QNJb+dvOE2XhxyhDbCjf6ivpC0lvtL3K21NPKo0TKw/YPhwRI29ZiIj/2t7WPrirtFctSlYlxXlJr5MkZdke2H5A0m8bh45IenjS6yPiPfbcFWD7Ttv3jDl+u+176V6Vkz/W6T7bL9v+xKN9mMctaJvt39l+e1Qi2D6RP5YIM2b7B7b/ZPuzMcnRtGP7Fdsnuo6/V2y/nwvgua5j6Run/4bwadure0iUKlm+sv2s+STR8py6XZVvbY/bR4RCcsvyku2tPSTKju1t22/YZktRSbZ/0yiAc7bvNve4d8JpPPi3KZJk3fafbT9p+3jXcS8s2wdt/yrXSMN8ZPv3tu+3Pc2HqGFGnLpjr44ol7/afsz2NV3HufCcZrDenFBrVT60fbbrmPvGaQas6Q9dx9Ubtv84ZYJs2n7R6X54tMxpuvjzWnmsmrtK22P7uO3HnZr2tRFJ8nfbt3Uda985TRtXnuo6nt6yfcT2M7n1qGzYvm7yq1Ga7QdzmbzmPfwPvyjE9vO1RPlL1/EgsX3I9pdmJX5/yC1Ltej4dNfxYJftM13HgBrbjzhNFbMtAhjH9tBbTQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwDz5HvsRnC7yay96AAAAAElFTkSuQmCC", + "e": 1 + }, + { + "id": "imgSeq_11", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAHuklEQVR4nO3d3Ytd1RnH8d8zL8nkVayvMZJSrSGKxjfsRcGS2l5Ii9CCFCpeeNm7gu1V6XV7UcSbUvEPEBR7UxDEO2lvFSsVS2nRSkuJSaqNyWQmmcz8erHWzuwzs8+co85+O/v7gcPJ7LOGeTJ7nr3Ws9ba50gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSQ7Xnb0dbPn2vrBwOf05ykxbaShURBn4RSsjT+d0uioG9C0kLTybLQ5A8DdkmRLBuSNvIxX3sxwpXf9SWQKOizOaWk8ZZHLT8I6IOqIr6WpKhComS2o83pR4xne16jiTIuQVzHsEsiUcpC0p58UtAR+XxMUyLUliRSdXf2pRVX5joDr4PtvcU/Ja0rFYqhdEGZk6SIuNJOdMOTZ7YWq14qPVspSdbrjKXWYt72XERsTG7ZGVZKjFD17+Zqs+EM1w5JUtm8zlikGhMl9ya96lGUepBxQ6/ar1oYMa/qv59W6shaEqVvQ66SneKmN2mA7cOSLkbE2pjXi96+0YShmB81tpDv2RCyl2wvStonaWlcm4hwTqJGzweJkuUx8dirFFPHjTiYn/dNahgRV9VgspAomyYNQ0mUGtneI2lP/nLB9sSyINeMjSQLiaKRBa1iWngtP8ongd9VvQ5u+XpiryKlIXETw2L2eiUbEXG56ngekjVePA6J7f3aPhW8ZPtiVyaGOPlT6uGaUKflC9CSUs8x7oJ9RdKFXI+0avCJQgI0K+9+2Cdp76S2JatKU8atrWMNNlHyLNYhSYqIz1oOZxBywX6dvli9Z0krkpbbuLANskDNJ+wGpSsbq+0Nyfvkzkm6qM+3a6Nou1c7rLHUaaaLedsHJe1XSobiMa/Rbp9EaVAuzpdtryidm/2aPLJZU+pNLrdV3M/00CsPr27QDivukj5lR3B78tT89dp+jizpkqSVLuyxm+mhV776nJ/QjEK+RTkJliteWo6IVgv4splOFEnK+4Iu7dCklTHvkNlesH1H6dCqRmuWde18zho384mSVV2xCgfyZjw0wPYhSd+SdLQ4lnv+8oLvclcWGgtDSZRJtdhhNj3Wz/ZRSY9KOqBUoJet5Of1iFhRx8z0rFfJ1kJxXen+kvn8WFDaa3Sh4bhmSt6Ksrb1XpK8Cn+PpK+VDo+stkfEFdvrSlPHnTO0RLFStz4yFJu0xR6T5R75EaXeWUqJUGwuXdLmzuBC1Y1Z58fdsNW2mRt62b69Yhg1r3TiPtmaJNK1HaidmF3pq1xTvKXNBFhQWtA9rO1JIlUkSleTRJqxRMld//1KaydlqxHx3y5srptl+SL0Tttx1GGmEkXS3Ur/p6PlgyRIcyLiY0l/n6Lp0byVqBdmJlFsXy/ptvzlkTY+GgDX/E1pT9dOliQ91JfZxpn4Y7K9T9LJ0qFFSbe2FM7g5Xplml7lJknHaw5nV/R21ivfU31EaZh1o7bPWp3Mbf7VtcWrgZh2a9Bx2//LQ7bO6kW3t5XtWyU9rOl6xM8kvR8RZ+uNCmW2b5H0jYqX1pRmIYtzZ6UZyT9GRKe2rZT1MlEkyfbNSotYh6b8lg8j4r0aQ0KJ7dslPVg6tCzpreImudJbphaP5S7v4u7t0Csiztg+K+mYpBOqnqu/Kum0pH9rcnGJCWyfknSHpJfGvBlHWXn/3GlJ75RnH/Ndipc1users3rbo5TljXanyockvadUn7CQuEtsn5T0rqQzkn4r6YWIOLelzV5Jj0l6RqlH+V5E/KPhUDGO7W/afiI/7m07nlll+wNvWrH9ou1Ttp+y/bLt86XXf9V2vINh+yu2fzJpvt32sZwkj/dpIatvbD/n6azYvrHteAfD9nW2P7H9h1zAj2u3aPv7tr/eZHxDY/vRKRPlxbZjHRzbH+Uu/UPb3y0dX7B9m+0Hc6IcNyvytbI9Z/vMFIlyou1YB8f2n2yftX3B9qrtf9o+bXsjP/5qm1t6G2L7tQlJ8kbbMe62vkwPf6Q0DVzcN3JEm5/IdEXSjyNitb3whsOp/ntoQrMPmoilSZ1PFKe3szmotGC1oM0PHi0+hPTnEfHn9iIcnB8pXah28p0mAmlSH8bzT+Tn80rJsqq0DWJd0uuSftdSXEP1syna3GX7ntojaVCnexSnNyO4X2lVfVHbe5RX2fDYHNuPSXpgmqaSfijp/Xojak5nexSntxC6T9JZpZXgc5I+VdrkeEmpZ5nqw2awa57NzxuS3pT0U0l3SrpF0i8k/Ueb78/1g6aDGyTbh2zfaftu2/faPmH727Zfsf1unvn6ZdtxDoXtA7Z/b/sZ21tvtS7a7LH9tO23ba/bPtZ0nMhyAv3a9l9s/6bteFAtX9S+2nYcg2Y7bD9p+/m2YwE6L08dAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF/Q/wHnvoriekCjMAAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "imgSeq_12", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAG6ElEQVR4nO3cy4tk5R3G8edXfRnHHjvOeEOFhIQsApIwgoGg+yxEEEQQXCQu/Cck/gfZZpFNsnaVBAQh/4BustCQjZrgdSBuxrn1TF+q6nHxvpU6c7q667SpOuc9p78fKGqq5jT8uk89572ekgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApbC9YTu6rqNq1HUBQJXtTUmbkooKymbXBQAztrc0v3i7y1rqCAo6l7tZWyqsFakiKGiF7ZGkjfrbSuEofghAUNCKiJja3lAPQrFIL4tGb41V2NijKYKC1kSEJR01PLyo3k6xg6f/V27mQ9I0Iqa1/wul/vIoIg67qO88y+OVrQaHTiJivO56mhhyUELS9uylpGl+HmnekhZzIs6bvF5SH9wvMo6IybrrWWawXa/czM/6w7MWZFP3/87T+s+hNU3HKpu5BepU5wWs2WlXIte7ZCjWZtdbWooaMK1aRExyE78IISmLJR3lnkBxBt2iLLkKDXZ81pVTLkqLVP/+04g4LDUk0sBbFJ1+IRjZjpJPTg/t5ovTXkTsLzl2tq/roA8TKoO+qtY22S1SxIzKUNjekXQpv5xI2pO0HxGuzEJeyI9tSdcj4l4nxZ7RYINSmx6eKp246vTwSGlAzzrKiuSu1yO1t2d/+/q6yVFEXG+lsBUYXNfL9kZuJULpBE1q3auJpEkO0qDHaG2LiLHtie5fH6muW1XttVPVagzqg2L7kqSHpLQJLyLGJ41BIsJ0u9bioMEx44hoclwxBhMU2w9I2lGz1V6sT5Ou7N21V7FigwhKHrTv5pcEpVtNxr3LZsSK08sxSuUmoA2lQeJFzU9Q2B6x6t6ZBxscE+rZdvveBcX2w0rTi6e5IKkX045DYntbzXYF9+789LHrdVPLB4wP5TEL2rXT8LhlF7ri9C4oebbqhk6fXgxJP8gLYFgh2z+3/fSC97c0X7eS0vrJvqQ7On6z1nbXmxzPqnddr5mIuGPbmq8EL3LJ9mZE3GyrrnNgW9KzthUR1yrvP6h0q++BpMPaQu5eDtKOUmsy+9aV3iz29jYo2V0dD8o4PyaVZ6zO7Mvp6mG5ddq+uYg4knQjr97vKAWOoKxK7j7dWzSLlfcQTTXvQu5FxJ1WCzx/Zp+ZWVhGEfFV082leQNk71r44oMi6UmlwflHJ0z5jpWuTvuEpBXVz0xIumr7cUm3NG/Nj5Ra8oOIuNV+iavXh6BsSLqidEI+XBCWidKJGcQJ6YFF079P5UfdJxrIeenDrFcoXaWuSPpF/naVqn1JN7ivZP1sX5TUdNr93xHx8TrraVPxU3S2f6a0dXtbqQW00mLVrIk/VDopvdsW0Sd5MfF55U2nS3wWEf9ac0mtKrrrVdmqcqgU6lCqeVfz1vBLQrJeZwzJF0MLiVRwUPKC1GNKLcehUjDqLeBXQzwpJTljSP4bEf9cc0mdKDYoSnPtobSANbvJKiqPzyPik+7KGy7bT+R/Xpf0KzULiSRdW35IPxUZlHwVG0m6rDTnPrtLbhaSfUmfdlbg8L0p6VlJv1X68H+j9FnZqjw/ouMtfNPvFe6dIoOiNOW7qzRwv51fV1uTPWa51uplSb+U9OeIeG/RAbYvK7U21c/QYHdBlDo9vKm0PeVmRNyOiG8kfavUDTtQD2/86QvbT0p6Lr/8Q54SPiYivpX0vu7fhlL81w59X8UFJc90TZUC8b97FvI3dszCQlDW5yXNu1Q/lvT2SQfmzaYfaB6WwQalOLbD9sj29qJt8rYftX2li9rOA9vv+n4Htq8u+Zld27/OO4TRlhyWjRyWY63egtV5rIDtH9ne93F3bP/R9osn3RDHjXIdWRYWrJbtV21/vSAkdbdt/8X2G7Yf7bpuiLC0wfZPbL/XICDT2uO27d90XT+ySlguuGe3j5YsX3x+Z/ve9wjJX23/sOvfAQsQktWy/Yrt/5wxJJ/Zfqnr2oHW2X7G9lu2389hOKkV+ZPtJt/ZBQyb7Sds/74WkIntmz5h4RE4t2z/vRKSse13uq4JKI7tn9res33ktK7yetc1AUWy/bbtu7ZvmJ0QwGJ5Ov4ftv/WdS1A0Wy/YPu1rusAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACF+g7VK6bkR7K7BgAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "imgSeq_13", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGdElEQVR4nO3cS28kVxkG4PeMPSQzuQyMAAlQSEhEWCBAisRlxZ9gy4ofwJ4tC34GW5BAYpUNGxaRsiAoi0QIgQSCgCJI0JjM2OOMbx+Lqo7LnfaMJ3K7q7qfRypVuy/ScZffOud8p1wJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXV1Vbq27DMlxbdQNYO9vrGBZB4dJUVesfrl1YBIXL1AaPt6tqbf6+1uYXYZSur0vP0h79FriYPhTbi15asK8kJ621WvD+0Vn0S01WVW0nOZ7Kl7+GzjvxtgWvn7TWjpfcnkuzFkHpJ5Hb6YaSk/ny10k/H7noMOuktXa4zPZctskHpT9A2zGMXJn+GFy/4NuPW2tHy2zPMkwqKFX1qZwGYja8OhMQw66rtQkhSaZX9TrM2YDoRVboMUNSUw1JMrGg9L3FQ7/sdardj1VVbfXzwq2cVrAe5WS5rVquSQ29kqS1dlJVRzm/7dtVdWgItlTPJDlqre0OnxyszG/l4hP7SZjk2fcRZcWWiw8HeEz9WskTSW4MgpGk6/H77Sgf7/knfeKaZFAuoPVrKly+G/3+2uDxx/Qns2FYBGWZqurZ+TPX/M/p1k4O+u2w3yY9Jh6j/nsfhuPmgmPxkT4sa7GuNeqz7mAR6+kk985522FrbRiKSZ+5Ru7JnD25bvXP7Z/3gdbaUVUlEz8uY+9RrqXrGbar6om51yrJwVxIWJKqup7uhDXv6QXH5ozW2tHUiyujXofoFxhnZ7GW5N6Ua/FT1B+Dm+km8A9znOR+kv2ph2KRsQflyZxewzXbZpPEw3TDrrU7KGPQ9xJP5fEriJVuKHZ/Shc9Pspog9JXrWb1+GuD/ax3aekOys46HZAxqKqb6dZKPqnjJLuttQ8vqUkrN8qg9JP4+W1r7uejdEMxc5Ql6NdLbvTbReeyR+l6knMn91M1uqpXX26swbYoCPvrdLYaqZN05fa9dPPEmzn/7+UwyV5r7cEVte3KjbJHST6qsszmJMNe5WBq/8swRVX1cpLrrbU/Dp67lS40QwettZ0rbdwKjLI83A+9TnK6cDjrWY6FZPmq6naSl5N8Zu6l3QVv31t+i1ZvlEHJYOjVz0FmYTFpX7K+J38l3Wjj1vBq7L5oMhzyHrXWDq64iSsxyqD0Jd8alH5PBhvL9c2cvZ7r1tzrwx5k7Sbt5xllUObNghNBWaqqejHJF+eePjP86hd8H+R0vWQjjK7qNTO/kKgMfLn66uIzSW6nC8PtdJWteZ9N8re55/bSDbs2ZrF3tFUvlqMPyLfTBeAi/1xVSd5urf1jqQ0bOUHZQFX1bLoJ++Osvr+b5K1NrToKyobqV96/nuT5i34k3ZzkzU1YN5knKBuuqr6Q5Fs5/+LHmnt8kuQvrbW/LrttYzKJqhfLUVU/SfJcktey+O42w3sFHyfZSfL3LF54XGujrXqxXFX1wyQ/S/Kj1trvq+o/Sb40e7nf76cLxp0kH2xy5VFQNlBVfT/Jz9MF4iv90zs5u4ZykOT1dbwS+JMQlA1TVV9L8pucHvuX+v2d2Vv6/VtCckpQNkhVfTXJqzldba8kL/aP76abp7Qk77TW/n31LRwvQVlDfa/xjXQheGmwn5WCh5cEPZ90V0JU1U66v4k/XXWb4cpV1Y+r6mSwHffbUVUdVtWDqtqvqr2qultV3+k/91xVPbXq9sOVqaofVNXuXDg+7MNxr6p2qur9qnq3qt6sqldW3eYxs+C4xqrqe0l+ne6Cx9ldG2f3BT5IdxXwg3Rl4P8l+Wlr7bXVtHbcBGXNVdULSX6R5IWc3m72Qbp/wNrvt91+u5vkV621362irWMmKBugqj6f5LfpJvCzgNxPd7n8Xrrb1d5LF5R7Sf7QWntjNa0dJ1WvDdBae6+qXk/y5ZyGZDddKP6Z5F9J3k/y3yQfpAsMA4KyOd5O16PMepL3kvyytXbnoZ8iiaBskj+nu0XqbKj16iZeLv9JCcrmeCfdivz9JG8ICSxQVZ+uqu9W1edW3RYYrararqr5G9oBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAeP0fvMdPcZ/TtjgAAAAASUVORK5CYII=", + "e": 1 + }, + { + "id": "imgSeq_14", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAErUlEQVR4nO3c22okRRgH8H+NG1fRVcEDKIKgFyJeCooP4Gv4Cr6AD+mF4LUHvFBEdLNmd5PM50X1ZHqzm2Q8ZA7dvx80c8gQag7//qq6qjsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmK+qWlTVYtft2JbZvFH+P0NAjpK0XbdlW/Y+KFU1my/jEIxCkgjKfhi+lOd23Q66Yad1NHpKUPZESy4Cww5dqiSzc2fXDdjQIsly142Yg6p6LusdaMv1VUNF2bWhzNewqSrbU+kBWOTmILS5jCEP4ce3Csuiqu4IzO1qrS2TnGbYQW3gUHol/8ne7g1Ge6rx7bgrsGytnW+9YTMxGrhv8hupJKettU3DdXD2du88+tDHH35d2rglw+e/aWVpSY6m3A3b2zf2jA999bimvOfaN//waNdkK8te9y9bazUKjIDsxnU703HVX91vmWC139uKMlZVTUi2azhM/GqSkzx9aH7ZWjvdfqt2Z2/HKOOul5BsV1W9mOT19C7X7EOS7HHXSzhux1Apkv6Dr0t/WyR5Jcnd0dPnWc+pzDIkyR4HhVtzlN6lSlUt04OwTB9XPJ+nexnLDOOOuYYkEZTZaa09rKoX0qvGItd3v6u1thzGiLOes9rbMQq36s9stnZumSRzD0kiKLM0LFP5Y4OXLqY8ifhPCMpMtdYeJ/nrppclubeF5uw9QZm3Bxu85oWqunvzy6ZNULjKeLb93txXbc/6zZM3k3yeJ38Hlxecru6/vK1G7SOHh2eoqo6SfJTkg6zPHl0F4kH6quHVyVurrVXVndba2fZbvHuCMjFVdSfJh0nuJzlOcn88UVhV7yT5OOvZ9/vpITlP8sdcg3ATQZmY1trZsFbr/dVzVfUwPTRH6UtULs4aTa8gJ0mOLRu6mqBM07dJ3sj6+72bvjwlWXezVidm/dRau7/1Fh4Yg/kJaq09TPJd1oFYDtv5aDtLrzK/76iZB0VQpuuHJL/l6XCcpVeSx0kexWWgNiIoEzWMN77Nk8E4TQ/Hw9H25q7aeEgEZdoeJPkifRnKo/RB+yogJ+lLWI6q6qWdtfBACMpEDctOvk7yWXr36iTrcKy21eOXLH68nqNeE1RVryX5Ksm7SX5M8kt6IC6PV8aP76ZXGp5BUCamqt5O8uXw8Pv0uZM/04OyOtL1OOvTey+umuIiHlcTlANUVZ8k+TTranCcHoJK8lb60a5HWQfhOD0sx8O5KM/6n0JyDUE5TN8keS99UnGZXjVWE4g/pleMVdU4S/LrMLdyJSG5ngHcgaqq59MH6kfpATm7dHuaHqLHSX62huu/EZQDNhzZei+9mlwenI8H7aettZNdtXMKBOXADZXlXtbLVMZbjW7PrxqfcDNBmYDh/JJFnn21/4v7xiH/nqBMwDBZeHEx89XzggEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE/6G6t6hzgTaFVIAAAAAElFTkSuQmCC", + "e": 1 + }, + { + "id": "imgSeq_15", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAADDklEQVR4nO3cXW8aRxQG4Hf8mTZRe5P2qv///7Vq0tgGTi9mgA0BG0uRMcvzSCtYDNbI7LtnPnadAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8oKraqdsAXKiqak5Cr3d16gbw5lqSu6q6eSkwI1TXb9Sud82Z5QJV1f1kd5Vk0Vqr8bOr9BPoVfrxsWqtPb19K9+Xm1M3gJNYZdubuEqvMJX9J87lm7XqHdP1ukyrPa/tC8mqtbbvvRdHUC7TsQe/ajIIygUa45F64W2lmmwJCocIyYSgXKAxs2XG8xUE5TIdszbi2Jjwx5ihqvp4aKFwsk5y8ONjcxnRhKDM022Sz1X1e1XtrpVd7zy/T++GLfL9AL/i+Niw4DhPD+kB+JDkQ1U9JPmSPt17n/6936QHpJJ8aa0tkywnFafFOGZDUObpcTyuK8Td2KavrbtYDyMkSZIxJbwa3S4VZRCUGWqtLatqkW03q555/Hrgd1QsOG4Iynw9JPkl+8Ox3h6n1YTDBGW+ntLHI/sCkvQFxW8naNdZEpT5uk4PQ+XHkFSSpUtUjicoMzRmrm7SxxiVHpr19O+0onAksxrzdJsekrskfyT5NPaX6QFZZjuzxRFUlDNUVX+mH/z/ju2/yR2KLcmvST6mB2aR5J983w3LeGyTfZ7hjHKGxuUpf43dVbYD88f0Rca78doivXr8PfZ3v+9aB4znCcqZqqpP2U7/TqtFy6R7lX6X4redz26+d0E5jq7X+fqaHorb9DWT3dmt9fbDOolwvJ6gnKnW2qqqnpL8ln4d13oWa3ccIhQ/gaCct5btQH1aOTbhUD1+DmOUM7VzX8l6jCIYMOVfowIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO/4HVObuJ+2YzhoAAAAASUVORK5CYII=", + "e": 1 + }, + { + "id": "imgSeq_16", + "w": 202, + "h": 244, + "t": "seq", + "u": "", + "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMoAAAD0CAYAAADaFbl1AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAABvUlEQVR4nO3a0WqDQBAF0FmT2v//3ELq9KEuiDWNIVpZew4EM9GHhXCzM0siAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeyMxy9BoAAAAAAAAAAABgL5nZZWbv/3Lb6Y5eALspEfEmLNsQlHMTlo0IyvnVsPiuX3A9egHsJmf1NTPzzv3PUsr8eSYE5X+Yh2BaD0LymKCcU4nfw1HrLKUMf7OktgnKyYyzSBcrgiIk6zkNOZHxdOtSy6VH6lW79RxBaVBmXiKij4iPuiuMIZmfbC2GRUiep/Vq0xDfP3LvmXmLiFsszyUxfnbvHivZURqVmf20HF915iiza4bTrZcISqPG9msahFh4H6HV2oTWq121/Zr6EQgh2YYdpWGTAb62XoKxEztK+8weAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACw0hcO3WMluFqQfAAAAABJRU5ErkJggg==", + "e": 1 + }, + { + "id": "sequence_0", + "layers": [ + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_0", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 0, + "st": 0, + "op": 1, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_1", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 1, + "st": 1, + "op": 2, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_2", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 2, + "st": 2, + "op": 3, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_3", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 3, + "st": 3, + "op": 4, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_4", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 4, + "st": 4, + "op": 5, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_5", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 5, + "st": 5, + "op": 6, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_6", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 6, + "st": 6, + "op": 7, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_7", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 7, + "st": 7, + "op": 8, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_8", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 8, + "st": 8, + "op": 9, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_9", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 9, + "st": 9, + "op": 10, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_10", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 10, + "st": 10, + "op": 11, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_11", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 11, + "st": 11, + "op": 12, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_12", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 12, + "st": 12, + "op": 13, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_13", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 13, + "st": 13, + "op": 14, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_14", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 14, + "st": 14, + "op": 15, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_15", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 15, + "st": 15, + "op": 16, + "sr": 1, + "bm": 0 + }, + { + "ty": 2, + "sc": "#00ffff", + "refId": "imgSeq_16", + "ks": { + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "r": { + "a": 0, + "k": [ + 0 + ] + }, + "o": { + "a": 0, + "k": [ + 100 + ] + } + }, + "ip": 16, + "st": 16, + "op": 18, + "sr": 1, + "bm": 0 + } + ] + }, + { + "id": "comp_0", + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "✨流星", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 47.228, + 61.728, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "hasMask": true, + "masksProperties": [ + { + "inv": false, + "mode": "a", + "pt": { + "a": 0, + "k": { + "i": [ + [ + 42.388, + 0 + ], + [ + 0, + -42.388 + ], + [ + -42.388, + 0 + ], + [ + 0, + 42.388 + ] + ], + "o": [ + [ + -42.388, + 0 + ], + [ + 0, + 42.388 + ], + [ + 42.388, + 0 + ], + [ + 0, + -42.388 + ] + ], + "v": [ + [ + 54.022, + -48.728 + ], + [ + -22.728, + 28.022 + ], + [ + 54.022, + 104.772 + ], + [ + 130.772, + 28.022 + ] + ], + "c": true + }, + "ix": 1 + }, + "o": { + "a": 0, + "k": 100, + "ix": 3 + }, + "x": { + "a": 0, + "k": 0, + "ix": 4 + }, + "nm": "蒙版 1" + } + ], + "ef": [ + { + "ty": 5, + "nm": "残影", + "np": 7, + "mn": "ADBE Echo", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "nm": "残影时间(秒)", + "mn": "ADBE Echo-0001", + "ix": 1, + "v": { + "a": 0, + "k": -0.028, + "ix": 1 + } + }, + { + "ty": 0, + "nm": "残影数量", + "mn": "ADBE Echo-0002", + "ix": 2, + "v": { + "a": 0, + "k": 3, + "ix": 2 + } + }, + { + "ty": 0, + "nm": "起始强度", + "mn": "ADBE Echo-0003", + "ix": 3, + "v": { + "a": 0, + "k": 1, + "ix": 3 + } + }, + { + "ty": 0, + "nm": "衰减", + "mn": "ADBE Echo-0004", + "ix": 4, + "v": { + "a": 0, + "k": 0.3, + "ix": 4 + } + }, + { + "ty": 7, + "nm": "残影运算符", + "mn": "ADBE Echo-0005", + "ix": 5, + "v": { + "a": 0, + "k": 1, + "ix": 5 + } + } + ] + } + ], + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 3.51 + ], + [ + -5.66, + 5.66 + ], + [ + -3.51, + 0 + ], + [ + -5.66, + -5.66 + ], + [ + 0, + -3.51 + ], + [ + 5.66, + -5.66 + ], + [ + 3.51, + 0 + ], + [ + 5.66, + 5.66 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "rd", + "nm": "圆角 1", + "r": { + "a": 0, + "k": 0.6, + "ix": 1 + }, + "ix": 2, + "mn": "ADBE Vector Filter - RC", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.74, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.159 + }, + "t": 36, + "s": [ + 38.732, + -68.361 + ], + "to": [ + -12.362, + 18.721 + ], + "ti": [ + 12.362, + -18.721 + ] + }, + { + "t": 46, + "s": [ + -35.439, + 43.968 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.74 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0.167 + ] + }, + "t": 36, + "s": [ + -45 + ] + }, + { + "t": 46, + "s": [ + 720 + ] + } + ], + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "星形", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 3.07 + ], + [ + -4.95, + 4.95 + ], + [ + -3.07, + 0 + ], + [ + -4.95, + -4.95 + ], + [ + 0, + -3.07 + ], + [ + 4.95, + -4.95 + ], + [ + 3.07, + 0 + ], + [ + 4.95, + 4.95 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "rd", + "nm": "圆角 1", + "r": { + "a": 0, + "k": 0.6, + "ix": 1 + }, + "ix": 2, + "mn": "ADBE Vector Filter - RC", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.74, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.157 + }, + "t": 39, + "s": [ + 94.317, + -52.128 + ], + "to": [ + -17.959, + 23.196 + ], + "ti": [ + 17.959, + -23.196 + ] + }, + { + "t": 49, + "s": [ + -13.44, + 87.049 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.74 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0.167 + ] + }, + "t": 39, + "s": [ + -45 + ] + }, + { + "t": 49, + "s": [ + 720 + ] + } + ], + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "星形 2", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 2, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 0, + 3.95 + ], + [ + -6.36, + 6.36 + ], + [ + -3.95, + 0 + ], + [ + -6.36, + -6.36 + ], + [ + 0, + -3.95 + ], + [ + 6.36, + -6.36 + ], + [ + 3.95, + 0 + ], + [ + 6.36, + 6.36 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "rd", + "nm": "圆角 1", + "r": { + "a": 0, + "k": 0.6, + "ix": 1 + }, + "ix": 2, + "mn": "ADBE Vector Filter - RC", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.74, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.156 + }, + "t": 42, + "s": [ + 154.797, + -1.631 + ], + "to": [ + -15.644, + 20.128 + ], + "ti": [ + 15.644, + -20.128 + ] + }, + { + "t": 52, + "s": [ + 60.936, + 119.135 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.74 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0.167 + ] + }, + "t": 42, + "s": [ + -45 + ] + }, + { + "t": 52, + "s": [ + 1080 + ] + } + ], + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "星形 3", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 3, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + } + ] + } + ], + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "▨ 墨镜 右 2", + "td": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.52, + "y": 0 + }, + "t": 56, + "s": [ + 106.898, + 80.715, + 0 + ], + "to": [ + 0, + 0.958, + 0 + ], + "ti": [ + 0, + -0.958, + 0 + ] + }, + { + "t": 62, + "s": [ + 106.898, + 86.465, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 12.899, + -0.035, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + -7.57, + 0 + ], + [ + 0, + -0.82 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 6.57, + 0 + ], + [ + 0.87, + 7.18 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0.74, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.12, + 8.14 + ], + [ + -6.04, + 0 + ], + [ + -0.34, + -2.81 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 23.66, + -9 + ], + [ + 25, + -7.51 + ], + [ + 25, + -6.01 + ], + [ + 25, + -5.75 + ], + [ + 12.97, + 8.93 + ], + [ + 1.42, + -2.962 + ], + [ + 1.42, + -9.012 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "墨镜", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 2, + "ty": 4, + "nm": "高光4", + "parent": 1, + "tt": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.48, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "t": 31, + "s": [ + -3.75, + -3.25, + 0 + ], + "to": [ + 2.292, + 0, + 0 + ], + "ti": [ + -2.292, + 0, + 0 + ] + }, + { + "i": { + "x": 0.48, + "y": 0.48 + }, + "o": { + "x": 0.26, + "y": 0.26 + }, + "t": 41, + "s": [ + 10, + -3.25, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.26, + "y": 0 + }, + "t": 56, + "s": [ + 10, + -3.25, + 0 + ], + "to": [ + 3.375, + 0, + 0 + ], + "ti": [ + -3.375, + 0, + 0 + ] + }, + { + "t": 62, + "s": [ + 30.25, + -3.25, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "a": 0, + "k": [ + 6, + 36 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 4 + }, + "nm": "矩形路径 1", + "mn": "ADBE Vector Shape - Rect", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.105882354081, + 0.098039217293, + 0.211764708161, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": -330, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "高光1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 31, + "op": 331, + "st": 31, + "bm": 0 + }, + { + "ddd": 0, + "ind": 3, + "ty": 4, + "nm": "▨ 墨镜 左 2", + "td": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.52, + "y": 0 + }, + "t": 56, + "s": [ + 94.123, + 80.75, + 0 + ], + "to": [ + 0, + 0.958, + 0 + ], + "ti": [ + 0, + -0.958, + 0 + ] + }, + { + "t": 62, + "s": [ + 94.123, + 86.5, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.157, + -1.294 + ], + [ + 6.04, + 0 + ], + [ + 0.12, + 8.14 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.74, + 0 + ], + [ + 0, + 0 + ], + [ + 0.054, + -1.31 + ] + ], + "o": [ + [ + -0.87, + 7.18 + ], + [ + -6.57, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -0.82 + ], + [ + 3.877, + 0 + ], + [ + 0, + 0 + ], + [ + -0.046, + 1.118 + ] + ], + "v": [ + [ + -3.34, + -2.95 + ], + [ + -14.24, + 9 + ], + [ + -25, + -5.75 + ], + [ + -25, + -6.01 + ], + [ + -25, + -7.51 + ], + [ + -23.66, + -9 + ], + [ + -2.998, + -9 + ], + [ + -3.053, + -6.747 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "墨镜", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + } + ], + "ip": -58, + "op": 242, + "st": -58, + "bm": 0 + }, + { + "ddd": 0, + "ind": 4, + "ty": 4, + "nm": "高光3", + "parent": 3, + "tt": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.48, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "t": 31, + "s": [ + -33.125, + -2.25, + 0 + ], + "to": [ + 2.625, + 0, + 0 + ], + "ti": [ + -2.625, + 0, + 0 + ] + }, + { + "i": { + "x": 0.48, + "y": 0.48 + }, + "o": { + "x": 0.26, + "y": 0.26 + }, + "t": 41, + "s": [ + -17.375, + -2.25, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.26, + "y": 0 + }, + "t": 56, + "s": [ + -17.375, + -2.25, + 0 + ], + "to": [ + 3.375, + 0, + 0 + ], + "ti": [ + -3.375, + 0, + 0 + ] + }, + { + "t": 62, + "s": [ + 2.875, + -2.25, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "a": 0, + "k": [ + 6, + 36 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 4 + }, + "nm": "矩形路径 1", + "mn": "ADBE Vector Shape - Rect", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.105882354081, + 0.098039217293, + 0.211764708161, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": -330, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "高光1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 31, + "op": 331, + "st": 31, + "bm": 0 + }, + { + "ddd": 0, + "ind": 5, + "ty": 4, + "nm": "▨ 墨镜 右", + "td": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 106.898, + 80.715, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 12.899, + -0.035, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + -7.57, + 0 + ], + [ + 0, + -0.82 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 6.57, + 0 + ], + [ + 0.87, + 7.18 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0.74, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.12, + 8.14 + ], + [ + -6.04, + 0 + ], + [ + -0.34, + -2.81 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 23.66, + -9 + ], + [ + 25, + -7.51 + ], + [ + 25, + -6.01 + ], + [ + 25, + -5.75 + ], + [ + 12.97, + 8.93 + ], + [ + 1.42, + -2.962 + ], + [ + 1.42, + -9.012 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "墨镜", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 6, + "ty": 4, + "nm": "高光2", + "parent": 5, + "tt": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.48, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "t": 16, + "s": [ + -3.75, + -3.25, + 0 + ], + "to": [ + 5.917, + 0, + 0 + ], + "ti": [ + -5.917, + 0, + 0 + ] + }, + { + "t": 26, + "s": [ + 31.75, + -3.25, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "a": 0, + "k": [ + 6, + 36 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 4 + }, + "nm": "矩形路径 1", + "mn": "ADBE Vector Shape - Rect", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.105882354081, + 0.098039217293, + 0.211764708161, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": -330, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "高光1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 16, + "op": 316, + "st": 16, + "bm": 0 + }, + { + "ddd": 0, + "ind": 7, + "ty": 4, + "nm": "▨ 墨镜 左", + "td": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 80.124, + 80.75, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + -13.999, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.157, + -1.294 + ], + [ + 6.04, + 0 + ], + [ + 0.12, + 8.14 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.74, + 0 + ], + [ + 0, + 0 + ], + [ + 0.054, + -1.31 + ] + ], + "o": [ + [ + -0.87, + 7.18 + ], + [ + -6.57, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -0.82 + ], + [ + 3.877, + 0 + ], + [ + 0, + 0 + ], + [ + -0.046, + 1.118 + ] + ], + "v": [ + [ + -3.34, + -2.95 + ], + [ + -14.24, + 9 + ], + [ + -25, + -5.75 + ], + [ + -25, + -6.01 + ], + [ + -25, + -7.51 + ], + [ + -23.66, + -9 + ], + [ + -2.998, + -9 + ], + [ + -3.053, + -6.747 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "墨镜", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + } + ], + "ip": -58, + "op": 242, + "st": -58, + "bm": 0 + }, + { + "ddd": 0, + "ind": 8, + "ty": 4, + "nm": "高光1", + "parent": 7, + "tt": 1, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.48, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "t": 16, + "s": [ + -33.125, + -2.25, + 0 + ], + "to": [ + 6.042, + 0, + 0 + ], + "ti": [ + -6.042, + 0, + 0 + ] + }, + { + "t": 26, + "s": [ + 3.125, + -2.25, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "a": 0, + "k": [ + 6, + 36 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 4 + }, + "nm": "矩形路径 1", + "mn": "ADBE Vector Shape - Rect", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.105882354081, + 0.098039217293, + 0.211764708161, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": -330, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "高光1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 16, + "op": 316, + "st": 16, + "bm": 0 + }, + { + "ddd": 0, + "ind": 9, + "ty": 4, + "nm": "墨镜", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.48, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "t": 5, + "s": [ + 93.748, + 86, + 0 + ], + "to": [ + 0.042, + -0.875, + 0 + ], + "ti": [ + -0.042, + 0.875, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "t": 11, + "s": [ + 93.998, + 80.75, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.52, + "y": 0 + }, + "t": 56, + "s": [ + 93.998, + 80.75, + 0 + ], + "to": [ + -0.042, + 0.875, + 0 + ], + "ti": [ + 0.042, + -0.875, + 0 + ] + }, + { + "t": 62, + "s": [ + 93.748, + 86, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + -7.57, + 0 + ], + [ + 0, + -0.82 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 6.57, + 0 + ], + [ + 0.87, + 7.18 + ], + [ + 0.34, + -2.81 + ], + [ + 6.04, + 0 + ], + [ + 0.12, + 8.14 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.74, + 0 + ], + [ + -8.2, + 0 + ] + ], + "o": [ + [ + 0.74, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.12, + 8.14 + ], + [ + -6.04, + 0 + ], + [ + -0.34, + -2.81 + ], + [ + -0.87, + 7.18 + ], + [ + -6.57, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -0.82 + ], + [ + 8.2, + 0 + ], + [ + 7.57, + 0 + ] + ], + "v": [ + [ + 23.66, + -9 + ], + [ + 25, + -7.51 + ], + [ + 25, + -6.01 + ], + [ + 25, + -5.75 + ], + [ + 12.97, + 8.93 + ], + [ + 0.95, + -2.95 + ], + [ + -3.34, + -2.95 + ], + [ + -14.24, + 9 + ], + [ + -25, + -5.75 + ], + [ + -25, + -6.01 + ], + [ + -25, + -7.51 + ], + [ + -23.66, + -9 + ], + [ + 0.95, + -9 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "墨镜", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 10, + "ty": 4, + "nm": "左腮红", + "sr": 1, + "ks": { + "o": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.48 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0.167 + ] + }, + "t": 5, + "s": [ + 0 + ] + }, + { + "i": { + "x": [ + 0.48 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0 + ] + }, + "t": 10, + "s": [ + 100 + ] + }, + { + "i": { + "x": [ + 0.833 + ], + "y": [ + 0.833 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0 + ] + }, + "t": 57, + "s": [ + 100 + ] + }, + { + "t": 62, + "s": [ + 0 + ] + } + ], + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 115.824, + 94.051, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 0, + "k": [ + 13, + 8 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "nm": "椭圆路径 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 0.250980407 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 25, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": -5, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "左腮红", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 289, + "st": -11, + "bm": 0 + }, + { + "ddd": 0, + "ind": 11, + "ty": 4, + "nm": "左腮红", + "sr": 1, + "ks": { + "o": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.48 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0.167 + ] + }, + "t": 5, + "s": [ + 0 + ] + }, + { + "i": { + "x": [ + 0.48 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0 + ] + }, + "t": 10, + "s": [ + 100 + ] + }, + { + "i": { + "x": [ + 0.833 + ], + "y": [ + 0.833 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0 + ] + }, + "t": 57, + "s": [ + 100 + ] + }, + { + "t": 62, + "s": [ + 0 + ] + } + ], + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 70.824, + 94.051, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 0, + "k": [ + 13, + 8 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "nm": "椭圆路径 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 0.250980407 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 25, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 5, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "左腮红", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 289, + "st": -11, + "bm": 0 + }, + { + "ddd": 0, + "ind": 12, + "ty": 4, + "nm": "嘴巴 2", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.833, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "t": 57, + "s": [ + 94.195, + 99.5, + 0 + ], + "to": [ + 0, + 0.169, + 0 + ], + "ti": [ + 0, + -0.169, + 0 + ] + }, + { + "t": 62, + "s": [ + 94.195, + 100.513, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + -3.65, + 8.13 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.02, + -0.2 + ] + ], + "v": [ + [ + -6, + 1.4 + ], + [ + 6, + -2.5 + ] + ], + "c": false + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.833 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0.167 + ] + }, + "t": 57, + "s": [ + 15 + ] + }, + { + "t": 62, + "s": [ + 0 + ] + } + ], + "ix": 1 + }, + "e": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.833 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.167 + ], + "y": [ + 0.167 + ] + }, + "t": 57, + "s": [ + 100 + ] + }, + { + "t": 62, + "s": [ + 65 + ] + } + ], + "ix": 2 + }, + "o": { + "a": 0, + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "修剪路径 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 3 + }, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 3, + "ix": 5 + }, + "lc": 2, + "lj": 2, + "bm": 0, + "nm": "描边 1", + "mn": "ADBE Vector Graphic - Stroke", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + -0.25, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": -5, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "嘴巴", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 56, + "op": 306, + "st": 6, + "bm": 0 + }, + { + "ddd": 0, + "ind": 13, + "ty": 4, + "nm": "嘴巴", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.26, + "y": 0.74 + }, + "t": 5, + "s": [ + 94.195, + 100.513, + 0 + ], + "to": [ + 0, + -0.169, + 0 + ], + "ti": [ + 0, + 0.169, + 0 + ] + }, + { + "t": 10, + "s": [ + 94.195, + 99.5, + 0 + ] + } + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + -3.65, + 8.13 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.02, + -0.2 + ] + ], + "v": [ + [ + -6, + 1.4 + ], + [ + 6, + -2.5 + ] + ], + "c": false + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.833 + ], + "y": [ + 0.833 + ] + }, + "o": { + "x": [ + 0.26 + ], + "y": [ + 0.5 + ] + }, + "t": 5, + "s": [ + 0 + ] + }, + { + "t": 10, + "s": [ + 15 + ] + } + ], + "ix": 1, + "x": "var $bm_rt;\nvar nearestKeyIndex, nearestKeyIndex, currentTime, currentTime, calculatedVelocity, amplitude, frequency, decay;\n$bm_rt = nearestKeyIndex = 0;\nif (numKeys > 0) {\n $bm_rt = nearestKeyIndex = nearestKey(time).index;\n if (key(nearestKeyIndex).time > time) {\n nearestKeyIndex--;\n }\n}\nif (nearestKeyIndex == 0) {\n $bm_rt = currentTime = 0;\n} else {\n $bm_rt = currentTime = $bm_sub(time, key(nearestKeyIndex).time);\n}\nif (nearestKeyIndex > 0 && currentTime < 1) {\n calculatedVelocity = velocityAtTime($bm_sub(key(nearestKeyIndex).time, $bm_div(thisComp.frameDuration, 10)));\n amplitude = 0.2;\n frequency = 2;\n decay = 6;\n $bm_rt = $bm_sum(value, $bm_div($bm_mul($bm_mul(calculatedVelocity, amplitude), Math.sin($bm_mul($bm_mul($bm_mul(frequency, currentTime), 2), Math.PI))), Math.exp($bm_mul(decay, currentTime))));\n} else {\n $bm_rt = value;\n}" + }, + "e": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.833 + ], + "y": [ + 0.833 + ] + }, + "o": { + "x": [ + 0.26 + ], + "y": [ + 0.5 + ] + }, + "t": 5, + "s": [ + 65 + ] + }, + { + "t": 10, + "s": [ + 100 + ] + } + ], + "ix": 2, + "x": "var $bm_rt;\nvar nearestKeyIndex, nearestKeyIndex, currentTime, currentTime, calculatedVelocity, amplitude, frequency, decay;\n$bm_rt = nearestKeyIndex = 0;\nif (numKeys > 0) {\n $bm_rt = nearestKeyIndex = nearestKey(time).index;\n if (key(nearestKeyIndex).time > time) {\n nearestKeyIndex--;\n }\n}\nif (nearestKeyIndex == 0) {\n $bm_rt = currentTime = 0;\n} else {\n $bm_rt = currentTime = $bm_sub(time, key(nearestKeyIndex).time);\n}\nif (nearestKeyIndex > 0 && currentTime < 1) {\n calculatedVelocity = velocityAtTime($bm_sub(key(nearestKeyIndex).time, $bm_div(thisComp.frameDuration, 10)));\n amplitude = 0.2;\n frequency = 2;\n decay = 6;\n $bm_rt = $bm_sum(value, $bm_div($bm_mul($bm_mul(calculatedVelocity, amplitude), Math.sin($bm_mul($bm_mul($bm_mul(frequency, currentTime), 2), Math.PI))), Math.exp($bm_mul(decay, currentTime))));\n} else {\n $bm_rt = value;\n}" + }, + "o": { + "a": 0, + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "修剪路径 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 3 + }, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 3, + "ix": 5 + }, + "lc": 2, + "lj": 2, + "bm": 0, + "nm": "描边 1", + "mn": "ADBE Vector Graphic - Stroke", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + -0.25, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": -5, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "嘴巴", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 56, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 14, + "ty": 4, + "nm": "右眼", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 108, + 77, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 0, + "k": [ + 10, + 10 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "nm": "椭圆路径 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "右眼", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 15, + "ty": 4, + "nm": "左眼", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 80, + 77, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + -0.028, + -0.775 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "椭圆 1", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 0, + "k": [ + 10, + 10 + ], + "ix": 2 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "nm": "椭圆路径 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "左眼", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 2, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 16, + "ty": 4, + "nm": "折角", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 124.125, + 116.629, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 4.15, + 0 + ], + [ + 0, + -10.44 + ], + [ + -0.76, + -2.02 + ], + [ + -0.47, + -0.83 + ] + ], + "o": [ + [ + -3.16, + -2.16 + ], + [ + -10.73, + 0 + ], + [ + 0, + 2.29 + ], + [ + 0.34, + 0.9 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 15.125, + -11.559 + ], + [ + 4.315, + -14.129 + ], + [ + -15.125, + 4.771 + ], + [ + -13.945, + 11.271 + ], + [ + -12.535, + 14.131 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 3 + }, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 3.165, + "ix": 5 + }, + "lc": 2, + "lj": 2, + "bm": 0, + "nm": "描边 1", + "mn": "ADBE Vector Graphic - Stroke", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 0.20000000298 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 20, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "折角", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 17, + "ty": 4, + "nm": "圆圈", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 101, + 91.5, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 4.61 + ], + [ + 22.64, + 0 + ], + [ + 0, + -22.64 + ], + [ + -22.64, + 0 + ], + [ + -3.19, + 0.79 + ] + ], + "o": [ + [ + 1.4, + -4.14 + ], + [ + 0, + -22.64 + ], + [ + -22.64, + 0 + ], + [ + 0, + 22.64 + ], + [ + 3.44, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 38.25, + 13.57 + ], + [ + 41, + 0 + ], + [ + 0, + -41 + ], + [ + -41, + 0 + ], + [ + 0, + 41 + ], + [ + 10.59, + 39.26 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "路径 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1, + 1 + ], + "ix": 3 + }, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 3, + "ix": 5 + }, + "lc": 2, + "lj": 2, + "bm": 0, + "nm": "描边 1", + "mn": "ADBE Vector Graphic - Stroke", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.105882354081, + 0.098039217293, + 0.211764708161, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "填充 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "变换" + } + ], + "nm": "圆圈", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 18, + "ty": 0, + "nm": "流星_[00036-00052].png", + "cl": "png", + "refId": "sequence_0", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 101, + 122, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 101, + 122, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "w": 202, + "h": 244, + "ip": 36, + "op": 53, + "st": 36, + "bm": 0 + }, + { + "ddd": 0, + "ind": 19, + "ty": 0, + "nm": "流星", + "refId": "comp_0", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 101, + 122, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 101, + 122, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "w": 202, + "h": 244, + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + } + ], + "markers": [ + { + "tm": 0, + "cm": "0", + "dr": 0 + }, + { + "tm": 5, + "cm": "1", + "dr": 0 + }, + { + "tm": 16, + "cm": "2", + "dr": 0 + }, + { + "tm": 41, + "cm": "3", + "dr": 0 + }, + { + "tm": 56, + "cm": "4", + "dr": 0 + }, + { + "tm": 62, + "cm": "5", + "dr": 0 + } + ] +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/animoji/baihu_Animoji.bundle b/FaceUnity/src/main/assets/animoji/baihu_Animoji.bundle new file mode 100644 index 000000000..a78c51d65 Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/baihu_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/baimao_Animoji.bundle b/FaceUnity/src/main/assets/animoji/baimao_Animoji.bundle new file mode 100644 index 000000000..708a73cae Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/baimao_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/cartoon_princess_Animoji.bundle b/FaceUnity/src/main/assets/animoji/cartoon_princess_Animoji.bundle new file mode 100644 index 000000000..cab34c84d Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/cartoon_princess_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/douniuquan_Animoji.bundle b/FaceUnity/src/main/assets/animoji/douniuquan_Animoji.bundle new file mode 100644 index 000000000..74ae417ed Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/douniuquan_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/frog_Animoji.bundle b/FaceUnity/src/main/assets/animoji/frog_Animoji.bundle new file mode 100644 index 000000000..84ac64458 Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/frog_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/hashiqi_Animoji.bundle b/FaceUnity/src/main/assets/animoji/hashiqi_Animoji.bundle new file mode 100644 index 000000000..52843b920 Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/hashiqi_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/hetun_Animoji.bundle b/FaceUnity/src/main/assets/animoji/hetun_Animoji.bundle new file mode 100644 index 000000000..2a8ddfbd4 Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/hetun_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/huangya_Animoji.bundle b/FaceUnity/src/main/assets/animoji/huangya_Animoji.bundle new file mode 100644 index 000000000..50f51182c Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/huangya_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/kaola_Animoji.bundle b/FaceUnity/src/main/assets/animoji/kaola_Animoji.bundle new file mode 100644 index 000000000..bbbad5d30 Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/kaola_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/kuloutou_Animoji.bundle b/FaceUnity/src/main/assets/animoji/kuloutou_Animoji.bundle new file mode 100644 index 000000000..b69842c62 Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/kuloutou_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/qgirl_Animoji.bundle b/FaceUnity/src/main/assets/animoji/qgirl_Animoji.bundle new file mode 100644 index 000000000..9b93c855c Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/qgirl_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/animoji/wuxia_Animoji.bundle b/FaceUnity/src/main/assets/animoji/wuxia_Animoji.bundle new file mode 100644 index 000000000..8dc259842 Binary files /dev/null and b/FaceUnity/src/main/assets/animoji/wuxia_Animoji.bundle differ diff --git a/FaceUnity/src/main/assets/effect/action/actiongame_android.bundle b/FaceUnity/src/main/assets/effect/action/actiongame_android.bundle new file mode 100644 index 000000000..4eaf23ef2 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/action/actiongame_android.bundle differ diff --git a/FaceUnity/src/main/assets/effect/ar/baozi.bundle b/FaceUnity/src/main/assets/effect/ar/baozi.bundle new file mode 100644 index 000000000..234c5c70b Binary files /dev/null and b/FaceUnity/src/main/assets/effect/ar/baozi.bundle differ diff --git a/FaceUnity/src/main/assets/effect/ar/bluebird.bundle b/FaceUnity/src/main/assets/effect/ar/bluebird.bundle new file mode 100644 index 000000000..9a26e4229 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/ar/bluebird.bundle differ diff --git a/FaceUnity/src/main/assets/effect/ar/fenhudie.bundle b/FaceUnity/src/main/assets/effect/ar/fenhudie.bundle new file mode 100644 index 000000000..affbcb7a3 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/ar/fenhudie.bundle differ diff --git a/FaceUnity/src/main/assets/effect/ar/lanhudie.bundle b/FaceUnity/src/main/assets/effect/ar/lanhudie.bundle new file mode 100644 index 000000000..b7476fef8 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/ar/lanhudie.bundle differ diff --git a/FaceUnity/src/main/assets/effect/ar/tiger.bundle b/FaceUnity/src/main/assets/effect/ar/tiger.bundle new file mode 100644 index 000000000..0997d0f6a Binary files /dev/null and b/FaceUnity/src/main/assets/effect/ar/tiger.bundle differ diff --git a/FaceUnity/src/main/assets/effect/ar/tiger_bai.bundle b/FaceUnity/src/main/assets/effect/ar/tiger_bai.bundle new file mode 100644 index 000000000..d4a68138d Binary files /dev/null and b/FaceUnity/src/main/assets/effect/ar/tiger_bai.bundle differ diff --git a/FaceUnity/src/main/assets/effect/ar/tiger_huang.bundle b/FaceUnity/src/main/assets/effect/ar/tiger_huang.bundle new file mode 100644 index 000000000..d94500201 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/ar/tiger_huang.bundle differ diff --git a/FaceUnity/src/main/assets/effect/ar/xiongmao.bundle b/FaceUnity/src/main/assets/effect/ar/xiongmao.bundle new file mode 100644 index 000000000..57c1f94a9 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/ar/xiongmao.bundle differ diff --git a/FaceUnity/src/main/assets/effect/big_head/big_head.bundle b/FaceUnity/src/main/assets/effect/big_head/big_head.bundle new file mode 100644 index 000000000..3c7890ab7 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/big_head/big_head.bundle differ diff --git a/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp2.bundle b/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp2.bundle new file mode 100644 index 000000000..9e23331fe Binary files /dev/null and b/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp2.bundle differ diff --git a/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp4.bundle b/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp4.bundle new file mode 100644 index 000000000..778646332 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp4.bundle differ diff --git a/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp5.bundle b/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp5.bundle new file mode 100644 index 000000000..ccef9c7f5 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp5.bundle differ diff --git a/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp6.bundle b/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp6.bundle new file mode 100644 index 000000000..96ee4f503 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/big_head/big_head_facewarp6.bundle differ diff --git a/FaceUnity/src/main/assets/effect/big_head/big_head_smile.bundle b/FaceUnity/src/main/assets/effect/big_head/big_head_smile.bundle new file mode 100644 index 000000000..a90c68982 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/big_head/big_head_smile.bundle differ diff --git a/FaceUnity/src/main/assets/effect/expression/future_warrior.bundle b/FaceUnity/src/main/assets/effect/expression/future_warrior.bundle new file mode 100644 index 000000000..16db3286c Binary files /dev/null and b/FaceUnity/src/main/assets/effect/expression/future_warrior.bundle differ diff --git a/FaceUnity/src/main/assets/effect/expression/jet_mask.bundle b/FaceUnity/src/main/assets/effect/expression/jet_mask.bundle new file mode 100644 index 000000000..baf7eb1e8 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/expression/jet_mask.bundle differ diff --git a/FaceUnity/src/main/assets/effect/expression/luhantongkuan_ztt_fu.bundle b/FaceUnity/src/main/assets/effect/expression/luhantongkuan_ztt_fu.bundle new file mode 100644 index 000000000..3e467c1d6 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/expression/luhantongkuan_ztt_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/expression/qingqing_ztt_fu.bundle b/FaceUnity/src/main/assets/effect/expression/qingqing_ztt_fu.bundle new file mode 100644 index 000000000..8cdeaf20b Binary files /dev/null and b/FaceUnity/src/main/assets/effect/expression/qingqing_ztt_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/expression/sdx2.bundle b/FaceUnity/src/main/assets/effect/expression/sdx2.bundle new file mode 100644 index 000000000..fb8fb3fa7 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/expression/sdx2.bundle differ diff --git a/FaceUnity/src/main/assets/effect/expression/xiaobianzi_zh_fu.bundle b/FaceUnity/src/main/assets/effect/expression/xiaobianzi_zh_fu.bundle new file mode 100644 index 000000000..fdfa9a2b2 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/expression/xiaobianzi_zh_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/expression/xiaoxueshen_ztt_fu.bundle b/FaceUnity/src/main/assets/effect/expression/xiaoxueshen_ztt_fu.bundle new file mode 100644 index 000000000..61e282fb2 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/expression/xiaoxueshen_ztt_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/facewarp/facewarp2.bundle b/FaceUnity/src/main/assets/effect/facewarp/facewarp2.bundle new file mode 100644 index 000000000..8868e88bd Binary files /dev/null and b/FaceUnity/src/main/assets/effect/facewarp/facewarp2.bundle differ diff --git a/FaceUnity/src/main/assets/effect/facewarp/facewarp3.bundle b/FaceUnity/src/main/assets/effect/facewarp/facewarp3.bundle new file mode 100644 index 000000000..71a32bf1d Binary files /dev/null and b/FaceUnity/src/main/assets/effect/facewarp/facewarp3.bundle differ diff --git a/FaceUnity/src/main/assets/effect/facewarp/facewarp4.bundle b/FaceUnity/src/main/assets/effect/facewarp/facewarp4.bundle new file mode 100644 index 000000000..a35cb6b95 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/facewarp/facewarp4.bundle differ diff --git a/FaceUnity/src/main/assets/effect/facewarp/facewarp5.bundle b/FaceUnity/src/main/assets/effect/facewarp/facewarp5.bundle new file mode 100644 index 000000000..a0fabc925 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/facewarp/facewarp5.bundle differ diff --git a/FaceUnity/src/main/assets/effect/facewarp/facewarp6.bundle b/FaceUnity/src/main/assets/effect/facewarp/facewarp6.bundle new file mode 100644 index 000000000..ffbd3b821 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/facewarp/facewarp6.bundle differ diff --git a/FaceUnity/src/main/assets/effect/gesture/ctrl_flower.bundle b/FaceUnity/src/main/assets/effect/gesture/ctrl_flower.bundle new file mode 100644 index 000000000..fad2583fb Binary files /dev/null and b/FaceUnity/src/main/assets/effect/gesture/ctrl_flower.bundle differ diff --git a/FaceUnity/src/main/assets/effect/gesture/ctrl_rain.bundle b/FaceUnity/src/main/assets/effect/gesture/ctrl_rain.bundle new file mode 100644 index 000000000..c34a4b09b Binary files /dev/null and b/FaceUnity/src/main/assets/effect/gesture/ctrl_rain.bundle differ diff --git a/FaceUnity/src/main/assets/effect/gesture/ctrl_snow.bundle b/FaceUnity/src/main/assets/effect/gesture/ctrl_snow.bundle new file mode 100644 index 000000000..800e1d0f3 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/gesture/ctrl_snow.bundle differ diff --git a/FaceUnity/src/main/assets/effect/gesture/ssd_thread_cute.bundle b/FaceUnity/src/main/assets/effect/gesture/ssd_thread_cute.bundle new file mode 100644 index 000000000..dcdde4ead Binary files /dev/null and b/FaceUnity/src/main/assets/effect/gesture/ssd_thread_cute.bundle differ diff --git a/FaceUnity/src/main/assets/effect/gesture/ssd_thread_korheart.bundle b/FaceUnity/src/main/assets/effect/gesture/ssd_thread_korheart.bundle new file mode 100644 index 000000000..f75d253c9 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/gesture/ssd_thread_korheart.bundle differ diff --git a/FaceUnity/src/main/assets/effect/gesture/ssd_thread_six.bundle b/FaceUnity/src/main/assets/effect/gesture/ssd_thread_six.bundle new file mode 100644 index 000000000..6602d71e0 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/gesture/ssd_thread_six.bundle differ diff --git a/FaceUnity/src/main/assets/effect/landmarks.bundle b/FaceUnity/src/main/assets/effect/landmarks.bundle new file mode 100644 index 000000000..82b1031e3 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/landmarks.bundle differ diff --git a/FaceUnity/src/main/assets/effect/musicfilter/douyin_01.bundle b/FaceUnity/src/main/assets/effect/musicfilter/douyin_01.bundle new file mode 100644 index 000000000..d6e31d5e7 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/musicfilter/douyin_01.bundle differ diff --git a/FaceUnity/src/main/assets/effect/musicfilter/douyin_01.mp3 b/FaceUnity/src/main/assets/effect/musicfilter/douyin_01.mp3 new file mode 100644 index 000000000..16f895789 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/musicfilter/douyin_01.mp3 differ diff --git a/FaceUnity/src/main/assets/effect/musicfilter/douyin_02.bundle b/FaceUnity/src/main/assets/effect/musicfilter/douyin_02.bundle new file mode 100644 index 000000000..58253544a Binary files /dev/null and b/FaceUnity/src/main/assets/effect/musicfilter/douyin_02.bundle differ diff --git a/FaceUnity/src/main/assets/effect/musicfilter/douyin_02.mp3 b/FaceUnity/src/main/assets/effect/musicfilter/douyin_02.mp3 new file mode 100644 index 000000000..16f895789 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/musicfilter/douyin_02.mp3 differ diff --git a/FaceUnity/src/main/assets/effect/normal/cat_sparks.bundle b/FaceUnity/src/main/assets/effect/normal/cat_sparks.bundle new file mode 100644 index 000000000..088b1bdfc Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/cat_sparks.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/daisypig.bundle b/FaceUnity/src/main/assets/effect/normal/daisypig.bundle new file mode 100644 index 000000000..8c0739f1a Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/daisypig.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/fashi.bundle b/FaceUnity/src/main/assets/effect/normal/fashi.bundle new file mode 100644 index 000000000..7318669d3 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/fashi.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/fu_zh_fenshu.bundle b/FaceUnity/src/main/assets/effect/normal/fu_zh_fenshu.bundle new file mode 100644 index 000000000..a5f523b7b Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/fu_zh_fenshu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/gaoshiqing.bundle b/FaceUnity/src/main/assets/effect/normal/gaoshiqing.bundle new file mode 100644 index 000000000..153d019fa Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/gaoshiqing.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/newy1.bundle b/FaceUnity/src/main/assets/effect/normal/newy1.bundle new file mode 100644 index 000000000..a4d86abab Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/newy1.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/redribbt.bundle b/FaceUnity/src/main/assets/effect/normal/redribbt.bundle new file mode 100644 index 000000000..ab5fea384 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/redribbt.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/sdlr.bundle b/FaceUnity/src/main/assets/effect/normal/sdlr.bundle new file mode 100644 index 000000000..ebc18df6d Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/sdlr.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/sdlu.bundle b/FaceUnity/src/main/assets/effect/normal/sdlu.bundle new file mode 100644 index 000000000..fad48d6ec Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/sdlu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/wobushi.bundle b/FaceUnity/src/main/assets/effect/normal/wobushi.bundle new file mode 100644 index 000000000..3c98927d7 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/wobushi.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/xlong_zh_fu.bundle b/FaceUnity/src/main/assets/effect/normal/xlong_zh_fu.bundle new file mode 100644 index 000000000..914ad6c4c Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/xlong_zh_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/normal/xueqiu_lm_fu.bundle b/FaceUnity/src/main/assets/effect/normal/xueqiu_lm_fu.bundle new file mode 100644 index 000000000..f6bf32deb Binary files /dev/null and b/FaceUnity/src/main/assets/effect/normal/xueqiu_lm_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/bg_segment.bundle b/FaceUnity/src/main/assets/effect/segment/bg_segment.bundle new file mode 100644 index 000000000..ddc65ca20 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/bg_segment.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/boyfriend1.bundle b/FaceUnity/src/main/assets/effect/segment/boyfriend1.bundle new file mode 100644 index 000000000..49008e265 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/boyfriend1.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/boyfriend2.bundle b/FaceUnity/src/main/assets/effect/segment/boyfriend2.bundle new file mode 100644 index 000000000..e3da0418d Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/boyfriend2.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/boyfriend3.bundle b/FaceUnity/src/main/assets/effect/segment/boyfriend3.bundle new file mode 100644 index 000000000..b07a9bb23 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/boyfriend3.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/gufeng_zh_fu.bundle b/FaceUnity/src/main/assets/effect/segment/gufeng_zh_fu.bundle new file mode 100644 index 000000000..120948ebf Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/gufeng_zh_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/hez_ztt_fu.bundle b/FaceUnity/src/main/assets/effect/segment/hez_ztt_fu.bundle new file mode 100644 index 000000000..73cd7d3df Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/hez_ztt_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/human_outline.bundle b/FaceUnity/src/main/assets/effect/segment/human_outline.bundle new file mode 100644 index 000000000..14adbadac Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/human_outline.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/ice_lm_fu.bundle b/FaceUnity/src/main/assets/effect/segment/ice_lm_fu.bundle new file mode 100644 index 000000000..2c41a4a5d Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/ice_lm_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/sea_lm_fu.bundle b/FaceUnity/src/main/assets/effect/segment/sea_lm_fu.bundle new file mode 100644 index 000000000..d4061c598 Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/sea_lm_fu.bundle differ diff --git a/FaceUnity/src/main/assets/effect/segment/xiandai_ztt_fu.bundle b/FaceUnity/src/main/assets/effect/segment/xiandai_ztt_fu.bundle new file mode 100644 index 000000000..67091225e Binary files /dev/null and b/FaceUnity/src/main/assets/effect/segment/xiandai_ztt_fu.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/color_setup.json b/FaceUnity/src/main/assets/makeup/color_setup.json new file mode 100644 index 000000000..319525c61 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/color_setup.json @@ -0,0 +1,1170 @@ +{ + "color_mu_style_eyebrow_01": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyeshadow_01": { + "color1": [ + 1.0, + 0.43, + 0.44, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color2": [ + 0.88, + 0.32, + 0.32, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color3": [ + 0.90, + 0.55, + 0.36, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color4": [ + 0.78, + 0.24, + 0.37, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color5": [ + 1.0, + 0.42, + 0.49, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "color_mu_style_eyeshadow_02": { + "color1": [ + 1.0, + 0.72, + 0.36, + 1.0, + 0.93, + 0.45, + 0.25, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color2": [ + 0.89, + 0.61, + 0.41, + 1.0, + 0.86, + 0.26, + 0.07, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color3": [ + 0.98, + 0.75, + 0.52, + 1.0, + 0.66, + 0.28, + 0.23, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color4": [ + 1.0, + 0.58, + 0.40, + 1.0, + 0.72, + 0.38, + 0.14, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color5": [ + 1.0, + 0.62, + 0.55, + 1.0, + 0.56, + 0.17, + 0.17, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "color_mu_style_eyeshadow_03": { + "color1": [ + 1.0, + 0.72, + 0.36, + 1.0, + 0.93, + 0.45, + 0.25, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color2": [ + 0.89, + 0.61, + 0.41, + 1.0, + 0.86, + 0.26, + 0.07, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color3": [ + 0.98, + 0.75, + 0.52, + 1.0, + 0.66, + 0.28, + 0.23, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color4": [ + 1.0, + 0.58, + 0.40, + 1.0, + 0.72, + 0.38, + 0.14, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color5": [ + 1.0, + 0.62, + 0.55, + 1.0, + 0.56, + 0.17, + 0.17, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "color_mu_style_eyeshadow_04": { + "color1": [ + 0.82, + 0.15, + 0.24, + 1.0, + 1.0, + 0.92, + 0.74, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color2": [ + 0.88, + 0.32, + 0.32, + 1.0, + 0.97, + 0.86, + 0.78, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color3": [ + 0.90, + 0.55, + 0.36, + 1.0, + 0.98, + 0.8, + 0.76, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color4": [ + 0.78, + 0.24, + 0.37, + 1.0, + 0.92, + 0.91, + 0.84, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "color5": [ + 1.0, + 0.43, + 0.44, + 1.0, + 0.99, + 0.78, + 0.84, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "color_mu_style_eyeshadow_05": { + "color1": [ + 1.0, + 0.72, + 0.36, + 1.0, + 1.0, + 0.43, + 0.44, + 1.0, + 0.72, + 0.38, + 0.15, + 1.0 + ], + "color2": [ + 0.89, + 0.61, + 0.41, + 1.0, + 0.78, + 0.24, + 0.37, + 1.0, + 0.56, + 0.17, + 0.17, + 1.0 + ], + "color3": [ + 0.98, + 0.75, + 0.52, + 1.0, + 0.90, + 0.55, + 0.36, + 1.0, + 0.93, + 0.45, + 0.25, + 1.0 + ], + "color4": [ + 1.0, + 0.58, + 0.40, + 1.0, + 0.88, + 0.32, + 0.32, + 1.0, + 0.66, + 0.28, + 0.23, + 1.0 + ], + "color5": [ + 1.0, + 0.62, + 0.55, + 1.0, + 1.0, + 0.42, + 0.49, + 1.0, + 0.86, + 0.26, + 0.07, + 1.0 + ] + }, + "color_mu_style_eyeshadow_06": { + "color1": [ + 1.0, + 0.43, + 0.44, + 1.0, + 0.66, + 0.28, + 0.23, + 1.0, + 1.0, + 0.92, + 0.74, + 1.0 + ], + "color2": [ + 0.88, + 0.32, + 0.32, + 1.0, + 0.69, + 0.25, + 0.25, + 1.0, + 0.98, + 0.8, + 0.76, + 1.0 + ], + "color3": [ + 0.90, + 0.55, + 0.36, + 1.0, + 0.72, + 0.38, + 0.15, + 1.0, + 0.97, + 0.86, + 0.78, + 1.0 + ], + "color4": [ + 1.0, + 0.58, + 0.40, + 1.0, + 0.56, + 0.17, + 0.17, + 1.0, + 0.99, + 0.78, + 0.84, + 1.0 + ], + "color5": [ + 1.0, + 0.62, + 0.55, + 1.0, + 0.86, + 0.26, + 0.07, + 1.0, + 0.92, + 0.91, + 0.84, + 1.0 + ] + }, + "color_mu_style_eyelash_01": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyelash_02": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyelash_03": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyelash_04": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyelash_05": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyelash_06": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyeliner_01": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyeliner_02": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyeliner_03": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyeliner_04": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyeliner_05": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyeliner_06": { + "color1": [ + 0.36, + 0.10, + 0.10, + 1.0 + ], + "color2": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "color3": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "color4": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "color5": [ + 0.31, + 0.17, + 0.22, + 1.0 + ] + }, + "color_mu_style_foundation_01": { + "color1": [ + 0.82, + 0.71, + 0.62, + 1.0 + ], + "color2": [ + 0.87, + 0.74, + 0.69, + 1.0 + ], + "color3": [ + 0.91, + 0.81, + 0.74, + 1.0 + ], + "color4": [ + 0.8, + 0.74, + 0.65, + 1.0 + ], + "color5": [ + 0.74, + 0.62, + 0.56, + 1.0 + ] + }, + "color_mu_style_highlight_01": { + "color1": [ + 0.98, + 0.95, + 0.94, + 1.0 + ], + "color2": [ + 1.0, + 0.97, + 0.93, + 1.0 + ], + "color3": [ + 1.0, + 0.96, + 0.93, + 1.0 + ], + "color4": [ + 0.97, + 0.95, + 0.95, + 1.0 + ], + "color5": [ + 0.99, + 0.98, + 0.95, + 1.0 + ] + }, + "color_mu_style_highlight_02": { + "color1": [ + 0.98, + 0.95, + 0.94, + 1.0 + ], + "color2": [ + 1.0, + 0.97, + 0.93, + 1.0 + ], + "color3": [ + 1.0, + 0.96, + 0.93, + 1.0 + ], + "color4": [ + 0.97, + 0.95, + 0.95, + 1.0 + ], + "color5": [ + 0.99, + 0.98, + 0.95, + 1.0 + ] + }, + "color_mu_style_blush_01": { + "color1": [ + 0.96, + 0.44, + 0.42, + 1.0 + ], + "color2": [ + 0.93, + 0.35, + 0.43, + 1.0 + ], + "color3": [ + 0.89, + 0.26, + 0.28, + 1.0 + ], + "color4": [ + 0.89, + 0.26, + 0.40, + 1.0 + ], + "color5": [ + 1.0, + 0.39, + 0.32, + 1.0 + ] + }, + "color_mu_style_blush_02": { + "color1": [ + 0.96, + 0.44, + 0.42, + 1.0 + ], + "color2": [ + 0.93, + 0.35, + 0.43, + 1.0 + ], + "color3": [ + 0.89, + 0.26, + 0.28, + 1.0 + ], + "color4": [ + 0.89, + 0.26, + 0.40, + 1.0 + ], + "color5": [ + 1.0, + 0.39, + 0.32, + 1.0 + ] + }, + "color_mu_style_blush_03": { + "color1": [ + 0.96, + 0.44, + 0.42, + 1.0 + ], + "color2": [ + 0.93, + 0.35, + 0.43, + 1.0 + ], + "color3": [ + 0.89, + 0.26, + 0.28, + 1.0 + ], + "color4": [ + 0.89, + 0.26, + 0.40, + 1.0 + ], + "color5": [ + 1.0, + 0.39, + 0.32, + 1.0 + ] + }, + "color_mu_style_blush_04": { + "color1": [ + 0.96, + 0.44, + 0.42, + 1.0 + ], + "color2": [ + 0.93, + 0.35, + 0.43, + 1.0 + ], + "color3": [ + 0.89, + 0.26, + 0.28, + 1.0 + ], + "color4": [ + 0.89, + 0.26, + 0.40, + 1.0 + ], + "color5": [ + 1.0, + 0.39, + 0.32, + 1.0 + ] + }, + "color_mu_style_contour_01": { + "color1": [ + 0.33, + 0.16, + 0.09, + 1.0 + ], + "color2": [ + 0.41, + 0.22, + 0.15, + 1.0 + ], + "color3": [ + 0.34, + 0.1, + 0.1, + 1.0 + ], + "color4": [ + 0.4, + 0.12, + 0.18, + 1.0 + ], + "color5": [ + 0.32, + 0.23, + 0.16, + 1.0 + ] + }, + "color_mu_style_lip_01": { + "color1": [ + 0.60, + 0.16, + 0.16, + 1.0 + ], + "color2": [ + 0.84, + 0.16, + 0.27, + 1.0 + ], + "color3": [ + 0.84, + 0.26, + 0.16, + 1.0 + ], + "color4": [ + 0.60, + 0.11, + 0.23, + 1.0 + ], + "color5": [ + 0.81, + 0.31, + 0.22, + 1.0 + ] + }, + "color_mu_style_eyepupil_01": { + "color1": [ + 0.33, + 0.13, + 0.06, + 1.0 + ], + "color2": [ + 0.61, + 0.18, + 0.25, + 1.0 + ], + "color3": [ + 0.73, + 0.51, + 0.11, + 1.0 + ], + "color4": [ + 0.13, + 0.72, + 0.72, + 1.0 + ], + "color5": [ + 0.39, + 0.64, + 0.43, + 1.0 + ] + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/chaoa.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/chaoa.bundle new file mode 100644 index 000000000..6d6f3482d Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/chaoa.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/chaomo.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/chaomo.bundle new file mode 100644 index 000000000..1fe066467 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/chaomo.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/chuju.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/chuju.bundle new file mode 100644 index 000000000..e305fb652 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/chuju.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/chuqiu.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/chuqiu.bundle new file mode 100644 index 000000000..44ee9310f Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/chuqiu.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/diadiatu.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/diadiatu.bundle new file mode 100644 index 000000000..89a9e82cb Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/diadiatu.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/dongling.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/dongling.bundle new file mode 100644 index 000000000..32d298843 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/dongling.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/dousha.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/dousha.bundle new file mode 100644 index 000000000..268fd7fed Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/dousha.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/gangfeng.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/gangfeng.bundle new file mode 100644 index 000000000..a8122028f Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/gangfeng.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/guofeng.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/guofeng.bundle new file mode 100644 index 000000000..7accb7084 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/guofeng.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/hongfeng.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/hongfeng.bundle new file mode 100644 index 000000000..ef4791e7d Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/hongfeng.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/hunxie.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/hunxie.bundle new file mode 100644 index 000000000..dadea8d79 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/hunxie.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/jianling.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/jianling.bundle new file mode 100644 index 000000000..a2c29b49b Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/jianling.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/linjia.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/linjia.bundle new file mode 100644 index 000000000..205476c8c Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/linjia.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/naicha.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/naicha.bundle new file mode 100644 index 000000000..73dd2bf5b Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/naicha.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/nuandong.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/nuandong.bundle new file mode 100644 index 000000000..2d3f202af Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/nuandong.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/oumei.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/oumei.bundle new file mode 100644 index 000000000..c2aaee19a Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/oumei.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/qianzhihe.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/qianzhihe.bundle new file mode 100644 index 000000000..8b01613b4 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/qianzhihe.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/renyu.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/renyu.bundle new file mode 100644 index 000000000..9d1a0e314 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/renyu.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/rose.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/rose.bundle new file mode 100644 index 000000000..c5292c559 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/rose.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/shaonv.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/shaonv.bundle new file mode 100644 index 000000000..1525c841b Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/shaonv.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/tianmei.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/tianmei.bundle new file mode 100644 index 000000000..252c9d35b Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/tianmei.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/wumei.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/wumei.bundle new file mode 100644 index 000000000..8199e47fd Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/wumei.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/xinggan.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/xinggan.bundle new file mode 100644 index 000000000..18055a693 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/xinggan.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/yanshimao.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/yanshimao.bundle new file mode 100644 index 000000000..cd8c16f4a Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/yanshimao.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/combination_bundle/ziyun.bundle b/FaceUnity/src/main/assets/makeup/combination_bundle/ziyun.bundle new file mode 100644 index 000000000..e3cef9ad0 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/combination_bundle/ziyun.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/config_json/chaomo.json b/FaceUnity/src/main/assets/makeup/config_json/chaomo.json new file mode 100644 index 000000000..053bd9622 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/chaomo.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 0.800000011920929, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 1.0, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 1.0, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 0.9882352948188782, + 0.95686274766922, + 0.9372549057006836, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 1.0, + "makeup_lip_color": [ + 0.501960813999176, + 0.10196078568696976, + 0.10196078568696976, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 1.0, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/chuju.json b/FaceUnity/src/main/assets/makeup/config_json/chuju.json new file mode 100644 index 000000000..909d1f1ec --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/chuju.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 0.800000011920929, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 0.800000011920929, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 0.699999988079071, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.6000000238418579, + "makeup_lip_color": [ + 0.6509804129600525, + 0.3019607961177826, + 0.250980406999588, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 0.8999999761581421, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/chuqiu.json b/FaceUnity/src/main/assets/makeup/config_json/chuqiu.json new file mode 100644 index 000000000..d6a8201a6 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/chuqiu.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 1.0, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 1.0, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 1.0, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 0.9882352948188782, + 0.9647058844566345, + 0.9490196108818054, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 0.800000011920929, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.6000000238418579, + "makeup_lip_color": [ + 0.7215686440467835, + 0.2705882489681244, + 0.18039216101169587, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 0.8999999761581421, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/diadiatu.json b/FaceUnity/src/main/assets/makeup/config_json/diadiatu.json new file mode 100644 index 000000000..51df2ff45 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/diadiatu.json @@ -0,0 +1,102 @@ +{ + "makeup_eyelash_color": [ + 0.3333333432674408, + 0.1921568661928177, + 0.1568627506494522, + 1.0 + ], + "tex_eyelash": "eyelash03.png", + "makeup_intensity_eyelash": 0.699999988079071, + "makeup_name": "Group_1_25", + "makeup_eyeBrow_color": [ + 0.5254902243614197, + 0.45098039507865906, + 0.32156863808631897, + 1.0 + ], + "tex_eyeBrow": "brow6.png", + "brow_warp": 0.0, + "brow_warp_type": 0, + "use_brow_v2": 1, + "makeup_intensity_eyeBrow": 0.800000011920929, + "makeup_eyeLiner_color": [ + 0.5098039507865906, + 0.30588236451148987, + 0.2549019753932953, + 1.0 + ], + "tex_eyeLiner": "eyeliner04.png", + "makeup_intensity_eyeLiner": 0.75, + "blend_type_tex_eye": 1, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "makeup_eye_color2": [ + 0.47843137383461, + 0.24313725531101227, + 0.2235294133424759, + 1.0 + ], + "makeup_eye_color3": [ + 0.49803921580314636, + 0.20392157137393951, + 0.1921568661928177, + 1.0 + ], + "tex_eye": "eye11.png", + "tex_eye2": "eye66.png", + "tex_eye3": "eye33.png", + "makeup_intensity_eye": 0.6000000238418579, + "makeup_pupil_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_pupil": "美瞳3.png", + "makeup_intensity_pupil": 0.800000011920929, + "makeup_lip_color": [ + 0.7254902124404907, + 0.16862745583057404, + 0.2235294133424759, + 1.0 + ], + "is_two_color": 0, + "tex_lip_mask_zz": "mask1.png", + "tex_lip_mask_bz": "mask.png", + "lip_type": 0, + "makeup_intensity_lip": 0.949999988079071, + "blend_type_tex_blusher": 1, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "mu_style_highlight_02.png", + "makeup_intensity_highlight": 0.699999988079071, + "makeup_shadow_color": [ + 0.7019608020782471, + 0.3764705955982208, + 0.29411765933036804, + 1.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 1.0, + "use_eye_v2": 1 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/dongling.json b/FaceUnity/src/main/assets/makeup/config_json/dongling.json new file mode 100644 index 000000000..42961b8a1 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/dongling.json @@ -0,0 +1,111 @@ +{ + "makeup_lip_color": [ + 0.6784313917160034, + 0.0470588244497776, + 0.24705882370471954, + 1.0 + ], + "makeup_lip_color_v2": [ + 0.6784313917160034, + 0.0470588244497776, + 0.24705882370471954, + 1.0 + ], + "makeup_lip_color_mix_strength": 0.6000000238418579, + "makeup_lip_highlight_strength": 0.800000011920929, + "makeup_lip_highlight_enable": 1, + "tex_lip_mask_zz": "mask1.png", + "tex_lip_mask_bz": "mask.png", + "lip_type": 7, + "makeup_intensity_lip": 0.8999999761581421, + "makeup_name": "Group_1_13", + "blend_type_tex_eye": 1, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 0, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.800000011920929, + 0.10980392247438431, + 0.3294117748737335, + 1.0 + ], + "tex_eye": "eye1.png", + "tex_eye2": "eye_2.png", + "makeup_intensity_eye": 0.8999999761581421, + "makeup_pupil_color": [ + 0.5882353186607361, + 0.5921568870544434, + 0.43921568989753723, + 1.0 + ], + "tex_pupil": "eyepupil.png", + "makeup_intensity_pupil": 1.0, + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 1.0, + 0.11372549086809158, + 0.45490196347236633, + 1.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 0.800000011920929, + "makeup_foundation_color": [ + 0.8627451062202454, + 0.7803921699523926, + 0.7803921699523926, + 1.0 + ], + "tex_foundation": "zhuangrong_fd.png", + "makeup_intensity_foundation": 0.800000011920929, + "makeup_eyelash_color": [ + 0.38823530077934265, + 0.12941177189350128, + 0.21176470816135406, + 1.0 + ], + "tex_eyelash": "eyeLash.png", + "makeup_intensity_eyelash": 0.6000000238418579, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.800000011920929, + "makeup_eyeBrow_color": [ + 0.3176470696926117, + 0.24705882370471954, + 0.22745098173618317, + 1.0 + ], + "tex_eyeBrow": "brow6.png", + "brow_warp": 0.0, + "brow_warp_type": 6, + "use_brow_v2": 1, + "makeup_intensity_eyeBrow": 0.800000011920929, + "makeup_eyeLiner_color": [ + 0.5411764979362488, + 0.14509804546833038, + 0.2705882489681244, + 1.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 0.25, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "mu_style_highlight_01.png", + "makeup_intensity_highlight": 0.800000011920929, + "use_eye_v2": 1 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/gangfeng.json b/FaceUnity/src/main/assets/makeup/config_json/gangfeng.json new file mode 100644 index 000000000..28575a85d --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/gangfeng.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 1.0, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 0.800000011920929, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 0.800000011920929, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 0.8999999761581421, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.800000011920929, + "makeup_lip_color": [ + 0.5803921818733215, + 0.25882354378700259, + 0.20000000298023225, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 0.800000011920929, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/guofeng.json b/FaceUnity/src/main/assets/makeup/config_json/guofeng.json new file mode 100644 index 000000000..9dd3167ee --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/guofeng.json @@ -0,0 +1,96 @@ +{ + "makeup_eyelash_color": [ + 0.6117647290229797, + 0.4313725531101227, + 0.12156862765550613, + 1.0 + ], + "tex_eyelash": "eyeLash03.png", + "makeup_intensity_eyelash": 0.550000011920929, + "makeup_name": "Group_1_25", + "makeup_eyeBrow_color": [ + 0.5254902243614197, + 0.45098039507865906, + 0.32156863808631897, + 1.0 + ], + "tex_eyeBrow": "brow6.png", + "brow_warp": 0.0, + "brow_warp_type": 0, + "use_brow_v2": 1, + "makeup_intensity_eyeBrow": 0.800000011920929, + "makeup_eyeLiner_color": [ + 0.4627451002597809, + 0.35686275362968445, + 0.20392157137393951, + 1.0 + ], + "tex_eyeLiner": "eyeLiner03.png", + "makeup_intensity_eyeLiner": 0.5, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.6705882549285889, + 0.3529411852359772, + 0.19607843458652496, + 1.0 + ], + "tex_eye": "eye03.png", + "makeup_intensity_eye": 0.8500000238418579, + "makeup_lip_color": [ + 0.5490196347236633, + 0.0, + 0.007843137718737125, + 1.0 + ], + "is_two_color": 0, + "tex_lip_mask_zz": "GF1015-5zz.png", + "tex_lip_mask_bz": "GF1015-5.png", + "lip_type": 0, + "makeup_intensity_lip": 1.0, + "blend_type_tex_blusher": 1, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 1.0, + 0.2549019753932953, + 0.27843138575553894, + 1.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 0.30000001192092896, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "mu_style_highlight_02.png", + "makeup_intensity_highlight": 0.550000011920929, + "makeup_foundation_color": [ + 0.6705882549285889, + 0.47058823704719543, + 0.4431372582912445, + 1.0 + ], + "tex_foundation": "zhuangrong_fd.png", + "makeup_intensity_foundation": 0.6000000238418579, + "makeup_shadow_color": [ + 0.5333333611488342, + 0.3294117748737335, + 0.29019609093666077, + 1.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.25, + "makeup_pupil_color": [ + 0.4745098054409027, + 0.42352941632270813, + 0.3960784375667572, + 1.0 + ], + "tex_pupil": "icon_style_eyepupil_03.png", + "makeup_intensity_pupil": 0.5, + "use_eye_v2": 1 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/hongfeng.json b/FaceUnity/src/main/assets/makeup/config_json/hongfeng.json new file mode 100644 index 000000000..900f4ece0 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/hongfeng.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 1.0, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 0.699999988079071, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 0.800000011920929, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 1.0, + "makeup_lip_color": [ + 0.5803921818733215, + 0.250980406999588, + 0.21960784494876862, + 1.0 + ], + "lip_type": 1, + "makeup_intensity_lip": 1.0, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/hunxie.json b/FaceUnity/src/main/assets/makeup/config_json/hunxie.json new file mode 100644 index 000000000..1d9a461a3 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/hunxie.json @@ -0,0 +1,117 @@ +{ + "makeup_lip_color": [ + 0.3764705955982208, + 0.0, + 0.0, + 1.0 + ], + "makeup_lip_color_v2": [ + 0.3764705955982208, + 0.0, + 0.0, + 1.0 + ], + "makeup_lip_color_mix_strength": 0.0, + "makeup_lip_highlight_strength": 0.30000001192092896, + "makeup_lip_highlight_enable": 1, + "tex_lip_mask_zz": "HX1015-3-zz.png", + "tex_lip_mask_bz": "HX1015-3.png", + "lip_type": 7, + "makeup_intensity_lip": 0.8500000238418579, + "makeup_name": "Group_1_8", + "blend_type_tex_eye": 1, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 0, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.47843137383461, + 0.24313725531101227, + 0.2235294133424759, + 1.0 + ], + "makeup_eye_color3": [ + 0.6941176652908325, + 0.3490196168422699, + 0.32156863808631897, + 1.0 + ], + "makeup_eye_color4": [ + 0.6784313917160034, + 0.34117648005485535, + 0.29411765933036804, + 1.0 + ], + "tex_eye": "eye11.png", + "tex_eye2": "eye3.png", + "tex_eye3": "eye66.png", + "tex_eye4": "eye04.png", + "makeup_intensity_eye": 1.0, + "makeup_eyelash_color": [ + 0.4274509847164154, + 0.2666666805744171, + 0.21568627655506134, + 1.0 + ], + "tex_eyelash": "eyelash03.png", + "makeup_intensity_eyelash": 0.8500000238418579, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "mu_style_highlight_02_2.png", + "makeup_intensity_highlight": 0.30000001192092896, + "makeup_eyeLiner_color": [ + 0.4745098054409027, + 0.30980393290519714, + 0.24313725531101227, + 1.0 + ], + "tex_eyeLiner": "eyeLiner04.png", + "makeup_intensity_eyeLiner": 0.800000011920929, + "makeup_pupil_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_pupil": "eyepupil.png", + "makeup_intensity_pupil": 0.550000011920929, + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 1.0, + "makeup_eyeBrow_color": [ + 0.5176470875740051, + 0.47843137383461, + 0.3803921639919281, + 1.0 + ], + "tex_eyeBrow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 6, + "use_brow_v2": 1, + "makeup_intensity_eyeBrow": 0.8999999761581421, + "makeup_shadow_color": [ + 0.7450980544090271, + 0.4745098054409027, + 0.4274509847164154, + 1.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.4000000059604645, + "use_eye_v2": 1 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/jianling.json b/FaceUnity/src/main/assets/makeup/config_json/jianling.json new file mode 100644 index 000000000..ce49b961e --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/jianling.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 0.8999999761581421, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 1.0, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 0.699999988079071, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.699999988079071, + "makeup_lip_color": [ + 0.6509804129600525, + 0.21176470816135407, + 0.29019609093666079, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 0.800000011920929, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/linjia.json b/FaceUnity/src/main/assets/makeup/config_json/linjia.json new file mode 100644 index 000000000..f0eb25871 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/linjia.json @@ -0,0 +1,71 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.89, + 0.26, + 0.28, + 1.0 + ], + "tex_blusher": "mu_style_blush_01.bundle", + "makeup_intensity_blusher": 1.0, + "makeup_eyeBrow_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_brow": "mu_style_eyebrow_01.bundle", + "makeup_intensity_eyeBrow": 0.20000000298023225, + "makeup_eyelash_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_eyeLash": "mu_style_eyelash_01.bundle", + "makeup_intensity_eyelash": 0.699999988079071, + "makeup_eyeLiner_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_eyeLiner": "mu_style_eyeliner_06.bundle", + "makeup_intensity_eyeLiner": 0.699999988079071, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 0, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 1.0, + 0.72, + 0.36, + 1.0 + ], + "makeup_eye_color2": [ + 0.93, + 0.45, + 0.25, + 1.0 + ], + "tex_eye": "mu_style_eyeshadow_02.bundle", + "makeup_intensity_eye": 0.8999999761581421, + "makeup_foundation_color": [ + 0.91, + 0.81, + 0.74, + 1.0 + ], + "tex_foundation": "mu_style_foundation_01.bundle", + "makeup_intensity_foundation": 1.0, + "makeup_lip_color": [ + 0.84, + 0.26, + 0.16, + 1.0 + ], + "lip_type": 0, + "is_two_color": 0, + "makeup_intensity_lip": 0.6000000238418579 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/nuandong.json b/FaceUnity/src/main/assets/makeup/config_json/nuandong.json new file mode 100644 index 000000000..c9858ec32 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/nuandong.json @@ -0,0 +1,96 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 1, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_blusher_color2": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "tex_blusher2": "zhuangrong_sh2.png", + "makeup_intensity_blusher": 0.699999988079071, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 0.8999999761581421, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 0.800000011920929, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 1.0, + "makeup_lip_color": [ + 0.5803921818733215, + 0.20000000298023225, + 0.10196078568696976, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 0.800000011920929, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/oumei.json b/FaceUnity/src/main/assets/makeup/config_json/oumei.json new file mode 100644 index 000000000..4d42e7950 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/oumei.json @@ -0,0 +1,87 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.89, + 0.26, + 0.40, + 1.0 + ], + "tex_blusher": "mu_style_blush_02.bundle", + "makeup_intensity_blusher": 1.0, + "makeup_eyeBrow_color": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "tex_brow": "mu_style_eyebrow_01.bundle", + "makeup_intensity_eyeBrow": 0.5, + "makeup_eyelash_color": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "tex_eyeLash": "mu_style_eyelash_06.bundle", + "makeup_intensity_eyelash": 0.6000000238418579, + "makeup_eyeLiner_color": [ + 0.21, + 0.05, + 0.02, + 1.0 + ], + "tex_eyeLiner": "mu_style_eyeliner_05.bundle", + "makeup_intensity_eyeLiner": 0.4000000059604645, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 1, + "blend_type_tex_eye3": 0, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.82, + 0.15, + 0.24, + 1.0 + ], + "makeup_eye_color2": [ + 1.0, + 0.92, + 0.74, + 1.0 + ], + "tex_eye": "mu_style_eyeshadow_04.bundle", + "makeup_intensity_eye": 0.800000011920929, + "makeup_foundation_color": [ + 0.87, + 0.74, + 0.69, + 1.0 + ], + "tex_foundation": "mu_style_foundation_01.bundle", + "makeup_intensity_foundation": 1.0, + "makeup_highlight_color": [ + 0.97, + 0.95, + 0.95, + 1.0 + ], + "tex_highlight": "mu_style_highlight_02.bundle", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.40, + 0.12, + 0.18, + 1.0 + ], + "tex_shadow": "mu_style_contour_01.bundle", + "makeup_intensity_shadow": 1.0, + "makeup_lip_color": [ + 0.6, + 0.11, + 0.23, + 1.0 + ], + "lip_type": 0, + "is_two_color": 0, + "makeup_intensity_lip": 0.8600000143051148 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/qianzhihe.json b/FaceUnity/src/main/assets/makeup/config_json/qianzhihe.json new file mode 100644 index 000000000..5c91e28c9 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/qianzhihe.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 1.0, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 5, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 0.8999999761581421, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 0.8999999761581421, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 0.8999999761581421, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 1.0, + "makeup_lip_color": [ + 0.5490196347236633, + 0.12156862765550614, + 0.10196078568696976, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 0.8999999761581421, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/renyu.json b/FaceUnity/src/main/assets/makeup/config_json/renyu.json new file mode 100644 index 000000000..9f8573ac3 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/renyu.json @@ -0,0 +1,96 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 1, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_blusher_color2": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "tex_blusher2": "zhuangrong_sh2.png", + "makeup_intensity_blusher": 1.0, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 5, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 1.0, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 1.0, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.800000011920929, + "makeup_lip_color": [ + 0.6000000238418579, + 0.239215686917305, + 0.27843138575553896, + 1.0 + ], + "lip_type": 1, + "makeup_intensity_lip": 0.8999999761581421, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/rose.json b/FaceUnity/src/main/assets/makeup/config_json/rose.json new file mode 100644 index 000000000..fb5798d00 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/rose.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 1, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 1.0, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 1.0, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 1.0, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 1.0, + "makeup_lip_color": [ + 0.38823530077934267, + 0.18039216101169587, + 0.12941177189350129, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 1.0, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/shaonv.json b/FaceUnity/src/main/assets/makeup/config_json/shaonv.json new file mode 100644 index 000000000..c3175b81e --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/shaonv.json @@ -0,0 +1,89 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 0.800000011920929, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.5, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 1.0, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 0.949999988079071, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 0.699999988079071, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.699999988079071, + "makeup_lip_color": [ + 0.5411764979362488, + 0.20000000298023225, + 0.20000000298023225, + 1.0 + ], + "lip_type": 1, + "makeup_intensity_lip": 1.0, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/tianmei.json b/FaceUnity/src/main/assets/makeup/config_json/tianmei.json new file mode 100644 index 000000000..9b0515cd2 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/tianmei.json @@ -0,0 +1,81 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.93, + 0.35, + 0.43, + 1.0 + ], + "tex_blusher": "mu_style_blush_04.bundle", + "makeup_intensity_blusher": 1.0, + "makeup_eyeBrow_color": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "tex_brow": "mu_style_eyebrow_01.bundle", + "makeup_intensity_eyeBrow": 0.5, + "makeup_eyeLiner_color": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "tex_eyeLiner": "mu_style_eyeliner_02.bundle", + "makeup_intensity_eyeLiner": 0.5, + "makeup_eyelash_color": [ + 0.33, + 0.09, + 0.18, + 1.0 + ], + "tex_eyeLash": "mu_style_eyelash_02.bundle", + "makeup_intensity_eyelash": 0.5, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 0, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 1.0, + 0.43, + 0.44, + 1.0 + ], + "tex_eye": "mu_style_eyeshadow_01.bundle", + "makeup_intensity_eye": 0.699999988079071, + "makeup_foundation_color": [ + 0.87, + 0.74, + 0.69, + 1.0 + ], + "tex_foundation": "mu_style_foundation_01.bundle", + "makeup_intensity_foundation": 1.0, + "makeup_highlight_color": [ + 1.0, + 0.96, + 0.93, + 1.0 + ], + "tex_highlight": "mu_style_highlight_01.bundle", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.41, + 0.22, + 0.15, + 1.0 + ], + "tex_shadow": "mu_style_contour_01.bundle", + "makeup_intensity_shadow": 1.0, + "makeup_lip_color": [ + 0.84, + 0.16, + 0.27, + 1.0 + ], + "lip_type": 0, + "is_two_color": 0, + "makeup_intensity_lip": 0.5 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/wumei.json b/FaceUnity/src/main/assets/makeup/config_json/wumei.json new file mode 100644 index 000000000..28d9887aa --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/wumei.json @@ -0,0 +1,79 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 1.0, + 0.39, + 0.32, + 1.0 + ], + "tex_blusher": "mu_style_blush_03.bundle", + "makeup_intensity_blusher": 1.0, + "makeup_eyeBrow_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_brow": "mu_style_eyebrow_01.bundle", + "makeup_intensity_eyeBrow": 0.6000000238418579, + "makeup_eyelash_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_eyeLash": "mu_style_eyelash_03.bundle", + "makeup_intensity_eyelash": 0.6000000238418579, + "makeup_eyeLiner_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_eyeLiner": "mu_style_eyeliner_03.bundle", + "makeup_intensity_eyeLiner": 0.6000000238418579, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 0, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.89, + 0.61, + 0.41, + 1.0 + ], + "makeup_eye_color2": [ + 0.86, + 0.26, + 0.07, + 1.0 + ], + "tex_eye": "mu_style_eyeshadow_03.bundle", + "makeup_intensity_eye": 0.699999988079071, + "makeup_foundation_color": [ + 0.80, + 0.74, + 0.65, + 1.0 + ], + "tex_foundation": "mu_style_foundation_01.bundle", + "makeup_intensity_foundation": 1.0, + "makeup_highlight_color": [ + 0.99, + 0.98, + 0.95, + 1.0 + ], + "tex_highlight": "mu_style_highlight_01.bundle", + "makeup_intensity_highlight": 1.0, + "makeup_lip_color": [ + 0.81, + 0.31, + 0.22, + 1.0 + ], + "lip_type": 0, + "is_two_color": 0, + "makeup_intensity_lip": 0.699999988079071 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/xinggan.json b/FaceUnity/src/main/assets/makeup/config_json/xinggan.json new file mode 100644 index 000000000..d04d1d0fd --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/xinggan.json @@ -0,0 +1,93 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.96, + 0.44, + 0.42, + 1.0 + ], + "tex_blusher": "mu_style_blush_02.bundle", + "makeup_intensity_blusher": 1.0, + "makeup_eyeBrow_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_brow": "mu_style_eyebrow_01.bundle", + "makeup_intensity_eyeBrow": 0.4000000059604645, + "makeup_eyelash_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_eyeLash": "mu_style_eyelash_04.bundle", + "makeup_intensity_eyelash": 0.699999988079071, + "makeup_eyeLiner_color": [ + 0.28, + 0.16, + 0.08, + 1.0 + ], + "tex_eyeLiner": "mu_style_eyeliner_01.bundle", + "makeup_intensity_eyeLiner": 0.6000000238418579, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.88, + 0.32, + 0.32, + 1.0 + ], + "makeup_eye_color2": [ + 0.69, + 0.25, + 0.25, + 1.0 + ], + "makeup_eye_color3": [ + 0.98, + 0.80, + 0.760, + 1.0 + ], + "tex_eye": "mu_style_eyeshadow_06.bundle", + "makeup_intensity_eye": 0.8999999761581421, + "makeup_foundation_color": [ + 0.82, + 0.71, + 0.62, + 1.0 + ], + "tex_foundation": "mu_style_foundation_01.bundle", + "makeup_intensity_foundation": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "mu_style_highlight_02.bundle", + "makeup_intensity_highlight": 0.0, + "makeup_shadow_color": [ + 0.33, + 0.16, + 0.09, + 1.0 + ], + "tex_shadow": "mu_style_contour_01.bundle", + "makeup_intensity_shadow": 1.0, + "makeup_lip_color": [ + 0.60, + 0.16, + 0.16, + 1.0 + ], + "lip_type": 0, + "is_two_color": 0, + "makeup_intensity_lip": 0.800000011920929 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/yanshimao.json b/FaceUnity/src/main/assets/makeup/config_json/yanshimao.json new file mode 100644 index 000000000..8b1a07c9a --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/yanshimao.json @@ -0,0 +1,96 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 1, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_blusher_color2": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "tex_blusher2": "zhuangrong_sh2.png", + "makeup_intensity_blusher": 1.0, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 0.699999988079071, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 0.699999988079071, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 0.8999999761581421, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 1.0, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.800000011920929, + "makeup_lip_color": [ + 0.501960813999176, + 0.10980392247438431, + 0.12941177189350129, + 1.0 + ], + "lip_type": 0, + "makeup_intensity_lip": 0.800000011920929, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/config_json/ziyun.json b/FaceUnity/src/main/assets/makeup/config_json/ziyun.json new file mode 100644 index 000000000..4b52089d3 --- /dev/null +++ b/FaceUnity/src/main/assets/makeup/config_json/ziyun.json @@ -0,0 +1,95 @@ +{ + "blend_type_tex_blusher": 0, + "blend_type_tex_blusher2": 0, + "makeup_blusher_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_blusher_color2": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_blusher": "zhuangrong_sh.png", + "makeup_intensity_blusher": 1.0, + "makeup_brow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_brow": "brow.png", + "brow_warp": 0.0, + "brow_warp_type": 3, + "makeup_intensity_eyeBrow": 0.699999988079071, + "makeup_eyeLash_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLash": "eyeLash.png", + "makeup_intensity_eyelash": 1.0, + "makeup_eyeLiner_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_eyeLiner": "eyeLiner.png", + "makeup_intensity_eyeLiner": 1.0, + "makeup_highlight_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_highlight": "zhuangrong_gg.png", + "makeup_intensity_highlight": 0.800000011920929, + "makeup_shadow_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "tex_shadow": "zhuangrong_yy.png", + "makeup_intensity_shadow": 0.699999988079071, + "makeup_lip_color": [ + 0.5490196347236633, + 0.20000000298023225, + 0.250980406999588, + 1.0 + ], + "lip_type": 1, + "makeup_intensity_lip": 0.8999999761581421, + "blend_type_tex_eye": 0, + "blend_type_tex_eye2": 0, + "blend_type_tex_eye3": 1, + "blend_type_tex_eye4": 0, + "makeup_eye_color": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "makeup_eye_color2": [ + 0.5882353186607361, + 0.3607843220233917, + 0.30588236451148989, + 1.0 + ], + "makeup_eye_color3": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "tex_eye": "eye.png", + "tex_eye2": "eye2.png", + "tex_eye3": "eye3.png", + "makeup_intensity_eye": 1.0, + "use_brow_v2": 1.0 +} \ No newline at end of file diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_01.bundle new file mode 100644 index 000000000..3cb656c69 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_02.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_02.bundle new file mode 100644 index 000000000..8d06af48b Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_02.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_03.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_03.bundle new file mode 100644 index 000000000..78417e58d Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_03.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_04.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_04.bundle new file mode 100644 index 000000000..03308cdd5 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_blush_04.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_contour_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_contour_01.bundle new file mode 100644 index 000000000..d8ffd7ba4 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_contour_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_01.bundle new file mode 100644 index 000000000..f2a1dc002 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_02.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_02.bundle new file mode 100644 index 000000000..c14b4369f Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_02.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_03.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_03.bundle new file mode 100644 index 000000000..8c8b45e55 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_03.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_04.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_04.bundle new file mode 100644 index 000000000..d4be845b8 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyebrow_04.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_01.bundle new file mode 100644 index 000000000..65dfbe7c3 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_02.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_02.bundle new file mode 100644 index 000000000..316fef6bb Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_02.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_03.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_03.bundle new file mode 100644 index 000000000..fe2e9882a Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_03.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_04.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_04.bundle new file mode 100644 index 000000000..f44b74cbb Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_04.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_05.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_05.bundle new file mode 100644 index 000000000..be7c2591f Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_05.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_06.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_06.bundle new file mode 100644 index 000000000..d97622b37 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyelash_06.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_01.bundle new file mode 100644 index 000000000..fb53fc166 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_02.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_02.bundle new file mode 100644 index 000000000..2630bf965 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_02.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_03.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_03.bundle new file mode 100644 index 000000000..85fc251a5 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_03.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_04.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_04.bundle new file mode 100644 index 000000000..56b0b6216 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_04.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_05.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_05.bundle new file mode 100644 index 000000000..79729a674 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_05.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_06.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_06.bundle new file mode 100644 index 000000000..88e2417db Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeliner_06.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_01.bundle new file mode 100644 index 000000000..a2bbcbf5a Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_03.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_03.bundle new file mode 100644 index 000000000..1295c15f6 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_03.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_04.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_04.bundle new file mode 100644 index 000000000..d3f172018 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_04.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_05.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_05.bundle new file mode 100644 index 000000000..f66543bc2 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_05.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_06.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_06.bundle new file mode 100644 index 000000000..f40ca1f4c Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_06.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_07.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_07.bundle new file mode 100644 index 000000000..55a1e3c45 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_07.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_08.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_08.bundle new file mode 100644 index 000000000..9534ec5e0 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_08.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_09.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_09.bundle new file mode 100644 index 000000000..b6199cd8e Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyepupil_09.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_01.bundle new file mode 100644 index 000000000..bd0732fe0 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_02.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_02.bundle new file mode 100644 index 000000000..54c25d9b3 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_02.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_03.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_03.bundle new file mode 100644 index 000000000..973e4d0a2 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_03.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_04.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_04.bundle new file mode 100644 index 000000000..adfb9f5e8 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_04.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_05.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_05.bundle new file mode 100644 index 000000000..c110d66ac Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_05.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_06.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_06.bundle new file mode 100644 index 000000000..a795ba791 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_eyeshadow_06.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_foundation_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_foundation_01.bundle new file mode 100644 index 000000000..3932a45e7 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_foundation_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_highlight_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_highlight_01.bundle new file mode 100644 index 000000000..87d8dbf89 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_highlight_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_highlight_02.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_highlight_02.bundle new file mode 100644 index 000000000..7ed3b7520 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_highlight_02.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_01.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_01.bundle new file mode 100644 index 000000000..ce5625d84 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_01.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_02.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_02.bundle new file mode 100644 index 000000000..410086a3c Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_02.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_03.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_03.bundle new file mode 100644 index 000000000..503dc3728 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_03.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_04.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_04.bundle new file mode 100644 index 000000000..63a2d7e14 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_04.bundle differ diff --git a/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_05.bundle b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_05.bundle new file mode 100644 index 000000000..fd3c071a6 Binary files /dev/null and b/FaceUnity/src/main/assets/makeup/item_bundle/mu_style_lip_05.bundle differ diff --git a/FaceUnity/src/main/assets/sticker/fashi.bundle b/FaceUnity/src/main/assets/sticker/fashi.bundle new file mode 100644 index 000000000..7318669d3 Binary files /dev/null and b/FaceUnity/src/main/assets/sticker/fashi.bundle differ diff --git a/FaceUnity/src/main/assets/sticker/sdlu.bundle b/FaceUnity/src/main/assets/sticker/sdlu.bundle new file mode 100644 index 000000000..fad48d6ec Binary files /dev/null and b/FaceUnity/src/main/assets/sticker/sdlu.bundle differ diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/FaceManager.java b/FaceUnity/src/main/java/com/yunbao/faceunity/FaceManager.java new file mode 100644 index 000000000..e81d12597 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/FaceManager.java @@ -0,0 +1,237 @@ +package com.yunbao.faceunity; + +import static android.content.Context.SENSOR_SERVICE; + +import android.content.Context; +import android.hardware.Camera; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Environment; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.faceunity.core.callback.OperateCallback; +import com.faceunity.core.entity.FURenderOutputData; +import com.faceunity.core.enumeration.CameraFacingEnum; +import com.faceunity.core.enumeration.FUAIProcessorEnum; +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.enumeration.FUInputTextureEnum; +import com.faceunity.core.enumeration.FUTransformMatrixEnum; +import com.faceunity.core.faceunity.FUAIKit; +import com.faceunity.core.faceunity.FURenderManager; +import com.faceunity.core.utils.CameraUtils; +import com.faceunity.core.utils.FULogger; +import com.yunbao.faceunity.data.FaceUnityDataFactory; +import com.yunbao.faceunity.listener.FURendererListener; +import com.yunbao.faceunity.ui.FaceUnityView; +import com.yunbao.faceunity.utils.Authpack; +import com.yunbao.faceunity.utils.CSVUtils; +import com.yunbao.faceunity.utils.FURenderer; +import com.yunbao.faceunity.utils.FaceUnityData; +import com.yunbao.faceunity.utils.net.OkHttpUtils; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import cn.rongcloud.rtc.api.RCRTCEngine; +import cn.rongcloud.rtc.api.callback.IRCRTCVideoOutputFrameListener; +import cn.rongcloud.rtc.base.RCRTCVideoFrame; + +/** + * 美颜模块管理类 + */ +public class FaceManager implements SensorEventListener { + private static boolean isInit = false; + private static final String TAG = FaceManager.class.getSimpleName(); + private FaceUnityDataFactory mFaceUnityDataFactory; + private FaceManager.FaceStatusChanged faceStatusChanged; + + /** + * 初始化美颜模块,在AppContext中调用 + */ + public static void initFaceUnity(Context context) { + if (isInit) { + return; + } + FaceUnityData.mApplication = context; + OkHttpUtils.getInstance().init(context, false); + FURenderManager.setCoreDebug(FULogger.LogLevel.OFF); + FURenderManager.setKitDebug(FULogger.LogLevel.OFF); + FURenderManager.registerFURender(context, Authpack.A(), new OperateCallback() { + @Override + public void onSuccess(int i, @NonNull String s) { + isInit = true; + } + + @Override + public void onFail(int i, @NonNull String s) { + + } + }); + + } + + private FURenderer mFURenderer; + + /** + * 配置美颜SDK + */ + public void initFURender(Context context) { + FURenderer.getInstance().setup(context); + mFURenderer = FURenderer.getInstance(); + mFURenderer.setInputTextureType(FUInputTextureEnum.FU_ADM_FLAG_COMMON_TEXTURE); + mFURenderer.setCameraFacing(CameraFacingEnum.CAMERA_FRONT); + mFURenderer.setInputBufferMatrix(FUTransformMatrixEnum.CCROT90_FLIPHORIZONTAL); + mFURenderer.setInputTextureMatrix(FUTransformMatrixEnum.CCROT90_FLIPHORIZONTAL); + mFURenderer.setOutputMatrix(FUTransformMatrixEnum.CCROT270); + mFURenderer.setInputOrientation(CameraUtils.INSTANCE.getCameraOrientation(Camera.CameraInfo.CAMERA_FACING_FRONT)); + mFURenderer.setMarkFPSEnable(true); + mFaceUnityDataFactory = FaceUnityDataFactory.getInstance(); + + SensorManager mSensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE); + Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL); + } + + /** + * 监听人脸识别个数 + */ + public void setFaceStatusChanged(FaceStatusChanged faceStatusChanged) { + this.faceStatusChanged = faceStatusChanged; + } + + private boolean mIsFirstFrame = true; + private CSVUtils mCSVUtils; + private int mSkippedFrames = CAMERA_SWITCH_SKIP_FRAME; + // 相机切换跳过 5 帧,如果还有问题,可以增加帧数 + private static final int CAMERA_SWITCH_SKIP_FRAME = 0; + private volatile boolean mSkip; + + /** + * 渲染融云视频帧 + */ + public void drawRongFrame(Context context) { + RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(new IRCRTCVideoOutputFrameListener() { + @Override + public RCRTCVideoFrame processVideoFrame(RCRTCVideoFrame callVideoFrame) { + //Log.i(TAG, "processVideoFrame: egl context " + EGL14.eglGetCurrentContext()); + int width = callVideoFrame.getWidth(); + int height = callVideoFrame.getHeight(); + + if (mIsFirstFrame) { + mIsFirstFrame = false; + //initCsvUtil(context); + mFURenderer.prepareRenderer(mFURendererListener); + } + //long start = System.nanoTime(); + mFURenderer.setInputOrientation(callVideoFrame.getRotation()); + FURenderOutputData data = mFURenderer.onDrawFrameInputWithReturn(callVideoFrame.getData(), width, height); + /* long time = System.nanoTime() - start; + if (mCSVUtils != null) { + mCSVUtils.writeCsv(null, time); + }*/ + if (mSkippedFrames > 0 || mSkip) { + --mSkippedFrames; + return callVideoFrame; + } + if (data != null && data.getImage() != null && data.getImage().getBuffer() != null) { + callVideoFrame.setData(data.getImage().getBuffer()); + } + return callVideoFrame; + } + }); + + } + + /** + * 记录渲染工具,调试用,在processVideoFrame里使用 + */ + private void initCsvUtil(Context context) { + mCSVUtils = new CSVUtils(context); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault()); + String dateStrDir = format.format(new Date(System.currentTimeMillis())); + dateStrDir = dateStrDir.replaceAll("-", "").replaceAll("_", ""); + SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault()); + String dateStrFile = df.format(new Date()); + String filePath = Environment.getExternalStoragePublicDirectory("") + dateStrDir + File.separator + "excel-" + dateStrFile + ".csv"; + Log.d("CSV", "initLog: CSV file path:" + filePath); + StringBuilder headerInfo = new StringBuilder(); + headerInfo.append("version:").append(FURenderer.getInstance().getVersion()).append(CSVUtils.COMMA) + .append("机型:").append(android.os.Build.MANUFACTURER).append(android.os.Build.MODEL) + .append("处理方式:Texture").append(CSVUtils.COMMA); + mCSVUtils.initHeader(filePath, headerInfo); + } + + + private FURendererListener mFURendererListener = new FURendererListener() { + + @Override + public void onPrepare() { + mFaceUnityDataFactory.bindCurrentRenderer(); + //Log.e(TAG, "mFURendererListener: onPrepare: "); + } + + @Override + public void onTrackStatusChanged(FUAIProcessorEnum type, int status) { + Log.e(TAG, "onTrackStatusChanged: 人脸数: " + status); + if (faceStatusChanged != null) { + faceStatusChanged.onFaceChanged(status); + } + + } + + @Override + public void onFpsChanged(double fps, double callTime) { + final String FPS = String.format(Locale.getDefault(), "%.2f", fps); + // Log.d(TAG, "onFpsChanged FPS: " + FPS + ", callTime: " + String.format("%.2f", callTime)); + } + + @Override + public void onRelease() { +// RongCallClient.getInstance().unregisterVideoFrameObserver(); + } + }; + + + @Override + public void onSensorChanged(SensorEvent sensorEvent) { + + } + + @Override + public void onAccuracyChanged(Sensor sensor, int i) { + + } + + + /** + * 离开渲染界面时注销融云监听器,不然会绿屏 + */ + public void onClose() { + RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(null); + } + + /** + * 释放资源 + */ + public void release() { + mFURenderer.release(); + try { + for (FUAITypeEnum value : FUAITypeEnum.values()) { + FUAIKit.getInstance().releaseAIProcessor(value); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public interface FaceStatusChanged { + void onFaceChanged(int num); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/ContainerRecyclerAdapter.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/ContainerRecyclerAdapter.java new file mode 100644 index 000000000..571e29300 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/ContainerRecyclerAdapter.java @@ -0,0 +1,259 @@ +package com.yunbao.faceunity.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.yunbao.common.utils.DpUtil; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.adapters.vh.AnimViewHolder; +import com.yunbao.faceunity.adapters.vh.AnimojiViewHolder; +import com.yunbao.faceunity.adapters.vh.BaseViewHolder; +import com.yunbao.faceunity.adapters.vh.BeautyBodyViewHolder; +import com.yunbao.faceunity.adapters.vh.BeautyShapeViewHolder; +import com.yunbao.faceunity.adapters.vh.BeautySkinViewHolder; +import com.yunbao.faceunity.adapters.vh.BigHeadViewHolder; +import com.yunbao.faceunity.adapters.vh.FilterViewHolder; +import com.yunbao.faceunity.adapters.vh.FineStickerViewHolder; +import com.yunbao.faceunity.adapters.vh.MakeupCustomItemViewHolder; +import com.yunbao.faceunity.adapters.vh.MakeupViewHolder; +import com.yunbao.faceunity.adapters.vh.StickerViewHolder; +import com.yunbao.faceunity.adapters.vh.StyleViewHolder; +import com.yunbao.faceunity.data.AnimojiDataFactory; +import com.yunbao.faceunity.data.BodyBeautyDataFactory; +import com.yunbao.faceunity.data.FaceBeautyDataFactory; +import com.yunbao.faceunity.data.FaceParam; +import com.yunbao.faceunity.data.FineStickerDataFactory; +import com.yunbao.faceunity.data.MakeupDataFactory; +import com.yunbao.faceunity.data.PropDataFactory; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.PropBean; +import com.yunbao.faceunity.seekbar.DiscreteSeekBar; +import com.yunbao.faceunity.utils.FaceSPUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 美颜配置适配器 + */ +public class ContainerRecyclerAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List list; + public int selectPosition = -1; + private FaceBeautyDataFactory faceBeautyDataFactory;//美颜工厂 + private MakeupDataFactory makeupDataFactory;//美妆工厂 + private BodyBeautyDataFactory bodyBeautyDataFactory;//美体工厂 + private PropDataFactory propDataFactory;//道具业务工厂:道具贴图、AR面具、搞笑大头、表情识别、哈哈镜、手势识别 + private AnimojiDataFactory animojiDataFactory;//Animoji工厂 + private FineStickerDataFactory fineStickerDataFactory;//精品贴图 + private DiscreteSeekBar seekBar; + private float seekY = 0; + + public ContainerRecyclerAdapter(Context mContext) { + this.mContext = mContext; + initDataFactory(); + } + + public void setSeekBar(DiscreteSeekBar seekBar) { + this.seekBar = seekBar; + } + + public DiscreteSeekBar getSeekBar() { + return seekBar; + } + + public void showSeekBar() { + if (seekBar.getVisibility() == View.VISIBLE) { + return; + } + seekBar.setVisibility(View.VISIBLE); + if (seekY == 0) { + seekY = seekBar.getY() - DpUtil.dp2px(20); + } + seekBar.setY(seekY); + } + + public void hideSeekBar() { + if (seekBar.getVisibility() == View.GONE) { + return; + } + seekBar.setOnProgressChangeListener(null); + seekBar.setVisibility(View.GONE); + } + + + private void initDataFactory() { + faceBeautyDataFactory = new FaceBeautyDataFactory(new FaceBeautyDataFactory.FaceBeautyListener() { + @Override + public void onFilterSelected(int res) { + + } + + @Override + public void onFaceBeautyEnable(boolean enable) { + + } + }); + propDataFactory = new PropDataFactory(new PropDataFactory.PropListener() { + @Override + public void onItemSelected(PropBean bean) { + + } + }, 0, 0); + animojiDataFactory = new AnimojiDataFactory(0, 0); + makeupDataFactory = new MakeupDataFactory(0); + bodyBeautyDataFactory = new BodyBeautyDataFactory(); + bodyBeautyDataFactory.bindCurrentRenderer(); + } + + public void setList(ArrayList list) { + this.list = list; + this.selectPosition = -1; + hideSeekBar(); + } + + public int getSelectPosition() { + return selectPosition; + } + + public void setSelectPosition(int selectPosition) { + this.selectPosition = selectPosition; + notifyDataSetChanged(); + } + + public FaceBeautyDataFactory getFaceBeautyDataFactory() { + return faceBeautyDataFactory; + } + + public MakeupDataFactory getMakeupDataFactory() { + return makeupDataFactory; + } + + public BodyBeautyDataFactory getBodyBeautyDataFactory() { + return bodyBeautyDataFactory; + } + + public PropDataFactory getPropDataFactory() { + return propDataFactory; + } + + public AnimojiDataFactory getAnimojiDataFactory() { + return animojiDataFactory; + } + + BaseViewHolder vh = null; + + @NonNull + @Override + public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + LayoutInflater from = LayoutInflater.from(mContext); + switch (viewType) { + case FaceParam.FACE_BEAUTY_SKIN: + vh = new BeautySkinViewHolder(from.inflate(R.layout.list_item_face_config, parent, false)); + break; + case FaceParam.FACE_BEAUTY_SHAPE: + vh = new BeautyShapeViewHolder(from.inflate(R.layout.list_item_face_config, parent, false)); + break; + case FaceParam.FACE_BEAUTY_BODY: + vh = new BeautyBodyViewHolder(from.inflate(R.layout.list_item_face_config, parent, false)); + break; + case FaceParam.FACE_BEAUTY_FILTER: + vh = new FilterViewHolder(from.inflate(R.layout.list_item_face_config_filter, parent, false)); + break; + case FaceParam.FACE_MAKEUP: + vh = new MakeupViewHolder(from.inflate(R.layout.list_item_face_config_filter, parent, false)); + break; + case FaceParam.FACE_BEAUTY_STYLE: + vh = new StyleViewHolder(from.inflate(R.layout.list_item_face_config_style, parent, false)); + break; + case FaceParam.FACE_ANIMOJI: + vh = new AnimojiViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false)); + break; + case FaceParam.FACE_ANIM: + vh = new AnimViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false)); + break; + case FaceParam.FACE_STICKER: + vh = new StickerViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false)); + break; + case FaceParam.FACE_BIG_HEAD: + vh = new BigHeadViewHolder(from.inflate(R.layout.list_item_face_config_big_head, parent, false)); + break; + case FaceParam.FACE_FINE_STICKER: + case FaceParam.FACE_FINE_STICKER_MIDDLE: + case FaceParam.FACE_FINE_STICKER_HIGH: + case FaceParam.FACE_FINE_STICKER_GAME: + vh = new FineStickerViewHolder(from.inflate(R.layout.list_item_face_config_fine_sticker, parent, false)); + break; + case FaceParam.FACE_MAKEUP_TYPE_FOUNDATION: + case FaceParam.FACE_MAKEUP_TYPE_LIP_STICK: + case FaceParam.FACE_MAKEUP_TYPE_BLUSHER: + case FaceParam.FACE_MAKEUP_TYPE_EYE_BROW: + case FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW: + case FaceParam.FACE_MAKEUP_TYPE_EYE_LINER: + case FaceParam.FACE_MAKEUP_TYPE_EYE_LASH: + case FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT: + case FaceParam.FACE_MAKEUP_TYPE_SHADOW: + case FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL: + vh = new MakeupCustomItemViewHolder(from.inflate(R.layout.list_item_face_config_filter, parent, false)); + break; + default: + vh = new BeautySkinViewHolder(LayoutInflater.from(mContext).inflate(R.layout.list_item_face_config, parent, false)); + } + vh.adapter = this; + return vh; + } + + @Override + public int getItemViewType(int position) { + return list.get(position).getBeanType(); + } + + @Override + public int getItemCount() { + return list.size(); + } + + @Override + public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) { + holder.setData(list.get(position)); + + } + + /** + * 保存配置 + */ + public void save(String key, String data) { + FaceSPUtils.getInstance().saveString(key, data); + } + + /** + * 读取配置 + */ + public String getString(String key) { + return FaceSPUtils.getInstance().getString(key); + } + + /** + * 删除配置 + */ + public void del(String key) { + FaceSPUtils.getInstance().del(key); + } + + /** + * 恢复默认设置 + */ + public void reset() { + if (vh != null) { + vh.reset(list); + } + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/MenuGroupRecyclerAdapter.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/MenuGroupRecyclerAdapter.java new file mode 100644 index 000000000..e1d73edc4 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/MenuGroupRecyclerAdapter.java @@ -0,0 +1,77 @@ +package com.yunbao.faceunity.adapters; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.yunbao.common.adapter.OnItemClickListener; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.MenuGroupBean; + +import java.util.List; + +/** + * 主菜单适配器 + */ +public class MenuGroupRecyclerAdapter extends RecyclerView.Adapter { + private Context context; + private List list; + private OnItemClickListener onItemClickListener; + + public MenuGroupRecyclerAdapter(Context context) { + this.context = context; + } + + public void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.onItemClickListener = onItemClickListener; + } + + public void setList(List list) { + this.list = list; + } + + @NonNull + @Override + public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new Vh(LayoutInflater.from(context).inflate(R.layout.list_item_menu_group, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull Vh holder, int position) { + holder.setData(list.get(position)); + } + + @Override + public int getItemCount() { + return list.size(); + } + + + protected class Vh extends RecyclerView.ViewHolder { + ImageView icon; + TextView title; + + public Vh(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.item_icon); + title = itemView.findViewById(R.id.item_text); + itemView.setOnClickListener(v -> { + if (onItemClickListener != null) { + onItemClickListener.onItemClick(getAdapterPosition()); + } + }); + } + + public void setData(MenuGroupBean menuGroupBean) { + icon.setImageResource(menuGroupBean.getIconId()); + title.setText(menuGroupBean.getTitleId()); + } + + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/AnimViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/AnimViewHolder.java new file mode 100644 index 000000000..748542fd0 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/AnimViewHolder.java @@ -0,0 +1,52 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.AnimationFilterBean; +import com.yunbao.faceunity.entity.BaseBean; + +import java.util.List; + +/** + * 动画滤镜 *暂无权限 + */ +public class AnimViewHolder extends BaseViewHolder { + ImageView icon; + + public AnimViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.iv_control); + icon.setBackgroundResource(R.drawable.bg_control_square_selector); + itemView.setOnClickListener(v -> { + adapter.getAnimojiDataFactory().onFilterSelected((AnimationFilterBean) itemView.getTag()); + setSelectPosition(getAdapterPosition()); + saveData(); + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + icon.setSelected(getAdapterPosition() == getSelectPosition()); + } + + @Override + public boolean loadData() { + return false; + } + + @Override + public void saveData() { + + } + + @Override + public void reset(List list) { + adapter.setSelectPosition(0); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/AnimojiViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/AnimojiViewHolder.java new file mode 100644 index 000000000..090198748 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/AnimojiViewHolder.java @@ -0,0 +1,71 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; + +import com.yunbao.common.utils.ToastUtil; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.AnimojiBean; +import com.yunbao.faceunity.entity.BaseBean; + +import java.util.List; + +/** + * Animoji + */ +public class AnimojiViewHolder extends BaseViewHolder { + ImageView icon; + + public AnimojiViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.iv_control); + itemView.setOnClickListener(v -> { + adapter.getAnimojiDataFactory().onAnimojiSelected((AnimojiBean) itemView.getTag()); + setSelectPosition(getLayoutPosition()); + saveData(); + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + int adapterPosition = getAdapterPosition(); + int selectPosition = getSelectPosition(); + if (loadData()) { + return; + } + icon.setSelected(adapterPosition == selectPosition); + + } + + @Override + public boolean loadData() { + String data = adapter.getString(getName(this)); + if (data == null) { + return false; + } + if (!data.equals(String.valueOf(getLayoutPosition()))) { + return false; + } + icon.setSelected(true); + adapter.getAnimojiDataFactory().onAnimojiSelected((AnimojiBean) itemView.getTag()); + return false; + } + + @Override + public void saveData() { + adapter.save(getName(this), String.valueOf(getLayoutPosition())); + } + + @Override + public void reset(List list) { + adapter.del(getName(this)); + adapter.getAnimojiDataFactory().onAnimojiSelected((AnimojiBean) list.get(0)); + adapter.setSelectPosition(0); + } + + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BaseViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BaseViewHolder.java new file mode 100644 index 000000000..56e766054 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BaseViewHolder.java @@ -0,0 +1,53 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.yunbao.faceunity.adapters.ContainerRecyclerAdapter; +import com.yunbao.faceunity.entity.BaseBean; + +import java.util.ArrayList; +import java.util.List; + +public abstract class BaseViewHolder extends RecyclerView.ViewHolder { + public ContainerRecyclerAdapter adapter; + + public int getSelectPosition() { + return adapter.selectPosition; + } + + public void setSelectPosition(int selectPosition) { + adapter.selectPosition = selectPosition; + adapter.notifyDataSetChanged(); + } + + public BaseViewHolder(@NonNull View itemView) { + super(itemView); + } + + public String getName(Object obj){ + return obj.getClass().getSimpleName()+"_"; + } + + public abstract void setData(BaseBean data); + + /** + * 读取配置 + * @return 是否有保存的配置 + */ + public abstract boolean loadData(); + + /** + * 保存配置 + */ + public abstract void saveData(); + + /** + * 恢复默认配置 + */ + public abstract void reset(List list); + + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautyBodyViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautyBodyViewHolder.java new file mode 100644 index 000000000..bf4c31ab3 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautyBodyViewHolder.java @@ -0,0 +1,93 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.BodyBeautyBean; +import com.yunbao.faceunity.entity.ModelAttributeData; +import com.yunbao.faceunity.seekbar.DiscreteSeekBar; +import com.yunbao.faceunity.utils.SeekBarUtils; + +import java.util.List; + +/** + * 美体 + */ +public class BeautyBodyViewHolder extends BaseViewHolder { + private ImageView icon; + private TextView title; + private TextView value; + private DiscreteSeekBar seekBar; + + public BeautyBodyViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.item_icon); + title = itemView.findViewById(R.id.item_title); + value = itemView.findViewById(R.id.item_value); + seekBar = itemView.findViewById(R.id.item_seekBar); + seekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener() { + @Override + public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) { + super.onProgressChanged(seekBar, value, fromUser); + BodyBeautyBean bean = (BodyBeautyBean) itemView.getTag(); + double toValue = SeekBarUtils.Companion.seekToValue(bean.getModelAttributeData().getMaxRange(), value, seekBar.getMin()); + BeautyBodyViewHolder.this.value.setText(String.format("%.1f", toValue)); + adapter.getBodyBeautyDataFactory().updateParamIntensity(bean.getKey(), toValue); + saveData(); + } + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + title.setText(data.getDesRes()); + if (loadData()) { + return; + } + ModelAttributeData attributeData = data.getModelAttributeData(); + value.setText(attributeData.getDefault() + ""); + SeekBarUtils.Companion.seekToSeekBar(seekBar, + attributeData.getDefault(), + attributeData.getStand(), + attributeData.getMaxRange()); + } + + @Override + public boolean loadData() { + BodyBeautyBean bean = (BodyBeautyBean) itemView.getTag(); + String val = adapter.getString(getName(this) + bean.getKey()); + if (val == null) { + return false; + } + ModelAttributeData attributeData = bean.getModelAttributeData(); + value.setText(val); + SeekBarUtils.Companion.seekToSeekBar(seekBar, + Double.parseDouble(val), + attributeData.getStand(), + attributeData.getMaxRange()); + return true; + } + + @Override + public void saveData() { + BodyBeautyBean bean = (BodyBeautyBean) itemView.getTag(); + String key = getName(this) + bean.getKey(); + adapter.save(key, (String) value.getText()); + } + + @Override + public void reset(List list) { + String name = getName(this); + for (BaseBean bean : list) { + adapter.del(name + bean.getKey()); + } + adapter.notifyDataSetChanged(); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautyShapeViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautyShapeViewHolder.java new file mode 100644 index 000000000..f415b93bf --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautyShapeViewHolder.java @@ -0,0 +1,94 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.FaceBeautyBean; +import com.yunbao.faceunity.entity.ModelAttributeData; +import com.yunbao.faceunity.seekbar.DiscreteSeekBar; +import com.yunbao.faceunity.utils.SeekBarUtils; + +import java.util.List; + +/** + * 美型 + */ +public class BeautyShapeViewHolder extends BaseViewHolder { + private ImageView icon; + private TextView title; + private TextView value; + private DiscreteSeekBar seekBar; + + + public BeautyShapeViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.item_icon); + title = itemView.findViewById(R.id.item_title); + value = itemView.findViewById(R.id.item_value); + seekBar = itemView.findViewById(R.id.item_seekBar); + seekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener() { + @Override + public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) { + super.onProgressChanged(seekBar, value, fromUser); + FaceBeautyBean bean = (FaceBeautyBean) itemView.getTag(); + double toValue = SeekBarUtils.Companion.seekToValue(bean.getModelAttributeData().getMaxRange(), value, seekBar.getMin()); + BeautyShapeViewHolder.this.value.setText(String.format("%.1f", toValue)); + adapter.getFaceBeautyDataFactory().updateParamIntensity(bean.getKey(), toValue); + saveData(); + } + }); + + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + title.setText(data.getDesRes()); + if(loadData()){ + return; + } + ModelAttributeData attributeData = data.getModelAttributeData(); + value.setText(attributeData.getDefault() + ""); + SeekBarUtils.Companion.seekToSeekBar(seekBar, + attributeData.getDefault(), + attributeData.getStand(), + attributeData.getMaxRange()); + } + + @Override + public boolean loadData() { + FaceBeautyBean bean = (FaceBeautyBean) itemView.getTag(); + String val = adapter.getString(getName(this) + bean.getKey()); + if(val==null) { + return false; + } + ModelAttributeData attributeData = bean.getModelAttributeData(); + value.setText(val); + SeekBarUtils.Companion.seekToSeekBar(seekBar, + Double.parseDouble(val), + attributeData.getStand(), + attributeData.getMaxRange()); + return true; + } + + @Override + public void saveData() { + FaceBeautyBean bean = (FaceBeautyBean) itemView.getTag(); + adapter.save(getName(this)+bean.getKey(), (String) value.getText()); + } + + @Override + public void reset(List list) { + String name = getName(this); + for (BaseBean bean : list) { + adapter.del(name+bean.getKey()); + } + adapter.notifyDataSetChanged(); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautySkinViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautySkinViewHolder.java new file mode 100644 index 000000000..c8a73e0ae --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BeautySkinViewHolder.java @@ -0,0 +1,93 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.FaceBeautyBean; +import com.yunbao.faceunity.entity.ModelAttributeData; +import com.yunbao.faceunity.seekbar.DiscreteSeekBar; +import com.yunbao.faceunity.utils.SeekBarUtils; + +import java.util.List; + +/** + * 美肤 + */ +public class BeautySkinViewHolder extends BaseViewHolder{ + private ImageView icon; + private TextView title; + private TextView value; + private DiscreteSeekBar seekBar; + + public BeautySkinViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.item_icon); + title = itemView.findViewById(R.id.item_title); + value = itemView.findViewById(R.id.item_value); + seekBar = itemView.findViewById(R.id.item_seekBar); + seekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener(){ + @Override + public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) { + super.onProgressChanged(seekBar, value, fromUser); + FaceBeautyBean bean = (FaceBeautyBean) itemView.getTag(); + double toValue = SeekBarUtils.Companion.seekToValue(bean.getModelAttributeData().getMaxRange(), value, seekBar.getMin()); + BeautySkinViewHolder.this.value.setText(String.format("%.1f",toValue)); + adapter.getFaceBeautyDataFactory().updateParamIntensity(bean.getKey(),toValue); + saveData(); + } + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + title.setText(data.getDesRes()); + if(loadData()){ + return; + } + ModelAttributeData attributeData = data.getModelAttributeData(); + value.setText(attributeData.getDefault() + ""); + SeekBarUtils.Companion.seekToSeekBar(seekBar, + attributeData.getDefault(), + attributeData.getStand(), + attributeData.getMaxRange()); + } + + @Override + public boolean loadData() { + BaseBean data = (FaceBeautyBean) itemView.getTag(); + ModelAttributeData attributeData = data.getModelAttributeData(); + String key = getName(this)+data.getKey(); + String val=adapter.getString(key); + if (val==null){ + return false; + } + value.setText(val); + SeekBarUtils.Companion.seekToSeekBar(seekBar, + Double.parseDouble(val), + attributeData.getStand(), + attributeData.getMaxRange() + ); + return true; + } + + @Override + public void saveData() { + String key = ((FaceBeautyBean)itemView.getTag()).getKey(); + String val= (String) value.getText(); + adapter.save(getName(this)+key,val); + } + + @Override + public void reset(List list) { + for (BaseBean bean : list) { + adapter.del(getName(this)+bean.getKey()); + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BigHeadViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BigHeadViewHolder.java new file mode 100644 index 000000000..a79337fbc --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/BigHeadViewHolder.java @@ -0,0 +1,76 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.FunctionEnum; +import com.yunbao.faceunity.entity.PropBean; + +import java.util.List; + +/** + * 大头 + */ +public class BigHeadViewHolder extends BaseViewHolder { + ImageView icon; + + public BigHeadViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.iv_control); + itemView.setOnClickListener(v -> { + PropBean bean = (PropBean) itemView.getTag(); + adapter.getPropDataFactory().setPropType(FunctionEnum.BIG_HEAD); + adapter.getPropDataFactory().onItemSelected(bean); + setSelectPosition(getAdapterPosition()); + saveData(); + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + if(loadData()){ + return; + } + + if (getAdapterPosition() == 0) { + icon.setBackgroundResource(R.drawable.bg_control_oval2_selector); + } + icon.setSelected(getSelectPosition() == getAdapterPosition()); + } + + @Override + public boolean loadData() { + PropBean bean = (PropBean) itemView.getTag(); + String val = adapter.getString(getName(this)); + if(val==null){ + return false; + } + if(!val.equals(bean.getKey())){ + return false; + } + icon.setSelected(true); + adapter.getPropDataFactory().setPropType(FunctionEnum.BIG_HEAD); + adapter.getPropDataFactory().onItemSelected(bean); + return true; + } + + @Override + public void saveData() { + PropBean bean = (PropBean) itemView.getTag(); + adapter.save(getName(this),bean.getKey()); + } + + @Override + public void reset(List list) { + adapter.del(getName(this)); + adapter.getPropDataFactory().setPropType(FunctionEnum.BIG_HEAD); + adapter.getPropDataFactory().onItemSelected((PropBean) list.get(0)); + adapter.setSelectPosition(0); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/FilterViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/FilterViewHolder.java new file mode 100644 index 000000000..e6c7c8853 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/FilterViewHolder.java @@ -0,0 +1,75 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.FaceBeautyFilterBean; + +import java.util.List; + +/** + * 滤镜 + */ +public class FilterViewHolder extends BaseViewHolder { + private ImageView icon; + private TextView title; + + public FilterViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.iv_control); + title = itemView.findViewById(R.id.tv_control); + itemView.setOnClickListener(view -> { + FaceBeautyFilterBean bean = (FaceBeautyFilterBean) itemView.getTag(); + adapter.getFaceBeautyDataFactory().onFilterSelected(bean.getKey(), bean.getIntensity(), bean.getDesRes()); + setSelectPosition(getAdapterPosition()); + saveData(); + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + title.setText(data.getDesRes()); + if (loadData()) { + return; + } + icon.setSelected(getSelectPosition() == getAdapterPosition()); + title.setSelected(getSelectPosition() == getAdapterPosition()); + + } + + @Override + public boolean loadData() { + FaceBeautyFilterBean bean = (FaceBeautyFilterBean) itemView.getTag(); + String val = adapter.getString(getName(this)); + if (val == null) { + return false; + } + if (!val.equals(bean.getKey())) { + return false; + } + icon.setSelected(true); + title.setSelected(true); + adapter.getFaceBeautyDataFactory().onFilterSelected(bean.getKey(), bean.getIntensity(), bean.getDesRes()); + return true; + } + + @Override + public void saveData() { + FaceBeautyFilterBean bean = (FaceBeautyFilterBean) itemView.getTag(); + adapter.save(getName(this), bean.getKey()); + } + + @Override + public void reset(List list) { + adapter.del(getName(this)); + itemView.callOnClick(); + adapter.setSelectPosition(0); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/FineStickerViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/FineStickerViewHolder.java new file mode 100644 index 000000000..52d5c613f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/FineStickerViewHolder.java @@ -0,0 +1,96 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; + +import com.yunbao.common.glide.ImgLoader; +import com.yunbao.common.utils.ToastUtil; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.data.FineStickerDataFactory; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.net.FineStickerEntity; +import com.yunbao.faceunity.utils.net.StickerDownloadHelper; + +import java.util.List; + +/** + * 精品贴纸 + */ +public class FineStickerViewHolder extends BaseViewHolder implements StickerDownloadHelper.Callback { + ImageView icon; + + public FineStickerViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.iv_control); + itemView.setOnClickListener(view -> { + FineStickerDataFactory.getInstance().downloadSticker((FineStickerEntity.DocsBean) itemView.getTag()); + setSelectPosition(getAdapterPosition()); + saveData(); + }); + FineStickerDataFactory.getInstance().addCallback(this); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + if (data.getImageUrl().isEmpty()) { + icon.setImageResource(R.mipmap.icon_control_none); + } else { + ImgLoader.display(icon.getContext(), data.getImageUrl(), icon); + } + if (loadData()) { + return; + } + icon.setSelected(getSelectPosition() == getAdapterPosition()); + } + + @Override + public boolean loadData() { + FineStickerEntity.DocsBean bean = (FineStickerEntity.DocsBean) itemView.getTag(); + String val = adapter.getString(getName(this) + bean.getKey()); + if(val==null){ + return false; + } + if(!val.equals(bean.getKey())){ + return false; + } + FineStickerDataFactory.getInstance().downloadSticker(bean); + icon.setSelected(true); + return true; + } + + @Override + public void saveData() { + FineStickerEntity.DocsBean bean = (FineStickerEntity.DocsBean) itemView.getTag(); + adapter.save(getName(this), bean.getKey()); + } + + @Override + public void reset(List list) { + adapter.del(getName(this)); + itemView.callOnClick(); + adapter.setSelectPosition(0); + } + + @Override + public void onGetTags(String[] tags) { + + } + + @Override + public void onGetList(String tag, FineStickerEntity fineSticker) { + + } + + @Override + public void onDownload(FineStickerEntity.DocsBean entity) { + FineStickerDataFactory.getInstance().onItemSelected(entity); + } + + @Override + public void onDownloadError(FineStickerEntity.DocsBean entity, String msg) { + ToastUtil.show("下载失败 = " + msg); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/MakeupCustomItemViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/MakeupCustomItemViewHolder.java new file mode 100644 index 000000000..172efd280 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/MakeupCustomItemViewHolder.java @@ -0,0 +1,162 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.data.FaceParam; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.MakeupCustomBean; +import com.yunbao.faceunity.repo.MakeupSource; +import com.yunbao.faceunity.seekbar.DiscreteSeekBar; + +import java.util.List; + +/** + * 美妆 - 自定义 + */ +public class MakeupCustomItemViewHolder extends BaseViewHolder { + private ImageView icon; + private TextView title; + + + public MakeupCustomItemViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.iv_control); + title = itemView.findViewById(R.id.tv_control); + title.setVisibility(View.INVISIBLE); + itemView.setOnClickListener(new View.OnClickListener() { + private String key = null; + + @Override + public void onClick(View v) { + adapter.showSeekBar(); + MakeupCustomBean bean = (MakeupCustomBean) itemView.getTag(); + key = getMakeupKey(bean.getBeanType()); + + if (key == null) { + return; + } + adapter.getMakeupDataFactory().enterCustomMakeup(); + adapter.getMakeupDataFactory().onCustomBeanSelected(key, getAdapterPosition()); + adapter.getMakeupDataFactory().bindCurrentRenderer(); + setSelectPosition(getAdapterPosition()); + double intensity = adapter.getMakeupDataFactory().getCurrentCustomIntensity(key, adapter.getMakeupDataFactory().getCurrentCustomItemIndex(key)); + adapter.getSeekBar().setProgress((int) (intensity * 100)); + adapter.getSeekBar().setOnProgressChangeListener(new DiscreteSeekBar.OnSimpleProgressChangeListener() { + @Override + public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) { + super.onProgressChanged(seekBar, value, fromUser); + float valueF = (float) (1.0 * (value - seekBar.getMin()) / 100); + int current = adapter.getMakeupDataFactory().getCurrentCustomItemIndex(key); + adapter.getMakeupDataFactory().updateCustomItemIntensity(key, current, valueF); + saveData(); + } + }); + saveData(); + } + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageDrawable(data.getImageDrawable()); + if (loadData()) { + return; + } + if (getSelectPosition() == getAdapterPosition()) { + icon.setSelected(true); + return; + } + icon.setSelected(false); + } + + @Override + public boolean loadData() { + MakeupCustomBean bean = (MakeupCustomBean) itemView.getTag(); + String model = adapter.getString(getName(this)); + String val = adapter.getString(getName(this) + bean.getKey() + "_val"); + if (model == null || val == null) { + return false; + } + if(!model.equals(bean.getKey())){ + return false; + } + icon.setSelected(true); + String key = getMakeupKey(bean.getBeanType()); + if (key == null) { + return false; + } + adapter.getMakeupDataFactory().enterCustomMakeup(); + adapter.getMakeupDataFactory().onCustomBeanSelected(key, getAdapterPosition()); + adapter.getMakeupDataFactory().bindCurrentRenderer(); + adapter.getSeekBar().setProgress(Integer.parseInt(val)); + + float valueF = (float) (1.0 * (Integer.parseInt(val) - adapter.getSeekBar().getMin()) / 100); + int current = adapter.getMakeupDataFactory().getCurrentCustomItemIndex(key); + adapter.getMakeupDataFactory().updateCustomItemIntensity(key, current, valueF); + return true; + } + + @Override + public void saveData() { + MakeupCustomBean bean = (MakeupCustomBean) itemView.getTag(); + String key=getMakeupKey(bean.getBeanType()); + if(key==null){ + return; + } + adapter.save(getName(this), key); + adapter.save(getName(this) + bean.getKey() + "_val", adapter.getSeekBar().getProgress() + ""); + } + + @Override + public void reset(List list) { + adapter.del(getName(this)); + for (BaseBean bean : list) { + adapter.del(getName(this) + bean.getKey() + "_val"); + } + itemView.callOnClick(); + adapter.setSelectPosition(0); + } + + public String getMakeupKey(int beanType) { + String key = null; + switch (beanType) { + case FaceParam.FACE_MAKEUP_TYPE_FOUNDATION: + key = MakeupSource.FACE_MAKEUP_TYPE_FOUNDATION; + break; + case FaceParam.FACE_MAKEUP_TYPE_LIP_STICK: + key = MakeupSource.FACE_MAKEUP_TYPE_LIP_STICK; + break; + case FaceParam.FACE_MAKEUP_TYPE_BLUSHER: + key = MakeupSource.FACE_MAKEUP_TYPE_BLUSHER; + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_BROW: + key = MakeupSource.FACE_MAKEUP_TYPE_EYE_BROW; + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW: + key = MakeupSource.FACE_MAKEUP_TYPE_EYE_SHADOW; + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_LINER: + key = MakeupSource.FACE_MAKEUP_TYPE_EYE_LINER; + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_LASH: + key = MakeupSource.FACE_MAKEUP_TYPE_EYE_LASH; + break; + case FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT: + key = MakeupSource.FACE_MAKEUP_TYPE_HIGH_LIGHT; + break; + case FaceParam.FACE_MAKEUP_TYPE_SHADOW: + key = MakeupSource.FACE_MAKEUP_TYPE_SHADOW; + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL: + key = MakeupSource.FACE_MAKEUP_TYPE_EYE_PUPIL; + break; + } + return key; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/MakeupViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/MakeupViewHolder.java new file mode 100644 index 000000000..604b9239e --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/MakeupViewHolder.java @@ -0,0 +1,82 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.MakeupCombinationBean; +import com.yunbao.faceunity.utils.FaceSPUtils; + +import java.util.List; + +/** + * 美妆 + */ +public class MakeupViewHolder extends BaseViewHolder { + private ImageView icon; + private TextView title; + + public MakeupViewHolder(@NonNull View itemView) { + super(itemView); + icon = itemView.findViewById(R.id.iv_control); + title = itemView.findViewById(R.id.tv_control); + itemView.setOnClickListener(v -> { + adapter.getMakeupDataFactory().onMakeupCombinationSelected((MakeupCombinationBean) itemView.getTag()); + setSelectPosition(getAdapterPosition()); + saveData(); + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + title.setText(data.getDesRes()); + if(loadData()){ + return; + } + if (getSelectPosition() == getAdapterPosition()) { + icon.setSelected(true); + title.setSelected(true); + return; + } + icon.setSelected(false); + title.setSelected(false); + } + + @Override + public boolean loadData() { + MakeupCombinationBean bean = (MakeupCombinationBean) itemView.getTag(); + String val = adapter.getString(getName(this)); + if(val==null){ + return false; + } + if(!val.equals(bean.getKey())){ + return false; + } + icon.setSelected(true); + title.setSelected(true); + adapter.getMakeupDataFactory().onMakeupCombinationSelected(bean); + return true; + + } + + @Override + public void saveData() { + MakeupCombinationBean bean = (MakeupCombinationBean) itemView.getTag(); + adapter.save(getName(this),bean.getKey()); + } + + @Override + public void reset(Listlist) { + adapter.del(getName(this)); + FaceSPUtils.getInstance().delStart("MakeupCustomItemViewHolder"); + adapter.getMakeupDataFactory().onMakeupCombinationSelected((MakeupCombinationBean) list.get(0)); + adapter.getMakeupDataFactory().clearAll(); + adapter.setSelectPosition(0); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/StickerViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/StickerViewHolder.java new file mode 100644 index 000000000..edc5ba70f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/StickerViewHolder.java @@ -0,0 +1,75 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.FunctionEnum; +import com.yunbao.faceunity.entity.PropBean; + +import java.util.List; + +/** + * 普通贴纸 + */ +public class StickerViewHolder extends BaseViewHolder{ + ImageView icon; + public StickerViewHolder(@NonNull View itemView) { + super(itemView); + icon =itemView.findViewById(R.id.iv_control); + itemView.setOnClickListener(v -> { + PropBean bean= (PropBean) itemView.getTag(); + adapter.getPropDataFactory().setPropType(FunctionEnum.STICKER); + adapter.getPropDataFactory().onItemSelected(bean); + setSelectPosition(getAdapterPosition()); + saveData(); + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + if(loadData()){ + return; + } + if(getAdapterPosition()==0){ + icon.setBackgroundResource(R.drawable.bg_control_oval2_selector); + } + icon.setSelected(getSelectPosition() == getAdapterPosition()); + } + + @Override + public boolean loadData() { + PropBean bean= (PropBean) itemView.getTag(); + String val = adapter.getString(getName(this)); + if(val==null){ + return false; + } + if(!val.equals(bean.getKey())){ + return false; + } + icon.setSelected(true); + adapter.getPropDataFactory().setPropType(FunctionEnum.STICKER); + adapter.getPropDataFactory().onItemSelected(bean); + return true; + + } + + @Override + public void saveData() { + PropBean bean= (PropBean) itemView.getTag(); + adapter.save(getName(this),bean.getKey()); + } + + @Override + public void reset(List list) { + adapter.del(getName(this)); + adapter.getPropDataFactory().setPropType(FunctionEnum.STICKER); + adapter.getPropDataFactory().onItemSelected((PropBean) list.get(0)); + adapter.setSelectPosition(0); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/StyleViewHolder.java b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/StyleViewHolder.java new file mode 100644 index 000000000..4bb4b8666 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/adapters/vh/StyleViewHolder.java @@ -0,0 +1,73 @@ +package com.yunbao.faceunity.adapters.vh; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BaseBean; + +import java.util.List; + +/** + * 风格推荐 + */ +public class StyleViewHolder extends BaseViewHolder{ + private ImageView icon; + private TextView title; + public StyleViewHolder(@NonNull View itemView) { + super(itemView); + icon=itemView.findViewById(R.id.iv_control); + title=itemView.findViewById(R.id.tv_control); + itemView.setOnClickListener(v -> { + BaseBean bean= (BaseBean) itemView.getTag(); + adapter.getFaceBeautyDataFactory().onStyleSelected(bean.getKey()); + setSelectPosition(getAdapterPosition()); + saveData(); + }); + } + + @Override + public void setData(BaseBean data) { + itemView.setTag(data); + icon.setImageResource(data.getImageRes()); + title.setText(data.getDesRes()); + if(loadData()){ + return; + } + icon.setSelected(getSelectPosition()==getAdapterPosition()); + title.setSelected(getSelectPosition()==getAdapterPosition()); + } + + @Override + public boolean loadData() { + BaseBean bean= (BaseBean) itemView.getTag(); + String val = adapter.getString(getName(this)); + if(val==null){ + return false; + } + if(!val.equals(bean.getKey())){ + return false; + } + icon.setSelected(true); + title.setSelected(true); + adapter.getFaceBeautyDataFactory().onStyleSelected(bean.getKey()); + return true; + + } + + @Override + public void saveData() { + BaseBean bean= (BaseBean) itemView.getTag(); + adapter.save(getName(this),bean.getKey()); + } + + @Override + public void reset(List list) { + adapter.del(getName(this)); + itemView.callOnClick(); + adapter.setSelectPosition(0); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/checkbox/CheckBoxCompat.java b/FaceUnity/src/main/java/com/yunbao/faceunity/checkbox/CheckBoxCompat.java new file mode 100644 index 000000000..a11d974f0 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/checkbox/CheckBoxCompat.java @@ -0,0 +1,35 @@ +package com.yunbao.faceunity.checkbox; + +import android.content.Context; +import android.graphics.drawable.StateListDrawable; +import android.util.AttributeSet; + +import androidx.appcompat.widget.AppCompatCheckBox; + + +/** + * 解决 RadioButton 在 Android4.4 调用setButtonDrawable(null) 和 XML 设置 android:button="@null"无效的问题 + * + * @author Richie on 2020.05.18 + */ +public class CheckBoxCompat extends AppCompatCheckBox { + + public CheckBoxCompat(Context context) { + super(context); + init(); + } + + public CheckBoxCompat(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public CheckBoxCompat(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + setButtonDrawable(new StateListDrawable()); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/checkbox/CheckGroup.java b/FaceUnity/src/main/java/com/yunbao/faceunity/checkbox/CheckGroup.java new file mode 100644 index 000000000..fcb2fcc1a --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/checkbox/CheckGroup.java @@ -0,0 +1,278 @@ +package com.yunbao.faceunity.checkbox; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.LinearLayout; + +import androidx.annotation.IdRes; + +/** + * Created by tujh on 2018/4/17. + */ +public class CheckGroup extends LinearLayout { + private static final String LOG_TAG = CheckGroup.class.getSimpleName(); + + // holds the checked id; the selection is empty by default + private int mCheckedId = View.NO_ID; + // tracks children radio buttons checked state + private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener; + // when true, mOnCheckedChangeListener discards events + private boolean mProtectFromCheckedChange = false; + private OnCheckedChangeListener mOnCheckedChangeListener; + private PassThroughHierarchyChangeListener mPassThroughListener; + private OnDispatchActionUpListener mOnDispatchActionUpListener; + + /** + * {@inheritDoc} + */ + public CheckGroup(Context context) { + super(context); + setOrientation(VERTICAL); + init(); + } + + /** + * {@inheritDoc} + */ + public CheckGroup(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + private void init() { + mChildOnCheckedChangeListener = new CheckedStateTracker(); + mPassThroughListener = new PassThroughHierarchyChangeListener(); + super.setOnHierarchyChangeListener(mPassThroughListener); + } + + public void setOnDispatchActionUpListener(OnDispatchActionUpListener onDispatchActionUpListener) { + mOnDispatchActionUpListener = onDispatchActionUpListener; + } + + /** + * {@inheritDoc} + */ + @Override + public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { + // the user listener is delegated to our pass-through listener + mPassThroughListener.mOnHierarchyChangeListener = listener; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_UP) { + if (mOnDispatchActionUpListener != null) { + mOnDispatchActionUpListener.onDispatchActionUp((int) ev.getX()); + } + } + return super.dispatchTouchEvent(ev); + } + + /** + * {@inheritDoc} + */ + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + // checks the appropriate radio button as requested in the XML file + if (mCheckedId != View.NO_ID) { + mProtectFromCheckedChange = true; + setCheckedStateForView(mCheckedId, true); + mProtectFromCheckedChange = false; + setCheckedId(mCheckedId); + } + } + + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (child instanceof CheckBox) { + final CheckBox button = (CheckBox) child; + if (button.isChecked()) { + mProtectFromCheckedChange = true; + if (mCheckedId != View.NO_ID) { + setCheckedStateForView(mCheckedId, false); + } + mProtectFromCheckedChange = false; + setCheckedId(button.getId()); + } + } + + super.addView(child, index, params); + } + + /** + *

Sets the selection to the radio button whose identifier is passed in + * parameter. Using View.NO_ID as the selection identifier clears the selection; + * such an operation is equivalent to invoking {@link #clearCheck()}.

+ * + * @param id the unique id of the radio button to select in this group + * @see #getCheckedCheckBoxId() + * @see #clearCheck() + */ + public void check(@IdRes int id) { + // don't even bother + if (id != View.NO_ID && (id == mCheckedId)) { + return; + } + + if (mCheckedId != View.NO_ID) { + setCheckedStateForView(mCheckedId, false); + } + + if (id != View.NO_ID) { + setCheckedStateForView(id, true); + } + + setCheckedId(id); + } + + private void setCheckedId(@IdRes int id) { + mCheckedId = id; + if (mOnCheckedChangeListener != null) { + mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId); + } + } + + private void setCheckedStateForView(int viewId, boolean checked) { + View checkedView = findViewById(viewId); + if (checkedView != null && checkedView instanceof CheckBox) { + ((CheckBox) checkedView).setChecked(checked); + } + } + + /** + *

Returns the identifier of the selected radio button in this group. + * Upon empty selection, the returned value is View.NO_ID.

+ * + * @return the unique id of the selected radio button in this group + * @attr ref android.R.styleable#CheckGroup_checkedButton + * @see #check(int) + * @see #clearCheck() + */ + @IdRes + public int getCheckedCheckBoxId() { + return mCheckedId; + } + + /** + *

Clears the selection. When the selection is cleared, no radio button + * in this group is selected and {@link #getCheckedCheckBoxId()} returns + * null.

+ * + * @see #check(int) + * @see #getCheckedCheckBoxId() + */ + public void clearCheck() { + check(View.NO_ID); + } + + /** + *

Register a callback to be invoked when the checked radio button + * changes in this group.

+ * + * @param listener the callback to call on checked state change + */ + public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { + mOnCheckedChangeListener = listener; + } + + @Override + public CharSequence getAccessibilityClassName() { + return CheckGroup.class.getName(); + } + + + /** + *

Interface definition for a callback to be invoked when the checked + * radio button changed in this group.

+ */ + public interface OnCheckedChangeListener { + /** + *

Called when the checked radio button has changed. When the + * selection is cleared, checkedId is View.NO_ID.

+ * + * @param group the group in which the checked radio button has changed + * @param checkedId the unique identifier of the newly checked radio button + */ + public void onCheckedChanged(CheckGroup group, @IdRes int checkedId); + } + + private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + // prevents from infinite recursion + if (mProtectFromCheckedChange) { + return; + } + + int id = buttonView.getId(); + mProtectFromCheckedChange = true; + if (mCheckedId != View.NO_ID && mCheckedId != id) { + setCheckedStateForView(mCheckedId, false); + } + mProtectFromCheckedChange = false; + + setCheckedId(isChecked ? id : View.NO_ID); + } + } + + /** + *

A pass-through listener acts upon the events and dispatches them + * to another listener. This allows the table layout to set its own internal + * hierarchy change listener without preventing the user to setup his.

+ */ + private class PassThroughHierarchyChangeListener implements + OnHierarchyChangeListener { + private OnHierarchyChangeListener mOnHierarchyChangeListener; + + /** + * {@inheritDoc} + */ + @Override + public void onChildViewAdded(View parent, View child) { + if (parent == CheckGroup.this && child instanceof CheckBox) { + int id = child.getId(); + // generates an id if it's missing + if (id == View.NO_ID) { + id = View.generateViewId(); + child.setId(id); + } + ((CheckBox) child).setOnCheckedChangeListener( + mChildOnCheckedChangeListener); + } + + if (mOnHierarchyChangeListener != null) { + mOnHierarchyChangeListener.onChildViewAdded(parent, child); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void onChildViewRemoved(View parent, View child) { + if (parent == CheckGroup.this && child instanceof CheckBox) { + ((CheckBox) child).setOnCheckedChangeListener(null); + } + + if (mOnHierarchyChangeListener != null) { + mOnHierarchyChangeListener.onChildViewRemoved(parent, child); + } + } + } + + public interface OnDispatchActionUpListener { + /** + * 分发 action up 事件时回调 + * + * @param x + */ + void onDispatchActionUp(int x); + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/AnimojiDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/AnimojiDataFactory.java new file mode 100644 index 000000000..ac181db54 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/AnimojiDataFactory.java @@ -0,0 +1,168 @@ +package com.yunbao.faceunity.data; + +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.faceunity.FUAIKit; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.model.animationFilter.AnimationFilter; +import com.faceunity.core.model.antialiasing.Antialiasing; +import com.faceunity.core.model.prop.Prop; +import com.faceunity.core.model.prop.PropContainer; +import com.faceunity.core.model.prop.animoji.Animoji; +import com.yunbao.faceunity.entity.AnimationFilterBean; +import com.yunbao.faceunity.entity.AnimojiBean; +import com.yunbao.faceunity.infe.AbstractAnimojiDataFactory; +import com.yunbao.faceunity.repo.AnimojiSource; +import com.yunbao.faceunity.utils.FaceUnityConfig; + +import java.util.ArrayList; + +/** + * DESC:Animoji业务工厂 + * Created on 2021/3/3 + */ +public class AnimojiDataFactory extends AbstractAnimojiDataFactory { + + /*渲染控制器*/ + private FURenderKit mFURenderKit = FURenderKit.getInstance(); + private FUAIKit mFUAIKit = FUAIKit.getInstance(); + /*3D抗锯齿*/ + public final Antialiasing antialiasing; + /*动漫滤镜模型*/ + public final AnimationFilter animationFilter; + /*当前选中贴图模型*/ + private Prop currentAnimoji; + /*当前选中下标*/ + private int currentAnimojiIndex; + /*当前滤镜下标*/ + private int currentFilterIndex; + /*Animoji数据*/ + private ArrayList animojiBeans; + /*Animoji滤镜数据*/ + private ArrayList animationFilterBeans; + + /** + * 构造 AnimojiDataFactory + * + * @param animojiIndex 贴图下标 + * @param filterIndex 滤镜下标 + */ + public AnimojiDataFactory(int animojiIndex, int filterIndex) { + antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING)); + animationFilter = new AnimationFilter(new FUBundleData(FaceUnityConfig.BUNDLE_ANIMATION_FILTER)); + currentAnimojiIndex = animojiIndex; + currentFilterIndex = filterIndex; + animojiBeans = AnimojiSource.buildAnimojis(); + animationFilterBeans = AnimojiSource.buildFilters(); + bindCurrentRenderer(); + } + + + /** + * 动漫贴图列表 + * + * @return + */ + @Override + public ArrayList getAnimojis() { + return animojiBeans; + } + + /** + * 动漫滤镜列表 + * + * @return + */ + @Override + public ArrayList 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); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/AvatarDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/AvatarDataFactory.java new file mode 100644 index 000000000..2ab36dc79 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/AvatarDataFactory.java @@ -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 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 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; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/BgSegGreenDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/BgSegGreenDataFactory.java new file mode 100644 index 000000000..ff10231e0 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/BgSegGreenDataFactory.java @@ -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 mBgSegGreenBackgroundBeans; + /* 绿幕抠像当前背景下标 */ + private int mCurrentBackgroundIndex; + + /*绿幕抠像安全区域列表*/ + private ArrayList 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 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 getModelAttributeRange() { + return BgSegGreenSource.buildModelAttributeRange(); + } + + /** + * 获取绿幕抠像功能列表 + * + * @return + */ + @Override + public ArrayList getBgSegGreenActions() { + return BgSegGreenSource.buildBgSegGreenAction(); + } + + /** + * 获取绿幕抠像安全区域功能列表 + * + * @return + */ + @Override + public ArrayList getBgSegGreenSafeAreas() { + return mBgSegGreenSafeAreaBeans; + } + + /** + * 获取绿幕抠像背景列表 + * + * @return + */ + @Override + public ArrayList 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 bgSegGreenSetMapping = new HashMap() { + { + put(BgSegGreenParam.SIMILARITY, value -> getCurrentBgSegGreenModel().setSimilarity(value)); + put(BgSegGreenParam.SMOOTHNESS, value -> getCurrentBgSegGreenModel().setSmoothness(value)); + put(BgSegGreenParam.TRANSPARENCY, value -> getCurrentBgSegGreenModel().setTransparency(value)); + } + }; + + /*模型映射获取模型值*/ + private final HashMap bgSegGreenGetMapping = new HashMap() { + { + 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)); + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/BodyBeautyDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/BodyBeautyDataFactory.java new file mode 100644 index 000000000..6a7cb088c --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/BodyBeautyDataFactory.java @@ -0,0 +1,160 @@ +package com.yunbao.faceunity.data; + +import com.faceunity.core.controller.bodyBeauty.BodyBeautyParam; +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.faceunity.FUAIKit; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.model.bodyBeauty.BodyBeauty; + +import com.yunbao.faceunity.entity.BodyBeautyBean; +import com.yunbao.faceunity.entity.ModelAttributeData; +import com.yunbao.faceunity.infe.AbstractBodyBeautyDataFactory; +import com.yunbao.faceunity.repo.BodyBeautySource; +import com.yunbao.faceunity.utils.FaceUnityConfig; + +import java.util.ArrayList; +import java.util.HashMap; + + +/** + * DESC:美体业务工厂 + * Created on 2021/3/2 + */ +public class BodyBeautyDataFactory extends AbstractBodyBeautyDataFactory { + + + interface BodyBeautySetParamInterface { + void setValue(double value); + } + + interface BodyBeautyGetParamInterface { + double getValue(); + } + + + /*渲染控制器*/ + private FURenderKit mFURenderKit = FURenderKit.getInstance(); + private FUAIKit mFUAIKit = FUAIKit.getInstance(); + + /*美体数据模型*/ + public final BodyBeauty bodyBeauty; + + public BodyBeautyDataFactory() { + bodyBeauty = new BodyBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_BODY_BEAUTY)); + + } + + + /** + * 获取美体属性列表 + * + * @return + */ + @Override + public ArrayList getBodyBeautyParam() { + return BodyBeautySource.buildBodyBeauty(); + } + + /** + * 获取美体扩展参数 + * + * @return + */ + @Override + public HashMap getModelAttributeRange() { + return BodyBeautySource.buildModelAttributeRange(); + } + + + /** + * 获取模型参数 + * + * @param key 名称标识 + * @return + */ + @Override + public double getParamIntensity(String key) { + if (bodyBeautyGetMapping.containsKey(key)) { + return bodyBeautyGetMapping.get(key).getValue(); + } + return 0.0; + } + + /** + * 设置属性参数 + * + * @param key 名称标识 + * @param value 结果值 + */ + @Override + public void updateParamIntensity(String key, double value) { + if (bodyBeautySetMapping.containsKey(key)) { + bodyBeautySetMapping.get(key).setValue(value); + } + } + + @Override + public void enableBodyBeauty(boolean enable) { + if (mFURenderKit.getBodyBeauty() != null) { + mFURenderKit.getBodyBeauty().setEnable(enable); + } + } + + /** + * 获取当前模型 + * + * @return + */ + private BodyBeauty getCurrentBodyBeautyModel() { + return bodyBeauty; + } + + + /*模型映射设置模型值*/ + private final HashMap bodyBeautySetMapping = new HashMap() { + { + put(BodyBeautyParam.BODY_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setBodySlimIntensity(value)); + put(BodyBeautyParam.LEG_STRETCH_INTENSITY, value -> getCurrentBodyBeautyModel().setLegStretchIntensity(value)); + put(BodyBeautyParam.WAIST_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setWaistSlimIntensity(value)); + put(BodyBeautyParam.SHOULDER_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setShoulderSlimIntensity(value)); + put(BodyBeautyParam.HIP_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setHipSlimIntensity(value)); + put(BodyBeautyParam.HEAD_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setHeadSlimIntensity(value)); + put(BodyBeautyParam.LEG_SLIM_INTENSITY, value -> getCurrentBodyBeautyModel().setLegSlimIntensity(value)); + } + }; + + /*模型映射获取模型值*/ + HashMap bodyBeautyGetMapping = new HashMap() { + { + put(BodyBeautyParam.BODY_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getBodySlimIntensity()); + put(BodyBeautyParam.LEG_STRETCH_INTENSITY, ()->getCurrentBodyBeautyModel().getLegStretchIntensity()); + put(BodyBeautyParam.WAIST_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getWaistSlimIntensity()); + put(BodyBeautyParam.SHOULDER_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getShoulderSlimIntensity()); + put(BodyBeautyParam.HIP_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getHipSlimIntensity()); + put(BodyBeautyParam.HEAD_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getHeadSlimIntensity()); + put(BodyBeautyParam.LEG_SLIM_INTENSITY, ()->getCurrentBodyBeautyModel().getLegSlimIntensity()); + + } + }; + + + /** + * FURenderKit加载当前特效 + */ + public void bindCurrentRenderer() { + mFUAIKit.loadAIProcessor(FaceUnityConfig.getAIHumanBundle(), FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR); + mFUAIKit.setMaxFaces(1); + mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty); + mFURenderKit.setBodyBeauty(bodyBeauty); + } + + /** + * 结束需要释放AI驱动 + */ + public void releaseAIProcessor() { + mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR); + } + + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceBeautyData.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceBeautyData.java new file mode 100644 index 000000000..2fe86d58a --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceBeautyData.java @@ -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 filterMap = new HashMap<>(); + + /* 滤镜相关 */ + /* 滤镜名称 */ + public String filterName = FaceBeautyFilterEnum.ORIGIN; + /* 滤镜程度 */ + public double filterIntensity = 0.0f; +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceBeautyDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceBeautyDataFactory.java new file mode 100644 index 000000000..823aedd07 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceBeautyDataFactory.java @@ -0,0 +1,457 @@ +package com.yunbao.faceunity.data; + + +import androidx.annotation.NonNull; + +import com.faceunity.core.controller.facebeauty.FaceBeautyParam; +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.faceunity.FUAIKit; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.model.facebeauty.FaceBeauty; +import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum; +import com.faceunity.core.model.prop.expression.ExpressionRecognition; +import com.yunbao.faceunity.entity.FaceBeautyBean; +import com.yunbao.faceunity.entity.FaceBeautyFilterBean; +import com.yunbao.faceunity.entity.FaceBeautyStyleBean; +import com.yunbao.faceunity.entity.ModelAttributeData; +import com.yunbao.faceunity.infe.AbstractFaceBeautyDataFactory; +import com.yunbao.faceunity.repo.FaceBeautySource; +import com.yunbao.faceunity.utils.FaceUnityConfig; + +import java.util.ArrayList; +import java.util.HashMap; + + +/** + * DESC:美颜业务工厂 + * Created on 2021/3/1 + */ +public class FaceBeautyDataFactory extends AbstractFaceBeautyDataFactory { + + public interface FaceBeautyListener { + /** + * 风格切换 + * + * @param res + */ + void onFilterSelected(int res); + + /** + * 美颜开关 + * + * @param enable + */ + void onFaceBeautyEnable(boolean enable); + } + + interface FaceBeautySetParamInterface { + /** + * 设置属性值 + * + * @param value + */ + void setValue(double value); + } + + interface FaceBeautyGetParamInterface { + /** + * 获取属性值 + * + * @return + */ + double getValue(); + } + + /*渲染控制器*/ + private FURenderKit mFURenderKit = FURenderKit.getInstance(); + + /*推荐风格标识*/ + private static int currentStyleIndex = -1; + + /*美颜缓存数据模型 用于普通美颜*/ + public static final FaceBeauty defaultFaceBeauty = FaceBeautySource.getDefaultFaceBeauty(); + + /*当前生效美颜数据模型 普通 or 风格的*/ + public static FaceBeauty faceBeauty = defaultFaceBeauty; + + + /*默认滤镜选中下标*/ + private int currentFilterIndex = 0; + /*业务回调*/ + private final FaceBeautyListener mFaceBeautyListener; + + + public FaceBeautyDataFactory(FaceBeautyListener listener) { + mFaceBeautyListener = listener; + } + + + /** + * 获取美肤参数列表 + * + * @return + */ + @NonNull + @Override + public ArrayList getSkinBeauty() { + return FaceBeautySource.buildSkinParams(); + } + + /** + * 获取美型参数列表 + * + * @return + */ + @NonNull + @Override + public ArrayList getShapeBeauty() { + return FaceBeautySource.buildShapeParams(); + } + + /** + * 获取美型参数列表 + * + * @return + */ + @NonNull + @Override + public ArrayList getShapeBeautySubItem() { + return FaceBeautySource.buildFaceShapeSubItemParams(); + } + + + /** + * 获取美肤、美型扩展参数 + * + * @return + */ + @NonNull + @Override + public HashMap getModelAttributeRange() { + return FaceBeautySource.buildModelAttributeRange(); + } + + + /** + * 获取滤镜参数列表 + * + * @return + */ + @NonNull + @Override + public ArrayList getBeautyFilters() { + ArrayList filterBeans = FaceBeautySource.buildFilters(); + for (int i = 0; i < filterBeans.size(); i++) { + if (filterBeans.get(i).getKey().equals(defaultFaceBeauty.getFilterName())) { + filterBeans.get(i).setIntensity(defaultFaceBeauty.getFilterIntensity()); + currentFilterIndex = i; + } + } + return filterBeans; + } + + /** + * 获取当前滤镜下标 + * + * @return + */ + @Override + public int getCurrentFilterIndex() { + return currentFilterIndex; + } + + /** + * 设置当前滤镜下标 + * + * @param currentFilterIndex + */ + @Override + public void setCurrentFilterIndex(int currentFilterIndex) { + this.currentFilterIndex = currentFilterIndex; + } + + /** + * 获取推荐风格列表 + * + * @return + */ + @NonNull + @Override + public ArrayList getBeautyStyles() { + return FaceBeautySource.buildStylesParams(); + } + + + /** + * 获取当前风格推荐标识 + * + * @return + */ + @Override + public int getCurrentStyleIndex() { + return currentStyleIndex; + } + + /** + * 设置风格推荐标识 + * + * @param styleIndex + */ + @Override + public void setCurrentStyleIndex(int styleIndex) { + currentStyleIndex = styleIndex; + } + + /** + * 设置风格推荐标识 来自于硬盘 + * + * @param styleIndex + */ + public static void setDiskCurrentStyleIndex(int styleIndex) { + currentStyleIndex = styleIndex; + } + + /** + * 美颜开关设置 + * + * @param enable + */ + @Override + public void enableFaceBeauty(boolean enable) { + mFaceBeautyListener.onFaceBeautyEnable(enable); + } + + /** + * 获取模型参数 + * + * @param key 名称标识 + * @return 属性值 + */ + @Override + public double getParamIntensity(@NonNull String key) { + if (faceBeautyGetMapping.containsKey(key)) { + return faceBeautyGetMapping.get(key).getValue(); + } + return 0.0; + } + + /** + * 设置模型参数 + * + * @param key 名称标识 + * @param value 属性值 + */ + @Override + public void updateParamIntensity(@NonNull String key, double value) { + if (faceBeautySetMapping.containsKey(key)) { + faceBeautySetMapping.get(key).setValue(value); + } + } + + /** + * 将所有效果制空 + */ + @Override + public void resetParamIntensity() { + if (faceBeauty != defaultFaceBeauty) { + faceBeauty = defaultFaceBeauty; + FURenderKit.getInstance().setFaceBeauty(faceBeauty); + } + + ArrayList skinBeauty = getSkinBeauty(); + ArrayList shapeBeauty = getShapeBeauty(); + HashMap 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 hashMap) { + CurrentFaceShapeUIValue.currentFaceShapeValue.clear(); + CurrentFaceShapeUIValue.currentFaceShapeValue.putAll(hashMap); + } + + /** + * 获取当前脸型的UI值 + */ + public HashMap getCurrentFaceShapeUIValue() { + return CurrentFaceShapeUIValue.currentFaceShapeValue; + } + + /** + * 切换滤镜 + * + * @param name 滤镜名称标识 + * @param intensity 滤镜强度 + * @param resID 滤镜名称 + */ + @Override + public void onFilterSelected(@NonNull String name, double intensity, int resID) { + defaultFaceBeauty.setFilterName(name); + defaultFaceBeauty.setFilterIntensity(intensity); + mFaceBeautyListener.onFilterSelected(resID); + } + + /** + * 更换滤镜强度 + * + * @param intensity 滤镜强度 + */ + @Override + public void updateFilterIntensity(double intensity) { + defaultFaceBeauty.setFilterIntensity(intensity); + } + + /** + * 设置推荐风格 + * + * @param name 风格key + */ + @Override + public void onStyleSelected(String name) { + if (name == null) { + faceBeauty = defaultFaceBeauty; + FURenderKit.getInstance().setFaceBeauty(faceBeauty); + } else { + Runnable runnable = FaceBeautySource.styleParams.get(name); + if (runnable != null) { + runnable.run(); + } + } + } + + /*模型映射设置模型值*/ + private final HashMap faceBeautySetMapping = new HashMap() {{ + put(FaceBeautyParam.COLOR_INTENSITY, defaultFaceBeauty::setColorIntensity); + put(FaceBeautyParam.BLUR_INTENSITY, defaultFaceBeauty::setBlurIntensity); + put(FaceBeautyParam.RED_INTENSITY, defaultFaceBeauty::setRedIntensity); + put(FaceBeautyParam.SHARPEN_INTENSITY, defaultFaceBeauty::setSharpenIntensity); + put(FaceBeautyParam.EYE_BRIGHT_INTENSITY, defaultFaceBeauty::setEyeBrightIntensity); + put(FaceBeautyParam.TOOTH_WHITEN_INTENSITY, defaultFaceBeauty::setToothIntensity); + put(FaceBeautyParam.REMOVE_POUCH_INTENSITY, defaultFaceBeauty::setRemovePouchIntensity); + put(FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, defaultFaceBeauty::setRemoveLawPatternIntensity); + /*美型*/ + put(FaceBeautyParam.FACE_SHAPE_INTENSITY, defaultFaceBeauty::setSharpenIntensity); + put(FaceBeautyParam.CHEEK_THINNING_INTENSITY, defaultFaceBeauty::setCheekThinningIntensity); + put(FaceBeautyParam.CHEEK_V_INTENSITY, defaultFaceBeauty::setCheekVIntensity); + put(FaceBeautyParam.CHEEK_LONG_INTENSITY, defaultFaceBeauty::setCheekLongIntensity); + put(FaceBeautyParam.CHEEK_CIRCLE_INTENSITY, defaultFaceBeauty::setCheekCircleIntensity); + put(FaceBeautyParam.CHEEK_NARROW_INTENSITY, defaultFaceBeauty::setCheekNarrowIntensity); + put(FaceBeautyParam.CHEEK_SHORT_INTENSITY, defaultFaceBeauty::setCheekShortIntensity); + put(FaceBeautyParam.CHEEK_SMALL_INTENSITY, defaultFaceBeauty::setCheekSmallIntensity); + put(FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, defaultFaceBeauty::setCheekBonesIntensity); + put(FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, defaultFaceBeauty::setLowerJawIntensity); + put(FaceBeautyParam.EYE_ENLARGING_INTENSITY, defaultFaceBeauty::setEyeEnlargingIntensity); + put(FaceBeautyParam.EYE_CIRCLE_INTENSITY, defaultFaceBeauty::setEyeCircleIntensity); + put(FaceBeautyParam.BROW_HEIGHT_INTENSITY, defaultFaceBeauty::setBrowHeightIntensity); + put(FaceBeautyParam.BROW_SPACE_INTENSITY, defaultFaceBeauty::setBrowSpaceIntensity); + put(FaceBeautyParam.CHIN_INTENSITY, defaultFaceBeauty::setChinIntensity); + put(FaceBeautyParam.FOREHEAD_INTENSITY, defaultFaceBeauty::setForHeadIntensity); + put(FaceBeautyParam.NOSE_INTENSITY, defaultFaceBeauty::setNoseIntensity); + put(FaceBeautyParam.MOUTH_INTENSITY, defaultFaceBeauty::setMouthIntensity); + put(FaceBeautyParam.CANTHUS_INTENSITY, defaultFaceBeauty::setCanthusIntensity); + put(FaceBeautyParam.EYE_SPACE_INTENSITY, defaultFaceBeauty::setEyeSpaceIntensity); + put(FaceBeautyParam.EYE_ROTATE_INTENSITY, defaultFaceBeauty::setEyeRotateIntensity); + put(FaceBeautyParam.LONG_NOSE_INTENSITY, defaultFaceBeauty::setLongNoseIntensity); + put(FaceBeautyParam.PHILTRUM_INTENSITY, defaultFaceBeauty::setPhiltrumIntensity); + put(FaceBeautyParam.SMILE_INTENSITY, defaultFaceBeauty::setSmileIntensity); + }}; + + /*模型映射获取模型值*/ + HashMap faceBeautyGetMapping = new HashMap() { + { + put(FaceBeautyParam.COLOR_INTENSITY, defaultFaceBeauty::getColorIntensity); + put(FaceBeautyParam.BLUR_INTENSITY, defaultFaceBeauty::getBlurIntensity); + put(FaceBeautyParam.RED_INTENSITY, defaultFaceBeauty::getRedIntensity); + put(FaceBeautyParam.SHARPEN_INTENSITY, defaultFaceBeauty::getSharpenIntensity); + put(FaceBeautyParam.EYE_BRIGHT_INTENSITY, defaultFaceBeauty::getEyeBrightIntensity); + put(FaceBeautyParam.TOOTH_WHITEN_INTENSITY, defaultFaceBeauty::getToothIntensity); + put(FaceBeautyParam.REMOVE_POUCH_INTENSITY, defaultFaceBeauty::getRemovePouchIntensity); + put(FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, defaultFaceBeauty::getRemoveLawPatternIntensity); + /*美型*/ + put(FaceBeautyParam.FACE_SHAPE_INTENSITY, defaultFaceBeauty::getSharpenIntensity); + put(FaceBeautyParam.CHEEK_THINNING_INTENSITY, defaultFaceBeauty::getCheekThinningIntensity); + put(FaceBeautyParam.CHEEK_V_INTENSITY, defaultFaceBeauty::getCheekVIntensity); + put(FaceBeautyParam.CHEEK_LONG_INTENSITY, defaultFaceBeauty::getCheekLongIntensity); + put(FaceBeautyParam.CHEEK_CIRCLE_INTENSITY, defaultFaceBeauty::getCheekCircleIntensity); + put(FaceBeautyParam.CHEEK_NARROW_INTENSITY, defaultFaceBeauty::getCheekNarrowIntensity); + put(FaceBeautyParam.CHEEK_SHORT_INTENSITY, defaultFaceBeauty::getCheekShortIntensity); + put(FaceBeautyParam.CHEEK_SMALL_INTENSITY, defaultFaceBeauty::getCheekSmallIntensity); + put(FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, defaultFaceBeauty::getCheekBonesIntensity); + put(FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, defaultFaceBeauty::getLowerJawIntensity); + put(FaceBeautyParam.EYE_ENLARGING_INTENSITY, defaultFaceBeauty::getEyeEnlargingIntensity); + put(FaceBeautyParam.EYE_CIRCLE_INTENSITY, defaultFaceBeauty::getEyeCircleIntensity); + put(FaceBeautyParam.BROW_HEIGHT_INTENSITY, defaultFaceBeauty::getBrowHeightIntensity); + put(FaceBeautyParam.BROW_SPACE_INTENSITY, defaultFaceBeauty::getBrowSpaceIntensity); + put(FaceBeautyParam.CHIN_INTENSITY, defaultFaceBeauty::getChinIntensity); + put(FaceBeautyParam.FOREHEAD_INTENSITY, defaultFaceBeauty::getForHeadIntensity); + put(FaceBeautyParam.NOSE_INTENSITY, defaultFaceBeauty::getNoseIntensity); + put(FaceBeautyParam.MOUTH_INTENSITY, defaultFaceBeauty::getMouthIntensity); + put(FaceBeautyParam.CANTHUS_INTENSITY, defaultFaceBeauty::getCanthusIntensity); + put(FaceBeautyParam.EYE_SPACE_INTENSITY, defaultFaceBeauty::getEyeSpaceIntensity); + put(FaceBeautyParam.EYE_ROTATE_INTENSITY, defaultFaceBeauty::getEyeRotateIntensity); + put(FaceBeautyParam.LONG_NOSE_INTENSITY, defaultFaceBeauty::getLongNoseIntensity); + put(FaceBeautyParam.PHILTRUM_INTENSITY, defaultFaceBeauty::getPhiltrumIntensity); + put(FaceBeautyParam.SMILE_INTENSITY, defaultFaceBeauty::getSmileIntensity); + + } + }; + + + /** + * FURenderKit加载当前特效 + */ + public void bindCurrentRenderer() { + mFURenderKit.setFaceBeauty(faceBeauty); + FUAIKit.getInstance().setMaxFaces(4); + if (FaceUnityConfig.IS_OPEN_LAND_MARK) { + ExpressionRecognition expressionRecognition = new ExpressionRecognition(new FUBundleData(FaceUnityConfig.BUNDLE_LANDMARKS)); + expressionRecognition.setLandmarksType(FUAITypeEnum.FUAITYPE_FACELANDMARKS239); + mFURenderKit.getPropContainer().addProp(expressionRecognition); + } + } + + /** + * 用于记录当前脸型的UI值 -> 用于用户下次点入的时候恢复 + */ + static class CurrentFaceShapeUIValue { + /* 当前生效的脸型 */ + public static String currentFaceShape = FaceBeautyParam.CHEEK_V_INTENSITY; + /* 当前脸型的UI值 */ + public static HashMap currentFaceShapeValue = new HashMap<>(); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceParam.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceParam.java new file mode 100644 index 000000000..8de420416 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceParam.java @@ -0,0 +1,34 @@ +package com.yunbao.faceunity.data; + +public class FaceParam { + public static final int FACE_BEAUTY=100;//美颜 + public static final int FACE_BEAUTY_SKIN=101;//美肤 + public static final int FACE_BEAUTY_SHAPE=102;//美型 + public static final int FACE_BEAUTY_FILTER=103;//滤镜 + public static final int FACE_BEAUTY_STYLE=104;//风格推荐 + public static final int FACE_MAKEUP=200;//美妆 + public static final int FACE_MAKEUP_TYPE_FOUNDATION=201;//粉底 + public static final int FACE_MAKEUP_TYPE_LIP_STICK=202;//口红 + public static final int FACE_MAKEUP_TYPE_BLUSHER=203;//腮红 + public static final int FACE_MAKEUP_TYPE_EYE_BROW=204;//眉毛 + public static final int FACE_MAKEUP_TYPE_EYE_SHADOW=205;//眼影 + public static final int FACE_MAKEUP_TYPE_EYE_LINER=206;//眼线 + public static final int FACE_MAKEUP_TYPE_EYE_LASH=207;//睫毛 + public static final int FACE_MAKEUP_TYPE_HIGH_LIGHT=208;//高光 + public static final int FACE_MAKEUP_TYPE_SHADOW=209;//阴影 + public static final int FACE_MAKEUP_TYPE_EYE_PUPIL=210;//美瞳 + public static final int FACE_BEAUTY_BODY=300;//美体 + public static final int FACE_BIG_HEAD=400;//大头 + public static final int FACE_ANIMOJI=500;//Animoji + public static final int FACE_STICKER=600;//贴纸 + public static final int FACE_FINE_STICKER=700;//精品贴纸 + public static final int FACE_FINE_STICKER_MIDDLE=701;//中级道具 + public static final int FACE_FINE_STICKER_HIGH=702;//高级道具 + public static final int FACE_FINE_STICKER_GAME=703;//游戏道具 + public static final int FACE_ANIM=800;//动漫滤镜 + // 占位符,以下均未使用 + public static final int FACE_ANIM_AR_MASK=900; + public static final int FACE_EXPRESSION_RECOGNITION=1000; + public static final int FACE_FACE_WARP=1100; + public static final int FACE_GESTURE_RECOGNITION=1200; +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceUnityDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceUnityDataFactory.java new file mode 100644 index 000000000..df73630a4 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FaceUnityDataFactory.java @@ -0,0 +1,159 @@ +package com.yunbao.faceunity.data; + +import com.faceunity.core.enumeration.FUAIProcessorEnum; +import com.faceunity.core.faceunity.FURenderKit; +import com.yunbao.faceunity.entity.PropBean; +import com.yunbao.faceunity.utils.FURenderer; + +/** + * DESC: + * Created on 2021/4/25 + */ +public class FaceUnityDataFactory { + + /** + * 道具数据工厂 + */ + public FaceBeautyDataFactory mFaceBeautyDataFactory; + public BodyBeautyDataFactory mBodyBeautyDataFactory; + public MakeupDataFactory mMakeupDataFactory; + public PropDataFactory mPropDataFactory; + + + private FURenderKit mFURenderKit = FURenderKit.getInstance(); + private FURenderer mFURenderer = FURenderer.getInstance(); + + private static FaceUnityDataFactory sInstance; + public static FaceUnityDataFactory getInstance() { + if (sInstance == null) { + synchronized (FaceUnityDataFactory.class) { + if (sInstance == null) { + sInstance = new FaceUnityDataFactory(0); + } + } + } + return sInstance; + } + + public static void release() { + sInstance = null; + } + + /** + * 道具加载标识 + */ + public int currentFunctionIndex; + private boolean hasFaceBeautyLoaded = false; + private boolean hasBodyBeautyLoaded = false; + private boolean hasMakeupLoaded = false; + private boolean hasPropLoaded = false; + + + public FaceUnityDataFactory(int index) { + currentFunctionIndex = index; + mFaceBeautyDataFactory = new FaceBeautyDataFactory(new FaceBeautyDataFactory.FaceBeautyListener() { + @Override + public void onFilterSelected(int res) { + + } + + @Override + public void onFaceBeautyEnable(boolean enable) { + + } + }); + mBodyBeautyDataFactory = new BodyBeautyDataFactory(); + mMakeupDataFactory = new MakeupDataFactory(0); + mPropDataFactory = new PropDataFactory(new PropDataFactory.PropListener() { + @Override + public void onItemSelected(PropBean bean) { + + } + },0,0); + } + + /** + * FURenderKit加载当前特效 + */ + public void bindCurrentRenderer() { + switch (currentFunctionIndex) { + case 0: + mFaceBeautyDataFactory.bindCurrentRenderer(); + hasFaceBeautyLoaded = true; + break; + case 1: + mPropDataFactory.bindCurrentRenderer(); + hasPropLoaded = true; + break; + + case 2: + mMakeupDataFactory.bindCurrentRenderer(); + hasMakeupLoaded = true; + break; + case 3: + mBodyBeautyDataFactory.bindCurrentRenderer(); + hasBodyBeautyLoaded = true; + break; + } + if (hasFaceBeautyLoaded && currentFunctionIndex != 0) { + mFaceBeautyDataFactory.bindCurrentRenderer(); + } + if (hasPropLoaded && currentFunctionIndex != 1) { + mPropDataFactory.bindCurrentRenderer(); + } + if (hasMakeupLoaded && currentFunctionIndex != 2) { + mMakeupDataFactory.bindCurrentRenderer(); + } + if (hasBodyBeautyLoaded && currentFunctionIndex != 3) { + mBodyBeautyDataFactory.bindCurrentRenderer(); + } + if (currentFunctionIndex == 3) { + mFURenderKit.getFUAIController().setMaxFaces(1); + mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.HUMAN_PROCESSOR); + } else { + mFURenderKit.getFUAIController().setMaxFaces(4); + mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.FACE_PROCESSOR); + } + } + + /** + * 道具功能切换 + */ + public void onFunctionSelected(int index) { + currentFunctionIndex = index; + switch (index) { + case 0: + if (!hasFaceBeautyLoaded) { + mFaceBeautyDataFactory.bindCurrentRenderer(); + hasFaceBeautyLoaded = true; + } + mFURenderKit.getFUAIController().setMaxFaces(4); + mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.FACE_PROCESSOR); + break; + case 1: + if (!hasPropLoaded) { + mPropDataFactory.bindCurrentRenderer(); + hasPropLoaded = true; + } + mFURenderKit.getFUAIController().setMaxFaces(4); + mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.FACE_PROCESSOR); + break; + case 2: + if (!hasMakeupLoaded) { + mMakeupDataFactory.bindCurrentRenderer(); + hasMakeupLoaded = true; + } + mFURenderKit.getFUAIController().setMaxFaces(4); + mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.FACE_PROCESSOR); + break; + case 3: + if (!hasBodyBeautyLoaded) { + mBodyBeautyDataFactory.bindCurrentRenderer(); + hasBodyBeautyLoaded = true; + } + mFURenderKit.getFUAIController().setMaxFaces(1); + mFURenderer.setAIProcessTrackType(FUAIProcessorEnum.HUMAN_PROCESSOR); + break; + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/FineStickerDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FineStickerDataFactory.java new file mode 100644 index 000000000..e500c4b6f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/FineStickerDataFactory.java @@ -0,0 +1,405 @@ +package com.yunbao.faceunity.data; + +import android.util.Log; +import android.view.MotionEvent; + + +import com.faceunity.core.avatar.model.Avatar; +import com.faceunity.core.avatar.model.Scene; +import com.faceunity.core.avatar.scene.ProcessorConfig; +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.entity.FUTranslationScale; +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.faceunity.FUAIKit; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.faceunity.FUSceneKit; +import com.faceunity.core.model.antialiasing.Antialiasing; +import com.faceunity.core.model.prop.sticker.FineSticker; +import com.faceunity.core.utils.FileUtils; + +import com.yunbao.faceunity.entity.net.FineStickerEntity; +import com.yunbao.faceunity.entity.net.FineStickerTagEntity; +import com.yunbao.faceunity.infe.AbstractFineStickerDataFactory; +import com.yunbao.faceunity.repo.AvatarSource; +import com.yunbao.faceunity.utils.FaceUnityConfig; +import com.yunbao.faceunity.utils.net.StickerDownloadHelper; + +import org.jetbrains.annotations.NotNull; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created on 2021/3/31 0031 15:28. + * Author: xloger + * Email:phoenix@xloger.com + */ +public class FineStickerDataFactory extends AbstractFineStickerDataFactory { + private static final String TAG = "FineStickerDataFactory"; + private static FineStickerDataFactory factory; + public static FineStickerDataFactory getInstance(){ + if(factory==null){ + factory=new FineStickerDataFactory(); + } + return factory; + } + + + + /*渲染控制器*/ + private final FURenderKit mFURenderKit = FURenderKit.getInstance(); + private FUAIKit mFUAIKit = FUAIKit.getInstance(); + /*当前选中道具模型*/ + private FineSticker currentProp; + /*菜单视图*/ + /*当前选中道具*/ + private FineStickerEntity.DocsBean currentSticker; + /*当前道具的类型 普通单bundle,avatar 默认为普通单bundle*/ + private BundleType mCurrentBundleType = BundleType.NORMAL_SINGLE_BUNDLE; + + //avatar相关 + /* 场景 */ + private Scene mSceneModel; + /* 对象 */ + private Avatar mCurrentAvatarModel; + /*3D抗锯齿*/ + public Antialiasing antialiasing; + + //回调 + private List callbacks; + + //avatar用于区分bundle类型的关键字 + private final String COMPONENTS_STR = "components"; + private final String ANIM_STR = "anim"; + private final String INFO = "info.json"; + private final String ZIP = ".zip"; + private final String AVATAR = "avatar"; + + private FineStickerDataFactory() { + callbacks=new ArrayList<>(); + StickerDownloadHelper.getInstance().setCallback(downloadHelper); + } + + /** + * 绑定菜单视图 + * + */ + public void bindView() { + + } + + public void addCallback(StickerDownloadHelper.Callback downloadHelper) { + callbacks.add(downloadHelper); + } + public void removeCallback(StickerDownloadHelper.Callback downloadHelper){ + callbacks.remove(downloadHelper); + } + private void removeAllCallback(){ + callbacks.clear(); + } + + public void refuseEvent() { + StickerDownloadHelper.getInstance().setCallback(null); + } + + /** + * 切换道具 + * + * @param bean + */ + @Override + public void onItemSelected(FineStickerEntity.DocsBean bean) { + currentSticker = bean; + if (bean != null && bean.getTool().getBundle().getUid().endsWith(ZIP)) { + //复合道具 + if (AVATAR.equals(bean.getTool().getCategory())) { + //avatar道具 + if (mCurrentBundleType == BundleType.NORMAL_SINGLE_BUNDLE) { + //移除旧的道具 + mFURenderKit.getPropContainer().removeAllProp(); + currentProp = null; + adapterMaxFace(); + } + if (bean.getUnZipFilePaths() != null) { + buildAvatarModel(bean); + //当前为 avatar bundle + mCurrentBundleType = BundleType.AVATAR_BUNDLE; + } + } + } else { + //普通道具 + if (mCurrentBundleType == BundleType.NORMAL_SINGLE_BUNDLE) { + mFURenderKit.getPropContainer().removeAllProp(); + currentProp = null; + if (bean != null && bean.getFilePath() != null && bean.getFilePath().trim().length() > 0) { + adapterMaxFace(); + FineSticker prop = adapterBean(bean.getFilePath()); + mFURenderKit.getPropContainer().addProp(prop); + currentProp = prop; + } + } else if (mCurrentBundleType == BundleType.AVATAR_BUNDLE) { + //关闭avatar 相关的东西 + if (mSceneModel != null && mCurrentAvatarModel != null) { + mSceneModel.removeAvatar(mCurrentAvatarModel); + FUSceneKit.getInstance().removeScene(mSceneModel); + mSceneModel = null; + mCurrentAvatarModel = null; + } + + //设置道具 + if (bean != null && bean.getFilePath() != null && bean.getFilePath().trim().length() > 0) { + adapterMaxFace(); + FineSticker prop = adapterBean(bean.getFilePath()); + mFURenderKit.getPropContainer().addProp(prop); + currentProp = prop; + } + } + + //当前为普通bundle + mCurrentBundleType = BundleType.NORMAL_SINGLE_BUNDLE; + } + + if (mBundleTypeListener != null) { + mBundleTypeListener.bundleType(mCurrentBundleType); + } + } + + /** + * 构建avatar -> scene + * @param bean + */ + private void buildAvatarModel(FineStickerEntity.DocsBean bean) { + //启动avatar基本逻辑 + if (antialiasing == null) + antialiasing = new Antialiasing(new FUBundleData(FaceUnityConfig.BUNDLE_ANTI_ALIASING)); + //3d抗锯齿 + mFURenderKit.setAntialiasing(antialiasing); + //判断是avatar 控件 -> 查看是否有json文件 + ArrayList unZipFilePaths = bean.getUnZipFilePaths(); + int hasJson = unZipFilePaths.indexOf(INFO); + + ArrayList strComponents = new ArrayList<>();//组件Bundle + ArrayList strAnimations = new ArrayList<>();//动画Bundle + if (hasJson >= 0) { + //用json的描述赋予每一个bundle自己的职责,还可以赋予其他参数 + String jsonPath = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + unZipFilePaths.get(hasJson); + //解析json文件 -> + String json = FileUtils.loadStringFromExternal(jsonPath); + //解析avatar的json文件 + try { + JSONObject jsonObject = new JSONObject(json); + JSONArray components = jsonObject.getJSONArray("components"); + for(int i =0 ;i < components.length();i++) { + String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + components.get(i); + strComponents.add(path); + } + + JSONArray anims = jsonObject.getJSONArray("anims"); + for(int i =0 ;i < anims.length();i++) { + String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + anims.get(i); + strAnimations.add(path); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } else { + //根据bundle的命名赋予每一个bundle自己的职责 + for (String str:unZipFilePaths) { + if (str.startsWith(COMPONENTS_STR)) { + String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + str; + strComponents.add(path); + } else if (str.startsWith(ANIM_STR)){ + String path = bean.getFilePath().substring(0,bean.getFilePath().lastIndexOf(".")) + "/" + str; + strAnimations.add(path); + } + } + } + + if (mSceneModel == null) { + mCurrentAvatarModel = AvatarSource.buildAvatarData(strComponents,strAnimations); + mSceneModel = AvatarSource.buildSceneModel(mCurrentAvatarModel); + mSceneModel.processorConfig.setTrackScene(ProcessorConfig.TrackScene.SceneFull); + mCurrentAvatarModel.transForm.setTranslationScale(new FUTranslationScale(0.5f, 0f, 0.1f)); + } else { + if (mCurrentAvatarModel != null) + mSceneModel.removeAvatar(mCurrentAvatarModel); + mCurrentAvatarModel = AvatarSource.buildAvatarData(strComponents,strAnimations); + mSceneModel.addAvatar(mCurrentAvatarModel); + } + FUSceneKit.getInstance().addScene(mSceneModel); + FUSceneKit.getInstance().setCurrentScene(mSceneModel); + } + + + /** + * 根据adpater 调整业务模型 + * 0:维持竖屏 + * 1:仅限一人 + * 2:美妆道具 + * 3:点击事件 + * 4:翻转 + * + * @param path + * @return + */ + private FineSticker adapterBean(String path) { + String adapter = currentSticker.getTool().getAdapter(); + if (adapter == null || !adapter.contains("1")) { + mFUAIKit.setMaxFaces(4); + } else { + mFUAIKit.setMaxFaces(1); + } + if (adapter != null && adapter.trim().length() > 0) { + boolean isFlipPoints = adapter.contains("2"); + boolean is3DFlipH = adapter.contains("4"); + boolean isClick = adapter.contains("3"); + return new FineSticker(new FUBundleData(path), isFlipPoints, is3DFlipH, isClick); + } else { + return new FineSticker(new FUBundleData(path)); + } + } + + + /** + * 网络回调 + */ + private StickerDownloadHelper.Callback downloadHelper = new StickerDownloadHelper.Callback() { + @Override + public void onGetTags(String[] tags) { + for (StickerDownloadHelper.Callback callback : callbacks) { + callback.onGetTags(tags); + } + } + + @Override + public void onGetList(String tag, FineStickerEntity fineSticker) { + for (StickerDownloadHelper.Callback callback : callbacks) { + callback.onGetList(tag, fineSticker); + } + } + + @Override + public void onDownload(FineStickerEntity.DocsBean entity) { + for (StickerDownloadHelper.Callback callback : callbacks) { + callback.onDownload(entity); + } + } + + @Override + public void onDownloadError(FineStickerEntity.DocsBean entity, String msg) { + for (StickerDownloadHelper.Callback callback : callbacks) { + callback.onDownloadError(entity, msg); + + } + } + }; + + + /** + * 获取标签列表 + * + * @return + */ + @NotNull + @Override + public List loadTagList() { + String[] tags = StickerDownloadHelper.getInstance().tags(); + return formatTag(tags); + } + + /** + * 获取标签对应道具列表 + * + * @param tag + * @return + */ + @NotNull + @Override + public FineStickerEntity loadStickerList(@NotNull FineStickerTagEntity tag) { + return StickerDownloadHelper.getInstance().tools(tag.getTag()); + } + + /** + * 下载道具 + * + * @param docsBean + */ + @Override + public void downloadSticker(@NotNull FineStickerEntity.DocsBean docsBean) { + try{ + StickerDownloadHelper.getInstance().download(docsBean); + } catch (Exception e) { + Log.e(TAG,"downloadSticker",e); + e.printStackTrace(); + } + } + + + /** + * 数据转换 + * + * @param tags + * @return + */ + public static List formatTag(String[] tags) { + List tagEntityList = new ArrayList<>(tags.length); + for (int i = 0; i < tags.length; i++) { + tagEntityList.add(new FineStickerTagEntity(tags[i])); + } + return tagEntityList; + } + + /** + * FURenderKit加载当前特效 + */ + public void bindCurrentRenderer() { + mFUAIKit.loadAIProcessor(FaceUnityConfig.getAIHumanBundle(), FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR); + mFUAIKit.loadAIProcessor(FaceUnityConfig.BUNDLE_AI_HAND, FUAITypeEnum.FUAITYPE_HANDGESTURE); + mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty); + mFUAIKit.setMaxFaces(1); + onItemSelected(currentSticker); + } + + + /** + * 结束需要释放AI驱动 + */ + public void releaseAIProcessor() { + mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR); + mFUAIKit.releaseAIProcessor(FUAITypeEnum.FUAITYPE_HANDGESTURE); + } + + + private void adapterMaxFace() { + if (currentSticker == null) return; + String adapter = currentSticker.getTool().getAdapter(); + if (adapter == null || !adapter.contains("1")) { + mFUAIKit.setMaxFaces(4); + } else { + mFUAIKit.setMaxFaces(1); + } + } + + public void onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP && currentProp != null && currentProp.isClick()) { + currentProp.onClick(); + } + } + + //通过枚举记录每一个bundle的类型 + public enum BundleType { + NORMAL_SINGLE_BUNDLE,//普通的单bundle道具 + AVATAR_BUNDLE//avatar bundle 一般为多bundle + } + + private BundleTypeListener mBundleTypeListener; + public interface BundleTypeListener { + void bundleType(BundleType bundleType); + } + public void setBundleTypeListener (BundleTypeListener bundleTypeListener){ + mBundleTypeListener = bundleTypeListener; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/LightMakeupDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/LightMakeupDataFactory.java new file mode 100644 index 000000000..6e5dce740 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/LightMakeupDataFactory.java @@ -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 lightMakeupBeans; + /* 当前轻美妆选中下标 */ + private int currentLightMakeupIndex; + + + public LightMakeupDataFactory(int index) { + currentLightMakeupIndex = index; + lightMakeupBeans = LightMakeupSource.buildLightMakeup(); + } + + /** + * 获取轻美妆队列 + * + * @return + */ + @Override + public ArrayList 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); + } + } + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/MakeupDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/MakeupDataFactory.java new file mode 100644 index 000000000..1e808a010 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/MakeupDataFactory.java @@ -0,0 +1,853 @@ +package com.yunbao.faceunity.data; + + +import static com.yunbao.faceunity.repo.MakeupSource.*; + +import androidx.annotation.NonNull; + +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.entity.FUColorRGBData; +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.faceunity.FUAIKit; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.model.makeup.Makeup; +import com.faceunity.core.model.makeup.MakeupLipEnum; + +import com.faceunity.core.model.prop.expression.ExpressionRecognition; +import com.faceunity.core.utils.DecimalUtils; +import com.yunbao.faceunity.entity.MakeupCombinationBean; +import com.yunbao.faceunity.entity.MakeupCustomBean; +import com.yunbao.faceunity.entity.MakeupCustomClassBean; +import com.yunbao.faceunity.infe.AbstractMakeupDataFactory; +import com.yunbao.faceunity.repo.FaceBeautySource; +import com.yunbao.faceunity.repo.MakeupSource; +import com.yunbao.faceunity.utils.FaceUnityConfig; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; + +/** + * DESC:美妆业务工厂 + * Created on 2021/3/1 + */ +public class MakeupDataFactory extends AbstractMakeupDataFactory { + + + /*渲染控制器*/ + private FURenderKit mFURenderKit = FURenderKit.getInstance(); + + /*组合妆容列表*/ + private ArrayList makeupCombinations; + /*组合妆容当前下标*/ + private int currentCombinationIndex;//-1:自定义 + /*美妆数据模型*/ + private Makeup currentMakeup; + /*当前滤镜*/ + private String currentFilterName; + /*当前滤镜*/ + private Double currentFilterIntensity; + + + private LinkedHashMap> mMakeUpColorMap;//美妆颜色表 + + private HashMap mCustomIndexMap = new HashMap<>();//key:美妆类别 value:当前美妆子项选中下标 默认0 + private HashMap mCustomIntensityMap = new HashMap<>();//key:美妆类别_子项下标 value:当前美妆选中子项的妆容强度 默认1.0 + private HashMap mCustomColorIndexMap = new HashMap<>();//key:美妆类别_子项下标 value:当前美妆选中子项的颜色下标 默认3 + + + public MakeupDataFactory(int index) { + makeupCombinations = MakeupSource.buildCombinations(); + mMakeUpColorMap = MakeupSource.buildMakeUpColorMap(); + currentCombinationIndex = index; + currentFilterName = makeupCombinations.get(index).getFilterName(); + currentFilterIntensity = makeupCombinations.get(index).getFilterIntensity(); + currentMakeup = MakeupSource.getMakeupModel(makeupCombinations.get(currentCombinationIndex)); // 当前生效模型 + } + + //region 组合妆 + + /** + * 获取当前组合妆容列表 + * + * @return + */ + @Override + @NonNull + public ArrayList getMakeupCombinations() { + return makeupCombinations; + } + + /** + * 获取当前组合妆容下标 + * + * @return + */ + @Override + public int getCurrentCombinationIndex() { + return currentCombinationIndex; + } + + /** + * 设置组合妆容下标 + * + * @param currentCombinationIndex + */ + @Override + public void setCurrentCombinationIndex(int currentCombinationIndex) { + this.currentCombinationIndex = currentCombinationIndex; + } + + /** + * 切换组合妆容 + * + * @param bean + */ + @Override + public void onMakeupCombinationSelected(MakeupCombinationBean bean) { + currentFilterName = bean.getFilterName(); + currentFilterIntensity = bean.getFilterIntensity(); + if (mFURenderKit.getFaceBeauty() != null) { + mFURenderKit.getFaceBeauty().setFilterName(currentFilterName); + mFURenderKit.getFaceBeauty().setFilterIntensity(currentFilterIntensity); + } + currentMakeup = MakeupSource.getMakeupModel(bean); + mFURenderKit.setMakeup(currentMakeup); + if (!currentMakeup.getControlBundle().getPath().equals(FaceUnityConfig.BUNDLE_FACE_MAKEUP)) + currentMakeup.setFilterIntensity(currentFilterIntensity); + } + + /** + * 切换美妆模型整体强度 + * + * @param intensity + */ + @Override + public void updateCombinationIntensity(double intensity) { + currentMakeup.setMakeupIntensity(intensity); + currentFilterIntensity = intensity; + if (mFURenderKit.getFaceBeauty() != null) { + mFURenderKit.getFaceBeauty().setFilterIntensity(currentFilterIntensity); + } + + if (!currentMakeup.getControlBundle().getPath().equals(FaceUnityConfig.BUNDLE_FACE_MAKEUP)) + currentMakeup.setFilterIntensity(currentFilterIntensity); + } + + + //endregion 组合妆 + + //region 子美妆 + + + /** + * 获取子妆类别列表 + * + * @return + */ + @Override + public ArrayList getMakeupCustomClass() { + return MakeupSource.buildCustomClasses(); + } + + /** + * 获取子妆列表参数 + * + * @return + */ + @Override + public LinkedHashMap> getMakeupCustomItemParams() { + return MakeupSource.buildCustomItemParams(mMakeUpColorMap); + } + + /** + * 设置子妆强度 + * + * @param key + * @param current + * @param intensity + */ + @Override + public void updateCustomItemIntensity(String key, int current, double intensity) { + if (key.equals(FACE_MAKEUP_TYPE_FOUNDATION)) { + currentMakeup.setFoundationIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_LIP_STICK)) { + currentMakeup.setLipIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_BLUSHER)) { + currentMakeup.setBlusherIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_BROW)) { + currentMakeup.setEyeBrowIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_SHADOW)) { + currentMakeup.setEyeShadowIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_LINER)) { + currentMakeup.setEyeLineIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_LASH)) { + currentMakeup.setEyeLashIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_HIGH_LIGHT)) { + currentMakeup.setHeightLightIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_SHADOW)) { + currentMakeup.setShadowIntensity(intensity); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_PUPIL)) { + currentMakeup.setPupilIntensity(intensity); + } + mCustomIntensityMap.put(key + "_" + current, intensity); + } + + /** + * 切换子妆单项 + * + * @param key 子妆类别 + * @param index 选中下标 + */ + @Override + public void onCustomBeanSelected(String key, int index) { + String itemDir = FaceUnityConfig.MAKEUP_RESOURCE_ITEM_BUNDLE_DIR; + mCustomIndexMap.put(key, index); + if (key.equals(FACE_MAKEUP_TYPE_FOUNDATION)) { + if (index == 0) { + currentMakeup.setFoundationIntensity(0.0); + } else { + currentMakeup.setFoundationBundle(new FUBundleData(itemDir + "mu_style_foundation_01.bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_FOUNDATION + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_FOUNDATION + "_" + index); + } + currentMakeup.setFoundationIntensity((intensity)); + updateCustomColor(key, index + 2); + double[] color = mMakeUpColorMap.get("color_mu_style_foundation_01").get(index + 2); + currentMakeup.setFoundationColor(buildFUColorRGBData(color)); + } + } else if (key.equals(FACE_MAKEUP_TYPE_LIP_STICK)) { + if (index == 0) { + currentMakeup.setLipIntensity(0.0); + } else { + currentMakeup.setLipBundle(new FUBundleData(itemDir + "mu_style_lip_0" + index + ".bundle")); + switch (index) { + case 1: + currentMakeup.setLipType(MakeupLipEnum.FOG); + currentMakeup.setEnableTwoLipColor(false); + currentMakeup.setLipHighLightEnable(false); + currentMakeup.setLipHighLightStrength(0.0); + break; + case 2: + currentMakeup.setLipType(MakeupLipEnum.MOIST); + currentMakeup.setEnableTwoLipColor(false); + currentMakeup.setLipHighLightEnable(false); + currentMakeup.setLipHighLightStrength(0.0); + break; + case 3: + currentMakeup.setLipType(MakeupLipEnum.WATER); + currentMakeup.setEnableTwoLipColor(false); + currentMakeup.setLipHighLightEnable(true); + currentMakeup.setLipHighLightStrength(0.8); + break; + case 4: + currentMakeup.setLipType(MakeupLipEnum.PEARL); + currentMakeup.setEnableTwoLipColor(false); + currentMakeup.setLipHighLightEnable(false); + currentMakeup.setLipHighLightStrength(0.0); + break; + case 5: + currentMakeup.setLipType(MakeupLipEnum.FOG); + currentMakeup.setEnableTwoLipColor(true); + currentMakeup.setLipHighLightEnable(false); + currentMakeup.setLipHighLightStrength(0.0); + currentMakeup.setLipColor2(new FUColorRGBData(0.0, 0.0, 0.0, 0.0)); + break; + } + + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_LIP_STICK + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_LIP_STICK + "_" + index); + } + currentMakeup.setLipIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_LIP_STICK + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_LIP_STICK + "_" + index); + } + updateCustomColor(key, colorIndex); + } + } else if (key.equals(FACE_MAKEUP_TYPE_BLUSHER)) { + if (index == 0) { + currentMakeup.setBlusherIntensity(0.0); + } else { + currentMakeup.setBlusherBundle(new FUBundleData(itemDir + "mu_style_blush_0" + index + ".bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_BLUSHER + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_BLUSHER + "_" + index); + } + currentMakeup.setBlusherIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_BLUSHER + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_BLUSHER + "_" + index); + } + updateCustomColor(key, colorIndex); + } + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_BROW)) { + if (index == 0) { + currentMakeup.setEyeBrowIntensity(0.0); + currentMakeup.setEnableBrowWarp(false); + } else { + currentMakeup.setEnableBrowWarp(false); + currentMakeup.setEyeBrowBundle(new FUBundleData(itemDir + "mu_style_eyebrow_0" + index + ".bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_BROW + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_BROW + "_" + index); + } + currentMakeup.setEyeBrowIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_BROW + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_BROW + "_" + index); + } + updateCustomColor(key, colorIndex); + } + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_SHADOW)) { + if (index == 0) { + currentMakeup.setEyeShadowIntensity(0.0); + } else { + currentMakeup.setEyeShadowBundle(new FUBundleData(itemDir + "mu_style_eyeshadow_0" + index + ".bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + index); + } + currentMakeup.setEyeShadowIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + index); + } + updateCustomColor(key, colorIndex); + } + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_LINER)) { + if (index == 0) { + currentMakeup.setEyeLineIntensity(0.0); + } else { + currentMakeup.setEyeLinerBundle(new FUBundleData(itemDir + "mu_style_eyeliner_0" + index + ".bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_LINER + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_LINER + "_" + index); + } + currentMakeup.setEyeLineIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_LINER + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_LINER + "_" + index); + } + updateCustomColor(key, colorIndex); + } + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_LASH)) { + if (index == 0) { + currentMakeup.setEyeLashIntensity(0.0); + } else { + currentMakeup.setEyeLashBundle(new FUBundleData(itemDir + "mu_style_eyelash_0" + index + ".bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_LASH + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_LASH + "_" + index); + } + currentMakeup.setEyeLashIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_LASH + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_LASH + "_" + index); + } + updateCustomColor(key, colorIndex); + } + } else if (key.equals(FACE_MAKEUP_TYPE_HIGH_LIGHT)) { + if (index == 0) { + currentMakeup.setHeightLightIntensity(0.0); + } else { + currentMakeup.setHighLightBundle(new FUBundleData(itemDir + "mu_style_highlight_0" + index + ".bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + index); + } + currentMakeup.setHeightLightIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + index); + } + updateCustomColor(key, colorIndex); + } + } else if (key.equals(FACE_MAKEUP_TYPE_SHADOW)) { + if (index == 0) { + currentMakeup.setShadowIntensity(0.0); + } else { + currentMakeup.setShadowBundle(new FUBundleData(itemDir + "mu_style_contour_01.bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_SHADOW + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_SHADOW + "_" + index); + } + currentMakeup.setShadowIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_SHADOW + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_SHADOW + "_" + index); + } + updateCustomColor(key, colorIndex); + } + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_PUPIL)) { + if (index == 0) { + currentMakeup.setPupilIntensity(0.0); + } else { + if (index == 1) { + currentMakeup.setPupilBundle(new FUBundleData(itemDir + "mu_style_eyepupil_01.bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index); + } + currentMakeup.setPupilIntensity((intensity)); + int colorIndex = 3; + if (mCustomColorIndexMap.containsKey(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index)) { + colorIndex = mCustomColorIndexMap.get(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index); + } + updateCustomColor(key, colorIndex); + } else { + currentMakeup.setPupilBundle(new FUBundleData(itemDir + "mu_style_eyepupil_0" + (index + 1) + ".bundle")); + double intensity = 1.0; + if (mCustomIntensityMap.containsKey(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index)) { + intensity = mCustomIntensityMap.get(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + index); + } + currentMakeup.setPupilIntensity((intensity)); + currentMakeup.setPupilColor(buildFUColorRGBData(new double[]{0.0, 0.0, 0.0, 0.0})); + } + + } + } + + } + + + /** + * 设置子妆颜色值 + * + * @param key 类别关键字 + * @param index 颜色下标 + */ + @Override + public void updateCustomColor(String key, int index) { + int current = mCustomIndexMap.containsKey(key) ? mCustomIndexMap.get(key) : 0; + if (key.equals(FACE_MAKEUP_TYPE_LIP_STICK)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_LIP_STICK + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_lip_01").get(index); + if (current == 3) + currentMakeup.setLipColorV2(buildFUColorRGBData(color)); + else + currentMakeup.setLipColor(buildFUColorRGBData(color)); + } else if (key.equals(FACE_MAKEUP_TYPE_BLUSHER)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_BLUSHER + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_blush_0" + current).get(index); + currentMakeup.setBlusherColor(buildFUColorRGBData(color)); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_BROW)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_BROW + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_eyebrow_01").get(index); + currentMakeup.setEyeBrowColor(buildFUColorRGBData(color)); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_SHADOW)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_eyeshadow_0" + current).get(index); + currentMakeup.setEyeShadowColor(new FUColorRGBData(color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255)); + currentMakeup.setEyeShadowColor2(new FUColorRGBData(color[4] * 255, color[5] * 255, color[6] * 255, color[7] * 255)); + currentMakeup.setEyeShadowColor3(new FUColorRGBData(color[8] * 255, color[9] * 255, color[10] * 255, color[11] * 255)); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_LINER)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_LINER + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_eyeliner_0" + current).get(index); + currentMakeup.setEyeLinerColor(buildFUColorRGBData(color)); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_LASH)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_LASH + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_eyelash_0" + current).get(index); + currentMakeup.setEyeLashColor(buildFUColorRGBData(color)); + } else if (key.equals(FACE_MAKEUP_TYPE_HIGH_LIGHT)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_highlight_0" + current).get(index); + currentMakeup.setHighLightColor(buildFUColorRGBData(color)); + } else if (key.equals(FACE_MAKEUP_TYPE_SHADOW)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_SHADOW + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_contour_01").get(index); + currentMakeup.setShadowColor(buildFUColorRGBData(color)); + } else if (key.equals(FACE_MAKEUP_TYPE_EYE_PUPIL)) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + current, index); + double[] color = mMakeUpColorMap.get("color_mu_style_eyepupil_01").get(index); + currentMakeup.setPupilColor(buildFUColorRGBData(color)); + } + } + + + //endregion 子美妆 + + //region 其他 + + /** + * 进入自定义美妆,模型分析 + */ + @Override + public void enterCustomMakeup() { + mCustomIndexMap.clear(); + mCustomColorIndexMap.clear(); + mCustomIntensityMap.clear(); + double makeupIntensity = currentMakeup.getMakeupIntensity(); + /*粉底*/ + if (currentMakeup.getFoundationIntensity() != 0.0) { + double intensity = currentMakeup.getFoundationIntensity() * makeupIntensity; + currentMakeup.setFoundationIntensity(intensity); + double[] array = currentMakeup.getFoundationColor().toScaleColorArray(); + ArrayList list = mMakeUpColorMap.get("color_mu_style_foundation_01"); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(array, list.get(i))) { + mCustomIndexMap.put(FACE_MAKEUP_TYPE_FOUNDATION, i - 2); + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_FOUNDATION + "_" + (i - 2), intensity); + break; + } + } + + } + /*口红*/ + if (currentMakeup.getLipIntensity() != 0.0) { + double intensity = currentMakeup.getLipIntensity() * makeupIntensity; + currentMakeup.setLipIntensity(intensity); + int current = 0; + switch (currentMakeup.getLipType()) { + case MakeupLipEnum.FOG: + if (currentMakeup.getEnableTwoLipColor()) { + current = 5; + } else { + current = 1; + } + break; + case MakeupLipEnum.MOIST: + current = 3; + break; + case MakeupLipEnum.PEARL: + current = 4; + break; + case MakeupLipEnum.WATER: + current = 2; + break; + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_LIP_STICK, current); + if (current != 0) { + double[] colorArray; + if (currentMakeup.getLipType() == MakeupLipEnum.WATER) { + colorArray = currentMakeup.getLipColorV2().toScaleColorArray(); + } else { + colorArray = currentMakeup.getLipColor().toScaleColorArray(); + } + + ArrayList list = mMakeUpColorMap.get("color_mu_style_lip_01"); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_LIP_STICK + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_LIP_STICK + "_" + current, intensity); + } + } + /*腮红*/ + if (currentMakeup.getBlusherIntensity() != 0.0 && currentMakeup.getBlusherBundle() != null) { + double intensity = currentMakeup.getBlusherIntensity() * makeupIntensity; + currentMakeup.setBlusherIntensity(intensity); + String path = currentMakeup.getBlusherBundle().getPath(); + int current = 0; + if (path.endsWith("mu_style_blush_01.bundle")) { + current = 1; + } else if (path.endsWith("mu_style_blush_02.bundle")) { + current = 2; + } else if (path.endsWith("mu_style_blush_03.bundle")) { + current = 3; + } else if (path.endsWith("mu_style_blush_04.bundle")) { + current = 4; + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_BLUSHER, current); + if (current != 0) { + double[] colorArray = currentMakeup.getBlusherColor().toScaleColorArray(); + ArrayList list = mMakeUpColorMap.get("color_mu_style_blush_0" + current); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_BLUSHER + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_BLUSHER + "_" + current, intensity); + } + } + /*眉毛*/ + if (currentMakeup.getEyeBrowIntensity() != 0.0) { + double intensity = currentMakeup.getEyeBrowIntensity() * makeupIntensity; + currentMakeup.setEyeBrowIntensity(intensity); + int current = 0; + if (currentMakeup.getEyeBrowBundle() != null && currentMakeup.getEyeBrowBundle().getPath() != null) { + String bundlePath = currentMakeup.getEyeBrowBundle().getPath(); + int spotIndex = bundlePath.lastIndexOf("."); + String index = bundlePath.substring(spotIndex - 1, spotIndex); + current = Integer.valueOf(index); + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_BROW, current); + if (current != 0) { + double[] colorArray = currentMakeup.getEyeBrowColor().toScaleColorArray(); + ArrayList list = mMakeUpColorMap.get("color_mu_style_eyebrow_01"); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_BROW + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_BROW + "_" + current, intensity); + } + } + /*眼影*/ + if (currentMakeup.getEyeShadowIntensity() != 0.0 && currentMakeup.getEyeShadowBundle() != null) { + double intensity = currentMakeup.getEyeShadowIntensity() * makeupIntensity; + currentMakeup.setEyeShadowIntensity(intensity); + String path = currentMakeup.getEyeShadowBundle().getPath(); + int current = 0; + if (path.endsWith("mu_style_eyeshadow_01.bundle")) { + current = 1; + } else if (path.endsWith("mu_style_eyeshadow_02.bundle")) { + current = 2; + } else if (path.endsWith("mu_style_eyeshadow_03.bundle")) { + current = 3; + } else if (path.endsWith("mu_style_eyeshadow_04.bundle")) { + current = 4; + } else if (path.endsWith("mu_style_eyeshadow_05.bundle")) { + current = 5; + } else if (path.endsWith("mu_style_eyeshadow_06.bundle")) { + current = 6; + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_SHADOW, current); + if (current != 0) { + double[] array = new double[12]; + double[] color1 = currentMakeup.getEyeShadowColor().toScaleColorArray(); + double[] color2 = currentMakeup.getEyeShadowColor2().toScaleColorArray(); + double[] color3 = currentMakeup.getEyeShadowColor3().toScaleColorArray(); + System.arraycopy(color1, 0, array, 0, color1.length); + System.arraycopy(color2, 0, array, 4, color2.length); + System.arraycopy(color3, 0, array, 8, color3.length); + ArrayList list = mMakeUpColorMap.get("color_mu_style_eyeshadow_0" + current); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(array, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_SHADOW + "_" + current, intensity); + } + } + /*眼线*/ + if (currentMakeup.getEyeLineIntensity() != 0.0 && currentMakeup.getEyeLinerBundle() != null) { + double intensity = currentMakeup.getEyeLineIntensity() * makeupIntensity; + currentMakeup.setEyeLineIntensity(intensity); + String path = currentMakeup.getEyeLinerBundle().getPath(); + int current = 0; + if (path.endsWith("mu_style_eyeliner_01.bundle")) { + current = 1; + } else if (path.endsWith("mu_style_eyeliner_02.bundle")) { + current = 2; + } else if (path.endsWith("mu_style_eyeliner_03.bundle")) { + current = 3; + } else if (path.endsWith("mu_style_eyeliner_04.bundle")) { + current = 4; + } else if (path.endsWith("mu_style_eyeliner_05.bundle")) { + current = 5; + } else if (path.endsWith("mu_style_eyeliner_06.bundle")) { + current = 6; + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_LINER, current); + if (current != 0) { + double[] colorArray = currentMakeup.getEyeLinerColor().toScaleColorArray(); + ArrayList list = mMakeUpColorMap.get("color_mu_style_eyeliner_0" + current); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_LINER + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_LINER + "_" + current, intensity); + } + } + /* 睫毛*/ + if (currentMakeup.getEyeLashIntensity() != 0.0 && currentMakeup.getEyeLashBundle() != null) { + double intensity = currentMakeup.getEyeLashIntensity() * makeupIntensity; + currentMakeup.setEyeLashIntensity(intensity); + String path = currentMakeup.getEyeLashBundle().getPath(); + int current = 0; + if (path.endsWith("mu_style_eyelash_01.bundle")) { + current = 1; + } else if (path.endsWith("mu_style_eyelash_02.bundle")) { + current = 2; + } else if (path.endsWith("mu_style_eyelash_03.bundle")) { + current = 3; + } else if (path.endsWith("mu_style_eyelash_04.bundle")) { + current = 4; + } else if (path.endsWith("mu_style_eyelash_05.bundle")) { + current = 5; + } else if (path.endsWith("mu_style_eyelash_06.bundle")) { + current = 6; + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_LASH, current); + if (current != 0) { + double[] colorArray = currentMakeup.getEyeLashColor().toScaleColorArray(); + ArrayList list = mMakeUpColorMap.get("color_mu_style_eyelash_0" + current); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_LASH + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_LASH + "_" + current, intensity); + } + } + /* 高光*/ + if (currentMakeup.getHeightLightIntensity() != 0.0 && currentMakeup.getHighLightBundle() != null) { + double intensity = currentMakeup.getHeightLightIntensity() * makeupIntensity; + currentMakeup.setHeightLightIntensity(intensity); + String path = currentMakeup.getHighLightBundle().getPath(); + int current = 0; + if (path.endsWith("mu_style_highlight_01.bundle")) { + current = 1; + } else if (path.endsWith("mu_style_highlight_02.bundle")) { + current = 2; + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_HIGH_LIGHT, current); + if (current != 0) { + double[] colorArray = currentMakeup.getHighLightColor().toScaleColorArray(); + ArrayList list = mMakeUpColorMap.get("color_mu_style_highlight_0" + current); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_HIGH_LIGHT + "_" + current, intensity); + } + } + /* 阴影*/ + if (currentMakeup.getShadowIntensity() != 0.0 && currentMakeup.getShadowBundle() != null) { + double intensity = currentMakeup.getShadowIntensity() * makeupIntensity; + currentMakeup.setShadowIntensity(intensity); + String path = currentMakeup.getShadowBundle().getPath(); + int current = 0; + if (path.endsWith("mu_style_contour_01.bundle")) { + current = 1; + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_SHADOW, current); + if (current != 0) { + double[] colorArray = currentMakeup.getShadowColor().toScaleColorArray(); + ArrayList list = mMakeUpColorMap.get("color_mu_style_contour_01"); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_SHADOW + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_SHADOW + "_" + current, intensity); + } + } + /* 美瞳*/ + if (currentMakeup.getPupilIntensity() != 0.0 && currentMakeup.getPupilBundle() != null) { + double intensity = currentMakeup.getPupilIntensity() * makeupIntensity; + currentMakeup.setPupilIntensity(intensity); + String path = currentMakeup.getPupilBundle().getPath(); + int current = 0; + if (path.endsWith("mu_style_eyepupil_01.bundle")) { + current = 1; + } else if (path.endsWith("mu_style_eyepupil_03.bundle")) { + current = 2; + } else if (path.endsWith("mu_style_eyepupil_04.bundle")) { + current = 3; + } else if (path.endsWith("mu_style_eyepupil_05.bundle")) { + current = 4; + } else if (path.endsWith("mu_style_eyepupil_06.bundle")) { + current = 5; + } else if (path.endsWith("mu_style_eyepupil_07.bundle")) { + current = 6; + } else if (path.endsWith("mu_style_eyepupil_08.bundle")) { + current = 7; + } else if (path.endsWith("mu_style_eyepupil_09.bundle")) { + current = 8; + } + mCustomIndexMap.put(FACE_MAKEUP_TYPE_EYE_PUPIL, current); + if (current != 0) { + double[] colorArray = currentMakeup.getPupilColor().toScaleColorArray(); + ArrayList list = mMakeUpColorMap.get("color_mu_style_eyepupil_01"); + for (int i = 0; i < list.size(); i++) { + if (DecimalUtils.doubleArrayEquals(colorArray, list.get(i))) { + mCustomColorIndexMap.put(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + current, i); + break; + } + } + mCustomIntensityMap.put(FACE_MAKEUP_TYPE_EYE_PUPIL + "_" + current, intensity); + } + } + currentMakeup.setMakeupIntensity(1.0); + } + + /** + * 或当单项列表当前下标 + * + * @param key + * @return + */ + @Override + public int getCurrentCustomItemIndex(String key) { + if (mCustomIndexMap.containsKey(key)) { + return mCustomIndexMap.get(key); + } + return 0; + } + + /** + * 获取当前单项颜色下标 + * + * @param key + * @param current + * @return + */ + @Override + public int getCurrentCustomColorIndex(String key, int current) { + if (mCustomColorIndexMap.containsKey(key + "_" + current)) { + return mCustomColorIndexMap.get(key + "_" + current); + } + return 3; + } + + /** + * 获取当前单项强度 + * + * @param key + * @param current + * @return + */ + @Override + public double getCurrentCustomIntensity(String key, int current) { + if (mCustomIntensityMap.containsKey(key + "_" + current)) { + return mCustomIntensityMap.get(key + "_" + current); + } + return 1.0; + } + + //endregion + + /** + * FURenderKit加载当前特效 + */ + public void bindCurrentRenderer() { + mFURenderKit.setFaceBeauty(FaceBeautySource.clone(FaceBeautyDataFactory.faceBeauty)); + mFURenderKit.getFaceBeauty().setFilterName(currentFilterName); + mFURenderKit.getFaceBeauty().setFilterIntensity(currentFilterIntensity); + if (!currentMakeup.getControlBundle().getPath().equals(FaceUnityConfig.BUNDLE_FACE_MAKEUP)) + currentMakeup.setFilterIntensity(currentFilterIntensity); + FUAIKit.getInstance().setMaxFaces(4); + mFURenderKit.setMakeup(currentMakeup); + + //特殊有一些需要设置图层混合模式的 04双色眼影3(第2层眼影的混合模式 == 1) 06三色眼影2(第3层眼影的混合模式 == 1) + if (currentMakeup.getEyeShadowBundle() != null && ("mu_style_eyeshadow_0" + 4).equals(currentMakeup.getEyeShadowBundle().getName())) + currentMakeup.setEyeShadowTexBlend2(1); + else if (currentMakeup.getEyeShadowBundle() != null && ("mu_style_eyeshadow_0" + 6).equals(currentMakeup.getEyeShadowBundle().getName())) + currentMakeup.setEyeShadowTexBlend3(1); + + if (FaceUnityConfig.IS_OPEN_LAND_MARK) { + ExpressionRecognition expressionRecognition = new ExpressionRecognition(new FUBundleData(FaceUnityConfig.BUNDLE_LANDMARKS)); + expressionRecognition.setLandmarksType(FUAITypeEnum.FUAITYPE_FACELANDMARKS239); + mFURenderKit.getPropContainer().addProp(expressionRecognition); + } + } + public void clearAll(){ + currentMakeup = new Makeup(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_MAKEUP)); + mFURenderKit.setMakeup(currentMakeup); + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/data/PropDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/data/PropDataFactory.java new file mode 100644 index 000000000..2be22075a --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/data/PropDataFactory.java @@ -0,0 +1,173 @@ +package com.yunbao.faceunity.data; + + +import androidx.annotation.NonNull; + +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.faceunity.FUAIKit; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.model.prop.Prop; +import com.faceunity.core.model.prop.arMask.ARMask; +import com.faceunity.core.model.prop.bigHead.BigHead; +import com.faceunity.core.model.prop.expression.ExpressionRecognition; +import com.faceunity.core.model.prop.faceWarp.FaceWarp; +import com.faceunity.core.model.prop.gesture.GestureRecognition; +import com.faceunity.core.model.prop.sticker.Sticker; +import com.yunbao.faceunity.entity.FunctionEnum; +import com.yunbao.faceunity.entity.PropBean; +import com.yunbao.faceunity.infe.AbstractPropDataFactory; +import com.yunbao.faceunity.repo.PropSource; +import com.yunbao.faceunity.utils.FaceUnityConfig; + +import java.util.ArrayList; + +/** + * DESC:道具业务工厂:道具贴图、AR面具、搞笑大头、表情识别、哈哈镜、手势识别 + * Created on 2021/3/2 + */ +public class PropDataFactory extends AbstractPropDataFactory { + + public interface PropListener { + + void onItemSelected(PropBean bean); + + } + + /*渲染控制器*/ + private final FURenderKit mFURenderKit = FURenderKit.getInstance(); + /*道具列表*/ + private final ArrayList propBeans; + + /*默认选中下标*/ + private int currentPropIndex; + /*当前道具*/ + public Prop currentProp; + /*回调接口*/ + private final PropListener mPropListener; + /*道具类型*/ + private int propType; + + + /** + * @param listener 回调接口 + * @param type 道具类型 + * @param index 默认选中下标 + */ + public PropDataFactory(PropListener listener, int type, int index) { + mPropListener = listener; + propType = type; + currentPropIndex = index; + propBeans = PropSource.buildPropBeans(type); + } + + + /** + * 获取当前选中下标 + * + * @return + */ + @Override + public int getCurrentPropIndex() { + return currentPropIndex; + } + + /** + * 设置当前选中下标 + * + * @param currentPropIndex + */ + @Override + public void setCurrentPropIndex(int currentPropIndex) { + this.currentPropIndex = currentPropIndex; + } + + /** + * 获取道具队列 + * + * @return + */ + @Override + @NonNull + public ArrayList getPropBeans() { + return propBeans; + } + + + /** + * 设置效果 + */ + @Override + public void onItemSelected(PropBean bean) { + onPropSelected(bean); + mPropListener.onItemSelected(bean); + } + + public void setPropType(int propType) { + this.propType = propType; + } + + /** + * 其他道具 + * + * @param bean + */ + private void onPropSelected(PropBean bean) { + String path = bean.getPath(); + if (path == null || path.trim().length() == 0) { + mFURenderKit.getPropContainer().removeAllProp(); + currentProp = null; + return; + } + Prop prop = null; + switch (propType) { + case FunctionEnum.STICKER: + prop = new Sticker(new FUBundleData(path)); + break; + case FunctionEnum.AR_MASK: + prop = new ARMask(new FUBundleData(path)); + break; + case FunctionEnum.BIG_HEAD: + prop = new BigHead(new FUBundleData(path)); + break; + case FunctionEnum.EXPRESSION_RECOGNITION: + prop = new ExpressionRecognition(new FUBundleData(path)); + break; + case FunctionEnum.FACE_WARP: + prop = new FaceWarp(new FUBundleData(path)); + break; + case FunctionEnum.GESTURE_RECOGNITION: + prop = new GestureRecognition(new FUBundleData(path)); + break; + } + mFURenderKit.getPropContainer().replaceProp(currentProp, prop); + currentProp = prop; + } + + + /** + * FURenderKit加载当前特效 + */ + public void bindCurrentRenderer() { + if (propType == FunctionEnum.GESTURE_RECOGNITION) { + FUAIKit.getInstance().loadAIProcessor(FaceUnityConfig.BUNDLE_AI_HAND, FUAITypeEnum.FUAITYPE_HANDGESTURE); + } + if (propType == FunctionEnum.BIG_HEAD) { + FUAIKit.getInstance().setMaxFaces(1); + } else { + FUAIKit.getInstance().setMaxFaces(4); + } + mFURenderKit.setFaceBeauty(FaceBeautyDataFactory.faceBeauty); + PropBean propBean = propBeans.get(currentPropIndex); + onItemSelected(propBean); + } + + /** + * 结束需要释放AI驱动 + */ + public void releaseAIProcessor() { + if (propType == FunctionEnum.GESTURE_RECOGNITION) { + FUAIKit.getInstance().releaseAIProcessor(FUAITypeEnum.FUAITYPE_HANDGESTURE); + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AnimationFilterBean.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AnimationFilterBean.java new file mode 100644 index 000000000..d6bb7b83d --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AnimationFilterBean.java @@ -0,0 +1,58 @@ +package com.yunbao.faceunity.entity; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.data.FaceParam; + +public class AnimationFilterBean extends BaseBean { + private int iconId; + private int style=0; + + public AnimationFilterBean(int iconId, int style) { + this.iconId = iconId; + this.style = style; + } + + public int getStyle() { + return style; + } + + public void setStyle(int style) { + this.style = style; + } + + public int getIconId() { + return iconId; + } + + public void setIconId(int iconId) { + this.iconId = iconId; + } + + @NonNull + @Override + public String getKey() { + return style+""; + } + + @Override + public int getDesRes() { + return 0; + } + + @Override + public int getImageRes() { + return iconId; + } + + @Override + public int getBeanType() { + return FaceParam.FACE_ANIM; + } + + @NonNull + @Override + public ModelAttributeData getModelAttributeData() { + return null; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AnimojiBean.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AnimojiBean.java new file mode 100644 index 000000000..acea3a73a --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AnimojiBean.java @@ -0,0 +1,64 @@ +package com.yunbao.faceunity.entity; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.data.FaceParam; + +/** + * 道具 + * @property iconId Int 图标 + * @property path String? Animoji 道具路径 + * @constructor + */ +public class AnimojiBean extends BaseBean{ + private int iconId; + private String path; + + public AnimojiBean(int iconId, String path) { + this.iconId = iconId; + this.path = path; + } + + public int getIconId() { + return iconId; + } + + public void setIconId(int iconId) { + this.iconId = iconId; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + @NonNull + @Override + public String getKey() { + return path; + } + + @Override + public int getDesRes() { + return 0; + } + + @Override + public int getImageRes() { + return iconId; + } + + @Override + public int getBeanType() { + return FaceParam.FACE_ANIMOJI; + } + + @NonNull + @Override + public ModelAttributeData getModelAttributeData() { + return null; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AvatarBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AvatarBean.kt new file mode 100644 index 000000000..689675f98 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/AvatarBean.kt @@ -0,0 +1,10 @@ +package com.yunbao.faceunity.entity + + +/** + * + * DESC: + * Created on 2020/12/4 + * + */ +data class AvatarBean(val iconId: Int, val des: String) \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BaseBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BaseBean.kt new file mode 100644 index 000000000..16310ea90 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BaseBean.kt @@ -0,0 +1,19 @@ +package com.yunbao.faceunity.entity + +import android.graphics.drawable.Drawable + +abstract class BaseBean { + abstract val key: String + abstract val desRes: Int + abstract val imageRes: Int + abstract val beanType: Int + + abstract fun getModelAttributeData(): ModelAttributeData + + open fun getImageUrl():String { + return ""; + } + open fun getImageDrawable(): Drawable{ + return null!! + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenBackgroundBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenBackgroundBean.kt new file mode 100644 index 000000000..f7807e753 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenBackgroundBean.kt @@ -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) \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenBean.kt new file mode 100644 index 000000000..f2c3654f5 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenBean.kt @@ -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//切换按钮,切换整个按钮功能 + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenSafeAreaBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenSafeAreaBean.kt new file mode 100644 index 000000000..fc5a1f18a --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BgSegGreenSafeAreaBean.kt @@ -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,//不选择按钮 + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BodyBeautyBean.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BodyBeautyBean.java new file mode 100644 index 000000000..b561f9dbf --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/BodyBeautyBean.java @@ -0,0 +1,75 @@ +package com.yunbao.faceunity.entity; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.data.FaceParam; +import com.yunbao.faceunity.repo.BodyBeautySource; + +import java.util.Objects; + +/** + * DESC:美体 + * Created on 2021/4/26 + */ +public class BodyBeautyBean extends BaseBean { + private String key;//名称标识 + private int desRes;//描述 + private int closeRes;//图片 + private int openRes;//图片 + + public BodyBeautyBean(String key, int desRes, int closeRes, int openRes) { + this.key = key; + this.desRes = desRes; + this.closeRes = closeRes; + this.openRes = openRes; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public int getDesRes() { + return desRes; + } + + public void setDesRes(int desRes) { + this.desRes = desRes; + } + + public int getCloseRes() { + return closeRes; + } + + public void setCloseRes(int closeRes) { + this.closeRes = closeRes; + } + + public int getOpenRes() { + return openRes; + } + + public void setOpenRes(int openRes) { + this.openRes = openRes; + } + + @Override + public int getImageRes() { + return closeRes; + } + + @Override + public int getBeanType() { + return FaceParam.FACE_BEAUTY_BODY; + } + + @NonNull + @Override + public ModelAttributeData getModelAttributeData() { + return Objects.requireNonNull(BodyBeautySource.buildModelAttributeRange().get(key)); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyBean.kt new file mode 100644 index 000000000..c54d1aefa --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyBean.kt @@ -0,0 +1,86 @@ +package com.yunbao.faceunity.entity + +import com.yunbao.faceunity.data.FaceParam +import com.yunbao.faceunity.repo.FaceBeautySource + + +/** + * + * @property key String 名称标识 + * @property desRes Int 描述 + * @property closeRes Int 图片 + * @property openRes Int 图片 + * @property buttonType 按钮类型 + * @constructor + */ +data class FaceBeautyBean( + override val key: String, + override val desRes: Int, + val closeRes: Int, + val openRes: Int, + val toastDesRes: Int, + val canUseFunction: Boolean = true, + val buttonType: ButtonType = ButtonType.NORMAL_BUTTON//定义一项按钮功能 普通按钮 返回按钮 子项按钮 + , override val beanType: Int + , override val imageRes: Int +) : BaseBean() { + constructor(key: String, desRes: Int, closeRes: Int, openRes: Int) : this( + key, + desRes, + closeRes, + openRes, + 0, + true, + ButtonType.NORMAL_BUTTON, + FaceParam.FACE_BEAUTY_SKIN, + closeRes + ) + + constructor( + key: String, + desRes: Int, + closeRes: Int, + openRes: Int, + toastDesRes: Int, + canUseFunction: Boolean + ) : this( + key, + desRes, + closeRes, + openRes, + toastDesRes, + canUseFunction, + ButtonType.NORMAL_BUTTON, + FaceParam.FACE_BEAUTY_SKIN, + closeRes + ) + constructor( + key: String, + desRes: Int, + closeRes: Int, + openRes: Int, + toastDesRes: Int, + canUseFunction: Boolean, + type:Int + ):this( + key, + desRes, + closeRes, + openRes, + toastDesRes, + canUseFunction, + ButtonType.NORMAL_BUTTON, + type, + closeRes + ) + + enum class ButtonType { + NORMAL_BUTTON, + BACK_BUTTON, + SUB_ITEM_BUTTON + } + + override fun getModelAttributeData(): ModelAttributeData { + return FaceBeautySource.buildModelAttributeRange()?.get(key)!! + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyFilterBean.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyFilterBean.java new file mode 100644 index 000000000..4cb9d2a99 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyFilterBean.java @@ -0,0 +1,79 @@ +package com.yunbao.faceunity.entity; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.data.FaceParam; + +/** + * DESC:美颜滤镜 + * Created on 2021/4/26 + */ +public class FaceBeautyFilterBean extends BaseBean { + + private String key;//名称标识 + private int imageRes;//图片 + private int desRes;//描述 + private double intensity = 0.4;//强度 + + public FaceBeautyFilterBean(String key, int imageRes, int desRes) { + this.key = key; + this.imageRes = imageRes; + this.desRes = desRes; + } + + public FaceBeautyFilterBean(String key, int imageRes, int desRes, double intensity) { + this.key = key; + this.imageRes = imageRes; + this.desRes = desRes; + this.intensity = intensity; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public int getImageRes() { + return imageRes; + } + + public void setImageRes(int imageRes) { + this.imageRes = imageRes; + } + + @Override + public int getDesRes() { + return desRes; + } + + public void setDesRes(int desRes) { + this.desRes = desRes; + } + + public double getIntensity() { + return intensity; + } + + public void setIntensity(double intensity) { + this.intensity = intensity; + } + + + @NonNull + @Override + public ModelAttributeData getModelAttributeData() { + return null; + } + + @Override + public int getBeanType() { + + return FaceParam.FACE_BEAUTY_FILTER; + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyStyleBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyStyleBean.kt new file mode 100644 index 000000000..9462ce709 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FaceBeautyStyleBean.kt @@ -0,0 +1,21 @@ +package com.yunbao.faceunity.entity + +/** + * 滤镜 + * @property key String 名称标识 + * @property imageRes Int 图片 + * @property desRes Int 描述 + * @constructor + */ +data class FaceBeautyStyleBean( + override val key: String, + override val imageRes: Int, + override val desRes: Int, + override val beanType:Int, + ): + BaseBean(){ + override fun getModelAttributeData(): ModelAttributeData { + return null!! + } + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FunctionEnum.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FunctionEnum.java new file mode 100644 index 000000000..b1b609ebc --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/FunctionEnum.java @@ -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; +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/LightMakeupBean.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/LightMakeupBean.java new file mode 100644 index 000000000..96f0561ec --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/LightMakeupBean.java @@ -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; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCombinationBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCombinationBean.kt new file mode 100644 index 000000000..2b4c7bd34 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCombinationBean.kt @@ -0,0 +1,43 @@ +package com.yunbao.faceunity.entity + + +/** + * + * @property key String 名称标识 + * @property type TypeEnum 类型 + * @property imageRes Int 图片 + * @property desRes Int 描述 + * @property bundlePath FUBundleData 资源句柄 + * @property jsonPath String 参数配置路径 + * @property filterName Double 滤镜 + * @property filterIntensity Double 滤镜强度 + * @property filterScale Double scale 标准滤镜比率 + * @property intensity Double 强度 + * @property jsonPathParams Double 参数配置缓存 + * @constructor + */ +data class MakeupCombinationBean @JvmOverloads constructor( + override val key: String, + val type: TypeEnum, + override val imageRes: Int, + override val desRes: Int, + val bundlePath: String?, + val jsonPath: String, + val filterName: String, + var filterScale: Double = 1.0, + var filterIntensity: Double = 0.7, + var intensity: Double = 0.7, + var jsonPathParams: LinkedHashMap? = null, + override val beanType: Int +): BaseBean() { + enum class TypeEnum { + TYPE_NONE, //无 + TYPE_DAILY,//日常妆,支持自定义 + TYPE_THEME_SUB,//主题妆_依附于face_makeup + TYPE_THEME_MAIN,//主题妆_替换face_makeup + } + + override fun getModelAttributeData(): ModelAttributeData { + return null!! + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCustomBean.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCustomBean.java new file mode 100644 index 000000000..dbc4ce688 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCustomBean.java @@ -0,0 +1,90 @@ +package com.yunbao.faceunity.entity; + +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +/** + * + * @property nameRes Int 名称 + * @property drawable Drawable 图片资源 + * @property doubleArray ArrayList? 颜色数组 + * @constructor + */ +public class MakeupCustomBean extends BaseBean{ + private int nameRes; + private Drawable drawable; + private ArrayList doubleArray; + private int beanType; + + public MakeupCustomBean(int nameRes, Drawable drawable, ArrayList doubleArray,int beanType) { + this.nameRes = nameRes; + this.drawable = drawable; + this.doubleArray = doubleArray; + this.beanType=beanType; + } + + + public MakeupCustomBean(int nameRes, Drawable drawable,int beanType) { + this.nameRes = nameRes; + this.drawable = drawable; + this.beanType=beanType; + } + + public int getNameRes() { + return nameRes; + } + + public void setNameRes(int nameRes) { + this.nameRes = nameRes; + } + + public Drawable getDrawable() { + return drawable; + } + + public void setDrawable(Drawable drawable) { + this.drawable = drawable; + } + + public ArrayList getDoubleArray() { + return doubleArray; + } + + public void setDoubleArray(ArrayList doubleArray) { + this.doubleArray = doubleArray; + } + + @Override + public String getKey() { + return nameRes+""; + } + + @Override + public int getDesRes() { + return nameRes; + } + + @Override + public int getImageRes() { + return 0; + } + + @NonNull + @Override + public Drawable getImageDrawable() { + return drawable; + } + + @Override + public int getBeanType() { + return beanType; + } + + @NonNull + @Override + public ModelAttributeData getModelAttributeData() { + return null; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCustomClassBean.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCustomClassBean.java new file mode 100644 index 000000000..86fdcd44b --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MakeupCustomClassBean.java @@ -0,0 +1,43 @@ +package com.yunbao.faceunity.entity; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.data.FaceParam; + +public class MakeupCustomClassBean extends BaseBean{ + private int nameRes; + private String key; + private int beanType; + + public MakeupCustomClassBean(int nameRes, String key, int beanType) { + this.nameRes = nameRes; + this.key = key; + this.beanType = beanType; + } + + @Override + public String getKey() { + return key; + } + + @Override + public int getDesRes() { + return nameRes; + } + + @Override + public int getImageRes() { + return 0; + } + + @Override + public int getBeanType() { + return beanType; + } + + @NonNull + @Override + public ModelAttributeData getModelAttributeData() { + return null; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MenuGroupBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MenuGroupBean.kt new file mode 100644 index 000000000..c9e885741 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/MenuGroupBean.kt @@ -0,0 +1,3 @@ +package com.yunbao.faceunity.entity + +data class MenuGroupBean(val titleId :Int,val iconId:Int) \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/ModelAttributeData.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/ModelAttributeData.kt new file mode 100644 index 000000000..7bbd2e3c9 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/ModelAttributeData.kt @@ -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) \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/PropBean.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/PropBean.java new file mode 100644 index 000000000..7e8625f06 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/PropBean.java @@ -0,0 +1,85 @@ +package com.yunbao.faceunity.entity; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.data.FaceParam; + +/** + * 道具 + * @property iconId Int 图标 + * @property path String 道具路径 + * @property descId Int 道具提示 + * @constructor + */ +public class PropBean extends BaseBean { + private int iconId; + private String path; + private int descId; + private int beanType; + + public PropBean(int iconId, String path,int beanType) { + this.iconId = iconId; + this.path = path; + this.beanType=beanType; + } + + public PropBean(int iconId, String path, int descId,int beanType) { + this.iconId = iconId; + this.path = path; + this.descId = descId; + this.beanType=beanType; + } + + public int getIconId() { + return iconId; + } + + public void setIconId(int iconId) { + this.iconId = iconId; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public int getDescId() { + return descId; + } + + public void setDescId(int descId) { + this.descId = descId; + } + + @NonNull + @Override + public String getKey() { + return path; + } + + @Override + public int getDesRes() { + return descId; + } + + @Override + public int getImageRes() { + return iconId; + } + + @Override + public int getBeanType() { + return beanType; + } + + @NonNull + @Override + public ModelAttributeData getModelAttributeData() { + return null; + } + + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/PropCustomBean.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/PropCustomBean.kt new file mode 100644 index 000000000..3f35a8800 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/PropCustomBean.kt @@ -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 +) \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/net/FineStickerEntity.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/net/FineStickerEntity.java new file mode 100644 index 000000000..fa520afc7 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/net/FineStickerEntity.java @@ -0,0 +1,328 @@ +package com.yunbao.faceunity.entity.net; + + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.data.FaceParam; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.entity.ModelAttributeData; + +import java.util.ArrayList; + +/** + * @author Qinyu on 2021-03-17 + * @description + */ +public class FineStickerEntity { + /** + * count : 2 + * docs : [{"_id":"6051a0aa6d670000230030c7","index":1,"tool":{"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}},"platform":"mobile","tag":"中级道具"},{"_id":"6051a2d36d670000230030c8","index":2,"tool":{"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}},"platform":"mobile","tag":"中级道具"}] + */ + + private int count; + private ArrayList docs; + private boolean isOnline; //手动设置 + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public ArrayList getDocs() { + return docs; + } + + public void setDocs(ArrayList docs) { + this.docs = docs; + } + + public boolean isOnline() { + return isOnline; + } + + public void setOnline(boolean online) { + isOnline = online; + } + + public static class DocsBean extends BaseBean { + /** + * _id : 6051a0aa6d670000230030c7 + * index : 1 + * tool : {"_id":"5f6ae24e570100009e006547","bundle":{"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"},"icon":{"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"}} + * platform : mobile + * tag : 中级道具 + */ + + private String _id; + private int index; + private ToolBean tool; + private String platform; + private String tag; + + private String filePath; //原始下载来的文件的存储地址,手动设置 + private ArrayList upZipFilePath;//解压的文件位置(绝对路径),手动设置 + private boolean isDownloading; //手动设置 + +// public Effect cast2Effect() { +// return new Effect(tool.bundle.name, 0, filePath, 1, Effect.EFFECT_TYPE_STICKER, 0); +// } + + public String get_id() { + return _id; + } + + public void set_id(String _id) { + this._id = _id; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public ToolBean getTool() { + return tool; + } + + public void setTool(ToolBean tool) { + this.tool = tool; + } + + public String getPlatform() { + return platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public ArrayList getUnZipFilePaths() { + return upZipFilePath; + } + + public void setUpZipFilePaths(ArrayList paths) { + upZipFilePath = paths; + } + + public boolean isDownloading() { + return isDownloading; + } + + public void setDownloading(boolean downloading) { + isDownloading = downloading; + } + + @NonNull + @Override + public String getKey() { + return _id; + } + + @Override + public int getDesRes() { + return 0; + } + + @Override + public int getImageRes() { + return 0; + } + + @Override + public String getImageUrl() { + if(tool==null||tool.getIcon()==null){ + return ""; + } + return tool.getIcon().getUrl(); + } + + @Override + public int getBeanType() { + return FaceParam.FACE_FINE_STICKER; + } + + @NonNull + @Override + public ModelAttributeData getModelAttributeData() { + return null; + } + + public static class ToolBean { + /** + * _id : 5f6ae24e570100009e006547 + * bundle : {"remark":"优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持","uid":"0a176380-b33e-11e9-8e6a-35012f229fc1.bundle","size":3872.85,"name":"hez_ztt_fu.bundle"} + * icon : {"remark":"v1.0","uid":"167f72e0-e173-11e8-b908-51298abcbcf5.png","size":61.83,"name":"hez_ztt_fu.png","url":"http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D"} + */ + + private String _id; + private BundleBean bundle; + private IconBean icon; + private String adapter; + private String category; + + public String get_id() { + return _id; + } + + public void set_id(String _id) { + this._id = _id; + } + + public BundleBean getBundle() { + return bundle; + } + + public void setBundle(BundleBean bundle) { + this.bundle = bundle; + } + + public IconBean getIcon() { + return icon; + } + + public void setIcon(IconBean icon) { + this.icon = icon; + } + + public String getAdapter() { + return adapter; + } + + public void setAdapter(String adapter) { + this.adapter = adapter; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public static class BundleBean { + /** + * remark : 优化背景分割,提高边缘稳定性,需要SDK v6.2.0支持 + * uid : 0a176380-b33e-11e9-8e6a-35012f229fc1.bundle + * size : 3872.85 + * name : hez_ztt_fu.bundle + */ + + private String remark; + private String uid; + private double size; + private String name; + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public double getSize() { + return size; + } + + public void setSize(double size) { + this.size = size; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class IconBean { + /** + * remark : v1.0 + * uid : 167f72e0-e173-11e8-b908-51298abcbcf5.png + * size : 61.83 + * name : hez_ztt_fu.png + * url : http://tools-manage.oss-cn-hangzhou.aliyuncs.com/167f72e0-e173-11e8-b908-51298abcbcf5.png?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1616057194&Signature=4aesuhXnenASOXCQwl0logppBM4%3D + */ + + private String remark; + private String uid; + private double size; + private String name; + private String url; + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public double getSize() { + return size; + } + + public void setSize(double size) { + this.size = size; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + } + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/entity/net/FineStickerTagEntity.java b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/net/FineStickerTagEntity.java new file mode 100644 index 000000000..0ba8893ad --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/entity/net/FineStickerTagEntity.java @@ -0,0 +1,29 @@ +package com.yunbao.faceunity.entity.net; + +/** + * Created on 2021/3/31 0031 16:12. + * Author: xloger + * Email:phoenix@xloger.com + */ +public class FineStickerTagEntity { + private String tag; + + public FineStickerTagEntity(String tag) { + this.tag = tag; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + @Override + public String toString() { + return "FineStickerTagEntity{" + + "tag='" + tag + '\'' + + '}'; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractAnimojiDataFactory.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractAnimojiDataFactory.kt new file mode 100644 index 000000000..3aa8a98f0 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractAnimojiDataFactory.kt @@ -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 + + /* 当前选中滤镜下标 */ + abstract var currentFilterIndex: Int + + /* 滤镜队列 */ + abstract val filters: ArrayList + + abstract fun onAnimojiSelected(data: AnimojiBean) + + abstract fun onFilterSelected(data: AnimationFilterBean) + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractAvatarDataFactory.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractAvatarDataFactory.kt new file mode 100644 index 000000000..9f4211f80 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractAvatarDataFactory.kt @@ -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 + + /** + * 默认选中人物下标 + */ + abstract var currentMemberIndex: Int + + /** + * true 全身、 false 半身 驱动切换 + */ + abstract var isHumanTrackSceneFull: Boolean + + /** + * 当前人物选中 + * @param bean AvatarBean + */ + abstract fun onMemberSelected(bean:AvatarBean) + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractBgSegGreenDataFactory.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractBgSegGreenDataFactory.kt new file mode 100644 index 000000000..e4c07e605 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractBgSegGreenDataFactory.kt @@ -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 + + /* 绿幕抠像功能列表 */ + abstract val bgSegGreenActions: ArrayList + + /* 绿幕抠图安全区域功能列表*/ + abstract val bgSegGreenSafeAreas: ArrayList + + /* 安全区域下标 */ + abstract var bgSafeAreaIndex: Int + + /* 刷新安全区域UI */ + abstract fun updateSafeAreaBeansAndIndex() :Boolean + + /* 绿幕抠像背景列表 */ + abstract val bgSegGreenBackgrounds: ArrayList + + /* 绿幕抠像当前背景下标 */ + 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) + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractBodyBeautyDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractBodyBeautyDataFactory.java new file mode 100644 index 000000000..afa20fd4d --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractBodyBeautyDataFactory.java @@ -0,0 +1,55 @@ +package com.yunbao.faceunity.infe; + + +import com.yunbao.faceunity.entity.BodyBeautyBean; +import com.yunbao.faceunity.entity.ModelAttributeData; + +import java.util.ArrayList; +import java.util.HashMap; + + +/** + * DESC:数据构造工厂抽象类 + * Created on 2021/4/26 + */ +public abstract class AbstractBodyBeautyDataFactory { + + + /** + * 获取美体参数集合 + * @return + */ + public abstract ArrayList getBodyBeautyParam(); + + + + /** + * 获取美体项目数据扩展模型 + * @return + */ + public abstract HashMap getModelAttributeRange(); + + + /** + * 根据名称标识获取对应的值 + * + * @param key String 标识 + * @return Double 值 + */ + public abstract double getParamIntensity(String key); + + /** + * 根据名称标识更新对应的值 + * + * @param key String 标识 + * @return Double 值 + */ + public abstract void updateParamIntensity(String key, double value); + + /** + * 美体开关 + * + * @param enable Boolean + */ + public abstract void enableBodyBeauty(boolean enable); +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractFaceBeautyDataFactory.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractFaceBeautyDataFactory.kt new file mode 100644 index 000000000..166018fac --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractFaceBeautyDataFactory.kt @@ -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 + + /*美型底部菜单数据*/ + abstract val shapeBeauty: ArrayList + + /*美型脸型子项数据*/ + abstract val shapeBeautySubItem: ArrayList + + /* 滤镜底部菜单数据*/ + abstract val beautyFilters: ArrayList + + /* 风格底部菜单数据*/ + abstract val beautyStyles: ArrayList + + /*系统推荐配置滤镜对应下标*/ + abstract var currentFilterIndex: Int + + /* 美颜项目数据扩展模型 */ + abstract val modelAttributeRange: HashMap + + /*系统风格对应下标*/ + 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) + + /** + * 获取当前脸型的UI值 + */ + abstract fun getCurrentFaceShapeUIValue() :HashMap + + /** + * 设置单项强度 + * @param key String + * @param value Double + */ + abstract fun updateParamIntensity(key: String, value: Double) + + /** + * 将所有效果置空 -> 变成标准值 + */ + abstract fun resetParamIntensity() +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractFineStickerDataFactory.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractFineStickerDataFactory.kt new file mode 100644 index 000000000..610a92c35 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractFineStickerDataFactory.kt @@ -0,0 +1,22 @@ +package com.yunbao.faceunity.infe + + +import com.yunbao.faceunity.entity.net.FineStickerEntity +import com.yunbao.faceunity.entity.net.FineStickerTagEntity + +/** + * Created on 2021/3/31 0031 15:27. + * Author: xloger + * Email:phoenix@xloger.com + */ +abstract class AbstractFineStickerDataFactory { + /*切换道具*/ + abstract fun onItemSelected(bean: FineStickerEntity.DocsBean?) + /*获取标签列表*/ + abstract fun loadTagList(): List + /*获取道具列表*/ + abstract fun loadStickerList(tag: FineStickerTagEntity): FineStickerEntity? + /*下载道具*/ + abstract fun downloadSticker(docsBean: FineStickerEntity.DocsBean) + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractLightMakeupDataFactory.java b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractLightMakeupDataFactory.java new file mode 100644 index 000000000..99ea19923 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractLightMakeupDataFactory.java @@ -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 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 getLightMakeUpBeans() { + return lightMakeUpBeans; + } + + public void setLightMakeUpBeans(ArrayList lightMakeUpBeans) { + this.lightMakeUpBeans = lightMakeUpBeans; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractMakeupDataFactory.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractMakeupDataFactory.kt new file mode 100644 index 000000000..6fe3b0526 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractMakeupDataFactory.kt @@ -0,0 +1,93 @@ +package com.yunbao.faceunity.infe + + +import com.yunbao.faceunity.entity.MakeupCombinationBean +import com.yunbao.faceunity.entity.MakeupCustomBean +import com.yunbao.faceunity.entity.MakeupCustomClassBean + + +/** + * + * DESC: + * Created on 2020/12/22 + * + */ +abstract class AbstractMakeupDataFactory { + + /* 默认组合妆容下标 */ + abstract var currentCombinationIndex: Int + + /* 美妆组合妆容配置 */ + abstract val makeupCombinations: ArrayList + + /** + * 组合妆容选中 + * @param bean MakeupCombinationBean + */ + abstract fun onMakeupCombinationSelected(bean: MakeupCombinationBean) + + /** + * 设置美妆整体强度 + * @param intensity Double + */ + abstract fun updateCombinationIntensity(intensity: Double) + + /** + * 进入自定义美妆 + */ + abstract fun enterCustomMakeup() + + /** + * 设置美妆单项强度 + * @param key String 单项key + * @param current Int 单项下标 + * @param intensity Double + */ + abstract fun updateCustomItemIntensity(key: String, current: Int, intensity: Double) + + /** + * 更换类别单项 + * @param key String + * @param index Int + */ + abstract fun onCustomBeanSelected(key: String, index: Int) + + /** + * 设置单项颜色 + * @param key String + * @param index Int + */ + abstract fun updateCustomColor(key: String, index: Int) + + + /* 美妆功能菜单 */ + abstract val makeupCustomItemParams: LinkedHashMap> + + /* 美妆子项类别 */ + + abstract val makeupCustomClass: ArrayList + + + /** + * 获取美妆单项当前下标 + * @param key String + * @return Int + */ + abstract fun getCurrentCustomItemIndex(key: String): Int + + /** + * 获取美妆当前选中项颜色下标 + * @param key String + * @param current Int + * @return Int + */ + abstract fun getCurrentCustomColorIndex(key: String, current: Int): Int + + /** + * 获取美妆当前选中项强度 + * @param key String + * @param current Int + * @return Double + */ + abstract fun getCurrentCustomIntensity(key: String, current: Int): Double +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractPropCustomDataFactory.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractPropCustomDataFactory.kt new file mode 100644 index 000000000..571ed324f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractPropCustomDataFactory.kt @@ -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 + + + /** + * 道具选中 + * @param bean StickerBean + */ + abstract fun onItemSelected(bean: PropCustomBean) + + + /** + * 道具选中 + */ + abstract fun onAddPropCustomBeanClick() + + + companion object { + const val TYPE_NONE = -1 + const val TYPE_ADD = -99 + } + + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractPropDataFactory.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractPropDataFactory.kt new file mode 100644 index 000000000..e81be3240 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/infe/AbstractPropDataFactory.kt @@ -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 + + + /** + * 道具选中 + * @param bean StickerBean + */ + abstract fun onItemSelected(bean: PropBean) + + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/listener/FURendererListener.java b/FaceUnity/src/main/java/com/yunbao/faceunity/listener/FURendererListener.java new file mode 100644 index 000000000..41b6e25ef --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/listener/FURendererListener.java @@ -0,0 +1,40 @@ +package com.yunbao.faceunity.listener; + +import com.faceunity.core.enumeration.FUAIProcessorEnum; + +/** + * DESC:FURenderer状态回调监听 + * Created on 2021/4/29 + */ +public interface FURendererListener { + + /** + * prepare完成回调 + */ + void onPrepare(); + + /** + * 识别到的人脸或人体数量发生变化 + * + * @param type 类型 + * @param status 数量 + */ + void onTrackStatusChanged(FUAIProcessorEnum type, int status); + + + /** + * 统计每 10 帧的平均数据,FPS 和渲染函数调用时间 + * + * @param fps FPS + * @param callTime 渲染函数调用时间 + */ + void onFpsChanged(double fps, double callTime); + + + /** + * release完成回调 + */ + void onRelease(); + + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/listener/IFaceModel.java b/FaceUnity/src/main/java/com/yunbao/faceunity/listener/IFaceModel.java new file mode 100644 index 000000000..7ff52c3c7 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/listener/IFaceModel.java @@ -0,0 +1,19 @@ +package com.yunbao.faceunity.listener; + +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.faceunity.FUAIKit; +import com.yunbao.faceunity.utils.FaceUnityConfig; + +/** + * 模块配置 + * @param + */ +public abstract class IFaceModel { + public abstract T Builder(); + + public void apply() { + FUAIKit.getInstance().loadAIProcessor(FaceUnityConfig.BUNDLE_AI_FACE, FUAITypeEnum.FUAITYPE_FACEPROCESSOR); + FUAIKit.getInstance().faceProcessorSetFaceLandmarkQuality(FaceUnityConfig.DEVICE_LEVEL); + } + public abstract void setEnable(boolean enable); +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/AnimojiSource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/AnimojiSource.java new file mode 100644 index 000000000..5cce78374 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/AnimojiSource.java @@ -0,0 +1,59 @@ +package com.yunbao.faceunity.repo; + +import com.faceunity.core.model.animationFilter.AnimationFilterTypeEnum; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.AnimationFilterBean; +import com.yunbao.faceunity.entity.AnimojiBean; + +import java.util.ArrayList; + +/** + * DESC:Animoji数据构造 + * Created on 2021/3/25 + */ +public class AnimojiSource { + + + /** + * 构造贴图数据 + * + * @return + */ + public static ArrayList buildAnimojis() { + ArrayList 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 buildFilters() { + ArrayList 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; + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/AvatarSource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/AvatarSource.java new file mode 100644 index 000000000..1b10d3e0a --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/AvatarSource.java @@ -0,0 +1,160 @@ +package com.yunbao.faceunity.repo; + +import com.faceunity.core.avatar.avatar.Color; +import com.faceunity.core.avatar.avatar.TransForm; +import com.faceunity.core.avatar.model.Avatar; +import com.faceunity.core.avatar.model.Scene; +import com.faceunity.core.entity.FUAnimationData; +import com.faceunity.core.entity.FUAvatarAnimFilterParams; +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.entity.FUColorRGBData; +import com.faceunity.core.entity.FUCoordinate3DData; +import com.faceunity.core.entity.FUTranslationScale; +import com.faceunity.core.entity.FUVisibleBundleData; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.AvatarBean; + +import java.io.File; +import java.util.ArrayList; + +/** + * DESC:Avatar数据构造 + * Created on 2021/3/30 + */ +public class AvatarSource { + // Avatar + private static String BUNDLE_AVATAR_CONTROLLER = "graphics" + File.separator + "controller_cpp.bundle"; + private static String BUNDLE_AVATAR_CONFIG = "pta" + File.separator + "controller_config.bundle"; + private static String BUNDLE_AVATAR_BACKGROUND = "pta" + File.separator + "default_bg.bundle"; + + public static String BOY = "boy"; + public static String GIRL = "girl"; + + /** + * 构造成员列表 + * + * @return + */ + public static ArrayList buildMembers() { + ArrayList 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 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 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 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 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 strComponents, ArrayList strAnimations) { + ArrayList 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 buildAnimations() { + String animDir = "pta/gesture/"; + ArrayList 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); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/BgSegGreenSource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/BgSegGreenSource.java new file mode 100644 index 000000000..0ec4f2c6f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/BgSegGreenSource.java @@ -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 + */ + public static HashMap buildModelAttributeRange() { + HashMap params = new HashMap(); + 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 buildBgSegGreenAction() { + ArrayList actions = new ArrayList(); + 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 buildBgSegGreenSafeArea() { + String fileDir = "bg_seg_green" + File.separator + "sample" + File.separator; + ArrayList safeAreaBeans = new ArrayList(); + 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 buildBgSegGreenBackground() { + ArrayList 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, ""); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/BodyBeautySource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/BodyBeautySource.java new file mode 100644 index 000000000..5a343b2b3 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/BodyBeautySource.java @@ -0,0 +1,56 @@ +package com.yunbao.faceunity.repo; + +import com.faceunity.core.controller.bodyBeauty.BodyBeautyParam; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.entity.BodyBeautyBean; +import com.yunbao.faceunity.entity.ModelAttributeData; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; + + +/** + * DESC:美体数据构造 + * Created on 2021/3/26 + */ +public class BodyBeautySource { + + public static final String BUNDLE_BODY_BEAUTY = "graphics" + File.separator + "body_slim.bundle"; + + + /** + * 构造美体 + * + * @return + */ + public static ArrayList buildBodyBeauty() { + ArrayList params = new ArrayList<>(); + params.add(new BodyBeautyBean(BodyBeautyParam.BODY_SLIM_INTENSITY, R.string.slimming, R.drawable.icon_body_slimming_close_selector, R.drawable.icon_body_slimming_open_selector)); + params.add(new BodyBeautyBean(BodyBeautyParam.LEG_STRETCH_INTENSITY, R.string.long_legs, R.drawable.icon_body_stovepipe_close_selector, R.drawable.icon_body_stovepipe_open_selector)); + params.add(new BodyBeautyBean(BodyBeautyParam.WAIST_SLIM_INTENSITY, R.string.thin_waist, R.drawable.icon_body_waist_close_selector, R.drawable.icon_body_waist_open_selector)); + params.add(new BodyBeautyBean(BodyBeautyParam.SHOULDER_SLIM_INTENSITY, R.string.beautify_shoulder, R.drawable.icon_body_shoulder_close_selector, R.drawable.icon_body_shoulder_open_selector)); + params.add(new BodyBeautyBean(BodyBeautyParam.HIP_SLIM_INTENSITY, R.string.beautify_hip_slim, R.drawable.icon_body_hip_close_selector, R.drawable.icon_body_hip_open_selector)); + params.add(new BodyBeautyBean(BodyBeautyParam.HEAD_SLIM_INTENSITY, R.string.beautify_head_slim, R.drawable.icon_body_little_head_close_selector, R.drawable.icon_body_little_head_open_selector)); + params.add(new BodyBeautyBean(BodyBeautyParam.LEG_SLIM_INTENSITY, R.string.beautify_leg_thin_slim, R.drawable.icon_body_thin_leg_close_selector, R.drawable.icon_body_thin_leg_open_selector)); + return params; + } + + /** + * 获取模型属性扩展数据 + * + * @return HashMap + */ + public static HashMap buildModelAttributeRange() { + HashMap params = new HashMap<>(); + params.put(BodyBeautyParam.BODY_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(BodyBeautyParam.LEG_STRETCH_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(BodyBeautyParam.WAIST_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(BodyBeautyParam.SHOULDER_SLIM_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0)); + params.put(BodyBeautyParam.HIP_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(BodyBeautyParam.HEAD_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(BodyBeautyParam.LEG_SLIM_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + return params; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/FaceBeautySource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/FaceBeautySource.java new file mode 100644 index 000000000..3b9895478 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/FaceBeautySource.java @@ -0,0 +1,761 @@ +package com.yunbao.faceunity.repo; + + +import com.faceunity.core.controller.facebeauty.FaceBeautyParam; +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.enumeration.FUFaceBeautyMultiModePropertyEnum; +import com.faceunity.core.enumeration.FUFaceBeautyPropertyModeEnum; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.model.facebeauty.FaceBeauty; +import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.data.FaceBeautyData; +import com.yunbao.faceunity.data.FaceBeautyDataFactory; +import com.yunbao.faceunity.data.FaceParam; +import com.yunbao.faceunity.entity.FaceBeautyBean; +import com.yunbao.faceunity.entity.FaceBeautyFilterBean; +import com.yunbao.faceunity.entity.FaceBeautyStyleBean; +import com.yunbao.faceunity.entity.ModelAttributeData; +import com.yunbao.faceunity.utils.FUUtils; +import com.yunbao.faceunity.utils.FaceUnityConfig; +import com.yunbao.faceunity.utils.FuDeviceUtils; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * DESC:美颜数据构造 + * Created on 2021/3/27 + */ +public class FaceBeautySource { + + private static ArrayList filters = new ArrayList<>(); + private static FaceBeautyData faceBeautyData; + + /** + * 获取默认推荐美颜模型 + * 一个app生命周期请求一次 + * + * @return + */ + public static FaceBeauty getDefaultFaceBeauty() { + FaceBeauty recommendFaceBeauty = new FaceBeauty(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_BEAUTIFICATION)); + if (FaceUnityConfig.OPEN_FACE_BEAUTY_TO_FILE) + faceBeautyData = FUUtils.loadFaceBeautyData(); + if (faceBeautyData != null) { + //有本地缓存 + FaceBeautyDataFactory.setDiskCurrentStyleIndex(faceBeautyData.styleTypeIndex); + FUUtils.setFaceBeauty(faceBeautyData, recommendFaceBeauty); + } else { + //没有本地缓存 + recommendFaceBeauty.setFilterName(FaceBeautyFilterEnum.ZIRAN_2); + recommendFaceBeauty.setFilterIntensity(0.4); + /*美肤*/ + recommendFaceBeauty.setSharpenIntensity(0.2); + recommendFaceBeauty.setColorIntensity(0.3); + recommendFaceBeauty.setRedIntensity(0.3); + recommendFaceBeauty.setBlurIntensity(4.2); + /*美型*/ + recommendFaceBeauty.setFaceShapeIntensity(1.0); + recommendFaceBeauty.setEyeEnlargingIntensity(0.4); + recommendFaceBeauty.setCheekVIntensity(0.5); + recommendFaceBeauty.setNoseIntensity(0.5); + recommendFaceBeauty.setForHeadIntensity(0.3); + recommendFaceBeauty.setMouthIntensity(0.4); + recommendFaceBeauty.setChinIntensity(0.3); + //性能最优策略 + if (FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID) { + setFaceBeautyPropertyMode(recommendFaceBeauty); + } + } + + return recommendFaceBeauty; + } + + /** + * 高端机的时候,开启4个相对吃性能的模式 + * 1.祛黑眼圈 MODE2 + * 2.祛法令纹 MODE2 + * 3.大眼 MODE3 + * 4.嘴型 MODE3 + */ + private static void setFaceBeautyPropertyMode(FaceBeauty faceBeauty) { + /* + * 多模式属性 + * 属性名称|支持模式|默认模式|最早支持版本 + * 美白 colorIntensity|MODE1 MODE2|MODE2|MODE2 8.2.0; + * 祛黑眼圈 removePouchIntensity|MODE1 MODE2|MODE2|MODE2 8.2.0; + * 祛法令纹 removeLawPatternIntensity|MODE1 MODE1|MODE2|MODE2 8.2.0; + * 窄脸程度 cheekNarrowIntensity|MODE1 MODE2|MODE2|MODE2 8.0.0; + * 小脸程度 cheekSmallIntensity|MODE1 MODE2|MODE2|MODE2 8.0.0; + * 大眼程度 eyeEnlargingIntensity|MODE1 MODE2 MODE3|MODE3|MODE2 8.0.0;MODE3 8.2.0; + * 额头调整程度 forHeadIntensity|MODE1 MODE2|MODE2|MODE2 8.0.0; + * 瘦鼻程度 noseIntensity|MODE1 MODE2|MODE2|MODE2 8.0.0; + * 嘴巴调整程度 mouthIntensity|MODE1 MODE2 MODE3|MODE3|MODE2 8.0.0;MODE3 8.2.0; + */ + faceBeauty.addPropertyMode(FUFaceBeautyMultiModePropertyEnum.REMOVE_POUCH_INTENSITY, FUFaceBeautyPropertyModeEnum.MODE2); + faceBeauty.addPropertyMode(FUFaceBeautyMultiModePropertyEnum.REMOVE_NASOLABIAL_FOLDS_INTENSITY, FUFaceBeautyPropertyModeEnum.MODE2); + faceBeauty.addPropertyMode(FUFaceBeautyMultiModePropertyEnum.EYE_ENLARGING_INTENSITY, FUFaceBeautyPropertyModeEnum.MODE3); + faceBeauty.addPropertyMode(FUFaceBeautyMultiModePropertyEnum.MOUTH_INTENSITY, FUFaceBeautyPropertyModeEnum.MODE3); + } + + + /** + * 初始化美肤参数 + * + * @return ArrayList + */ + public static ArrayList buildSkinParams() { + ArrayList params = new ArrayList<>(); + params.add(new FaceBeautyBean( + FaceBeautyParam.BLUR_INTENSITY + , R.string.beauty_box_heavy_blur_fine + , R.drawable.icon_beauty_skin_buffing_close_selector + , R.drawable.icon_beauty_skin_buffing_open_selector + , 0 + , true, + FaceParam.FACE_BEAUTY_SKIN + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.COLOR_INTENSITY, R.string.beauty_box_color_level, + R.drawable.icon_beauty_skin_color_close_selector, R.drawable.icon_beauty_skin_color_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SKIN + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.RED_INTENSITY, R.string.beauty_box_red_level, + R.drawable.icon_beauty_skin_red_close_selector, R.drawable.icon_beauty_skin_red_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SKIN + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.SHARPEN_INTENSITY, R.string.beauty_box_sharpen, + R.drawable.icon_beauty_skin_sharpen_close_selector, R.drawable.icon_beauty_skin_sharpen_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SKIN + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.EYE_BRIGHT_INTENSITY, R.string.beauty_box_eye_bright, + R.drawable.icon_beauty_skin_eyes_bright_close_selector, R.drawable.icon_beauty_skin_eyes_bright_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SKIN + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.TOOTH_WHITEN_INTENSITY, R.string.beauty_box_tooth_whiten, + R.drawable.icon_beauty_skin_teeth_close_selector, R.drawable.icon_beauty_skin_teeth_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SKIN + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.REMOVE_POUCH_INTENSITY, R.string.beauty_micro_pouch, + R.drawable.icon_beauty_skin_dark_circles_close_selector, R.drawable.icon_beauty_skin_dark_circles_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SKIN) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, R.string.beauty_micro_nasolabial, + R.drawable.icon_beauty_skin_wrinkle_close_selector, R.drawable.icon_beauty_skin_wrinkle_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SKIN) + ); + + return params; + } + + /** + * 初始化美型参数 + * + * @return ArrayList + */ + public static ArrayList buildShapeParams() { + ArrayList params = new ArrayList<>(); +// params.add( +// new FaceBeautyBean( +// "", R.string.avatar_face_face, +// R.drawable.icon_beauty_shape_face_shape_close_selector, R.drawable.icon_beauty_shape_face_shape_open_selector, FaceBeautyBean.ButtonType.SUB_ITEM_BUTTON +// ) +// ); + + //瘦脸 + params.add( + new FaceBeautyBean( + FaceBeautyParam.CHEEK_THINNING_INTENSITY, R.string.beauty_box_cheek_thinning, + R.drawable.icon_beauty_shape_face_cheekthin_close_selector, R.drawable.icon_beauty_shape_face_cheekthin_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + + //V脸 + params.add( + new FaceBeautyBean( + FaceBeautyParam.CHEEK_V_INTENSITY, R.string.beauty_box_cheek_v, + R.drawable.icon_beauty_shape_face_v_close_selector, R.drawable.icon_beauty_shape_face_v_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + + //窄脸 + params.add( + new FaceBeautyBean( + FaceBeautyParam.CHEEK_NARROW_INTENSITY, R.string.beauty_box_cheek_narrow, + R.drawable.icon_beauty_shape_face_narrow_close_selector, R.drawable.icon_beauty_shape_face_narrow_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + + //小脸 -> 短脸 --使用的参数是以前小脸的 + params.add( + new FaceBeautyBean( + FaceBeautyParam.CHEEK_SHORT_INTENSITY, R.string.beauty_box_cheek_short, + R.drawable.icon_beauty_shape_face_short_close_selector, R.drawable.icon_beauty_shape_face_short_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + + //小脸 -> 新增 + params.add( + new FaceBeautyBean( + FaceBeautyParam.CHEEK_SMALL_INTENSITY, R.string.beauty_box_cheek_small, + R.drawable.icon_beauty_shape_face_little_close_selector, R.drawable.icon_beauty_shape_face_little_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, R.string.beauty_box_cheekbones, + R.drawable.icon_beauty_shape_cheek_bones_close_selector, R.drawable.icon_beauty_shape_cheek_bones_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, R.string.beauty_box_lower_jaw, + R.drawable.icon_beauty_shape_lower_jaw_close_selector, R.drawable.icon_beauty_shape_lower_jaw_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.EYE_ENLARGING_INTENSITY, R.string.beauty_box_eye_enlarge, + R.drawable.icon_beauty_shape_enlarge_eye_close_selector, R.drawable.icon_beauty_shape_enlarge_eye_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.EYE_CIRCLE_INTENSITY, R.string.beauty_box_eye_circle, + R.drawable.icon_beauty_shape_round_eye_close_selector, R.drawable.icon_beauty_shape_round_eye_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.CHIN_INTENSITY, R.string.beauty_box_intensity_chin, + R.drawable.icon_beauty_shape_chin_close_selector, R.drawable.icon_beauty_shape_chin_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.FOREHEAD_INTENSITY, R.string.beauty_box_intensity_forehead, + R.drawable.icon_beauty_shape_forehead_close_selector, R.drawable.icon_beauty_shape_forehead_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.NOSE_INTENSITY, R.string.beauty_box_intensity_nose, + R.drawable.icon_beauty_shape_thin_nose_close_selector, R.drawable.icon_beauty_shape_thin_nose_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.MOUTH_INTENSITY, R.string.beauty_box_intensity_mouth, + R.drawable.icon_beauty_shape_mouth_close_selector, R.drawable.icon_beauty_shape_mouth_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.CANTHUS_INTENSITY, R.string.beauty_micro_canthus, + R.drawable.icon_beauty_shape_open_eyes_close_selector, R.drawable.icon_beauty_shape_open_eyes_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.EYE_SPACE_INTENSITY, R.string.beauty_micro_eye_space, + R.drawable.icon_beauty_shape_distance_close_selector, R.drawable.icon_beauty_shape_distance_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.EYE_ROTATE_INTENSITY, R.string.beauty_micro_eye_rotate, + R.drawable.icon_beauty_shape_angle_close_selector, R.drawable.icon_beauty_shape_angle_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.LONG_NOSE_INTENSITY, R.string.beauty_micro_long_nose, + R.drawable.icon_beauty_shape_proboscis_close_selector, R.drawable.icon_beauty_shape_proboscis_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.PHILTRUM_INTENSITY, R.string.beauty_micro_philtrum, + R.drawable.icon_beauty_shape_shrinking_close_selector, R.drawable.icon_beauty_shape_shrinking_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.SMILE_INTENSITY, R.string.beauty_micro_smile, + R.drawable.icon_beauty_shape_smile_close_selector, R.drawable.icon_beauty_shape_smile_open_selector, 0 + , true, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.BROW_HEIGHT_INTENSITY, + R.string.beauty_brow_height, + R.drawable.icon_beauty_shape_brow_height_close_selector, + R.drawable.icon_beauty_shape_brow_height_open_selector, + R.string.brow_height_tips, + FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID, + FaceParam.FACE_BEAUTY_SHAPE + + ) + ); + params.add( + new FaceBeautyBean( + FaceBeautyParam.BROW_SPACE_INTENSITY, R.string.beauty_brow_space, + R.drawable.icon_beauty_shape_brow_space_close_selector, R.drawable.icon_beauty_shape_brow_space_open_selector, + R.string.brow_space_tips, FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID, + FaceParam.FACE_BEAUTY_SHAPE + ) + ); + return params; + } + + /** + * 加载脸型子项 + * + * @return + */ + public static ArrayList buildFaceShapeSubItemParams() { + return buildSubItemParams(FaceBeautyParam.FACE_SHAPE); + } + + public static ArrayList buildSubItemParams(String key) { + ArrayList params = new ArrayList<>(); +// if (key != null && !key.isEmpty()) { +// if (key.equals(FaceBeautyParam.FACE_SHAPE)) { +// //返回 +// params.add( +// new FaceBeautyBean( +// "", R.string.back, +// R.mipmap.icon_beauty_back, R.mipmap.icon_beauty_back, FaceBeautyBean.ButtonType.BACK_BUTTON +// ) +// ); +// +// //自然 V脸 -> 自然脸 +// params.add( +// new FaceBeautyBean( +// FaceBeautyParam.CHEEK_V_INTENSITY, R.string.beauty_box_cheek_natural, +// R.drawable.icon_beauty_shape_face_natural_close_selector, R.drawable.icon_beauty_shape_face_natural_open_selector +// ) +// ); +// +// //女神 瘦脸 -> 女神脸 +// params.add( +// new FaceBeautyBean( +// FaceBeautyParam.CHEEK_THINNING_INTENSITY, R.string.beauty_box_cheek_goddess, +// R.drawable.icon_beauty_shape_face_goddess_close_selector, R.drawable.icon_beauty_shape_face_goddess_open_selector +// ) +// ); +// +// //长脸 +// params.add( +// new FaceBeautyBean( +// FaceBeautyParam.CHEEK_LONG_INTENSITY, R.string.beauty_box_cheek_long_face, +// R.drawable.icon_beauty_shape_face_long_close_selector, R.drawable.icon_beauty_shape_face_long_open_selector +// ) +// ); +// +// //圆脸 +// params.add( +// new FaceBeautyBean( +// FaceBeautyParam.CHEEK_CIRCLE_INTENSITY, R.string.beauty_box_cheek_round_face, +// R.drawable.icon_beauty_shape_face_round_close_selector, R.drawable.icon_beauty_shape_face_round_open_selector +// ) +// ); +// } +// } + + return params; + } + + /** + * 初始化参数扩展列表 + * + * @return HashMap + */ + public static HashMap buildModelAttributeRange() { + HashMap params = new HashMap<>(); + /*美肤*/ + params.put(FaceBeautyParam.COLOR_INTENSITY, new ModelAttributeData(0.3, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.BLUR_INTENSITY, new ModelAttributeData(4.2, 0.0, 0.0, 6.0)); + params.put(FaceBeautyParam.RED_INTENSITY, new ModelAttributeData(0.3, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.SHARPEN_INTENSITY, new ModelAttributeData(0.2, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.EYE_BRIGHT_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.TOOTH_WHITEN_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.REMOVE_POUCH_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.REMOVE_NASOLABIAL_FOLDS_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + /*美型*/ + params.put(FaceBeautyParam.FACE_SHAPE_INTENSITY, new ModelAttributeData(1.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.CHEEK_THINNING_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.CHEEK_LONG_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.CHEEK_CIRCLE_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.CHEEK_V_INTENSITY, new ModelAttributeData(0.5, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.CHEEK_NARROW_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.CHEEK_SHORT_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.CHEEK_SMALL_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.INTENSITY_CHEEKBONES_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.INTENSITY_LOW_JAW_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.EYE_ENLARGING_INTENSITY, new ModelAttributeData(0.4, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.EYE_CIRCLE_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.CHIN_INTENSITY, new ModelAttributeData(0.3, 0.5, 0.0, 1.0)); + params.put(FaceBeautyParam.FOREHEAD_INTENSITY, new ModelAttributeData(0.3, 0.5, 0.0, 1.0)); + params.put(FaceBeautyParam.NOSE_INTENSITY, new ModelAttributeData(0.5, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.MOUTH_INTENSITY, new ModelAttributeData(0.4, 0.5, 0.0, 1.0)); + params.put(FaceBeautyParam.CANTHUS_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.EYE_SPACE_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0)); + params.put(FaceBeautyParam.EYE_ROTATE_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0)); + params.put(FaceBeautyParam.LONG_NOSE_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0)); + params.put(FaceBeautyParam.PHILTRUM_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0)); + params.put(FaceBeautyParam.SMILE_INTENSITY, new ModelAttributeData(0.0, 0.0, 0.0, 1.0)); + params.put(FaceBeautyParam.BROW_HEIGHT_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0)); + params.put(FaceBeautyParam.BROW_SPACE_INTENSITY, new ModelAttributeData(0.5, 0.5, 0.0, 1.0)); + return params; + } + + + /** + * 初始化滤镜参数 + * + * @return ArrayList + */ + public static ArrayList buildFilters() { + if (!filters.isEmpty()) { + return filters; + } + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ORIGIN, R.mipmap.icon_beauty_filter_cancel, R.string.origin, 0.0)); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_1, R.mipmap.icon_beauty_filter_natural_1, R.string.ziran_1, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_2, R.mipmap.icon_beauty_filter_natural_2, R.string.ziran_2, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_2))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_3, R.mipmap.icon_beauty_filter_natural_3, R.string.ziran_3, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_4, R.mipmap.icon_beauty_filter_natural_4, R.string.ziran_4, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_4))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_5, R.mipmap.icon_beauty_filter_natural_5, R.string.ziran_5, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_5))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_6, R.mipmap.icon_beauty_filter_natural_6, R.string.ziran_6, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_6))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_7, R.mipmap.icon_beauty_filter_natural_7, R.string.ziran_7, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_7))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZIRAN_8, R.mipmap.icon_beauty_filter_natural_8, R.string.ziran_8, getDiskFilterValue(FaceBeautyFilterEnum.ZIRAN_8))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_1, R.mipmap.icon_beauty_filter_texture_gray_1, R.string.zhiganhui_1, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_2, R.mipmap.icon_beauty_filter_texture_gray_2, R.string.zhiganhui_2, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_2))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_3, R.mipmap.icon_beauty_filter_texture_gray_3, R.string.zhiganhui_3, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_4, R.mipmap.icon_beauty_filter_texture_gray_4, R.string.zhiganhui_4, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_4))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_5, R.mipmap.icon_beauty_filter_texture_gray_5, R.string.zhiganhui_5, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_5))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_6, R.mipmap.icon_beauty_filter_texture_gray_6, R.string.zhiganhui_6, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_6))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_7, R.mipmap.icon_beauty_filter_texture_gray_7, R.string.zhiganhui_7, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_7))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.ZHIGANHUI_8, R.mipmap.icon_beauty_filter_texture_gray_8, R.string.zhiganhui_8, getDiskFilterValue(FaceBeautyFilterEnum.ZHIGANHUI_8))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_1, R.mipmap.icon_beauty_filter_peach_1, R.string.mitao_1, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_2, R.mipmap.icon_beauty_filter_peach_2, R.string.mitao_2, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_2))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_3, R.mipmap.icon_beauty_filter_peach_3, R.string.mitao_3, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_4, R.mipmap.icon_beauty_filter_peach_4, R.string.mitao_4, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_4))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_5, R.mipmap.icon_beauty_filter_peach_5, R.string.mitao_5, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_5))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_6, R.mipmap.icon_beauty_filter_peach_6, R.string.mitao_6, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_6))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_7, R.mipmap.icon_beauty_filter_peach_7, R.string.mitao_7, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_7))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.MITAO_8, R.mipmap.icon_beauty_filter_peach_8, R.string.mitao_8, getDiskFilterValue(FaceBeautyFilterEnum.MITAO_8))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_1, R.mipmap.icon_beauty_filter_bailiang_1, R.string.bailiang_1, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_2, R.mipmap.icon_beauty_filter_bailiang_2, R.string.bailiang_2, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_2))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_3, R.mipmap.icon_beauty_filter_bailiang_3, R.string.bailiang_3, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_4, R.mipmap.icon_beauty_filter_bailiang_4, R.string.bailiang_4, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_4))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_5, R.mipmap.icon_beauty_filter_bailiang_5, R.string.bailiang_5, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_5))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_6, R.mipmap.icon_beauty_filter_bailiang_6, R.string.bailiang_6, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_6))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.BAILIANG_7, R.mipmap.icon_beauty_filter_bailiang_7, R.string.bailiang_7, getDiskFilterValue(FaceBeautyFilterEnum.BAILIANG_7))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_1, R.mipmap.icon_beauty_filter_fennen_1, R.string.fennen_1, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_2, R.mipmap.icon_beauty_filter_fennen_2, R.string.fennen_2, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_2))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_3, R.mipmap.icon_beauty_filter_fennen_3, R.string.fennen_3, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_5, R.mipmap.icon_beauty_filter_fennen_5, R.string.fennen_5, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_5))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_6, R.mipmap.icon_beauty_filter_fennen_6, R.string.fennen_6, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_6))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_7, R.mipmap.icon_beauty_filter_fennen_7, R.string.fennen_7, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_7))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.FENNEN_8, R.mipmap.icon_beauty_filter_fennen_8, R.string.fennen_8, getDiskFilterValue(FaceBeautyFilterEnum.FENNEN_8))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_1, R.mipmap.icon_beauty_filter_lengsediao_1, R.string.lengsediao_1, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_2, R.mipmap.icon_beauty_filter_lengsediao_2, R.string.lengsediao_2, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_2))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_3, R.mipmap.icon_beauty_filter_lengsediao_3, R.string.lengsediao_3, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_4, R.mipmap.icon_beauty_filter_lengsediao_4, R.string.lengsediao_4, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_4))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_7, R.mipmap.icon_beauty_filter_lengsediao_7, R.string.lengsediao_7, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_7))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_8, R.mipmap.icon_beauty_filter_lengsediao_8, R.string.lengsediao_8, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_8))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.LENGSEDIAO_11, R.mipmap.icon_beauty_filter_lengsediao_11, R.string.lengsediao_11, getDiskFilterValue(FaceBeautyFilterEnum.LENGSEDIAO_11))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.NUANSEDIAO_1, R.mipmap.icon_beauty_filter_nuansediao_1, R.string.nuansediao_1, getDiskFilterValue(FaceBeautyFilterEnum.NUANSEDIAO_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.NUANSEDIAO_2, R.mipmap.icon_beauty_filter_nuansediao_2, R.string.nuansediao_2, getDiskFilterValue(FaceBeautyFilterEnum.NUANSEDIAO_2))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_1, R.mipmap.icon_beauty_filter_gexing_1, R.string.gexing_1, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_2, R.mipmap.icon_beauty_filter_gexing_2, R.string.gexing_2, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_2))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_3, R.mipmap.icon_beauty_filter_gexing_3, R.string.gexing_3, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_4, R.mipmap.icon_beauty_filter_gexing_4, R.string.gexing_4, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_4))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_5, R.mipmap.icon_beauty_filter_gexing_5, R.string.gexing_5, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_5))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_7, R.mipmap.icon_beauty_filter_gexing_7, R.string.gexing_7, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_7))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_10, R.mipmap.icon_beauty_filter_gexing_10, R.string.gexing_10, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_10))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.GEXING_11, R.mipmap.icon_beauty_filter_gexing_11, R.string.gexing_11, getDiskFilterValue(FaceBeautyFilterEnum.GEXING_11))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.XIAOQINGXIN_1, R.mipmap.icon_beauty_filter_xiaoqingxin_1, R.string.xiaoqingxin_1, getDiskFilterValue(FaceBeautyFilterEnum.XIAOQINGXIN_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.XIAOQINGXIN_3, R.mipmap.icon_beauty_filter_xiaoqingxin_3, R.string.xiaoqingxin_3, getDiskFilterValue(FaceBeautyFilterEnum.XIAOQINGXIN_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.XIAOQINGXIN_4, R.mipmap.icon_beauty_filter_xiaoqingxin_4, R.string.xiaoqingxin_4, getDiskFilterValue(FaceBeautyFilterEnum.XIAOQINGXIN_4))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.XIAOQINGXIN_6, R.mipmap.icon_beauty_filter_xiaoqingxin_6, R.string.xiaoqingxin_6, getDiskFilterValue(FaceBeautyFilterEnum.XIAOQINGXIN_6))); + + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.HEIBAI_1, R.mipmap.icon_beauty_filter_heibai_1, R.string.heibai_1, getDiskFilterValue(FaceBeautyFilterEnum.HEIBAI_1))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.HEIBAI_2, R.mipmap.icon_beauty_filter_heibai_2, R.string.heibai_2, getDiskFilterValue(FaceBeautyFilterEnum.HEIBAI_2))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.HEIBAI_3, R.mipmap.icon_beauty_filter_heibai_3, R.string.heibai_3, getDiskFilterValue(FaceBeautyFilterEnum.HEIBAI_3))); + filters.add(new FaceBeautyFilterBean(FaceBeautyFilterEnum.HEIBAI_4, R.mipmap.icon_beauty_filter_heibai_4, R.string.heibai_4, getDiskFilterValue(FaceBeautyFilterEnum.HEIBAI_4))); + + return filters; + } + + /** + * 从磁盘获取所有项滤镜强度 + * + * @param key + * @return + */ + private static double getDiskFilterValue(String key) { + if (faceBeautyData != null) { + return faceBeautyData.filterMap.get(key); + } else { + return 0.4; + } + } + + private static final String CONFIG_BIAOZHUN = "biaozhun"; + private static final String CONFIG_HUAJIAO = "huajiao"; + private static final String CONFIG_KUAISHOU = "kuaishou"; + private static final String CONFIG_QINGYAN = "qingyan"; + private static final String CONFIG_SHANGTANG = "shangtang"; + private static final String CONFIG_YINGKE = "yingke"; + private static final String CONFIG_ZIJIETIAODONG = "zijietiaodong"; + + + /** + * 初始化风格推荐 + * + * @return ArrayList + */ + public static ArrayList buildStylesParams() { + ArrayList params = new ArrayList<>(); + params.add(new FaceBeautyStyleBean(CONFIG_KUAISHOU, R.drawable.icon_beauty_style_1_selector, R.string.beauty_face_style_1,FaceParam.FACE_BEAUTY_STYLE)); + params.add(new FaceBeautyStyleBean(CONFIG_QINGYAN, R.drawable.icon_beauty_style_2_selector, R.string.beauty_face_style_2,FaceParam.FACE_BEAUTY_STYLE)); + params.add(new FaceBeautyStyleBean(CONFIG_ZIJIETIAODONG, R.drawable.icon_beauty_style_3_selector, R.string.beauty_face_style_3,FaceParam.FACE_BEAUTY_STYLE)); + params.add(new FaceBeautyStyleBean(CONFIG_HUAJIAO, R.drawable.icon_beauty_style_4_selector, R.string.beauty_face_style_4,FaceParam.FACE_BEAUTY_STYLE)); + params.add(new FaceBeautyStyleBean(CONFIG_YINGKE, R.drawable.icon_beauty_style_5_selector, R.string.beauty_face_style_5,FaceParam.FACE_BEAUTY_STYLE)); + params.add(new FaceBeautyStyleBean(CONFIG_SHANGTANG, R.drawable.icon_beauty_style_6_selector, R.string.beauty_face_style_6,FaceParam.FACE_BEAUTY_STYLE)); + params.add(new FaceBeautyStyleBean(CONFIG_BIAOZHUN, R.drawable.icon_beauty_style_7_selector, R.string.beauty_face_style_7,FaceParam.FACE_BEAUTY_STYLE)); + return params; + } + + /** + * 风格对应参数配置 + */ + public static HashMap styleParams = new HashMap() { + { + 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; + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/LightMakeupSource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/LightMakeupSource.java new file mode 100644 index 000000000..54af740c5 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/LightMakeupSource.java @@ -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 buildLightMakeup() { + ArrayList 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 LightMakeupParams = new HashMap() { + { + 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; + } + + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/MakeupSource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/MakeupSource.java new file mode 100644 index 000000000..4b4b6ca47 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/MakeupSource.java @@ -0,0 +1,489 @@ +package com.yunbao.faceunity.repo; + + +import android.annotation.SuppressLint; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; + +import com.faceunity.core.controller.makeup.MakeupParam; +import com.faceunity.core.entity.FUBundleData; +import com.faceunity.core.entity.FUColorRGBData; +import com.faceunity.core.model.facebeauty.FaceBeautyFilterEnum; +import com.faceunity.core.model.makeup.Makeup; +import com.faceunity.core.utils.FileUtils; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.data.FaceParam; +import com.yunbao.faceunity.entity.MakeupCombinationBean; +import com.yunbao.faceunity.entity.MakeupCustomBean; +import com.yunbao.faceunity.entity.MakeupCustomClassBean; +import com.yunbao.faceunity.utils.FaceUnityConfig; +import com.yunbao.faceunity.utils.FaceUnityData; +import com.yunbao.faceunity.entity.MakeupCombinationBean.TypeEnum; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * DESC:美妆数据构造 + * Created on 2021/3/28 + */ +public class MakeupSource { + public static String BUNDLE_FACE_MAKEUP = "graphics" + File.separator + "face_makeup.bundle"; + + + //region 组合妆容 + + /** + * 构造美妆组合妆容配置 + * + * @return ArrayList + */ + public static ArrayList buildCombinations() { + ArrayList combinations = new ArrayList(); + String jsonDir = FaceUnityConfig.MAKEUP_RESOURCE_JSON_DIR; + String bundleDir = FaceUnityConfig.MAKEUP_RESOURCE_COMBINATION_BUNDLE_DIR; + combinations.add(new MakeupCombinationBean("origin", TypeEnum.TYPE_NONE, R.mipmap.icon_control_none, R.string.makeup_radio_remove, null, "", FaceBeautyFilterEnum.ZIRAN_2, 1.0,0.0,FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("diadiatu", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_diadiatu, R.string.makeup_combination_diadiatu, bundleDir + "diadiatu.bundle", jsonDir + "diadiatu.json", FaceBeautyFilterEnum.ORIGIN, 0.68,FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("dongling", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_freezing_age, R.string.makeup_combination_dongling, bundleDir + "dongling.bundle", jsonDir + "dongling.json", FaceBeautyFilterEnum.ORIGIN, 0.68,FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("guofeng", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_guo_feng, R.string.makeup_combination_guofeng, bundleDir + "guofeng.bundle", jsonDir + "guofeng.json", FaceBeautyFilterEnum.ORIGIN, 0.6,FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("hunxie", TypeEnum.TYPE_THEME_MAIN, R.mipmap.icon_makeup_combination_mixed_race, R.string.makeup_combination_hunxie, bundleDir + "hunxie.bundle", jsonDir + "hunxie.json", FaceBeautyFilterEnum.ORIGIN, 0.6,FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("jianling", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_age, R.string.makeup_combination_jianling, bundleDir + "jianling.bundle", jsonDir + "jianling.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("nuandong", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_warm_winter, R.string.makeup_combination_nuandong, bundleDir + "nuandong.bundle", jsonDir + "nuandong.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("hongfeng", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_red_maple, R.string.makeup_combination_hongfeng, bundleDir + "hongfeng.bundle", jsonDir + "hongfeng.json", FaceBeautyFilterEnum.ZHIGANHUI_3, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("rose", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_rose, R.string.makeup_combination_rose, bundleDir + "rose.bundle", jsonDir + "rose.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("shaonv", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_girl, R.string.makeup_combination_shaonv, bundleDir + "shaonv.bundle", jsonDir + "shaonv.json", FaceBeautyFilterEnum.ZHIGANHUI_4, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("ziyun", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_purple_rhyme, R.string.makeup_combination_ziyun, bundleDir + "ziyun.bundle", jsonDir + "ziyun.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("yanshimao", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_bored_cat, R.string.makeup_combination_yanshimao, bundleDir + "yanshimao.bundle", jsonDir + "yanshimao.json", FaceBeautyFilterEnum.ZHIGANHUI_5, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("renyu", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_mermaid, R.string.makeup_combination_renyu, bundleDir + "renyu.bundle", jsonDir + "renyu.json", FaceBeautyFilterEnum.ZHIGANHUI_1, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("chuqiu", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_early_autumn, R.string.makeup_combination_chuqiu, bundleDir + "chuqiu.bundle", jsonDir + "chuqiu.json", FaceBeautyFilterEnum.ZHIGANHUI_6, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("qianzhihe", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_paper_cranes, R.string.makeup_combination_qianzhihe, bundleDir + "qianzhihe.bundle", jsonDir + "qianzhihe.json", FaceBeautyFilterEnum.ZHIGANHUI_2, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("chaomo", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_supermodel, R.string.makeup_combination_chaomo, bundleDir + "chaomo.bundle", jsonDir + "chaomo.json", FaceBeautyFilterEnum.ZHIGANHUI_7, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("chuju", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_daisy, R.string.makeup_combination_chuju, bundleDir + "chuju.bundle", jsonDir + "chuju.json", FaceBeautyFilterEnum.ZHIGANHUI_8, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("gangfeng", TypeEnum.TYPE_THEME_SUB, R.mipmap.icon_makeup_combination_harbour_wind, R.string.makeup_combination_gangfeng, bundleDir + "gangfeng.bundle", jsonDir + "gangfeng.json", FaceBeautyFilterEnum.ZIRAN_8, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("xinggan", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_sexy, R.string.makeup_combination_sexy, bundleDir + "xinggan.bundle", jsonDir + "xinggan.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("tianmei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_sweet, R.string.makeup_combination_sweet, bundleDir + "tianmei.bundle", jsonDir + "tianmei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("linjia", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_neighbor_girl, R.string.makeup_combination_neighbor, bundleDir + "linjia.bundle", jsonDir + "linjia.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("oumei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_occident, R.string.makeup_combination_occident, bundleDir + "oumei.bundle", jsonDir + "oumei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP)); + combinations.add(new MakeupCombinationBean("wumei", TypeEnum.TYPE_DAILY, R.mipmap.icon_makeup_combination_charming, R.string.makeup_combination_charming, bundleDir + "wumei.bundle", jsonDir + "wumei.json", FaceBeautyFilterEnum.ZIRAN_4, FaceParam.FACE_MAKEUP)); + return combinations; + } + + + /** + * 构造美妆模型 + * + * @return + */ + public static Makeup getMakeupModel(MakeupCombinationBean bean) { + Makeup makeupModel; + if (TypeEnum.TYPE_THEME_MAIN == bean.getType() && bean.getBundlePath() != null && bean.getBundlePath().trim().length() > 0) { + makeupModel = new Makeup(new FUBundleData(bean.getBundlePath())); + //新的组合妆容设置滤镜scale + makeupModel.setCurrentFilterScale(bean.getFilterScale()); + } else { + makeupModel = new Makeup(new FUBundleData(FaceUnityConfig.BUNDLE_FACE_MAKEUP)); + } + + if (bean.getKey().equals("origin")) { + return makeupModel; + } + + if ((TypeEnum.TYPE_THEME_SUB == bean.getType() || TypeEnum.TYPE_DAILY == bean.getType()) && bean.getBundlePath() != null && bean.getBundlePath().trim().length() > 0) + makeupModel.setCombinedConfig(new FUBundleData(bean.getBundlePath())); + + makeupModel.setMakeupIntensity(bean.getIntensity()); + if (bean.getJsonPathParams() == null) { + bean.setJsonPathParams(getLocalParams(bean.getJsonPath())); + } + LinkedHashMap params = bean.getJsonPathParams(); + + //支持自定义,所以需要知道选中了妆容的哪一些项 + for (Map.Entry entry : params.entrySet()) { + Object value = entry.getValue(); + String key = entry.getKey(); + if (value instanceof double[] && ((double[]) value).length > 4) { + int count = ((double[]) value).length / 4; + for (int i = 0; i < count; i++) { + if (i == 0) { + if (makeupSetMapping.containsKey(key)) { + makeupSetMapping.get(key).setValue(makeupModel, value); + } + } else { + if (makeupSetMapping.containsKey(key + (i + 1))) { + makeupSetMapping.get(key + (i + 1)).setValue(makeupModel, value); + } + } + } + } else { + if (makeupSetMapping.containsKey(key)) { + makeupSetMapping.get(key).setValue(makeupModel, value); + } + } + } + + return makeupModel; + } + + + /** + * 读取本地参数配置 + * + * @param jsonPath String json文件路径 + * @return LinkedHashMap + */ + private static LinkedHashMap getLocalParams(String jsonPath) { + LinkedHashMap map = new LinkedHashMap(32); + map.put(MakeupParam.LIP_INTENSITY, 0.0); + map.put(MakeupParam.EYE_LINER_INTENSITY, 0.0); + map.put(MakeupParam.BLUSHER_INTENSITY, 0.0); + map.put(MakeupParam.PUPIL_INTENSITY, 0.0); + map.put(MakeupParam.EYE_BROW_INTENSITY, 0.0); + map.put(MakeupParam.EYE_SHADOW_INTENSITY, 0.0); + map.put(MakeupParam.EYELASH_INTENSITY, 0.0); + map.put(MakeupParam.FOUNDATION_INTENSITY, 0.0); + map.put(MakeupParam.HIGHLIGHT_INTENSITY, 0.0); + map.put(MakeupParam.SHADOW_INTENSITY, 0.0); + LinkedHashMap jsonParam = FileUtils.INSTANCE.loadParamsFromLocal(FaceUnityData.mApplication, jsonPath); + for (Map.Entry entry : jsonParam.entrySet()) { + if (entry.getKey().startsWith("tex_")) { + if (entry.getValue() instanceof String && ((String) entry.getValue()).contains(".bundle")) { + map.put(entry.getKey(), FaceUnityConfig.MAKEUP_RESOURCE_ITEM_BUNDLE_DIR + entry.getValue()); + } + } else { + map.put(entry.getKey(), entry.getValue()); + } + } + return map; + } + + interface MakeupSetParam { + /** + * 模型属性赋值 + * + * @param makeup + * @param value + */ + void setValue(Makeup makeup, Object value); + + } + + /*美妆映射模型*/ + public static HashMap makeupSetMapping = new HashMap() { + { + put(MakeupParam.LIP_TYPE, (makeup, value) -> makeup.setLipType((int) value)); + put(MakeupParam.IS_TWO_COLOR, (makeup, value) -> makeup.setEnableTwoLipColor((int) value == 1)); + put(MakeupParam.MAKEUP_LIP_HIGH_LIGHT_ENABLE, (makeup, value) -> makeup.setLipHighLightEnable((int) value == 1)); + put(MakeupParam.MAKEUP_LIP_HIGH_LIGHT_STRENGTH, (makeup, value) -> makeup.setLipHighLightStrength((double) value)); + put(MakeupParam.BROW_WARP, (makeup, value) -> makeup.setEnableBrowWarp((double) value == 1.0)); + put(MakeupParam.BROW_WARP_TYPE, (makeup, value) -> makeup.setBrowWarpType((int) value)); + /*强度*/ + put(MakeupParam.MAKEUP_INTENSITY, (makeup, value) -> makeup.setMakeupIntensity((double) value)); + put(MakeupParam.LIP_INTENSITY, (makeup, value) -> makeup.setLipIntensity((double) value)); + put(MakeupParam.EYE_LINER_INTENSITY, (makeup, value) -> makeup.setEyeLineIntensity((double) value)); + put(MakeupParam.BLUSHER_INTENSITY, (makeup, value) -> makeup.setBlusherIntensity((double) value)); + put(MakeupParam.PUPIL_INTENSITY, (makeup, value) -> makeup.setPupilIntensity((double) value)); + put(MakeupParam.EYE_BROW_INTENSITY, (makeup, value) -> makeup.setEyeBrowIntensity((double) value)); + put(MakeupParam.EYE_SHADOW_INTENSITY, (makeup, value) -> makeup.setEyeShadowIntensity((double) value)); + put(MakeupParam.EYELASH_INTENSITY, (makeup, value) -> makeup.setEyeLashIntensity((double) value)); + put(MakeupParam.FOUNDATION_INTENSITY, (makeup, value) -> makeup.setFoundationIntensity((double) value)); + put(MakeupParam.HIGHLIGHT_INTENSITY, (makeup, value) -> makeup.setHeightLightIntensity((double) value)); + put(MakeupParam.SHADOW_INTENSITY, (makeup, value) -> makeup.setShadowIntensity((double) value)); + /*子项妆容贴图*/ + put(MakeupParam.TEX_LIP, (makeup, value) -> makeup.setLipBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_EYE_BROW, (makeup, value) -> makeup.setEyeBrowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_EYE_SHADOW, (makeup, value) -> makeup.setEyeShadowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_EYE_SHADOW2, (makeup, value) -> makeup.setEyeShadowBundle2(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_EYE_SHADOW3, (makeup, value) -> makeup.setEyeShadowBundle3(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_EYE_SHADOW4, (makeup, value) -> makeup.setEyeShadowBundle4(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_PUPIL, (makeup, value) -> makeup.setPupilBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_EYE_LASH, (makeup, value) -> makeup.setEyeLashBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_EYE_LINER, (makeup, value) -> makeup.setEyeLinerBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_BLUSHER, (makeup, value) -> makeup.setBlusherBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_BLUSHER2, (makeup, value) -> makeup.setBlusherBundle2(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_FOUNDATION, (makeup, value) -> makeup.setFoundationBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_HIGH_LIGHT, (makeup, value) -> makeup.setHighLightBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + put(MakeupParam.TEX_SHADOW, (makeup, value) -> makeup.setShadowBundle(((String) value).endsWith(".bundle") ? new FUBundleData((String) value) : null)); + /*子项妆容颜色*/ + put(MakeupParam.MAKEUP_LIP_COLOR, (makeup, value) -> makeup.setLipColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_LIP_COLOR_V2, (makeup, value) -> makeup.setLipColorV2(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_LIP_COLOR2, (makeup, value) -> makeup.setLipColor2(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_EYE_LINER_COLOR, (makeup, value) -> makeup.setEyeLinerColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_EYE_LASH_COLOR, (makeup, value) -> makeup.setEyeLashColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_BLUSHER_COLOR, (makeup, value) -> makeup.setBlusherColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_BLUSHER_COLOR2, (makeup, value) -> makeup.setBlusherColor2(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_FOUNDATION_COLOR, (makeup, value) -> makeup.setFoundationColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_HIGH_LIGHT_COLOR, (makeup, value) -> makeup.setHighLightColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_SHADOW_COLOR, (makeup, value) -> makeup.setShadowColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_EYE_BROW_COLOR, (makeup, value) -> makeup.setEyeBrowColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_PUPIL_COLOR, (makeup, value) -> makeup.setPupilColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR, (makeup, value) -> makeup.setEyeShadowColor(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR2, (makeup, value) -> makeup.setEyeShadowColor2(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR3, (makeup, value) -> makeup.setEyeShadowColor3(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_EYE_SHADOW_COLOR4, (makeup, value) -> makeup.setEyeShadowColor4(buildFUColorRGBData(value))); + put(MakeupParam.MAKEUP_EYE_BROW_COLOR, (makeup, value) -> makeup.setEyeBrowColor(buildFUColorRGBData(value))); + /* 图层混合模式 */ + put(MakeupParam.BLEND_TEX_EYE_SHADOW, (makeup, value) -> makeup.setEyeShadowTexBlend((int) value)); + put(MakeupParam.BLEND_TEX_EYE_SHADOW2, (makeup, value) -> makeup.setEyeShadowTexBlend2((int) value)); + put(MakeupParam.BLEND_TEX_EYE_SHADOW3, (makeup, value) -> makeup.setEyeShadowTexBlend3((int) value)); + put(MakeupParam.BLEND_TEX_EYE_SHADOW4, (makeup, value) -> makeup.setEyeShadowTexBlend4((int) value)); + put(MakeupParam.BLEND_TEX_EYE_LASH, (makeup, value) -> makeup.setEyeLashTexBlend((int) value)); + put(MakeupParam.BLEND_TEX_EYE_LINER, (makeup, value) -> makeup.setEyeLinerTexBlend((int) value)); + put(MakeupParam.BLEND_TEX_BLUSHER, (makeup, value) -> makeup.setBlusherTexBlend((int) value)); + put(MakeupParam.BLEND_TEX_BLUSHER2, (makeup, value) -> makeup.setBlusherTexBlend2((int) value)); + put(MakeupParam.BLEND_TEX_PUPIL, (makeup, value) -> makeup.setPupilTexBlend((int) value)); + } + }; + + + /** + * 构造颜色模型 + * + * @param object + * @return + */ + public static FUColorRGBData buildFUColorRGBData(Object object) { + if (object instanceof double[]) { + double[] array = (double[]) object; + if (array.length == 4) { + return new FUColorRGBData(array[0] * 255, array[1] * 255, array[2] * 255, array[3] * 255); + } + } + return new FUColorRGBData(0.0, 0.0, 0.0, 0.0); + } + //endregion 组合妆容 + +// region 子妆容 + + /* 粉底 */ + public static String FACE_MAKEUP_TYPE_FOUNDATION = "FOUNDATION"; + /* 口红 */ + public static String FACE_MAKEUP_TYPE_LIP_STICK = "STICK"; + /* 腮红 */ + public static String FACE_MAKEUP_TYPE_BLUSHER = "BLUSHER"; + /* 眉毛 */ + public static String FACE_MAKEUP_TYPE_EYE_BROW = "EYE_BROW"; + /* 眼影 */ + public static String FACE_MAKEUP_TYPE_EYE_SHADOW = "EYE_SHADOW"; + /* 眼线 */ + public static String FACE_MAKEUP_TYPE_EYE_LINER = "EYE_LINER"; + /* 睫毛 */ + public static String FACE_MAKEUP_TYPE_EYE_LASH = "EYE_LASH"; + /* 高光 */ + public static String FACE_MAKEUP_TYPE_HIGH_LIGHT = "HIGHLIGHT"; + /* 阴影 */ + public static String FACE_MAKEUP_TYPE_SHADOW = "SHADOW"; + /* 美瞳 */ + public static String FACE_MAKEUP_TYPE_EYE_PUPIL = "EYE_PUPIL"; + + /** + * 构造美妆子项类别 + */ + public static ArrayList buildCustomClasses() { + ArrayList classes = new ArrayList(); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_foundation, FACE_MAKEUP_TYPE_FOUNDATION,FaceParam.FACE_MAKEUP_TYPE_FOUNDATION)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_lipstick, FACE_MAKEUP_TYPE_LIP_STICK,FaceParam.FACE_MAKEUP_TYPE_LIP_STICK)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_blusher, FACE_MAKEUP_TYPE_BLUSHER,FaceParam.FACE_MAKEUP_TYPE_BLUSHER)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eyebrow, FACE_MAKEUP_TYPE_EYE_BROW,FaceParam.FACE_MAKEUP_TYPE_EYE_BROW)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eye_shadow, FACE_MAKEUP_TYPE_EYE_SHADOW,FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eye_liner, FACE_MAKEUP_TYPE_EYE_LINER,FaceParam.FACE_MAKEUP_TYPE_EYE_LINER)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_eyelash, FACE_MAKEUP_TYPE_EYE_LASH,FaceParam.FACE_MAKEUP_TYPE_EYE_LASH)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_highlight, FACE_MAKEUP_TYPE_HIGH_LIGHT,FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_shadow, FACE_MAKEUP_TYPE_SHADOW,FaceParam.FACE_MAKEUP_TYPE_SHADOW)); + classes.add(new MakeupCustomClassBean(R.string.makeup_radio_contact_lens, FACE_MAKEUP_TYPE_EYE_PUPIL,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + return classes; + } + + public static LinkedHashMap> buildCustomItemParams(){ + return buildCustomItemParams(MakeupSource.buildMakeUpColorMap()); + } + /** + * 美妆单项妆容配置参数 + * + * @return LinkedHashMap> + */ + public static LinkedHashMap> buildCustomItemParams(LinkedHashMap> colorMap) { + LinkedHashMap> mCustomItems = new LinkedHashMap<>(); + /*粉底*/ + ArrayList makeupItems = new ArrayList(6); + makeupItems.add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_FOUNDATION)); + ArrayList list = colorMap.get("color_mu_style_foundation_01"); + for (int i = 3; i < 8; i++) { + double[] colors = list.get(i); + ColorDrawable drawable = new ColorDrawable(Color.argb((int) (colors[3] * 255), (int) (colors[0] * 255), (int) (colors[1] * 255), (int) (colors[2] * 255))); + makeupItems.add(new MakeupCustomBean(0, drawable,FaceParam.FACE_MAKEUP_TYPE_FOUNDATION)); + } + mCustomItems.put(FACE_MAKEUP_TYPE_FOUNDATION, makeupItems); + + + /*口红*/ + mCustomItems.put(FACE_MAKEUP_TYPE_LIP_STICK, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK)); + add(new MakeupCustomBean(R.string.makeup_lip_fog, getDrawable(R.mipmap.icon_makeup_lip_fog), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK)); + add(new MakeupCustomBean(R.string.makeup_lip_moist1, getDrawable(R.mipmap.icon_makeup_lip_moist), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK)); + add(new MakeupCustomBean(R.string.makeup_lip_moist2, getDrawable(R.mipmap.icon_makeup_lip_water), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK)); + add(new MakeupCustomBean(R.string.makeup_lip_pearl, getDrawable(R.mipmap.icon_makeup_lip_pearl), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK)); + add(new MakeupCustomBean(R.string.makeup_lip_bitelip, getDrawable(R.mipmap.icon_makeup_lip_beitelip), colorMap.get("color_mu_style_lip_01"),FaceParam.FACE_MAKEUP_TYPE_LIP_STICK)); + } + }); + + /*腮红*/ + mCustomItems.put(FACE_MAKEUP_TYPE_BLUSHER, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_BLUSHER)); + add(new MakeupCustomBean(R.string.makeup_blusher_apple, getDrawable(R.mipmap.icon_makeup_blush_01), colorMap.get("color_mu_style_blush_01"),FaceParam.FACE_MAKEUP_TYPE_BLUSHER)); + add(new MakeupCustomBean(R.string.makeup_blusher_fan, getDrawable(R.mipmap.icon_makeup_blush_02), colorMap.get("color_mu_style_blush_02"),FaceParam.FACE_MAKEUP_TYPE_BLUSHER)); + add(new MakeupCustomBean(R.string.makeup_blusher_eye_corner, getDrawable(R.mipmap.icon_makeup_blush_03), colorMap.get("color_mu_style_blush_03"),FaceParam.FACE_MAKEUP_TYPE_BLUSHER)); + add(new MakeupCustomBean(R.string.makeup_blusher_slight_drunk, getDrawable(R.mipmap.icon_makeup_blush_04), colorMap.get("color_mu_style_blush_04"),FaceParam.FACE_MAKEUP_TYPE_BLUSHER)); + } + }); + /*眉毛*/ + mCustomItems.put(FACE_MAKEUP_TYPE_EYE_BROW, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW)); + add(new MakeupCustomBean(R.string.makeup_eyebrow_willow, getDrawable(R.mipmap.icon_makeup_eyebrow_01), colorMap.get("color_mu_style_eyebrow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW)); + add(new MakeupCustomBean(R.string.makeup_eyebrow_wild, getDrawable(R.mipmap.icon_makeup_eyebrow_02), colorMap.get("color_mu_style_eyebrow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW)); + add(new MakeupCustomBean(R.string.makeup_eyebrow_classical, getDrawable(R.mipmap.icon_makeup_eyebrow_03), colorMap.get("color_mu_style_eyebrow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW)); + add(new MakeupCustomBean(R.string.makeup_eyebrow_standard, getDrawable(R.mipmap.icon_makeup_eyebrow_04), colorMap.get("color_mu_style_eyebrow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_BROW)); + } + }); + + /*眼影*/ + mCustomItems.put(FACE_MAKEUP_TYPE_EYE_SHADOW, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW)); + add(new MakeupCustomBean(R.string.makeup_eye_shadow_single, getDrawable(R.mipmap.icon_makeup_eyeshadow_01), colorMap.get("color_mu_style_eyeshadow_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW)); + add(new MakeupCustomBean(R.string.makeup_eye_shadow_double1, getDrawable(R.mipmap.icon_makeup_eyeshadow_02), colorMap.get("color_mu_style_eyeshadow_02"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW)); + add(new MakeupCustomBean(R.string.makeup_eye_shadow_double2, getDrawable(R.mipmap.icon_makeup_eyeshadow_03), colorMap.get("color_mu_style_eyeshadow_03"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW)); + add(new MakeupCustomBean(R.string.makeup_eye_shadow_double3, getDrawable(R.mipmap.icon_makeup_eyeshadow_04), colorMap.get("color_mu_style_eyeshadow_04"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW)); + add(new MakeupCustomBean(R.string.makeup_eye_shadow_triple1, getDrawable(R.mipmap.icon_makeup_eyeshadow_05), colorMap.get("color_mu_style_eyeshadow_05"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW)); + add(new MakeupCustomBean(R.string.makeup_eye_shadow_triple2, getDrawable(R.mipmap.icon_makeup_eyeshadow_06), colorMap.get("color_mu_style_eyeshadow_06"),FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW)); + } + }); + + /*眼线*/ + mCustomItems.put(FACE_MAKEUP_TYPE_EYE_LINER, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER)); + add(new MakeupCustomBean(R.string.makeup_eye_linear_cat, getDrawable(R.mipmap.icon_makeup_eyeliner_01), colorMap.get("color_mu_style_eyeliner_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER)); + add(new MakeupCustomBean(R.string.makeup_eye_linear_drooping, getDrawable(R.mipmap.icon_makeup_eyeliner_02), colorMap.get("color_mu_style_eyeliner_02"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER)); + add(new MakeupCustomBean(R.string.makeup_eye_linear_pull_open, getDrawable(R.mipmap.icon_makeup_eyeliner_03), colorMap.get("color_mu_style_eyeliner_03"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER)); + add(new MakeupCustomBean(R.string.makeup_eye_linear_pull_close, getDrawable(R.mipmap.icon_makeup_eyeliner_04), colorMap.get("color_mu_style_eyeliner_04"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER)); + add(new MakeupCustomBean(R.string.makeup_eye_linear_long, getDrawable(R.mipmap.icon_makeup_eyeliner_05), colorMap.get("color_mu_style_eyeliner_05"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER)); + add(new MakeupCustomBean(R.string.makeup_eye_linear_circular, getDrawable(R.mipmap.icon_makeup_eyeliner_06), colorMap.get("color_mu_style_eyeliner_06"),FaceParam.FACE_MAKEUP_TYPE_EYE_LINER)); + } + }); + /*睫毛*/ + mCustomItems.put(FACE_MAKEUP_TYPE_EYE_LASH, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH)); + add(new MakeupCustomBean(R.string.makeup_eyelash_natural1, getDrawable(R.mipmap.icon_makeup_eyelash_01), colorMap.get("color_mu_style_eyelash_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH)); + add(new MakeupCustomBean(R.string.makeup_eyelash_natural2, getDrawable(R.mipmap.icon_makeup_eyelash_02), colorMap.get("color_mu_style_eyelash_02"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH)); + add(new MakeupCustomBean(R.string.makeup_eyelash_thick1, getDrawable(R.mipmap.icon_makeup_eyelash_03), colorMap.get("color_mu_style_eyelash_03"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH)); + add(new MakeupCustomBean(R.string.makeup_eyelash_thick2, getDrawable(R.mipmap.icon_makeup_eyelash_04), colorMap.get("color_mu_style_eyelash_04"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH)); + add(new MakeupCustomBean(R.string.makeup_eyelash_exaggerate1, getDrawable(R.mipmap.icon_makeup_eyelash_05), colorMap.get("color_mu_style_eyelash_05"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH)); + add(new MakeupCustomBean(R.string.makeup_eyelash_exaggerate2, getDrawable(R.mipmap.icon_makeup_eyelash_06), colorMap.get("color_mu_style_eyelash_06"),FaceParam.FACE_MAKEUP_TYPE_EYE_LASH)); + } + }); + + /*高光*/ + mCustomItems.put(FACE_MAKEUP_TYPE_HIGH_LIGHT, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT)); + add(new MakeupCustomBean(R.string.makeup_highlight_one, getDrawable(R.mipmap.icon_makeup_highlight_01), colorMap.get("color_mu_style_highlight_01"),FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT)); + add(new MakeupCustomBean(R.string.makeup_highlight_two, getDrawable(R.mipmap.icon_makeup_highlight_02), colorMap.get("color_mu_style_highlight_02"),FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT)); + } + }); + /*阴影*/ + mCustomItems.put(FACE_MAKEUP_TYPE_SHADOW, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_SHADOW)); + add(new MakeupCustomBean(R.string.makeup_shadow_one, getDrawable(R.mipmap.icon_makeup_contour_01), colorMap.get("color_mu_style_contour_01"),FaceParam.FACE_MAKEUP_TYPE_SHADOW)); + } + }); + /*美瞳*/ + mCustomItems.put(FACE_MAKEUP_TYPE_EYE_PUPIL, new ArrayList() { + { + add(new MakeupCustomBean(R.string.makeup_radio_remove, getDrawable(R.mipmap.icon_control_none),FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + add(new MakeupCustomBean(R.string.makeup_pupil_1, getDrawable(R.mipmap.icon_makeup_eyepupil_01), colorMap.get("color_mu_style_eyepupil_01"),FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + add(new MakeupCustomBean(R.string.makeup_pupil_2, getDrawable(R.mipmap.icon_makeup_eyepupil_03), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + add(new MakeupCustomBean(R.string.makeup_pupil_3, getDrawable(R.mipmap.icon_makeup_eyepupil_04), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + add(new MakeupCustomBean(R.string.makeup_pupil_4, getDrawable(R.mipmap.icon_makeup_eyepupil_05), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + add(new MakeupCustomBean(R.string.makeup_pupil_5, getDrawable(R.mipmap.icon_makeup_eyepupil_06), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + add(new MakeupCustomBean(R.string.makeup_pupil_6, getDrawable(R.mipmap.icon_makeup_eyepupil_07), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + add(new MakeupCustomBean(R.string.makeup_pupil_7, getDrawable(R.mipmap.icon_makeup_eyepupil_08), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + add(new MakeupCustomBean(R.string.makeup_pupil_8, getDrawable(R.mipmap.icon_makeup_eyepupil_09), null,FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL)); + } + }); + return mCustomItems; + } + + + //endregion 子妆容 + + + //region 其他 + + /** + * 获取颜色值配置 + * + * @return LinkedHashMap> + */ + public static LinkedHashMap> buildMakeUpColorMap() { + LinkedHashMap> makeupColorMap = new LinkedHashMap<>(32); + String colorJson = FileUtils.INSTANCE.loadStringFromLocal(FaceUnityData.mApplication, FaceUnityConfig.MAKEUP_RESOURCE_COLOR_SETUP_JSON); + if (colorJson != null && colorJson.trim().length() > 0) { + try { + JSONObject jsonObject = new JSONObject(colorJson); + Iterator keys = jsonObject.keys(); + while (keys.hasNext()) { + String key = keys.next(); + ArrayList colorList = new ArrayList(12); + // add additional transparent to fit ui + //增加透明色,兼容ColorRecycleView展示 + colorList.add(new double[]{0.0, 0.0, 0.0, 0.0}); + colorList.add(new double[]{0.0, 0.0, 0.0, 0.0}); + colorList.add(new double[]{0.0, 0.0, 0.0, 0.0}); + JSONObject colorObject = jsonObject.optJSONObject(key); + for (int i = 1; i < 6; i++) { + JSONArray jsonArray = colorObject.optJSONArray("color" + i); + int length = jsonArray.length(); + double[] colors = new double[length]; + for (int j = 0; j < length; j++) { + colors[j] = jsonArray.optDouble(j, 0.0); + } + colorList.add(colors); + } + colorList.add(new double[]{0.0, 0.0, 0.0, 0.0}); + colorList.add(new double[]{0.0, 0.0, 0.0, 0.0}); + colorList.add(new double[]{0.0, 0.0, 0.0, 0.0}); + makeupColorMap.put(key, colorList); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + return makeupColorMap; + } + + + /** + * 获取Drawable对象 + * + * @param res Int + * @return Drawable + */ + @SuppressLint("UseCompatLoadingForDrawables") + private static Drawable getDrawable(int res) { + return FaceUnityData.mApplication.getResources().getDrawable(res); + } + //endregion +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/PortraitSegmentSource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/PortraitSegmentSource.java new file mode 100644 index 000000000..15d15117f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/PortraitSegmentSource.java @@ -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 buildPropBeans() { + ArrayList 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; + } + + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/repo/PropSource.java b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/PropSource.java new file mode 100644 index 000000000..4d126b480 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/repo/PropSource.java @@ -0,0 +1,80 @@ +package com.yunbao.faceunity.repo; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.data.FaceParam; +import com.yunbao.faceunity.entity.FunctionEnum; +import com.yunbao.faceunity.entity.PropBean; + +import java.util.ArrayList; + +/** + * DESC:道具数据构造:道具贴图、AR面具、搞笑大头、表情识别、哈哈镜、手势识别、游戏 + * Created on 2021/3/28 + */ +public class PropSource { + + public static ArrayList buildPropBeans(int propType) { + ArrayList propBeans = new ArrayList<>(); + switch (propType) { + case FunctionEnum.STICKER: + propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null, FaceParam.FACE_STICKER)); + propBeans.add(new PropBean(R.mipmap.icon_sticker_cat_sparks, "effect/normal/cat_sparks.bundle", FaceParam.FACE_STICKER)); + propBeans.add(new PropBean(R.mipmap.icon_sticker_fu_zh_fenshu, "effect/normal/fu_zh_fenshu.bundle", FaceParam.FACE_STICKER)); + propBeans.add(new PropBean(R.mipmap.icon_sticker_sdlr, "effect/normal/sdlr.bundle", FaceParam.FACE_STICKER)); + propBeans.add(new PropBean(R.mipmap.icon_sticker_xlong_zh_fu, "effect/normal/xlong_zh_fu.bundle", FaceParam.FACE_STICKER)); + propBeans.add(new PropBean(R.mipmap.icon_sticker_newy1, "effect/normal/newy1.bundle", FaceParam.FACE_STICKER)); + propBeans.add(new PropBean(R.mipmap.icon_sticker_redribbt, "effect/normal/redribbt.bundle", FaceParam.FACE_STICKER)); + propBeans.add(new PropBean(R.mipmap.icon_sticker_daisypig, "effect/normal/daisypig.bundle", FaceParam.FACE_STICKER)); + propBeans.add(new PropBean(R.mipmap.icon_sticker_sdlu, "effect/normal/sdlu.bundle", FaceParam.FACE_STICKER)); + break; + case FunctionEnum.AR_MASK: + propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null, FaceParam.FACE_ANIM_AR_MASK)); + propBeans.add(new PropBean(R.mipmap.icon_ar_bluebird, "effect/ar/bluebird.bundle", FaceParam.FACE_ANIM_AR_MASK)); + propBeans.add(new PropBean(R.mipmap.icon_ar_lanhudie, "effect/ar/lanhudie.bundle", FaceParam.FACE_ANIM_AR_MASK)); + propBeans.add(new PropBean(R.mipmap.icon_ar_fenhudie, "effect/ar/fenhudie.bundle", FaceParam.FACE_ANIM_AR_MASK)); + propBeans.add(new PropBean(R.mipmap.icon_ar_tiger_huang, "effect/ar/tiger_huang.bundle", FaceParam.FACE_ANIM_AR_MASK)); + propBeans.add(new PropBean(R.mipmap.icon_ar_tiger_bai, "effect/ar/tiger_bai.bundle", FaceParam.FACE_ANIM_AR_MASK)); + propBeans.add(new PropBean(R.mipmap.icon_ar_baozi, "effect/ar/baozi.bundle", FaceParam.FACE_ANIM_AR_MASK)); + propBeans.add(new PropBean(R.mipmap.icon_ar_tiger, "effect/ar/tiger.bundle", FaceParam.FACE_ANIM_AR_MASK)); + propBeans.add(new PropBean(R.mipmap.icon_ar_xiongmao, "effect/ar/xiongmao.bundle", FaceParam.FACE_ANIM_AR_MASK)); + break; + case FunctionEnum.BIG_HEAD: + propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null, FaceParam.FACE_BIG_HEAD)); + propBeans.add(new PropBean(R.mipmap.icon_big_head, "effect/big_head/big_head.bundle", FaceParam.FACE_BIG_HEAD)); + propBeans.add(new PropBean(R.mipmap.icon_big_head_husky_face, "effect/big_head/big_head_facewarp2.bundle", FaceParam.FACE_BIG_HEAD)); + propBeans.add(new PropBean(R.mipmap.icon_big_head_sausage_mouth, "effect/big_head/big_head_facewarp4.bundle", FaceParam.FACE_BIG_HEAD)); + propBeans.add(new PropBean(R.mipmap.icon_big_head_blush, "effect/big_head/big_head_facewarp5.bundle", FaceParam.FACE_BIG_HEAD)); + propBeans.add(new PropBean(R.mipmap.icon_big_head_dark_circles, "effect/big_head/big_head_facewarp6.bundle", FaceParam.FACE_BIG_HEAD)); + propBeans.add(new PropBean(R.mipmap.icon_big_head_smiling_head, "effect/big_head/big_head_smile.bundle", R.string.xiaobianzi_zh_fu, FaceParam.FACE_BIG_HEAD)); + break; + case FunctionEnum.EXPRESSION_RECOGNITION: + propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null,FaceParam.FACE_EXPRESSION_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_expression_future_warrior, "effect/expression/future_warrior.bundle", R.string.future_warrior,FaceParam.FACE_EXPRESSION_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_expression_jet_mask, "effect/expression/jet_mask.bundle", R.string.jet_mask,FaceParam.FACE_EXPRESSION_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_expression_sdx2, "effect/expression/sdx2.bundle", R.string.sdx2,FaceParam.FACE_EXPRESSION_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_expression_luhantongkuan_ztt_fu, "effect/expression/luhantongkuan_ztt_fu.bundle", R.string.luhantongkuan_ztt_fu,FaceParam.FACE_EXPRESSION_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_expression_qingqing_ztt_fu, "effect/expression/qingqing_ztt_fu.bundle", R.string.qingqing_ztt_fu,FaceParam.FACE_EXPRESSION_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_expression_xiaobianzi_zh_fu, "effect/expression/xiaobianzi_zh_fu.bundle", R.string.xiaobianzi_zh_fu,FaceParam.FACE_EXPRESSION_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_expression_xiaoxueshen_ztt_fu, "effect/expression/xiaoxueshen_ztt_fu.bundle", R.string.xiaoxueshen_ztt_fu,FaceParam.FACE_EXPRESSION_RECOGNITION)); + break; + case FunctionEnum.FACE_WARP: + propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null,FaceParam.FACE_FACE_WARP)); + propBeans.add(new PropBean(R.mipmap.icon_face_warp_2, "effect/facewarp/facewarp2.bundle",FaceParam.FACE_FACE_WARP)); + propBeans.add(new PropBean(R.mipmap.icon_face_warp_3, "effect/facewarp/facewarp3.bundle",FaceParam.FACE_FACE_WARP)); + propBeans.add(new PropBean(R.mipmap.icon_face_warp_4, "effect/facewarp/facewarp4.bundle",FaceParam.FACE_FACE_WARP)); + propBeans.add(new PropBean(R.mipmap.icon_face_warp_5, "effect/facewarp/facewarp5.bundle",FaceParam.FACE_FACE_WARP)); + propBeans.add(new PropBean(R.mipmap.icon_face_warp_6, "effect/facewarp/facewarp6.bundle",FaceParam.FACE_FACE_WARP)); + break; + case FunctionEnum.GESTURE_RECOGNITION: + propBeans.add(new PropBean(R.mipmap.icon_control_delete_all, null,FaceParam.FACE_GESTURE_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_gesture_rain, "effect/gesture/ctrl_rain.bundle", R.string.push_hand,FaceParam.FACE_GESTURE_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_gesture_snow, "effect/gesture/ctrl_snow.bundle", R.string.push_hand,FaceParam.FACE_GESTURE_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_gesture_flower, "effect/gesture/ctrl_flower.bundle", R.string.push_hand,FaceParam.FACE_GESTURE_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_gesture_koreaheart, "effect/gesture/ssd_thread_korheart.bundle", R.string.fu_lm_koreaheart,FaceParam.FACE_GESTURE_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_gesture_six, "effect/gesture/ssd_thread_six.bundle", R.string.ssd_thread_six,FaceParam.FACE_GESTURE_RECOGNITION)); + propBeans.add(new PropBean(R.mipmap.icon_gesture_cute, "effect/gesture/ssd_thread_cute.bundle", R.string.ssd_thread_cute,FaceParam.FACE_GESTURE_RECOGNITION)); + break; + } + return propBeans; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/DiscreteSeekBar.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/DiscreteSeekBar.java new file mode 100644 index 000000000..f01c4292f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/DiscreteSeekBar.java @@ -0,0 +1,1084 @@ +package com.yunbao.faceunity.seekbar; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewParent; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.DrawableCompat; +import androidx.core.view.ViewCompat; + + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.seekbar.internal.PopupIndicator; +import com.yunbao.faceunity.seekbar.internal.compat.AnimatorCompat; +import com.yunbao.faceunity.seekbar.internal.compat.SeekBarCompat; +import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable; +import com.yunbao.faceunity.seekbar.internal.drawable.ThumbDrawable; +import com.yunbao.faceunity.seekbar.internal.drawable.TrackRectDrawable; + +import java.util.Formatter; +import java.util.Locale; + +public class DiscreteSeekBar extends View { + private static final String TAG = DiscreteSeekBar.class.getSimpleName(); + + /** + * Interface to propagate seekbar change event + */ + public interface OnProgressChangeListener { + /** + * When the {@link DiscreteSeekBar} value changes + * + * @param seekBar The DiscreteSeekBar + * @param value the new value + * @param fromUser if the change was made from the user or not (i.e. the developer calling {@link #setProgress(int)} + */ + public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser); + + public void onStartTrackingTouch(DiscreteSeekBar seekBar); + + public void onStopTrackingTouch(DiscreteSeekBar seekBar); + } + + public static class OnSimpleProgressChangeListener implements OnProgressChangeListener { + public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) { + + } + + public void onStartTrackingTouch(DiscreteSeekBar seekBar) { + + } + + public void onStopTrackingTouch(DiscreteSeekBar seekBar) { + + } + } + + /** + * Interface to transform the current internal value of this DiscreteSeekBar to anther one for the visualization. + *

+ * This will be used on the floating bubble to display a different value if needed. + *

+ * Using this in conjunction with {@link #setIndicatorFormatter(String)} you will be able to manipulate the + * value seen by the user + * + * @see #setIndicatorFormatter(String) + * @see #setNumericTransformer(NumericTransformer) + */ + public static abstract class NumericTransformer { + /** + * Return the desired value to be shown to the user. + * This value will be formatted using the format specified by {@link #setIndicatorFormatter} before displaying it + * + * @param value The value to be transformed + * @return The transformed int + */ + public abstract int transform(int value); + + /** + * Return the desired value to be shown to the user. + * This value will be displayed 'as is' without further formatting. + * + * @param value The value to be transformed + * @return A formatted string + */ + public String transformToString(int value) { + return String.valueOf(value); + } + + /** + * Used to indicate which transform will be used. If this method returns true, + * {@link #transformToString(int)} will be used, otherwise {@link #transform(int)} + * will be used + */ + public boolean useStringTransform() { + return false; + } + } + + + private static class DefaultNumericTransformer extends NumericTransformer { + + @Override + public int transform(int value) { + return value; + } + } + + + private static final boolean isLollipopOrGreater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; + //We want to always use a formatter so the indicator numbers are "translated" to specific locales. + private static final String DEFAULT_FORMATTER = "%d"; + + private static final int PRESSED_STATE = android.R.attr.state_pressed; + private static final int FOCUSED_STATE = android.R.attr.state_focused; + private static final int PROGRESS_ANIMATION_DURATION = 250; + private static final int INDICATOR_DELAY_FOR_TAPS = 150; + private static final int DEFAULT_THUMB_COLOR = 0xff009688; + private static final int SEPARATION_DP = 5; + private ThumbDrawable mThumb; + private TrackRectDrawable mTrack; + private TrackRectDrawable mTrackBase; + private TrackRectDrawable mScrubber; + private Drawable mRipple; + + private int mTrackHeight; + private int mTrackBaseHeight; + private int mScrubberHeight; + private final int mAddedTouchBounds; + + private int mMax; + private int mMin; + private int mValue; + private int mKeyProgressIncrement = 1; + private boolean mMirrorForRtl = false; + private boolean mAllowTrackClick = true; + private boolean mIndicatorPopupEnabled = true; + //We use our own Formatter to avoid creating new instances on every progress change + Formatter mFormatter; + private String mIndicatorFormatter; + private NumericTransformer mNumericTransformer; + private StringBuilder mFormatBuilder; + private OnProgressChangeListener mPublicChangeListener; + private boolean mIsDragging; + private int mDragOffset; + + private Rect mInvalidateRect = new Rect(); + private Rect mTempRect = new Rect(); + private PopupIndicator mIndicator; + private AnimatorCompat mPositionAnimator; + private float mAnimationPosition; + private int mAnimationTarget; + private float mDownX; + private float mTouchSlop; + + private int mValueBase; + + public DiscreteSeekBar(Context context) { + this(context, null); + } + + public DiscreteSeekBar(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.discreteSeekBarStyle); + } + + public DiscreteSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setFocusable(true); + setWillNotDraw(false); + + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + float density = context.getResources().getDisplayMetrics().density; + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DiscreteSeekBar, + defStyleAttr, R.style.Widget_DiscreteSeekBar); + + int max = 100; + int min = 0; + mMirrorForRtl = a.getBoolean(R.styleable.DiscreteSeekBar_dsb_mirrorForRtl, mMirrorForRtl); + mAllowTrackClick = a.getBoolean(R.styleable.DiscreteSeekBar_dsb_allowTrackClickToDrag, mAllowTrackClick); + mIndicatorPopupEnabled = a.getBoolean(R.styleable.DiscreteSeekBar_dsb_indicatorPopupEnabled, mIndicatorPopupEnabled); + mTrackHeight = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_trackHeight, (int) (1 * density)); + mTrackBaseHeight = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_trackBaseHeight, (int) (1 * density)); + mScrubberHeight = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_scrubberHeight, (int) (4 * density)); + int thumbSize = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_thumbSize, (int) (density * ThumbDrawable.DEFAULT_SIZE_DP)); + int separation = a.getDimensionPixelSize(R.styleable.DiscreteSeekBar_dsb_indicatorSeparation, + (int) (SEPARATION_DP * density)); + + int touchBounds = thumbSize * 3 / 2; + mAddedTouchBounds = Math.max(0, (touchBounds - thumbSize) / 2); + + int indexMax = R.styleable.DiscreteSeekBar_dsb_max; + int indexMin = R.styleable.DiscreteSeekBar_dsb_min; + int indexValue = R.styleable.DiscreteSeekBar_dsb_value; + final TypedValue out = new TypedValue(); + //Not sure why, but we wanted to be able to use dimensions here... + if (a.getValue(indexMax, out)) { + if (out.type == TypedValue.TYPE_DIMENSION) { + max = a.getDimensionPixelSize(indexMax, max); + } else { + max = a.getInteger(indexMax, max); + } + } + if (a.getValue(indexMin, out)) { + if (out.type == TypedValue.TYPE_DIMENSION) { + min = a.getDimensionPixelSize(indexMin, min); + } else { + min = a.getInteger(indexMin, min); + } + } + if (a.getValue(indexValue, out)) { + if (out.type == TypedValue.TYPE_DIMENSION) { + mValueBase = a.getDimensionPixelSize(indexValue, mValueBase); + } else { + mValueBase = a.getInteger(indexValue, mValueBase); + } + } + + mMin = min; + mMax = Math.max(min + 1, max); + mValue = Math.max(min, Math.min(max, mValueBase)); + updateKeyboardRange(); + + mIndicatorFormatter = a.getString(R.styleable.DiscreteSeekBar_dsb_indicatorFormatter); + + ColorStateList trackColor = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_trackColor); + ColorStateList progressColor = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_progressColor); + ColorStateList rippleColor = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_rippleColor); + boolean editMode = isInEditMode(); + if (editMode || rippleColor == null) { + rippleColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.DKGRAY}); + } + if (editMode || trackColor == null) { + trackColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.GRAY}); + } + if (editMode || progressColor == null) { + progressColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{DEFAULT_THUMB_COLOR}); + } + + mRipple = SeekBarCompat.getRipple(rippleColor); + if (isLollipopOrGreater) { + SeekBarCompat.setBackground(this, mRipple); + } else { + mRipple.setCallback(this); + } + + TrackRectDrawable shapeDrawable = new TrackRectDrawable(trackColor); + mTrack = shapeDrawable; + mTrack.setCallback(this); + + mTrackBase = new TrackRectDrawable(trackColor); + mTrackBase.setCallback(this); + + shapeDrawable = new TrackRectDrawable(progressColor); + mScrubber = shapeDrawable; + mScrubber.setCallback(this); + + mThumb = new ThumbDrawable(progressColor, thumbSize); + mThumb.setCallback(this); + mThumb.setBounds(0, 0, mThumb.getIntrinsicWidth(), mThumb.getIntrinsicHeight()); + + + if (!editMode) { + mIndicator = new PopupIndicator(context, attrs, defStyleAttr, convertValueToMessage(mMax), + thumbSize, thumbSize + mAddedTouchBounds + separation); + mIndicator.setListener(mFloaterListener); + } + a.recycle(); + + setNumericTransformer(new DefaultNumericTransformer()); + + } + + /** + * Sets the current Indicator formatter string + * + * @param formatter + * @see String#format(String, Object...) + * @see #setNumericTransformer(NumericTransformer) + */ + public void setIndicatorFormatter(@Nullable String formatter) { + mIndicatorFormatter = formatter; + updateProgressMessage(mValue); + } + + /** + * Sets the current {@link NumericTransformer} + * + * @param transformer + * @see #getNumericTransformer() + */ + public void setNumericTransformer(@Nullable NumericTransformer transformer) { + mNumericTransformer = transformer != null ? transformer : new DefaultNumericTransformer(); + //We need to refresh the PopupIndicator view + updateIndicatorSizes(); + updateProgressMessage(mValue); + } + + /** + * Retrieves the current {@link NumericTransformer} + * + * @return NumericTransformer + * @see #setNumericTransformer + */ + public NumericTransformer getNumericTransformer() { + return mNumericTransformer; + } + + /** + * Sets the maximum value for this DiscreteSeekBar + * if the supplied argument is smaller than the Current MIN value, + * the MIN value will be set to MAX-1 + *

+ *

+ * Also if the current progress is out of the new range, it will be set to MIN + *

+ * + * @param max + * @see #setMin(int) + * @see #setProgress(int) + */ + public void setMax(int max) { + if (mMax == max) + return; + mMax = max; + if (mMax < mMin) { + setMin(mMax - 1); + } + updateKeyboardRange(); + + //We need to refresh the PopupIndicator view + updateIndicatorSizes(); + } + + public int getMax() { + return mMax; + } + + /** + * Sets the minimum value for this DiscreteSeekBar + * if the supplied argument is bigger than the Current MAX value, + * the MAX value will be set to MIN+1 + *

+ * Also if the current progress is out of the new range, it will be set to MIN + *

+ * + * @param min + * @see #setMax(int) + * @see #setProgress(int) + */ + public void setMin(int min) { + if (mMin == min) + return; + mMin = min; + if (mMin > mMax) { + setMax(mMin + 1); + } + updateKeyboardRange(); + } + + public int getMin() { + return mMin; + } + + /** + * Sets the current progress for this DiscreteSeekBar + * The supplied argument will be capped to the current MIN-MAX range + * + * @param progress + * @see #setMax(int) + * @see #setMin(int) + */ + public void setProgress(int progress) { + setProgress(progress, false); + } + + private void setProgress(int value, boolean fromUser) { + value = Math.max(mMin, Math.min(mMax, value)); + if (isAnimationRunning()) { + mPositionAnimator.cancel(); + } + + mValue = value; + notifyProgress(value, fromUser); + updateProgressMessage(value); + updateThumbPosFromCurrentProgress(); + } + + /** + * Get the current progress + * + * @return the current progress :-P + */ + public int getProgress() { + return mValue; + } + + /** + * Sets a listener to receive notifications of changes to the DiscreteSeekBar's progress level. Also + * provides notifications of when the DiscreteSeekBar shows/hides the bubble indicator. + * + * @param listener The seek bar notification listener + * @see OnProgressChangeListener + */ + public void setOnProgressChangeListener(@Nullable OnProgressChangeListener listener) { + mPublicChangeListener = listener; + } + + /** + * Sets the color of the seek thumb, as well as the color of the popup indicator. + * + * @param thumbColor The color the seek thumb will be changed to + * @param indicatorColor The color the popup indicator will be changed to + * The indicator will animate from thumbColor to indicatorColor + * when opening + */ + public void setThumbColor(int thumbColor, int indicatorColor) { + mThumb.setColorStateList(ColorStateList.valueOf(thumbColor)); + mIndicator.setColors(indicatorColor, thumbColor); + } + + /** + * Sets the color of the seek thumb, as well as the color of the popup indicator. + * + * @param thumbColorStateList The ColorStateList the seek thumb will be changed to + * @param indicatorColor The color the popup indicator will be changed to + * The indicator will animate from thumbColorStateList(pressed state) to indicatorColor + * when opening + */ + public void setThumbColor(@NonNull ColorStateList thumbColorStateList, int indicatorColor) { + mThumb.setColorStateList(thumbColorStateList); + //we use the "pressed" color to morph the indicator from it to its own color + int thumbColor = thumbColorStateList.getColorForState(new int[]{PRESSED_STATE}, thumbColorStateList.getDefaultColor()); + mIndicator.setColors(indicatorColor, thumbColor); + } + + /** + * Sets the color of the seekbar scrubber + * + * @param color The color the track scrubber will be changed to + */ + public void setScrubberColor(int color) { + mScrubber.setColorStateList(ColorStateList.valueOf(color)); + } + + /** + * Sets the color of the seekbar scrubber + * + * @param colorStateList The ColorStateList the track scrubber will be changed to + */ + public void setScrubberColor(@NonNull ColorStateList colorStateList) { + mScrubber.setColorStateList(colorStateList); + } + + /** + * Sets the color of the seekbar ripple + * + * @param color The color the track ripple will be changed to + */ + public void setRippleColor(int color) { + setRippleColor(new ColorStateList(new int[][]{new int[]{}}, new int[]{color})); + } + + /** + * Sets the color of the seekbar ripple + * + * @param colorStateList The ColorStateList the track ripple will be changed to + */ + public void setRippleColor(@NonNull ColorStateList colorStateList) { + SeekBarCompat.setRippleColor(mRipple, colorStateList); + } + + /** + * Sets the color of the seekbar scrubber + * + * @param color The color the track will be changed to + */ + public void setTrackColor(int color) { + mTrack.setColorStateList(ColorStateList.valueOf(color)); + } + + /** + * Sets the color of the seekbar scrubber + * + * @param colorStateList The ColorStateList the track will be changed to + */ + public void setTrackColor(@NonNull ColorStateList colorStateList) { + mTrack.setColorStateList(colorStateList); + } + + /** + * If {@code enabled} is false the indicator won't appear. By default popup indicator is + * enabled. + */ + public void setIndicatorPopupEnabled(boolean enabled) { + this.mIndicatorPopupEnabled = enabled; + } + + private void updateIndicatorSizes() { + if (!isInEditMode()) { + if (mNumericTransformer.useStringTransform()) { + mIndicator.updateSizes(mNumericTransformer.transformToString(mMax)); + } else { + mIndicator.updateSizes(convertValueToMessage(mNumericTransformer.transform(mMax))); + } + } + + } + + private void notifyProgress(int value, boolean fromUser) { + if (mPublicChangeListener != null) { + mPublicChangeListener.onProgressChanged(DiscreteSeekBar.this, value, fromUser); + } + onValueChanged(value); + } + + private void notifyBubble(boolean open) { + if (open) { + onShowBubble(); + } else { + onHideBubble(); + } + } + + /** + * When the {@link DiscreteSeekBar} enters pressed or focused state + * the bubble with the value will be shown, and this method called + *

+ * Subclasses may override this to add functionality around this event + *

+ */ + protected void onShowBubble() { + } + + /** + * When the {@link DiscreteSeekBar} exits pressed or focused state + * the bubble with the value will be hidden, and this method called + *

+ * Subclasses may override this to add functionality around this event + *

+ */ + protected void onHideBubble() { + } + + /** + * When the {@link DiscreteSeekBar} value changes this method is called + *

+ * Subclasses may override this to add functionality around this event + * without having to specify a {@link OnProgressChangeListener} + *

+ */ + protected void onValueChanged(int value) { + } + + private void updateKeyboardRange() { + int range = mMax - mMin; + if ((mKeyProgressIncrement == 0) || (range / mKeyProgressIncrement > 20)) { + // It will take the user too long to change this via keys, change it + // to something more reasonable + mKeyProgressIncrement = Math.max(1, Math.round((float) range / 20)); + } + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int height = mThumb.getIntrinsicHeight() + getPaddingTop() + getPaddingBottom(); + height += (mAddedTouchBounds * 2); + setMeasuredDimension(widthSize, height); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (changed) { + removeCallbacks(mShowIndicatorRunnable); + if (!isInEditMode()) { + mIndicator.dismissComplete(); + } + updateFromDrawableState(); + } + } + + @Override + public void scheduleDrawable(Drawable who, Runnable what, long when) { + super.scheduleDrawable(who, what, when); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + int thumbWidth = mThumb.getIntrinsicWidth(); + int thumbHeight = mThumb.getIntrinsicHeight(); + int addedThumb = mAddedTouchBounds; + int halfThumb = thumbWidth / 2; + int paddingLeft = getPaddingLeft() + addedThumb; + int paddingRight = getPaddingRight(); + int bottom = getHeight() - getPaddingBottom() - addedThumb; + mThumb.setBounds(paddingLeft, bottom - thumbHeight, paddingLeft + thumbWidth, bottom); + int trackHeight = Math.max(mTrackHeight / 2, 1); + mTrack.setBounds(paddingLeft + halfThumb, bottom - halfThumb - trackHeight, + getWidth() - halfThumb - paddingRight - addedThumb, bottom - halfThumb + trackHeight); + int available = getWidth() - paddingRight - addedThumb - paddingLeft - thumbWidth; + float scaleDrawBase = (mValueBase - mMin) / (float) (mMax - mMin); + final int thumbPosBase = (int) (scaleDrawBase * available + 0.5f); + mTrackBase.setBounds(paddingLeft + halfThumb + thumbPosBase - mTrackBaseHeight / 8, bottom - halfThumb - mTrackBaseHeight / 2, + paddingLeft + halfThumb + thumbPosBase + mTrackBaseHeight / 8, bottom - halfThumb + mTrackBaseHeight / 2); + int scrubberHeight = Math.max(mScrubberHeight / 2, 2); + mScrubber.setBounds(paddingLeft + halfThumb, bottom - halfThumb - scrubberHeight, + paddingLeft + halfThumb, bottom - halfThumb + scrubberHeight); + + //Update the thumb position after size changed + updateThumbPosFromCurrentProgress(); + } + + @Override + protected synchronized void onDraw(Canvas canvas) { + if (!isLollipopOrGreater) { + mRipple.draw(canvas); + } + super.onDraw(canvas); + mTrack.draw(canvas); + mScrubber.draw(canvas); + if (mMin != mValueBase && mMax != mValueBase) { + mTrackBase.draw(canvas); + } + mThumb.draw(canvas); + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + updateFromDrawableState(); + } + + private void updateFromDrawableState() { + int[] state = getDrawableState(); + boolean focused = false; + boolean pressed = false; + for (int i : state) { + if (i == FOCUSED_STATE) { + focused = true; + } else if (i == PRESSED_STATE) { + pressed = true; + } + } + if (isEnabled() && (focused || pressed) && mIndicatorPopupEnabled) { + //We want to add a small delay here to avoid + //poping in/out on simple taps + removeCallbacks(mShowIndicatorRunnable); + postDelayed(mShowIndicatorRunnable, INDICATOR_DELAY_FOR_TAPS); + } else { + hideFloater(); + } + mThumb.setState(state); + mTrack.setState(state); + mScrubber.setState(state); + mRipple.setState(state); + } + + private void updateProgressMessage(int value) { + if (!isInEditMode()) { + if (mNumericTransformer.useStringTransform()) { + mIndicator.setValue(mNumericTransformer.transformToString(value)); + } else { + mIndicator.setValue(convertValueToMessage(mNumericTransformer.transform(value))); + } + } + } + + private String convertValueToMessage(int value) { + String format = mIndicatorFormatter != null ? mIndicatorFormatter : DEFAULT_FORMATTER; + //We're trying to re-use the Formatter here to avoid too much memory allocations + //But I'm not completey sure if it's doing anything good... :( + //Previously, this condition was wrong so the Formatter was always re-created + //But as I fixed the condition, the formatter started outputting trash characters from previous + //calls, so I mark the StringBuilder as empty before calling format again. + + //Anyways, I see the memory usage still go up on every call to this method + //and I have no clue on how to fix that... damn Strings... + if (mFormatter == null || !mFormatter.locale().equals(Locale.getDefault())) { + int bufferSize = format.length() + String.valueOf(mMax).length(); + if (mFormatBuilder == null) { + mFormatBuilder = new StringBuilder(bufferSize); + } else { + mFormatBuilder.ensureCapacity(bufferSize); + } + mFormatter = new Formatter(mFormatBuilder, Locale.getDefault()); + } else { + mFormatBuilder.setLength(0); + } + return mFormatter.format(format, value).toString(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled()) { + return false; + } + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + mDownX = event.getX(); + startDragging(event, isInScrollingContainer()); + break; + case MotionEvent.ACTION_MOVE: + if (isDragging()) { + updateDragging(event); + } else { + final float x = event.getX(); + if (Math.abs(x - mDownX) > mTouchSlop) { + startDragging(event, false); + } + } + break; + case MotionEvent.ACTION_UP: + if (!isDragging() && mAllowTrackClick) { + startDragging(event, false); + updateDragging(event); + } + stopDragging(); + break; + case MotionEvent.ACTION_CANCEL: + stopDragging(); + break; + } + return true; + } + + private boolean isInScrollingContainer() { + return SeekBarCompat.isInScrollingContainer(getParent()); + } + + private boolean startDragging(MotionEvent ev, boolean ignoreTrackIfInScrollContainer) { + final Rect bounds = mTempRect; + mThumb.copyBounds(bounds); + //Grow the current thumb rect for a bigger touch area + bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); + mIsDragging = (bounds.contains((int) ev.getX(), (int) ev.getY())); + if (!mIsDragging && mAllowTrackClick && !ignoreTrackIfInScrollContainer) { + //If the user clicked outside the thumb, we compute the current position + //and force an immediate drag to it. + mIsDragging = true; + mDragOffset = (bounds.width() / 2) - mAddedTouchBounds; + updateDragging(ev); + //As the thumb may have moved, get the bounds again + mThumb.copyBounds(bounds); + bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); + } + if (mIsDragging) { + setPressed(true); + attemptClaimDrag(); + setHotspot(ev.getX(), ev.getY()); + mDragOffset = (int) (ev.getX() - bounds.left - mAddedTouchBounds); + if (mPublicChangeListener != null) { + mPublicChangeListener.onStartTrackingTouch(this); + } + } + return mIsDragging; + } + + private boolean isDragging() { + return mIsDragging; + } + + private void stopDragging() { + if (mPublicChangeListener != null) { + mPublicChangeListener.onStopTrackingTouch(this); + } + mIsDragging = false; + setPressed(false); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + boolean handled = false; + if (isEnabled()) { + int progress = getAnimatedProgress(); + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_LEFT: + handled = true; + if (progress <= mMin) + break; + animateSetProgress(progress - mKeyProgressIncrement); + break; + case KeyEvent.KEYCODE_DPAD_RIGHT: + handled = true; + if (progress >= mMax) + break; + animateSetProgress(progress + mKeyProgressIncrement); + break; + } + } + + return handled || super.onKeyDown(keyCode, event); + } + + private int getAnimatedProgress() { + return isAnimationRunning() ? getAnimationTarget() : mValue; + } + + + boolean isAnimationRunning() { + return mPositionAnimator != null && mPositionAnimator.isRunning(); + } + + void animateSetProgress(int progress) { + final float curProgress = isAnimationRunning() ? getAnimationPosition() : getProgress(); + + if (progress < mMin) { + progress = mMin; + } else if (progress > mMax) { + progress = mMax; + } + //setProgressValueOnly(progress); + + if (mPositionAnimator != null) { + mPositionAnimator.cancel(); + } + + mAnimationTarget = progress; + mPositionAnimator = AnimatorCompat.create(curProgress, + progress, new AnimatorCompat.AnimationFrameUpdateListener() { + @Override + public void onAnimationFrame(float currentValue) { + setAnimationPosition(currentValue); + } + }); + mPositionAnimator.setDuration(PROGRESS_ANIMATION_DURATION); + mPositionAnimator.start(); + } + + private int getAnimationTarget() { + return mAnimationTarget; + } + + void setAnimationPosition(float position) { + mAnimationPosition = position; + float currentScale = (position - mMin) / (float) (mMax - mMin); + updateProgressFromAnimation(currentScale); + } + + float getAnimationPosition() { + return mAnimationPosition; + } + + + private void updateDragging(MotionEvent ev) { + setHotspot(ev.getX(), ev.getY()); + int x = (int) ev.getX(); + Rect oldBounds = mThumb.getBounds(); + int halfThumb = oldBounds.width() / 2; + int addedThumb = mAddedTouchBounds; + int newX = x - mDragOffset + halfThumb; + int left = getPaddingLeft() + halfThumb + addedThumb; + int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb); + if (newX < left) { + newX = left; + } else if (newX > right) { + newX = right; + } + + int available = right - left; + float scale = (float) (newX - left) / (float) available; + if (isRtl()) { + scale = 1f - scale; + } + int progress = Math.round((scale * (mMax - mMin)) + mMin); + setProgress(progress, true); + } + + private void updateProgressFromAnimation(float scale) { + Rect bounds = mThumb.getBounds(); + int halfThumb = bounds.width() / 2; + int addedThumb = mAddedTouchBounds; + int left = getPaddingLeft() + halfThumb + addedThumb; + int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb); + int available = right - left; + int progress = Math.round((scale * (mMax - mMin)) + mMin); + //we don't want to just call setProgress here to avoid the animation being cancelled, + //and this position is not bound to a real progress value but interpolated + if (progress != getProgress()) { + mValue = progress; + notifyProgress(mValue, true); + updateProgressMessage(progress); + } + final int thumbPos = (int) (scale * available + 0.5f); + + float scaleDrawBase = (mValueBase - mMin) / (float) (mMax - mMin); + final int thumbPosBase = (int) (scaleDrawBase * available + 0.5f); + + updateThumbPos(thumbPosBase, thumbPos); + } + + private void updateThumbPosFromCurrentProgress() { + int thumbWidth = mThumb.getIntrinsicWidth(); + int addedThumb = mAddedTouchBounds; + int halfThumb = thumbWidth / 2; + + //This doesn't matter if RTL, as we just need the "avaiable" area + int left = getPaddingLeft() + halfThumb + addedThumb; + int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb); + int available = right - left; + + float scaleDraw = (mValue - mMin) / (float) (mMax - mMin); + float scaleDrawBase = (mValueBase - mMin) / (float) (mMax - mMin); + + final int thumbPos = (int) (scaleDraw * available + 0.5f); + final int thumbPosBase = (int) (scaleDrawBase * available + 0.5f); + updateThumbPos(thumbPosBase, thumbPos); + } + + private void updateThumbPos(int base, int value) { + base += getPaddingLeft() + mAddedTouchBounds; + value += getPaddingLeft() + mAddedTouchBounds; + int start = Math.min(base, value); + int end = Math.max(base, value); + + int thumbWidth = mThumb.getIntrinsicWidth(); + int halfThumb = thumbWidth / 2; + mThumb.copyBounds(mInvalidateRect); + mThumb.setBounds(value, mInvalidateRect.top, value + thumbWidth, mInvalidateRect.bottom); + mScrubber.getBounds().left = start + halfThumb; + mScrubber.getBounds().right = end + halfThumb; + final Rect finalBounds = mTempRect; + mThumb.copyBounds(finalBounds); + if (!isInEditMode()) { + mIndicator.move(finalBounds.centerX()); + } + mTrackBase.getBounds().left = base + halfThumb - mTrackBaseHeight / 8; + mTrackBase.getBounds().right = base + halfThumb + mTrackBaseHeight / 8; + mInvalidateRect.inset(-mAddedTouchBounds, -mAddedTouchBounds); + finalBounds.inset(-mAddedTouchBounds, -mAddedTouchBounds); + mInvalidateRect.union(finalBounds); + SeekBarCompat.setHotspotBounds(mRipple, finalBounds.left, finalBounds.top, finalBounds.right, finalBounds.bottom); + invalidate(mInvalidateRect); + } + + + private void setHotspot(float x, float y) { + DrawableCompat.setHotspot(mRipple, x, y); + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return who == mThumb || who == mTrack || who == mScrubber || who == mRipple || super.verifyDrawable(who); + } + + private void attemptClaimDrag() { + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + } + + private Runnable mShowIndicatorRunnable = new Runnable() { + @Override + public void run() { + showFloater(); + } + }; + + private void showFloater() { + if (!isInEditMode()) { + mThumb.animateToPressed(); + mIndicator.showIndicator(this, mThumb.getBounds()); + notifyBubble(true); + } + } + + private void hideFloater() { + removeCallbacks(mShowIndicatorRunnable); + if (!isInEditMode()) { + mIndicator.dismiss(); + notifyBubble(false); + } + } + + private MarkerDrawable.MarkerAnimationListener mFloaterListener = new MarkerDrawable.MarkerAnimationListener() { + @Override + public void onClosingComplete() { + mThumb.animateToNormal(); + } + + @Override + public void onOpeningComplete() { + + } + + }; + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + removeCallbacks(mShowIndicatorRunnable); + if (!isInEditMode()) { + mIndicator.dismissComplete(); + } + } + + @SuppressLint("WrongConstant") + public boolean isRtl() { + return (ViewCompat.getLayoutDirection(this) == LAYOUT_DIRECTION_RTL) && mMirrorForRtl; + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + CustomState state = new CustomState(superState); + state.progress = getProgress(); + state.max = mMax; + state.min = mMin; + return state; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state == null || !state.getClass().equals(CustomState.class)) { + super.onRestoreInstanceState(state); + return; + } + + CustomState customState = (CustomState) state; + setMin(customState.min); + setMax(customState.max); + setProgress(customState.progress, false); + super.onRestoreInstanceState(customState.getSuperState()); + } + + static class CustomState extends BaseSavedState { + private int progress; + private int max; + private int min; + + public CustomState(Parcel source) { + super(source); + progress = source.readInt(); + max = source.readInt(); + min = source.readInt(); + } + + public CustomState(Parcelable superState) { + super(superState); + } + + @Override + public void writeToParcel(Parcel outcoming, int flags) { + super.writeToParcel(outcoming, flags); + outcoming.writeInt(progress); + outcoming.writeInt(max); + outcoming.writeInt(min); + } + + public static final Creator CREATOR = + new Creator() { + + @Override + public CustomState[] newArray(int size) { + return new CustomState[size]; + } + + @Override + public CustomState createFromParcel(Parcel incoming) { + return new CustomState(incoming); + } + }; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/Marker.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/Marker.java new file mode 100644 index 000000000..cd354b290 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/Marker.java @@ -0,0 +1,196 @@ +package com.yunbao.faceunity.seekbar.internal; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.core.view.ViewCompat; + +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.seekbar.internal.compat.SeekBarCompat; +import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable; + + +/** + * {@link ViewGroup} to be used as the real indicator. + *

+ * I've used this to be able to accommodate the TextView + * and the {@link MarkerDrawable} + * with the required positions and offsets + *

+ * + * @hide + */ +public class Marker extends ViewGroup implements MarkerDrawable.MarkerAnimationListener { + private static final int PADDING_DP = 1; + private static final int ELEVATION_DP = 8; + //The TextView to show the info + private TextView mNumber; + //The max width of this View + private int mWidth; + //some distance between the thumb and our bubble marker. + //This will be added to our measured height + private int mSeparation; + MarkerDrawable mMarkerDrawable; + + public Marker(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) { + super(context, attrs, defStyleAttr); + //as we're reading the parent DiscreteSeekBar attributes, it may wrongly set this view's visibility. + setVisibility(View.VISIBLE); + + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DiscreteSeekBar, + R.attr.discreteSeekBarStyle, R.style.Widget_DiscreteSeekBar); + + int padding = (int) (PADDING_DP * displayMetrics.density) * 2; + int textAppearanceId = a.getResourceId(R.styleable.DiscreteSeekBar_dsb_indicatorTextAppearance, + R.style.Widget_DiscreteIndicatorTextAppearance); + mNumber = new TextView(context); + //Add some padding to this textView so the bubble has some space to breath + mNumber.setPadding(padding, 0, padding, 0); + mNumber.setTextAppearance(context, textAppearanceId); + mNumber.setGravity(Gravity.CENTER); + mNumber.setText(maxValue); + mNumber.setMaxLines(1); + mNumber.setSingleLine(true); + SeekBarCompat.setTextDirection(mNumber, TEXT_DIRECTION_LOCALE); + mNumber.setVisibility(View.INVISIBLE); + + //add some padding for the elevation shadow not to be clipped + //I'm sure there are better ways of doing this... + setPadding(padding, padding, padding, padding); + + resetSizes(maxValue); + + mSeparation = separation; + ColorStateList color = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_indicatorColor); + mMarkerDrawable = new MarkerDrawable(color, thumbSize); + mMarkerDrawable.setCallback(this); + mMarkerDrawable.setMarkerListener(this); + mMarkerDrawable.setExternalOffset(padding); + + //Elevation for anroid 5+ + float elevation = a.getDimension(R.styleable.DiscreteSeekBar_dsb_indicatorElevation, ELEVATION_DP * displayMetrics.density); + ViewCompat.setElevation(this, elevation); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + SeekBarCompat.setOutlineProvider(this, mMarkerDrawable); + } + a.recycle(); + } + + public void resetSizes(String maxValue) { + DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); + //Account for negative numbers... is there any proper way of getting the biggest string between our range???? + mNumber.setText("-" + maxValue); + //Do a first forced measure call for the TextView (with the biggest text content), + //to calculate the max width and use always the same. + //this avoids the TextView from shrinking and growing when the text content changes + int wSpec = MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, MeasureSpec.AT_MOST); + int hSpec = MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels, MeasureSpec.AT_MOST); + mNumber.measure(wSpec, hSpec); + mWidth = Math.max(mNumber.getMeasuredWidth(), mNumber.getMeasuredHeight()); + removeView(mNumber); + addView(mNumber, new FrameLayout.LayoutParams(mWidth, mWidth, Gravity.LEFT | Gravity.TOP)); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + mMarkerDrawable.draw(canvas); + super.dispatchDraw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + measureChildren(widthMeasureSpec, heightMeasureSpec); + int widthSize = mWidth + getPaddingLeft() + getPaddingRight(); + int heightSize = mWidth + getPaddingTop() + getPaddingBottom(); + //This diff is the basic calculation of the difference between + //a square side size and its diagonal + //this helps us account for the visual offset created by MarkerDrawable + //when leaving one of the corners un-rounded + int diff = (int) ((1.41f * mWidth) - mWidth) / 2; + setMeasuredDimension(widthSize, heightSize + diff + mSeparation); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int left = getPaddingLeft(); + int top = getPaddingTop(); + int right = getWidth() - getPaddingRight(); + int bottom = getHeight() - getPaddingBottom(); + //the TetView is always layout at the top + mNumber.layout(left, top, left + mWidth, top + mWidth); + //the MarkerDrawable uses the whole view, it will adapt itself... + // or it seems so... + mMarkerDrawable.setBounds(left, top, right, bottom); + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return who == mMarkerDrawable || super.verifyDrawable(who); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + //HACK: Sometimes, the animateOpen() call is made before the View is attached + //so the drawable cannot schedule itself to run the animation + //I think we can call it here safely. + //I've seen it happen in android 2.3.7 + animateOpen(); + } + + public void setValue(CharSequence value) { + mNumber.setText(value); + } + + public CharSequence getValue() { + return mNumber.getText(); + } + + public void animateOpen() { + mMarkerDrawable.stop(); + mMarkerDrawable.animateToPressed(); + } + + public void animateClose() { + mMarkerDrawable.stop(); + mNumber.setVisibility(View.INVISIBLE); + mMarkerDrawable.animateToNormal(); + } + + @Override + public void onOpeningComplete() { + mNumber.setVisibility(View.VISIBLE); + if (getParent() instanceof MarkerDrawable.MarkerAnimationListener) { + ((MarkerDrawable.MarkerAnimationListener) getParent()).onOpeningComplete(); + } + } + + @Override + public void onClosingComplete() { + if (getParent() instanceof MarkerDrawable.MarkerAnimationListener) { + ((MarkerDrawable.MarkerAnimationListener) getParent()).onClosingComplete(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mMarkerDrawable.stop(); + } + + public void setColors(int startColor, int endColor) { + mMarkerDrawable.setColors(startColor, endColor); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/PopupIndicator.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/PopupIndicator.java new file mode 100644 index 000000000..d968abd51 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/PopupIndicator.java @@ -0,0 +1,256 @@ +package com.yunbao.faceunity.seekbar.internal; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.IBinder; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import androidx.core.view.GravityCompat; + +import com.yunbao.faceunity.seekbar.internal.compat.SeekBarCompat; +import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable; + + +/** + * Class to manage the floating bubble thing, similar (but quite worse tested than {@link android.widget.PopupWindow} + *

+ *

+ * This will attach a View to the Window (full-width, measured-height, positioned just under the thumb) + *

+ * + * @hide + * @see #showIndicator(View, Rect) + * @see #dismiss() + * @see #dismissComplete() + * @see Floater + */ +public class PopupIndicator { + + private final WindowManager mWindowManager; + private boolean mShowing; + private Floater mPopupView; + //Outside listener for the DiscreteSeekBar to get MarkerDrawable animation events. + //The whole chain of events goes this way: + //MarkerDrawable->Marker->Floater->mListener->DiscreteSeekBar.... + //... phew! + private MarkerDrawable.MarkerAnimationListener mListener; + private int[] mDrawingLocation = new int[2]; + Point screenSize = new Point(); + + public PopupIndicator(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) { + mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + mPopupView = new Floater(context, attrs, defStyleAttr, maxValue, thumbSize, separation); + } + + public void updateSizes(String maxValue) { + dismissComplete(); + if (mPopupView != null) { + mPopupView.mMarker.resetSizes(maxValue); + } + } + + public void setListener(MarkerDrawable.MarkerAnimationListener listener) { + mListener = listener; + } + + /** + * We want the Floater to be full-width because the contents will be moved from side to side. + * We may/should change this in the future to use just the PARENT View width and/or pass it in the constructor + */ + private void measureFloater() { + int specWidth = View.MeasureSpec.makeMeasureSpec(screenSize.x, View.MeasureSpec.EXACTLY); + int specHeight = View.MeasureSpec.makeMeasureSpec(screenSize.y, View.MeasureSpec.AT_MOST); + mPopupView.measure(specWidth, specHeight); + } + + public void setValue(CharSequence value) { + mPopupView.mMarker.setValue(value); + } + + public boolean isShowing() { + return mShowing; + } + + public void showIndicator(View parent, Rect touchBounds) { + if (isShowing()) { + mPopupView.mMarker.animateOpen(); + return; + } + + IBinder windowToken = parent.getWindowToken(); + if (windowToken != null) { + WindowManager.LayoutParams p = createPopupLayout(windowToken); + + p.gravity = Gravity.TOP | GravityCompat.START; + updateLayoutParamsForPosiion(parent, p, touchBounds.bottom); + mShowing = true; + + translateViewIntoPosition(touchBounds.centerX()); + invokePopup(p); + } + } + + public void move(int x) { + if (!isShowing()) { + return; + } + translateViewIntoPosition(x); + } + + public void setColors(int startColor, int endColor) { + mPopupView.setColors(startColor, endColor); + } + + /** + * This will start the closing animation of the Marker and call onClosingComplete when finished + */ + public void dismiss() { + mPopupView.mMarker.animateClose(); + } + + /** + * FORCE the popup window to be removed. + * You typically calls this when the parent view is being removed from the window to avoid a Window Leak + */ + public void dismissComplete() { + if (isShowing()) { + mShowing = false; + try { + mWindowManager.removeViewImmediate(mPopupView); + } finally { + } + } + } + + + private void updateLayoutParamsForPosiion(View anchor, WindowManager.LayoutParams p, int yOffset) { + DisplayMetrics displayMetrics = anchor.getResources().getDisplayMetrics(); + screenSize.set(displayMetrics.widthPixels, displayMetrics.heightPixels); + + measureFloater(); + int measuredHeight = mPopupView.getMeasuredHeight(); + int paddingBottom = mPopupView.mMarker.getPaddingBottom(); + anchor.getLocationInWindow(mDrawingLocation); + p.x = 0; + p.y = mDrawingLocation[1] - measuredHeight + yOffset + paddingBottom; + p.width = screenSize.x; + p.height = measuredHeight; + } + + private void translateViewIntoPosition(final int x) { + mPopupView.setFloatOffset(x + mDrawingLocation[0]); + } + + private void invokePopup(WindowManager.LayoutParams p) { + mWindowManager.addView(mPopupView, p); + mPopupView.mMarker.animateOpen(); + } + + private WindowManager.LayoutParams createPopupLayout(IBinder token) { + WindowManager.LayoutParams p = new WindowManager.LayoutParams(); + p.gravity = Gravity.START | Gravity.TOP; + p.width = ViewGroup.LayoutParams.MATCH_PARENT; + p.height = ViewGroup.LayoutParams.MATCH_PARENT; + p.format = PixelFormat.TRANSLUCENT; + p.flags = computeFlags(p.flags); + p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; + p.token = token; + p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN; + p.setTitle("DiscreteSeekBar Indicator:" + Integer.toHexString(hashCode())); + + return p; + } + + /** + * I'm NOT completely sure how all this bitwise things work... + * + * @param curFlags + * @return + */ + private int computeFlags(int curFlags) { + curFlags &= ~( + WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES | + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | + WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | + WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES; + curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; + return curFlags; + } + + /** + * Small FrameLayout class to hold and move the bubble around when requested + * I wanted to use the {@link Marker} directly + * but doing so would make some things harder to implement + * (like moving the marker around, having the Marker's outline to work, etc) + */ + private class Floater extends FrameLayout implements MarkerDrawable.MarkerAnimationListener { + private Marker mMarker; + private int mOffset; + + public Floater(Context context, AttributeSet attrs, int defStyleAttr, String maxValue, int thumbSize, int separation) { + super(context); + mMarker = new Marker(context, attrs, defStyleAttr, maxValue, thumbSize, separation); + addView(mMarker, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + measureChildren(widthMeasureSpec, heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSie = mMarker.getMeasuredHeight(); + setMeasuredDimension(widthSize, heightSie); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int centerDiffX = mMarker.getMeasuredWidth() / 2; + int offset = (mOffset - centerDiffX); + mMarker.layout(offset, 0, offset + mMarker.getMeasuredWidth(), mMarker.getMeasuredHeight()); + } + + public void setFloatOffset(int x) { + mOffset = x; + int centerDiffX = mMarker.getMeasuredWidth() / 2; + int offset = (x - centerDiffX); + mMarker.offsetLeftAndRight(offset - mMarker.getLeft()); + //Without hardware acceleration (or API levels<11), offsetting a view seems to NOT invalidate the proper area. + //We should calc the proper invalidate Rect but this will be for now... + if (!SeekBarCompat.isHardwareAccelerated(this)) { + invalidate(); + } + } + + @Override + public void onClosingComplete() { + if (mListener != null) { + mListener.onClosingComplete(); + } + dismissComplete(); + } + + @Override + public void onOpeningComplete() { + if (mListener != null) { + mListener.onOpeningComplete(); + } + } + + public void setColors(int startColor, int endColor) { + mMarker.setColors(startColor, endColor); + } + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/AnimatorCompat.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/AnimatorCompat.java new file mode 100644 index 000000000..94f11d8f0 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/AnimatorCompat.java @@ -0,0 +1,73 @@ +package com.yunbao.faceunity.seekbar.internal.compat; + + +import com.yunbao.faceunity.seekbar.DiscreteSeekBar; + +/** + * Currently, there's no {@link android.animation.ValueAnimator} compatibility version + * and as we didn't want to throw in external dependencies, we made this small class. + *

+ *

+ * This will work like {@link android.support.v4.view.ViewPropertyAnimatorCompat}, that is, + * not doing anything on API<11 and using the default {@link android.animation.ValueAnimator} + * on API>=11 + *

+ *

+ * This class is used to provide animation to the {@link DiscreteSeekBar} + * when navigating with the Keypad + *

+ * + * @hide + */ +public abstract class AnimatorCompat { + public interface AnimationFrameUpdateListener { + public void onAnimationFrame(float currentValue); + } + + AnimatorCompat() { + + } + + public abstract void cancel(); + + public abstract boolean isRunning(); + + public abstract void setDuration(int progressAnimationDuration); + + public abstract void start(); + + public static final AnimatorCompat create(float start, float end, AnimationFrameUpdateListener listener) { + return new AnimatorCompatBase(start, end, listener); + } + + private static class AnimatorCompatBase extends AnimatorCompat { + + private final AnimationFrameUpdateListener mListener; + private final float mEndValue; + + public AnimatorCompatBase(float start, float end, AnimationFrameUpdateListener listener) { + mListener = listener; + mEndValue = end; + } + + @Override + public void cancel() { + + } + + @Override + public boolean isRunning() { + return false; + } + + @Override + public void setDuration(int progressAnimationDuration) { + + } + + @Override + public void start() { + mListener.onAnimationFrame(mEndValue); + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/SeekBarCompat.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/SeekBarCompat.java new file mode 100644 index 000000000..55b9e583f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/SeekBarCompat.java @@ -0,0 +1,130 @@ +package com.yunbao.faceunity.seekbar.internal.compat; + +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.os.Build; +import android.view.View; +import android.view.ViewParent; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.DrawableCompat; + +import com.yunbao.faceunity.seekbar.internal.drawable.AlmostRippleDrawable; +import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable; + + +/** + * Wrapper compatibility class to call some API-Specific methods + * And offer alternate procedures when possible + * + * @hide + */ +public class SeekBarCompat { + + /** + * Sets the custom Outline provider on API>=21. + * Does nothing on API<21 + * + * @param view + * @param markerDrawable + */ + public static void setOutlineProvider(View view, final MarkerDrawable markerDrawable) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + SeekBarCompatDontCrash.setOutlineProvider(view, markerDrawable); + } + } + + /** + * Our DiscreteSeekBar implementation uses a circular drawable on API < 21 + * because we don't set it as Background, but draw it ourselves + * + * @param colorStateList + * @return + */ + public static Drawable getRipple(ColorStateList colorStateList) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + return SeekBarCompatDontCrash.getRipple(colorStateList); + } else { + return new AlmostRippleDrawable(colorStateList); + } + } + + /** + * Sets the color of the seekbar ripple + * + * @param drawable + * @param colorStateList The ColorStateList the track ripple will be changed to + */ + public static void setRippleColor(@NonNull Drawable drawable, ColorStateList colorStateList) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ((RippleDrawable) drawable).setColor(colorStateList); + } else { + ((AlmostRippleDrawable) drawable).setColor(colorStateList); + } + } + + /** + * As our DiscreteSeekBar implementation uses a circular drawable on API < 21 + * we want to use the same method to set its bounds as the Ripple's hotspot bounds. + * + * @param drawable + * @param left + * @param top + * @param right + * @param bottom + */ + public static void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + //We don't want the full size rect, Lollipop ripple would be too big + int size = (right - left) / 8; + DrawableCompat.setHotspotBounds(drawable, left + size, top + size, right - size, bottom - size); + } else { + drawable.setBounds(left, top, right, bottom); + } + } + + /** + * android.support.v4.view.ViewCompat SHOULD include this once and for all!! + * But it doesn't... + * + * @param view + * @param background + */ + @SuppressWarnings("deprecation") + public static void setBackground(View view, Drawable background) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + SeekBarCompatDontCrash.setBackground(view, background); + } else { + view.setBackgroundDrawable(background); + } + } + + /** + * Sets the TextView text direction attribute when possible + * + * @param textView + * @param textDirection + * @see TextView#setTextDirection(int) + */ + public static void setTextDirection(TextView textView, int textDirection) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + SeekBarCompatDontCrash.setTextDirection(textView, textDirection); + } + } + + public static boolean isInScrollingContainer(ViewParent p) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + return SeekBarCompatDontCrash.isInScrollingContainer(p); + } + return false; + } + + public static boolean isHardwareAccelerated(View view) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + return SeekBarCompatDontCrash.isHardwareAccelerated(view); + } + return false; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/SeekBarCompatDontCrash.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/SeekBarCompatDontCrash.java new file mode 100644 index 000000000..ef13919fb --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/compat/SeekBarCompatDontCrash.java @@ -0,0 +1,59 @@ +package com.yunbao.faceunity.seekbar.internal.compat; + +import android.annotation.TargetApi; +import android.content.res.ColorStateList; +import android.graphics.Outline; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewOutlineProvider; +import android.view.ViewParent; +import android.widget.TextView; + +import com.yunbao.faceunity.seekbar.internal.drawable.MarkerDrawable; + + +/** + * Wrapper compatibility class to call some API-Specific methods + * And offer alternate procedures when possible + * + * @hide + */ +@TargetApi(21) +class SeekBarCompatDontCrash { + public static void setOutlineProvider(View marker, final MarkerDrawable markerDrawable) { + marker.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setConvexPath(markerDrawable.getPath()); + } + }); + } + + public static Drawable getRipple(ColorStateList colorStateList) { + return new RippleDrawable(colorStateList, null, null); + } + + public static void setBackground(View view, Drawable background) { + view.setBackground(background); + } + + public static void setTextDirection(TextView number, int textDirection) { + number.setTextDirection(textDirection); + } + + public static boolean isInScrollingContainer(ViewParent p) { + while (p != null && p instanceof ViewGroup) { + if (((ViewGroup) p).shouldDelayChildPressedState()) { + return true; + } + p = p.getParent(); + } + return false; + } + + public static boolean isHardwareAccelerated(View view) { + return view.isHardwareAccelerated(); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/AlmostRippleDrawable.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/AlmostRippleDrawable.java new file mode 100644 index 000000000..e69e2df5c --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/AlmostRippleDrawable.java @@ -0,0 +1,206 @@ +package com.yunbao.faceunity.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Animatable; +import android.os.SystemClock; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + +import androidx.annotation.NonNull; + + +public class AlmostRippleDrawable extends StateDrawable implements Animatable { + private static final long FRAME_DURATION = 1000 / 60; + private static final int ANIMATION_DURATION = 250; + + private static final float INACTIVE_SCALE = 0f; + private static final float ACTIVE_SCALE = 1f; + private float mCurrentScale = INACTIVE_SCALE; + private Interpolator mInterpolator; + private long mStartTime; + private boolean mReverse = false; + private boolean mRunning = false; + private int mDuration = ANIMATION_DURATION; + private float mAnimationInitialValue; + //We don't use colors just with our drawable state because of animations + private int mPressedColor; + private int mFocusedColor; + private int mDisabledColor; + private int mRippleColor; + private int mRippleBgColor; + + public AlmostRippleDrawable(@NonNull ColorStateList tintStateList) { + super(tintStateList); + mInterpolator = new AccelerateDecelerateInterpolator(); + setColor(tintStateList); + } + + public void setColor(@NonNull ColorStateList tintStateList) { + int defaultColor = tintStateList.getDefaultColor(); + mFocusedColor = tintStateList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}, defaultColor); + mPressedColor = tintStateList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, defaultColor); + mDisabledColor = tintStateList.getColorForState(new int[]{-android.R.attr.state_enabled}, defaultColor); + + //The ripple should be partially transparent + mFocusedColor = getModulatedAlphaColor(130, mFocusedColor); + mPressedColor = getModulatedAlphaColor(130, mPressedColor); + mDisabledColor = getModulatedAlphaColor(130, mDisabledColor); + } + + private static int getModulatedAlphaColor(int alphaValue, int originalColor) { + int alpha = Color.alpha(originalColor); + int scale = alphaValue + (alphaValue >> 7); + alpha = alpha * scale >> 8; + return Color.argb(alpha, Color.red(originalColor), Color.green(originalColor), Color.blue(originalColor)); + } + + @Override + public void doDraw(Canvas canvas, Paint paint) { + Rect bounds = getBounds(); + int size = Math.min(bounds.width(), bounds.height()); + float scale = mCurrentScale; + int rippleColor = mRippleColor; + int bgColor = mRippleBgColor; + float radius = (size / 2); + float radiusAnimated = radius * scale; + if (scale > INACTIVE_SCALE) { + if (bgColor != 0) { + paint.setColor(bgColor); + paint.setAlpha(decreasedAlpha(Color.alpha(bgColor))); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), radius, paint); + } + if (rippleColor != 0) { + paint.setColor(rippleColor); + paint.setAlpha(modulateAlpha(Color.alpha(rippleColor))); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), radiusAnimated, paint); + } + } + } + + private int decreasedAlpha(int alpha) { + int scale = 100 + (100 >> 7); + return alpha * scale >> 8; + } + + @Override + public boolean setState(int[] stateSet) { + int[] oldState = getState(); + boolean oldPressed = false; + for (int i : oldState) { + if (i == android.R.attr.state_pressed) { + oldPressed = true; + } + } + super.setState(stateSet); + boolean focused = false; + boolean pressed = false; + boolean disabled = true; + for (int i : stateSet) { + if (i == android.R.attr.state_focused) { + focused = true; + } else if (i == android.R.attr.state_pressed) { + pressed = true; + } else if (i == android.R.attr.state_enabled) { + disabled = false; + } + } + + if (disabled) { + unscheduleSelf(mUpdater); + mRippleColor = mDisabledColor; + mRippleBgColor = 0; + mCurrentScale = ACTIVE_SCALE / 2; + invalidateSelf(); + } else { + if (pressed) { + animateToPressed(); + mRippleColor = mRippleBgColor = mPressedColor; + } else if (oldPressed) { + mRippleColor = mRippleBgColor = mPressedColor; + animateToNormal(); + } else if (focused) { + mRippleColor = mFocusedColor; + mRippleBgColor = 0; + mCurrentScale = ACTIVE_SCALE; + invalidateSelf(); + } else { + mRippleColor = 0; + mRippleBgColor = 0; + mCurrentScale = INACTIVE_SCALE; + invalidateSelf(); + } + } + return true; + } + + public void animateToPressed() { + unscheduleSelf(mUpdater); + if (mCurrentScale < ACTIVE_SCALE) { + mReverse = false; + mRunning = true; + mAnimationInitialValue = mCurrentScale; + float durationFactor = 1f - ((mAnimationInitialValue - INACTIVE_SCALE) / (ACTIVE_SCALE - INACTIVE_SCALE)); + mDuration = (int) (ANIMATION_DURATION * durationFactor); + mStartTime = SystemClock.uptimeMillis(); + scheduleSelf(mUpdater, mStartTime + FRAME_DURATION); + } + } + + public void animateToNormal() { + unscheduleSelf(mUpdater); + if (mCurrentScale > INACTIVE_SCALE) { + mReverse = true; + mRunning = true; + mAnimationInitialValue = mCurrentScale; + float durationFactor = 1f - ((mAnimationInitialValue - ACTIVE_SCALE) / (INACTIVE_SCALE - ACTIVE_SCALE)); + mDuration = (int) (ANIMATION_DURATION * durationFactor); + mStartTime = SystemClock.uptimeMillis(); + scheduleSelf(mUpdater, mStartTime + FRAME_DURATION); + } + } + + private void updateAnimation(float factor) { + float initial = mAnimationInitialValue; + float destination = mReverse ? INACTIVE_SCALE : ACTIVE_SCALE; + mCurrentScale = initial + (destination - initial) * factor; + invalidateSelf(); + } + + private final Runnable mUpdater = new Runnable() { + + @Override + public void run() { + + long currentTime = SystemClock.uptimeMillis(); + long diff = currentTime - mStartTime; + if (diff < mDuration) { + float interpolation = mInterpolator.getInterpolation((float) diff / (float) mDuration); + scheduleSelf(mUpdater, currentTime + FRAME_DURATION); + updateAnimation(interpolation); + } else { + unscheduleSelf(mUpdater); + mRunning = false; + updateAnimation(1f); + } + } + }; + + @Override + public void start() { + //No-Op. We control our own animation + } + + @Override + public void stop() { + //No-Op. We control our own animation + } + + @Override + public boolean isRunning() { + return mRunning; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/MarkerDrawable.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/MarkerDrawable.java new file mode 100644 index 000000000..8c5a04745 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/MarkerDrawable.java @@ -0,0 +1,235 @@ +package com.yunbao.faceunity.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Animatable; +import android.os.SystemClock; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + +import androidx.annotation.NonNull; + + +/** + * Implementation of {@link StateDrawable} to draw a morphing marker symbol. + *

+ * It's basically an implementation of an {@link Animatable} Drawable with the following details: + *

+ *
    + *
  • Animates from a circle shape to a "marker" shape just using a RoundRect
  • + *
  • Animates color change from the normal state color to the pressed state color
  • + *
  • Uses a {@link Path} to also serve as Outline for API>=21
  • + *
+ * + * @hide + */ +public class MarkerDrawable extends StateDrawable implements Animatable { + private static final long FRAME_DURATION = 1000 / 60; + private static final int ANIMATION_DURATION = 250; + + private float mCurrentScale = 0f; + private Interpolator mInterpolator; + private long mStartTime; + private boolean mReverse = false; + private boolean mRunning = false; + private int mDuration = ANIMATION_DURATION; + //size of the actual thumb drawable to use as circle state size + private float mClosedStateSize; + //value to store que current scale when starting an animation and interpolate from it + private float mAnimationInitialValue; + //extra offset directed from the View to account + //for its internal padding between circle state and marker state + private int mExternalOffset; + //colors for interpolation + private int mStartColor;//Color when the Marker is OPEN + private int mEndColor;//Color when the arker is CLOSED + + Path mPath = new Path(); + RectF mRect = new RectF(); + Matrix mMatrix = new Matrix(); + private MarkerAnimationListener mMarkerListener; + + public MarkerDrawable(@NonNull ColorStateList tintList, int closedSize) { + super(tintList); + mInterpolator = new AccelerateDecelerateInterpolator(); + mClosedStateSize = closedSize; + mStartColor = tintList.getColorForState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, tintList.getDefaultColor()); + mEndColor = tintList.getDefaultColor(); + + } + + public void setExternalOffset(int offset) { + mExternalOffset = offset; + } + + /** + * The two colors that will be used for the seek thumb. + * + * @param startColor Color used for the seek thumb + * @param endColor Color used for popup indicator + */ + public void setColors(int startColor, int endColor) { + mStartColor = startColor; + mEndColor = endColor; + } + + @Override + void doDraw(Canvas canvas, Paint paint) { + if (!mPath.isEmpty()) { + paint.setStyle(Paint.Style.FILL); + int color = blendColors(mStartColor, mEndColor, mCurrentScale); + paint.setColor(color); + canvas.drawPath(mPath, paint); + } + } + + public Path getPath() { + return mPath; + } + + @Override + protected void onBoundsChange(Rect bounds) { + super.onBoundsChange(bounds); + computePath(bounds); + } + + private void computePath(Rect bounds) { + final float currentScale = mCurrentScale; + final Path path = mPath; + final RectF rect = mRect; + final Matrix matrix = mMatrix; + + path.reset(); + int totalSize = Math.min(bounds.width(), bounds.height()); + + float initial = mClosedStateSize; + float destination = totalSize; + float currentSize = initial + (destination - initial) * currentScale; + + float halfSize = currentSize / 2f; + float inverseScale = 1f - currentScale; + float cornerSize = halfSize * inverseScale; + float[] corners = new float[]{halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize}; + rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize); + path.addRoundRect(rect, corners, Path.Direction.CCW); + matrix.reset(); + matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize); + matrix.postTranslate((bounds.width() - currentSize) / 2, 0); + float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale; + matrix.postTranslate(0, hDiff); + path.transform(matrix); + } + + private void updateAnimation(float factor) { + float initial = mAnimationInitialValue; + float destination = mReverse ? 0f : 1f; + mCurrentScale = initial + (destination - initial) * factor; + computePath(getBounds()); + invalidateSelf(); + } + + public void animateToPressed() { + unscheduleSelf(mUpdater); + mReverse = false; + if (mCurrentScale < 1) { + mRunning = true; + mAnimationInitialValue = mCurrentScale; + float durationFactor = 1f - mCurrentScale; + mDuration = (int) (ANIMATION_DURATION * durationFactor); + mStartTime = SystemClock.uptimeMillis(); + scheduleSelf(mUpdater, mStartTime + FRAME_DURATION); + } else { + notifyFinishedToListener(); + } + } + + public void animateToNormal() { + mReverse = true; + unscheduleSelf(mUpdater); + if (mCurrentScale > 0) { + mRunning = true; + mAnimationInitialValue = mCurrentScale; + float durationFactor = 1f - mCurrentScale; + mDuration = ANIMATION_DURATION - (int) (ANIMATION_DURATION * durationFactor); + mStartTime = SystemClock.uptimeMillis(); + scheduleSelf(mUpdater, mStartTime + FRAME_DURATION); + } else { + notifyFinishedToListener(); + } + } + + private final Runnable mUpdater = new Runnable() { + + @Override + public void run() { + + long currentTime = SystemClock.uptimeMillis(); + long diff = currentTime - mStartTime; + if (diff < mDuration) { + float interpolation = mInterpolator.getInterpolation((float) diff / (float) mDuration); + scheduleSelf(mUpdater, currentTime + FRAME_DURATION); + updateAnimation(interpolation); + } else { + unscheduleSelf(mUpdater); + mRunning = false; + updateAnimation(1f); + notifyFinishedToListener(); + } + } + }; + + public void setMarkerListener(MarkerAnimationListener listener) { + mMarkerListener = listener; + } + + private void notifyFinishedToListener() { + if (mMarkerListener != null) { + if (mReverse) { + mMarkerListener.onClosingComplete(); + } else { + mMarkerListener.onOpeningComplete(); + } + } + } + + @Override + public void start() { + //No-Op. We control our own animation + } + + @Override + public void stop() { + unscheduleSelf(mUpdater); + } + + @Override + public boolean isRunning() { + return mRunning; + } + + private static int blendColors(int color1, int color2, float factor) { + final float inverseFactor = 1f - factor; + float a = (Color.alpha(color1) * factor) + (Color.alpha(color2) * inverseFactor); + float r = (Color.red(color1) * factor) + (Color.red(color2) * inverseFactor); + float g = (Color.green(color1) * factor) + (Color.green(color2) * inverseFactor); + float b = (Color.blue(color1) * factor) + (Color.blue(color2) * inverseFactor); + return Color.argb((int) a, (int) r, (int) g, (int) b); + } + + + /** + * A listener interface to porpagate animation events + * This is the "poor's man" AnimatorListener for this Drawable + */ + public interface MarkerAnimationListener { + public void onClosingComplete(); + + public void onOpeningComplete(); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/StateDrawable.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/StateDrawable.java new file mode 100644 index 000000000..9c24bb35c --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/StateDrawable.java @@ -0,0 +1,105 @@ +package com.yunbao.faceunity.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; + + +/** + * A drawable that changes it's Paint color depending on the Drawable State + *

+ * Subclasses should implement {@link #doDraw(Canvas, Paint)} + *

+ * + * @hide + */ +public abstract class StateDrawable extends Drawable { + private ColorStateList mTintStateList; + private final Paint mPaint; + private int mCurrentColor; + private int mAlpha = 255; + + public StateDrawable(@NonNull ColorStateList tintStateList) { + super(); + setColorStateList(tintStateList); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + + @Override + public boolean isStateful() { + return (mTintStateList.isStateful()) || super.isStateful(); + } + + @Override + public boolean setState(int[] stateSet) { + boolean handled = super.setState(stateSet); + handled = updateTint(stateSet) || handled; + return handled; + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + private boolean updateTint(int[] state) { + final int color = mTintStateList.getColorForState(state, mCurrentColor); + if (color != mCurrentColor) { + mCurrentColor = color; + //We've changed states + invalidateSelf(); + return true; + } + return false; + } + + @Override + public void draw(Canvas canvas) { + mPaint.setColor(mCurrentColor); + int alpha = modulateAlpha(Color.alpha(mCurrentColor)); + mPaint.setAlpha(alpha); + doDraw(canvas, mPaint); + } + + public void setColorStateList(@NonNull ColorStateList tintStateList) { + mTintStateList = tintStateList; + mCurrentColor = tintStateList.getDefaultColor(); + } + + /** + * Subclasses should implement this method to do the actual drawing + * + * @param canvas The current {@link Canvas} to draw into + * @param paint The {@link Paint} preconfigurred with the current + * {@link ColorStateList} color + */ + abstract void doDraw(Canvas canvas, Paint paint); + + @Override + public void setAlpha(int alpha) { + mAlpha = alpha; + invalidateSelf(); + } + + int modulateAlpha(int alpha) { + int scale = mAlpha + (mAlpha >> 7); + return alpha * scale >> 8; + } + + @Override + public int getAlpha() { + return mAlpha; + } + + @Override + public void setColorFilter(ColorFilter cf) { + mPaint.setColorFilter(cf); + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/ThumbDrawable.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/ThumbDrawable.java new file mode 100644 index 000000000..54256e479 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/ThumbDrawable.java @@ -0,0 +1,96 @@ +package com.yunbao.faceunity.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Animatable; +import android.os.SystemClock; + +import androidx.annotation.NonNull; + +import com.yunbao.faceunity.seekbar.internal.Marker; + + +/** + *

HACK

+ *

+ * Special {@link StateDrawable} implementation + * to draw the Thumb circle. + *

+ *

+ * It's special because it will stop drawing once the state is pressed/focused BUT only after a small delay. + *

+ *

+ * This special delay is meant to help avoiding frame glitches while the {@link Marker} is added to the Window + *

+ * + * @hide + */ +public class ThumbDrawable extends StateDrawable implements Animatable { + //The current size for this drawable. Must be converted to real DPs + public static final int DEFAULT_SIZE_DP = 12; + private final int mSize; + private boolean mOpen; + private boolean mRunning; + + public ThumbDrawable(@NonNull ColorStateList tintStateList, int size) { + super(tintStateList); + mSize = size; + } + + @Override + public int getIntrinsicWidth() { + return mSize; + } + + @Override + public int getIntrinsicHeight() { + return mSize; + } + + @Override + public void doDraw(Canvas canvas, Paint paint) { + if (!mOpen) { + Rect bounds = getBounds(); + float radius = (mSize / 2); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), radius, paint); + } + } + + public void animateToPressed() { + scheduleSelf(opener, SystemClock.uptimeMillis() + 100); + mRunning = true; + } + + public void animateToNormal() { + mOpen = false; + mRunning = false; + unscheduleSelf(opener); + invalidateSelf(); + } + + private Runnable opener = new Runnable() { + @Override + public void run() { + mOpen = true; + invalidateSelf(); + mRunning = false; + } + }; + + @Override + public void start() { + //NOOP + } + + @Override + public void stop() { + animateToNormal(); + } + + @Override + public boolean isRunning() { + return mRunning; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/TrackOvalDrawable.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/TrackOvalDrawable.java new file mode 100644 index 000000000..f3a5898b1 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/TrackOvalDrawable.java @@ -0,0 +1,30 @@ +package com.yunbao.faceunity.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; + +import androidx.annotation.NonNull; + + +/** + * Simple {@link StateDrawable} implementation + * to draw circles/ovals + * + * @hide + */ +public class TrackOvalDrawable extends StateDrawable { + private RectF mRectF = new RectF(); + + public TrackOvalDrawable(@NonNull ColorStateList tintStateList) { + super(tintStateList); + } + + @Override + void doDraw(Canvas canvas, Paint paint) { + mRectF.set(getBounds()); + canvas.drawOval(mRectF, paint); + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/TrackRectDrawable.java b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/TrackRectDrawable.java new file mode 100644 index 000000000..165e24f03 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/seekbar/internal/drawable/TrackRectDrawable.java @@ -0,0 +1,26 @@ +package com.yunbao.faceunity.seekbar.internal.drawable; + +import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Paint; + +import androidx.annotation.NonNull; + + +/** + * Simple {@link StateDrawable} implementation + * to draw rectangles + * + * @hide + */ +public class TrackRectDrawable extends StateDrawable { + public TrackRectDrawable(@NonNull ColorStateList tintStateList) { + super(tintStateList); + } + + @Override + void doDraw(Canvas canvas, Paint paint) { + canvas.drawRect(getBounds(), paint); + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/ui/FaceUnityView.java b/FaceUnity/src/main/java/com/yunbao/faceunity/ui/FaceUnityView.java new file mode 100644 index 000000000..064872467 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/ui/FaceUnityView.java @@ -0,0 +1,407 @@ +package com.yunbao.faceunity.ui; + +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.Nullable; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.tabs.TabLayout; +import com.yunbao.common.utils.WordUtil; +import com.yunbao.faceunity.R; +import com.yunbao.faceunity.adapters.ContainerRecyclerAdapter; +import com.yunbao.faceunity.adapters.MenuGroupRecyclerAdapter; +import com.yunbao.faceunity.data.FaceParam; +import com.yunbao.faceunity.data.FaceUnityDataFactory; +import com.yunbao.faceunity.entity.BaseBean; +import com.yunbao.faceunity.data.FineStickerDataFactory; +import com.yunbao.faceunity.entity.FunctionEnum; +import com.yunbao.faceunity.entity.MakeupCustomClassBean; +import com.yunbao.faceunity.entity.MenuGroupBean; +import com.yunbao.faceunity.entity.net.FineStickerEntity; +import com.yunbao.faceunity.entity.net.FineStickerTagEntity; +import com.yunbao.faceunity.repo.AnimojiSource; +import com.yunbao.faceunity.repo.BodyBeautySource; +import com.yunbao.faceunity.repo.FaceBeautySource; +import com.yunbao.faceunity.repo.MakeupSource; +import com.yunbao.faceunity.repo.PropSource; +import com.yunbao.faceunity.seekbar.DiscreteSeekBar; +import com.yunbao.faceunity.utils.net.StickerDownloadHelper; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * DESC: + * Created on 2021/4/26 + */ +public class FaceUnityView extends LinearLayout implements StickerDownloadHelper.Callback { + + private Context mContext; + private RecyclerView menuGroup; + private RecyclerView containerRecycler; + private ContainerRecyclerAdapter containerAdapter; + private TabLayout tabLayout; + private TextView title; + private LinearLayout menu2, menuDiy, reset, menu2Reset; + private ImageView menu2Back, back, close; + private DiscreteSeekBar seekBar; + + public FaceUnityView(Context context) { + super(context); + mContext = context; + init(); + } + + public FaceUnityView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + mContext = context; + init(); + } + + public FaceUnityView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + init(); + } + + + private void init() { + LayoutInflater.from(mContext).inflate(R.layout.layout_faceunity, this); + initView(); + FineStickerDataFactory.getInstance().addCallback(this); + } + + /** + * 初始化View + */ + private void initView() { + menuGroup = findViewById(R.id.menu_group); + containerRecycler = findViewById(R.id.menu2_container_view); + tabLayout = findViewById(R.id.menu2_tab); + title = findViewById(R.id.menu_title); + menu2 = findViewById(R.id.layout_faceunity_menu2); + back = findViewById(R.id.menu_back); + menu2Back = findViewById(R.id.menu2_back); + close = findViewById(R.id.menu_close); + reset = findViewById(R.id.menu_reset); + menu2Reset = findViewById(R.id.menu2_reset); + menuDiy = findViewById(R.id.menu_diy); + seekBar = findViewById(R.id.item_seekBar); + initMenuGroup(); + setContainerRecycler(new ArrayList<>()); + initViewClick(); + } + + /** + * 初始化配置点击事件 + */ + private void initViewClick() { + menu2Back.setOnClickListener(v -> { + Object tag = menu2Back.getTag(); + if(tag==null) { + goBackMainMenu(); + }else if(tag.equals("makeup")){ + title.setText(R.string.home_function_name_makeup); + title.setVisibility(VISIBLE); + menuDiy.setVisibility(VISIBLE); + tabLayout.removeAllTabs(); + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCombinations()); + menu2Back.setTag(null); + } + }); + menuDiy.setOnClickListener(v -> { + menu2Back.setTag("makeup"); + changeRecyclerItemCount(5); + menuDiy.setVisibility(GONE); + ArrayList list = MakeupSource.buildCustomClasses(); + setTab(createTabs(list)); + }); + menu2Reset.setOnClickListener(view -> { + containerAdapter.reset(); + }); + } + + /** + * 回到默认界面 + */ + private void goBackMainMenu() { + setContainerRecycler(new ArrayList<>()); + title.setText("美顏特效選擇"); + title.setVisibility(VISIBLE); + menu2.setVisibility(GONE); + menuGroup.setVisibility(VISIBLE); + menuDiy.setVisibility(GONE); + } + + /** + * 配置主菜单 + */ + private void initMenuGroup() { + MenuGroupRecyclerAdapter adapter = new MenuGroupRecyclerAdapter(mContext); + menuGroup.setLayoutManager(new GridLayoutManager(mContext, 4)); + List layoutItem = new ArrayList<>(); + layoutItem.add(new MenuGroupBean(R.string.home_function_name_beauty, R.mipmap.ico_home_beauty)); + layoutItem.add(new MenuGroupBean(R.string.home_function_name_makeup, R.mipmap.ico_home_makeup)); + layoutItem.add(new MenuGroupBean(R.string.home_function_name_beauty_body, R.mipmap.ico_home_beauty_body)); + layoutItem.add(new MenuGroupBean(R.string.home_function_name_big_head, R.mipmap.ico_home_big_head)); + layoutItem.add(new MenuGroupBean(R.string.home_function_name_animoji, R.mipmap.ico_home_animoji)); + layoutItem.add(new MenuGroupBean(R.string.home_function_name_sticker, R.mipmap.ico_home_sticker)); + layoutItem.add(new MenuGroupBean(R.string.home_function_name_fine_sticker, R.mipmap.ico_home_fine_sticker)); + adapter.setList(layoutItem); + adapter.setOnItemClickListener(position -> { + LinkedHashMap map = new LinkedHashMap<>(); + title.setVisibility(GONE); + switch (position) { + case 0: + map.put(R.string.beauty_radio_skin_beauty, FaceParam.FACE_BEAUTY_SKIN); + map.put(R.string.beauty_radio_face_shape, FaceParam.FACE_BEAUTY_SHAPE); + map.put(R.string.beauty_radio_filter, FaceParam.FACE_BEAUTY_FILTER); + map.put(R.string.beauty_radio_style, FaceParam.FACE_BEAUTY_STYLE); + setContainerRecycler(FaceBeautySource.buildSkinParams()); + break; + case 1: + title.setText(R.string.home_function_name_makeup); + title.setVisibility(VISIBLE); + menuDiy.setVisibility(VISIBLE); + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCombinations()); + break; + case 2: + title.setText(R.string.home_function_name_beauty_body); + title.setVisibility(VISIBLE); + changeRecyclerItemCount(2); + setContainerRecycler(BodyBeautySource.buildBodyBeauty()); + break; + case 3: + changeRecyclerItemCount(5); + setContainerRecycler(PropSource.buildPropBeans(FunctionEnum.BIG_HEAD)); + break; + case 4: + changeRecyclerItemCount(5); + map.put(R.string.animoji_filter, FaceParam.FACE_ANIMOJI); + map.put(R.string.cartoon_filter, FaceParam.FACE_ANIM); + setContainerRecycler(AnimojiSource.buildAnimojis()); + break; + case 5: + changeRecyclerItemCount(5); + setContainerRecycler(PropSource.buildPropBeans(FunctionEnum.STICKER)); + break; + case 6: + List tagList = FineStickerDataFactory.getInstance().loadTagList(); + if (!tagList.isEmpty()) { + setTab(createTabs(tagList)); + } + break; + } + setTab(createTabs(map)); + menuGroup.setVisibility(GONE); + menu2.setVisibility(VISIBLE); + }); + menuGroup.setAdapter(adapter); + } + + /** + * 创建Tab + */ + private List createTabs(Map map) { + List list = new ArrayList<>(); + for (Integer key : map.keySet()) { + TabLayout.Tab tab = tabLayout.newTab().setText(key); + tab.setTag(map.get(key)); + list.add(tab); + } + return list; + } + + /** + * 创建菜单 + */ + private List createTabs(List tags) { + List list = new ArrayList<>(); + for (FineStickerTagEntity tag : tags) { + TabLayout.Tab tab; + if (WordUtil.isZh()) { + tab = tabLayout.newTab().setText(tag.getTag().split("/")[0]); + } else { + tab = tabLayout.newTab().setText(tag.getTag().split("/")[1]); + } + tab.setTag(tag); + list.add(tab); + } + return list; + } + + /** + * 创建菜单 + */ + private List createTabs(ArrayList tags) { + List list = new ArrayList<>(); + for (MakeupCustomClassBean tag : tags) { + TabLayout.Tab tab; + tab = tabLayout.newTab().setText(tag.getDesRes()); + tab.setTag(tag.getBeanType()); + list.add(tab); + } + return list; + } + + /** + * 设置菜单 + */ + private void setTab(List tabs) { + tabLayout.removeAllTabs(); + for (TabLayout.Tab tab : tabs) { + tabLayout.addTab(tab); + } + tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { + Object tabTag = tab.getTag(); + if (tabTag instanceof Integer) { + switch ((int) tab.getTag()) { + case FaceParam.FACE_BEAUTY_SKIN: + changeRecyclerItemCount(2); + setContainerRecycler(FaceBeautySource.buildSkinParams()); + break; + case FaceParam.FACE_BEAUTY_SHAPE: + changeRecyclerItemCount(2); + setContainerRecycler(FaceBeautySource.buildShapeParams()); + break; + case FaceParam.FACE_BEAUTY_FILTER: + changeRecyclerItemCount(5); + setContainerRecycler(FaceBeautySource.buildFilters()); + break; + case FaceParam.FACE_BEAUTY_STYLE: + changeRecyclerItemCount(5); + setContainerRecycler(FaceBeautySource.buildStylesParams()); + break; + case FaceParam.FACE_ANIMOJI: + changeRecyclerItemCount(5); + setContainerRecycler(AnimojiSource.buildAnimojis()); + break; + case FaceParam.FACE_ANIM: + changeRecyclerItemCount(5); + setContainerRecycler(AnimojiSource.buildFilters()); + break; + case FaceParam.FACE_MAKEUP_TYPE_FOUNDATION: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_FOUNDATION)); + break; + case FaceParam.FACE_MAKEUP_TYPE_LIP_STICK: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_LIP_STICK)); + break; + case FaceParam.FACE_MAKEUP_TYPE_BLUSHER: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_BLUSHER)); + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_BROW: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_BROW)); + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_SHADOW: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_SHADOW)); + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_LINER: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_LINER)); + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_LASH: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_LASH)); + break; + case FaceParam.FACE_MAKEUP_TYPE_HIGH_LIGHT: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_HIGH_LIGHT)); + break; + case FaceParam.FACE_MAKEUP_TYPE_SHADOW: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_SHADOW)); + break; + case FaceParam.FACE_MAKEUP_TYPE_EYE_PUPIL: + changeRecyclerItemCount(5); + setContainerRecycler(MakeupSource.buildCustomItemParams().get(MakeupSource.FACE_MAKEUP_TYPE_EYE_PUPIL)); + break; + default: + setContainerRecycler(new ArrayList<>()); + } + } else if (tabTag instanceof FineStickerTagEntity) { + FineStickerTagEntity tag = (FineStickerTagEntity) tabTag; + FineStickerEntity sticker = FineStickerDataFactory.getInstance().loadStickerList(tag); + ArrayList list = new ArrayList<>(); + FineStickerEntity.DocsBean docsBean = new FineStickerEntity.DocsBean(); + docsBean.set_id("-1"); + list.add(docsBean); + list.addAll(sticker.getDocs()); + changeRecyclerItemCount(5); + setContainerRecycler(list); + } + } + + @Override + public void onTabUnselected(TabLayout.Tab tab) { + + } + + @Override + public void onTabReselected(TabLayout.Tab tab) { + + } + }); + } + + /** + * 设置美颜选项配置行数,图标为5个,拖动条为2个 + * @param count + */ + private void changeRecyclerItemCount(int count) { + containerRecycler.setLayoutManager(new GridLayoutManager(mContext, count)); + } + + /** + * 设置美颜Recycler内容 + * @param list + */ + private void setContainerRecycler(ArrayList list) { + if (containerAdapter == null) { + containerAdapter = new ContainerRecyclerAdapter(mContext); + containerAdapter.setSeekBar(seekBar); + containerRecycler.setLayoutManager(new GridLayoutManager(mContext, 2)); + containerRecycler.setAdapter(containerAdapter); + } + containerAdapter.setList(list); + containerAdapter.notifyDataSetChanged(); + } + + @Override + public void onGetTags(String[] tags) { + List list = FineStickerDataFactory.formatTag(tags); + setTab(createTabs(list)); + } + + @Override + public void onGetList(String tag, FineStickerEntity fineSticker) { + + } + + @Override + public void onDownload(FineStickerEntity.DocsBean entity) { + + } + + @Override + public void onDownloadError(FineStickerEntity.DocsBean entity, String msg) { + + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/Authpack.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/Authpack.java new file mode 100644 index 000000000..85ad85c89 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/Authpack.java @@ -0,0 +1,1299 @@ +package com.yunbao.faceunity.utils; + +import java.security.MessageDigest; + +public class Authpack { + public static int sha1_32(byte[] buf){int ret=0;try{byte[] digest=MessageDigest.getInstance("SHA1").digest(buf);return ((int)(digest[0]&0xff)<<24)+((int)(digest[1]&0xff)<<16)+((int)(digest[2]&0xff)<<8)+((int)(digest[3]&0xff)<<0);}catch(Exception e){}return ret;} + public static byte[] A(){ + byte[] buf=new byte[1287]; + int i=0; + for(i=-67;i<-49;i++){ buf[0]=(byte)i; if(sha1_32(buf)==-391754430){break;} } + for(i=-80;i<-55;i++){ buf[1]=(byte)i; if(sha1_32(buf)==1900926373){break;} } + for(i=-43;i<-24;i++){ buf[2]=(byte)i; if(sha1_32(buf)==-1665990518){break;} } + for(i=-15;i<13;i++){ buf[3]=(byte)i; if(sha1_32(buf)==-1665990518){break;} } + for(i=4;i<27;i++){ buf[4]=(byte)i; if(sha1_32(buf)==1047145318){break;} } + for(i=-16;i<0;i++){ buf[5]=(byte)i; if(sha1_32(buf)==-424862454){break;} } + for(i=-127;i<-109;i++){ buf[6]=(byte)i; if(sha1_32(buf)==1209499468){break;} } + for(i=-31;i<-14;i++){ buf[7]=(byte)i; if(sha1_32(buf)==856316850){break;} } + for(i=-22;i<-6;i++){ buf[8]=(byte)i; if(sha1_32(buf)==-2092471705){break;} } + for(i=95;i<107;i++){ buf[9]=(byte)i; if(sha1_32(buf)==-984113952){break;} } + for(i=39;i<42;i++){ buf[10]=(byte)i; if(sha1_32(buf)==-1718767640){break;} } + for(i=-18;i<11;i++){ buf[11]=(byte)i; if(sha1_32(buf)==-555788840){break;} } + for(i=-24;i<-11;i++){ buf[12]=(byte)i; if(sha1_32(buf)==-910213045){break;} } + for(i=36;i<60;i++){ buf[13]=(byte)i; if(sha1_32(buf)==-2044929937){break;} } + for(i=-12;i<-3;i++){ buf[14]=(byte)i; if(sha1_32(buf)==518665237){break;} } + for(i=-17;i<-3;i++){ buf[15]=(byte)i; if(sha1_32(buf)==854770556){break;} } + for(i=87;i<116;i++){ buf[16]=(byte)i; if(sha1_32(buf)==-739025236){break;} } + for(i=67;i<77;i++){ buf[17]=(byte)i; if(sha1_32(buf)==1255114494){break;} } + for(i=73;i<97;i++){ buf[18]=(byte)i; if(sha1_32(buf)==1976741542){break;} } + for(i=-89;i<-74;i++){ buf[19]=(byte)i; if(sha1_32(buf)==-1961518064){break;} } + for(i=-18;i<7;i++){ buf[20]=(byte)i; if(sha1_32(buf)==-336610323){break;} } + for(i=-12;i<-4;i++){ buf[21]=(byte)i; if(sha1_32(buf)==-1123062247){break;} } + for(i=-9;i<3;i++){ buf[22]=(byte)i; if(sha1_32(buf)==-1992256418){break;} } + for(i=-88;i<-75;i++){ buf[23]=(byte)i; if(sha1_32(buf)==1018895511){break;} } + for(i=-68;i<-41;i++){ buf[24]=(byte)i; if(sha1_32(buf)==-876830013){break;} } + for(i=98;i<112;i++){ buf[25]=(byte)i; if(sha1_32(buf)==1228289588){break;} } + for(i=-128;i<-116;i++){ buf[26]=(byte)i; if(sha1_32(buf)==1545307171){break;} } + for(i=84;i<99;i++){ buf[27]=(byte)i; if(sha1_32(buf)==1025915855){break;} } + for(i=-120;i<-110;i++){ buf[28]=(byte)i; if(sha1_32(buf)==85392660){break;} } + for(i=20;i<34;i++){ buf[29]=(byte)i; if(sha1_32(buf)==-1972027660){break;} } + for(i=-99;i<-72;i++){ buf[30]=(byte)i; if(sha1_32(buf)==1690302090){break;} } + for(i=6;i<24;i++){ buf[31]=(byte)i; if(sha1_32(buf)==-574981697){break;} } + for(i=-120;i<-104;i++){ buf[32]=(byte)i; if(sha1_32(buf)==-887866308){break;} } + for(i=28;i<45;i++){ buf[33]=(byte)i; if(sha1_32(buf)==1222447740){break;} } + for(i=-25;i<-17;i++){ buf[34]=(byte)i; if(sha1_32(buf)==-545537371){break;} } + for(i=77;i<94;i++){ buf[35]=(byte)i; if(sha1_32(buf)==1941347942){break;} } + for(i=-69;i<-61;i++){ buf[36]=(byte)i; if(sha1_32(buf)==1223549852){break;} } + for(i=-92;i<-83;i++){ buf[37]=(byte)i; if(sha1_32(buf)==2024830132){break;} } + for(i=-79;i<-62;i++){ buf[38]=(byte)i; if(sha1_32(buf)==1143517641){break;} } + for(i=102;i<121;i++){ buf[39]=(byte)i; if(sha1_32(buf)==-896817134){break;} } + for(i=-96;i<-69;i++){ buf[40]=(byte)i; if(sha1_32(buf)==317582632){break;} } + for(i=-26;i<-6;i++){ buf[41]=(byte)i; if(sha1_32(buf)==1672427421){break;} } + for(i=-128;i<-116;i++){ buf[42]=(byte)i; if(sha1_32(buf)==-537648615){break;} } + for(i=36;i<54;i++){ buf[43]=(byte)i; if(sha1_32(buf)==1113091889){break;} } + for(i=23;i<46;i++){ buf[44]=(byte)i; if(sha1_32(buf)==-754782113){break;} } + for(i=-32;i<-16;i++){ buf[45]=(byte)i; if(sha1_32(buf)==-1818800460){break;} } + for(i=91;i<102;i++){ buf[46]=(byte)i; if(sha1_32(buf)==-1127713536){break;} } + for(i=-21;i<0;i++){ buf[47]=(byte)i; if(sha1_32(buf)==8152419){break;} } + for(i=-128;i<-108;i++){ buf[48]=(byte)i; if(sha1_32(buf)==-1135760392){break;} } + for(i=122;i<127;i++){ buf[49]=(byte)i; if(sha1_32(buf)==52108472){break;} } + for(i=-20;i<3;i++){ buf[50]=(byte)i; if(sha1_32(buf)==1527805073){break;} } + for(i=-62;i<-43;i++){ buf[51]=(byte)i; if(sha1_32(buf)==1662310747){break;} } + for(i=-2;i<21;i++){ buf[52]=(byte)i; if(sha1_32(buf)==-988866357){break;} } + for(i=-113;i<-102;i++){ buf[53]=(byte)i; if(sha1_32(buf)==-1940075124){break;} } + for(i=80;i<107;i++){ buf[54]=(byte)i; if(sha1_32(buf)==1476703425){break;} } + for(i=113;i<128;i++){ buf[55]=(byte)i; if(sha1_32(buf)==-1992340705){break;} } + for(i=52;i<63;i++){ buf[56]=(byte)i; if(sha1_32(buf)==-1934770772){break;} } + for(i=109;i<124;i++){ buf[57]=(byte)i; if(sha1_32(buf)==-1782391826){break;} } + for(i=38;i<62;i++){ buf[58]=(byte)i; if(sha1_32(buf)==-2112743083){break;} } + for(i=108;i<127;i++){ buf[59]=(byte)i; if(sha1_32(buf)==-802874781){break;} } + for(i=-18;i<-3;i++){ buf[60]=(byte)i; if(sha1_32(buf)==-1151716369){break;} } + for(i=29;i<46;i++){ buf[61]=(byte)i; if(sha1_32(buf)==-1267923030){break;} } + for(i=-33;i<-19;i++){ buf[62]=(byte)i; if(sha1_32(buf)==735438287){break;} } + for(i=62;i<86;i++){ buf[63]=(byte)i; if(sha1_32(buf)==-1472222342){break;} } + for(i=-109;i<-101;i++){ buf[64]=(byte)i; if(sha1_32(buf)==920655195){break;} } + for(i=-1;i<13;i++){ buf[65]=(byte)i; if(sha1_32(buf)==1473134326){break;} } + for(i=-102;i<-82;i++){ buf[66]=(byte)i; if(sha1_32(buf)==2043662542){break;} } + for(i=-53;i<-31;i++){ buf[67]=(byte)i; if(sha1_32(buf)==-831915519){break;} } + for(i=21;i<34;i++){ buf[68]=(byte)i; if(sha1_32(buf)==2133658053){break;} } + for(i=-29;i<-21;i++){ buf[69]=(byte)i; if(sha1_32(buf)==2063888385){break;} } + for(i=-73;i<-45;i++){ buf[70]=(byte)i; if(sha1_32(buf)==1361289840){break;} } + for(i=-85;i<-70;i++){ buf[71]=(byte)i; if(sha1_32(buf)==2052823646){break;} } + for(i=-103;i<-88;i++){ buf[72]=(byte)i; if(sha1_32(buf)==-1797847253){break;} } + for(i=36;i<48;i++){ buf[73]=(byte)i; if(sha1_32(buf)==1812053799){break;} } + for(i=69;i<83;i++){ buf[74]=(byte)i; if(sha1_32(buf)==-255176161){break;} } + for(i=-34;i<-13;i++){ buf[75]=(byte)i; if(sha1_32(buf)==1827402642){break;} } + for(i=123;i<128;i++){ buf[76]=(byte)i; if(sha1_32(buf)==-2128834832){break;} } + for(i=-89;i<-81;i++){ buf[77]=(byte)i; if(sha1_32(buf)==1507936178){break;} } + for(i=85;i<108;i++){ buf[78]=(byte)i; if(sha1_32(buf)==794056559){break;} } + for(i=29;i<38;i++){ buf[79]=(byte)i; if(sha1_32(buf)==-1594614370){break;} } + for(i=89;i<95;i++){ buf[80]=(byte)i; if(sha1_32(buf)==-770139794){break;} } + for(i=64;i<88;i++){ buf[81]=(byte)i; if(sha1_32(buf)==-1673933191){break;} } + for(i=50;i<61;i++){ buf[82]=(byte)i; if(sha1_32(buf)==-393706017){break;} } + for(i=68;i<83;i++){ buf[83]=(byte)i; if(sha1_32(buf)==-262250143){break;} } + for(i=-35;i<-24;i++){ buf[84]=(byte)i; if(sha1_32(buf)==-550708740){break;} } + for(i=-13;i<14;i++){ buf[85]=(byte)i; if(sha1_32(buf)==-1315064457){break;} } + for(i=91;i<111;i++){ buf[86]=(byte)i; if(sha1_32(buf)==-1975186804){break;} } + for(i=96;i<115;i++){ buf[87]=(byte)i; if(sha1_32(buf)==-929199652){break;} } + for(i=-67;i<-62;i++){ buf[88]=(byte)i; if(sha1_32(buf)==1665475556){break;} } + for(i=9;i<30;i++){ buf[89]=(byte)i; if(sha1_32(buf)==2145697620){break;} } + for(i=90;i<120;i++){ buf[90]=(byte)i; if(sha1_32(buf)==824905423){break;} } + for(i=-25;i<0;i++){ buf[91]=(byte)i; if(sha1_32(buf)==1465634888){break;} } + for(i=25;i<48;i++){ buf[92]=(byte)i; if(sha1_32(buf)==-953103076){break;} } + for(i=109;i<128;i++){ buf[93]=(byte)i; if(sha1_32(buf)==-1148756392){break;} } + for(i=75;i<93;i++){ buf[94]=(byte)i; if(sha1_32(buf)==986260642){break;} } + for(i=-102;i<-95;i++){ buf[95]=(byte)i; if(sha1_32(buf)==-994058873){break;} } + for(i=4;i<20;i++){ buf[96]=(byte)i; if(sha1_32(buf)==-1987528081){break;} } + for(i=32;i<47;i++){ buf[97]=(byte)i; if(sha1_32(buf)==-248889704){break;} } + for(i=-82;i<-55;i++){ buf[98]=(byte)i; if(sha1_32(buf)==-1681465177){break;} } + for(i=-124;i<-109;i++){ buf[99]=(byte)i; if(sha1_32(buf)==640792383){break;} } + for(i=-15;i<-7;i++){ buf[100]=(byte)i; if(sha1_32(buf)==786658470){break;} } + for(i=-3;i<2;i++){ buf[101]=(byte)i; if(sha1_32(buf)==-896698207){break;} } + for(i=-16;i<3;i++){ buf[102]=(byte)i; if(sha1_32(buf)==2067389578){break;} } + for(i=38;i<44;i++){ buf[103]=(byte)i; if(sha1_32(buf)==-72581513){break;} } + for(i=-61;i<-41;i++){ buf[104]=(byte)i; if(sha1_32(buf)==-2139601543){break;} } + for(i=-16;i<-2;i++){ buf[105]=(byte)i; if(sha1_32(buf)==1927135073){break;} } + for(i=37;i<50;i++){ buf[106]=(byte)i; if(sha1_32(buf)==2132848442){break;} } + for(i=84;i<98;i++){ buf[107]=(byte)i; if(sha1_32(buf)==-2096950942){break;} } + for(i=15;i<31;i++){ buf[108]=(byte)i; if(sha1_32(buf)==52833424){break;} } + for(i=-38;i<-17;i++){ buf[109]=(byte)i; if(sha1_32(buf)==1463164582){break;} } + for(i=50;i<68;i++){ buf[110]=(byte)i; if(sha1_32(buf)==-1275186949){break;} } + for(i=-96;i<-83;i++){ buf[111]=(byte)i; if(sha1_32(buf)==-625103736){break;} } + for(i=108;i<128;i++){ buf[112]=(byte)i; if(sha1_32(buf)==-665386407){break;} } + for(i=87;i<93;i++){ buf[113]=(byte)i; if(sha1_32(buf)==388350333){break;} } + for(i=114;i<128;i++){ buf[114]=(byte)i; if(sha1_32(buf)==-1060971883){break;} } + for(i=86;i<101;i++){ buf[115]=(byte)i; if(sha1_32(buf)==-841965955){break;} } + for(i=41;i<53;i++){ buf[116]=(byte)i; if(sha1_32(buf)==-1650432622){break;} } + for(i=118;i<128;i++){ buf[117]=(byte)i; if(sha1_32(buf)==-1276227243){break;} } + for(i=-89;i<-70;i++){ buf[118]=(byte)i; if(sha1_32(buf)==-617645963){break;} } + for(i=-65;i<-47;i++){ buf[119]=(byte)i; if(sha1_32(buf)==1555146982){break;} } + for(i=-112;i<-107;i++){ buf[120]=(byte)i; if(sha1_32(buf)==1023886184){break;} } + for(i=-93;i<-65;i++){ buf[121]=(byte)i; if(sha1_32(buf)==1637650516){break;} } + for(i=-128;i<-114;i++){ buf[122]=(byte)i; if(sha1_32(buf)==-592787991){break;} } + for(i=88;i<100;i++){ buf[123]=(byte)i; if(sha1_32(buf)==625231611){break;} } + for(i=57;i<75;i++){ buf[124]=(byte)i; if(sha1_32(buf)==-1554004227){break;} } + for(i=-101;i<-85;i++){ buf[125]=(byte)i; if(sha1_32(buf)==20018369){break;} } + for(i=71;i<89;i++){ buf[126]=(byte)i; if(sha1_32(buf)==1903106075){break;} } + for(i=-103;i<-87;i++){ buf[127]=(byte)i; if(sha1_32(buf)==175558840){break;} } + for(i=-72;i<-48;i++){ buf[128]=(byte)i; if(sha1_32(buf)==1961437748){break;} } + for(i=19;i<44;i++){ buf[129]=(byte)i; if(sha1_32(buf)==300929953){break;} } + for(i=42;i<66;i++){ buf[130]=(byte)i; if(sha1_32(buf)==-840477363){break;} } + for(i=-128;i<-122;i++){ buf[131]=(byte)i; if(sha1_32(buf)==-298674684){break;} } + for(i=-67;i<-42;i++){ buf[132]=(byte)i; if(sha1_32(buf)==-6416740){break;} } + for(i=74;i<82;i++){ buf[133]=(byte)i; if(sha1_32(buf)==1163922176){break;} } + for(i=74;i<75;i++){ buf[134]=(byte)i; if(sha1_32(buf)==1595667229){break;} } + for(i=-19;i<-3;i++){ buf[135]=(byte)i; if(sha1_32(buf)==-433850003){break;} } + for(i=-123;i<-117;i++){ buf[136]=(byte)i; if(sha1_32(buf)==1030206619){break;} } + for(i=-9;i<1;i++){ buf[137]=(byte)i; if(sha1_32(buf)==-1454843081){break;} } + for(i=-85;i<-67;i++){ buf[138]=(byte)i; if(sha1_32(buf)==-1585626251){break;} } + for(i=-50;i<-39;i++){ buf[139]=(byte)i; if(sha1_32(buf)==-1417127426){break;} } + for(i=-72;i<-53;i++){ buf[140]=(byte)i; if(sha1_32(buf)==1015317819){break;} } + for(i=30;i<40;i++){ buf[141]=(byte)i; if(sha1_32(buf)==-1100859684){break;} } + for(i=96;i<105;i++){ buf[142]=(byte)i; if(sha1_32(buf)==706995274){break;} } + for(i=-76;i<-59;i++){ buf[143]=(byte)i; if(sha1_32(buf)==-888501731){break;} } + for(i=84;i<109;i++){ buf[144]=(byte)i; if(sha1_32(buf)==1178620419){break;} } + for(i=95;i<108;i++){ buf[145]=(byte)i; if(sha1_32(buf)==-755248538){break;} } + for(i=-17;i<-3;i++){ buf[146]=(byte)i; if(sha1_32(buf)==-2029583273){break;} } + for(i=68;i<85;i++){ buf[147]=(byte)i; if(sha1_32(buf)==-1635628256){break;} } + for(i=-16;i<6;i++){ buf[148]=(byte)i; if(sha1_32(buf)==-438000480){break;} } + for(i=62;i<77;i++){ buf[149]=(byte)i; if(sha1_32(buf)==2020205680){break;} } + for(i=91;i<107;i++){ buf[150]=(byte)i; if(sha1_32(buf)==1261152384){break;} } + for(i=-23;i<-11;i++){ buf[151]=(byte)i; if(sha1_32(buf)==950869604){break;} } + for(i=-69;i<-50;i++){ buf[152]=(byte)i; if(sha1_32(buf)==-1479156358){break;} } + for(i=-118;i<-113;i++){ buf[153]=(byte)i; if(sha1_32(buf)==1655572574){break;} } + for(i=29;i<33;i++){ buf[154]=(byte)i; if(sha1_32(buf)==-1922333602){break;} } + for(i=56;i<71;i++){ buf[155]=(byte)i; if(sha1_32(buf)==1625494262){break;} } + for(i=34;i<55;i++){ buf[156]=(byte)i; if(sha1_32(buf)==138674777){break;} } + for(i=-114;i<-94;i++){ buf[157]=(byte)i; if(sha1_32(buf)==-938911648){break;} } + for(i=119;i<128;i++){ buf[158]=(byte)i; if(sha1_32(buf)==-1925207802){break;} } + for(i=-96;i<-83;i++){ buf[159]=(byte)i; if(sha1_32(buf)==31589957){break;} } + for(i=-96;i<-82;i++){ buf[160]=(byte)i; if(sha1_32(buf)==798238332){break;} } + for(i=3;i<20;i++){ buf[161]=(byte)i; if(sha1_32(buf)==-476594378){break;} } + for(i=101;i<107;i++){ buf[162]=(byte)i; if(sha1_32(buf)==-1342464130){break;} } + for(i=-122;i<-105;i++){ buf[163]=(byte)i; if(sha1_32(buf)==-261562528){break;} } + for(i=-72;i<-54;i++){ buf[164]=(byte)i; if(sha1_32(buf)==296367174){break;} } + for(i=-62;i<-42;i++){ buf[165]=(byte)i; if(sha1_32(buf)==-771895432){break;} } + for(i=96;i<111;i++){ buf[166]=(byte)i; if(sha1_32(buf)==-814394945){break;} } + for(i=3;i<12;i++){ buf[167]=(byte)i; if(sha1_32(buf)==-885009181){break;} } + for(i=102;i<107;i++){ buf[168]=(byte)i; if(sha1_32(buf)==-1428969787){break;} } + for(i=31;i<38;i++){ buf[169]=(byte)i; if(sha1_32(buf)==1108829564){break;} } + for(i=64;i<75;i++){ buf[170]=(byte)i; if(sha1_32(buf)==774403827){break;} } + for(i=34;i<55;i++){ buf[171]=(byte)i; if(sha1_32(buf)==950137282){break;} } + for(i=-115;i<-87;i++){ buf[172]=(byte)i; if(sha1_32(buf)==1611066465){break;} } + for(i=53;i<71;i++){ buf[173]=(byte)i; if(sha1_32(buf)==-984030300){break;} } + for(i=61;i<75;i++){ buf[174]=(byte)i; if(sha1_32(buf)==1499512222){break;} } + for(i=101;i<115;i++){ buf[175]=(byte)i; if(sha1_32(buf)==501848953){break;} } + for(i=15;i<34;i++){ buf[176]=(byte)i; if(sha1_32(buf)==-1544698149){break;} } + for(i=-63;i<-40;i++){ buf[177]=(byte)i; if(sha1_32(buf)==-1512542676){break;} } + for(i=-3;i<22;i++){ buf[178]=(byte)i; if(sha1_32(buf)==1701343711){break;} } + for(i=-64;i<-51;i++){ buf[179]=(byte)i; if(sha1_32(buf)==-1976089139){break;} } + for(i=-103;i<-87;i++){ buf[180]=(byte)i; if(sha1_32(buf)==-1588324412){break;} } + for(i=-43;i<-22;i++){ buf[181]=(byte)i; if(sha1_32(buf)==-429216395){break;} } + for(i=0;i<23;i++){ buf[182]=(byte)i; if(sha1_32(buf)==1029048871){break;} } + for(i=51;i<65;i++){ buf[183]=(byte)i; if(sha1_32(buf)==1889493243){break;} } + for(i=62;i<84;i++){ buf[184]=(byte)i; if(sha1_32(buf)==558419144){break;} } + for(i=-34;i<-21;i++){ buf[185]=(byte)i; if(sha1_32(buf)==13546166){break;} } + for(i=-5;i<15;i++){ buf[186]=(byte)i; if(sha1_32(buf)==1334868490){break;} } + for(i=50;i<65;i++){ buf[187]=(byte)i; if(sha1_32(buf)==-731555921){break;} } + for(i=-34;i<-10;i++){ buf[188]=(byte)i; if(sha1_32(buf)==-2100838080){break;} } + for(i=-55;i<-40;i++){ buf[189]=(byte)i; if(sha1_32(buf)==197929139){break;} } + for(i=-94;i<-79;i++){ buf[190]=(byte)i; if(sha1_32(buf)==-454931231){break;} } + for(i=28;i<34;i++){ buf[191]=(byte)i; if(sha1_32(buf)==2135555647){break;} } + for(i=-38;i<-31;i++){ buf[192]=(byte)i; if(sha1_32(buf)==19636287){break;} } + for(i=-32;i<-17;i++){ buf[193]=(byte)i; if(sha1_32(buf)==-665528133){break;} } + for(i=-50;i<-25;i++){ buf[194]=(byte)i; if(sha1_32(buf)==331867916){break;} } + for(i=-47;i<-25;i++){ buf[195]=(byte)i; if(sha1_32(buf)==696388947){break;} } + for(i=-105;i<-85;i++){ buf[196]=(byte)i; if(sha1_32(buf)==1178114167){break;} } + for(i=31;i<53;i++){ buf[197]=(byte)i; if(sha1_32(buf)==1634019413){break;} } + for(i=-45;i<-29;i++){ buf[198]=(byte)i; if(sha1_32(buf)==1536577486){break;} } + for(i=-22;i<1;i++){ buf[199]=(byte)i; if(sha1_32(buf)==-2012652150){break;} } + for(i=116;i<124;i++){ buf[200]=(byte)i; if(sha1_32(buf)==2085170396){break;} } + for(i=-106;i<-83;i++){ buf[201]=(byte)i; if(sha1_32(buf)==-1536536318){break;} } + for(i=13;i<44;i++){ buf[202]=(byte)i; if(sha1_32(buf)==-2105445226){break;} } + for(i=91;i<118;i++){ buf[203]=(byte)i; if(sha1_32(buf)==-1428545725){break;} } + for(i=-30;i<-19;i++){ buf[204]=(byte)i; if(sha1_32(buf)==222916244){break;} } + for(i=-121;i<-101;i++){ buf[205]=(byte)i; if(sha1_32(buf)==432908454){break;} } + for(i=73;i<97;i++){ buf[206]=(byte)i; if(sha1_32(buf)==-1375007617){break;} } + for(i=-19;i<-4;i++){ buf[207]=(byte)i; if(sha1_32(buf)==-1225462788){break;} } + for(i=124;i<128;i++){ buf[208]=(byte)i; if(sha1_32(buf)==1443789543){break;} } + for(i=-103;i<-100;i++){ buf[209]=(byte)i; if(sha1_32(buf)==827855038){break;} } + for(i=-100;i<-91;i++){ buf[210]=(byte)i; if(sha1_32(buf)==1213811138){break;} } + for(i=-63;i<-45;i++){ buf[211]=(byte)i; if(sha1_32(buf)==-2015122730){break;} } + for(i=-15;i<1;i++){ buf[212]=(byte)i; if(sha1_32(buf)==-261649054){break;} } + for(i=-120;i<-100;i++){ buf[213]=(byte)i; if(sha1_32(buf)==1544135387){break;} } + for(i=-71;i<-48;i++){ buf[214]=(byte)i; if(sha1_32(buf)==-337921079){break;} } + for(i=117;i<128;i++){ buf[215]=(byte)i; if(sha1_32(buf)==1915914909){break;} } + for(i=107;i<122;i++){ buf[216]=(byte)i; if(sha1_32(buf)==1433434586){break;} } + for(i=-111;i<-93;i++){ buf[217]=(byte)i; if(sha1_32(buf)==1687573691){break;} } + for(i=67;i<95;i++){ buf[218]=(byte)i; if(sha1_32(buf)==753326018){break;} } + for(i=93;i<101;i++){ buf[219]=(byte)i; if(sha1_32(buf)==405654874){break;} } + for(i=-99;i<-76;i++){ buf[220]=(byte)i; if(sha1_32(buf)==603271977){break;} } + for(i=-74;i<-52;i++){ buf[221]=(byte)i; if(sha1_32(buf)==1426353767){break;} } + for(i=-87;i<-75;i++){ buf[222]=(byte)i; if(sha1_32(buf)==-977940918){break;} } + for(i=113;i<123;i++){ buf[223]=(byte)i; if(sha1_32(buf)==1890985037){break;} } + for(i=20;i<38;i++){ buf[224]=(byte)i; if(sha1_32(buf)==201436187){break;} } + for(i=-55;i<-35;i++){ buf[225]=(byte)i; if(sha1_32(buf)==-476346111){break;} } + for(i=-128;i<-101;i++){ buf[226]=(byte)i; if(sha1_32(buf)==-412224428){break;} } + for(i=3;i<20;i++){ buf[227]=(byte)i; if(sha1_32(buf)==544544594){break;} } + for(i=51;i<70;i++){ buf[228]=(byte)i; if(sha1_32(buf)==-1222025602){break;} } + for(i=-128;i<-125;i++){ buf[229]=(byte)i; if(sha1_32(buf)==-2116087238){break;} } + for(i=31;i<39;i++){ buf[230]=(byte)i; if(sha1_32(buf)==56723441){break;} } + for(i=-97;i<-85;i++){ buf[231]=(byte)i; if(sha1_32(buf)==-1125905803){break;} } + for(i=-62;i<-45;i++){ buf[232]=(byte)i; if(sha1_32(buf)==990895925){break;} } + for(i=-72;i<-58;i++){ buf[233]=(byte)i; if(sha1_32(buf)==-1376776670){break;} } + for(i=44;i<47;i++){ buf[234]=(byte)i; if(sha1_32(buf)==480225460){break;} } + for(i=-21;i<-3;i++){ buf[235]=(byte)i; if(sha1_32(buf)==-821765744){break;} } + for(i=-111;i<-104;i++){ buf[236]=(byte)i; if(sha1_32(buf)==-863307099){break;} } + for(i=-128;i<-111;i++){ buf[237]=(byte)i; if(sha1_32(buf)==1925384714){break;} } + for(i=-83;i<-72;i++){ buf[238]=(byte)i; if(sha1_32(buf)==-810575860){break;} } + for(i=-24;i<-1;i++){ buf[239]=(byte)i; if(sha1_32(buf)==-523136410){break;} } + for(i=-83;i<-58;i++){ buf[240]=(byte)i; if(sha1_32(buf)==1170602926){break;} } + for(i=6;i<14;i++){ buf[241]=(byte)i; if(sha1_32(buf)==111023715){break;} } + for(i=90;i<107;i++){ buf[242]=(byte)i; if(sha1_32(buf)==-1282467375){break;} } + for(i=2;i<3;i++){ buf[243]=(byte)i; if(sha1_32(buf)==-1449750294){break;} } + for(i=-124;i<-95;i++){ buf[244]=(byte)i; if(sha1_32(buf)==1609889082){break;} } + for(i=28;i<38;i++){ buf[245]=(byte)i; if(sha1_32(buf)==875830543){break;} } + for(i=-1;i<28;i++){ buf[246]=(byte)i; if(sha1_32(buf)==1535923499){break;} } + for(i=-33;i<-17;i++){ buf[247]=(byte)i; if(sha1_32(buf)==689781359){break;} } + for(i=80;i<94;i++){ buf[248]=(byte)i; if(sha1_32(buf)==1614888858){break;} } + for(i=65;i<90;i++){ buf[249]=(byte)i; if(sha1_32(buf)==1135391074){break;} } + for(i=117;i<128;i++){ buf[250]=(byte)i; if(sha1_32(buf)==-686174037){break;} } + for(i=97;i<105;i++){ buf[251]=(byte)i; if(sha1_32(buf)==-1437888082){break;} } + for(i=55;i<69;i++){ buf[252]=(byte)i; if(sha1_32(buf)==1362356396){break;} } + for(i=-15;i<3;i++){ buf[253]=(byte)i; if(sha1_32(buf)==1948572451){break;} } + for(i=-70;i<-47;i++){ buf[254]=(byte)i; if(sha1_32(buf)==2078354710){break;} } + for(i=-14;i<8;i++){ buf[255]=(byte)i; if(sha1_32(buf)==-1421641677){break;} } + for(i=-116;i<-101;i++){ buf[256]=(byte)i; if(sha1_32(buf)==1566684267){break;} } + for(i=20;i<39;i++){ buf[257]=(byte)i; if(sha1_32(buf)==-175732101){break;} } + for(i=-19;i<11;i++){ buf[258]=(byte)i; if(sha1_32(buf)==-1186043155){break;} } + for(i=-4;i<14;i++){ buf[259]=(byte)i; if(sha1_32(buf)==-79605125){break;} } + for(i=102;i<119;i++){ buf[260]=(byte)i; if(sha1_32(buf)==-420244970){break;} } + for(i=33;i<44;i++){ buf[261]=(byte)i; if(sha1_32(buf)==52041363){break;} } + for(i=-93;i<-73;i++){ buf[262]=(byte)i; if(sha1_32(buf)==1195247081){break;} } + for(i=92;i<110;i++){ buf[263]=(byte)i; if(sha1_32(buf)==950914747){break;} } + for(i=20;i<36;i++){ buf[264]=(byte)i; if(sha1_32(buf)==908373225){break;} } + for(i=-128;i<-115;i++){ buf[265]=(byte)i; if(sha1_32(buf)==1781017630){break;} } + for(i=-31;i<-10;i++){ buf[266]=(byte)i; if(sha1_32(buf)==1322505273){break;} } + for(i=16;i<28;i++){ buf[267]=(byte)i; if(sha1_32(buf)==-1361433270){break;} } + for(i=-61;i<-43;i++){ buf[268]=(byte)i; if(sha1_32(buf)==-851359458){break;} } + for(i=92;i<113;i++){ buf[269]=(byte)i; if(sha1_32(buf)==-1868884631){break;} } + for(i=1;i<16;i++){ buf[270]=(byte)i; if(sha1_32(buf)==1087081334){break;} } + for(i=-69;i<-59;i++){ buf[271]=(byte)i; if(sha1_32(buf)==1488478048){break;} } + for(i=-71;i<-52;i++){ buf[272]=(byte)i; if(sha1_32(buf)==370206610){break;} } + for(i=-20;i<-13;i++){ buf[273]=(byte)i; if(sha1_32(buf)==1397236068){break;} } + for(i=45;i<49;i++){ buf[274]=(byte)i; if(sha1_32(buf)==-1138281536){break;} } + for(i=119;i<128;i++){ buf[275]=(byte)i; if(sha1_32(buf)==-429617078){break;} } + for(i=-68;i<-67;i++){ buf[276]=(byte)i; if(sha1_32(buf)==61334015){break;} } + for(i=93;i<100;i++){ buf[277]=(byte)i; if(sha1_32(buf)==-1026018987){break;} } + for(i=-81;i<-70;i++){ buf[278]=(byte)i; if(sha1_32(buf)==867755380){break;} } + for(i=118;i<124;i++){ buf[279]=(byte)i; if(sha1_32(buf)==775095680){break;} } + for(i=102;i<126;i++){ buf[280]=(byte)i; if(sha1_32(buf)==-1686360851){break;} } + for(i=-34;i<-4;i++){ buf[281]=(byte)i; if(sha1_32(buf)==-1103388644){break;} } + for(i=80;i<98;i++){ buf[282]=(byte)i; if(sha1_32(buf)==-1171605593){break;} } + for(i=33;i<53;i++){ buf[283]=(byte)i; if(sha1_32(buf)==-1048739608){break;} } + for(i=-124;i<-112;i++){ buf[284]=(byte)i; if(sha1_32(buf)==-324156208){break;} } + for(i=107;i<122;i++){ buf[285]=(byte)i; if(sha1_32(buf)==-1910086713){break;} } + for(i=-71;i<-55;i++){ buf[286]=(byte)i; if(sha1_32(buf)==2074936258){break;} } + for(i=70;i<91;i++){ buf[287]=(byte)i; if(sha1_32(buf)==681070660){break;} } + for(i=43;i<49;i++){ buf[288]=(byte)i; if(sha1_32(buf)==-383734725){break;} } + for(i=86;i<87;i++){ buf[289]=(byte)i; if(sha1_32(buf)==556081178){break;} } + for(i=70;i<94;i++){ buf[290]=(byte)i; if(sha1_32(buf)==2143166463){break;} } + for(i=-28;i<-11;i++){ buf[291]=(byte)i; if(sha1_32(buf)==1292496247){break;} } + for(i=71;i<86;i++){ buf[292]=(byte)i; if(sha1_32(buf)==1844811825){break;} } + for(i=-114;i<-104;i++){ buf[293]=(byte)i; if(sha1_32(buf)==1323054413){break;} } + for(i=36;i<52;i++){ buf[294]=(byte)i; if(sha1_32(buf)==-1139981795){break;} } + for(i=-8;i<0;i++){ buf[295]=(byte)i; if(sha1_32(buf)==1127901793){break;} } + for(i=23;i<45;i++){ buf[296]=(byte)i; if(sha1_32(buf)==1240273528){break;} } + for(i=23;i<42;i++){ buf[297]=(byte)i; if(sha1_32(buf)==-662859486){break;} } + for(i=-128;i<-106;i++){ buf[298]=(byte)i; if(sha1_32(buf)==1794822263){break;} } + for(i=8;i<26;i++){ buf[299]=(byte)i; if(sha1_32(buf)==959734032){break;} } + for(i=-42;i<-36;i++){ buf[300]=(byte)i; if(sha1_32(buf)==-186158208){break;} } + for(i=-82;i<-60;i++){ buf[301]=(byte)i; if(sha1_32(buf)==-1498030536){break;} } + for(i=-70;i<-41;i++){ buf[302]=(byte)i; if(sha1_32(buf)==1445295671){break;} } + for(i=-104;i<-97;i++){ buf[303]=(byte)i; if(sha1_32(buf)==-857606524){break;} } + for(i=11;i<38;i++){ buf[304]=(byte)i; if(sha1_32(buf)==-2079097095){break;} } + for(i=-19;i<-15;i++){ buf[305]=(byte)i; if(sha1_32(buf)==1263307227){break;} } + for(i=0;i<23;i++){ buf[306]=(byte)i; if(sha1_32(buf)==1675806033){break;} } + for(i=-44;i<-28;i++){ buf[307]=(byte)i; if(sha1_32(buf)==-1453985331){break;} } + for(i=-34;i<-14;i++){ buf[308]=(byte)i; if(sha1_32(buf)==1938579318){break;} } + for(i=-56;i<-50;i++){ buf[309]=(byte)i; if(sha1_32(buf)==981269455){break;} } + for(i=47;i<64;i++){ buf[310]=(byte)i; if(sha1_32(buf)==-960616575){break;} } + for(i=13;i<40;i++){ buf[311]=(byte)i; if(sha1_32(buf)==1174906321){break;} } + for(i=-78;i<-65;i++){ buf[312]=(byte)i; if(sha1_32(buf)==1786385487){break;} } + for(i=97;i<114;i++){ buf[313]=(byte)i; if(sha1_32(buf)==1856017351){break;} } + for(i=57;i<75;i++){ buf[314]=(byte)i; if(sha1_32(buf)==-390209586){break;} } + for(i=-28;i<-17;i++){ buf[315]=(byte)i; if(sha1_32(buf)==1557284659){break;} } + for(i=-125;i<-122;i++){ buf[316]=(byte)i; if(sha1_32(buf)==1707896620){break;} } + for(i=-125;i<-114;i++){ buf[317]=(byte)i; if(sha1_32(buf)==1545252813){break;} } + for(i=64;i<84;i++){ buf[318]=(byte)i; if(sha1_32(buf)==834379007){break;} } + for(i=95;i<112;i++){ buf[319]=(byte)i; if(sha1_32(buf)==-652662847){break;} } + for(i=65;i<79;i++){ buf[320]=(byte)i; if(sha1_32(buf)==-916862378){break;} } + for(i=89;i<97;i++){ buf[321]=(byte)i; if(sha1_32(buf)==1256243200){break;} } + for(i=40;i<43;i++){ buf[322]=(byte)i; if(sha1_32(buf)==1352555621){break;} } + for(i=-128;i<-115;i++){ buf[323]=(byte)i; if(sha1_32(buf)==-1240624110){break;} } + for(i=38;i<55;i++){ buf[324]=(byte)i; if(sha1_32(buf)==1256417714){break;} } + for(i=-88;i<-66;i++){ buf[325]=(byte)i; if(sha1_32(buf)==27675450){break;} } + for(i=-127;i<-111;i++){ buf[326]=(byte)i; if(sha1_32(buf)==1558400560){break;} } + for(i=-59;i<-36;i++){ buf[327]=(byte)i; if(sha1_32(buf)==1569826700){break;} } + for(i=12;i<37;i++){ buf[328]=(byte)i; if(sha1_32(buf)==1547382227){break;} } + for(i=-86;i<-68;i++){ buf[329]=(byte)i; if(sha1_32(buf)==2019607936){break;} } + for(i=2;i<24;i++){ buf[330]=(byte)i; if(sha1_32(buf)==-1757408613){break;} } + for(i=75;i<91;i++){ buf[331]=(byte)i; if(sha1_32(buf)==139528627){break;} } + for(i=-95;i<-85;i++){ buf[332]=(byte)i; if(sha1_32(buf)==-738843284){break;} } + for(i=-75;i<-49;i++){ buf[333]=(byte)i; if(sha1_32(buf)==-2093377577){break;} } + for(i=55;i<69;i++){ buf[334]=(byte)i; if(sha1_32(buf)==770305433){break;} } + for(i=1;i<10;i++){ buf[335]=(byte)i; if(sha1_32(buf)==123700283){break;} } + for(i=-17;i<10;i++){ buf[336]=(byte)i; if(sha1_32(buf)==262166502){break;} } + for(i=-128;i<-116;i++){ buf[337]=(byte)i; if(sha1_32(buf)==2075691425){break;} } + for(i=-78;i<-65;i++){ buf[338]=(byte)i; if(sha1_32(buf)==92964351){break;} } + for(i=-30;i<-14;i++){ buf[339]=(byte)i; if(sha1_32(buf)==1165908725){break;} } + for(i=20;i<32;i++){ buf[340]=(byte)i; if(sha1_32(buf)==-836059634){break;} } + for(i=-27;i<-7;i++){ buf[341]=(byte)i; if(sha1_32(buf)==473014824){break;} } + for(i=62;i<77;i++){ buf[342]=(byte)i; if(sha1_32(buf)==1533421976){break;} } + for(i=121;i<128;i++){ buf[343]=(byte)i; if(sha1_32(buf)==1286800324){break;} } + for(i=-128;i<-119;i++){ buf[344]=(byte)i; if(sha1_32(buf)==-1467669336){break;} } + for(i=-20;i<-12;i++){ buf[345]=(byte)i; if(sha1_32(buf)==1238585230){break;} } + for(i=-64;i<-51;i++){ buf[346]=(byte)i; if(sha1_32(buf)==220306295){break;} } + for(i=7;i<31;i++){ buf[347]=(byte)i; if(sha1_32(buf)==-1559591610){break;} } + for(i=-98;i<-92;i++){ buf[348]=(byte)i; if(sha1_32(buf)==-1728805110){break;} } + for(i=-33;i<-27;i++){ buf[349]=(byte)i; if(sha1_32(buf)==-823465976){break;} } + for(i=-78;i<-50;i++){ buf[350]=(byte)i; if(sha1_32(buf)==1073874256){break;} } + for(i=10;i<26;i++){ buf[351]=(byte)i; if(sha1_32(buf)==-1206375065){break;} } + for(i=20;i<36;i++){ buf[352]=(byte)i; if(sha1_32(buf)==1290895631){break;} } + for(i=19;i<23;i++){ buf[353]=(byte)i; if(sha1_32(buf)==459331649){break;} } + for(i=113;i<128;i++){ buf[354]=(byte)i; if(sha1_32(buf)==372758153){break;} } + for(i=-25;i<-5;i++){ buf[355]=(byte)i; if(sha1_32(buf)==-928067560){break;} } + for(i=-119;i<-106;i++){ buf[356]=(byte)i; if(sha1_32(buf)==808697252){break;} } + for(i=-53;i<-37;i++){ buf[357]=(byte)i; if(sha1_32(buf)==1138525558){break;} } + for(i=-16;i<4;i++){ buf[358]=(byte)i; if(sha1_32(buf)==-1449657209){break;} } + for(i=77;i<96;i++){ buf[359]=(byte)i; if(sha1_32(buf)==-1881999714){break;} } + for(i=44;i<61;i++){ buf[360]=(byte)i; if(sha1_32(buf)==323348962){break;} } + for(i=44;i<53;i++){ buf[361]=(byte)i; if(sha1_32(buf)==1117989614){break;} } + for(i=-118;i<-102;i++){ buf[362]=(byte)i; if(sha1_32(buf)==417606728){break;} } + for(i=10;i<26;i++){ buf[363]=(byte)i; if(sha1_32(buf)==-1732857528){break;} } + for(i=71;i<88;i++){ buf[364]=(byte)i; if(sha1_32(buf)==1214366528){break;} } + for(i=71;i<92;i++){ buf[365]=(byte)i; if(sha1_32(buf)==2116539288){break;} } + for(i=-124;i<-117;i++){ buf[366]=(byte)i; if(sha1_32(buf)==1966030432){break;} } + for(i=112;i<128;i++){ buf[367]=(byte)i; if(sha1_32(buf)==442833700){break;} } + for(i=16;i<46;i++){ buf[368]=(byte)i; if(sha1_32(buf)==1209047741){break;} } + for(i=-99;i<-80;i++){ buf[369]=(byte)i; if(sha1_32(buf)==2064105203){break;} } + for(i=23;i<31;i++){ buf[370]=(byte)i; if(sha1_32(buf)==1962921844){break;} } + for(i=93;i<118;i++){ buf[371]=(byte)i; if(sha1_32(buf)==-1798195149){break;} } + for(i=-99;i<-94;i++){ buf[372]=(byte)i; if(sha1_32(buf)==1196726097){break;} } + for(i=109;i<121;i++){ buf[373]=(byte)i; if(sha1_32(buf)==-1629763996){break;} } + for(i=-29;i<-9;i++){ buf[374]=(byte)i; if(sha1_32(buf)==-1135791940){break;} } + for(i=-103;i<-85;i++){ buf[375]=(byte)i; if(sha1_32(buf)==-1921345995){break;} } + for(i=95;i<109;i++){ buf[376]=(byte)i; if(sha1_32(buf)==924551682){break;} } + for(i=45;i<50;i++){ buf[377]=(byte)i; if(sha1_32(buf)==813658466){break;} } + for(i=-25;i<-12;i++){ buf[378]=(byte)i; if(sha1_32(buf)==-1647238183){break;} } + for(i=-128;i<-106;i++){ buf[379]=(byte)i; if(sha1_32(buf)==-687188532){break;} } + for(i=87;i<107;i++){ buf[380]=(byte)i; if(sha1_32(buf)==-157977277){break;} } + for(i=88;i<114;i++){ buf[381]=(byte)i; if(sha1_32(buf)==-525902358){break;} } + for(i=-3;i<21;i++){ buf[382]=(byte)i; if(sha1_32(buf)==148447155){break;} } + for(i=-100;i<-81;i++){ buf[383]=(byte)i; if(sha1_32(buf)==-464787119){break;} } + for(i=-12;i<0;i++){ buf[384]=(byte)i; if(sha1_32(buf)==-792316736){break;} } + for(i=-38;i<-31;i++){ buf[385]=(byte)i; if(sha1_32(buf)==-858139243){break;} } + for(i=52;i<64;i++){ buf[386]=(byte)i; if(sha1_32(buf)==-1069769593){break;} } + for(i=8;i<16;i++){ buf[387]=(byte)i; if(sha1_32(buf)==1043018564){break;} } + for(i=116;i<128;i++){ buf[388]=(byte)i; if(sha1_32(buf)==1792935681){break;} } + for(i=-97;i<-75;i++){ buf[389]=(byte)i; if(sha1_32(buf)==-1936047353){break;} } + for(i=-59;i<-42;i++){ buf[390]=(byte)i; if(sha1_32(buf)==1311489621){break;} } + for(i=-113;i<-98;i++){ buf[391]=(byte)i; if(sha1_32(buf)==1837646775){break;} } + for(i=114;i<127;i++){ buf[392]=(byte)i; if(sha1_32(buf)==1383108593){break;} } + for(i=104;i<123;i++){ buf[393]=(byte)i; if(sha1_32(buf)==2093039570){break;} } + for(i=75;i<85;i++){ buf[394]=(byte)i; if(sha1_32(buf)==1054745819){break;} } + for(i=88;i<105;i++){ buf[395]=(byte)i; if(sha1_32(buf)==321524122){break;} } + for(i=-115;i<-111;i++){ buf[396]=(byte)i; if(sha1_32(buf)==1380327489){break;} } + for(i=-65;i<-40;i++){ buf[397]=(byte)i; if(sha1_32(buf)==-1868200771){break;} } + for(i=-128;i<-117;i++){ buf[398]=(byte)i; if(sha1_32(buf)==-306538795){break;} } + for(i=-7;i<18;i++){ buf[399]=(byte)i; if(sha1_32(buf)==78108234){break;} } + for(i=42;i<64;i++){ buf[400]=(byte)i; if(sha1_32(buf)==218521347){break;} } + for(i=16;i<30;i++){ buf[401]=(byte)i; if(sha1_32(buf)==1103448038){break;} } + for(i=-12;i<3;i++){ buf[402]=(byte)i; if(sha1_32(buf)==-792783999){break;} } + for(i=52;i<72;i++){ buf[403]=(byte)i; if(sha1_32(buf)==2134375104){break;} } + for(i=-33;i<-16;i++){ buf[404]=(byte)i; if(sha1_32(buf)==1751314759){break;} } + for(i=-3;i<20;i++){ buf[405]=(byte)i; if(sha1_32(buf)==-492128099){break;} } + for(i=-92;i<-79;i++){ buf[406]=(byte)i; if(sha1_32(buf)==788144321){break;} } + for(i=-86;i<-71;i++){ buf[407]=(byte)i; if(sha1_32(buf)==1021440416){break;} } + for(i=70;i<85;i++){ buf[408]=(byte)i; if(sha1_32(buf)==-1757753705){break;} } + for(i=-4;i<3;i++){ buf[409]=(byte)i; if(sha1_32(buf)==-1757753705){break;} } + for(i=57;i<60;i++){ buf[410]=(byte)i; if(sha1_32(buf)==351743013){break;} } + for(i=1;i<28;i++){ buf[411]=(byte)i; if(sha1_32(buf)==346949450){break;} } + for(i=67;i<84;i++){ buf[412]=(byte)i; if(sha1_32(buf)==1484167264){break;} } + for(i=-109;i<-105;i++){ buf[413]=(byte)i; if(sha1_32(buf)==-225493642){break;} } + for(i=114;i<128;i++){ buf[414]=(byte)i; if(sha1_32(buf)==-1691339989){break;} } + for(i=-16;i<4;i++){ buf[415]=(byte)i; if(sha1_32(buf)==-1177687546){break;} } + for(i=40;i<53;i++){ buf[416]=(byte)i; if(sha1_32(buf)==-44730966){break;} } + for(i=113;i<128;i++){ buf[417]=(byte)i; if(sha1_32(buf)==-1099287942){break;} } + for(i=-110;i<-93;i++){ buf[418]=(byte)i; if(sha1_32(buf)==1104397920){break;} } + for(i=-41;i<-37;i++){ buf[419]=(byte)i; if(sha1_32(buf)==410370293){break;} } + for(i=117;i<128;i++){ buf[420]=(byte)i; if(sha1_32(buf)==-1706304772){break;} } + for(i=-32;i<-16;i++){ buf[421]=(byte)i; if(sha1_32(buf)==1779465200){break;} } + for(i=-72;i<-53;i++){ buf[422]=(byte)i; if(sha1_32(buf)==783332057){break;} } + for(i=71;i<101;i++){ buf[423]=(byte)i; if(sha1_32(buf)==-1600770238){break;} } + for(i=-10;i<11;i++){ buf[424]=(byte)i; if(sha1_32(buf)==-1600770238){break;} } + for(i=18;i<26;i++){ buf[425]=(byte)i; if(sha1_32(buf)==-354652161){break;} } + for(i=-94;i<-84;i++){ buf[426]=(byte)i; if(sha1_32(buf)==1369038958){break;} } + for(i=104;i<115;i++){ buf[427]=(byte)i; if(sha1_32(buf)==1105731567){break;} } + for(i=-8;i<6;i++){ buf[428]=(byte)i; if(sha1_32(buf)==-1440254697){break;} } + for(i=-86;i<-76;i++){ buf[429]=(byte)i; if(sha1_32(buf)==1395951968){break;} } + for(i=19;i<46;i++){ buf[430]=(byte)i; if(sha1_32(buf)==-1662385736){break;} } + for(i=-104;i<-92;i++){ buf[431]=(byte)i; if(sha1_32(buf)==-1600360904){break;} } + for(i=-93;i<-76;i++){ buf[432]=(byte)i; if(sha1_32(buf)==-1173475091){break;} } + for(i=-95;i<-73;i++){ buf[433]=(byte)i; if(sha1_32(buf)==2031419338){break;} } + for(i=79;i<90;i++){ buf[434]=(byte)i; if(sha1_32(buf)==1858593452){break;} } + for(i=-79;i<-56;i++){ buf[435]=(byte)i; if(sha1_32(buf)==-970837550){break;} } + for(i=-107;i<-100;i++){ buf[436]=(byte)i; if(sha1_32(buf)==1859497737){break;} } + for(i=-6;i<5;i++){ buf[437]=(byte)i; if(sha1_32(buf)==350160746){break;} } + for(i=13;i<35;i++){ buf[438]=(byte)i; if(sha1_32(buf)==-1876000603){break;} } + for(i=-111;i<-87;i++){ buf[439]=(byte)i; if(sha1_32(buf)==-1517649888){break;} } + for(i=72;i<81;i++){ buf[440]=(byte)i; if(sha1_32(buf)==-1168224674){break;} } + for(i=-119;i<-98;i++){ buf[441]=(byte)i; if(sha1_32(buf)==-211497471){break;} } + for(i=45;i<73;i++){ buf[442]=(byte)i; if(sha1_32(buf)==1286373258){break;} } + for(i=2;i<23;i++){ buf[443]=(byte)i; if(sha1_32(buf)==1102706167){break;} } + for(i=-120;i<-101;i++){ buf[444]=(byte)i; if(sha1_32(buf)==440282413){break;} } + for(i=-58;i<-49;i++){ buf[445]=(byte)i; if(sha1_32(buf)==1287734805){break;} } + for(i=83;i<96;i++){ buf[446]=(byte)i; if(sha1_32(buf)==-198551034){break;} } + for(i=-21;i<-2;i++){ buf[447]=(byte)i; if(sha1_32(buf)==-1055537683){break;} } + for(i=-116;i<-98;i++){ buf[448]=(byte)i; if(sha1_32(buf)==-2019070452){break;} } + for(i=-100;i<-87;i++){ buf[449]=(byte)i; if(sha1_32(buf)==1645730466){break;} } + for(i=36;i<43;i++){ buf[450]=(byte)i; if(sha1_32(buf)==-1919037742){break;} } + for(i=-124;i<-106;i++){ buf[451]=(byte)i; if(sha1_32(buf)==-812420350){break;} } + for(i=-30;i<-5;i++){ buf[452]=(byte)i; if(sha1_32(buf)==-1361199407){break;} } + for(i=-128;i<-106;i++){ buf[453]=(byte)i; if(sha1_32(buf)==-1679597417){break;} } + for(i=-56;i<-48;i++){ buf[454]=(byte)i; if(sha1_32(buf)==917856781){break;} } + for(i=-12;i<12;i++){ buf[455]=(byte)i; if(sha1_32(buf)==1714614132){break;} } + for(i=121;i<125;i++){ buf[456]=(byte)i; if(sha1_32(buf)==2068334508){break;} } + for(i=-124;i<-107;i++){ buf[457]=(byte)i; if(sha1_32(buf)==347480362){break;} } + for(i=-87;i<-67;i++){ buf[458]=(byte)i; if(sha1_32(buf)==-1289641013){break;} } + for(i=116;i<128;i++){ buf[459]=(byte)i; if(sha1_32(buf)==1175185600){break;} } + for(i=-84;i<-66;i++){ buf[460]=(byte)i; if(sha1_32(buf)==-18576159){break;} } + for(i=-23;i<-9;i++){ buf[461]=(byte)i; if(sha1_32(buf)==-1938771769){break;} } + for(i=-44;i<-34;i++){ buf[462]=(byte)i; if(sha1_32(buf)==-1187820649){break;} } + for(i=-128;i<-121;i++){ buf[463]=(byte)i; if(sha1_32(buf)==578015200){break;} } + for(i=34;i<43;i++){ buf[464]=(byte)i; if(sha1_32(buf)==691096919){break;} } + for(i=27;i<43;i++){ buf[465]=(byte)i; if(sha1_32(buf)==693912125){break;} } + for(i=-81;i<-60;i++){ buf[466]=(byte)i; if(sha1_32(buf)==1963501561){break;} } + for(i=23;i<40;i++){ buf[467]=(byte)i; if(sha1_32(buf)==-1812234144){break;} } + for(i=-85;i<-75;i++){ buf[468]=(byte)i; if(sha1_32(buf)==-957878455){break;} } + for(i=64;i<79;i++){ buf[469]=(byte)i; if(sha1_32(buf)==-963610725){break;} } + for(i=55;i<70;i++){ buf[470]=(byte)i; if(sha1_32(buf)==-343529411){break;} } + for(i=20;i<34;i++){ buf[471]=(byte)i; if(sha1_32(buf)==-1704740558){break;} } + for(i=73;i<88;i++){ buf[472]=(byte)i; if(sha1_32(buf)==-1113725046){break;} } + for(i=-45;i<-27;i++){ buf[473]=(byte)i; if(sha1_32(buf)==-2145645120){break;} } + for(i=-77;i<-55;i++){ buf[474]=(byte)i; if(sha1_32(buf)==-883203113){break;} } + for(i=80;i<95;i++){ buf[475]=(byte)i; if(sha1_32(buf)==-2043978145){break;} } + for(i=-101;i<-89;i++){ buf[476]=(byte)i; if(sha1_32(buf)==-408065104){break;} } + for(i=-119;i<-93;i++){ buf[477]=(byte)i; if(sha1_32(buf)==-431406000){break;} } + for(i=-48;i<-25;i++){ buf[478]=(byte)i; if(sha1_32(buf)==-1201005378){break;} } + for(i=-59;i<-41;i++){ buf[479]=(byte)i; if(sha1_32(buf)==-1041009913){break;} } + for(i=105;i<119;i++){ buf[480]=(byte)i; if(sha1_32(buf)==1462073621){break;} } + for(i=-56;i<-41;i++){ buf[481]=(byte)i; if(sha1_32(buf)==116529330){break;} } + for(i=94;i<110;i++){ buf[482]=(byte)i; if(sha1_32(buf)==-1462052658){break;} } + for(i=-98;i<-67;i++){ buf[483]=(byte)i; if(sha1_32(buf)==1167200785){break;} } + for(i=-54;i<-27;i++){ buf[484]=(byte)i; if(sha1_32(buf)==-1202588922){break;} } + for(i=115;i<128;i++){ buf[485]=(byte)i; if(sha1_32(buf)==-1101204127){break;} } + for(i=50;i<65;i++){ buf[486]=(byte)i; if(sha1_32(buf)==2061686263){break;} } + for(i=25;i<36;i++){ buf[487]=(byte)i; if(sha1_32(buf)==-1420568322){break;} } + for(i=-104;i<-89;i++){ buf[488]=(byte)i; if(sha1_32(buf)==-1237053071){break;} } + for(i=-24;i<-5;i++){ buf[489]=(byte)i; if(sha1_32(buf)==-134331954){break;} } + for(i=-115;i<-99;i++){ buf[490]=(byte)i; if(sha1_32(buf)==156999132){break;} } + for(i=56;i<82;i++){ buf[491]=(byte)i; if(sha1_32(buf)==-1603977095){break;} } + for(i=48;i<59;i++){ buf[492]=(byte)i; if(sha1_32(buf)==686226542){break;} } + for(i=-2;i<12;i++){ buf[493]=(byte)i; if(sha1_32(buf)==1892334296){break;} } + for(i=74;i<96;i++){ buf[494]=(byte)i; if(sha1_32(buf)==65740742){break;} } + for(i=68;i<88;i++){ buf[495]=(byte)i; if(sha1_32(buf)==-1280035118){break;} } + for(i=45;i<57;i++){ buf[496]=(byte)i; if(sha1_32(buf)==1642936812){break;} } + for(i=-128;i<-112;i++){ buf[497]=(byte)i; if(sha1_32(buf)==382969491){break;} } + for(i=16;i<33;i++){ buf[498]=(byte)i; if(sha1_32(buf)==-547547377){break;} } + for(i=-60;i<-39;i++){ buf[499]=(byte)i; if(sha1_32(buf)==-1842153238){break;} } + for(i=-69;i<-48;i++){ buf[500]=(byte)i; if(sha1_32(buf)==-2021292184){break;} } + for(i=101;i<121;i++){ buf[501]=(byte)i; if(sha1_32(buf)==-1453688289){break;} } + for(i=111;i<123;i++){ buf[502]=(byte)i; if(sha1_32(buf)==-1350737308){break;} } + for(i=-19;i<1;i++){ buf[503]=(byte)i; if(sha1_32(buf)==-1442064354){break;} } + for(i=119;i<128;i++){ buf[504]=(byte)i; if(sha1_32(buf)==-1703722060){break;} } + for(i=81;i<90;i++){ buf[505]=(byte)i; if(sha1_32(buf)==-56183450){break;} } + for(i=86;i<107;i++){ buf[506]=(byte)i; if(sha1_32(buf)==301583941){break;} } + for(i=48;i<77;i++){ buf[507]=(byte)i; if(sha1_32(buf)==-1098954584){break;} } + for(i=-101;i<-86;i++){ buf[508]=(byte)i; if(sha1_32(buf)==882871208){break;} } + for(i=96;i<101;i++){ buf[509]=(byte)i; if(sha1_32(buf)==-125057558){break;} } + for(i=-10;i<8;i++){ buf[510]=(byte)i; if(sha1_32(buf)==1007551878){break;} } + for(i=-75;i<-71;i++){ buf[511]=(byte)i; if(sha1_32(buf)==-889315492){break;} } + for(i=26;i<46;i++){ buf[512]=(byte)i; if(sha1_32(buf)==-1493230782){break;} } + for(i=-128;i<-118;i++){ buf[513]=(byte)i; if(sha1_32(buf)==-1217430520){break;} } + for(i=-61;i<-51;i++){ buf[514]=(byte)i; if(sha1_32(buf)==-719766361){break;} } + for(i=97;i<108;i++){ buf[515]=(byte)i; if(sha1_32(buf)==1780444762){break;} } + for(i=7;i<31;i++){ buf[516]=(byte)i; if(sha1_32(buf)==93631430){break;} } + for(i=-128;i<-109;i++){ buf[517]=(byte)i; if(sha1_32(buf)==-1579614481){break;} } + for(i=36;i<56;i++){ buf[518]=(byte)i; if(sha1_32(buf)==1122764340){break;} } + for(i=-91;i<-69;i++){ buf[519]=(byte)i; if(sha1_32(buf)==204441373){break;} } + for(i=-52;i<-32;i++){ buf[520]=(byte)i; if(sha1_32(buf)==-1345108836){break;} } + for(i=-22;i<-7;i++){ buf[521]=(byte)i; if(sha1_32(buf)==-473026700){break;} } + for(i=-18;i<3;i++){ buf[522]=(byte)i; if(sha1_32(buf)==-53570723){break;} } + for(i=-28;i<-22;i++){ buf[523]=(byte)i; if(sha1_32(buf)==-742354020){break;} } + for(i=5;i<22;i++){ buf[524]=(byte)i; if(sha1_32(buf)==57188405){break;} } + for(i=-118;i<-97;i++){ buf[525]=(byte)i; if(sha1_32(buf)==-805152784){break;} } + for(i=101;i<110;i++){ buf[526]=(byte)i; if(sha1_32(buf)==1884589447){break;} } + for(i=22;i<41;i++){ buf[527]=(byte)i; if(sha1_32(buf)==1321287803){break;} } + for(i=36;i<51;i++){ buf[528]=(byte)i; if(sha1_32(buf)==1991102187){break;} } + for(i=77;i<100;i++){ buf[529]=(byte)i; if(sha1_32(buf)==116811737){break;} } + for(i=34;i<54;i++){ buf[530]=(byte)i; if(sha1_32(buf)==-1621297999){break;} } + for(i=34;i<51;i++){ buf[531]=(byte)i; if(sha1_32(buf)==-1169590718){break;} } + for(i=49;i<56;i++){ buf[532]=(byte)i; if(sha1_32(buf)==-1433549503){break;} } + for(i=101;i<108;i++){ buf[533]=(byte)i; if(sha1_32(buf)==-1961000107){break;} } + for(i=-13;i<9;i++){ buf[534]=(byte)i; if(sha1_32(buf)==-491166058){break;} } + for(i=88;i<113;i++){ buf[535]=(byte)i; if(sha1_32(buf)==-1433097452){break;} } + for(i=-18;i<-4;i++){ buf[536]=(byte)i; if(sha1_32(buf)==-196646497){break;} } + for(i=-109;i<-93;i++){ buf[537]=(byte)i; if(sha1_32(buf)==-1040279050){break;} } + for(i=-85;i<-74;i++){ buf[538]=(byte)i; if(sha1_32(buf)==2144991839){break;} } + for(i=-11;i<-5;i++){ buf[539]=(byte)i; if(sha1_32(buf)==-1322695683){break;} } + for(i=-3;i<19;i++){ buf[540]=(byte)i; if(sha1_32(buf)==1002324823){break;} } + for(i=64;i<95;i++){ buf[541]=(byte)i; if(sha1_32(buf)==1839522840){break;} } + for(i=72;i<87;i++){ buf[542]=(byte)i; if(sha1_32(buf)==1154496666){break;} } + for(i=-109;i<-86;i++){ buf[543]=(byte)i; if(sha1_32(buf)==-1943462088){break;} } + for(i=59;i<63;i++){ buf[544]=(byte)i; if(sha1_32(buf)==-229369447){break;} } + for(i=44;i<55;i++){ buf[545]=(byte)i; if(sha1_32(buf)==1981459588){break;} } + for(i=-115;i<-98;i++){ buf[546]=(byte)i; if(sha1_32(buf)==-1369068247){break;} } + for(i=-124;i<-108;i++){ buf[547]=(byte)i; if(sha1_32(buf)==1244213688){break;} } + for(i=77;i<84;i++){ buf[548]=(byte)i; if(sha1_32(buf)==-1907866199){break;} } + for(i=-124;i<-104;i++){ buf[549]=(byte)i; if(sha1_32(buf)==-1303249819){break;} } + for(i=79;i<97;i++){ buf[550]=(byte)i; if(sha1_32(buf)==-2036674089){break;} } + for(i=-45;i<-29;i++){ buf[551]=(byte)i; if(sha1_32(buf)==-296348860){break;} } + for(i=-46;i<-33;i++){ buf[552]=(byte)i; if(sha1_32(buf)==-185013177){break;} } + for(i=-124;i<-103;i++){ buf[553]=(byte)i; if(sha1_32(buf)==367236665){break;} } + for(i=-6;i<15;i++){ buf[554]=(byte)i; if(sha1_32(buf)==864237735){break;} } + for(i=80;i<101;i++){ buf[555]=(byte)i; if(sha1_32(buf)==1088399791){break;} } + for(i=14;i<35;i++){ buf[556]=(byte)i; if(sha1_32(buf)==-1805827882){break;} } + for(i=91;i<105;i++){ buf[557]=(byte)i; if(sha1_32(buf)==1644855928){break;} } + for(i=-102;i<-101;i++){ buf[558]=(byte)i; if(sha1_32(buf)==291861395){break;} } + for(i=94;i<102;i++){ buf[559]=(byte)i; if(sha1_32(buf)==618025978){break;} } + for(i=-88;i<-77;i++){ buf[560]=(byte)i; if(sha1_32(buf)==-2058102905){break;} } + for(i=78;i<100;i++){ buf[561]=(byte)i; if(sha1_32(buf)==1295014773){break;} } + for(i=-10;i<3;i++){ buf[562]=(byte)i; if(sha1_32(buf)==1295014773){break;} } + for(i=-90;i<-66;i++){ buf[563]=(byte)i; if(sha1_32(buf)==-940307543){break;} } + for(i=-6;i<5;i++){ buf[564]=(byte)i; if(sha1_32(buf)==-608290120){break;} } + for(i=42;i<69;i++){ buf[565]=(byte)i; if(sha1_32(buf)==-226393781){break;} } + for(i=60;i<70;i++){ buf[566]=(byte)i; if(sha1_32(buf)==1212651045){break;} } + for(i=-39;i<-22;i++){ buf[567]=(byte)i; if(sha1_32(buf)==-1980889466){break;} } + for(i=-121;i<-107;i++){ buf[568]=(byte)i; if(sha1_32(buf)==1649795123){break;} } + for(i=-53;i<-42;i++){ buf[569]=(byte)i; if(sha1_32(buf)==-668183297){break;} } + for(i=-113;i<-99;i++){ buf[570]=(byte)i; if(sha1_32(buf)==-1829134115){break;} } + for(i=-37;i<-30;i++){ buf[571]=(byte)i; if(sha1_32(buf)==-395308505){break;} } + for(i=117;i<124;i++){ buf[572]=(byte)i; if(sha1_32(buf)==1891225526){break;} } + for(i=-41;i<-13;i++){ buf[573]=(byte)i; if(sha1_32(buf)==1150922579){break;} } + for(i=-101;i<-80;i++){ buf[574]=(byte)i; if(sha1_32(buf)==-1289498605){break;} } + for(i=-20;i<-9;i++){ buf[575]=(byte)i; if(sha1_32(buf)==151661924){break;} } + for(i=-13;i<-6;i++){ buf[576]=(byte)i; if(sha1_32(buf)==995968938){break;} } + for(i=-105;i<-91;i++){ buf[577]=(byte)i; if(sha1_32(buf)==2025150891){break;} } + for(i=78;i<86;i++){ buf[578]=(byte)i; if(sha1_32(buf)==1127675594){break;} } + for(i=-77;i<-65;i++){ buf[579]=(byte)i; if(sha1_32(buf)==-1452855725){break;} } + for(i=120;i<128;i++){ buf[580]=(byte)i; if(sha1_32(buf)==-1177531315){break;} } + for(i=-55;i<-36;i++){ buf[581]=(byte)i; if(sha1_32(buf)==-1974723444){break;} } + for(i=-81;i<-61;i++){ buf[582]=(byte)i; if(sha1_32(buf)==-1418460157){break;} } + for(i=114;i<128;i++){ buf[583]=(byte)i; if(sha1_32(buf)==-595809126){break;} } + for(i=58;i<79;i++){ buf[584]=(byte)i; if(sha1_32(buf)==-2050484102){break;} } + for(i=-72;i<-51;i++){ buf[585]=(byte)i; if(sha1_32(buf)==-162737880){break;} } + for(i=14;i<23;i++){ buf[586]=(byte)i; if(sha1_32(buf)==906434587){break;} } + for(i=-68;i<-61;i++){ buf[587]=(byte)i; if(sha1_32(buf)==-1736950091){break;} } + for(i=108;i<124;i++){ buf[588]=(byte)i; if(sha1_32(buf)==1838923683){break;} } + for(i=84;i<103;i++){ buf[589]=(byte)i; if(sha1_32(buf)==-1325076045){break;} } + for(i=22;i<38;i++){ buf[590]=(byte)i; if(sha1_32(buf)==-2043417461){break;} } + for(i=-9;i<16;i++){ buf[591]=(byte)i; if(sha1_32(buf)==-2043417461){break;} } + for(i=-93;i<-78;i++){ buf[592]=(byte)i; if(sha1_32(buf)==-1191370538){break;} } + for(i=-78;i<-55;i++){ buf[593]=(byte)i; if(sha1_32(buf)==1508086351){break;} } + for(i=67;i<80;i++){ buf[594]=(byte)i; if(sha1_32(buf)==-41542873){break;} } + for(i=55;i<72;i++){ buf[595]=(byte)i; if(sha1_32(buf)==1341292614){break;} } + for(i=41;i<62;i++){ buf[596]=(byte)i; if(sha1_32(buf)==-1752988133){break;} } + for(i=103;i<120;i++){ buf[597]=(byte)i; if(sha1_32(buf)==270595236){break;} } + for(i=-68;i<-51;i++){ buf[598]=(byte)i; if(sha1_32(buf)==-262672057){break;} } + for(i=59;i<78;i++){ buf[599]=(byte)i; if(sha1_32(buf)==799549267){break;} } + for(i=106;i<128;i++){ buf[600]=(byte)i; if(sha1_32(buf)==852207141){break;} } + for(i=62;i<88;i++){ buf[601]=(byte)i; if(sha1_32(buf)==-2044100874){break;} } + for(i=-101;i<-85;i++){ buf[602]=(byte)i; if(sha1_32(buf)==-1226311413){break;} } + for(i=-38;i<-33;i++){ buf[603]=(byte)i; if(sha1_32(buf)==51643495){break;} } + for(i=-93;i<-68;i++){ buf[604]=(byte)i; if(sha1_32(buf)==-1580049198){break;} } + for(i=-94;i<-80;i++){ buf[605]=(byte)i; if(sha1_32(buf)==-1988312088){break;} } + for(i=56;i<66;i++){ buf[606]=(byte)i; if(sha1_32(buf)==178678728){break;} } + for(i=79;i<96;i++){ buf[607]=(byte)i; if(sha1_32(buf)==1579577994){break;} } + for(i=89;i<110;i++){ buf[608]=(byte)i; if(sha1_32(buf)==1006333265){break;} } + for(i=30;i<46;i++){ buf[609]=(byte)i; if(sha1_32(buf)==-459612890){break;} } + for(i=-18;i<-12;i++){ buf[610]=(byte)i; if(sha1_32(buf)==-57773091){break;} } + for(i=123;i<128;i++){ buf[611]=(byte)i; if(sha1_32(buf)==-1996317046){break;} } + for(i=-92;i<-78;i++){ buf[612]=(byte)i; if(sha1_32(buf)==54516584){break;} } + for(i=30;i<53;i++){ buf[613]=(byte)i; if(sha1_32(buf)==-1617064106){break;} } + for(i=-122;i<-99;i++){ buf[614]=(byte)i; if(sha1_32(buf)==1207830648){break;} } + for(i=-25;i<-15;i++){ buf[615]=(byte)i; if(sha1_32(buf)==-484139056){break;} } + for(i=-51;i<-31;i++){ buf[616]=(byte)i; if(sha1_32(buf)==2068744186){break;} } + for(i=37;i<51;i++){ buf[617]=(byte)i; if(sha1_32(buf)==1046413910){break;} } + for(i=98;i<124;i++){ buf[618]=(byte)i; if(sha1_32(buf)==-1722846813){break;} } + for(i=-1;i<18;i++){ buf[619]=(byte)i; if(sha1_32(buf)==-947513710){break;} } + for(i=-93;i<-74;i++){ buf[620]=(byte)i; if(sha1_32(buf)==960957071){break;} } + for(i=-67;i<-51;i++){ buf[621]=(byte)i; if(sha1_32(buf)==-1765385207){break;} } + for(i=-74;i<-56;i++){ buf[622]=(byte)i; if(sha1_32(buf)==-923815254){break;} } + for(i=-95;i<-92;i++){ buf[623]=(byte)i; if(sha1_32(buf)==1713837577){break;} } + for(i=-114;i<-95;i++){ buf[624]=(byte)i; if(sha1_32(buf)==-262063588){break;} } + for(i=-29;i<-13;i++){ buf[625]=(byte)i; if(sha1_32(buf)==1515876818){break;} } + for(i=-79;i<-63;i++){ buf[626]=(byte)i; if(sha1_32(buf)==-1966876680){break;} } + for(i=68;i<85;i++){ buf[627]=(byte)i; if(sha1_32(buf)==-1191224209){break;} } + for(i=26;i<43;i++){ buf[628]=(byte)i; if(sha1_32(buf)==-1395698145){break;} } + for(i=-9;i<1;i++){ buf[629]=(byte)i; if(sha1_32(buf)==649200137){break;} } + for(i=-79;i<-73;i++){ buf[630]=(byte)i; if(sha1_32(buf)==1387155612){break;} } + for(i=42;i<63;i++){ buf[631]=(byte)i; if(sha1_32(buf)==1570446125){break;} } + for(i=82;i<97;i++){ buf[632]=(byte)i; if(sha1_32(buf)==1744853453){break;} } + for(i=-103;i<-90;i++){ buf[633]=(byte)i; if(sha1_32(buf)==-1890752382){break;} } + for(i=-107;i<-87;i++){ buf[634]=(byte)i; if(sha1_32(buf)==622783297){break;} } + for(i=-52;i<-35;i++){ buf[635]=(byte)i; if(sha1_32(buf)==828050581){break;} } + for(i=79;i<99;i++){ buf[636]=(byte)i; if(sha1_32(buf)==1488981738){break;} } + for(i=-88;i<-79;i++){ buf[637]=(byte)i; if(sha1_32(buf)==-1858150360){break;} } + for(i=69;i<79;i++){ buf[638]=(byte)i; if(sha1_32(buf)==-1945392469){break;} } + for(i=-67;i<-55;i++){ buf[639]=(byte)i; if(sha1_32(buf)==1671229127){break;} } + for(i=28;i<45;i++){ buf[640]=(byte)i; if(sha1_32(buf)==-1014933907){break;} } + for(i=-58;i<-39;i++){ buf[641]=(byte)i; if(sha1_32(buf)==1372881456){break;} } + for(i=84;i<89;i++){ buf[642]=(byte)i; if(sha1_32(buf)==1053371928){break;} } + for(i=-99;i<-76;i++){ buf[643]=(byte)i; if(sha1_32(buf)==-577006868){break;} } + for(i=-50;i<-26;i++){ buf[644]=(byte)i; if(sha1_32(buf)==-433234050){break;} } + for(i=121;i<128;i++){ buf[645]=(byte)i; if(sha1_32(buf)==89846106){break;} } + for(i=49;i<51;i++){ buf[646]=(byte)i; if(sha1_32(buf)==-2066320762){break;} } + for(i=65;i<69;i++){ buf[647]=(byte)i; if(sha1_32(buf)==1057230177){break;} } + for(i=-102;i<-75;i++){ buf[648]=(byte)i; if(sha1_32(buf)==-1377425863){break;} } + for(i=59;i<67;i++){ buf[649]=(byte)i; if(sha1_32(buf)==570665573){break;} } + for(i=-31;i<-14;i++){ buf[650]=(byte)i; if(sha1_32(buf)==1067699666){break;} } + for(i=-91;i<-64;i++){ buf[651]=(byte)i; if(sha1_32(buf)==-916882436){break;} } + for(i=11;i<24;i++){ buf[652]=(byte)i; if(sha1_32(buf)==2042806545){break;} } + for(i=90;i<117;i++){ buf[653]=(byte)i; if(sha1_32(buf)==908851881){break;} } + for(i=-93;i<-66;i++){ buf[654]=(byte)i; if(sha1_32(buf)==-207310256){break;} } + for(i=105;i<128;i++){ buf[655]=(byte)i; if(sha1_32(buf)==1828902765){break;} } + for(i=-128;i<-119;i++){ buf[656]=(byte)i; if(sha1_32(buf)==30956198){break;} } + for(i=-69;i<-59;i++){ buf[657]=(byte)i; if(sha1_32(buf)==-902634309){break;} } + for(i=-112;i<-110;i++){ buf[658]=(byte)i; if(sha1_32(buf)==1719326906){break;} } + for(i=-52;i<-34;i++){ buf[659]=(byte)i; if(sha1_32(buf)==1367537128){break;} } + for(i=13;i<35;i++){ buf[660]=(byte)i; if(sha1_32(buf)==449402226){break;} } + for(i=-38;i<-16;i++){ buf[661]=(byte)i; if(sha1_32(buf)==171459991){break;} } + for(i=73;i<83;i++){ buf[662]=(byte)i; if(sha1_32(buf)==-1019826484){break;} } + for(i=46;i<75;i++){ buf[663]=(byte)i; if(sha1_32(buf)==-871913117){break;} } + for(i=26;i<39;i++){ buf[664]=(byte)i; if(sha1_32(buf)==1669352892){break;} } + for(i=98;i<116;i++){ buf[665]=(byte)i; if(sha1_32(buf)==741551986){break;} } + for(i=104;i<112;i++){ buf[666]=(byte)i; if(sha1_32(buf)==152788533){break;} } + for(i=-88;i<-83;i++){ buf[667]=(byte)i; if(sha1_32(buf)==-1165372910){break;} } + for(i=47;i<55;i++){ buf[668]=(byte)i; if(sha1_32(buf)==-614878886){break;} } + for(i=94;i<109;i++){ buf[669]=(byte)i; if(sha1_32(buf)==93320575){break;} } + for(i=-104;i<-87;i++){ buf[670]=(byte)i; if(sha1_32(buf)==505453804){break;} } + for(i=-93;i<-76;i++){ buf[671]=(byte)i; if(sha1_32(buf)==-362417380){break;} } + for(i=-30;i<-4;i++){ buf[672]=(byte)i; if(sha1_32(buf)==-1046029673){break;} } + for(i=-55;i<-37;i++){ buf[673]=(byte)i; if(sha1_32(buf)==721648088){break;} } + for(i=-22;i<-17;i++){ buf[674]=(byte)i; if(sha1_32(buf)==595203198){break;} } + for(i=14;i<25;i++){ buf[675]=(byte)i; if(sha1_32(buf)==240685342){break;} } + for(i=25;i<31;i++){ buf[676]=(byte)i; if(sha1_32(buf)==1496755219){break;} } + for(i=-120;i<-96;i++){ buf[677]=(byte)i; if(sha1_32(buf)==-1739155155){break;} } + for(i=-48;i<-36;i++){ buf[678]=(byte)i; if(sha1_32(buf)==-816329296){break;} } + for(i=-55;i<-46;i++){ buf[679]=(byte)i; if(sha1_32(buf)==-1571402407){break;} } + for(i=87;i<96;i++){ buf[680]=(byte)i; if(sha1_32(buf)==-1728895964){break;} } + for(i=-117;i<-103;i++){ buf[681]=(byte)i; if(sha1_32(buf)==-1836957716){break;} } + for(i=-2;i<13;i++){ buf[682]=(byte)i; if(sha1_32(buf)==969049136){break;} } + for(i=38;i<52;i++){ buf[683]=(byte)i; if(sha1_32(buf)==-1719771880){break;} } + for(i=-59;i<-53;i++){ buf[684]=(byte)i; if(sha1_32(buf)==541033024){break;} } + for(i=82;i<99;i++){ buf[685]=(byte)i; if(sha1_32(buf)==-476047248){break;} } + for(i=113;i<123;i++){ buf[686]=(byte)i; if(sha1_32(buf)==-1951363620){break;} } + for(i=-81;i<-74;i++){ buf[687]=(byte)i; if(sha1_32(buf)==-769691078){break;} } + for(i=-2;i<11;i++){ buf[688]=(byte)i; if(sha1_32(buf)==-551158611){break;} } + for(i=-39;i<-22;i++){ buf[689]=(byte)i; if(sha1_32(buf)==-328422012){break;} } + for(i=-47;i<-41;i++){ buf[690]=(byte)i; if(sha1_32(buf)==889845553){break;} } + for(i=-69;i<-62;i++){ buf[691]=(byte)i; if(sha1_32(buf)==2139051921){break;} } + for(i=11;i<27;i++){ buf[692]=(byte)i; if(sha1_32(buf)==1806821192){break;} } + for(i=-42;i<-27;i++){ buf[693]=(byte)i; if(sha1_32(buf)==337075310){break;} } + for(i=-107;i<-81;i++){ buf[694]=(byte)i; if(sha1_32(buf)==226733550){break;} } + for(i=-113;i<-108;i++){ buf[695]=(byte)i; if(sha1_32(buf)==-1990212717){break;} } + for(i=85;i<107;i++){ buf[696]=(byte)i; if(sha1_32(buf)==-1810328381){break;} } + for(i=112;i<117;i++){ buf[697]=(byte)i; if(sha1_32(buf)==1647160761){break;} } + for(i=44;i<65;i++){ buf[698]=(byte)i; if(sha1_32(buf)==1589212639){break;} } + for(i=-61;i<-54;i++){ buf[699]=(byte)i; if(sha1_32(buf)==2087918322){break;} } + for(i=-14;i<-5;i++){ buf[700]=(byte)i; if(sha1_32(buf)==1513533111){break;} } + for(i=86;i<91;i++){ buf[701]=(byte)i; if(sha1_32(buf)==454012298){break;} } + for(i=-110;i<-95;i++){ buf[702]=(byte)i; if(sha1_32(buf)==1047429821){break;} } + for(i=-58;i<-42;i++){ buf[703]=(byte)i; if(sha1_32(buf)==-1322772056){break;} } + for(i=-124;i<-108;i++){ buf[704]=(byte)i; if(sha1_32(buf)==609002583){break;} } + for(i=-61;i<-45;i++){ buf[705]=(byte)i; if(sha1_32(buf)==-192132710){break;} } + for(i=84;i<105;i++){ buf[706]=(byte)i; if(sha1_32(buf)==-353004533){break;} } + for(i=-11;i<3;i++){ buf[707]=(byte)i; if(sha1_32(buf)==-682206379){break;} } + for(i=-28;i<-4;i++){ buf[708]=(byte)i; if(sha1_32(buf)==1739650568){break;} } + for(i=-56;i<-37;i++){ buf[709]=(byte)i; if(sha1_32(buf)==-1887075561){break;} } + for(i=-63;i<-53;i++){ buf[710]=(byte)i; if(sha1_32(buf)==-1987706557){break;} } + for(i=-59;i<-41;i++){ buf[711]=(byte)i; if(sha1_32(buf)==1145160466){break;} } + for(i=-34;i<-25;i++){ buf[712]=(byte)i; if(sha1_32(buf)==-1917563737){break;} } + for(i=-69;i<-47;i++){ buf[713]=(byte)i; if(sha1_32(buf)==-830983507){break;} } + for(i=-118;i<-93;i++){ buf[714]=(byte)i; if(sha1_32(buf)==611377946){break;} } + for(i=116;i<128;i++){ buf[715]=(byte)i; if(sha1_32(buf)==-100929146){break;} } + for(i=-48;i<-28;i++){ buf[716]=(byte)i; if(sha1_32(buf)==1998472813){break;} } + for(i=-70;i<-60;i++){ buf[717]=(byte)i; if(sha1_32(buf)==-1999506602){break;} } + for(i=-40;i<-32;i++){ buf[718]=(byte)i; if(sha1_32(buf)==-2062558004){break;} } + for(i=44;i<66;i++){ buf[719]=(byte)i; if(sha1_32(buf)==-1437504374){break;} } + for(i=7;i<21;i++){ buf[720]=(byte)i; if(sha1_32(buf)==69093141){break;} } + for(i=88;i<98;i++){ buf[721]=(byte)i; if(sha1_32(buf)==1715447445){break;} } + for(i=-8;i<10;i++){ buf[722]=(byte)i; if(sha1_32(buf)==1715447445){break;} } + for(i=-113;i<-93;i++){ buf[723]=(byte)i; if(sha1_32(buf)==-744637815){break;} } + for(i=48;i<64;i++){ buf[724]=(byte)i; if(sha1_32(buf)==-10703579){break;} } + for(i=91;i<113;i++){ buf[725]=(byte)i; if(sha1_32(buf)==1007919336){break;} } + for(i=-84;i<-61;i++){ buf[726]=(byte)i; if(sha1_32(buf)==-842724439){break;} } + for(i=-83;i<-69;i++){ buf[727]=(byte)i; if(sha1_32(buf)==67430318){break;} } + for(i=-2;i<18;i++){ buf[728]=(byte)i; if(sha1_32(buf)==-869830687){break;} } + for(i=-111;i<-91;i++){ buf[729]=(byte)i; if(sha1_32(buf)==-2097491929){break;} } + for(i=0;i<17;i++){ buf[730]=(byte)i; if(sha1_32(buf)==-377242918){break;} } + for(i=-57;i<-42;i++){ buf[731]=(byte)i; if(sha1_32(buf)==341732908){break;} } + for(i=18;i<35;i++){ buf[732]=(byte)i; if(sha1_32(buf)==-1999159237){break;} } + for(i=111;i<125;i++){ buf[733]=(byte)i; if(sha1_32(buf)==-765707552){break;} } + for(i=-1;i<17;i++){ buf[734]=(byte)i; if(sha1_32(buf)==-1537423752){break;} } + for(i=-127;i<-122;i++){ buf[735]=(byte)i; if(sha1_32(buf)==-566196193){break;} } + for(i=-29;i<-9;i++){ buf[736]=(byte)i; if(sha1_32(buf)==597187632){break;} } + for(i=-116;i<-101;i++){ buf[737]=(byte)i; if(sha1_32(buf)==-537078429){break;} } + for(i=-29;i<-12;i++){ buf[738]=(byte)i; if(sha1_32(buf)==1640983571){break;} } + for(i=97;i<105;i++){ buf[739]=(byte)i; if(sha1_32(buf)==-2018360703){break;} } + for(i=-27;i<-6;i++){ buf[740]=(byte)i; if(sha1_32(buf)==-138807690){break;} } + for(i=32;i<50;i++){ buf[741]=(byte)i; if(sha1_32(buf)==757431772){break;} } + for(i=-4;i<16;i++){ buf[742]=(byte)i; if(sha1_32(buf)==-1171597137){break;} } + for(i=-107;i<-80;i++){ buf[743]=(byte)i; if(sha1_32(buf)==1464155363){break;} } + for(i=53;i<78;i++){ buf[744]=(byte)i; if(sha1_32(buf)==-845879662){break;} } + for(i=115;i<122;i++){ buf[745]=(byte)i; if(sha1_32(buf)==1382938010){break;} } + for(i=53;i<67;i++){ buf[746]=(byte)i; if(sha1_32(buf)==-37392070){break;} } + for(i=43;i<65;i++){ buf[747]=(byte)i; if(sha1_32(buf)==577566107){break;} } + for(i=-89;i<-74;i++){ buf[748]=(byte)i; if(sha1_32(buf)==1768021172){break;} } + for(i=-1;i<14;i++){ buf[749]=(byte)i; if(sha1_32(buf)==-1089583346){break;} } + for(i=-123;i<-102;i++){ buf[750]=(byte)i; if(sha1_32(buf)==1466994441){break;} } + for(i=98;i<114;i++){ buf[751]=(byte)i; if(sha1_32(buf)==980284703){break;} } + for(i=-76;i<-60;i++){ buf[752]=(byte)i; if(sha1_32(buf)==-1090087637){break;} } + for(i=-108;i<-96;i++){ buf[753]=(byte)i; if(sha1_32(buf)==75673914){break;} } + for(i=-44;i<-31;i++){ buf[754]=(byte)i; if(sha1_32(buf)==2066954313){break;} } + for(i=54;i<57;i++){ buf[755]=(byte)i; if(sha1_32(buf)==-660784448){break;} } + for(i=-119;i<-93;i++){ buf[756]=(byte)i; if(sha1_32(buf)==1258721527){break;} } + for(i=25;i<50;i++){ buf[757]=(byte)i; if(sha1_32(buf)==-949686713){break;} } + for(i=91;i<103;i++){ buf[758]=(byte)i; if(sha1_32(buf)==-1876393076){break;} } + for(i=2;i<28;i++){ buf[759]=(byte)i; if(sha1_32(buf)==1883511282){break;} } + for(i=-6;i<22;i++){ buf[760]=(byte)i; if(sha1_32(buf)==-25852589){break;} } + for(i=-128;i<-123;i++){ buf[761]=(byte)i; if(sha1_32(buf)==896610725){break;} } + for(i=-17;i<0;i++){ buf[762]=(byte)i; if(sha1_32(buf)==-1469514116){break;} } + for(i=-79;i<-60;i++){ buf[763]=(byte)i; if(sha1_32(buf)==1817404646){break;} } + for(i=-54;i<-42;i++){ buf[764]=(byte)i; if(sha1_32(buf)==1854896924){break;} } + for(i=-98;i<-72;i++){ buf[765]=(byte)i; if(sha1_32(buf)==2095565205){break;} } + for(i=96;i<106;i++){ buf[766]=(byte)i; if(sha1_32(buf)==133959406){break;} } + for(i=68;i<90;i++){ buf[767]=(byte)i; if(sha1_32(buf)==-524527593){break;} } + for(i=-127;i<-110;i++){ buf[768]=(byte)i; if(sha1_32(buf)==-2102010037){break;} } + for(i=80;i<90;i++){ buf[769]=(byte)i; if(sha1_32(buf)==-1585912232){break;} } + for(i=99;i<124;i++){ buf[770]=(byte)i; if(sha1_32(buf)==-113852134){break;} } + for(i=65;i<77;i++){ buf[771]=(byte)i; if(sha1_32(buf)==165021182){break;} } + for(i=-24;i<-9;i++){ buf[772]=(byte)i; if(sha1_32(buf)==1185063661){break;} } + for(i=43;i<54;i++){ buf[773]=(byte)i; if(sha1_32(buf)==542063601){break;} } + for(i=17;i<22;i++){ buf[774]=(byte)i; if(sha1_32(buf)==-61114818){break;} } + for(i=86;i<101;i++){ buf[775]=(byte)i; if(sha1_32(buf)==395416014){break;} } + for(i=113;i<128;i++){ buf[776]=(byte)i; if(sha1_32(buf)==2094255887){break;} } + for(i=-108;i<-86;i++){ buf[777]=(byte)i; if(sha1_32(buf)==1586242558){break;} } + for(i=59;i<78;i++){ buf[778]=(byte)i; if(sha1_32(buf)==1644994060){break;} } + for(i=42;i<57;i++){ buf[779]=(byte)i; if(sha1_32(buf)==1158017383){break;} } + for(i=34;i<59;i++){ buf[780]=(byte)i; if(sha1_32(buf)==1647976507){break;} } + for(i=41;i<49;i++){ buf[781]=(byte)i; if(sha1_32(buf)==-1800240491){break;} } + for(i=78;i<91;i++){ buf[782]=(byte)i; if(sha1_32(buf)==751422193){break;} } + for(i=-77;i<-72;i++){ buf[783]=(byte)i; if(sha1_32(buf)==1636024626){break;} } + for(i=-114;i<-97;i++){ buf[784]=(byte)i; if(sha1_32(buf)==-610726987){break;} } + for(i=-7;i<8;i++){ buf[785]=(byte)i; if(sha1_32(buf)==-519365171){break;} } + for(i=42;i<60;i++){ buf[786]=(byte)i; if(sha1_32(buf)==-867561653){break;} } + for(i=-41;i<-26;i++){ buf[787]=(byte)i; if(sha1_32(buf)==585047951){break;} } + for(i=-93;i<-83;i++){ buf[788]=(byte)i; if(sha1_32(buf)==267169594){break;} } + for(i=105;i<128;i++){ buf[789]=(byte)i; if(sha1_32(buf)==1738821431){break;} } + for(i=-128;i<-108;i++){ buf[790]=(byte)i; if(sha1_32(buf)==-1693539687){break;} } + for(i=-45;i<-41;i++){ buf[791]=(byte)i; if(sha1_32(buf)==-902228403){break;} } + for(i=5;i<30;i++){ buf[792]=(byte)i; if(sha1_32(buf)==-41813566){break;} } + for(i=-14;i<2;i++){ buf[793]=(byte)i; if(sha1_32(buf)==1845271809){break;} } + for(i=-64;i<-58;i++){ buf[794]=(byte)i; if(sha1_32(buf)==638787502){break;} } + for(i=-71;i<-59;i++){ buf[795]=(byte)i; if(sha1_32(buf)==-1123669508){break;} } + for(i=-74;i<-62;i++){ buf[796]=(byte)i; if(sha1_32(buf)==-567143598){break;} } + for(i=-23;i<2;i++){ buf[797]=(byte)i; if(sha1_32(buf)==-889989332){break;} } + for(i=110;i<122;i++){ buf[798]=(byte)i; if(sha1_32(buf)==-162337473){break;} } + for(i=1;i<28;i++){ buf[799]=(byte)i; if(sha1_32(buf)==-1982333401){break;} } + for(i=-78;i<-65;i++){ buf[800]=(byte)i; if(sha1_32(buf)==462169358){break;} } + for(i=93;i<94;i++){ buf[801]=(byte)i; if(sha1_32(buf)==-685466243){break;} } + for(i=-48;i<-30;i++){ buf[802]=(byte)i; if(sha1_32(buf)==1804125925){break;} } + for(i=-121;i<-113;i++){ buf[803]=(byte)i; if(sha1_32(buf)==-82172140){break;} } + for(i=84;i<98;i++){ buf[804]=(byte)i; if(sha1_32(buf)==1052341966){break;} } + for(i=-16;i<1;i++){ buf[805]=(byte)i; if(sha1_32(buf)==-1686606408){break;} } + for(i=-113;i<-101;i++){ buf[806]=(byte)i; if(sha1_32(buf)==-1914891881){break;} } + for(i=45;i<71;i++){ buf[807]=(byte)i; if(sha1_32(buf)==-865747878){break;} } + for(i=-93;i<-85;i++){ buf[808]=(byte)i; if(sha1_32(buf)==428614481){break;} } + for(i=103;i<128;i++){ buf[809]=(byte)i; if(sha1_32(buf)==-1206258725){break;} } + for(i=2;i<17;i++){ buf[810]=(byte)i; if(sha1_32(buf)==-1713833313){break;} } + for(i=-68;i<-52;i++){ buf[811]=(byte)i; if(sha1_32(buf)==1434677899){break;} } + for(i=-1;i<21;i++){ buf[812]=(byte)i; if(sha1_32(buf)==1161810759){break;} } + for(i=-70;i<-63;i++){ buf[813]=(byte)i; if(sha1_32(buf)==-1540696839){break;} } + for(i=-97;i<-95;i++){ buf[814]=(byte)i; if(sha1_32(buf)==207983115){break;} } + for(i=0;i<17;i++){ buf[815]=(byte)i; if(sha1_32(buf)==-2055237251){break;} } + for(i=125;i<127;i++){ buf[816]=(byte)i; if(sha1_32(buf)==-963941860){break;} } + for(i=-54;i<-30;i++){ buf[817]=(byte)i; if(sha1_32(buf)==-270749236){break;} } + for(i=-100;i<-77;i++){ buf[818]=(byte)i; if(sha1_32(buf)==-1091830460){break;} } + for(i=28;i<49;i++){ buf[819]=(byte)i; if(sha1_32(buf)==-333903443){break;} } + for(i=-72;i<-52;i++){ buf[820]=(byte)i; if(sha1_32(buf)==-1330406511){break;} } + for(i=6;i<28;i++){ buf[821]=(byte)i; if(sha1_32(buf)==1971072200){break;} } + for(i=29;i<33;i++){ buf[822]=(byte)i; if(sha1_32(buf)==-841256028){break;} } + for(i=89;i<97;i++){ buf[823]=(byte)i; if(sha1_32(buf)==2100583283){break;} } + for(i=-75;i<-63;i++){ buf[824]=(byte)i; if(sha1_32(buf)==-307565791){break;} } + for(i=-94;i<-74;i++){ buf[825]=(byte)i; if(sha1_32(buf)==-1552341751){break;} } + for(i=102;i<113;i++){ buf[826]=(byte)i; if(sha1_32(buf)==-735312381){break;} } + for(i=-71;i<-56;i++){ buf[827]=(byte)i; if(sha1_32(buf)==-1528312675){break;} } + for(i=81;i<92;i++){ buf[828]=(byte)i; if(sha1_32(buf)==-1903345054){break;} } + for(i=52;i<63;i++){ buf[829]=(byte)i; if(sha1_32(buf)==1693254285){break;} } + for(i=-90;i<-76;i++){ buf[830]=(byte)i; if(sha1_32(buf)==418558915){break;} } + for(i=-2;i<22;i++){ buf[831]=(byte)i; if(sha1_32(buf)==892650728){break;} } + for(i=10;i<29;i++){ buf[832]=(byte)i; if(sha1_32(buf)==-1352026041){break;} } + for(i=18;i<38;i++){ buf[833]=(byte)i; if(sha1_32(buf)==602054511){break;} } + for(i=-17;i<-6;i++){ buf[834]=(byte)i; if(sha1_32(buf)==-652737712){break;} } + for(i=-110;i<-97;i++){ buf[835]=(byte)i; if(sha1_32(buf)==-255728508){break;} } + for(i=82;i<88;i++){ buf[836]=(byte)i; if(sha1_32(buf)==839993150){break;} } + for(i=-78;i<-72;i++){ buf[837]=(byte)i; if(sha1_32(buf)==-129302860){break;} } + for(i=-91;i<-77;i++){ buf[838]=(byte)i; if(sha1_32(buf)==1067379676){break;} } + for(i=-87;i<-75;i++){ buf[839]=(byte)i; if(sha1_32(buf)==1770315905){break;} } + for(i=-48;i<-35;i++){ buf[840]=(byte)i; if(sha1_32(buf)==-2035378410){break;} } + for(i=53;i<66;i++){ buf[841]=(byte)i; if(sha1_32(buf)==-1483708569){break;} } + for(i=-45;i<-21;i++){ buf[842]=(byte)i; if(sha1_32(buf)==1586520443){break;} } + for(i=68;i<78;i++){ buf[843]=(byte)i; if(sha1_32(buf)==1669500039){break;} } + for(i=97;i<113;i++){ buf[844]=(byte)i; if(sha1_32(buf)==1602773918){break;} } + for(i=23;i<32;i++){ buf[845]=(byte)i; if(sha1_32(buf)==401760213){break;} } + for(i=96;i<110;i++){ buf[846]=(byte)i; if(sha1_32(buf)==-1273186339){break;} } + for(i=-16;i<9;i++){ buf[847]=(byte)i; if(sha1_32(buf)==-403034651){break;} } + for(i=-75;i<-61;i++){ buf[848]=(byte)i; if(sha1_32(buf)==-27341535){break;} } + for(i=16;i<36;i++){ buf[849]=(byte)i; if(sha1_32(buf)==-1458465891){break;} } + for(i=117;i<126;i++){ buf[850]=(byte)i; if(sha1_32(buf)==1386340566){break;} } + for(i=101;i<117;i++){ buf[851]=(byte)i; if(sha1_32(buf)==-709154867){break;} } + for(i=70;i<81;i++){ buf[852]=(byte)i; if(sha1_32(buf)==1318812156){break;} } + for(i=35;i<56;i++){ buf[853]=(byte)i; if(sha1_32(buf)==-1667457443){break;} } + for(i=-126;i<-117;i++){ buf[854]=(byte)i; if(sha1_32(buf)==1786470338){break;} } + for(i=-71;i<-62;i++){ buf[855]=(byte)i; if(sha1_32(buf)==-348197784){break;} } + for(i=-56;i<-42;i++){ buf[856]=(byte)i; if(sha1_32(buf)==-392859654){break;} } + for(i=66;i<84;i++){ buf[857]=(byte)i; if(sha1_32(buf)==-1552540387){break;} } + for(i=-7;i<7;i++){ buf[858]=(byte)i; if(sha1_32(buf)==-1027035735){break;} } + for(i=39;i<46;i++){ buf[859]=(byte)i; if(sha1_32(buf)==1117339936){break;} } + for(i=-13;i<1;i++){ buf[860]=(byte)i; if(sha1_32(buf)==1117339936){break;} } + for(i=-4;i<7;i++){ buf[861]=(byte)i; if(sha1_32(buf)==-1766186839){break;} } + for(i=-77;i<-66;i++){ buf[862]=(byte)i; if(sha1_32(buf)==622449929){break;} } + for(i=-92;i<-70;i++){ buf[863]=(byte)i; if(sha1_32(buf)==-561339063){break;} } + for(i=-64;i<-52;i++){ buf[864]=(byte)i; if(sha1_32(buf)==2064457750){break;} } + for(i=110;i<127;i++){ buf[865]=(byte)i; if(sha1_32(buf)==-104679845){break;} } + for(i=76;i<97;i++){ buf[866]=(byte)i; if(sha1_32(buf)==-1821335791){break;} } + for(i=-76;i<-55;i++){ buf[867]=(byte)i; if(sha1_32(buf)==-798071534){break;} } + for(i=9;i<34;i++){ buf[868]=(byte)i; if(sha1_32(buf)==-66464778){break;} } + for(i=9;i<30;i++){ buf[869]=(byte)i; if(sha1_32(buf)==2030132946){break;} } + for(i=42;i<70;i++){ buf[870]=(byte)i; if(sha1_32(buf)==570644358){break;} } + for(i=-128;i<-123;i++){ buf[871]=(byte)i; if(sha1_32(buf)==2137278266){break;} } + for(i=-5;i<10;i++){ buf[872]=(byte)i; if(sha1_32(buf)==865726083){break;} } + for(i=-111;i<-95;i++){ buf[873]=(byte)i; if(sha1_32(buf)==29549824){break;} } + for(i=44;i<47;i++){ buf[874]=(byte)i; if(sha1_32(buf)==-3838194){break;} } + for(i=93;i<96;i++){ buf[875]=(byte)i; if(sha1_32(buf)==1749705662){break;} } + for(i=-75;i<-57;i++){ buf[876]=(byte)i; if(sha1_32(buf)==1902400663){break;} } + for(i=-80;i<-74;i++){ buf[877]=(byte)i; if(sha1_32(buf)==-1293240671){break;} } + for(i=1;i<25;i++){ buf[878]=(byte)i; if(sha1_32(buf)==976397329){break;} } + for(i=84;i<100;i++){ buf[879]=(byte)i; if(sha1_32(buf)==-587412251){break;} } + for(i=-85;i<-79;i++){ buf[880]=(byte)i; if(sha1_32(buf)==423859293){break;} } + for(i=99;i<118;i++){ buf[881]=(byte)i; if(sha1_32(buf)==1598825202){break;} } + for(i=86;i<96;i++){ buf[882]=(byte)i; if(sha1_32(buf)==-422482673){break;} } + for(i=78;i<86;i++){ buf[883]=(byte)i; if(sha1_32(buf)==-1758414551){break;} } + for(i=75;i<95;i++){ buf[884]=(byte)i; if(sha1_32(buf)==16934576){break;} } + for(i=27;i<36;i++){ buf[885]=(byte)i; if(sha1_32(buf)==1280778899){break;} } + for(i=14;i<29;i++){ buf[886]=(byte)i; if(sha1_32(buf)==-775687360){break;} } + for(i=97;i<117;i++){ buf[887]=(byte)i; if(sha1_32(buf)==-10868877){break;} } + for(i=-4;i<16;i++){ buf[888]=(byte)i; if(sha1_32(buf)==-10868877){break;} } + for(i=46;i<62;i++){ buf[889]=(byte)i; if(sha1_32(buf)==677175607){break;} } + for(i=-11;i<-7;i++){ buf[890]=(byte)i; if(sha1_32(buf)==-1916553541){break;} } + for(i=-128;i<-114;i++){ buf[891]=(byte)i; if(sha1_32(buf)==-894290563){break;} } + for(i=-28;i<1;i++){ buf[892]=(byte)i; if(sha1_32(buf)==-716648695){break;} } + for(i=-65;i<-58;i++){ buf[893]=(byte)i; if(sha1_32(buf)==-1511622391){break;} } + for(i=-128;i<-121;i++){ buf[894]=(byte)i; if(sha1_32(buf)==-355232066){break;} } + for(i=-58;i<-35;i++){ buf[895]=(byte)i; if(sha1_32(buf)==-1480545957){break;} } + for(i=-11;i<4;i++){ buf[896]=(byte)i; if(sha1_32(buf)==44257716){break;} } + for(i=7;i<12;i++){ buf[897]=(byte)i; if(sha1_32(buf)==1344265495){break;} } + for(i=114;i<128;i++){ buf[898]=(byte)i; if(sha1_32(buf)==177943959){break;} } + for(i=110;i<128;i++){ buf[899]=(byte)i; if(sha1_32(buf)==1047084741){break;} } + for(i=28;i<53;i++){ buf[900]=(byte)i; if(sha1_32(buf)==883887904){break;} } + for(i=-62;i<-41;i++){ buf[901]=(byte)i; if(sha1_32(buf)==-1442904045){break;} } + for(i=-126;i<-110;i++){ buf[902]=(byte)i; if(sha1_32(buf)==-2092933049){break;} } + for(i=-26;i<-19;i++){ buf[903]=(byte)i; if(sha1_32(buf)==-510482468){break;} } + for(i=-82;i<-73;i++){ buf[904]=(byte)i; if(sha1_32(buf)==-668453573){break;} } + for(i=42;i<65;i++){ buf[905]=(byte)i; if(sha1_32(buf)==1857954310){break;} } + for(i=-42;i<-25;i++){ buf[906]=(byte)i; if(sha1_32(buf)==1907832141){break;} } + for(i=-81;i<-52;i++){ buf[907]=(byte)i; if(sha1_32(buf)==-1753105372){break;} } + for(i=-3;i<16;i++){ buf[908]=(byte)i; if(sha1_32(buf)==-965477713){break;} } + for(i=64;i<85;i++){ buf[909]=(byte)i; if(sha1_32(buf)==-163342230){break;} } + for(i=112;i<128;i++){ buf[910]=(byte)i; if(sha1_32(buf)==1036256089){break;} } + for(i=88;i<107;i++){ buf[911]=(byte)i; if(sha1_32(buf)==2053132359){break;} } + for(i=-57;i<-29;i++){ buf[912]=(byte)i; if(sha1_32(buf)==-1974612880){break;} } + for(i=78;i<102;i++){ buf[913]=(byte)i; if(sha1_32(buf)==-986051065){break;} } + for(i=-8;i<0;i++){ buf[914]=(byte)i; if(sha1_32(buf)==898942523){break;} } + for(i=121;i<128;i++){ buf[915]=(byte)i; if(sha1_32(buf)==1210960058){break;} } + for(i=111;i<128;i++){ buf[916]=(byte)i; if(sha1_32(buf)==-1158947702){break;} } + for(i=26;i<45;i++){ buf[917]=(byte)i; if(sha1_32(buf)==-821628464){break;} } + for(i=69;i<80;i++){ buf[918]=(byte)i; if(sha1_32(buf)==1540568198){break;} } + for(i=2;i<5;i++){ buf[919]=(byte)i; if(sha1_32(buf)==-296279185){break;} } + for(i=-122;i<-99;i++){ buf[920]=(byte)i; if(sha1_32(buf)==1337175685){break;} } + for(i=5;i<27;i++){ buf[921]=(byte)i; if(sha1_32(buf)==-2144800837){break;} } + for(i=63;i<78;i++){ buf[922]=(byte)i; if(sha1_32(buf)==415363442){break;} } + for(i=-79;i<-69;i++){ buf[923]=(byte)i; if(sha1_32(buf)==-1781703638){break;} } + for(i=-118;i<-116;i++){ buf[924]=(byte)i; if(sha1_32(buf)==-1571473907){break;} } + for(i=30;i<50;i++){ buf[925]=(byte)i; if(sha1_32(buf)==1917938139){break;} } + for(i=-2;i<14;i++){ buf[926]=(byte)i; if(sha1_32(buf)==-975403474){break;} } + for(i=-82;i<-73;i++){ buf[927]=(byte)i; if(sha1_32(buf)==2121550735){break;} } + for(i=106;i<123;i++){ buf[928]=(byte)i; if(sha1_32(buf)==-1602277109){break;} } + for(i=-101;i<-82;i++){ buf[929]=(byte)i; if(sha1_32(buf)==-1516708668){break;} } + for(i=101;i<112;i++){ buf[930]=(byte)i; if(sha1_32(buf)==1622192437){break;} } + for(i=41;i<53;i++){ buf[931]=(byte)i; if(sha1_32(buf)==-686978238){break;} } + for(i=25;i<45;i++){ buf[932]=(byte)i; if(sha1_32(buf)==166884904){break;} } + for(i=-116;i<-92;i++){ buf[933]=(byte)i; if(sha1_32(buf)==-97223331){break;} } + for(i=116;i<128;i++){ buf[934]=(byte)i; if(sha1_32(buf)==1263643143){break;} } + for(i=-27;i<-7;i++){ buf[935]=(byte)i; if(sha1_32(buf)==1436612733){break;} } + for(i=-19;i<9;i++){ buf[936]=(byte)i; if(sha1_32(buf)==1335962688){break;} } + for(i=-93;i<-78;i++){ buf[937]=(byte)i; if(sha1_32(buf)==754589298){break;} } + for(i=33;i<42;i++){ buf[938]=(byte)i; if(sha1_32(buf)==-1450477894){break;} } + for(i=99;i<114;i++){ buf[939]=(byte)i; if(sha1_32(buf)==-1577794591){break;} } + for(i=-123;i<-114;i++){ buf[940]=(byte)i; if(sha1_32(buf)==-248050048){break;} } + for(i=-64;i<-42;i++){ buf[941]=(byte)i; if(sha1_32(buf)==1968183316){break;} } + for(i=36;i<45;i++){ buf[942]=(byte)i; if(sha1_32(buf)==-650365666){break;} } + for(i=108;i<128;i++){ buf[943]=(byte)i; if(sha1_32(buf)==-1698723717){break;} } + for(i=-31;i<-21;i++){ buf[944]=(byte)i; if(sha1_32(buf)==-1507659087){break;} } + for(i=22;i<40;i++){ buf[945]=(byte)i; if(sha1_32(buf)==-1552804680){break;} } + for(i=-72;i<-47;i++){ buf[946]=(byte)i; if(sha1_32(buf)==697619244){break;} } + for(i=-38;i<-22;i++){ buf[947]=(byte)i; if(sha1_32(buf)==1144754024){break;} } + for(i=-55;i<-38;i++){ buf[948]=(byte)i; if(sha1_32(buf)==1611176787){break;} } + for(i=-59;i<-34;i++){ buf[949]=(byte)i; if(sha1_32(buf)==-957661096){break;} } + for(i=75;i<92;i++){ buf[950]=(byte)i; if(sha1_32(buf)==992333398){break;} } + for(i=38;i<45;i++){ buf[951]=(byte)i; if(sha1_32(buf)==-1343154612){break;} } + for(i=24;i<29;i++){ buf[952]=(byte)i; if(sha1_32(buf)==-1023071938){break;} } + for(i=-91;i<-74;i++){ buf[953]=(byte)i; if(sha1_32(buf)==-1142385161){break;} } + for(i=25;i<51;i++){ buf[954]=(byte)i; if(sha1_32(buf)==-1259893995){break;} } + for(i=-111;i<-85;i++){ buf[955]=(byte)i; if(sha1_32(buf)==-265732050){break;} } + for(i=-6;i<5;i++){ buf[956]=(byte)i; if(sha1_32(buf)==52640541){break;} } + for(i=75;i<82;i++){ buf[957]=(byte)i; if(sha1_32(buf)==-1592044720){break;} } + for(i=37;i<52;i++){ buf[958]=(byte)i; if(sha1_32(buf)==253203775){break;} } + for(i=55;i<67;i++){ buf[959]=(byte)i; if(sha1_32(buf)==-1186737008){break;} } + for(i=-106;i<-81;i++){ buf[960]=(byte)i; if(sha1_32(buf)==-1878577613){break;} } + for(i=-33;i<-3;i++){ buf[961]=(byte)i; if(sha1_32(buf)==-2056595243){break;} } + for(i=106;i<117;i++){ buf[962]=(byte)i; if(sha1_32(buf)==-2120205781){break;} } + for(i=-53;i<-36;i++){ buf[963]=(byte)i; if(sha1_32(buf)==125468582){break;} } + for(i=-41;i<-21;i++){ buf[964]=(byte)i; if(sha1_32(buf)==-759282965){break;} } + for(i=-100;i<-91;i++){ buf[965]=(byte)i; if(sha1_32(buf)==46037119){break;} } + for(i=85;i<90;i++){ buf[966]=(byte)i; if(sha1_32(buf)==-1381494939){break;} } + for(i=-31;i<-25;i++){ buf[967]=(byte)i; if(sha1_32(buf)==2011245134){break;} } + for(i=-68;i<-56;i++){ buf[968]=(byte)i; if(sha1_32(buf)==-231002651){break;} } + for(i=-99;i<-88;i++){ buf[969]=(byte)i; if(sha1_32(buf)==-2118350372){break;} } + for(i=-100;i<-95;i++){ buf[970]=(byte)i; if(sha1_32(buf)==441671649){break;} } + for(i=-66;i<-41;i++){ buf[971]=(byte)i; if(sha1_32(buf)==2083516320){break;} } + for(i=20;i<36;i++){ buf[972]=(byte)i; if(sha1_32(buf)==867170251){break;} } + for(i=101;i<127;i++){ buf[973]=(byte)i; if(sha1_32(buf)==-1984396790){break;} } + for(i=-42;i<-23;i++){ buf[974]=(byte)i; if(sha1_32(buf)==64715245){break;} } + for(i=4;i<23;i++){ buf[975]=(byte)i; if(sha1_32(buf)==1684700478){break;} } + for(i=63;i<81;i++){ buf[976]=(byte)i; if(sha1_32(buf)==-1149849537){break;} } + for(i=-20;i<-7;i++){ buf[977]=(byte)i; if(sha1_32(buf)==-1384937396){break;} } + for(i=51;i<73;i++){ buf[978]=(byte)i; if(sha1_32(buf)==-1450734456){break;} } + for(i=-54;i<-37;i++){ buf[979]=(byte)i; if(sha1_32(buf)==-2073975361){break;} } + for(i=113;i<128;i++){ buf[980]=(byte)i; if(sha1_32(buf)==1020168706){break;} } + for(i=76;i<85;i++){ buf[981]=(byte)i; if(sha1_32(buf)==-1137564100){break;} } + for(i=0;i<15;i++){ buf[982]=(byte)i; if(sha1_32(buf)==-433673203){break;} } + for(i=44;i<57;i++){ buf[983]=(byte)i; if(sha1_32(buf)==1891301518){break;} } + for(i=-27;i<-9;i++){ buf[984]=(byte)i; if(sha1_32(buf)==-1026494060){break;} } + for(i=-60;i<-31;i++){ buf[985]=(byte)i; if(sha1_32(buf)==-1057319415){break;} } + for(i=-126;i<-105;i++){ buf[986]=(byte)i; if(sha1_32(buf)==-1648711413){break;} } + for(i=84;i<101;i++){ buf[987]=(byte)i; if(sha1_32(buf)==-2002260226){break;} } + for(i=-47;i<-34;i++){ buf[988]=(byte)i; if(sha1_32(buf)==-1163678002){break;} } + for(i=-80;i<-69;i++){ buf[989]=(byte)i; if(sha1_32(buf)==-656455502){break;} } + for(i=-29;i<-8;i++){ buf[990]=(byte)i; if(sha1_32(buf)==341901046){break;} } + for(i=-123;i<-106;i++){ buf[991]=(byte)i; if(sha1_32(buf)==-2036861356){break;} } + for(i=-49;i<-39;i++){ buf[992]=(byte)i; if(sha1_32(buf)==-993733222){break;} } + for(i=68;i<83;i++){ buf[993]=(byte)i; if(sha1_32(buf)==989275190){break;} } + for(i=-105;i<-89;i++){ buf[994]=(byte)i; if(sha1_32(buf)==1662925223){break;} } + for(i=4;i<14;i++){ buf[995]=(byte)i; if(sha1_32(buf)==-1800560843){break;} } + for(i=-74;i<-62;i++){ buf[996]=(byte)i; if(sha1_32(buf)==323592519){break;} } + for(i=41;i<63;i++){ buf[997]=(byte)i; if(sha1_32(buf)==1537635689){break;} } + for(i=-91;i<-81;i++){ buf[998]=(byte)i; if(sha1_32(buf)==-714086883){break;} } + for(i=80;i<96;i++){ buf[999]=(byte)i; if(sha1_32(buf)==-1350742941){break;} } + for(i=-8;i<10;i++){ buf[1000]=(byte)i; if(sha1_32(buf)==2139369971){break;} } + for(i=118;i<125;i++){ buf[1001]=(byte)i; if(sha1_32(buf)==-538711097){break;} } + for(i=114;i<128;i++){ buf[1002]=(byte)i; if(sha1_32(buf)==-1138038063){break;} } + for(i=48;i<64;i++){ buf[1003]=(byte)i; if(sha1_32(buf)==-545071251){break;} } + for(i=75;i<92;i++){ buf[1004]=(byte)i; if(sha1_32(buf)==-1184016227){break;} } + for(i=-45;i<-31;i++){ buf[1005]=(byte)i; if(sha1_32(buf)==605541705){break;} } + for(i=108;i<128;i++){ buf[1006]=(byte)i; if(sha1_32(buf)==-1923048554){break;} } + for(i=-113;i<-94;i++){ buf[1007]=(byte)i; if(sha1_32(buf)==880753395){break;} } + for(i=-90;i<-79;i++){ buf[1008]=(byte)i; if(sha1_32(buf)==1123046122){break;} } + for(i=30;i<48;i++){ buf[1009]=(byte)i; if(sha1_32(buf)==1739166413){break;} } + for(i=-26;i<-9;i++){ buf[1010]=(byte)i; if(sha1_32(buf)==-2094165455){break;} } + for(i=28;i<54;i++){ buf[1011]=(byte)i; if(sha1_32(buf)==2139995727){break;} } + for(i=0;i<14;i++){ buf[1012]=(byte)i; if(sha1_32(buf)==203920209){break;} } + for(i=40;i<49;i++){ buf[1013]=(byte)i; if(sha1_32(buf)==-1135645249){break;} } + for(i=77;i<94;i++){ buf[1014]=(byte)i; if(sha1_32(buf)==962273992){break;} } + for(i=-112;i<-104;i++){ buf[1015]=(byte)i; if(sha1_32(buf)==1112237553){break;} } + for(i=-40;i<-31;i++){ buf[1016]=(byte)i; if(sha1_32(buf)==1072697815){break;} } + for(i=87;i<102;i++){ buf[1017]=(byte)i; if(sha1_32(buf)==534244137){break;} } + for(i=6;i<23;i++){ buf[1018]=(byte)i; if(sha1_32(buf)==-204135386){break;} } + for(i=-86;i<-83;i++){ buf[1019]=(byte)i; if(sha1_32(buf)==-1950067505){break;} } + for(i=-1;i<25;i++){ buf[1020]=(byte)i; if(sha1_32(buf)==169292245){break;} } + for(i=-91;i<-73;i++){ buf[1021]=(byte)i; if(sha1_32(buf)==1668251079){break;} } + for(i=118;i<128;i++){ buf[1022]=(byte)i; if(sha1_32(buf)==351773699){break;} } + for(i=52;i<71;i++){ buf[1023]=(byte)i; if(sha1_32(buf)==1094142757){break;} } + for(i=108;i<115;i++){ buf[1024]=(byte)i; if(sha1_32(buf)==-1499940564){break;} } + for(i=-64;i<-60;i++){ buf[1025]=(byte)i; if(sha1_32(buf)==974511154){break;} } + for(i=95;i<111;i++){ buf[1026]=(byte)i; if(sha1_32(buf)==-225629822){break;} } + for(i=80;i<99;i++){ buf[1027]=(byte)i; if(sha1_32(buf)==775334224){break;} } + for(i=70;i<87;i++){ buf[1028]=(byte)i; if(sha1_32(buf)==1989615161){break;} } + for(i=-8;i<16;i++){ buf[1029]=(byte)i; if(sha1_32(buf)==2013841521){break;} } + for(i=-96;i<-84;i++){ buf[1030]=(byte)i; if(sha1_32(buf)==-38959762){break;} } + for(i=32;i<54;i++){ buf[1031]=(byte)i; if(sha1_32(buf)==17007173){break;} } + for(i=-128;i<-108;i++){ buf[1032]=(byte)i; if(sha1_32(buf)==-1093049954){break;} } + for(i=-33;i<-24;i++){ buf[1033]=(byte)i; if(sha1_32(buf)==-1380990090){break;} } + for(i=-76;i<-60;i++){ buf[1034]=(byte)i; if(sha1_32(buf)==-1435978553){break;} } + for(i=-128;i<-103;i++){ buf[1035]=(byte)i; if(sha1_32(buf)==275186307){break;} } + for(i=96;i<109;i++){ buf[1036]=(byte)i; if(sha1_32(buf)==1781919692){break;} } + for(i=-117;i<-114;i++){ buf[1037]=(byte)i; if(sha1_32(buf)==-785589820){break;} } + for(i=-93;i<-74;i++){ buf[1038]=(byte)i; if(sha1_32(buf)==-1162000185){break;} } + for(i=15;i<36;i++){ buf[1039]=(byte)i; if(sha1_32(buf)==-99645430){break;} } + for(i=91;i<119;i++){ buf[1040]=(byte)i; if(sha1_32(buf)==-267557470){break;} } + for(i=107;i<123;i++){ buf[1041]=(byte)i; if(sha1_32(buf)==-2072445968){break;} } + for(i=-96;i<-74;i++){ buf[1042]=(byte)i; if(sha1_32(buf)==-2082764174){break;} } + for(i=-46;i<-42;i++){ buf[1043]=(byte)i; if(sha1_32(buf)==-737479610){break;} } + for(i=83;i<100;i++){ buf[1044]=(byte)i; if(sha1_32(buf)==-807107930){break;} } + for(i=-128;i<-115;i++){ buf[1045]=(byte)i; if(sha1_32(buf)==-1241257099){break;} } + for(i=-128;i<-119;i++){ buf[1046]=(byte)i; if(sha1_32(buf)==1786443960){break;} } + for(i=-59;i<-30;i++){ buf[1047]=(byte)i; if(sha1_32(buf)==1665456595){break;} } + for(i=121;i<128;i++){ buf[1048]=(byte)i; if(sha1_32(buf)==-1140341445){break;} } + for(i=106;i<119;i++){ buf[1049]=(byte)i; if(sha1_32(buf)==-1450332040){break;} } + for(i=20;i<43;i++){ buf[1050]=(byte)i; if(sha1_32(buf)==138519052){break;} } + for(i=-115;i<-92;i++){ buf[1051]=(byte)i; if(sha1_32(buf)==1443995933){break;} } + for(i=-70;i<-61;i++){ buf[1052]=(byte)i; if(sha1_32(buf)==637333117){break;} } + for(i=73;i<91;i++){ buf[1053]=(byte)i; if(sha1_32(buf)==-1892526595){break;} } + for(i=-70;i<-52;i++){ buf[1054]=(byte)i; if(sha1_32(buf)==645156581){break;} } + for(i=-95;i<-89;i++){ buf[1055]=(byte)i; if(sha1_32(buf)==1243080065){break;} } + for(i=90;i<109;i++){ buf[1056]=(byte)i; if(sha1_32(buf)==-378078286){break;} } + for(i=-123;i<-108;i++){ buf[1057]=(byte)i; if(sha1_32(buf)==-318888651){break;} } + for(i=28;i<35;i++){ buf[1058]=(byte)i; if(sha1_32(buf)==1678813882){break;} } + for(i=8;i<28;i++){ buf[1059]=(byte)i; if(sha1_32(buf)==691156564){break;} } + for(i=-33;i<-21;i++){ buf[1060]=(byte)i; if(sha1_32(buf)==2025172207){break;} } + for(i=-88;i<-77;i++){ buf[1061]=(byte)i; if(sha1_32(buf)==559736034){break;} } + for(i=-87;i<-59;i++){ buf[1062]=(byte)i; if(sha1_32(buf)==1986380456){break;} } + for(i=-79;i<-64;i++){ buf[1063]=(byte)i; if(sha1_32(buf)==-1043296392){break;} } + for(i=-35;i<-21;i++){ buf[1064]=(byte)i; if(sha1_32(buf)==85150754){break;} } + for(i=41;i<55;i++){ buf[1065]=(byte)i; if(sha1_32(buf)==-1409625681){break;} } + for(i=109;i<128;i++){ buf[1066]=(byte)i; if(sha1_32(buf)==2022758805){break;} } + for(i=-32;i<-15;i++){ buf[1067]=(byte)i; if(sha1_32(buf)==-1105339080){break;} } + for(i=-56;i<-49;i++){ buf[1068]=(byte)i; if(sha1_32(buf)==-370534867){break;} } + for(i=-52;i<-27;i++){ buf[1069]=(byte)i; if(sha1_32(buf)==-629446371){break;} } + for(i=-83;i<-71;i++){ buf[1070]=(byte)i; if(sha1_32(buf)==726716218){break;} } + for(i=15;i<28;i++){ buf[1071]=(byte)i; if(sha1_32(buf)==-2092877279){break;} } + for(i=-110;i<-89;i++){ buf[1072]=(byte)i; if(sha1_32(buf)==-1321909687){break;} } + for(i=-115;i<-108;i++){ buf[1073]=(byte)i; if(sha1_32(buf)==-1436307508){break;} } + for(i=106;i<122;i++){ buf[1074]=(byte)i; if(sha1_32(buf)==1408958465){break;} } + for(i=-110;i<-100;i++){ buf[1075]=(byte)i; if(sha1_32(buf)==669571210){break;} } + for(i=-112;i<-85;i++){ buf[1076]=(byte)i; if(sha1_32(buf)==-337770707){break;} } + for(i=-27;i<-10;i++){ buf[1077]=(byte)i; if(sha1_32(buf)==1786361597){break;} } + for(i=112;i<121;i++){ buf[1078]=(byte)i; if(sha1_32(buf)==1106785408){break;} } + for(i=-21;i<-10;i++){ buf[1079]=(byte)i; if(sha1_32(buf)==-1358058883){break;} } + for(i=85;i<88;i++){ buf[1080]=(byte)i; if(sha1_32(buf)==-1594661626){break;} } + for(i=-48;i<-31;i++){ buf[1081]=(byte)i; if(sha1_32(buf)==1947674546){break;} } + for(i=-65;i<-40;i++){ buf[1082]=(byte)i; if(sha1_32(buf)==326878353){break;} } + for(i=40;i<49;i++){ buf[1083]=(byte)i; if(sha1_32(buf)==-827463723){break;} } + for(i=49;i<73;i++){ buf[1084]=(byte)i; if(sha1_32(buf)==-1488052013){break;} } + for(i=67;i<89;i++){ buf[1085]=(byte)i; if(sha1_32(buf)==-2145446721){break;} } + for(i=51;i<68;i++){ buf[1086]=(byte)i; if(sha1_32(buf)==879361044){break;} } + for(i=79;i<89;i++){ buf[1087]=(byte)i; if(sha1_32(buf)==210235629){break;} } + for(i=123;i<128;i++){ buf[1088]=(byte)i; if(sha1_32(buf)==1373695713){break;} } + for(i=23;i<32;i++){ buf[1089]=(byte)i; if(sha1_32(buf)==839481198){break;} } + for(i=52;i<74;i++){ buf[1090]=(byte)i; if(sha1_32(buf)==-233898711){break;} } + for(i=5;i<22;i++){ buf[1091]=(byte)i; if(sha1_32(buf)==-1146841254){break;} } + for(i=117;i<128;i++){ buf[1092]=(byte)i; if(sha1_32(buf)==1792110236){break;} } + for(i=-3;i<6;i++){ buf[1093]=(byte)i; if(sha1_32(buf)==-2085652053){break;} } + for(i=-99;i<-87;i++){ buf[1094]=(byte)i; if(sha1_32(buf)==300722691){break;} } + for(i=26;i<43;i++){ buf[1095]=(byte)i; if(sha1_32(buf)==-523984871){break;} } + for(i=-38;i<-23;i++){ buf[1096]=(byte)i; if(sha1_32(buf)==1572248949){break;} } + for(i=17;i<24;i++){ buf[1097]=(byte)i; if(sha1_32(buf)==70148005){break;} } + for(i=-93;i<-76;i++){ buf[1098]=(byte)i; if(sha1_32(buf)==1078930454){break;} } + for(i=-83;i<-64;i++){ buf[1099]=(byte)i; if(sha1_32(buf)==-1891642768){break;} } + for(i=26;i<37;i++){ buf[1100]=(byte)i; if(sha1_32(buf)==-877048145){break;} } + for(i=-80;i<-71;i++){ buf[1101]=(byte)i; if(sha1_32(buf)==-2092113685){break;} } + for(i=-71;i<-64;i++){ buf[1102]=(byte)i; if(sha1_32(buf)==-64359604){break;} } + for(i=-17;i<-1;i++){ buf[1103]=(byte)i; if(sha1_32(buf)==462331862){break;} } + for(i=42;i<61;i++){ buf[1104]=(byte)i; if(sha1_32(buf)==-1581108711){break;} } + for(i=-16;i<-12;i++){ buf[1105]=(byte)i; if(sha1_32(buf)==-835618069){break;} } + for(i=111;i<124;i++){ buf[1106]=(byte)i; if(sha1_32(buf)==103796386){break;} } + for(i=103;i<110;i++){ buf[1107]=(byte)i; if(sha1_32(buf)==-1758071957){break;} } + for(i=-63;i<-48;i++){ buf[1108]=(byte)i; if(sha1_32(buf)==-1651694256){break;} } + for(i=-92;i<-67;i++){ buf[1109]=(byte)i; if(sha1_32(buf)==-527349781){break;} } + for(i=68;i<82;i++){ buf[1110]=(byte)i; if(sha1_32(buf)==-2006844027){break;} } + for(i=-91;i<-86;i++){ buf[1111]=(byte)i; if(sha1_32(buf)==1011655464){break;} } + for(i=-95;i<-72;i++){ buf[1112]=(byte)i; if(sha1_32(buf)==119363532){break;} } + for(i=26;i<40;i++){ buf[1113]=(byte)i; if(sha1_32(buf)==1827654098){break;} } + for(i=-90;i<-72;i++){ buf[1114]=(byte)i; if(sha1_32(buf)==-1214355055){break;} } + for(i=-54;i<-34;i++){ buf[1115]=(byte)i; if(sha1_32(buf)==-1943150988){break;} } + for(i=-128;i<-123;i++){ buf[1116]=(byte)i; if(sha1_32(buf)==1666015883){break;} } + for(i=14;i<29;i++){ buf[1117]=(byte)i; if(sha1_32(buf)==-178424823){break;} } + for(i=-77;i<-57;i++){ buf[1118]=(byte)i; if(sha1_32(buf)==438492201){break;} } + for(i=-77;i<-68;i++){ buf[1119]=(byte)i; if(sha1_32(buf)==987747054){break;} } + for(i=20;i<31;i++){ buf[1120]=(byte)i; if(sha1_32(buf)==-1233386100){break;} } + for(i=-128;i<-113;i++){ buf[1121]=(byte)i; if(sha1_32(buf)==-258497829){break;} } + for(i=-28;i<-11;i++){ buf[1122]=(byte)i; if(sha1_32(buf)==-1735166566){break;} } + for(i=-117;i<-105;i++){ buf[1123]=(byte)i; if(sha1_32(buf)==-501716166){break;} } + for(i=4;i<23;i++){ buf[1124]=(byte)i; if(sha1_32(buf)==1728576604){break;} } + for(i=-19;i<-4;i++){ buf[1125]=(byte)i; if(sha1_32(buf)==-1079202770){break;} } + for(i=-6;i<6;i++){ buf[1126]=(byte)i; if(sha1_32(buf)==1491635534){break;} } + for(i=51;i<71;i++){ buf[1127]=(byte)i; if(sha1_32(buf)==-19365497){break;} } + for(i=40;i<61;i++){ buf[1128]=(byte)i; if(sha1_32(buf)==-1154220082){break;} } + for(i=72;i<93;i++){ buf[1129]=(byte)i; if(sha1_32(buf)==185062196){break;} } + for(i=-71;i<-52;i++){ buf[1130]=(byte)i; if(sha1_32(buf)==1091765059){break;} } + for(i=-37;i<-27;i++){ buf[1131]=(byte)i; if(sha1_32(buf)==-2079990844){break;} } + for(i=-54;i<-35;i++){ buf[1132]=(byte)i; if(sha1_32(buf)==1738222119){break;} } + for(i=-20;i<-11;i++){ buf[1133]=(byte)i; if(sha1_32(buf)==-2121921500){break;} } + for(i=111;i<128;i++){ buf[1134]=(byte)i; if(sha1_32(buf)==-1511886409){break;} } + for(i=103;i<114;i++){ buf[1135]=(byte)i; if(sha1_32(buf)==-438984646){break;} } + for(i=-95;i<-73;i++){ buf[1136]=(byte)i; if(sha1_32(buf)==-1587092422){break;} } + for(i=-60;i<-55;i++){ buf[1137]=(byte)i; if(sha1_32(buf)==2085270602){break;} } + for(i=58;i<77;i++){ buf[1138]=(byte)i; if(sha1_32(buf)==-542145516){break;} } + for(i=95;i<105;i++){ buf[1139]=(byte)i; if(sha1_32(buf)==-1595714757){break;} } + for(i=82;i<98;i++){ buf[1140]=(byte)i; if(sha1_32(buf)==-174273588){break;} } + for(i=107;i<122;i++){ buf[1141]=(byte)i; if(sha1_32(buf)==1900664030){break;} } + for(i=-70;i<-53;i++){ buf[1142]=(byte)i; if(sha1_32(buf)==2066126526){break;} } + for(i=20;i<45;i++){ buf[1143]=(byte)i; if(sha1_32(buf)==1659349440){break;} } + for(i=-84;i<-54;i++){ buf[1144]=(byte)i; if(sha1_32(buf)==371249220){break;} } + for(i=-64;i<-59;i++){ buf[1145]=(byte)i; if(sha1_32(buf)==1092328833){break;} } + for(i=43;i<52;i++){ buf[1146]=(byte)i; if(sha1_32(buf)==-153394063){break;} } + for(i=-89;i<-71;i++){ buf[1147]=(byte)i; if(sha1_32(buf)==398580307){break;} } + for(i=-74;i<-67;i++){ buf[1148]=(byte)i; if(sha1_32(buf)==-1661525123){break;} } + for(i=89;i<108;i++){ buf[1149]=(byte)i; if(sha1_32(buf)==1360348283){break;} } + for(i=-52;i<-44;i++){ buf[1150]=(byte)i; if(sha1_32(buf)==236358520){break;} } + for(i=80;i<101;i++){ buf[1151]=(byte)i; if(sha1_32(buf)==1672281133){break;} } + for(i=105;i<108;i++){ buf[1152]=(byte)i; if(sha1_32(buf)==749554350){break;} } + for(i=59;i<76;i++){ buf[1153]=(byte)i; if(sha1_32(buf)==-292394596){break;} } + for(i=11;i<18;i++){ buf[1154]=(byte)i; if(sha1_32(buf)==-234575886){break;} } + for(i=102;i<117;i++){ buf[1155]=(byte)i; if(sha1_32(buf)==-1419752642){break;} } + for(i=98;i<104;i++){ buf[1156]=(byte)i; if(sha1_32(buf)==722616406){break;} } + for(i=118;i<128;i++){ buf[1157]=(byte)i; if(sha1_32(buf)==207023551){break;} } + for(i=21;i<38;i++){ buf[1158]=(byte)i; if(sha1_32(buf)==-34321382){break;} } + for(i=-128;i<-110;i++){ buf[1159]=(byte)i; if(sha1_32(buf)==1813147722){break;} } + for(i=-42;i<-30;i++){ buf[1160]=(byte)i; if(sha1_32(buf)==-1807506824){break;} } + for(i=20;i<26;i++){ buf[1161]=(byte)i; if(sha1_32(buf)==1245686884){break;} } + for(i=69;i<89;i++){ buf[1162]=(byte)i; if(sha1_32(buf)==-1191294795){break;} } + for(i=-128;i<-123;i++){ buf[1163]=(byte)i; if(sha1_32(buf)==636251977){break;} } + for(i=-75;i<-47;i++){ buf[1164]=(byte)i; if(sha1_32(buf)==265150458){break;} } + for(i=-111;i<-95;i++){ buf[1165]=(byte)i; if(sha1_32(buf)==1795673353){break;} } + for(i=-98;i<-82;i++){ buf[1166]=(byte)i; if(sha1_32(buf)==818727338){break;} } + for(i=55;i<73;i++){ buf[1167]=(byte)i; if(sha1_32(buf)==-1686255078){break;} } + for(i=114;i<125;i++){ buf[1168]=(byte)i; if(sha1_32(buf)==-663421916){break;} } + for(i=-34;i<-24;i++){ buf[1169]=(byte)i; if(sha1_32(buf)==129953861){break;} } + for(i=-10;i<12;i++){ buf[1170]=(byte)i; if(sha1_32(buf)==-758812232){break;} } + for(i=-121;i<-111;i++){ buf[1171]=(byte)i; if(sha1_32(buf)==1559375840){break;} } + for(i=-128;i<-102;i++){ buf[1172]=(byte)i; if(sha1_32(buf)==469597355){break;} } + for(i=-82;i<-58;i++){ buf[1173]=(byte)i; if(sha1_32(buf)==-878089631){break;} } + for(i=-5;i<9;i++){ buf[1174]=(byte)i; if(sha1_32(buf)==-1831567414){break;} } + for(i=-59;i<-40;i++){ buf[1175]=(byte)i; if(sha1_32(buf)==80030536){break;} } + for(i=21;i<38;i++){ buf[1176]=(byte)i; if(sha1_32(buf)==-303161426){break;} } + for(i=91;i<115;i++){ buf[1177]=(byte)i; if(sha1_32(buf)==-933075582){break;} } + for(i=-115;i<-103;i++){ buf[1178]=(byte)i; if(sha1_32(buf)==-1298353680){break;} } + for(i=82;i<93;i++){ buf[1179]=(byte)i; if(sha1_32(buf)==-1865930790){break;} } + for(i=-123;i<-98;i++){ buf[1180]=(byte)i; if(sha1_32(buf)==-372037200){break;} } + for(i=-113;i<-96;i++){ buf[1181]=(byte)i; if(sha1_32(buf)==2109374435){break;} } + for(i=-64;i<-48;i++){ buf[1182]=(byte)i; if(sha1_32(buf)==-1813148922){break;} } + for(i=-2;i<7;i++){ buf[1183]=(byte)i; if(sha1_32(buf)==-1813148922){break;} } + for(i=55;i<72;i++){ buf[1184]=(byte)i; if(sha1_32(buf)==-548158664){break;} } + for(i=47;i<60;i++){ buf[1185]=(byte)i; if(sha1_32(buf)==-1842516851){break;} } + for(i=-8;i<10;i++){ buf[1186]=(byte)i; if(sha1_32(buf)==-1295167494){break;} } + for(i=-12;i<7;i++){ buf[1187]=(byte)i; if(sha1_32(buf)==-710236125){break;} } + for(i=58;i<77;i++){ buf[1188]=(byte)i; if(sha1_32(buf)==1268747381){break;} } + for(i=100;i<113;i++){ buf[1189]=(byte)i; if(sha1_32(buf)==-747145295){break;} } + for(i=43;i<56;i++){ buf[1190]=(byte)i; if(sha1_32(buf)==-1308171970){break;} } + for(i=2;i<29;i++){ buf[1191]=(byte)i; if(sha1_32(buf)==-2102687634){break;} } + for(i=10;i<35;i++){ buf[1192]=(byte)i; if(sha1_32(buf)==-2110628114){break;} } + for(i=114;i<119;i++){ buf[1193]=(byte)i; if(sha1_32(buf)==-1804143624){break;} } + for(i=-85;i<-82;i++){ buf[1194]=(byte)i; if(sha1_32(buf)==-1370218155){break;} } + for(i=-121;i<-96;i++){ buf[1195]=(byte)i; if(sha1_32(buf)==-839382276){break;} } + for(i=29;i<44;i++){ buf[1196]=(byte)i; if(sha1_32(buf)==195442480){break;} } + for(i=-84;i<-60;i++){ buf[1197]=(byte)i; if(sha1_32(buf)==-1558366254){break;} } + for(i=-29;i<-13;i++){ buf[1198]=(byte)i; if(sha1_32(buf)==-1321274593){break;} } + for(i=50;i<72;i++){ buf[1199]=(byte)i; if(sha1_32(buf)==1378503636){break;} } + for(i=-114;i<-91;i++){ buf[1200]=(byte)i; if(sha1_32(buf)==1771958436){break;} } + for(i=68;i<75;i++){ buf[1201]=(byte)i; if(sha1_32(buf)==-1159135819){break;} } + for(i=53;i<66;i++){ buf[1202]=(byte)i; if(sha1_32(buf)==-753115336){break;} } + for(i=-73;i<-64;i++){ buf[1203]=(byte)i; if(sha1_32(buf)==20272569){break;} } + for(i=-128;i<-118;i++){ buf[1204]=(byte)i; if(sha1_32(buf)==1285477298){break;} } + for(i=-119;i<-105;i++){ buf[1205]=(byte)i; if(sha1_32(buf)==-1703165409){break;} } + for(i=50;i<62;i++){ buf[1206]=(byte)i; if(sha1_32(buf)==594237475){break;} } + for(i=3;i<24;i++){ buf[1207]=(byte)i; if(sha1_32(buf)==-952877050){break;} } + for(i=-42;i<-27;i++){ buf[1208]=(byte)i; if(sha1_32(buf)==896862829){break;} } + for(i=-101;i<-85;i++){ buf[1209]=(byte)i; if(sha1_32(buf)==1364580057){break;} } + for(i=-32;i<-19;i++){ buf[1210]=(byte)i; if(sha1_32(buf)==1819535054){break;} } + for(i=27;i<33;i++){ buf[1211]=(byte)i; if(sha1_32(buf)==-1686160198){break;} } + for(i=-93;i<-72;i++){ buf[1212]=(byte)i; if(sha1_32(buf)==1023996577){break;} } + for(i=-100;i<-91;i++){ buf[1213]=(byte)i; if(sha1_32(buf)==579671853){break;} } + for(i=-32;i<-15;i++){ buf[1214]=(byte)i; if(sha1_32(buf)==-188752328){break;} } + for(i=-114;i<-94;i++){ buf[1215]=(byte)i; if(sha1_32(buf)==-1788309873){break;} } + for(i=89;i<105;i++){ buf[1216]=(byte)i; if(sha1_32(buf)==-1222797574){break;} } + for(i=89;i<105;i++){ buf[1217]=(byte)i; if(sha1_32(buf)==-215334977){break;} } + for(i=-128;i<-115;i++){ buf[1218]=(byte)i; if(sha1_32(buf)==-1765880598){break;} } + for(i=31;i<51;i++){ buf[1219]=(byte)i; if(sha1_32(buf)==1576480807){break;} } + for(i=63;i<76;i++){ buf[1220]=(byte)i; if(sha1_32(buf)==1158935180){break;} } + for(i=42;i<49;i++){ buf[1221]=(byte)i; if(sha1_32(buf)==-1419476236){break;} } + for(i=20;i<35;i++){ buf[1222]=(byte)i; if(sha1_32(buf)==1958000843){break;} } + for(i=-106;i<-87;i++){ buf[1223]=(byte)i; if(sha1_32(buf)==786142651){break;} } + for(i=62;i<76;i++){ buf[1224]=(byte)i; if(sha1_32(buf)==1546995582){break;} } + for(i=-128;i<-126;i++){ buf[1225]=(byte)i; if(sha1_32(buf)==2084041227){break;} } + for(i=60;i<79;i++){ buf[1226]=(byte)i; if(sha1_32(buf)==-144463173){break;} } + for(i=41;i<56;i++){ buf[1227]=(byte)i; if(sha1_32(buf)==-1235874263){break;} } + for(i=-83;i<-74;i++){ buf[1228]=(byte)i; if(sha1_32(buf)==1636272900){break;} } + for(i=-75;i<-66;i++){ buf[1229]=(byte)i; if(sha1_32(buf)==1213836500){break;} } + for(i=43;i<56;i++){ buf[1230]=(byte)i; if(sha1_32(buf)==1243745150){break;} } + for(i=98;i<108;i++){ buf[1231]=(byte)i; if(sha1_32(buf)==1549128667){break;} } + for(i=11;i<31;i++){ buf[1232]=(byte)i; if(sha1_32(buf)==636865778){break;} } + for(i=-111;i<-93;i++){ buf[1233]=(byte)i; if(sha1_32(buf)==-699507039){break;} } + for(i=-105;i<-83;i++){ buf[1234]=(byte)i; if(sha1_32(buf)==-1958780713){break;} } + for(i=6;i<16;i++){ buf[1235]=(byte)i; if(sha1_32(buf)==291036541){break;} } + for(i=-85;i<-64;i++){ buf[1236]=(byte)i; if(sha1_32(buf)==305816622){break;} } + for(i=108;i<127;i++){ buf[1237]=(byte)i; if(sha1_32(buf)==138337407){break;} } + for(i=106;i<114;i++){ buf[1238]=(byte)i; if(sha1_32(buf)==990276981){break;} } + for(i=-128;i<-112;i++){ buf[1239]=(byte)i; if(sha1_32(buf)==758125124){break;} } + for(i=-78;i<-70;i++){ buf[1240]=(byte)i; if(sha1_32(buf)==821392939){break;} } + for(i=31;i<38;i++){ buf[1241]=(byte)i; if(sha1_32(buf)==1272689785){break;} } + for(i=-68;i<-54;i++){ buf[1242]=(byte)i; if(sha1_32(buf)==-451791906){break;} } + for(i=-128;i<-121;i++){ buf[1243]=(byte)i; if(sha1_32(buf)==-1006720983){break;} } + for(i=9;i<28;i++){ buf[1244]=(byte)i; if(sha1_32(buf)==-2038368783){break;} } + for(i=105;i<116;i++){ buf[1245]=(byte)i; if(sha1_32(buf)==987022077){break;} } + for(i=-89;i<-68;i++){ buf[1246]=(byte)i; if(sha1_32(buf)==-138796089){break;} } + for(i=54;i<61;i++){ buf[1247]=(byte)i; if(sha1_32(buf)==283079607){break;} } + for(i=56;i<79;i++){ buf[1248]=(byte)i; if(sha1_32(buf)==-386702342){break;} } + for(i=115;i<128;i++){ buf[1249]=(byte)i; if(sha1_32(buf)==-1278013589){break;} } + for(i=24;i<46;i++){ buf[1250]=(byte)i; if(sha1_32(buf)==-1543136169){break;} } + for(i=2;i<29;i++){ buf[1251]=(byte)i; if(sha1_32(buf)==776602743){break;} } + for(i=20;i<29;i++){ buf[1252]=(byte)i; if(sha1_32(buf)==1740349896){break;} } + for(i=66;i<84;i++){ buf[1253]=(byte)i; if(sha1_32(buf)==-281134038){break;} } + for(i=-29;i<-6;i++){ buf[1254]=(byte)i; if(sha1_32(buf)==-1704754264){break;} } + for(i=67;i<93;i++){ buf[1255]=(byte)i; if(sha1_32(buf)==1978860888){break;} } + for(i=-12;i<4;i++){ buf[1256]=(byte)i; if(sha1_32(buf)==-310399196){break;} } + for(i=46;i<75;i++){ buf[1257]=(byte)i; if(sha1_32(buf)==-358370940){break;} } + for(i=-33;i<-21;i++){ buf[1258]=(byte)i; if(sha1_32(buf)==427972523){break;} } + for(i=101;i<119;i++){ buf[1259]=(byte)i; if(sha1_32(buf)==-97871858){break;} } + for(i=84;i<97;i++){ buf[1260]=(byte)i; if(sha1_32(buf)==-817348087){break;} } + for(i=-112;i<-96;i++){ buf[1261]=(byte)i; if(sha1_32(buf)==1206459387){break;} } + for(i=-123;i<-108;i++){ buf[1262]=(byte)i; if(sha1_32(buf)==1759629363){break;} } + for(i=-111;i<-97;i++){ buf[1263]=(byte)i; if(sha1_32(buf)==-621376529){break;} } + for(i=49;i<63;i++){ buf[1264]=(byte)i; if(sha1_32(buf)==187753316){break;} } + for(i=69;i<93;i++){ buf[1265]=(byte)i; if(sha1_32(buf)==-1688586181){break;} } + for(i=53;i<69;i++){ buf[1266]=(byte)i; if(sha1_32(buf)==-2002801302){break;} } + for(i=11;i<28;i++){ buf[1267]=(byte)i; if(sha1_32(buf)==67885761){break;} } + for(i=-120;i<-110;i++){ buf[1268]=(byte)i; if(sha1_32(buf)==310175039){break;} } + for(i=-47;i<-26;i++){ buf[1269]=(byte)i; if(sha1_32(buf)==-2065221852){break;} } + for(i=59;i<77;i++){ buf[1270]=(byte)i; if(sha1_32(buf)==-1770810308){break;} } + for(i=3;i<27;i++){ buf[1271]=(byte)i; if(sha1_32(buf)==414020951){break;} } + for(i=78;i<107;i++){ buf[1272]=(byte)i; if(sha1_32(buf)==1642487656){break;} } + for(i=49;i<73;i++){ buf[1273]=(byte)i; if(sha1_32(buf)==-1689510636){break;} } + for(i=45;i<63;i++){ buf[1274]=(byte)i; if(sha1_32(buf)==1165890790){break;} } + for(i=68;i<83;i++){ buf[1275]=(byte)i; if(sha1_32(buf)==1792898471){break;} } + for(i=62;i<77;i++){ buf[1276]=(byte)i; if(sha1_32(buf)==1970953191){break;} } + for(i=110;i<120;i++){ buf[1277]=(byte)i; if(sha1_32(buf)==1828616521){break;} } + for(i=-83;i<-71;i++){ buf[1278]=(byte)i; if(sha1_32(buf)==-501095679){break;} } + for(i=-128;i<-121;i++){ buf[1279]=(byte)i; if(sha1_32(buf)==-1042754258){break;} } + for(i=107;i<120;i++){ buf[1280]=(byte)i; if(sha1_32(buf)==-2021034367){break;} } + for(i=104;i<122;i++){ buf[1281]=(byte)i; if(sha1_32(buf)==-515216398){break;} } + for(i=20;i<41;i++){ buf[1282]=(byte)i; if(sha1_32(buf)==1999387980){break;} } + for(i=-60;i<-29;i++){ buf[1283]=(byte)i; if(sha1_32(buf)==-797913149){break;} } + for(i=-100;i<-85;i++){ buf[1284]=(byte)i; if(sha1_32(buf)==237396739){break;} } + for(i=-36;i<-28;i++){ buf[1285]=(byte)i; if(sha1_32(buf)==-1641086748){break;} } + for(i=-89;i<-65;i++){ buf[1286]=(byte)i; if(sha1_32(buf)==-1834110753){break;} } + return buf; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/CPUInfoUtil.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/CPUInfoUtil.java new file mode 100644 index 000000000..a059a1541 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/CPUInfoUtil.java @@ -0,0 +1,172 @@ +package com.yunbao.faceunity.utils; + +import android.content.Context; +import android.os.Build; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.RandomAccessFile; + +/** + * cpu使用率获取工具类 + * Created by lirui on 2017/8/2. + */ + +public class CPUInfoUtil { + private long lastTotalCpu = 0; + private long lastProcessCpu = 0; + + private final String PackageName; + + private volatile boolean isRunningCPU = false; + private volatile double cpuRate = 0; + + public CPUInfoUtil(Context context) { + if (Build.VERSION.SDK_INT >= 26) { + final String pn = context.getPackageName(); + if (pn.length() <= 16) { + PackageName = pn; + } else { + PackageName = pn.substring(0, 15) + "+"; + } +// Log.e(TAG, "CSVUtils PackageName " + PackageName); + isRunningCPU = true; + CPUInfoThread cpuinfothread = new CPUInfoThread(); + cpuinfothread.start(); + } else { + PackageName = null; + } + } + + public double getProcessCpuUsed() { + if (Build.VERSION.SDK_INT >= 26) { + return cpuRate; + } else { + double pcpu = 0; + double tmp = 1.0; + long nowTotalCpu = getTotalCpu(); + long nowProcessCpu = getMyProcessCpu(); + if (nowTotalCpu != 0 && (nowTotalCpu - lastTotalCpu) != 0) { +// Log.e(TAG, "cpu used nowProcessCpu " + nowProcessCpu + " lastProcessCpu " + lastProcessCpu + " nowTotalCpu " + nowTotalCpu + " lastTotalCpu " + lastTotalCpu); + pcpu = 100 * (tmp * (nowProcessCpu - lastProcessCpu) / (nowTotalCpu - lastTotalCpu)); + } + lastProcessCpu = nowProcessCpu; + lastTotalCpu = nowTotalCpu; + return pcpu < 0 ? 0 : pcpu; + } + } + + public void close() { + if (Build.VERSION.SDK_INT >= 26) { + isRunningCPU = false; + } + } + + private long getTotalCpu() { + String[] cpuInfos = null; + try { + RandomAccessFile reader = null; + reader = new RandomAccessFile("/proc/stat", "r"); + String load = reader.readLine(); + reader.close(); + cpuInfos = load.split(" "); + } catch (IOException e) { + e.printStackTrace(); + return 0; + } + long totalCpu = 0; + try { + totalCpu = Long.parseLong(cpuInfos[2]) + + Long.parseLong(cpuInfos[3]) + Long.parseLong(cpuInfos[4]) + + Long.parseLong(cpuInfos[6]) + Long.parseLong(cpuInfos[5]) + + Long.parseLong(cpuInfos[7]) + Long.parseLong(cpuInfos[8]); + } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + return 0; + } + return totalCpu; + } + + private long getMyProcessCpu() { + String[] cpuInfos = null; + try { + int pid = android.os.Process.myPid(); + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream("/proc/" + pid + "/stat")), 1000); + String load = reader.readLine(); + reader.close(); + cpuInfos = load.split(" "); + } catch (IOException e) { + e.printStackTrace(); + return 0; + } + long appCpuTime = 0; + try { + appCpuTime = Long.parseLong(cpuInfos[13]) + + Long.parseLong(cpuInfos[14]) + Long.parseLong(cpuInfos[15]) + + Long.parseLong(cpuInfos[16]); + } catch (ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + return 0; + } + return appCpuTime; + } + + class CPUInfoThread extends Thread { + + private double allCPU = 0; + + @Override + public void run() { + String line = null; + InputStream is = null; + try { + + Runtime runtime = Runtime.getRuntime(); + Process proc = runtime.exec("top -d 1"); + is = proc.getInputStream(); + + // 换成BufferedReader + BufferedReader buf = new BufferedReader(new InputStreamReader(is)); + do { + line = buf.readLine(); + if (allCPU == 0 && line.contains("user") && line.contains("nice") && line.contains("sys") && line.contains("idle") && line.contains("iow") && line.contains("irq") && line.contains("sirq") && line.contains("host")) { + if (line.indexOf("%cpu ") > 0) + allCPU = Double.parseDouble(line.split("%cpu ")[0]); + if (allCPU == 0) { + String[] s = line.split("%,"); + for (String st : s) { + String[] sts = st.split(" "); + if (sts.length > 0) + allCPU += Double.parseDouble(sts[sts.length - 1]); + } + } + } + // 读取到相应pkgName跳出循环(或者未找到) + if (line == null || line.endsWith(PackageName)) { +// Log.e(TAG, "cpu line : " + line); + String str[] = line.split(" "); + int t = 0; + for (int i = str.length - 1; i > 0; i--) { + if (!str[i].isEmpty() && ++t == 4) { +// Log.e(TAG, "cpu : " + str[i] + " allCPU " + allCPU); + cpuRate = 100 * Double.parseDouble(str[i]) / allCPU; + } + } + continue; + } + } while (isRunningCPU); + + if (is != null) { + buf.close(); + is.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/CSVUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/CSVUtils.java new file mode 100644 index 000000000..e30df5b0a --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/CSVUtils.java @@ -0,0 +1,168 @@ +package com.yunbao.faceunity.utils; + +import android.app.ActivityManager; +import android.content.Context; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Process; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * Created by tujh on 2017/11/2. + */ +public class CSVUtils { + public static final String TAG = CSVUtils.class.getSimpleName(); + /* 每 100 帧统计一次 */ + public static final int FRAME_STEP = 100; + + public static final String COMMA = ","; + + private OutputStreamWriter mStreamWriter; + + private ActivityManager mActivityManager; + + private Handler mHandler; + + private CPUInfoUtil mCPUInfoUtil; + + private int mFrameRate; + private volatile double mCpuUsed; + private volatile double mAverageFps; + private volatile double mAverageRenderTime; + private volatile double mMemory; + private long mSumRenderTimeInNano; + private volatile long mTimestamp; + + public CSVUtils(Context context) { + mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + mCPUInfoUtil = new CPUInfoUtil(context); + + HandlerThread handlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); + handlerThread.start(); + mHandler = new Handler(handlerThread.getLooper()); + } + + public void initHeader(String folderName, StringBuilder headerInfo) { + Log.d(TAG, "initHeader() called with: folderName = [" + folderName + "], headerInfo = [" + headerInfo + "]"); + StringBuilder stringBuilder = new StringBuilder().append("时间").append(COMMA) + .append("帧率").append(COMMA) + .append("渲染耗时").append(COMMA) + .append("CPU").append(COMMA) + .append("内存").append(COMMA); + if (headerInfo != null) { + stringBuilder.append(headerInfo); + } + stringBuilder.append("\n"); + + File file = new File(folderName); + File parentFile = file.getParentFile(); + if (!parentFile.exists()) { + parentFile.mkdirs(); + } + try { + if (!file.exists()) { + file.createNewFile(); + } + mStreamWriter = new OutputStreamWriter(new FileOutputStream(file, false), "GBK"); + } catch (IOException e) { + Log.e(TAG, "CSVUtils: ", e); + } + flush(stringBuilder); + mTimestamp = System.currentTimeMillis(); + } + + public void writeCsv(final StringBuilder extraInfo, long renderTimeInNano) { + if (mStreamWriter == null) { + return; + } + + mSumRenderTimeInNano += renderTimeInNano; + if (mFrameRate % FRAME_STEP == FRAME_STEP - 1) { + mTimestamp = System.currentTimeMillis(); + mAverageFps = FPSUtil.fpsAVG(FRAME_STEP); + mAverageRenderTime = (double) mSumRenderTimeInNano / FRAME_STEP / 1_000_000; + mSumRenderTimeInNano = 0; + mHandler.post(new Runnable() { + @Override + public void run() { + mCpuUsed = mCPUInfoUtil.getProcessCpuUsed(); + mMemory = MemoryInfoUtil.getMemory(mActivityManager.getProcessMemoryInfo(new int[]{Process.myPid()})); + String strCPU = String.format(Locale.getDefault(), "%.2f", mCpuUsed); + String strMemory = String.format(Locale.getDefault(), "%.2f", mMemory); + + StringBuilder stringBuilder = new StringBuilder(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS", Locale.getDefault()); + + stringBuilder.append(dateFormat.format(new Date(mTimestamp))).append(COMMA) + .append(String.format(Locale.getDefault(), "%.2f", mAverageFps)).append(COMMA) + .append(String.format(Locale.getDefault(), "%.2f", mAverageRenderTime)).append(COMMA) + .append(strCPU).append(COMMA) + .append(strMemory).append(COMMA); + + if (extraInfo != null) { + stringBuilder.append(extraInfo); + } + stringBuilder.append("\n"); + flush(stringBuilder); + } + }); + } + mFrameRate++; + } + + private void flush(StringBuilder stringBuilder) { + if (mStreamWriter == null) { + return; + } + try { + mStreamWriter.write(stringBuilder.toString()); + mStreamWriter.flush(); + } catch (IOException e) { + Log.e(TAG, "flush: ", e); + } + } + + public void close() { + Log.d(TAG, "close: "); + mHandler.post(new Runnable() { + @Override + public void run() { + if (mStreamWriter != null) { + try { + mStreamWriter.close(); + mStreamWriter = null; + } catch (IOException e) { + Log.e(TAG, "close: ", e); + } + } + } + }); + mHandler.getLooper().quitSafely(); + mHandler = null; + mCPUInfoUtil.close(); + } + + public double getCpuUsed() { + return mCpuUsed; + } + + public double getMemory() { + return mMemory; + } + + public double getAverageRenderTime() { + return mAverageRenderTime; + } + + public double getAverageFps() { + return mAverageFps; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FPSUtil.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FPSUtil.java new file mode 100644 index 000000000..4a20acafb --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FPSUtil.java @@ -0,0 +1,63 @@ +package com.yunbao.faceunity.utils; + +/** + * FPS工具类 + * Created by tujh on 2018/5/24. + */ +public class FPSUtil { + private static final int NANO_IN_ONE_MILLI_SECOND = 1000000; + private static final int NANO_IN_ONE_SECOND = 1000 * NANO_IN_ONE_MILLI_SECOND; + + private static long sLastFrameTimeStamp = 0; + + /** + * 每帧都计算 + * + * @return + */ + public static double fps() { + long tmp = System.nanoTime(); + double fps = ((double) NANO_IN_ONE_SECOND) / (tmp - sLastFrameTimeStamp); + sLastFrameTimeStamp = tmp; +// Log.e(TAG, "FPS : " + fps); + return fps; + } + + private static long mStartTime = 0; + + /** + * 平均值 + * + * @return + */ + public static double fpsAVG(int time) { + long tmp = System.nanoTime(); + double fps = ((double) NANO_IN_ONE_SECOND) * time / (tmp - mStartTime); + mStartTime = tmp; +// Log.e(TAG, "FPS : " + fps); + return fps; + } + + private long mLimitMinTime = 33333333; + private long mLimitStartTime; + private int mLimitFrameRate; + + public void setLimitMinTime(long limitMinTime) { + mLimitMinTime = limitMinTime; + } + + public void limit() { + try { + if (mLimitFrameRate == 0 || mLimitFrameRate > 600000) { + mLimitStartTime = System.nanoTime(); + mLimitFrameRate = 0; + } + long sleepTime = mLimitMinTime * mLimitFrameRate++ - (System.nanoTime() - mLimitStartTime); + if (sleepTime > 0) { + Thread.sleep(sleepTime / NANO_IN_ONE_MILLI_SECOND, (int) (sleepTime % NANO_IN_ONE_MILLI_SECOND)); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FURenderer.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FURenderer.java new file mode 100644 index 000000000..313aed9eb --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FURenderer.java @@ -0,0 +1,326 @@ +package com.yunbao.faceunity.utils; + +import android.content.Context; +import android.hardware.Camera; + +import com.faceunity.core.callback.OperateCallback; +import com.faceunity.core.entity.FURenderInputData; +import com.faceunity.core.entity.FURenderOutputData; +import com.faceunity.core.enumeration.CameraFacingEnum; +import com.faceunity.core.enumeration.FUAIProcessorEnum; +import com.faceunity.core.enumeration.FUAITypeEnum; +import com.faceunity.core.faceunity.FURenderConfig; +import com.faceunity.core.faceunity.FURenderKit; +import com.faceunity.core.faceunity.FURenderManager; +import com.faceunity.core.utils.CameraUtils; +import com.faceunity.core.utils.FULogger; +import com.yunbao.faceunity.listener.FURendererListener; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; + + +/** + * DESC: + * Created on 2021/4/26 + */ +public class FURenderer extends IFURenderer { + + private static final String TAG = "FURenderer"; + + public volatile static FURenderer INSTANCE; + + public static FURenderer getInstance() { + if (INSTANCE == null) { + synchronized (FURenderer.class) { + if (INSTANCE == null) { + INSTANCE = new FURenderer(); + INSTANCE.mFURenderKit = FURenderKit.getInstance(); + } + } + } + return INSTANCE; + } + + /** + * 状态回调监听 + */ + private FURendererListener mFURendererListener; + + + /* 特效FURenderKit*/ + private FURenderKit mFURenderKit; + + /* AI道具*/ + private String BUNDLE_AI_FACE = "model" + File.separator + "ai_face_processor.bundle"; + private String BUNDLE_AI_HUMAN = "model" + File.separator + "ai_human_processor.bundle"; + + /* GL 线程 ID */ + private Long mGlThreadId = 0L; + /* 任务队列 */ + private ArrayList mEventQueue = new ArrayList<>(16); + private final Object queueLock = new Object(); + /* 渲染开关标识 */ + private volatile boolean mRendererSwitch = false; + /* 清除队列标识 */ + private volatile boolean mClearQueue = false; + + /* 相机角度-朝向映射 */ + private HashMap cameraOrientationMap = new HashMap<>(); + + /*检测类型*/ + private FUAIProcessorEnum aIProcess = FUAIProcessorEnum.FACE_PROCESSOR; + /*检测标识*/ + private int aIProcessTrackStatus = -1; + + public String getVersion() { + return mFURenderKit.getVersion(); + } + + /** + * 初始化鉴权 + * + * @param context + */ + @Override + public void setup(Context context) { + FURenderManager.setKitDebug(FULogger.LogLevel.TRACE); + FURenderManager.setCoreDebug(FULogger.LogLevel.DEBUG); + FURenderManager.registerFURender(context, Authpack.A(), new OperateCallback() { + @Override + public void onSuccess(int i, @NotNull String s) { + if (i == FURenderConfig.OPERATE_SUCCESS_AUTH) { + mFURenderKit.getFUAIController().loadAIProcessor(BUNDLE_AI_FACE, FUAITypeEnum.FUAITYPE_FACEPROCESSOR); + mFURenderKit.getFUAIController().loadAIProcessor(BUNDLE_AI_HUMAN, FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR); + mFURenderKit.setReadBackSync(true); + int cameraFrontOrientation = CameraUtils.INSTANCE.getCameraOrientation(Camera.CameraInfo.CAMERA_FACING_FRONT); + int cameraBackOrientation = CameraUtils.INSTANCE.getCameraOrientation(Camera.CameraInfo.CAMERA_FACING_BACK); + cameraOrientationMap.put(cameraFrontOrientation, CameraFacingEnum.CAMERA_FRONT); + cameraOrientationMap.put(cameraBackOrientation, CameraFacingEnum.CAMERA_BACK); + } + } + + @Override + public void onFail(int i, @NotNull String s) { + } + }); + } + + /** + * 开启合成状态 + */ + @Override + public void prepareRenderer(FURendererListener mFURendererListener) { + this.mFURendererListener = mFURendererListener; + mRendererSwitch = true; + mClearQueue = false; + queueEvent(() -> mGlThreadId = Thread.currentThread().getId()); + mFURendererListener.onPrepare(); + } + + + /** + * 双输入接口,输入 buffer 和 texture,必须在具有 GL 环境的线程调用 + * 由于省去数据拷贝,性能相对最优,优先推荐使用。 + * 缺点是无法保证 buffer 和纹理对齐,可能出现点位和效果对不上的情况。 + * + * @param img NV21 buffer + * @param texId 纹理 ID + * @param width 宽 + * @param height 高 + * @return + */ + @Override + public int onDrawFrameDualInput(byte[] img, int texId, int width, int height) { + prepareDrawFrame(); + if (!mRendererSwitch) { + return texId; + } + FURenderInputData inputData = new FURenderInputData(width, height); + if (img != null) { + inputData.setImageBuffer(new FURenderInputData.FUImageBuffer(inputBufferType, img)); + } + if (texId != -1) { + inputData.setTexture(new FURenderInputData.FUTexture(inputTextureType, texId)); + } + FURenderInputData.FURenderConfig config = inputData.getRenderConfig(); + config.setExternalInputType(externalInputType); + config.setInputOrientation(inputOrientation); + config.setDeviceOrientation(deviceOrientation); + config.setInputBufferMatrix(inputBufferMatrix); + config.setInputTextureMatrix(inputTextureMatrix); + config.setOutputMatrix(outputMatrix); + config.setCameraFacing(cameraFacing); + FURenderOutputData outputData = mFURenderKit.renderWithInput(inputData); + if (outputData.getTexture() != null && outputData.getTexture().getTexId() > 0) { + return outputData.getTexture().getTexId(); + } + return texId; + } + + public FURenderOutputData onDrawFrameInputWithReturn(byte[] img, int width, int height) { + prepareDrawFrame(); + if (!mRendererSwitch) { + return null ; + } + FURenderInputData inputData = new FURenderInputData(width, height); + if (img != null) { + inputData.setImageBuffer(new FURenderInputData.FUImageBuffer(inputBufferType, img)); + } + FURenderInputData.FURenderConfig config = inputData.getRenderConfig(); + config.setExternalInputType(externalInputType); + config.setInputOrientation(inputOrientation); + config.setDeviceOrientation(deviceOrientation); + config.setInputBufferMatrix(inputBufferMatrix); + config.setInputTextureMatrix(inputTextureMatrix); + config.setCameraFacing(cameraFacing); + config.setNeedBufferReturn(true); + config.setOutputMatrix(outputMatrix); + return mFURenderKit.renderWithInput(inputData); + } + + /** + * 类似 GLSurfaceView 的 queueEvent 机制,把任务抛到 GL 线程执行。 + * + * @param runnable + */ + @Override + public void queueEvent(Runnable runnable) { + if (runnable == null) { + return; + } + if (mGlThreadId == Thread.currentThread().getId()) { + runnable.run(); + } else { + synchronized (queueLock) { + mEventQueue.add(runnable); + } + } + } + + + /** + * 释放资源 + */ + @Override + public void release() { + mRendererSwitch = false; + mClearQueue = true; + mGlThreadId = 0L; + synchronized (queueLock) { + mEventQueue.clear(); + mClearQueue = false; + mFURenderKit.release(); + aIProcessTrackStatus = -1; + if (mFURendererListener != null) { + mFURendererListener.onRelease(); + mFURendererListener = null; + } + } + } + + + /** + * 渲染前置执行 + * + * @return + */ + private void prepareDrawFrame() { + benchmarkFPS(); + + // 执行任务队列中的任务 + synchronized (queueLock) { + while (!mEventQueue.isEmpty() && !mClearQueue) { + mEventQueue.remove(0).run(); + } + } + // AI检测 + trackStatus(); + } + + /** + * 设置检测类型 + * + * @param type + */ + @Override + public void setAIProcessTrackType(FUAIProcessorEnum type) { + aIProcess = type; + aIProcessTrackStatus = -1; + } + + /** + * 设置FPS检测 + * + * @param enable + */ + @Override + public void setMarkFPSEnable(boolean enable) { + mIsRunBenchmark = enable; + } + + @Override + public void setInputOrientation(int inputOrientation) { + if (cameraOrientationMap.containsKey(inputOrientation)) { + setCameraFacing(cameraOrientationMap.get(inputOrientation)); + } + super.setInputOrientation(inputOrientation); + } + + /** + * AI识别数目检测 + */ + private void trackStatus() { + int trackCount; + if (aIProcess == FUAIProcessorEnum.HAND_GESTURE_PROCESSOR) { + trackCount = mFURenderKit.getFUAIController().handProcessorGetNumResults(); + } else if (aIProcess == FUAIProcessorEnum.HUMAN_PROCESSOR) { + trackCount = mFURenderKit.getFUAIController().humanProcessorGetNumResults(); + } else { + trackCount = mFURenderKit.getFUAIController().isTracking(); + } + if (trackCount != aIProcessTrackStatus) { + aIProcessTrackStatus = trackCount; + } else { + return; + } + if (mFURendererListener != null) { + mFURendererListener.onTrackStatusChanged(aIProcess, trackCount); + } + } + //endregion AI识别 + + //------------------------------FPS 渲染时长回调相关定义------------------------------------ + + private static final int NANO_IN_ONE_MILLI_SECOND = 1_000_000; + private static final int NANO_IN_ONE_SECOND = 1_000_000_000; + private static final int FRAME_COUNT = 20; + private boolean mIsRunBenchmark = false; + private int mCurrentFrameCount; + private long mLastFrameTimestamp; + private long mSumCallTime; + private long mCallStartTime; + + private void benchmarkFPS() { + if (!mIsRunBenchmark) { + return; + } + if (++mCurrentFrameCount == FRAME_COUNT) { + long tmp = System.nanoTime(); + double fps = (double) NANO_IN_ONE_SECOND / ((double) (tmp - mLastFrameTimestamp) / FRAME_COUNT); + double renderTime = (double) mSumCallTime / FRAME_COUNT / NANO_IN_ONE_MILLI_SECOND; + mLastFrameTimestamp = tmp; + mSumCallTime = 0; + mCurrentFrameCount = 0; + + if (mFURendererListener != null) { + mFURendererListener.onFpsChanged(fps, renderTime); + } + } + } + + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FUUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FUUtils.java new file mode 100644 index 000000000..2194ea131 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FUUtils.java @@ -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 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 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, ""); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceSPUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceSPUtils.java new file mode 100644 index 000000000..f4ba6d5b0 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceSPUtils.java @@ -0,0 +1,41 @@ +package com.yunbao.faceunity.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.yunbao.common.CommonAppContext; + +public class FaceSPUtils { + private static FaceSPUtils utils; + private SharedPreferences mSharedPreferences; + private FaceSPUtils(){ + mSharedPreferences = CommonAppContext.sInstance.getSharedPreferences("FaceUnityConfig", Context.MODE_PRIVATE); + } + public static FaceSPUtils getInstance(){ + if(utils==null){ + utils=new FaceSPUtils(); + } + return utils; + } + public void saveString(String key,String value){ + mSharedPreferences.edit().putString(key,value).apply(); + } + public String getString(String key){ + return mSharedPreferences.getString(key,null); + } + public boolean saveBool(String key,boolean value){ + return mSharedPreferences.getBoolean(key,false); + } + + public void del(String key) { + mSharedPreferences.edit().remove(key).apply(); + } + + public void delStart(String key){ + for (String _key : mSharedPreferences.getAll().keySet()) { + if(_key.startsWith(key)){ + mSharedPreferences.edit().remove(key).apply(); + } + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceUnityConfig.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceUnityConfig.java new file mode 100644 index 000000000..b6a2d51de --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceUnityConfig.java @@ -0,0 +1,127 @@ +package com.yunbao.faceunity.utils; + +import android.app.Application; +import android.os.Environment; + + +import java.io.File; + +/** + * 一些配置参数 + * DESC: + * Created on 2021/3/1 + */ +public class FaceUnityConfig { + + /************************** 算法Model ******************************/ + // 人脸识别 + public static String BUNDLE_AI_FACE = "model" + File.separator + "ai_face_processor.bundle"; + // 手势 + public static String BUNDLE_AI_HAND = "model" + File.separator + "ai_hand_processor.bundle"; + + //获取人体bundle + public static String getAIHumanBundle() { + if (FaceUnityConfig.DEVICE_LEVEL > FuDeviceUtils.DEVICE_LEVEL_MID) + return BUNDLE_AI_HUMAN_GPU; + else + return BUNDLE_AI_HUMAN; + } + + // 人体 + public static String BUNDLE_AI_HUMAN = "model" + File.separator + "ai_human_processor.bundle"; + // 人体 + public static String BUNDLE_AI_HUMAN_GPU = "model" + File.separator + "ai_human_processor_gpu.bundle"; + // 头发 + public static String BUNDLE_AI_HAIR_SEG = "model" + File.separator + "ai_hairseg.bundle"; + // 舌头 + public static String BUNDLE_AI_TONGUE = "graphics" + File.separator + "tongue.bundle"; + + /************************** 业务道具存储 ******************************/ + // 美颜 + public static String BUNDLE_FACE_BEAUTIFICATION = "graphics" + File.separator + "face_beautification.bundle"; + + // 美妆 + public static String BUNDLE_FACE_MAKEUP = "graphics" + File.separator + "face_makeup.bundle"; + // 美妆根目录 + private static String MAKEUP_RESOURCE_DIR = "makeup" + File.separator; + //美妆单项颜色组合文件 + public static String MAKEUP_RESOURCE_COLOR_SETUP_JSON = MAKEUP_RESOURCE_DIR + "color_setup.json"; + // 美妆参数配置文件目录 + public static String MAKEUP_RESOURCE_JSON_DIR = MAKEUP_RESOURCE_DIR + "config_json" + File.separator; + //美妆组合妆句柄文件目录 + public static String MAKEUP_RESOURCE_COMBINATION_BUNDLE_DIR = MAKEUP_RESOURCE_DIR + "combination_bundle" + File.separator;// + //美妆妆容单项句柄文件目录 + public static String MAKEUP_RESOURCE_ITEM_BUNDLE_DIR = MAKEUP_RESOURCE_DIR + "item_bundle" + File.separator; + + // 美体 + public static String BUNDLE_BODY_BEAUTY = "graphics" + File.separator + "body_slim.bundle"; + + //动漫滤镜 + public static String BUNDLE_ANIMATION_FILTER = "graphics" + File.separator + "fuzzytoonfilter.bundle"; + + // 美发正常色 + public static String BUNDLE_HAIR_NORMAL = "hair_seg" + File.separator + "hair_normal.bundle"; + // 美发渐变色 + public static String BUNDLE_HAIR_GRADIENT = "hair_seg" + File.separator + "hair_gradient.bundle"; + // 轻美妆 + public static String BUNDLE_LIGHT_MAKEUP = "light_makeup" + File.separator + "light_makeup.bundle"; + + // 海报换脸 + public static String BUNDLE_POSTER_CHANGE_FACE = "change_face" + File.separator + "change_face.bundle"; + + // 绿幕抠像 + public static String BUNDLE_BG_SEG_GREEN = "bg_seg_green" + File.separator + "green_screen.bundle"; + + // 3D抗锯齿 + public static String BUNDLE_ANTI_ALIASING = "graphics" + File.separator + "fxaa.bundle"; + + // 人像分割 + public static String BUNDLE_BG_SEG_CUSTOM = "effect" + File.separator + "segment" + File.separator + "bg_segment.bundle"; + + //mask bundle + public static String BUNDLE_LANDMARKS = "effect" + File.separator + "landmarks.bundle"; + + //设备等级默认为中级 + public static int DEVICE_LEVEL = FuDeviceUtils.DEVICE_LEVEL_HIGH; + + //人脸置信度 标准 + public static float FACE_CONFIDENCE_SCORE = 0.95f; + + //测试使用 -> 是否开启人脸点位,目前仅在美颜,美妆 情况下使用 + public static boolean IS_OPEN_LAND_MARK = false; + + //设备名称 + public static String DEVICE_NAME = ""; + + //是否开启日志重定向到文件 + public static boolean OPEN_FILE_LOG = false; + //TAG + public static final String APP_NAME = "KotlinFaceUnityDemo"; + //文件夹路径 + public static String OPEN_FILE_PATH = Environment.getExternalStoragePublicDirectory("") + File.separator + "FaceUnity" + File.separator + APP_NAME + File.separator; + //文件夹名称 + public static String OPEN_FILE_NAME = "openFile.txt"; + //文件大小 + public static int OPEN_FILE_MAX_SIZE = 100 * 1024 * 1024; + //文件数量 + public static int OPEN_FILES = 100; + + //timeProfile是否开启 + public static boolean OPEN_TIME_PROFILE_LOG = false; + //timeProfile文件夹路径 + public static String OPEN_TIME_PROFILE_PATH = Environment.getExternalStoragePublicDirectory("") + File.separator + "FaceUnity" + File.separator + APP_NAME + File.separator; + + //是否开启美颜序列化到磁盘 + public static boolean OPEN_FACE_BEAUTY_TO_FILE = true; + + //获取缓存路径 + public static String cacheFilePath(Application application){ + return application.getCacheDir() + File.separator + "attribute"; + } + + //绿幕背景切换的时候跳过的帧数 + public static final int BG_GREEN_FILTER_FRAME = 1; + + //测试用是否展示效果还原按钮 + public static final boolean IS_SHOW_RESET_BUTTON = false; +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceUnityData.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceUnityData.java new file mode 100644 index 000000000..bb9cc8a03 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FaceUnityData.java @@ -0,0 +1,7 @@ +package com.yunbao.faceunity.utils; + +import android.content.Context; + +public class FaceUnityData { + public static Context mApplication; +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FileUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FileUtils.java new file mode 100644 index 000000000..ae38e1cf0 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FileUtils.java @@ -0,0 +1,577 @@ +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.getFilesDir(); + return fileDir; + } + + /** + * 应用下缓存文件目录 + * + * @return + */ + public static File getCacheFileDir(Context context) { + File fileDir = context.getCacheDir(); + if (fileDir == null) { + fileDir = context.getFilesDir(); + } + return fileDir; + } + + /** + * 获取当前时间日期 + * + * @return + */ + public static String getDateTimeString() { + GregorianCalendar now = new GregorianCalendar(); + return new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.US).format(now.getTime()); + } + + + /** + * 获取视频缓存文件 + * + * @param context Context + * @return File + */ + public static File getCacheVideoFile(Context context) { + File fileDir = new File(getExternalFileDir(context).getPath() + File.separator + "video"); + if (!fileDir.exists()) { + fileDir.mkdirs(); + } + File file = new File(fileDir, getCurrentVideoFileName()); + if (file.exists()) { + file.delete(); + } + return file; + } + + /** + * 构造视频文件名称 + * + * @return + */ + public static String getCurrentVideoFileName() { + return getDateTimeString() + VIDEO_FORMAT_MP4; + } + + + /** + * 构造图片文件名称 + * + * @return + */ + public static String getCurrentPhotoFileName() { + return getDateTimeString() + IMAGE_FORMAT_JPG; + } + + + /** + * Bitmap保存到本地 + * + * @param context Context + * @param bitmap Bitmap + * @return String? + */ + public static String addBitmapToExternal(Context context, Bitmap bitmap) { + if (bitmap == null) return null; + File fileDir = new File(getExternalFileDir(context).getPath() + File.separator + "photo"); + if (!fileDir.exists()) { + fileDir.mkdirs(); + } + File file = new File(fileDir, getCurrentPhotoFileName()); + if (file.exists()) { + file.delete(); + } + try { + FileOutputStream fos = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); + fos.flush(); + fos.close(); + return file.getAbsolutePath(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 将Bitmap文件保存到相册 + * + * @param bitmap Bitmap + */ + public static String addBitmapToAlbum(Context context, Bitmap bitmap) { + if (bitmap == null) return null; + FileOutputStream fos = null; + File dcimFile; + + File fileDir = new File(exportVideoDir); + if (fileDir.exists()) { + dcimFile = new File(exportVideoDir, getCurrentPhotoFileName()); + } else { + dcimFile = new File(photoFilePath, getCurrentPhotoFileName()); + } + if (dcimFile.exists()) { + dcimFile.delete(); + } + try { + fos = new FileOutputStream(dcimFile); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); + fos.flush(); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(dcimFile))); + return dcimFile.getAbsolutePath(); + } + + + /** + * 将视频文件保存到相册 + * + * @param videoFile File + * @return Uri? + */ + + public static String addVideoToAlbum(Context context, File videoFile) { + if (videoFile == null) return null; + File fileDir = new File(exportVideoDir); + File dcimFile; + if (fileDir.exists()) { + dcimFile = new File(exportVideoDir, getCurrentVideoFileName()); + } else { + dcimFile = new File(videoFilePath, getCurrentVideoFileName()); + } + if (dcimFile.exists()) { + dcimFile.delete(); + } + BufferedInputStream bis = null; + BufferedOutputStream bos = null; + try { + bis = new BufferedInputStream(new FileInputStream(videoFile)); + bos = new BufferedOutputStream(new FileOutputStream(dcimFile)); + byte[] bytes = new byte[1024 * 10]; + int length; + while ((length = bis.read(bytes)) != -1) { + bos.write(bytes, 0, length); + } + bos.flush(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } finally { + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (bos != null) { + try { + bos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(dcimFile))); + return dcimFile.getAbsolutePath(); + } + + + /** + * 将Assets文件拷贝到应用作用域存储 + * + * @param context Context + * @param assetsPath String + * @param fileName String + */ + public static String copyAssetsToExternalFilesDir(Context context, String assetsPath, String fileName) { + File fileDir = new File(getExternalFileDir(context).getPath() + File.separator + "assets"); + if (!fileDir.exists()) { + fileDir.mkdirs(); + } + File file = new File(fileDir, fileName); + if (file.exists()) { + return file.getAbsolutePath(); + } + try { + InputStream inputStream = context.getAssets().open(assetsPath); + FileOutputStream fos = new FileOutputStream(file); + BufferedInputStream bis = new BufferedInputStream(inputStream); + BufferedOutputStream bos = new BufferedOutputStream(fos); + byte[] byteArray = new byte[1024]; + int bytes = bis.read(byteArray); + while (bytes > 0) { + bos.write(byteArray, 0, bytes); + bos.flush(); + bytes = bis.read(byteArray); + } + bos.close(); + fos.close(); + return file.getAbsolutePath(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 获取Uri文件绝对路径 + * + * @param context: Context + * @param uri Uri + * @return String + */ + public static String getFilePathByUri(Context context, Uri uri) { + if (uri == null) return null; + return Uri2PathUtil.getRealPathFromUri(context, uri); + } + + private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { + Cursor cursor = null; + String[] projection = new String[]{MediaStore.Images.Media.DATA}; + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + if (cursor != null && cursor.moveToFirst()) { + int index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + return cursor.getString(index); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + + /** + * load本地图片 + * + * @param path + * @param screenWidth + * @return + */ + public static Bitmap loadBitmapFromExternal(String path, int screenWidth) { + BitmapFactory.Options opt = new BitmapFactory.Options(); + opt.inJustDecodeBounds = true; + BitmapFactory.decodeFile(path, opt); + int picWidth = opt.outWidth; + int picHeight = opt.outHeight; + opt.inSampleSize = 1; + // 根据屏的大小和图片大小计算出缩放比例 + if (picWidth > picHeight) { + if (picHeight > screenWidth) { + opt.inSampleSize = picHeight / screenWidth; + } + } else { + if (picWidth > screenWidth) { + opt.inSampleSize = picWidth / screenWidth; + } + } + opt.inJustDecodeBounds = false; + Bitmap bitmap = BitmapFactory.decodeFile(path, opt); + int orientation = getPhotoOrientation(path); + bitmap = rotateBitmap(bitmap, orientation); + return bitmap; + } + + /** + * load本地图片 + * + * @param path String + * @param screenWidth Int + * @param screenHeight Int + * @return Bitmap + */ + public static Bitmap loadBitmapFromExternal(String path, int screenWidth, int screenHeight) { + BitmapFactory.Options opt = new BitmapFactory.Options(); + opt.inJustDecodeBounds = true; + BitmapFactory.decodeFile(path, opt); + int picWidth = opt.outWidth; + int picHeight = opt.outHeight; + int inSampleSize = 1; + // 根据屏的大小和图片大小计算出缩放比例 + if (picHeight > screenHeight || picWidth > screenWidth) { + int halfHeight = picHeight / 2; + int halfWidth = picWidth / 2; + while (halfHeight / inSampleSize >= screenHeight && halfWidth / inSampleSize >= screenWidth) { + inSampleSize *= 2; + } + } + opt.inSampleSize = inSampleSize; + opt.inJustDecodeBounds = false; + Bitmap bitmap = BitmapFactory.decodeFile(path, opt); + int orientation = getPhotoOrientation(path); + bitmap = rotateBitmap(bitmap, orientation); + return bitmap; + } + + + /** + * 旋转 Bitmap + * + * @param bitmap + * @param orientation + * @return + */ + private static Bitmap rotateBitmap(Bitmap bitmap, int orientation) { + if (orientation == 90 || orientation == 180 || orientation == 270) { + Matrix matrix = new Matrix(); + matrix.postRotate((float) orientation); + bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); + } + return bitmap; + } + + + /** + * 获取图片的方向 + * + * @param path + * @return + */ + public static int getPhotoOrientation(String path) { + int orientation = 0; + int tagOrientation = 0; + try { + tagOrientation = new ExifInterface(path).getAttributeInt(ExifInterface.TAG_ORIENTATION, -1); + } catch (IOException e) { + e.printStackTrace(); + } + switch (tagOrientation) { + case ExifInterface.ORIENTATION_ROTATE_90: + orientation = 90; + break; + + case ExifInterface.ORIENTATION_ROTATE_180: + orientation = 180; + break; + + case ExifInterface.ORIENTATION_ROTATE_270: + orientation = 270; + break; + } + return orientation; + } + + + /** + * 选中图片 + * + * @param activity Activity + */ + public static void pickImageFile(Activity activity, int requestCode) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("image/*"); + activity.startActivityForResult(intent, requestCode); + } + + /** + * 选中视频 + * + * @param activity Activity + * 回调可参考下方 + */ + public static void pickVideoFile(Activity activity, int requestCode) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("video/*"); + activity.startActivityForResult(intent, requestCode); + } + + /** + * 根据路径获取InputStream + * + * @param context Context + * @param path String + * @return InputStream? + */ + public static InputStream readInputStreamByPath(Context context, String path) { + if (path == null || path.trim().length() == 0) + return null; + InputStream inputStream = null; + try { + inputStream = context.getAssets().open(path); + } catch (IOException e1) { + try { + inputStream = new FileInputStream(path); + } catch (IOException e2) { + e2.printStackTrace(); + } + } + return inputStream; + } + + /** + * 相机byte转bitmap + * + * @param buffer + * @param width + * @param height + * @return + */ + public static Bitmap bytes2Bitmap(byte[] buffer, int width, int height) { + YuvImage yuvimage = new YuvImage(buffer, ImageFormat.NV21, width, height, null);//20、20分别是图的宽度与高度 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + yuvimage.compressToJpeg(new Rect(0, 0, width, height), 80, baos);//80--JPG图片的质量[0-100],100最高 + byte[] jdata = baos.toByteArray(); + return BitmapFactory.decodeByteArray(baos.toByteArray(), 0, jdata.length); + } + + /** + * 遍历一个文件夹获取改文件夹下所有文件名 + * @param path + * @return + */ + public static ArrayList getFileList(String path) { + ArrayList 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; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FuDeviceUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FuDeviceUtils.java new file mode 100644 index 000000000..79a58785e --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/FuDeviceUtils.java @@ -0,0 +1,720 @@ +package com.yunbao.faceunity.utils; + +import static android.content.Context.MODE_PRIVATE; + +import android.annotation.TargetApi; +import android.app.ActivityManager; +import android.content.Context; +import android.content.SharedPreferences; +import android.opengl.GLES20; +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; + +import com.faceunity.core.faceunity.OffLineRenderHandler; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * 工具类 + */ +public class FuDeviceUtils { + + public static final String TAG = "FuDeviceUtils"; + public static final String DEVICE_LEVEL = "device_level"; + + public static final int DEVICE_LEVEL_HIGH = 2; + public static final int DEVICE_LEVEL_MID = 1; + public static final int DEVICE_LEVEL_LOW = 0; + + /** + * The default return value of any method in this class when an + * error occurs or when processing fails (Currently set to -1). Use this to check if + * the information about the device in question was successfully obtained. + */ + public static final int DEVICEINFO_UNKNOWN = -1; + + private static final FileFilter CPU_FILTER = new FileFilter() { + @Override + public boolean accept(File pathname) { + String path = pathname.getName(); + //regex is slow, so checking char by char. + if (path.startsWith("cpu")) { + for (int i = 3; i < path.length(); i++) { + if (!Character.isDigit(path.charAt(i))) { + return false; + } + } + return true; + } + return false; + } + }; + + + /** + * Calculates the total RAM of the device through Android API or /proc/meminfo. + * + * @param c - Context object for current running activity. + * @return Total RAM that the device has, or DEVICEINFO_UNKNOWN = -1 in the event of an error. + */ + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + public static long getTotalMemory(Context c) { + // memInfo.totalMem not supported in pre-Jelly Bean APIs. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo(); + ActivityManager am = (ActivityManager) c.getSystemService(Context.ACTIVITY_SERVICE); + am.getMemoryInfo(memInfo); + if (memInfo != null) { + return memInfo.totalMem; + } else { + return DEVICEINFO_UNKNOWN; + } + } else { + long totalMem = DEVICEINFO_UNKNOWN; + try { + FileInputStream stream = new FileInputStream("/proc/meminfo"); + try { + totalMem = parseFileForValue("MemTotal", stream); + totalMem *= 1024; + } finally { + stream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return totalMem; + } + } + + /** + * Method for reading the clock speed of a CPU core on the device. Will read from either + * {@code /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq} or {@code /proc/cpuinfo}. + * + * @return Clock speed of a core on the device, or -1 in the event of an error. + */ + public static int getCPUMaxFreqKHz() { + int maxFreq = DEVICEINFO_UNKNOWN; + try { + for (int i = 0; i < getNumberOfCPUCores(); i++) { + String filename = + "/sys/devices/system/cpu/cpu" + i + "/cpufreq/cpuinfo_max_freq"; + File cpuInfoMaxFreqFile = new File(filename); + if (cpuInfoMaxFreqFile.exists() && cpuInfoMaxFreqFile.canRead()) { + byte[] buffer = new byte[128]; + FileInputStream stream = new FileInputStream(cpuInfoMaxFreqFile); + try { + stream.read(buffer); + int endIndex = 0; + //Trim the first number out of the byte buffer. + while (Character.isDigit(buffer[endIndex]) && endIndex < buffer.length) { + endIndex++; + } + String str = new String(buffer, 0, endIndex); + Integer freqBound = Integer.parseInt(str); + if (freqBound > maxFreq) { + maxFreq = freqBound; + } + } catch (NumberFormatException e) { + //Fall through and use /proc/cpuinfo. + } finally { + stream.close(); + } + } + } + if (maxFreq == DEVICEINFO_UNKNOWN) { + FileInputStream stream = new FileInputStream("/proc/cpuinfo"); + try { + int freqBound = parseFileForValue("cpu MHz", stream); + freqBound *= 1024; //MHz -> kHz + if (freqBound > maxFreq) maxFreq = freqBound; + } finally { + stream.close(); + } + } + } catch (IOException e) { + maxFreq = DEVICEINFO_UNKNOWN; //Fall through and return unknown. + } + return maxFreq; + } + + /** + * Reads the number of CPU cores from the first available information from + * {@code /sys/devices/system/cpu/possible}, {@code /sys/devices/system/cpu/present}, + * then {@code /sys/devices/system/cpu/}. + * + * @return Number of CPU cores in the phone, or DEVICEINFO_UKNOWN = -1 in the event of an error. + */ + public static int getNumberOfCPUCores() { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { + // Gingerbread doesn't support giving a single application access to both cores, but a + // handful of devices (Atrix 4G and Droid X2 for example) were released with a dual-core + // chipset and Gingerbread; that can let an app in the background run without impacting + // the foreground application. But for our purposes, it makes them single core. + return 1; + } + int cores; + try { + cores = getCoresFromFileInfo("/sys/devices/system/cpu/possible"); + if (cores == DEVICEINFO_UNKNOWN) { + cores = getCoresFromFileInfo("/sys/devices/system/cpu/present"); + } + if (cores == DEVICEINFO_UNKNOWN) { + cores = new File("/sys/devices/system/cpu/").listFiles(CPU_FILTER).length; + } + } catch (SecurityException e) { + cores = DEVICEINFO_UNKNOWN; + } catch (NullPointerException e) { + cores = DEVICEINFO_UNKNOWN; + } + return cores; + } + + /** + * Tries to read file contents from the file location to determine the number of cores on device. + * + * @param fileLocation The location of the file with CPU information + * @return Number of CPU cores in the phone, or DEVICEINFO_UKNOWN = -1 in the event of an error. + */ + private static int getCoresFromFileInfo(String fileLocation) { + InputStream is = null; + try { + is = new FileInputStream(fileLocation); + BufferedReader buf = new BufferedReader(new InputStreamReader(is)); + String fileContents = buf.readLine(); + buf.close(); + return getCoresFromFileString(fileContents); + } catch (IOException e) { + return DEVICEINFO_UNKNOWN; + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // Do nothing. + } + } + } + } + + /** + * Converts from a CPU core information format to number of cores. + * + * @param str The CPU core information string, in the format of "0-N" + * @return The number of cores represented by this string + */ + private static int getCoresFromFileString(String str) { + if (str == null || !str.matches("0-[\\d]+$")) { + return DEVICEINFO_UNKNOWN; + } + return Integer.valueOf(str.substring(2)) + 1; + } + + /** + * Helper method for reading values from system files, using a minimised buffer. + * + * @param textToMatch - Text in the system files to read for. + * @param stream - FileInputStream of the system file being read from. + * @return A numerical value following textToMatch in specified the system file. + * -1 in the event of a failure. + */ + private static int parseFileForValue(String textToMatch, FileInputStream stream) { + byte[] buffer = new byte[1024]; + try { + int length = stream.read(buffer); + for (int i = 0; i < length; i++) { + if (buffer[i] == '\n' || i == 0) { + if (buffer[i] == '\n') i++; + for (int j = i; j < length; j++) { + int textIndex = j - i; + //Text doesn't match query at some point. + if (buffer[j] != textToMatch.charAt(textIndex)) { + break; + } + //Text matches query here. + if (textIndex == textToMatch.length() - 1) { + return extractValue(buffer, j); + } + } + } + } + } catch (IOException e) { + //Ignore any exceptions and fall through to return unknown value. + } catch (NumberFormatException e) { + } + return DEVICEINFO_UNKNOWN; + } + + /** + * Helper method used by {@link #parseFileForValue(String, FileInputStream) parseFileForValue}. Parses + * the next available number after the match in the file being read and returns it as an integer. + * + * @param index - The index in the buffer array to begin looking. + * @return The next number on that line in the buffer, returned as an int. Returns + * DEVICEINFO_UNKNOWN = -1 in the event that no more numbers exist on the same line. + */ + private static int extractValue(byte[] buffer, int index) { + while (index < buffer.length && buffer[index] != '\n') { + if (Character.isDigit(buffer[index])) { + int start = index; + index++; + while (index < buffer.length && Character.isDigit(buffer[index])) { + index++; + } + String str = new String(buffer, 0, start, index - start); + return Integer.parseInt(str); + } + index++; + } + return DEVICEINFO_UNKNOWN; + } + + /** + * 获取当前剩余内存(ram) + * + * @param context + * @return + */ + public static long getAvailMemory(Context context) { + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); + am.getMemoryInfo(mi); + return mi.availMem; + } + + /** + * 获取厂商信息 + * + * @return + */ + public static String getBrand() { + return Build.BRAND; + } + + /** + * 获取手机机型 + * + * @return + */ + public static String getModel() { + return Build.MODEL; + } + + /** + * 获取硬件信息(cpu型号) + * + * @return + */ + public static String getHardWare() { + try { + FileReader fr = new FileReader("/proc/cpuinfo"); + BufferedReader br = new BufferedReader(fr); + String text; + String last = ""; + while ((text = br.readLine()) != null) { + last = text; + } + //一般机型的cpu型号都会在cpuinfo文件的最后一行 + if (last.contains("Hardware")) { + String[] hardWare = last.split(":\\s+", 2); + return hardWare[1]; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return Build.HARDWARE; + } + + /** + * Level judgement based on current memory and CPU. + * + * @param context - Context object. + * @return + */ + public static int judgeDeviceLevel(Context context) { + //加一个sp读取 和 设置 + int cacheDeviceLevel = getCacheDeviceLevel(context); + if (cacheDeviceLevel > -1) { + return cacheDeviceLevel; + } + + int level; + //有一些设备不符合下述的判断规则,则走一个机型判断模式 + int specialDevice = judgeDeviceLevelInDeviceName(); + if (specialDevice >= 0) return specialDevice; + + int ramLevel = judgeMemory(context); + int cpuLevel = judgeCPU(); + if (ramLevel == 0 || ramLevel == 1 || cpuLevel == 0) { + level = DEVICE_LEVEL_LOW; + } else { + if (cpuLevel > 1) { + level = DEVICE_LEVEL_HIGH; + } else { + level = DEVICE_LEVEL_MID; + } + } + Log.d(TAG,"DeviceLevel: " + level); + saveCacheDeviceLevel(context,level); + return level; + } + + /** + * Level judgement based on current GPU. + * 需要GL环境 + * @return + */ + public static int judgeDeviceLevelGPU(Context context) { + int cacheDeviceLevel = getCacheDeviceLevel(context); + if (cacheDeviceLevel > -1) { + return cacheDeviceLevel; + } + + OffLineRenderHandler.getInstance().onResume(); + CountDownLatch countDownLatch = new CountDownLatch(1); + //加一个sp读取 和 设置 + final int[] level = {-1}; + //有一些设备不符合下述的判断规则,则走一个机型判断模式 + OffLineRenderHandler.getInstance().queueEvent(() -> { + try { + //高低端名单 + int specialDevice = judgeDeviceLevelInDeviceName(); + level[0] = specialDevice; + if (specialDevice >= 0) return; + + String glRenderer = GLES20.glGetString(GLES20.GL_RENDERER); //GPU 渲染器 + String glVendor = GLES20.glGetString(GLES20.GL_VENDOR); //GPU 供应商 + int GPUVersion; + if ("Qualcomm".equals(glVendor)) { + //高通 + if (glRenderer != null && glRenderer.startsWith("Adreno")) { + //截取后面的数字 + String GPUVersionStr = glRenderer.substring(glRenderer.lastIndexOf(" ") + 1); + try { + GPUVersion = Integer.parseInt(GPUVersionStr); + } catch (NumberFormatException e) { + e.printStackTrace(); + //可能是后面还包含了非数字的东西,那么截取三位 + String GPUVersionStrNew = GPUVersionStr.substring(0,3); + GPUVersion = Integer.parseInt(GPUVersionStrNew); + } + + if (GPUVersion >= 512) { + level[0] = DEVICE_LEVEL_HIGH; + } else { + level[0] = DEVICE_LEVEL_MID; + } + countDownLatch.countDown(); + } + } else if ("ARM".equals(glVendor)) { + //ARM + if (glRenderer != null && glRenderer.startsWith("Mali")) { + //截取-后面的东西 + String GPUVersionStr = glRenderer.substring(glRenderer.lastIndexOf("-") + 1); + String strStart = GPUVersionStr.substring(0, 1); + String strEnd = GPUVersionStr.substring(1); + try { + GPUVersion = Integer.parseInt(strEnd); + } catch (NumberFormatException e) { + e.printStackTrace(); + //可能是后面还包含了非数字的东西,那么截取三位 + String strEndNew = strEnd.substring(0,2); + GPUVersion = Integer.parseInt(strEndNew); + } + + if ("G".equals(strStart)) { + if (GPUVersion >= 51) { + level[0] = DEVICE_LEVEL_HIGH; + } else { + level[0] = DEVICE_LEVEL_MID; + } + } else if ("T".equals(strStart)) { + if (GPUVersion > 880) { + level[0] = DEVICE_LEVEL_HIGH; + } else { + level[0] = DEVICE_LEVEL_MID; + } + } + countDownLatch.countDown(); + } + } + } catch (Exception e) { + e.printStackTrace(); + level[0] = -1; + countDownLatch.countDown(); + } + }); + + try { + countDownLatch.await(200,TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + OffLineRenderHandler.getInstance().onPause(); + + //存储设备等级 + saveCacheDeviceLevel(context,level[0]); + Log.d(TAG,"DeviceLevel: " + level); + return level[0]; + } + + /** + * -1 不是特定的高低端机型 + * @return + */ + private static int judgeDeviceLevelInDeviceName() { + String currentDeviceName = getDeviceName(); + for (String deviceName:upscaleDevice) { + if (deviceName.equals(currentDeviceName)) { + return DEVICE_LEVEL_HIGH; + } + } + + for (String deviceName:middleDevice) { + if (deviceName.equals(currentDeviceName)) { + return DEVICE_LEVEL_MID; + } + } + + for (String deviceName:lowDevice) { + if (deviceName.equals(currentDeviceName)) { + return DEVICE_LEVEL_LOW; + } + } + return -1; + } + + public static final String[] upscaleDevice = {"vivo X6S A","MHA-AL00","VKY-AL00","V1838A"}; + public static final String[] lowDevice = {}; + public static final String[] middleDevice = {"OPPO R11s","PAR-AL00","MI 8 Lite","ONEPLUS A6000","PRO 6","PRO 7 Plus"}; + + /** + * 评定内存的等级. + * + * @return + */ + private static int judgeMemory(Context context) { + long ramMB = getTotalMemory(context) / (1024 * 1024); + int level = -1; + if (ramMB <= 2000) { //2G或以下的最低档 + level = 0; + } else if (ramMB <= 3000) { //2-3G + level = 1; + } else if (ramMB <= 4000) { //4G档 2018主流中端机 + level = 2; + } else if (ramMB <= 6000) { //6G档 高端机 + level = 3; + } else { //6G以上 旗舰机配置 + level = 4; + } + return level; + } + + /** + * 评定CPU等级.(按频率和厂商型号综合判断) + * + * @return + */ + private static int judgeCPU() { + int level = 0; + String cpuName = getHardWare(); + int freqMHz = getCPUMaxFreqKHz() / 1024; + + //一个不符合下述规律的高级白名单 + //如果可以获取到CPU型号名称 -> 根据不同的名称走不同判定策略 + if (!TextUtils.isEmpty(cpuName)) { + if (cpuName.contains("qcom") || cpuName.contains("Qualcomm")) { //高通骁龙 + return judgeQualcommCPU(cpuName, freqMHz); + } else if (cpuName.contains("hi") || cpuName.contains("kirin")) { //海思麒麟 + return judgeSkinCPU(cpuName, freqMHz); + } else if (cpuName.contains("MT")) {//联发科 + return judgeMTCPU(cpuName, freqMHz); + } + } + + //cpu型号无法获取的普通规则 + if (freqMHz <= 1600) { //1.5G 低端 + level = 0; + } else if (freqMHz <= 1950) { //2GHz 低中端 + level = 1; + } else if (freqMHz <= 2500) { //2.2 2.3g 中高端 + level = 2; + } else { //高端 + level = 3; + } + return level; + } + + /** + * 联发科芯片等级判定 + * + * @return + */ + private static int judgeMTCPU(String cpuName, int freqMHz) { + //P60之前的全是低端机 MT6771V/C + int level = 0; + int mtCPUVersion = getMTCPUVersion(cpuName); + if (mtCPUVersion == -1) { + //读取不出version 按照一个比较严格的方式来筛选出高端机 + if (freqMHz <= 1600) { //1.5G 低端 + level = 0; + } else if (freqMHz <= 2200) { //2GHz 低中端 + level = 1; + } else if (freqMHz <= 2700) { //2.2 2.3g 中高端 + level = 2; + } else { //高端 + level = 3; + } + } else if (mtCPUVersion < 6771) { + //均为中低端机 + if (freqMHz <= 1600) { //1.5G 低端 + level = 0; + } else { //2GHz 中端 + level = 1; + } + } else { + if (freqMHz <= 1600) { //1.5G 低端 + level = 0; + } else if (freqMHz <= 1900) { //2GHz 低中端 + level = 1; + } else if (freqMHz <= 2500) { //2.2 2.3g 中高端 + level = 2; + } else { //高端 + level = 3; + } + } + + return level; + } + + /** + * 通过联发科CPU型号定义 -> 获取cpu version + * + * @param cpuName + * @return + */ + private static int getMTCPUVersion(String cpuName) { + //截取MT后面的四位数字 + int cpuVersion = -1; + if (cpuName.length() > 5) { + String cpuVersionStr = cpuName.substring(2, 6); + try { + cpuVersion = Integer.valueOf(cpuVersionStr); + } catch (NumberFormatException exception) { + exception.printStackTrace(); + } + } + + return cpuVersion; + } + + /** + * 高通骁龙芯片等级判定 + * + * @return + */ + private static int judgeQualcommCPU(String cpuName, int freqMHz) { + int level = 0; + //xxxx inc MSM8937 比较老的芯片 + //7 8 xxx inc SDM710 + if (cpuName.contains("MSM")) { + //老芯片 + if (freqMHz <= 1600) { //1.5G 低端 + level = 0; + } else { //2GHz 低中端 + level = 1; + } + } else { + //新的芯片 + if (freqMHz <= 1600) { //1.5G 低端 + level = 0; + } else if (freqMHz <= 2000) { //2GHz 低中端 + level = 1; + } else if (freqMHz <= 2500) { //2.2 2.3g 中高端 + level = 2; + } else { //高端 + level = 3; + } + } + + return level; + } + + /** + * 麒麟芯片等级判定 + * + * @param freqMHz + * @return + */ + private static int judgeSkinCPU(String cpuName, int freqMHz) { + //型号 -> kirin710之后 & 最高核心频率 + int level = 0; + if (cpuName.startsWith("hi")) { + //这个是海思的芯片中低端 + if (freqMHz <= 1600) { //1.5G 低端 + level = 0; + } else if (freqMHz <= 2000) { //2GHz 低中端 + level = 1; + } + } else { + //这个是海思麒麟的芯片 + if (freqMHz <= 1600) { //1.5G 低端 + level = 0; + } else if (freqMHz <= 2000) { //2GHz 低中端 + level = 1; + } else if (freqMHz <= 2500) { //2.2 2.3g 中高端 + level = 2; + } else { //高端 + level = 3; + } + } + + return level; + } + + public static final String Nexus_6P = "Nexus 6P"; + + /** + * 获取设备名 + * + * @return + */ + public static String getDeviceName() { + String deviceName = ""; + if (Build.MODEL != null) deviceName = Build.MODEL; + Log.d(TAG,"deviceName: " + deviceName); + return deviceName; + } + + /** + * 缓存设备等级 + * + * @param level + */ + public static void saveCacheDeviceLevel(Context context,int level) { + SharedPreferences sp = context.getSharedPreferences(DEVICE_LEVEL, MODE_PRIVATE); + sp.edit().putInt(DEVICE_LEVEL, level).apply(); + } + + /** + * 获取设备等级 + * + * @return + */ + public static int getCacheDeviceLevel(Context context) { + SharedPreferences sp = context.getSharedPreferences(DEVICE_LEVEL, MODE_PRIVATE); + return sp.getInt(DEVICE_LEVEL, -1); + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/IFURenderer.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/IFURenderer.java new file mode 100644 index 000000000..e6be37267 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/IFURenderer.java @@ -0,0 +1,249 @@ +package com.yunbao.faceunity.utils; + + +import android.content.Context; + +import com.faceunity.core.enumeration.CameraFacingEnum; +import com.faceunity.core.enumeration.FUAIProcessorEnum; +import com.faceunity.core.enumeration.FUExternalInputEnum; +import com.faceunity.core.enumeration.FUInputBufferEnum; +import com.faceunity.core.enumeration.FUInputTextureEnum; +import com.faceunity.core.enumeration.FUTransformMatrixEnum; +import com.yunbao.faceunity.listener.FURendererListener; + +/** + * DESC: + * Created on 2021/4/26 + */ +abstract class IFURenderer { + + /** + * 渲染属性 + */ + protected FUExternalInputEnum externalInputType = FUExternalInputEnum.EXTERNAL_INPUT_TYPE_CAMERA;//数据源类型 + protected FUInputTextureEnum inputTextureType = FUInputTextureEnum.FU_ADM_FLAG_EXTERNAL_OES_TEXTURE;//纹理类型 + protected FUInputBufferEnum inputBufferType = FUInputBufferEnum.FU_FORMAT_NV21_BUFFER;//数据类型 + protected int inputOrientation = 270;//数据源朝向 + protected int deviceOrientation = 90;//手机设备朝向 + protected CameraFacingEnum cameraFacing = CameraFacingEnum.CAMERA_FRONT; //数据源为相机时候->前后置相机 + protected FUTransformMatrixEnum inputTextureMatrix = FUTransformMatrixEnum.CCROT0_FLIPVERTICAL;//纹理旋转类型 + protected FUTransformMatrixEnum inputBufferMatrix = FUTransformMatrixEnum.CCROT0_FLIPVERTICAL;//图象旋转类型 + protected FUTransformMatrixEnum outputMatrix = FUTransformMatrixEnum.CCROT0;//图象旋转类型 + + + /** + * 初始化鉴权 + */ + public abstract void setup(Context context); + + + /** + * 双输入接口,输入 buffer 和 texture,必须在具有 GL 环境的线程调用 + * 由于省去数据拷贝,性能相对最优,优先推荐使用。 + * 缺点是无法保证 buffer 和纹理对齐,可能出现点位和效果对不上的情况。 + * + * @param img NV21 buffer + * @param texId 纹理 ID + * @param width 宽 + * @param height 高 + * @return + */ + public abstract int onDrawFrameDualInput(byte[] img, int texId, int width, int height); + + /** + * 类似 GLSurfaceView 的 queueEvent 机制,把任务抛到 GL 线程执行。 + * + * @param runnable + */ + public abstract void queueEvent(Runnable runnable); + + + /** + * 设置检测类型 + * + * @param type + */ + public abstract void setAIProcessTrackType(FUAIProcessorEnum type); + + /** + * 资源释放 + */ + public abstract void release(); + + /** + * 开启合成状态 + */ + public abstract void prepareRenderer(FURendererListener mFURendererListener); + + + /** + * 设置FPS检测 + * + * @param enable + */ + public abstract void setMarkFPSEnable(boolean enable); + + + + /** + * 获取输入源类型 + * + * @return + */ + public FUExternalInputEnum getExternalInputType() { + return externalInputType; + } + + /** + * 设置输入源类型 + * + * @param externalInputType + */ + public void setExternalInputType(FUExternalInputEnum externalInputType) { + this.externalInputType = externalInputType; + } + + /** + * 获取输入纹理类型 + * + * @return + */ + public FUInputTextureEnum getInputTextureType() { + return inputTextureType; + } + + /** + * 设置输入纹理类型 + * + * @param inputTextureType + */ + public void setInputTextureType(FUInputTextureEnum inputTextureType) { + this.inputTextureType = inputTextureType; + } + + /** + * 获取输入Buffer类型 + * + * @return + */ + public FUInputBufferEnum getInputBufferType() { + return inputBufferType; + } + + /** + * 设置输入Buffer类型 + * + * @param inputBufferType + */ + public void setInputBufferType(FUInputBufferEnum inputBufferType) { + this.inputBufferType = inputBufferType; + } + + /** + * 获取输入数据朝向 + * + * @return + */ + public int getInputOrientation() { + return inputOrientation; + } + + /** + * 设置输入数据朝向 + * + * @param inputOrientation + */ + public void setInputOrientation(int inputOrientation) { + this.inputOrientation = inputOrientation; + } + + /** + * 获取设备类型 + * + * @return + */ + public int getDeviceOrientation() { + return deviceOrientation; + } + + /** + * 设置设备类型 + * + * @param deviceOrientation + */ + public void setDeviceOrientation(int deviceOrientation) { + this.deviceOrientation = deviceOrientation; + } + + /** + * 获取设备朝向 + * + * @return + */ + public CameraFacingEnum getCameraFacing() { + return cameraFacing; + } + + /** + * 设置设备朝向 + * + * @param cameraFacing + */ + public void setCameraFacing(CameraFacingEnum cameraFacing) { + this.cameraFacing = cameraFacing; + } + + /** + * 获取输入纹理旋转类型 + * + * @return + */ + public FUTransformMatrixEnum getInputTextureMatrix() { + return inputTextureMatrix; + } + + /** + * 设置输入纹理旋转类型 + * + * @param inputTextureMatrix + */ + public void setInputTextureMatrix(FUTransformMatrixEnum inputTextureMatrix) { + this.inputTextureMatrix = inputTextureMatrix; + } + + /** + * 获取输入数据旋转类型 + * + * @return + */ + public FUTransformMatrixEnum getInputBufferMatrix() { + return inputBufferMatrix; + } + + /** + * 设置输入数据旋转类型 + * + * @param inputBufferMatrix + */ + public void setInputBufferMatrix(FUTransformMatrixEnum inputBufferMatrix) { + this.inputBufferMatrix = inputBufferMatrix; + } + + /** + * 获取输出数据旋转类型 + * + * @return + */ + public FUTransformMatrixEnum getOutputMatrix() { + return outputMatrix; + } + + /** + * 设置输出数据旋转类型 + * + * @param outputMatrix + */ + public void setOutputMatrix(FUTransformMatrixEnum outputMatrix) { + this.outputMatrix = outputMatrix; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/MemoryInfoUtil.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/MemoryInfoUtil.java new file mode 100644 index 000000000..6b5f95c3f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/MemoryInfoUtil.java @@ -0,0 +1,90 @@ +package com.yunbao.faceunity.utils; + +import android.os.Build; +import android.os.Debug; + +import androidx.annotation.RequiresApi; + +import java.lang.reflect.Field; + +/** + * 内存使用率获取工具类 + * Created by tujh on 2018/5/24. + */ +public abstract class MemoryInfoUtil { + + @RequiresApi(api = Build.VERSION_CODES.M) + public static double getMemory(Debug.MemoryInfo[] memoryInfos) { + try { + if (Build.VERSION.SDK_INT >= 27) { + return compute(memoryInfos); + } + + Field otherStats_Field = memoryInfos[0].getClass().getDeclaredField("otherStats"); + otherStats_Field.setAccessible(true); + int[] otherStats = (int[]) otherStats_Field.get(memoryInfos[0]); + + Field NUM_CATEGORIES_Field = memoryInfos[0].getClass().getDeclaredField("NUM_CATEGORIES"); + Field offsetPrivateClean_Field = memoryInfos[0].getClass().getDeclaredField("offsetPrivateClean"); + Field offsetPrivateDirty_Field = memoryInfos[0].getClass().getDeclaredField("offsetPrivateDirty"); + final int NUM_CATEGORIES = (int) NUM_CATEGORIES_Field.get(memoryInfos[0]); + final int offsetPrivateClean = (int) offsetPrivateClean_Field.get(memoryInfos[0]); + final int offsetPrivateDirty = (int) offsetPrivateDirty_Field.get(memoryInfos[0]); + + int javaHeap = memoryInfos[0].dalvikPrivateDirty + + otherStats[12 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[12 * NUM_CATEGORIES + offsetPrivateDirty]; + int nativeHeap = memoryInfos[0].nativePrivateDirty; + int code = otherStats[6 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[6 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[7 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[7 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[8 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[8 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[9 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[9 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[10 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[10 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[11 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[11 * NUM_CATEGORIES + offsetPrivateDirty]; + int stack = otherStats[NUM_CATEGORIES + offsetPrivateDirty]; + int graphics = otherStats[4 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[4 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[14 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[14 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[15 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[15 * NUM_CATEGORIES + offsetPrivateDirty]; + int other = otherStats[0 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[0 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[2 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[2 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[3 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[3 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[5 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[5 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[13 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[13 * NUM_CATEGORIES + offsetPrivateDirty] + + otherStats[16 * NUM_CATEGORIES + offsetPrivateClean] + otherStats[16 * NUM_CATEGORIES + offsetPrivateDirty]; + int all = javaHeap + nativeHeap + code + stack + graphics + other; +// Log.d("MemoryAll", "javaHeap=" + javaHeap +// + "\nnativeHeap=" + nativeHeap + "\ncode=" + code + "\nstack=" + stack +// + "\ngraphics=" + graphics + "\nother=" + other); +// Log.e(TAG, "memory " + memoryStr +// + " java-heap " + String.format("%.2f", ((double) javaHeap) / 1024) +// + " native-heap " + String.format("%.2f", ((double) nativeHeap) / 1024) +// + " code " + String.format("%.2f", ((double) code) / 1024) +// + " stack " + String.format("%.2f", ((double) stack) / 1024) +// + " graphics " + String.format("%.2f", ((double) graphics) / 1024) +// + " other " + String.format("%.2f", ((double) other) / 1024) +// + " pps " + String.format("%.2f", ((double) memoryInfos[0].getTotalPss()) / 1024) +// ); + return ((double) all) / 1024; + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + + @RequiresApi(api = Build.VERSION_CODES.M) + private static double compute(Debug.MemoryInfo[] memInfo) { + String java_mem = memInfo[0].getMemoryStat("summary.java-heap"); + String native_mem = memInfo[0].getMemoryStat("summary.native-heap"); + String graphics_mem = memInfo[0].getMemoryStat("summary.graphics"); + String stack_mem = memInfo[0].getMemoryStat("summary.stack"); + String code_mem = memInfo[0].getMemoryStat("summary.code"); + String others_mem = memInfo[0].getMemoryStat("summary.system"); + int all = Integer.parseInt(java_mem) + + Integer.parseInt(native_mem) + + Integer.parseInt(graphics_mem) + + Integer.parseInt(stack_mem) + + Integer.parseInt(code_mem) + + Integer.parseInt(others_mem); + return ((double) all) / 1024; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/SeekBarUtils.kt b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/SeekBarUtils.kt new file mode 100644 index 000000000..cadecf261 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/SeekBarUtils.kt @@ -0,0 +1,37 @@ +package com.yunbao.faceunity.utils + +import android.view.View +import com.yunbao.faceunity.seekbar.DiscreteSeekBar + +class SeekBarUtils { + companion object { + /** + * 设置滚动条数值 + * @param value Double 结果值 + * @param stand Double 标准值 + * @param range Double 范围区间 + */ + fun seekToSeekBar(bar: DiscreteSeekBar, value: Double, stand: Double, range: Double) { + if (stand == 0.5) { + bar.min = -50 + bar.max = 50 + bar.progress = (value * 100 / range - 50).toInt() + } else { + bar.min = 0 + bar.max = 100 + bar.progress = (value * 100 / range).toInt() + } + bar.visibility = View.VISIBLE + } + + /** + * 转换成滚动条的值 + */ + fun seekToValue(range:Double,value:Int,seekBarMin:Int):Double{ + val valueF: Double = 1.0 * (value - seekBarMin) / 100 + return range*valueF; + } + } + + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/Uri2PathUtil.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/Uri2PathUtil.java new file mode 100644 index 000000000..01af25574 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/Uri2PathUtil.java @@ -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()); + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/ZipUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/ZipUtils.java new file mode 100644 index 000000000..22cbfa3af --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/ZipUtils.java @@ -0,0 +1,251 @@ +package com.yunbao.faceunity.utils; + +import android.util.Log; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +/** + * @author: lijuan + * @description: 解压ZIP文件 + * @date: 2017-04-11 + * @time: 09:22 + */ +public class ZipUtils { + public static final String TAG = "ZIP"; + + /** + * 解压zip到指定的路径 + * + * @param zipFileString ZIP的名称 + * @param outPathString 要解压缩路径 + * @throws Exception + */ + public static void unZipFolder(String zipFileString, String outPathString) throws Exception { + ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString)); + ZipEntry zipEntry; + String szName = ""; + while ((zipEntry = inZip.getNextEntry()) != null) { + szName = zipEntry.getName(); + if (zipEntry.isDirectory()) { + //获取部件的文件夹名 + szName = szName.substring(0, szName.length() - 1); + File folder = new File(outPathString + File.separator + szName); + folder.mkdirs(); + } else { + Log.i(TAG, outPathString + File.separator + szName); + File file = new File(outPathString + File.separator + szName); + if (!file.exists()) { + Log.i(TAG, "Create the file:" + outPathString + File.separator + szName); + file.getParentFile().mkdirs(); + file.createNewFile(); + } + // 获取文件的输出流 + FileOutputStream out = new FileOutputStream(file); + int len; + byte[] buffer = new byte[1024]; + // 读取(字节)字节到缓冲区 + while ((len = inZip.read(buffer)) != -1) { + // 从缓冲区(0)位置写入(字节)字节 + out.write(buffer, 0, len); + out.flush(); + } + out.close(); + } + } + inZip.close(); + } + + /** + * 解压zip到指定的路径 + * + * @param zipFileString ZIP的名称 + * @param outPathString 要解压缩路径 + * @throws Exception + */ + public static ArrayList unZipFolderWithFileName(String zipFileString, String outPathString) throws Exception { + //记录所有文件名 + ArrayList list = new ArrayList<>(); + ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString)); + ZipEntry zipEntry; + String szName = ""; + while ((zipEntry = inZip.getNextEntry()) != null) { + szName = zipEntry.getName(); + if (zipEntry.isDirectory()) { + //获取部件的文件夹名 + szName = szName.substring(0, szName.length() - 1); + File folder = new File(outPathString + File.separator + szName); + folder.mkdirs(); + } else { + Log.i(TAG, outPathString + File.separator + szName); + list.add(szName); + File file = new File(outPathString + File.separator + szName); + if (!file.exists()) { + Log.i(TAG, "Create the file:" + outPathString + File.separator + szName); + file.getParentFile().mkdirs(); + file.createNewFile(); + } + // 获取文件的输出流 + FileOutputStream out = new FileOutputStream(file); + int len; + byte[] buffer = new byte[1024]; + // 读取(字节)字节到缓冲区 + while ((len = inZip.read(buffer)) != -1) { + // 从缓冲区(0)位置写入(字节)字节 + out.write(buffer, 0, len); + out.flush(); + } + out.close(); + } + } + inZip.close(); + return list; + } + + public static void unZipFolder(String zipFileString, String outPathString, String szName) throws Exception { + ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString)); + ZipEntry zipEntry; + while ((zipEntry = inZip.getNextEntry()) != null) { + //szName = zipEntry.getName(); + if (zipEntry.isDirectory()) { + //获取部件的文件夹名 + szName = szName.substring(0, szName.length() - 1); + File folder = new File(outPathString + File.separator + szName); + folder.mkdirs(); + } else { + Log.i(TAG, outPathString + File.separator + szName); + File file = new File(outPathString + File.separator + szName); + if (!file.exists()) { + Log.i(TAG, "Create the file:" + outPathString + File.separator + szName); + file.getParentFile().mkdirs(); + file.createNewFile(); + } + // 获取文件的输出流 + FileOutputStream out = new FileOutputStream(file); + int len; + byte[] buffer = new byte[1024]; + // 读取(字节)字节到缓冲区 + while ((len = inZip.read(buffer)) != -1) { + // 从缓冲区(0)位置写入(字节)字节 + out.write(buffer, 0, len); + out.flush(); + } + out.close(); + } + } + inZip.close(); + } + + /** + * 压缩文件和文件夹 + * + * @param srcFileString 要压缩的文件或文件夹 + * @param zipFileString 解压完成的Zip路径 + * @throws Exception + */ + public static void zipFolder(String srcFileString, String zipFileString) throws Exception { + //创建ZIP + ZipOutputStream outZip = new ZipOutputStream(new FileOutputStream(zipFileString)); + //创建文件 + File file = new File(srcFileString); + //压缩 + zipFiles(file.getParent() + File.separator, file.getName(), outZip); + //完成和关闭 + outZip.finish(); + outZip.close(); + } + + /** + * 压缩文件 + * + * @param folderString + * @param fileString + * @param zipOutputSteam + * @throws Exception + */ + private static void zipFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam) throws Exception { + if (zipOutputSteam == null) + return; + File file = new File(folderString + fileString); + if (file.isFile()) { + ZipEntry zipEntry = new ZipEntry(fileString); + FileInputStream inputStream = new FileInputStream(file); + zipOutputSteam.putNextEntry(zipEntry); + int len; + byte[] buffer = new byte[4096]; + while ((len = inputStream.read(buffer)) != -1) { + zipOutputSteam.write(buffer, 0, len); + } + zipOutputSteam.closeEntry(); + } else { + //文件夹 + String fileList[] = file.list(); + //没有子文件和压缩 + if (fileList.length <= 0) { + ZipEntry zipEntry = new ZipEntry(fileString + File.separator); + zipOutputSteam.putNextEntry(zipEntry); + zipOutputSteam.closeEntry(); + } + //子文件和递归 + for (int i = 0; i < fileList.length; i++) { + zipFiles(folderString, fileString + File.separator + fileList[i], zipOutputSteam); + } + } + } + + /** + * 返回zip的文件输入流 + * + * @param zipFileString zip的名称 + * @param fileString ZIP的文件名 + * @return InputStream + * @throws Exception + */ + public static InputStream upZip(String zipFileString, String fileString) throws Exception { + ZipFile zipFile = new ZipFile(zipFileString); + ZipEntry zipEntry = zipFile.getEntry(fileString); + return zipFile.getInputStream(zipEntry); + } + + /** + * 返回ZIP中的文件列表(文件和文件夹) + * + * @param zipFileString ZIP的名称 + * @param bContainFolder 是否包含文件夹 + * @param bContainFile 是否包含文件 + * @return + * @throws Exception + */ + public static List getFileList(String zipFileString, boolean bContainFolder, boolean bContainFile) throws Exception { + List fileList = new ArrayList(); + ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString)); + ZipEntry zipEntry; + String szName = ""; + while ((zipEntry = inZip.getNextEntry()) != null) { + szName = zipEntry.getName(); + if (zipEntry.isDirectory()) { + // 获取部件的文件夹名 + szName = szName.substring(0, szName.length() - 1); + File folder = new File(szName); + if (bContainFolder) { + fileList.add(folder); + } + } else { + File file = new File(szName); + if (bContainFile) { + fileList.add(file); + } + } + } + inZip.close(); + return fileList; + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/GsonConverter.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/GsonConverter.java new file mode 100644 index 000000000..8a14aab2f --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/GsonConverter.java @@ -0,0 +1,86 @@ +package com.yunbao.faceunity.utils.net; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.google.gson.reflect.TypeToken; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * GSON 转换器 + * + * @author Richie on 2018.12.22 + */ +public final class GsonConverter { + private final static Gson GSON = new Gson(); + + private GsonConverter() { + } + + /** + * json to bean + * + * @param json must be JSONObject + * @param classOfT + * @param + * @return + */ + public static T jsonToBean(String json, Class classOfT) { + return GSON.fromJson(json, classOfT); + } + + /** + * json to bean list, without generic erase problem, recommend + * + * @param json must be JSONArray + * @param classOfT + * @param + * @return + */ + public static List jsonToList(String json, Class classOfT) { + JsonArray array = JsonParser.parseString(json).getAsJsonArray(); + List list = new ArrayList<>(array.size()); + for (JsonElement elem : array) { + T t = GSON.fromJson(elem, classOfT); + list.add(t); + } + return list; + } + + /** + * json to map + * + * @param json must be JSONObject + * @return + */ + public static Map jsonToMap(String json) { + return GSON.fromJson(json, new TypeToken>() { + }.getType()); + } + + /** + * json to bean list containing map + * + * @param json must be JSONObject + * @return + */ + public static List> jsonToMapList(String json) { + return GSON.fromJson(json, new TypeToken>>() { + }.getType()); + } + + /** + * bean to json + * + * @param src + * @return + */ + public static String objectToJson(Object src) { + return GSON.toJson(src); + } + +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/HttpUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/HttpUtils.java new file mode 100644 index 000000000..1c120caa2 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/HttpUtils.java @@ -0,0 +1,179 @@ +package com.yunbao.faceunity.utils.net; + +import android.os.Build; +import android.text.TextUtils; +import android.webkit.WebSettings; + +import androidx.annotation.NonNull; + +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.net.FileNameMap; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import okhttp3.MediaType; + +/** + * @author Richie on 2018.12.22 + */ +public final class HttpUtils { + public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8"); + public static final MediaType MEDIA_TYPE_PLAIN = MediaType.parse("text/plain; charset=utf-8"); + public static final MediaType MEDIA_TYPE_STREAM = MediaType.parse("application/octet-stream"); + public static final String HEAD_KEY_USER_AGENT = "User-Agent"; + private static String sUserAgent; + + private HttpUtils() { + } + + /** + * 为 HttpGet 的 url 方便的添加键值对参数 + * + * @param url + * @param name + * @param value + * @return + */ + public static String attachHttpGetParam(@NonNull String url, @NonNull String name, @NonNull String value) { + return url + "?" + name + "=" + value; + } + + /** + * 为 HttpGet 的 url 方便的添加键值对参数 + * + * @param url + * @param params + * @return + */ + public static String attachHttpGetParams(@NonNull String url, @NonNull Map params) { + StringBuilder sb = new StringBuilder(url); + sb.append("?"); + Set> entries = params.entrySet(); + for (Map.Entry entry : entries) { + try { + sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + sb.deleteCharAt(sb.length() - 1); + return sb.toString(); + } + + /** + * 通过 ‘?’ 和 ‘/’ 判断文件名 + * http://mavin-manzhan.oss-cn-hangzhou.aliyuncs.com/1486631099150286149.jpg?x-oss-process=image/watermark,image_d2F0ZXJtYXJrXzIwMF81MC5wbmc + */ + public static String getUrlFileName(String url) { + String filename = null; + String[] strings = url.split("/"); + for (String string : strings) { + if (string.contains("?")) { + int endIndex = string.indexOf("?"); + if (endIndex != -1) { + filename = string.substring(0, endIndex); + return filename; + } + } + } + if (strings.length > 0) { + filename = strings[strings.length - 1]; + } + return filename; + } + + /** + * 根据文件名获取MIME类型 + */ + public static MediaType guessMimeType(String fileName) { + FileNameMap fileNameMap = URLConnection.getFileNameMap(); + fileName = fileName.replace("#", ""); //解决文件名中含有#号异常的问题 + String contentType = fileNameMap.getContentTypeFor(fileName); + if (contentType == null) { + return MEDIA_TYPE_STREAM; + } + return MediaType.parse(contentType); + } + + /** + * User-Agent: Mozilla/5.0 (Linux; U; Android 5.0.2; zh-cn; Redmi Note 3 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 + */ + public static String getUserAgent() { + if (TextUtils.isEmpty(sUserAgent)) { + String webUserAgent = null; + try { + Class sysResCls = Class.forName("com.android.internal.R$string"); + Field webUserAgentField = sysResCls.getDeclaredField("web_user_agent"); + Integer resId = (Integer) webUserAgentField.get(null); + webUserAgent =OkHttpUtils.getInstance().getContext().getString(resId); + } catch (Exception e) { + // maybe failed on Android P or higher version + e.printStackTrace(); + } + + if (TextUtils.isEmpty(webUserAgent)) { + try { + webUserAgent = WebSettings.getDefaultUserAgent(OkHttpUtils.getInstance().getContext()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (TextUtils.isEmpty(webUserAgent)) { + try { + webUserAgent = System.getProperty("http.agent"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (TextUtils.isEmpty(webUserAgent)) { + webUserAgent = "okhttp/square"; + } + + Locale locale = Locale.getDefault(); + StringBuffer buffer = new StringBuffer(); + // Add version + final String version = Build.VERSION.RELEASE; + if (version.length() > 0) { + buffer.append(version); + } else { + // default to "1.0" + buffer.append("1.0"); + } + buffer.append("; "); + final String language = locale.getLanguage(); + if (language != null) { + buffer.append(language.toLowerCase(locale)); + final String country = locale.getCountry(); + if (!TextUtils.isEmpty(country)) { + buffer.append("-"); + buffer.append(country.toLowerCase(locale)); + } + } else { + // default to "en" + buffer.append("en"); + } + // add the model for the release build + if ("REL".equals(Build.VERSION.CODENAME)) { + final String model = Build.MODEL; + if (model.length() > 0) { + buffer.append("; "); + buffer.append(model); + } + } + final String id = Build.ID; + if (id.length() > 0) { + buffer.append(" Build/"); + buffer.append(id); + } + sUserAgent = String.format(webUserAgent, buffer, "Mobile "); + } + return sUserAgent; + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/HttpsUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/HttpsUtils.java new file mode 100644 index 000000000..4336160ea --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/HttpsUtils.java @@ -0,0 +1,193 @@ +package com.yunbao.faceunity.utils.net; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +/** + * Https相关的工具类 + * + * @author Richie on 2018.12.22 + */ +final class HttpsUtils { + + /** + * 为了解决客户端不信任服务器数字证书的问题,网络上大部分的解决方案都是让客户端不对证书做任何检查, + * 这是一种有很大安全漏洞的办法 + */ + public static X509TrustManager UnSafeTrustManager = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[]{}; + } + }; + /** + * 此类是用于主机名验证的基接口。 在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配, + * 则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。策略可以是基于证书的或依赖于其他验证方案。 + * 当验证 URL 主机名使用的默认规则失败时使用这些回调。如果主机名是可接受的,则返回 true + */ + public static HostnameVerifier UnSafeHostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + public static SSLParams getSslSocketFactory() { + return getSslSocketFactoryBase(null, null, null); + } + + /** + * https单向认证 + * 可以额外配置信任服务端的证书策略,否则默认是按CA证书去验证的,若不是CA可信任的证书,则无法通过验证 + */ + public static SSLParams getSslSocketFactory(X509TrustManager trustManager) { + return getSslSocketFactoryBase(trustManager, null, null); + } + + /** + * https单向认证 + * 用含有服务端公钥的证书校验服务端证书 + */ + public static SSLParams getSslSocketFactory(InputStream... certificates) { + return getSslSocketFactoryBase(null, null, null, certificates); + } + + /** + * https双向认证 + * bksFile 和 password -> 客户端使用bks证书校验服务端证书 + * certificates -> 用含有服务端公钥的证书校验服务端证书 + */ + public static SSLParams getSslSocketFactory(InputStream bksFile, String password, InputStream... certificates) { + return getSslSocketFactoryBase(null, bksFile, password, certificates); + } + + /** + * https双向认证 + * bksFile 和 password -> 客户端使用bks证书校验服务端证书 + * X509TrustManager -> 如果需要自己校验,那么可以自己实现相关校验,如果不需要自己校验,那么传null即可 + */ + public static SSLParams getSslSocketFactory(InputStream bksFile, String password, X509TrustManager trustManager) { + return getSslSocketFactoryBase(trustManager, bksFile, password); + } + + private static SSLParams getSslSocketFactoryBase(X509TrustManager trustManager, InputStream bksFile, String password, InputStream... certificates) { + SSLParams sslParams = new SSLParams(); + try { + KeyManager[] keyManagers = prepareKeyManager(bksFile, password); + TrustManager[] trustManagers = prepareTrustManager(certificates); + X509TrustManager manager; + if (trustManager != null) { + //优先使用用户自定义的TrustManager + manager = trustManager; + } else if (trustManagers != null) { + //然后使用默认的TrustManager + manager = chooseTrustManager(trustManagers); + } else { + //否则使用不安全的TrustManager + manager = UnSafeTrustManager; + } + // 创建TLS类型的SSLContext对象, that uses our TrustManager + SSLContext sslContext = SSLContext.getInstance("TLS"); + // 用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书 + // 第一个参数是授权的密钥管理器,用来授权验证,比如授权自签名的证书验证。第二个是被授权的证书管理器,用来验证服务器端的证书 + sslContext.init(keyManagers, new TrustManager[]{manager}, null); + // 通过sslContext获取SSLSocketFactory对象 + sslParams.sSLSocketFactory = sslContext.getSocketFactory(); + sslParams.trustManager = manager; + return sslParams; + } catch (NoSuchAlgorithmException | KeyManagementException e) { + throw new AssertionError(e); + } + } + + private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) { + try { + if (bksFile == null || password == null) { + return null; + } + KeyStore clientKeyStore = KeyStore.getInstance("BKS"); + clientKeyStore.load(bksFile, password.toCharArray()); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(clientKeyStore, password.toCharArray()); + return kmf.getKeyManagers(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private static TrustManager[] prepareTrustManager(InputStream... certificates) { + if (certificates == null || certificates.length <= 0) { + return null; + } + try { + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + // 创建一个默认类型的KeyStore,存储我们信任的证书 + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null); + int index = 0; + for (InputStream certStream : certificates) { + String certificateAlias = Integer.toString(index++); + // 证书工厂根据证书文件的流生成证书 cert + Certificate cert = certificateFactory.generateCertificate(certStream); + // 将 cert 作为可信证书放入到keyStore中 + keyStore.setCertificateEntry(certificateAlias, cert); + try { + if (certStream != null) { + certStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + //我们创建一个默认类型的TrustManagerFactory + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + //用我们之前的keyStore实例初始化TrustManagerFactory,这样tmf就会信任keyStore中的证书 + tmf.init(keyStore); + //通过tmf获取TrustManager数组,TrustManager也会信任keyStore中的证书 + return tmf.getTrustManagers(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) { + for (TrustManager trustManager : trustManagers) { + if (trustManager instanceof X509TrustManager) { + return (X509TrustManager) trustManager; + } + } + return null; + } + + static class SSLParams { + SSLSocketFactory sSLSocketFactory; + X509TrustManager trustManager; + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/OkHttpUtils.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/OkHttpUtils.java new file mode 100644 index 000000000..3f3b0b939 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/OkHttpUtils.java @@ -0,0 +1,710 @@ +package com.yunbao.faceunity.utils.net; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.webkit.MimeTypeMap; + +import androidx.annotation.NonNull; + +import org.jetbrains.annotations.NotNull; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.SSLSocketFactory; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Cookie; +import okhttp3.CookieJar; +import okhttp3.FormBody; +import okhttp3.HttpUrl; +import okhttp3.MultipartBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +/** + * OkHttp 工具类 + * + * @author Richie on 2018.12.19 + */ +public final class OkHttpUtils { + private static final String NETWORK_FAILURE_MESSAGE = "网络访问失败"; + private static final String PARSE_FAILURE_MESSAGE = "数据解析失败"; + private static final String DOWNLOAD_FAILURE_MESSAGE = "文件下载失败"; + private static final String RESPONSE_FAILURE_MESSAGE = "响应错误 "; + private static final String UPLOAD_FAILURE_MESSAGE = "文件上传失败 "; + private static final int TIMEOUT = 10; + private final Handler mMainHandler = new Handler(Looper.getMainLooper()); + private OkHttpClient mOkHttpClient; + private Context mContext; + + private OkHttpUtils() { + } + + public static OkHttpUtils getInstance() { + return OkHttpUtilsHolder.INSTANCE; + } + + /** + * 初始化 OkHttp + * + * @param context + * @param debug + */ + public void init(@NonNull Context context, boolean debug) { + mContext = context.getApplicationContext(); + OkLogger.debug(debug); + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .connectTimeout(TIMEOUT, TimeUnit.SECONDS) + .readTimeout(TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(TIMEOUT * 5, TimeUnit.SECONDS) + .cookieJar(new CookieJar() { + private final HashMap> cookieStore = new HashMap<>(); + + @Override + public void saveFromResponse(@NotNull HttpUrl httpUrl, @NotNull List list) { + cookieStore.put(httpUrl.host(), list); + } + + @NotNull + @Override + public List loadForRequest(@NotNull HttpUrl httpUrl) { + List cookies = cookieStore.get(httpUrl.host()); + return cookies != null ? cookies : new ArrayList<>(); + } + }); + + //Android4.4一下手机制定ssl1.2 + try { + SSLSocketFactory factory = new SSLSocketFactoryCompat(); + builder.sslSocketFactory(factory); + } catch (Exception e) { + e.printStackTrace(); + } +// HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(); +// builder.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager); + builder.hostnameVerifier(HttpsUtils.UnSafeHostnameVerifier); + mOkHttpClient = builder.build(); + } + + public Context getContext() { + return mContext; + } + + public void getAsString(@NonNull String url, @NonNull OkHttpCallback callback) { + getAsString(url, null, callback); + } + + /** + * 发送 Get 请求,返回值是字符串 + * + * @param url + * @param paramMap + * @param callback + */ + public void getAsString(@NonNull String url, Map paramMap, @NonNull OkHttpCallback callback) { + if (paramMap != null) { + url = HttpUtils.attachHttpGetParams(url, paramMap); + } + Request request = buildGetRequest(url); + newStringCall(callback, request); + } + + /** + * 发送 Get 请求,返回值是数据实体 + * + * @param url + * @param callback + * @param + */ + public void getAsEntity(@NonNull String url, @NonNull final OkHttpCallback callback) { + getAsEntity(url, null, callback); + } + + /** + * 发送 Get 请求,返回值是数据实体 + * + * @param url + * @param paramMap + * @param callback + * @param + */ + public void getAsEntity(@NonNull String url, Map paramMap, @NonNull final OkHttpCallback callback) { + if (paramMap != null) { + url = HttpUtils.attachHttpGetParams(url, paramMap); + } + Request request = buildGetRequest(url); + newEntityCall(callback, request); + } + + /** + * 发送 Post 键值对,表单数据,返回字符串 + * + * @param url + * @param paramMap + * @param callback + */ + public void postKeyValueAsString(@NonNull String url, Map paramMap, @NonNull OkHttpCallback callback) { + Request request = buildPostRequest(url, paramMap); + newStringCall(callback, request); + } + + /** + * 发送 Post 键值对,表单数据,返回数据实体 + * + * @param url + * @param paramMap + * @param callback + */ + public void postKeyValueAsEntity(@NonNull String url, Map paramMap, @NonNull OkHttpCallback callback) { + Request request = buildPostRequest(url, paramMap); + newEntityCall(callback, request); + } + + /** + * 发送 Post JSON 数据,返回值s字符串 + * + * @param url + * @param jsonStr + * @param callback + */ + public void postJsonAsString(@NonNull String url, @NonNull String jsonStr, @NonNull OkHttpCallback callback) { + RequestBody requestBody = RequestBody.create(HttpUtils.MEDIA_TYPE_JSON, jsonStr); + Request request = buildPostRequest(url, requestBody); + newStringCall(callback, request); + } + + /** + * 发送 Post JSON 数据,返回值是数据实体 + * + * @param url + * @param jsonStr + * @param callback + */ + public void postJsonAsEntity(@NonNull String url, @NonNull String jsonStr, @NonNull OkHttpCallback callback) { + RequestBody requestBody = RequestBody.create(HttpUtils.MEDIA_TYPE_JSON, jsonStr); + Request request = buildPostRequest(url, requestBody); + newEntityCall(callback, request); + } + + /** + * 下载文件,并且回调到主线程 + * + * @param url + * @param file + * @param callback + */ + public void downloadFile(@NonNull String url, @NonNull final File file, @NonNull final OkHttpCallback callback) { + realDownloadFile(url, file, callback, true); + } + + /** + * 下载文件,回调再同一线程 + * + * @param url + * @param file + * @param callback + */ + public void downloadFileCallBackExecute(@NonNull String url, @NonNull final File file, @NonNull final OkHttpCallback callback) { + realDownloadFile(url, file, callback, false); + } + + /** + * 下载文件 回调同步线程 + * + * @param url + * @param file + * @param callback + */ + public void realDownloadFile(@NonNull String url, @NonNull final File file, @NonNull final OkHttpCallback callback, Boolean callBackInUIThread) { + if (file.exists()) { + if (callBackInUIThread) { + runOnUiThread(() -> { + callback.onStart(); + callback.onSuccess(file); + callback.onFinish(); + }); + } else { + callback.onStart(); + callback.onSuccess(file); + callback.onFinish(); + } + return; + } + Request request = buildGetRequest(url); + callback.onStart(); + mOkHttpClient.newCall(request) + .enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + if (callBackInUIThread) + onRequestFailure(e, callback); + else + onRequestFailureCallBackExecute(e, callback); + } + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + InputStream is = null; + BufferedOutputStream bos = null; + try { + is = response.body().byteStream(); + bos = new BufferedOutputStream(new FileOutputStream(file)); + byte[] bytes = new byte[10240]; + int len; + while ((len = is.read(bytes)) != -1) { + bos.write(bytes, 0, len); + } + bos.flush(); + if (callBackInUIThread) { + runOnUiThread(() -> callback.onSuccess(file)); + } else { + callback.onSuccess(file); + } + } catch (Exception e) { + OkLogger.printStackTrace(e); + if (callBackInUIThread) { + runOnUiThread(() -> callback.onFailure(DOWNLOAD_FAILURE_MESSAGE)); + } else { + callback.onFailure(DOWNLOAD_FAILURE_MESSAGE); + } + } finally { + if (bos != null) { + try { + bos.close(); + } catch (IOException e) { + // ignored + } + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignored + } + } + callback.onFinish(); + } + } else { + if (callBackInUIThread) onResponseFailure(response, callback); + else onResponseFailureCallBackExecute(response, callback); + } + } + }); + } + + /** + * 上传文件 + * + * @param url + * @param file + * @param callback + */ + public void uploadFile(@NonNull String url, @NonNull File file, @NonNull final OkHttpCallback callback) { + if (!file.exists() || !file.isFile()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onStart(); + callback.onFailure(UPLOAD_FAILURE_MESSAGE); + callback.onFinish(); + } + }); + return; + } + RequestBody fileBody = RequestBody.create(HttpUtils.MEDIA_TYPE_STREAM, file); + Request request = buildPostRequest(url, fileBody); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onStart(); + } + }); + mOkHttpClient.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + onRequestFailure(e, callback); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) { + if (response.isSuccessful()) { + try { + final String string = response.body().string(); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onSuccess(string); + } + }); + } catch (Exception e) { + OkLogger.printStackTrace(e); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFailure(PARSE_FAILURE_MESSAGE); + } + }); + } finally { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFinish(); + } + }); + } + } else { + onResponseFailure(response, callback); + } + } + }); + } + + /** + * 带参数上传文件 + * + * @param url + * @param name + * @param file + * @param paramMap + * @param callback + */ + public void uploadFile(@NonNull String url, @NonNull String name, @NonNull File file, + @NonNull Map paramMap, @NonNull final OkHttpCallback callback) { + if (!file.exists() || !file.isFile()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onStart(); + callback.onFailure(UPLOAD_FAILURE_MESSAGE); + callback.onFinish(); + } + }); + return; + } + MultipartBody.Builder mbBuilder = new MultipartBody.Builder(); + mbBuilder.setType(MultipartBody.FORM); + Set> entries = paramMap.entrySet(); + for (Map.Entry entry : entries) { + mbBuilder.addFormDataPart(entry.getKey(), entry.getValue()); + } + String fileExtension = MimeTypeMap.getFileExtensionFromUrl(file.getAbsolutePath()); + String fileName = System.currentTimeMillis() + "." + fileExtension; + mbBuilder.addFormDataPart(name, fileName, RequestBody.create(HttpUtils.MEDIA_TYPE_STREAM, file)); + Request request = buildPostRequest(url, mbBuilder.build()); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onStart(); + } + }); + mOkHttpClient.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + onRequestFailure(e, callback); + } + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + try { + final String string = response.body().string(); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onSuccess(string); + } + }); + } catch (Exception e) { + OkLogger.printStackTrace(e); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFailure(PARSE_FAILURE_MESSAGE); + } + }); + } finally { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFinish(); + } + }); + } + } else { + onResponseFailure(response, callback); + } + } + }); + } + + /** + * 取消所有网络请求 + */ + public void cancelAll() { + List queuedCalls = mOkHttpClient.dispatcher().queuedCalls(); + for (Call call : queuedCalls) { + call.cancel(); + } + List runningCalls = mOkHttpClient.dispatcher().runningCalls(); + for (Call call : runningCalls) { + call.cancel(); + } + } + + /** + * 根据 tag 取消请求,默认情况下,tag 就是 url + * + * @param tag + */ + public void cancelTag(@NonNull String tag) { + List queuedCalls = mOkHttpClient.dispatcher().queuedCalls(); + for (Call call : queuedCalls) { + if (tag.equals(call.request().tag())) { + call.cancel(); + } + } + List runningCalls = mOkHttpClient.dispatcher().runningCalls(); + for (Call call : runningCalls) { + if (tag.equals(call.request().tag())) { + call.cancel(); + } + } + } + + private void onRequestFailure(IOException e, @NonNull final OkHttpCallback callback) { + OkLogger.printStackTrace(e); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFailure(NETWORK_FAILURE_MESSAGE); + callback.onFinish(); + } + }); + } + + private void onRequestFailureCallBackExecute(IOException e, @NonNull final OkHttpCallback callback) { + OkLogger.printStackTrace(e); + callback.onFailure(NETWORK_FAILURE_MESSAGE); + callback.onFinish(); + } + + @NonNull + private Request buildGetRequest(@NonNull String url) { + return new Request.Builder() + .get() + .url(url) + .build(); + } + + @NonNull + private Request buildPostRequest(@NonNull String url, RequestBody requestBody) { + return new Request.Builder() + .post(requestBody) + .url(url) + .build(); + } + + @NonNull + private Request buildPostRequest(@NonNull String url, Map paramMap) { + FormBody.Builder builder = new FormBody.Builder(); + if (paramMap != null && paramMap.size() > 0) { + Set> entries = paramMap.entrySet(); + for (Map.Entry entry : entries) { + builder.add(entry.getKey(), entry.getValue()); + } + } + RequestBody formBody = builder.build(); + return new Request.Builder() + .post(formBody) + .url(url) + .build(); + } + + private void newStringCall(@NonNull final OkHttpCallback callback, Request request) { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onStart(); + } + }); + mOkHttpClient.newCall(request) + .enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + onRequestFailure(e, callback); + } + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + try { + final String string = response.body().string(); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onSuccess(string); + } + }); + } catch (Exception e) { + OkLogger.printStackTrace(e); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFailure(PARSE_FAILURE_MESSAGE); + } + }); + } finally { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFinish(); + } + }); + } + } else { + onResponseFailure(response, callback); + } + } + }); + } + + private void newEntityCall(@NonNull final OkHttpCallback callback, Request request) { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onStart(); + } + }); + mOkHttpClient.newCall(request) + .enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + onRequestFailure(e, callback); + } + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + try { + String string = response.body().string(); + Type type = callback.getClass().getGenericSuperclass(); + Type[] params = ((ParameterizedType) type).getActualTypeArguments(); + Class responseClass = (Class) params[0]; + final T t = GsonConverter.jsonToBean(string, responseClass); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onSuccess(t); + } + }); + } catch (Exception e) { + OkLogger.printStackTrace(e); + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFailure(PARSE_FAILURE_MESSAGE); + } + }); + } finally { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFinish(); + } + }); + } + } else { + onResponseFailure(response, callback); + } + } + }); + } + + private void runOnUiThread(Runnable runnable) { + if (Thread.currentThread() == mMainHandler.getLooper().getThread()) { + runnable.run(); + } else { + mMainHandler.post(runnable); + } + } + + private void onResponseFailure(final Response response, @NonNull final OkHttpCallback callback) { + runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onFailure(RESPONSE_FAILURE_MESSAGE + response.code() + ":" + response.message()); + callback.onFinish(); + } + }); + } + + private void onResponseFailureCallBackExecute(final Response response, @NonNull final OkHttpCallback callback) { + callback.onFailure(RESPONSE_FAILURE_MESSAGE + response.code() + ":" + response.message()); + callback.onFinish(); + } + + private static class OkHttpUtilsHolder { + private static final OkHttpUtils INSTANCE = new OkHttpUtils(); + } + + /** + * 网络请求回调 + * + * @param + */ + public abstract static class OkHttpCallback { + /** + * 开始 + */ + protected void onStart() { + } + + /** + * 响应成功 + * + * @param result + */ + protected abstract void onSuccess(T result); + + /** + * 响应失败 + * + * @param errorMsg + */ + protected abstract void onFailure(String errorMsg); + + /** + * 结束 + */ + protected void onFinish() { + } + } + + public abstract static class ProgressOkHttpCallback extends OkHttpCallback { + /** + * 进度 + * + * @param current + * @param total + */ + protected abstract void onProgress(long current, long total); + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/OkLogger.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/OkLogger.java new file mode 100644 index 000000000..ba3c372e6 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/OkLogger.java @@ -0,0 +1,100 @@ +package com.yunbao.faceunity.utils.net; + +import android.util.Log; + +/** + * OkHttp 日志的工具类 + * + * @author Richie on 2018.12.31 + */ +public final class OkLogger { + private static boolean isEnable = false; + private static String tag = "OkHttpUtils"; + + public static void debug(boolean isEnable) { + debug(tag, isEnable); + } + + public static void debug(String tag, boolean isEnable) { + OkLogger.tag = tag; + OkLogger.isEnable = isEnable; + } + + public static void v(String msg) { + v(tag, msg); + } + + public static void v(String tag, String msg) { + if (isEnable) { + Log.v(tag, msg); + } + } + + public static void d(String msg) { + d(tag, msg); + } + + public static void d(String tag, String msg) { + if (isEnable) { + Log.d(tag, msg); + } + } + + public static void i(String msg) { + i(tag, msg); + } + + public static void i(String tag, String msg) { + if (isEnable) { + Log.i(tag, msg); + } + } + + public static void w(String msg) { + w(tag, msg); + } + + public static void w(String tag, String msg) { + if (isEnable) { + Log.w(tag, msg); + } + } + + public static void e(String msg) { + e(tag, msg); + } + + public static void e(String tag, String msg) { + if (isEnable) { + Log.e(tag, msg); + } + } + + public static void printStackTrace(Throwable t) { + if (isEnable && t != null) { + Log.e(tag, "OkHttp error", t); + } + } + + public static void log(int level, String message) { + switch (level) { + case Log.VERBOSE: + v(message); + break; + case Log.DEBUG: + d(message); + break; + case Log.INFO: + i(message); + break; + case Log.WARN: + w(message); + break; + case Log.ERROR: + e(message); + break; + default: + v(message); + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/SSLSocketFactoryCompat.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/SSLSocketFactoryCompat.java new file mode 100644 index 000000000..a54499758 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/SSLSocketFactoryCompat.java @@ -0,0 +1,76 @@ +package com.yunbao.faceunity.utils.net; + +import android.os.Build; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +public class SSLSocketFactoryCompat extends SSLSocketFactory{ + private static final String[] TLS_V12_ONLY = {"TLSv1.2"}; + + private final SSLSocketFactory delegate; + + public SSLSocketFactoryCompat() throws KeyManagementException, NoSuchAlgorithmException { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, null, null); + delegate = sc.getSocketFactory(); + } + + public SSLSocketFactoryCompat(SSLSocketFactory delegate) { + if (delegate == null) { + throw new NullPointerException(); + } + this.delegate = delegate; + } + + @Override + public String[] getDefaultCipherSuites() { + return delegate.getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return delegate.getSupportedCipherSuites(); + } + + private Socket enableTls12(Socket socket) { + if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 20) { + if (socket instanceof SSLSocket) { + ((SSLSocket) socket).setEnabledProtocols(TLS_V12_ONLY); + } + } + return socket; + } + + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + return enableTls12(delegate.createSocket(s, host, port, autoClose)); + } + + @Override + public Socket createSocket(String host, int port) throws IOException { + return enableTls12(delegate.createSocket(host, port)); + } + + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { + return enableTls12(delegate.createSocket(host, port, localHost, localPort)); + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + return enableTls12(delegate.createSocket(host, port)); + } + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + return enableTls12(delegate.createSocket(address, port, localAddress, localPort)); + } +} \ No newline at end of file diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/StickerDownloadHelper.java b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/StickerDownloadHelper.java new file mode 100644 index 000000000..393cf0dc3 --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/utils/net/StickerDownloadHelper.java @@ -0,0 +1,280 @@ +package com.yunbao.faceunity.utils.net; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Handler; +import android.os.Looper; +import android.util.ArrayMap; +import android.util.Log; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.yunbao.faceunity.entity.net.FineStickerEntity; +import com.yunbao.faceunity.utils.FaceUnityData; +import com.yunbao.faceunity.utils.FileUtils; +import com.yunbao.faceunity.utils.ZipUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; + +/** + * 道具下载 缓存 + * + * @author Richie on 2021.03.03 + */ +public final class StickerDownloadHelper { + private static final String TAG = "StickerDownloadHelper"; + private static final String URL_HOST = "https://items.faceunity.com:4006"; + private static final String URL_TAGS = URL_HOST + "/api/guest/tags?platform=mobile"; + private static final String URL_TOOLS = URL_HOST + "/api/guest/tools"; + private static final String URL_DOWNLOAD = URL_HOST + "/api/guest/download?id="; + public static final String STICKER_DIR_PATH = FileUtils.getExternalFileDir(FaceUnityData.mApplication) + "/fine_sticker"; + private final Handler mMainHandler = new Handler(Looper.getMainLooper()); + + private Gson gson; + private String[] mTags; + private Map mFineStickerEntityMap = new ArrayMap<>(); + + static { + File file = new File(STICKER_DIR_PATH); + if (!file.exists()) { + file.mkdir(); + } + } + + private StickerDownloadHelper() { + gson = new Gson(); + String tagArray = loadFormSp(TAG); + JsonArray array = gson.fromJson(tagArray, JsonArray.class); + if (null != array) { + mTags = new String[array.size()]; + for (int i = 0; i < array.size(); i++) { + mTags[i] = array.get(i).toString(); + mTags[i] = mTags[i].substring(1, mTags[i].length() - 1); // 后台把引号放进来了 + } + } else { + mTags = new String[0]; + } + for (int i = 0; i < mTags.length; i++) { + String json = loadFormSp(mTags[i]); + FineStickerEntity fineSticker = gson.fromJson(json, FineStickerEntity.class); + if (null != fineSticker) { + mFineStickerEntityMap.put(mTags[i], fineSticker); + } + } + } + + private static class StickerDownloadHelperHolder { + private static StickerDownloadHelper INSTANCE = new StickerDownloadHelper(); + } + + public static StickerDownloadHelper getInstance() { + return StickerDownloadHelperHolder.INSTANCE; + } + + public interface Callback { + void onGetTags(String[] tags); + + void onGetList(String tag, FineStickerEntity fineSticker); + + void onDownload(FineStickerEntity.DocsBean entity); + + void onDownloadError(FineStickerEntity.DocsBean entity, String msg); + } + + private Callback mCallback; + + public void setCallback(Callback callback) { + mCallback = callback; + } + + public String[] tags() { + // {"code":2,"message":"ok","data":["中级道具","高级道具","专业道具"]} + OkHttpUtils.getInstance().getAsEntity(URL_TAGS, new OkHttpUtils.OkHttpCallback() { + @Override + protected void onSuccess(JsonObject result) { + JsonArray array = null; + try { + array = result.getAsJsonArray("data"); + } catch (Exception e) { + e.printStackTrace(); + } + if (array == null) { + return; + } + mTags = new String[array.size()]; + for (int i = 0; i < array.size(); i++) { + mTags[i] = array.get(i).toString(); + mTags[i] = mTags[i].substring(1, mTags[i].length() - 1); // 后台把引号放进来了 + } + if (null != mCallback) { + mCallback.onGetTags(mTags); + } + saveToSp(TAG, array.toString()); + } + + @Override + protected void onFailure(String errorMsg) { + Log.e(TAG, URL_TAGS + " " + errorMsg); + } + }); + return mTags; + } + + /** + * 根据tag获取道具列表 + */ + public FineStickerEntity tools(String tag) { + if (mFineStickerEntityMap.get(tag) == null) { + FineStickerEntity entity = new FineStickerEntity(); + entity.setDocs(new ArrayList<>()); + mFineStickerEntityMap.put(tag, entity); + } + if (!mFineStickerEntityMap.get(tag).isOnline()) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("platform", "mobile"); + jsonObject.addProperty("tag", tag); + OkHttpUtils.getInstance().postJsonAsEntity(URL_TOOLS, jsonObject.toString(), new OkHttpUtils.OkHttpCallback() { + @Override + protected void onSuccess(JsonObject result) { + FineStickerEntity entity = gson.fromJson(result.get("data"), FineStickerEntity.class); + entity.setOnline(true); + mFineStickerEntityMap.put(tag, entity); + checkDownloaded(entity); + if (null != mCallback) { + mCallback.onGetList(tag, entity); + } + saveToSp(tag, result.get("data").toString()); + } + + @Override + protected void onFailure(String errorMsg) { + Log.e(TAG, URL_TOOLS + " " + errorMsg); + } + }); + } + checkDownloaded(mFineStickerEntityMap.get(tag)); + return mFineStickerEntityMap.get(tag); + } + + /** + * 获取道具下载地址 + * 获取完就直接开始下载了 + */ + public void download(FineStickerEntity.DocsBean entity) { + String url = URL_DOWNLOAD + entity.getTool().get_id() + "&platform=mobile"; + OkHttpUtils.getInstance().getAsEntity(url, new OkHttpUtils.OkHttpCallback() { + /** { + * "code": 2, + * "message": "ok", + * "data": { // 请自行下载url + * "url": "http://tools-manage.oss-cn-hangzhou.aliyuncs.com/0a176380-b33e-11e9-8e6a-35012f229fc1-enc.bundle?OSSAccessKeyId=LTAIZvD3ylHAD1vH&Expires=1615967910&Signature=2%2B0YwGKKidAWNqLHEXf0BtByQoI%3D" + * } + * } + */ + @Override + protected void onSuccess(JsonObject result) { + realDownload(result.getAsJsonObject("data").get("url").getAsString(), entity); + } + + @Override + protected void onFailure(String errorMsg) { + Log.e(TAG, url + " " + errorMsg); + if (null != mCallback) { + mCallback.onDownloadError(entity,errorMsg); + } + } + }); + } + + /** + * 下载道具 + */ + private void realDownload(String url, FineStickerEntity.DocsBean entity) { + File dest = new File(STICKER_DIR_PATH, entity.getTool().getBundle().getUid()); + OkHttpUtils.getInstance().downloadFileCallBackExecute(url, dest, new OkHttpUtils.OkHttpCallback() { + @Override + protected void onSuccess(File result) { + if (entity.getTool().getBundle().getUid().endsWith(".zip")) { + //请求成功和解压是一个原子操作 + //zip,解压 + boolean unZipSuccess = true; + String outPathString = STICKER_DIR_PATH + "/" + entity.getTool().getBundle().getUid().substring(0,entity.getTool().getBundle().getUid().lastIndexOf(".")); + try { + //获取解压后的文件名赋值 + ArrayList fileNameList = ZipUtils.unZipFolderWithFileName(STICKER_DIR_PATH + "/" + entity.getTool().getBundle().getUid(), outPathString); + if (fileNameList != null && !fileNameList.isEmpty()) + entity.setUpZipFilePaths(fileNameList); + else + unZipSuccess = false; + } catch (Exception e) { + e.printStackTrace(); + unZipSuccess = false; + } + + if (!unZipSuccess) { + if (null != mCallback) + runOnUiThread(()-> mCallback.onDownloadError(entity,"unZipFolder failed")); + return; + } + } + + entity.setFilePath(result.getAbsolutePath()); + if (null != mCallback) + runOnUiThread(()-> mCallback.onDownload(entity)); + } + + @Override + protected void onFailure(String errorMsg) { + Log.e(TAG, url + " " + errorMsg); + if (null != mCallback) + runOnUiThread(()-> mCallback.onDownloadError(entity,errorMsg)); + } + }); + } + + private void runOnUiThread(Runnable runnable) { + if (Thread.currentThread() == mMainHandler.getLooper().getThread()) { + runnable.run(); + } else { + mMainHandler.post(runnable); + } + } + + /************************** 缓存相关 **************************/ + + private void saveToSp(String key, String value) { + SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(FaceUnityData.mApplication.getPackageName(), Context.MODE_PRIVATE); + sp.edit().putString(key, value).apply(); + } + + private String loadFormSp(String key) { + SharedPreferences sp = FaceUnityData.mApplication.getSharedPreferences(FaceUnityData.mApplication.getPackageName(), Context.MODE_PRIVATE); + return sp.getString(key, ""); + } + + private void checkDownloaded(FineStickerEntity fineStickerEntity) { + if (null == fineStickerEntity.getDocs()) { + return; + } + String[] bundles = new File(STICKER_DIR_PATH).list(); + HashSet bundleSet = new HashSet<>(); + if (bundles != null && bundles.length > 0) { + Collections.addAll(bundleSet, bundles); + } + for (FineStickerEntity.DocsBean fineSticker : fineStickerEntity.getDocs()) { + if (bundleSet.contains(fineSticker.getTool().getBundle().getUid())) { + fineSticker.setFilePath(STICKER_DIR_PATH + "/" + fineSticker.getTool().getBundle().getUid()); + if (fineSticker.getTool().getBundle().getUid().endsWith(".zip")) { + //遍历解压文件地址 + String path = STICKER_DIR_PATH + "/" + fineSticker.getTool().getBundle().getUid().substring(0,fineSticker.getTool().getBundle().getUid().lastIndexOf(".")); + fineSticker.setUpZipFilePaths(FileUtils.getFileList(path)); + } + } + } + } +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/widget/CircleImageView.java b/FaceUnity/src/main/java/com/yunbao/faceunity/widget/CircleImageView.java new file mode 100644 index 000000000..eff65490c --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/widget/CircleImageView.java @@ -0,0 +1,463 @@ +/* + * Copyright 2014 - 2020 Henning Dodenhof + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yunbao.faceunity.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewOutlineProvider; +import android.widget.ImageView; + +import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.RequiresApi; + +import com.yunbao.faceunity.R; + + +/** + * Thanks for https://github.com/hdodenhof/CircleImageView + * Current version is 3.1.0 + */ +@SuppressWarnings("UnusedDeclaration") +public class CircleImageView extends ImageView { + + private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; + + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + private static final int COLORDRAWABLE_DIMENSION = 2; + + private static final int DEFAULT_BORDER_WIDTH = 0; + private static final int DEFAULT_BORDER_COLOR = Color.BLACK; + private static final int DEFAULT_CIRCLE_BACKGROUND_COLOR = Color.TRANSPARENT; + private static final boolean DEFAULT_BORDER_OVERLAY = false; + + private final RectF mDrawableRect = new RectF(); + private final RectF mBorderRect = new RectF(); + + private final Matrix mShaderMatrix = new Matrix(); + private final Paint mBitmapPaint = new Paint(); + private final Paint mBorderPaint = new Paint(); + private final Paint mCircleBackgroundPaint = new Paint(); + + private int mBorderColor = DEFAULT_BORDER_COLOR; + private int mBorderWidth = DEFAULT_BORDER_WIDTH; + private int mCircleBackgroundColor = DEFAULT_CIRCLE_BACKGROUND_COLOR; + + private Bitmap mBitmap; + private BitmapShader mBitmapShader; + private int mBitmapWidth; + private int mBitmapHeight; + + private float mDrawableRadius; + private float mBorderRadius; + + private ColorFilter mColorFilter; + + private boolean mReady; + private boolean mSetupPending; + private boolean mBorderOverlay; + private boolean mDisableCircularTransformation; + + public CircleImageView(Context context) { + super(context); + + init(); + } + + public CircleImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircleImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); + + mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH); + mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR); + mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY); + mCircleBackgroundColor = a.getColor(R.styleable.CircleImageView_civ_circle_background_color, DEFAULT_CIRCLE_BACKGROUND_COLOR); + + a.recycle(); + + init(); + } + + private void init() { + super.setScaleType(SCALE_TYPE); + mReady = true; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setOutlineProvider(new OutlineProvider()); + } + + if (mSetupPending) { + setup(); + mSetupPending = false; + } + } + + @Override + public ScaleType getScaleType() { + return SCALE_TYPE; + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (scaleType != SCALE_TYPE) { + throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); + } + } + + @Override + public void setAdjustViewBounds(boolean adjustViewBounds) { + if (adjustViewBounds) { + throw new IllegalArgumentException("adjustViewBounds not supported."); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (mDisableCircularTransformation) { + super.onDraw(canvas); + return; + } + + if (mBitmap == null) { + return; + } + + if (mCircleBackgroundColor != Color.TRANSPARENT) { + canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mCircleBackgroundPaint); + } + canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint); + if (mBorderWidth > 0) { + canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + @Override + public void setPadding(int left, int top, int right, int bottom) { + super.setPadding(left, top, right, bottom); + setup(); + } + + @Override + public void setPaddingRelative(int start, int top, int end, int bottom) { + super.setPaddingRelative(start, top, end, bottom); + setup(); + } + + public int getBorderColor() { + return mBorderColor; + } + + public void setBorderColor(@ColorInt int borderColor) { + if (borderColor == mBorderColor) { + return; + } + + mBorderColor = borderColor; + mBorderPaint.setColor(mBorderColor); + invalidate(); + } + + public int getCircleBackgroundColor() { + return mCircleBackgroundColor; + } + + public void setCircleBackgroundColor(@ColorInt int circleBackgroundColor) { + if (circleBackgroundColor == mCircleBackgroundColor) { + return; + } + + mCircleBackgroundColor = circleBackgroundColor; + mCircleBackgroundPaint.setColor(circleBackgroundColor); + invalidate(); + } + + public void setCircleBackgroundColorResource(@ColorRes int circleBackgroundRes) { + setCircleBackgroundColor(getContext().getResources().getColor(circleBackgroundRes)); + } + + public int getBorderWidth() { + return mBorderWidth; + } + + public void setBorderWidth(int borderWidth) { + if (borderWidth == mBorderWidth) { + return; + } + + mBorderWidth = borderWidth; + setup(); + } + + public boolean isBorderOverlay() { + return mBorderOverlay; + } + + public void setBorderOverlay(boolean borderOverlay) { + if (borderOverlay == mBorderOverlay) { + return; + } + + mBorderOverlay = borderOverlay; + setup(); + } + + public boolean isDisableCircularTransformation() { + return mDisableCircularTransformation; + } + + public void setDisableCircularTransformation(boolean disableCircularTransformation) { + if (mDisableCircularTransformation == disableCircularTransformation) { + return; + } + + mDisableCircularTransformation = disableCircularTransformation; + initializeBitmap(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + initializeBitmap(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + initializeBitmap(); + } + + @Override + public void setImageResource(@DrawableRes int resId) { + super.setImageResource(resId); + initializeBitmap(); + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + initializeBitmap(); + } + + @Override + public void setColorFilter(ColorFilter cf) { + if (cf == mColorFilter) { + return; + } + + mColorFilter = cf; + applyColorFilter(); + invalidate(); + } + + @Override + public ColorFilter getColorFilter() { + return mColorFilter; + } + + @SuppressWarnings("ConstantConditions") + private void applyColorFilter() { + // This might be called from setColorFilter during ImageView construction + // before member initialization has finished on API level <= 19. + if (mBitmapPaint != null) { + mBitmapPaint.setColorFilter(mColorFilter); + } + } + + private Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable == null) { + return null; + } + + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + try { + Bitmap bitmap; + + if (drawable instanceof ColorDrawable) { + bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private void initializeBitmap() { + if (mDisableCircularTransformation) { + mBitmap = null; + } else { + mBitmap = getBitmapFromDrawable(getDrawable()); + } + setup(); + } + + private void setup() { + if (!mReady) { + mSetupPending = true; + return; + } + + if (getWidth() == 0 && getHeight() == 0) { + return; + } + + if (mBitmap == null) { + invalidate(); + return; + } + + mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + mBitmapPaint.setAntiAlias(true); + mBitmapPaint.setDither(true); + mBitmapPaint.setFilterBitmap(true); + mBitmapPaint.setShader(mBitmapShader); + + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setAntiAlias(true); + mBorderPaint.setColor(mBorderColor); + mBorderPaint.setStrokeWidth(mBorderWidth); + + mCircleBackgroundPaint.setStyle(Paint.Style.FILL); + mCircleBackgroundPaint.setAntiAlias(true); + mCircleBackgroundPaint.setColor(mCircleBackgroundColor); + + mBitmapHeight = mBitmap.getHeight(); + mBitmapWidth = mBitmap.getWidth(); + + mBorderRect.set(calculateBounds()); + mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f); + + mDrawableRect.set(mBorderRect); + if (!mBorderOverlay && mBorderWidth > 0) { + mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f); + } + mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f); + + applyColorFilter(); + updateShaderMatrix(); + invalidate(); + } + + private RectF calculateBounds() { + int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight(); + int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom(); + + int sideLength = Math.min(availableWidth, availableHeight); + + float left = getPaddingLeft() + (availableWidth - sideLength) / 2f; + float top = getPaddingTop() + (availableHeight - sideLength) / 2f; + + return new RectF(left, top, left + sideLength, top + sideLength); + } + + private void updateShaderMatrix() { + float scale; + float dx = 0; + float dy = 0; + + mShaderMatrix.set(null); + + if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { + scale = mDrawableRect.height() / (float) mBitmapHeight; + dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; + } else { + scale = mDrawableRect.width() / (float) mBitmapWidth; + dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; + } + + mShaderMatrix.setScale(scale, scale); + mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top); + + mBitmapShader.setLocalMatrix(mShaderMatrix); + } + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mDisableCircularTransformation) { + return super.onTouchEvent(event); + } + + return inTouchableArea(event.getX(), event.getY()) && super.onTouchEvent(event); + } + + private boolean inTouchableArea(float x, float y) { + if (mBorderRect.isEmpty()) { + return true; + } + + return Math.pow(x - mBorderRect.centerX(), 2) + Math.pow(y - mBorderRect.centerY(), 2) <= Math.pow(mBorderRadius, 2); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private class OutlineProvider extends ViewOutlineProvider { + + @Override + public void getOutline(View view, Outline outline) { + if (mDisableCircularTransformation) { + ViewOutlineProvider.BACKGROUND.getOutline(view, outline); + } else { + Rect bounds = new Rect(); + mBorderRect.roundOut(bounds); + outline.setRoundRect(bounds, bounds.width() / 2.0f); + } + } + + } + +} diff --git a/FaceUnity/src/main/java/com/yunbao/faceunity/widget/TouchStateImageView.java b/FaceUnity/src/main/java/com/yunbao/faceunity/widget/TouchStateImageView.java new file mode 100644 index 000000000..6a54842ca --- /dev/null +++ b/FaceUnity/src/main/java/com/yunbao/faceunity/widget/TouchStateImageView.java @@ -0,0 +1,91 @@ +package com.yunbao.faceunity.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + + +/** + * Touch 事件时支持 state 变换 + * + * @author Richie on 2018.09.20 + */ +public class TouchStateImageView extends AppCompatImageView { + private OnTouchStateListener mOnTouchStateListener; + + public TouchStateImageView(Context context) { + super(context); + } + + public TouchStateImageView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public TouchStateImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public void setOnTouchStateListener(OnTouchStateListener onTouchStateListener) { + mOnTouchStateListener = onTouchStateListener; + } + + @Override + public void setOnTouchListener(final OnTouchListener l) { + OnTouchListener onTouchListener = new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + setState(event); + boolean ret = l.onTouch(v, event); + if (!ret && mOnTouchStateListener != null) { + return mOnTouchStateListener.onTouch(v, event); + } else { + return ret; + } + } + }; + super.setOnTouchListener(onTouchListener); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + setState(event); + if (mOnTouchStateListener != null) { + return mOnTouchStateListener.onTouch(this, event); + } else { + return super.onTouchEvent(event); + } + } + + private void setState(MotionEvent event) { + int action = event.getAction(); + if (action == MotionEvent.ACTION_DOWN) { + setSelected(true); + } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + setSelected(false); + } + } + + /** + * Interface definition for a callback to be invoked when a touch event is + * dispatched to this view. The callback will be invoked before the touch + * event is given to the view. + */ + public interface OnTouchStateListener { + /** + * Called when a touch event is dispatched to a view. This allows listeners to + * get a chance to respond before the target view. + * + * @param v The view the touch event has been dispatched to. + * @param event The MotionEvent object containing full information about + * the event. + * @return True if the listener has consumed the event, false otherwise. + */ + boolean onTouch(View v, MotionEvent event); + + + } +} diff --git a/FaceUnity/src/main/res/color/bottom_radio_color.xml b/FaceUnity/src/main/res/color/bottom_radio_color.xml new file mode 100644 index 000000000..c7338f3b2 --- /dev/null +++ b/FaceUnity/src/main/res/color/bottom_radio_color.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/color/dsb_progress_color_list.xml b/FaceUnity/src/main/res/color/dsb_progress_color_list.xml new file mode 100644 index 000000000..6f2ebb433 --- /dev/null +++ b/FaceUnity/src/main/res/color/dsb_progress_color_list.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/color/dsb_ripple_color_list.xml b/FaceUnity/src/main/res/color/dsb_ripple_color_list.xml new file mode 100644 index 000000000..44850abd1 --- /dev/null +++ b/FaceUnity/src/main/res/color/dsb_ripple_color_list.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/color/dsb_track_color_list.xml b/FaceUnity/src/main/res/color/dsb_track_color_list.xml new file mode 100644 index 000000000..9259d9e5f --- /dev/null +++ b/FaceUnity/src/main/res/color/dsb_track_color_list.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/color/tv_main_color_selector.xml b/FaceUnity/src/main/res/color/tv_main_color_selector.xml new file mode 100644 index 000000000..180d724e5 --- /dev/null +++ b/FaceUnity/src/main/res/color/tv_main_color_selector.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_confirm_dialog.xml b/FaceUnity/src/main/res/drawable/bg_confirm_dialog.xml new file mode 100644 index 000000000..4b7303f52 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_confirm_dialog.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_confirm_dialog_option.xml b/FaceUnity/src/main/res/drawable/bg_confirm_dialog_option.xml new file mode 100644 index 000000000..fecf83b9e --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_confirm_dialog_option.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_control_oval2_selector.xml b/FaceUnity/src/main/res/drawable/bg_control_oval2_selector.xml new file mode 100644 index 000000000..ade9e3579 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_control_oval2_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_control_oval_selector.xml b/FaceUnity/src/main/res/drawable/bg_control_oval_selector.xml new file mode 100644 index 000000000..2dd990cf8 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_control_oval_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_control_square2_selector.xml b/FaceUnity/src/main/res/drawable/bg_control_square2_selector.xml new file mode 100644 index 000000000..a9b68b517 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_control_square2_selector.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_control_square_selector.xml b/FaceUnity/src/main/res/drawable/bg_control_square_selector.xml new file mode 100644 index 000000000..10a6269a3 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_control_square_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_radio_group.xml b/FaceUnity/src/main/res/drawable/bg_radio_group.xml new file mode 100644 index 000000000..5f5d2c37d --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_radio_group.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_radio_left.xml b/FaceUnity/src/main/res/drawable/bg_radio_left.xml new file mode 100644 index 000000000..e7599d96a --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_radio_left.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_radio_left_check.xml b/FaceUnity/src/main/res/drawable/bg_radio_left_check.xml new file mode 100644 index 000000000..977b89c64 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_radio_left_check.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_radio_left_selector.xml b/FaceUnity/src/main/res/drawable/bg_radio_left_selector.xml new file mode 100644 index 000000000..c37ababf2 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_radio_left_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_radio_middle.xml b/FaceUnity/src/main/res/drawable/bg_radio_middle.xml new file mode 100644 index 000000000..1725e000e --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_radio_middle.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_radio_right.xml b/FaceUnity/src/main/res/drawable/bg_radio_right.xml new file mode 100644 index 000000000..2051e5e83 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_radio_right.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_radio_right_check.xml b/FaceUnity/src/main/res/drawable/bg_radio_right_check.xml new file mode 100644 index 000000000..f2fb3b700 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_radio_right_check.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_radio_right_selector.xml b/FaceUnity/src/main/res/drawable/bg_radio_right_selector.xml new file mode 100644 index 000000000..9e121fe6b --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_radio_right_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_seek_bar.xml b/FaceUnity/src/main/res/drawable/bg_seek_bar.xml new file mode 100644 index 000000000..f4454ddb2 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_seek_bar.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/FaceUnity/src/main/res/drawable/bg_shape_oval2_theme.xml b/FaceUnity/src/main/res/drawable/bg_shape_oval2_theme.xml new file mode 100644 index 000000000..b96b25912 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_shape_oval2_theme.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_shape_oval_theme.xml b/FaceUnity/src/main/res/drawable/bg_shape_oval_theme.xml new file mode 100644 index 000000000..a1f311960 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_shape_oval_theme.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_shape_rect2_theme.xml b/FaceUnity/src/main/res/drawable/bg_shape_rect2_theme.xml new file mode 100644 index 000000000..f06b2bd46 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_shape_rect2_theme.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_shape_rect_theme.xml b/FaceUnity/src/main/res/drawable/bg_shape_rect_theme.xml new file mode 100644 index 000000000..2f9cae221 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_shape_rect_theme.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/bg_toast_more.xml b/FaceUnity/src/main/res/drawable/bg_toast_more.xml new file mode 100644 index 000000000..f6ad08a0f --- /dev/null +++ b/FaceUnity/src/main/res/drawable/bg_toast_more.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_angle_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_angle_close_selector.xml new file mode 100644 index 000000000..41d26f99c --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_angle_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_angle_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_angle_open_selector.xml new file mode 100644 index 000000000..7254807ee --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_angle_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_height_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_height_close_selector.xml new file mode 100644 index 000000000..57b1ab4d0 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_height_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_height_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_height_open_selector.xml new file mode 100644 index 000000000..33ef8ecdf --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_height_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_space_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_space_close_selector.xml new file mode 100644 index 000000000..f86e0320b --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_space_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_space_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_space_open_selector.xml new file mode 100644 index 000000000..aaf636905 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_brow_space_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_cheek_bones_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_cheek_bones_close_selector.xml new file mode 100644 index 000000000..82f59fddd --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_cheek_bones_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_cheek_bones_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_cheek_bones_open_selector.xml new file mode 100644 index 000000000..883a58393 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_cheek_bones_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_chin_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_chin_close_selector.xml new file mode 100644 index 000000000..0d0be92a9 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_chin_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_chin_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_chin_open_selector.xml new file mode 100644 index 000000000..934ea564e --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_chin_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_distance_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_distance_close_selector.xml new file mode 100644 index 000000000..8e9e8136f --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_distance_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_distance_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_distance_open_selector.xml new file mode 100644 index 000000000..06b5a434c --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_distance_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_enlarge_eye_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_enlarge_eye_close_selector.xml new file mode 100644 index 000000000..8e68aa5a3 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_enlarge_eye_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_enlarge_eye_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_enlarge_eye_open_selector.xml new file mode 100644 index 000000000..cdd04dcc9 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_enlarge_eye_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_cheekthin_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_cheekthin_close_selector.xml new file mode 100644 index 000000000..59fab5797 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_cheekthin_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_cheekthin_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_cheekthin_open_selector.xml new file mode 100644 index 000000000..b0ca206a6 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_cheekthin_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_little_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_little_close_selector.xml new file mode 100644 index 000000000..4276d959b --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_little_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_little_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_little_open_selector.xml new file mode 100644 index 000000000..faef91e0d --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_little_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_narrow_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_narrow_close_selector.xml new file mode 100644 index 000000000..71903f9f4 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_narrow_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_narrow_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_narrow_open_selector.xml new file mode 100644 index 000000000..6015ad7c7 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_narrow_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_short_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_short_close_selector.xml new file mode 100644 index 000000000..c0a88e6aa --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_short_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_short_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_short_open_selector.xml new file mode 100644 index 000000000..fcb3174e2 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_short_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_v_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_v_close_selector.xml new file mode 100644 index 000000000..e12998754 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_v_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_v_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_v_open_selector.xml new file mode 100644 index 000000000..8a3258cdb --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_face_v_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_forehead_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_forehead_close_selector.xml new file mode 100644 index 000000000..f96ee3801 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_forehead_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_forehead_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_forehead_open_selector.xml new file mode 100644 index 000000000..f30be5ac2 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_forehead_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_lower_jaw_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_lower_jaw_close_selector.xml new file mode 100644 index 000000000..10415b9f5 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_lower_jaw_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_lower_jaw_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_lower_jaw_open_selector.xml new file mode 100644 index 000000000..43a12f695 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_lower_jaw_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_mouth_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_mouth_close_selector.xml new file mode 100644 index 000000000..a376c9c6e --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_mouth_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_mouth_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_mouth_open_selector.xml new file mode 100644 index 000000000..fbcad5370 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_mouth_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_open_eyes_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_open_eyes_close_selector.xml new file mode 100644 index 000000000..c2f742bec --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_open_eyes_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_open_eyes_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_open_eyes_open_selector.xml new file mode 100644 index 000000000..fb9fa082d --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_open_eyes_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_proboscis_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_proboscis_close_selector.xml new file mode 100644 index 000000000..bb561ed08 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_proboscis_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_proboscis_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_proboscis_open_selector.xml new file mode 100644 index 000000000..7b105c95d --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_proboscis_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_round_eye_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_round_eye_close_selector.xml new file mode 100644 index 000000000..6990d6f05 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_round_eye_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_round_eye_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_round_eye_open_selector.xml new file mode 100644 index 000000000..ab235f69f --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_round_eye_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_shrinking_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_shrinking_close_selector.xml new file mode 100644 index 000000000..dd7fb492e --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_shrinking_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_shrinking_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_shrinking_open_selector.xml new file mode 100644 index 000000000..984626418 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_shrinking_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_smile_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_smile_close_selector.xml new file mode 100644 index 000000000..4e3353ab3 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_smile_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_smile_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_smile_open_selector.xml new file mode 100644 index 000000000..aad751b95 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_smile_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_thin_nose_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_thin_nose_close_selector.xml new file mode 100644 index 000000000..6de232e9a --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_thin_nose_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_shape_thin_nose_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_shape_thin_nose_open_selector.xml new file mode 100644 index 000000000..c6fbc1f25 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_shape_thin_nose_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_buffing_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_buffing_close_selector.xml new file mode 100644 index 000000000..9c46501b1 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_buffing_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_buffing_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_buffing_open_selector.xml new file mode 100644 index 000000000..cfbd51a46 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_buffing_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_color_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_color_close_selector.xml new file mode 100644 index 000000000..57f0c0f1c --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_color_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_color_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_color_open_selector.xml new file mode 100644 index 000000000..284fabc2b --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_color_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_dark_circles_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_dark_circles_close_selector.xml new file mode 100644 index 000000000..30cb39c8f --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_dark_circles_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_dark_circles_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_dark_circles_open_selector.xml new file mode 100644 index 000000000..b2b7db2e2 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_dark_circles_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_eyes_bright_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_eyes_bright_close_selector.xml new file mode 100644 index 000000000..89227b2cc --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_eyes_bright_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_eyes_bright_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_eyes_bright_open_selector.xml new file mode 100644 index 000000000..8ca8afa82 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_eyes_bright_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_red_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_red_close_selector.xml new file mode 100644 index 000000000..35d515d68 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_red_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_red_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_red_open_selector.xml new file mode 100644 index 000000000..ae7fde13e --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_red_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_sharpen_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_sharpen_close_selector.xml new file mode 100644 index 000000000..854fe0dc8 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_sharpen_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_sharpen_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_sharpen_open_selector.xml new file mode 100644 index 000000000..5d81e38c6 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_sharpen_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_teeth_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_teeth_close_selector.xml new file mode 100644 index 000000000..656a32026 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_teeth_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_teeth_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_teeth_open_selector.xml new file mode 100644 index 000000000..0cf8a500a --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_teeth_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_wrinkle_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_wrinkle_close_selector.xml new file mode 100644 index 000000000..df777a4b2 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_wrinkle_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_skin_wrinkle_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_skin_wrinkle_open_selector.xml new file mode 100644 index 000000000..ac097210d --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_skin_wrinkle_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_style_1_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_style_1_selector.xml new file mode 100644 index 000000000..e9f3c0614 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_style_1_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_style_2_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_style_2_selector.xml new file mode 100644 index 000000000..39acf826a --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_style_2_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_style_3_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_style_3_selector.xml new file mode 100644 index 000000000..5e023ce8a --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_style_3_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_style_4_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_style_4_selector.xml new file mode 100644 index 000000000..316c1337e --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_style_4_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_style_5_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_style_5_selector.xml new file mode 100644 index 000000000..7f3dfd3d0 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_style_5_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_style_6_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_style_6_selector.xml new file mode 100644 index 000000000..ce3cff002 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_style_6_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_style_7_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_style_7_selector.xml new file mode 100644 index 000000000..d2b1ab3ca --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_style_7_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_beauty_style_none_selector.xml b/FaceUnity/src/main/res/drawable/icon_beauty_style_none_selector.xml new file mode 100644 index 000000000..04cd43a81 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_beauty_style_none_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_hip_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_hip_close_selector.xml new file mode 100644 index 000000000..6182ca304 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_hip_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_hip_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_hip_open_selector.xml new file mode 100644 index 000000000..147df52a1 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_hip_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_little_head_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_little_head_close_selector.xml new file mode 100644 index 000000000..971404c0c --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_little_head_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_little_head_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_little_head_open_selector.xml new file mode 100644 index 000000000..71df7d760 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_little_head_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_shoulder_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_shoulder_close_selector.xml new file mode 100644 index 000000000..d79248402 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_shoulder_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_shoulder_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_shoulder_open_selector.xml new file mode 100644 index 000000000..3c82e5998 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_shoulder_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_slimming_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_slimming_close_selector.xml new file mode 100644 index 000000000..cb09db6fd --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_slimming_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_slimming_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_slimming_open_selector.xml new file mode 100644 index 000000000..95bf22e7f --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_slimming_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_stovepipe_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_stovepipe_close_selector.xml new file mode 100644 index 000000000..16d104fdd --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_stovepipe_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_stovepipe_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_stovepipe_open_selector.xml new file mode 100644 index 000000000..6078524a4 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_stovepipe_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_thin_leg_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_thin_leg_close_selector.xml new file mode 100644 index 000000000..473cc7dad --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_thin_leg_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_thin_leg_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_thin_leg_open_selector.xml new file mode 100644 index 000000000..2828a71e8 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_thin_leg_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_waist_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_waist_close_selector.xml new file mode 100644 index 000000000..2200d900f --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_waist_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_body_waist_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_body_waist_open_selector.xml new file mode 100644 index 000000000..d65381a30 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_body_waist_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_color_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_color_selector.xml new file mode 100644 index 000000000..72739e218 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_color_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_safe_area_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_safe_area_close_selector.xml new file mode 100644 index 000000000..ba35bae71 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_safe_area_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_safe_area_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_safe_area_open_selector.xml new file mode 100644 index 000000000..984f952a9 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_safe_area_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_similarityr_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_similarityr_close_selector.xml new file mode 100644 index 000000000..87c9aee8b --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_similarityr_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_similarityr_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_similarityr_open_selector.xml new file mode 100644 index 000000000..52e0f381b --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_similarityr_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_smooth_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_smooth_close_selector.xml new file mode 100644 index 000000000..30bdffb22 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_smooth_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_smooth_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_smooth_open_selector.xml new file mode 100644 index 000000000..e604dacaa --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_smooth_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_transparency_close_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_transparency_close_selector.xml new file mode 100644 index 000000000..20c757d1c --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_transparency_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/drawable/icon_green_transparency_open_selector.xml b/FaceUnity/src/main/res/drawable/icon_green_transparency_open_selector.xml new file mode 100644 index 000000000..3ee451af8 --- /dev/null +++ b/FaceUnity/src/main/res/drawable/icon_green_transparency_open_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/layout/dialog_confirm.xml b/FaceUnity/src/main/res/layout/dialog_confirm.xml new file mode 100644 index 000000000..a0652da86 --- /dev/null +++ b/FaceUnity/src/main/res/layout/dialog_confirm.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/layout/layout_animo_control.xml b/FaceUnity/src/main/res/layout/layout_animo_control.xml new file mode 100644 index 000000000..7edcd738b --- /dev/null +++ b/FaceUnity/src/main/res/layout/layout_animo_control.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/FaceUnity/src/main/res/layout/layout_body_beauty_control.xml b/FaceUnity/src/main/res/layout/layout_body_beauty_control.xml new file mode 100644 index 000000000..456a31925 --- /dev/null +++ b/FaceUnity/src/main/res/layout/layout_body_beauty_control.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/layout/layout_effect_control.xml b/FaceUnity/src/main/res/layout/layout_effect_control.xml new file mode 100644 index 000000000..4083e6262 --- /dev/null +++ b/FaceUnity/src/main/res/layout/layout_effect_control.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/FaceUnity/src/main/res/layout/layout_face_beauty_control.xml b/FaceUnity/src/main/res/layout/layout_face_beauty_control.xml new file mode 100644 index 000000000..07307f4f5 --- /dev/null +++ b/FaceUnity/src/main/res/layout/layout_face_beauty_control.xml @@ -0,0 +1,200 @@ + + + + + + + +