From 43b4650ee37db475fa9ce7fa06e4b909b0db8e5e Mon Sep 17 00:00:00 2001 From: "JSD\\13999" <1399945104@qq.com> Date: Tue, 26 May 2026 17:55:41 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E9=BD=90=E5=A4=87=E4=BB=BD=E5=B7=A5?= =?UTF-8?q?=E7=A8=8B=E6=89=93=E5=BC=80=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/AppsFlyer.meta | 8 + Assets/AppsFlyer/AFAdRevenueEvent.cs | 34 + Assets/AppsFlyer/AFAdRevenueEvent.cs.meta | 11 + Assets/AppsFlyer/AFInAppEvents.cs | 73 + Assets/AppsFlyer/AFInAppEvents.cs.meta | 11 + Assets/AppsFlyer/AFMiniJSON.cs | 547 ++ Assets/AppsFlyer/AFMiniJSON.cs.meta | 11 + Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs | 35 + .../AFPurchaseDetailsAndroid.cs.meta | 11 + Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs | 30 + .../AppsFlyer/AFSDKPurchaseDetailsIOS.cs.meta | 11 + Assets/AppsFlyer/AFSDKValidateAndLogResult.cs | 38 + .../AFSDKValidateAndLogResult.cs.meta | 11 + Assets/AppsFlyer/AppsFlyer.asmdef | 13 + Assets/AppsFlyer/AppsFlyer.asmdef.meta | 7 + Assets/AppsFlyer/AppsFlyer.cs | 1087 ++++ Assets/AppsFlyer/AppsFlyer.cs.meta | 11 + Assets/AppsFlyer/AppsFlyerAdRevenue.cs | 178 + Assets/AppsFlyer/AppsFlyerAdRevenue.cs.meta | 11 + Assets/AppsFlyer/AppsFlyerAndroid.cs | 779 +++ Assets/AppsFlyer/AppsFlyerAndroid.cs.meta | 11 + Assets/AppsFlyer/AppsFlyerConsent.cs | 51 + Assets/AppsFlyer/AppsFlyerConsent.cs.meta | 11 + Assets/AppsFlyer/AppsFlyerEventArgs.cs | 218 + Assets/AppsFlyer/AppsFlyerEventArgs.cs.meta | 11 + Assets/AppsFlyer/AppsFlyerObject.prefab | 49 + Assets/AppsFlyer/AppsFlyerObject.prefab.meta | 7 + Assets/AppsFlyer/AppsFlyerObjectScript.cs | 70 + .../AppsFlyer/AppsFlyerObjectScript.cs.meta | 11 + Assets/AppsFlyer/AppsFlyeriOS.cs | 997 +++ Assets/AppsFlyer/AppsFlyeriOS.cs.meta | 11 + Assets/AppsFlyer/Editor.meta | 8 + .../AppsFlyer/Editor/AppsFlyer.Editor.asmdef | 17 + .../Editor/AppsFlyer.Editor.asmdef.meta | 7 + .../Editor/AppsFlyerAdRevenueDependencies.xml | 13 + .../AppsFlyerAdRevenueDependencies.xml.meta | 7 + .../Editor/AppsFlyerDependencies.xml | 18 + .../Editor/AppsFlyerDependencies.xml.meta | 7 + .../AppsFlyer/Editor/AppsFlyerObjectEditor.cs | 84 + .../Editor/AppsFlyerObjectEditor.cs.meta | 11 + Assets/AppsFlyer/Editor/appsflyer_logo.png | Bin 0 -> 9426 bytes .../AppsFlyer/Editor/appsflyer_logo.png.meta | 92 + Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs | 31 + .../AppsFlyer/IAppsFlyerAndroidBridge.cs.meta | 11 + Assets/AppsFlyer/IAppsFlyerConversionData.cs | 31 + .../IAppsFlyerConversionData.cs.meta | 11 + Assets/AppsFlyer/IAppsFlyerIOSBridge.cs | 26 + Assets/AppsFlyer/IAppsFlyerIOSBridge.cs.meta | 11 + Assets/AppsFlyer/IAppsFlyerNativeBridge.cs | 74 + .../AppsFlyer/IAppsFlyerNativeBridge.cs.meta | 11 + Assets/AppsFlyer/IAppsFlyerUserInvite.cs | 26 + Assets/AppsFlyer/IAppsFlyerUserInvite.cs.meta | 11 + Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs | 19 + .../IAppsFlyerValidateAndLog.cs.meta | 11 + Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs | 19 + .../IAppsFlyerValidateReceipt.cs.meta | 11 + Assets/AppsFlyer/Mac.meta | 8 + .../AppsFlyer/Mac/AppsFlyerBundle.bundle.meta | 33 + .../Mac/AppsFlyerBundle.bundle/Contents.meta | 8 + .../Contents/Info.plist | 48 + .../Contents/Info.plist.meta | 7 + .../Contents/MacOS.meta | 8 + .../Contents/MacOS/AppsFlyerBundle | Bin 0 -> 1132768 bytes .../Contents/MacOS/AppsFlyerBundle.meta | 7 + .../Contents/_CodeSignature.meta | 8 + .../Contents/_CodeSignature/CodeResources | 115 + .../_CodeSignature/CodeResources.meta | 7 + Assets/AppsFlyer/Plugins.meta | 8 + Assets/AppsFlyer/Plugins/iOS.meta | 8 + Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h | 22 + .../AppsFlyer/Plugins/iOS/AFUnityUtils.h.meta | 27 + Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm | 145 + .../Plugins/iOS/AFUnityUtils.mm.meta | 37 + .../Plugins/iOS/AppsFlyer+AppController.m | 132 + .../iOS/AppsFlyer+AppController.m.meta | 37 + .../Plugins/iOS/AppsFlyerAdRevenueWrapper.h | 16 + .../iOS/AppsFlyerAdRevenueWrapper.h.meta | 27 + .../Plugins/iOS/AppsFlyerAdRevenueWrapper.mm | 51 + .../iOS/AppsFlyerAdRevenueWrapper.mm.meta | 37 + .../Plugins/iOS/AppsFlyerAppController.mm | 126 + .../iOS/AppsFlyerAppController.mm.meta | 37 + .../Plugins/iOS/AppsFlyerAttribution.h | 34 + .../Plugins/iOS/AppsFlyerAttribution.h.meta | 27 + .../Plugins/iOS/AppsFlyerAttribution.m | 86 + .../Plugins/iOS/AppsFlyerAttribution.m.meta | 37 + .../Plugins/iOS/AppsFlyeriOSWrapper.h | 50 + .../Plugins/iOS/AppsFlyeriOSWrapper.h.meta | 27 + .../Plugins/iOS/AppsFlyeriOSWrapper.mm | 370 ++ .../Plugins/iOS/AppsFlyeriOSWrapper.mm.meta | 37 + .../AppsFlyer/Plugins/iOS/SwiftForUnity.swift | 1 + .../Plugins/iOS/SwiftForUnity.swift.meta | 37 + Assets/AppsFlyer/Tests.meta | 8 + Assets/AppsFlyer/Tests/Castle.Core.dll | Bin 0 -> 442368 bytes Assets/AppsFlyer/Tests/Castle.Core.dll.meta | 33 + Assets/AppsFlyer/Tests/NSubstitute.dll | Bin 0 -> 152064 bytes Assets/AppsFlyer/Tests/NSubstitute.dll.meta | 33 + ...System.Runtime.CompilerServices.Unsafe.dll | Bin 0 -> 18024 bytes ...m.Runtime.CompilerServices.Unsafe.dll.meta | 33 + .../System.Threading.Tasks.Extensions.dll | Bin 0 -> 25984 bytes ...System.Threading.Tasks.Extensions.dll.meta | 33 + Assets/AppsFlyer/Tests/Tests.asmdef | 24 + Assets/AppsFlyer/Tests/Tests.asmdef.meta | 7 + Assets/AppsFlyer/Tests/Tests_Suite.cs | 810 +++ Assets/AppsFlyer/Tests/Tests_Suite.cs.meta | 11 + Assets/AppsFlyer/Windows.meta | 8 + Assets/AppsFlyer/Windows/AppsFlyerLib.pri | Bin 0 -> 672 bytes .../AppsFlyer/Windows/AppsFlyerLib.pri.meta | 7 + Assets/AppsFlyer/Windows/AppsFlyerLib.winmd | Bin 0 -> 45056 bytes .../AppsFlyer/Windows/AppsFlyerLib.winmd.meta | 38 + Assets/AppsFlyer/Windows/AppsFlyerWindows.cs | 145 + .../Windows/AppsFlyerWindows.cs.meta | 11 + Assets/AppsFlyer/package.json | 8 + Assets/AppsFlyer/package.json.meta | 7 + Assets/MaxSdk.meta | 8 + Assets/MaxSdk/AppLovin.meta | 8 + Assets/MaxSdk/AppLovin/Editor.meta | 8 + .../MaxSdk/AppLovin/Editor/Dependencies.xml | 9 + .../AppLovin/Editor/Dependencies.xml.meta | 10 + Assets/MaxSdk/AppLovin/Plugins.meta | 8 + Assets/MaxSdk/AppLovin/Plugins/Android.meta | 8 + .../Android/applovin-max-unity-plugin.aar | Bin 0 -> 42544 bytes .../applovin-max-unity-plugin.aar.meta | 35 + Assets/MaxSdk/AppLovin/Plugins/iOS.meta | 8 + .../AppLovin/Plugins/iOS/MAUnityAdManager.h | 106 + .../Plugins/iOS/MAUnityAdManager.h.meta | 115 + .../AppLovin/Plugins/iOS/MAUnityAdManager.m | 2084 +++++++ .../Plugins/iOS/MAUnityAdManager.m.meta | 109 + .../AppLovin/Plugins/iOS/MAUnityPlugin.mm | 1146 ++++ .../Plugins/iOS/MAUnityPlugin.mm.meta | 109 + Assets/MaxSdk/Mediation.meta | 11 + Assets/MaxSdk/Mediation/Facebook.meta | 8 + Assets/MaxSdk/Mediation/Facebook/Editor.meta | 11 + .../Facebook/Editor/Dependencies.xml | 13 + .../Facebook/Editor/Dependencies.xml.meta | 10 + Assets/MaxSdk/Mediation/Fyber.meta | 8 + Assets/MaxSdk/Mediation/Fyber/Editor.meta | 11 + .../Mediation/Fyber/Editor/Dependencies.xml | 9 + .../Fyber/Editor/Dependencies.xml.meta | 10 + Assets/MaxSdk/Mediation/Google.meta | 8 + Assets/MaxSdk/Mediation/Google/Editor.meta | 11 + .../Mediation/Google/Editor/Dependencies.xml | 10 + .../Google/Editor/Dependencies.xml.meta | 10 + Assets/MaxSdk/Mediation/IronSource.meta | 8 + .../MaxSdk/Mediation/IronSource/Editor.meta | 11 + .../IronSource/Editor/Dependencies.xml | 13 + .../IronSource/Editor/Dependencies.xml.meta | 10 + Assets/MaxSdk/Mediation/MediationAdapters.txt | 2 + .../Mediation/MediationAdapters.txt.meta | 6 + Assets/MaxSdk/Mediation/UnityAds.meta | 8 + Assets/MaxSdk/Mediation/UnityAds/Editor.meta | 11 + .../UnityAds/Editor/Dependencies.xml | 9 + .../UnityAds/Editor/Dependencies.xml.meta | 10 + Assets/MaxSdk/Mediation/Vungle.meta | 8 + Assets/MaxSdk/Mediation/Vungle/Editor.meta | 11 + .../Mediation/Vungle/Editor/Dependencies.xml | 9 + .../Vungle/Editor/Dependencies.xml.meta | 10 + Assets/MaxSdk/Prefabs.meta | 8 + Assets/MaxSdk/Prefabs/BannerBottom.prefab | 402 ++ .../MaxSdk/Prefabs/BannerBottom.prefab.meta | 10 + Assets/MaxSdk/Prefabs/BannerTop.prefab | 402 ++ Assets/MaxSdk/Prefabs/BannerTop.prefab.meta | 10 + Assets/MaxSdk/Prefabs/Interstitial.prefab | 523 ++ .../MaxSdk/Prefabs/Interstitial.prefab.meta | 10 + Assets/MaxSdk/Prefabs/Rewarded.prefab | 795 +++ Assets/MaxSdk/Prefabs/Rewarded.prefab.meta | 10 + Assets/MaxSdk/Resources.meta | 8 + .../MaxSdk/Resources/AppLovinSettings.asset | 36 + .../Resources/AppLovinSettings.asset.meta | 8 + Assets/MaxSdk/Resources/Images.meta | 8 + Assets/MaxSdk/Resources/Images/alert_icon.png | Bin 0 -> 1154 bytes .../Resources/Images/alert_icon.png.meta | 94 + .../Resources/Images/uninstall_icon.png | Bin 0 -> 159 bytes .../Resources/Images/uninstall_icon.png.meta | 94 + .../MaxSdk/Resources/Images/warning_icon.png | Bin 0 -> 959 bytes .../Resources/Images/warning_icon.png.meta | 91 + Assets/MaxSdk/Scripts.meta | 8 + Assets/MaxSdk/Scripts/IntegrationManager.meta | 11 + .../Scripts/IntegrationManager/Editor.meta | 11 + .../Editor/AppLovinAutoUpdater.cs | 172 + .../Editor/AppLovinAutoUpdater.cs.meta | 14 + .../Editor/AppLovinCommandLine.cs | 94 + .../Editor/AppLovinCommandLine.cs.meta | 14 + .../Editor/AppLovinEditorCoroutine.cs | 91 + .../Editor/AppLovinEditorCoroutine.cs.meta | 14 + .../Editor/AppLovinInitialize.cs | 141 + .../Editor/AppLovinInitialize.cs.meta | 14 + .../Editor/AppLovinIntegrationManager.cs | 754 +++ .../Editor/AppLovinIntegrationManager.cs.meta | 14 + .../AppLovinIntegrationManagerWindow.cs | 1131 ++++ .../AppLovinIntegrationManagerWindow.cs.meta | 14 + .../Editor/AppLovinInternalSettings.cs | 297 + .../Editor/AppLovinInternalSettings.cs.meta | 14 + .../Editor/AppLovinMenuItems.cs | 60 + .../Editor/AppLovinMenuItems.cs.meta | 14 + .../Editor/AppLovinPostProcessAndroid.cs | 550 ++ .../Editor/AppLovinPostProcessAndroid.cs.meta | 14 + .../AppLovinPostProcessAndroidGradle.cs | 70 + .../AppLovinPostProcessAndroidGradle.cs.meta | 14 + .../Editor/AppLovinPostProcessiOS.cs | 791 +++ .../Editor/AppLovinPostProcessiOS.cs.meta | 14 + .../Editor/AppLovinPreProcess.cs | 105 + .../Editor/AppLovinPreProcess.cs.meta | 14 + .../Editor/AppLovinPreProcessAndroid.cs | 67 + .../Editor/AppLovinPreProcessAndroid.cs.meta | 14 + .../Editor/AppLovinPreProcessiOS.cs | 49 + .../Editor/AppLovinPreProcessiOS.cs.meta | 14 + .../Editor/AppLovinProcessGradleBuildFile.cs | 602 ++ .../AppLovinProcessGradleBuildFile.cs.meta | 14 + .../Editor/AppLovinSettings.cs | 425 ++ .../Editor/AppLovinSettings.cs.meta | 14 + .../MaxSdk.IntegrationManager.Editor.asmdef | 10 + ...xSdk.IntegrationManager.Editor.asmdef.meta | 6 + Assets/MaxSdk/Scripts/MaxCmpService.cs | 170 + Assets/MaxSdk/Scripts/MaxCmpService.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxEventExecutor.cs | 108 + .../MaxSdk/Scripts/MaxEventExecutor.cs.meta | 14 + .../MaxSdk/Scripts/MaxEventSystemChecker.cs | 37 + .../Scripts/MaxEventSystemChecker.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxEvents.cs | 21 + Assets/MaxSdk/Scripts/MaxEvents.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef | 6 + .../MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta | 10 + Assets/MaxSdk/Scripts/MaxSdk.cs | 30 + Assets/MaxSdk/Scripts/MaxSdk.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSdkAndroid.cs | 1069 ++++ Assets/MaxSdk/Scripts/MaxSdkAndroid.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSdkBase.cs | 808 +++ Assets/MaxSdk/Scripts/MaxSdkBase.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs | 1737 ++++++ Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSdkLogger.cs | 70 + Assets/MaxSdk/Scripts/MaxSdkLogger.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSdkUnityEditor.cs | 1383 +++++ .../MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSdkUtils.cs | 662 ++ Assets/MaxSdk/Scripts/MaxSdkUtils.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSdkiOS.cs | 1342 +++++ Assets/MaxSdk/Scripts/MaxSdkiOS.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxSegmentCollection.cs | 91 + .../Scripts/MaxSegmentCollection.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxTargetingData.cs | 1 + .../MaxSdk/Scripts/MaxTargetingData.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxUserSegment.cs | 1 + Assets/MaxSdk/Scripts/MaxUserSegment.cs.meta | 14 + .../MaxSdk/Scripts/MaxUserServiceAndroid.cs | 35 + .../Scripts/MaxUserServiceAndroid.cs.meta | 14 + .../Scripts/MaxUserServiceUnityEditor.cs | 32 + .../Scripts/MaxUserServiceUnityEditor.cs.meta | 14 + Assets/MaxSdk/Scripts/MaxUserServiceiOS.cs | 29 + .../MaxSdk/Scripts/MaxUserServiceiOS.cs.meta | 14 + Assets/MaxSdk/Scripts/ThirdParty.meta | 11 + Assets/MaxSdk/Scripts/ThirdParty/MiniJSON.cs | 629 ++ .../Scripts/ThirdParty/MiniJSON.cs.meta | 14 + Assets/MaxSdk/Version.md | 3 + Assets/MaxSdk/Version.md.meta | 10 + Assets/Plugins/CodeStage.meta | 8 +- Assets/Plugins/IngameDebugConsole.meta | 9 + .../Plugins/IngameDebugConsole/Android.meta | 9 + .../Android/DebugLogLogcatListener.cs | 54 + .../Android/DebugLogLogcatListener.cs.meta | 12 + .../Android/IngameDebugConsole.aar | Bin 0 -> 3343 bytes .../Android/IngameDebugConsole.aar.meta | 33 + Assets/Plugins/IngameDebugConsole/Editor.meta | 9 + .../Editor/DebugLogManagerEditor.cs | 160 + .../Editor/DebugLogManagerEditor.cs.meta | 12 + .../Editor/IngameDebugConsole.Editor.asmdef | 17 + .../IngameDebugConsole.Editor.asmdef.meta | 7 + .../IngameDebugConsole.Runtime.asmdef | 6 + .../IngameDebugConsole.Runtime.asmdef.meta | 7 + Assets/Plugins/IngameDebugConsole/README.txt | 7 + .../IngameDebugConsole/README.txt.meta | 8 + .../Plugins/IngameDebugConsole/Scripts.meta | 9 + .../Scripts/CircularBuffer.cs | 119 + .../Scripts/CircularBuffer.cs.meta | 12 + .../IngameDebugConsole/Scripts/Commands.meta | 8 + .../Scripts/Commands/PlayerPrefsCommands.cs | 58 + .../Commands/PlayerPrefsCommands.cs.meta | 11 + .../Scripts/Commands/SceneCommands.cs | 58 + .../Scripts/Commands/SceneCommands.cs.meta | 11 + .../Scripts/Commands/TimeCommands.cs | 19 + .../Scripts/Commands/TimeCommands.cs.meta | 11 + .../Scripts/ConsoleMethodAttribute.cs | 23 + .../Scripts/ConsoleMethodAttribute.cs.meta | 12 + .../Scripts/DebugLogConsole.cs | 1505 +++++ .../Scripts/DebugLogConsole.cs.meta | 12 + .../Scripts/DebugLogEntry.cs | 170 + .../Scripts/DebugLogEntry.cs.meta | 12 + .../Scripts/DebugLogIndexList.cs | 39 + .../Scripts/DebugLogIndexList.cs.meta | 12 + .../Scripts/DebugLogItem.cs | 283 + .../Scripts/DebugLogItem.cs.meta | 12 + .../Scripts/DebugLogItemCopyWebGL.cs | 36 + .../Scripts/DebugLogItemCopyWebGL.cs.meta | 11 + .../Scripts/DebugLogManager.cs | 1758 ++++++ .../Scripts/DebugLogManager.cs.meta | 12 + .../Scripts/DebugLogPopup.cs | 277 + .../Scripts/DebugLogPopup.cs.meta | 12 + .../Scripts/DebugLogRecycledListView.cs | 392 ++ .../Scripts/DebugLogRecycledListView.cs.meta | 12 + .../Scripts/DebugLogResizeListener.cs | 24 + .../Scripts/DebugLogResizeListener.cs.meta | 12 + .../Scripts/DebugsOnScrollListener.cs | 60 + .../Scripts/DebugsOnScrollListener.cs.meta | 12 + .../Scripts/EventSystemHandler.cs | 75 + .../Scripts/EventSystemHandler.cs.meta | 12 + Assets/Plugins/IngameDebugConsole/WebGL.meta | 9 + .../WebGL/IngameDebugConsole.jslib | 70 + .../WebGL/IngameDebugConsole.jslib.meta | 39 + Assets/Plugins/IngameDebugConsole/iOS.meta | 9 + .../iOS/IngameDebugConsole.mm | 4 + .../iOS/IngameDebugConsole.mm.meta | 33 + Assets/Plugins/LubanLib.meta | 8 +- Assets/Plugins/WaterCausticsModules.meta | 8 + .../WaterCausticsEffect.meta | 8 + .../WaterCausticsEffect/DEMO (Effect).meta | 8 + .../WaterCausticsEffect/Effect.meta | 8 + .../WaterCausticsEffect/Effect/Misc.meta | 8 + .../Effect/Misc/MaskTexture.png | Bin 0 -> 2089 bytes .../Effect/Misc/MaskTexture.png.meta | 144 + .../WaterCausticsEffect/Effect/Misc/NoTex.png | Bin 0 -> 121 bytes .../Effect/Misc/NoTex.png.meta | 144 + .../WaterCausticsEffect/Effect/Scripts.meta | 8 + .../Effect/Scripts/AtOnce.cs | 128 + .../Effect/Scripts/AtOnce.cs.meta | 11 + .../Effect/Scripts/Editor.meta | 8 + .../Scripts/Editor/CheckRenderPipeline.cs | 97 + .../Editor/CheckRenderPipeline.cs.meta | 13 + .../Scripts/Editor/DisableInPreviewWindow.cs | 67 + .../Editor/DisableInPreviewWindow.cs.meta | 11 + .../Scripts/Editor/EffectModuleRef.asset | 17 + .../Scripts/Editor/EffectModuleRef.asset.meta | 8 + .../Effect/Scripts/Editor/EffectModuleRef.cs | 25 + .../Scripts/Editor/EffectModuleRef.cs.meta | 11 + .../Scripts/Editor/ImportPackageForASE.cs | 50 + .../Editor/ImportPackageForASE.cs.meta | 11 + .../Effect/Scripts/Editor/OptimizeShader.cs | 54 + .../Scripts/Editor/OptimizeShader.cs.meta | 11 + .../Scripts/Editor/ReimportFunctions.cs | 40 + .../Scripts/Editor/ReimportFunctions.cs.meta | 11 + .../Editor/WaterCausticsEffectData.asset | 15 + .../Editor/WaterCausticsEffectData.asset.meta | 8 + .../Scripts/Editor/WaterCausticsEffectData.cs | 47 + .../Editor/WaterCausticsEffectData.cs.meta | 11 + .../Editor/WaterCausticsEffectEditor.cs | 935 +++ .../Editor/WaterCausticsEffectEditor.cs.meta | 11 + .../WaterCausticsEffectFeatureEditor.cs | 207 + .../WaterCausticsEffectFeatureEditor.cs.meta | 11 + .../Editor/WaterCausticsEffectMenuItem.cs | 48 + .../WaterCausticsEffectMenuItem.cs.meta | 11 + .../Effect/Scripts/WaterCausticsEffect.cs | 1036 ++++ .../Scripts/WaterCausticsEffect.cs.meta | 15 + .../Scripts/WaterCausticsEffectFeature.cs | 49 + .../WaterCausticsEffectFeature.cs.meta | 11 + .../WaterCausticsEffect/Effect/Shaders.meta | 8 + .../Effect/Shaders/WaterCausticsEffect.shader | 522 ++ .../Shaders/WaterCausticsEffect.shader.meta | 10 + .../Shaders/WaterCausticsEffectCommon.hlsl | 377 ++ .../WaterCausticsEffectCommon.hlsl.meta | 10 + .../Effect/Shaders/hextiling.hlsl | 95 + .../Effect/Shaders/hextiling.hlsl.meta | 10 + .../WaterCausticsEffect/ShaderFunctions.meta | 8 + .../ShaderFunctions/Common.meta | 8 + .../WaterCausticsEmissionSync_Common.hlsl | 98 + ...WaterCausticsEmissionSync_Common.hlsl.meta | 10 + .../ShaderFunctions/ForHLSL.meta | 8 + .../WaterCausticsEmissionFunc_HLSL.hlsl | 53 + .../WaterCausticsEmissionFunc_HLSL.hlsl.meta | 10 + .../ShaderFunctions/ForShaderGraph.meta | 8 + .../WaterCausticsEmission.shadersubgraph | 5321 +++++++++++++++++ .../WaterCausticsEmission.shadersubgraph.meta | 10 + ...WaterCausticsEmissionFunc_ShaderGraph.hlsl | 30 + ...CausticsEmissionFunc_ShaderGraph.hlsl.meta | 10 + .../WaterCausticsEmissionSync.shadersubgraph | 1209 ++++ ...erCausticsEmissionSync.shadersubgraph.meta | 10 + .../WaterCausticsModules.Effect.asmdef | 39 + .../WaterCausticsModules.Effect.asmdef.meta | 7 + .../WaterCausticsTexGenerator.meta | 8 + .../DEMO (TexGen).meta | 8 + .../WaterCausticsTexGenerator/Scripts.meta | 8 + .../Scripts/Editor.meta | 8 + .../Scripts/Editor/CheckConflict.cs | 71 + .../Scripts/Editor/CheckConflict.cs.meta | 11 + .../Scripts/Editor/Constant.cs | 46 + .../Scripts/Editor/Constant.cs.meta | 11 + .../Scripts/Editor/Misc.meta | 8 + .../Scripts/Editor/Misc/IconLock.png | Bin 0 -> 261 bytes .../Scripts/Editor/Misc/IconLock.png.meta | 144 + .../Scripts/Editor/Misc/IconMenu.png | Bin 0 -> 188 bytes .../Scripts/Editor/Misc/IconMenu.png.meta | 144 + .../Scripts/Editor/Misc/IconShader.shader | 50 + .../Editor/Misc/IconShader.shader.meta | 10 + .../Scripts/Editor/Misc/IconUnlock.png | Bin 0 -> 231 bytes .../Scripts/Editor/Misc/IconUnlock.png.meta | 144 + .../Scripts/Editor/PreventOverwriteAsset.cs | 67 + .../Editor/PreventOverwriteAsset.cs.meta | 11 + .../Scripts/Editor/PreviewWindow.cs | 361 ++ .../Scripts/Editor/PreviewWindow.cs.meta | 19 + .../Scripts/Editor/Readme.meta | 8 + .../Scripts/Editor/Readme/WCMReadme.cs | 66 + .../Scripts/Editor/Readme/WCMReadme.cs.meta | 12 + .../Scripts/Editor/Readme/WCMReadmeEditor.cs | 146 + .../Editor/Readme/WCMReadmeEditor.cs.meta | 11 + .../Scripts/Editor/Readme/WCMReadmeIcon.png | Bin 0 -> 2834 bytes .../Editor/Readme/WCMReadmeIcon.png.meta | 144 + .../Scripts/Editor/Readme/WCMReadmeThumb.png | Bin 0 -> 22119 bytes .../Editor/Readme/WCMReadmeThumb.png.meta | 144 + .../Scripts/Editor/TexGenModuleRef.asset | 16 + .../Scripts/Editor/TexGenModuleRef.asset.meta | 8 + .../Scripts/Editor/TexGenModuleRef.cs | 21 + .../Scripts/Editor/TexGenModuleRef.cs.meta | 11 + .../Scripts/Editor/VersionCheck.cs | 43 + .../Scripts/Editor/VersionCheck.cs.meta | 11 + .../Editor/WaterCausticsTexGeneratorEditor.cs | 865 +++ .../WaterCausticsTexGeneratorEditor.cs.meta | 11 + .../WaterCausticsTexGeneratorMenuItem.cs | 72 + .../WaterCausticsTexGeneratorMenuItem.cs.meta | 11 + .../Scripts/WaterCausticsTexGenerator.cs | 936 +++ .../Scripts/WaterCausticsTexGenerator.cs.meta | 15 + .../WaterCausticsTexGenerator/Shaders.meta | 8 + .../Shaders/GenCausticsCShader.compute | 250 + .../Shaders/GenCausticsCShader.compute.meta | 9 + .../Shaders/GenCausticsShader.shader | 178 + .../Shaders/GenCausticsShader.shader.meta | 10 + .../Shaders/UIRawImagePreview.mat | 29 + .../Shaders/UIRawImagePreview.mat.meta | 8 + .../Shaders/UIRawImagePreview.shader | 51 + .../Shaders/UIRawImagePreview.shader.meta | 10 + .../Shaders/snoise.cginc | 102 + .../Shaders/snoise.cginc.meta | 10 + .../WaterCausticsModules.TexGen.asmdef | 20 + .../WaterCausticsModules.TexGen.asmdef.meta | 7 + BACKUP_MANIFEST.md | 1 + DEPENDENCY_REPORT.md | 9 +- 433 files changed, 49783 insertions(+), 3 deletions(-) create mode 100644 Assets/AppsFlyer.meta create mode 100644 Assets/AppsFlyer/AFAdRevenueEvent.cs create mode 100644 Assets/AppsFlyer/AFAdRevenueEvent.cs.meta create mode 100644 Assets/AppsFlyer/AFInAppEvents.cs create mode 100644 Assets/AppsFlyer/AFInAppEvents.cs.meta create mode 100644 Assets/AppsFlyer/AFMiniJSON.cs create mode 100644 Assets/AppsFlyer/AFMiniJSON.cs.meta create mode 100644 Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs create mode 100644 Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs.meta create mode 100644 Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs create mode 100644 Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs.meta create mode 100644 Assets/AppsFlyer/AFSDKValidateAndLogResult.cs create mode 100644 Assets/AppsFlyer/AFSDKValidateAndLogResult.cs.meta create mode 100644 Assets/AppsFlyer/AppsFlyer.asmdef create mode 100644 Assets/AppsFlyer/AppsFlyer.asmdef.meta create mode 100644 Assets/AppsFlyer/AppsFlyer.cs create mode 100644 Assets/AppsFlyer/AppsFlyer.cs.meta create mode 100644 Assets/AppsFlyer/AppsFlyerAdRevenue.cs create mode 100644 Assets/AppsFlyer/AppsFlyerAdRevenue.cs.meta create mode 100644 Assets/AppsFlyer/AppsFlyerAndroid.cs create mode 100644 Assets/AppsFlyer/AppsFlyerAndroid.cs.meta create mode 100644 Assets/AppsFlyer/AppsFlyerConsent.cs create mode 100644 Assets/AppsFlyer/AppsFlyerConsent.cs.meta create mode 100644 Assets/AppsFlyer/AppsFlyerEventArgs.cs create mode 100644 Assets/AppsFlyer/AppsFlyerEventArgs.cs.meta create mode 100644 Assets/AppsFlyer/AppsFlyerObject.prefab create mode 100644 Assets/AppsFlyer/AppsFlyerObject.prefab.meta create mode 100644 Assets/AppsFlyer/AppsFlyerObjectScript.cs create mode 100644 Assets/AppsFlyer/AppsFlyerObjectScript.cs.meta create mode 100644 Assets/AppsFlyer/AppsFlyeriOS.cs create mode 100644 Assets/AppsFlyer/AppsFlyeriOS.cs.meta create mode 100644 Assets/AppsFlyer/Editor.meta create mode 100644 Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef create mode 100644 Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef.meta create mode 100644 Assets/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml create mode 100644 Assets/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml.meta create mode 100644 Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml create mode 100644 Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml.meta create mode 100644 Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs create mode 100644 Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs.meta create mode 100644 Assets/AppsFlyer/Editor/appsflyer_logo.png create mode 100644 Assets/AppsFlyer/Editor/appsflyer_logo.png.meta create mode 100644 Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs create mode 100644 Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs.meta create mode 100644 Assets/AppsFlyer/IAppsFlyerConversionData.cs create mode 100644 Assets/AppsFlyer/IAppsFlyerConversionData.cs.meta create mode 100644 Assets/AppsFlyer/IAppsFlyerIOSBridge.cs create mode 100644 Assets/AppsFlyer/IAppsFlyerIOSBridge.cs.meta create mode 100644 Assets/AppsFlyer/IAppsFlyerNativeBridge.cs create mode 100644 Assets/AppsFlyer/IAppsFlyerNativeBridge.cs.meta create mode 100644 Assets/AppsFlyer/IAppsFlyerUserInvite.cs create mode 100644 Assets/AppsFlyer/IAppsFlyerUserInvite.cs.meta create mode 100644 Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs create mode 100644 Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs.meta create mode 100644 Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs create mode 100644 Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs.meta create mode 100644 Assets/AppsFlyer/Mac.meta create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle.meta create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents.meta create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/Info.plist create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/Info.plist.meta create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS.meta create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS/AppsFlyerBundle create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS/AppsFlyerBundle.meta create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/_CodeSignature.meta create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/_CodeSignature/CodeResources create mode 100644 Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/_CodeSignature/CodeResources.meta create mode 100644 Assets/AppsFlyer/Plugins.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h create mode 100644 Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm create mode 100644 Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.h create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.h.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.mm create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.mm.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm create mode 100644 Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm.meta create mode 100644 Assets/AppsFlyer/Plugins/iOS/SwiftForUnity.swift create mode 100644 Assets/AppsFlyer/Plugins/iOS/SwiftForUnity.swift.meta create mode 100644 Assets/AppsFlyer/Tests.meta create mode 100644 Assets/AppsFlyer/Tests/Castle.Core.dll create mode 100644 Assets/AppsFlyer/Tests/Castle.Core.dll.meta create mode 100644 Assets/AppsFlyer/Tests/NSubstitute.dll create mode 100644 Assets/AppsFlyer/Tests/NSubstitute.dll.meta create mode 100644 Assets/AppsFlyer/Tests/System.Runtime.CompilerServices.Unsafe.dll create mode 100644 Assets/AppsFlyer/Tests/System.Runtime.CompilerServices.Unsafe.dll.meta create mode 100644 Assets/AppsFlyer/Tests/System.Threading.Tasks.Extensions.dll create mode 100644 Assets/AppsFlyer/Tests/System.Threading.Tasks.Extensions.dll.meta create mode 100644 Assets/AppsFlyer/Tests/Tests.asmdef create mode 100644 Assets/AppsFlyer/Tests/Tests.asmdef.meta create mode 100644 Assets/AppsFlyer/Tests/Tests_Suite.cs create mode 100644 Assets/AppsFlyer/Tests/Tests_Suite.cs.meta create mode 100644 Assets/AppsFlyer/Windows.meta create mode 100644 Assets/AppsFlyer/Windows/AppsFlyerLib.pri create mode 100644 Assets/AppsFlyer/Windows/AppsFlyerLib.pri.meta create mode 100644 Assets/AppsFlyer/Windows/AppsFlyerLib.winmd create mode 100644 Assets/AppsFlyer/Windows/AppsFlyerLib.winmd.meta create mode 100644 Assets/AppsFlyer/Windows/AppsFlyerWindows.cs create mode 100644 Assets/AppsFlyer/Windows/AppsFlyerWindows.cs.meta create mode 100644 Assets/AppsFlyer/package.json create mode 100644 Assets/AppsFlyer/package.json.meta create mode 100644 Assets/MaxSdk.meta create mode 100644 Assets/MaxSdk/AppLovin.meta create mode 100644 Assets/MaxSdk/AppLovin/Editor.meta create mode 100644 Assets/MaxSdk/AppLovin/Editor/Dependencies.xml create mode 100644 Assets/MaxSdk/AppLovin/Editor/Dependencies.xml.meta create mode 100644 Assets/MaxSdk/AppLovin/Plugins.meta create mode 100644 Assets/MaxSdk/AppLovin/Plugins/Android.meta create mode 100644 Assets/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar create mode 100644 Assets/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta create mode 100644 Assets/MaxSdk/AppLovin/Plugins/iOS.meta create mode 100644 Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h create mode 100644 Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta create mode 100644 Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m create mode 100644 Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta create mode 100644 Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm create mode 100644 Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta create mode 100644 Assets/MaxSdk/Mediation.meta create mode 100644 Assets/MaxSdk/Mediation/Facebook.meta create mode 100644 Assets/MaxSdk/Mediation/Facebook/Editor.meta create mode 100644 Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml create mode 100644 Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml.meta create mode 100644 Assets/MaxSdk/Mediation/Fyber.meta create mode 100644 Assets/MaxSdk/Mediation/Fyber/Editor.meta create mode 100644 Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml create mode 100644 Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml.meta create mode 100644 Assets/MaxSdk/Mediation/Google.meta create mode 100644 Assets/MaxSdk/Mediation/Google/Editor.meta create mode 100644 Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml create mode 100644 Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml.meta create mode 100644 Assets/MaxSdk/Mediation/IronSource.meta create mode 100644 Assets/MaxSdk/Mediation/IronSource/Editor.meta create mode 100644 Assets/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml create mode 100644 Assets/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml.meta create mode 100644 Assets/MaxSdk/Mediation/MediationAdapters.txt create mode 100644 Assets/MaxSdk/Mediation/MediationAdapters.txt.meta create mode 100644 Assets/MaxSdk/Mediation/UnityAds.meta create mode 100644 Assets/MaxSdk/Mediation/UnityAds/Editor.meta create mode 100644 Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml create mode 100644 Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml.meta create mode 100644 Assets/MaxSdk/Mediation/Vungle.meta create mode 100644 Assets/MaxSdk/Mediation/Vungle/Editor.meta create mode 100644 Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml create mode 100644 Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml.meta create mode 100644 Assets/MaxSdk/Prefabs.meta create mode 100644 Assets/MaxSdk/Prefabs/BannerBottom.prefab create mode 100644 Assets/MaxSdk/Prefabs/BannerBottom.prefab.meta create mode 100644 Assets/MaxSdk/Prefabs/BannerTop.prefab create mode 100644 Assets/MaxSdk/Prefabs/BannerTop.prefab.meta create mode 100644 Assets/MaxSdk/Prefabs/Interstitial.prefab create mode 100644 Assets/MaxSdk/Prefabs/Interstitial.prefab.meta create mode 100644 Assets/MaxSdk/Prefabs/Rewarded.prefab create mode 100644 Assets/MaxSdk/Prefabs/Rewarded.prefab.meta create mode 100644 Assets/MaxSdk/Resources.meta create mode 100644 Assets/MaxSdk/Resources/AppLovinSettings.asset create mode 100644 Assets/MaxSdk/Resources/AppLovinSettings.asset.meta create mode 100644 Assets/MaxSdk/Resources/Images.meta create mode 100644 Assets/MaxSdk/Resources/Images/alert_icon.png create mode 100644 Assets/MaxSdk/Resources/Images/alert_icon.png.meta create mode 100644 Assets/MaxSdk/Resources/Images/uninstall_icon.png create mode 100644 Assets/MaxSdk/Resources/Images/uninstall_icon.png.meta create mode 100644 Assets/MaxSdk/Resources/Images/warning_icon.png create mode 100644 Assets/MaxSdk/Resources/Images/warning_icon.png.meta create mode 100644 Assets/MaxSdk/Scripts.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef create mode 100644 Assets/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta create mode 100644 Assets/MaxSdk/Scripts/MaxCmpService.cs create mode 100644 Assets/MaxSdk/Scripts/MaxCmpService.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxEventExecutor.cs create mode 100644 Assets/MaxSdk/Scripts/MaxEventExecutor.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxEventSystemChecker.cs create mode 100644 Assets/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxEvents.cs create mode 100644 Assets/MaxSdk/Scripts/MaxEvents.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef create mode 100644 Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdk.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSdk.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdkAndroid.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSdkAndroid.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdkBase.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSdkBase.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdkLogger.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSdkLogger.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdkUnityEditor.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSdkUnityEditor.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdkUtils.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSdkUtils.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSdkiOS.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSdkiOS.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxSegmentCollection.cs create mode 100644 Assets/MaxSdk/Scripts/MaxSegmentCollection.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxTargetingData.cs create mode 100644 Assets/MaxSdk/Scripts/MaxTargetingData.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxUserSegment.cs create mode 100644 Assets/MaxSdk/Scripts/MaxUserSegment.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxUserServiceAndroid.cs create mode 100644 Assets/MaxSdk/Scripts/MaxUserServiceAndroid.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxUserServiceUnityEditor.cs create mode 100644 Assets/MaxSdk/Scripts/MaxUserServiceUnityEditor.cs.meta create mode 100644 Assets/MaxSdk/Scripts/MaxUserServiceiOS.cs create mode 100644 Assets/MaxSdk/Scripts/MaxUserServiceiOS.cs.meta create mode 100644 Assets/MaxSdk/Scripts/ThirdParty.meta create mode 100644 Assets/MaxSdk/Scripts/ThirdParty/MiniJSON.cs create mode 100644 Assets/MaxSdk/Scripts/ThirdParty/MiniJSON.cs.meta create mode 100644 Assets/MaxSdk/Version.md create mode 100644 Assets/MaxSdk/Version.md.meta create mode 100644 Assets/Plugins/IngameDebugConsole.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Android.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Android/DebugLogLogcatListener.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Android/DebugLogLogcatListener.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Android/IngameDebugConsole.aar create mode 100644 Assets/Plugins/IngameDebugConsole/Android/IngameDebugConsole.aar.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Editor.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Editor/DebugLogManagerEditor.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Editor/DebugLogManagerEditor.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Editor/IngameDebugConsole.Editor.asmdef create mode 100644 Assets/Plugins/IngameDebugConsole/Editor/IngameDebugConsole.Editor.asmdef.meta create mode 100644 Assets/Plugins/IngameDebugConsole/IngameDebugConsole.Runtime.asmdef create mode 100644 Assets/Plugins/IngameDebugConsole/IngameDebugConsole.Runtime.asmdef.meta create mode 100644 Assets/Plugins/IngameDebugConsole/README.txt create mode 100644 Assets/Plugins/IngameDebugConsole/README.txt.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/CircularBuffer.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/CircularBuffer.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/Commands.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/Commands/PlayerPrefsCommands.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/Commands/PlayerPrefsCommands.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/Commands/SceneCommands.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/Commands/SceneCommands.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/Commands/TimeCommands.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/Commands/TimeCommands.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/ConsoleMethodAttribute.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/ConsoleMethodAttribute.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogConsole.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogConsole.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogEntry.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogEntry.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogIndexList.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogIndexList.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogItem.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogItem.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogItemCopyWebGL.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogItemCopyWebGL.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogManager.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogManager.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogPopup.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogPopup.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogRecycledListView.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogRecycledListView.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogResizeListener.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugLogResizeListener.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugsOnScrollListener.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/DebugsOnScrollListener.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/EventSystemHandler.cs create mode 100644 Assets/Plugins/IngameDebugConsole/Scripts/EventSystemHandler.cs.meta create mode 100644 Assets/Plugins/IngameDebugConsole/WebGL.meta create mode 100644 Assets/Plugins/IngameDebugConsole/WebGL/IngameDebugConsole.jslib create mode 100644 Assets/Plugins/IngameDebugConsole/WebGL/IngameDebugConsole.jslib.meta create mode 100644 Assets/Plugins/IngameDebugConsole/iOS.meta create mode 100644 Assets/Plugins/IngameDebugConsole/iOS/IngameDebugConsole.mm create mode 100644 Assets/Plugins/IngameDebugConsole/iOS/IngameDebugConsole.mm.meta create mode 100644 Assets/Plugins/WaterCausticsModules.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/DEMO (Effect).meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Misc.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Misc/MaskTexture.png create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Misc/MaskTexture.png.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Misc/NoTex.png create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Misc/NoTex.png.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/AtOnce.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/AtOnce.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/CheckRenderPipeline.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/CheckRenderPipeline.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/DisableInPreviewWindow.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/DisableInPreviewWindow.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/EffectModuleRef.asset create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/EffectModuleRef.asset.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/EffectModuleRef.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/EffectModuleRef.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/ImportPackageForASE.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/ImportPackageForASE.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/OptimizeShader.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/OptimizeShader.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/ReimportFunctions.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/ReimportFunctions.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectData.asset create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectData.asset.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectData.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectData.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectEditor.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectEditor.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectFeatureEditor.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectFeatureEditor.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectMenuItem.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/Editor/WaterCausticsEffectMenuItem.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/WaterCausticsEffect.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/WaterCausticsEffect.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/WaterCausticsEffectFeature.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Scripts/WaterCausticsEffectFeature.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Shaders.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Shaders/WaterCausticsEffect.shader create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Shaders/WaterCausticsEffect.shader.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Shaders/WaterCausticsEffectCommon.hlsl create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Shaders/WaterCausticsEffectCommon.hlsl.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Shaders/hextiling.hlsl create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/Effect/Shaders/hextiling.hlsl.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/Common.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/Common/WaterCausticsEmissionSync_Common.hlsl create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/Common/WaterCausticsEmissionSync_Common.hlsl.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForHLSL.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForHLSL/WaterCausticsEmissionFunc_HLSL.hlsl create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForHLSL/WaterCausticsEmissionFunc_HLSL.hlsl.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForShaderGraph.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForShaderGraph/WaterCausticsEmission.shadersubgraph create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForShaderGraph/WaterCausticsEmission.shadersubgraph.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForShaderGraph/WaterCausticsEmissionFunc_ShaderGraph.hlsl create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForShaderGraph/WaterCausticsEmissionFunc_ShaderGraph.hlsl.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForShaderGraph/WaterCausticsEmissionSync.shadersubgraph create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/ShaderFunctions/ForShaderGraph/WaterCausticsEmissionSync.shadersubgraph.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/WaterCausticsModules.Effect.asmdef create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsEffect/WaterCausticsModules.Effect.asmdef.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/DEMO (TexGen).meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/CheckConflict.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/CheckConflict.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Constant.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Constant.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc/IconLock.png create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc/IconLock.png.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc/IconMenu.png create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc/IconMenu.png.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc/IconShader.shader create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc/IconShader.shader.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc/IconUnlock.png create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Misc/IconUnlock.png.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/PreventOverwriteAsset.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/PreventOverwriteAsset.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/PreviewWindow.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/PreviewWindow.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme/WCMReadme.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme/WCMReadme.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme/WCMReadmeEditor.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme/WCMReadmeEditor.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme/WCMReadmeIcon.png create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme/WCMReadmeIcon.png.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme/WCMReadmeThumb.png create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/Readme/WCMReadmeThumb.png.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/TexGenModuleRef.asset create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/TexGenModuleRef.asset.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/TexGenModuleRef.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/TexGenModuleRef.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/VersionCheck.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/VersionCheck.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/WaterCausticsTexGeneratorEditor.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/WaterCausticsTexGeneratorEditor.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/WaterCausticsTexGeneratorMenuItem.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/Editor/WaterCausticsTexGeneratorMenuItem.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/WaterCausticsTexGenerator.cs create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Scripts/WaterCausticsTexGenerator.cs.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/GenCausticsCShader.compute create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/GenCausticsCShader.compute.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/GenCausticsShader.shader create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/GenCausticsShader.shader.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/UIRawImagePreview.mat create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/UIRawImagePreview.mat.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/UIRawImagePreview.shader create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/UIRawImagePreview.shader.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/snoise.cginc create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/Shaders/snoise.cginc.meta create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/WaterCausticsModules.TexGen.asmdef create mode 100644 Assets/Plugins/WaterCausticsModules/WaterCausticsTexGenerator/WaterCausticsModules.TexGen.asmdef.meta diff --git a/Assets/AppsFlyer.meta b/Assets/AppsFlyer.meta new file mode 100644 index 0000000..00aa988 --- /dev/null +++ b/Assets/AppsFlyer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da76ae4f9ba92124087139583d0dd929 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AFAdRevenueEvent.cs b/Assets/AppsFlyer/AFAdRevenueEvent.cs new file mode 100644 index 0000000..6ed2afb --- /dev/null +++ b/Assets/AppsFlyer/AFAdRevenueEvent.cs @@ -0,0 +1,34 @@ +using System.Collections; +using UnityEngine; + +public class AFAdRevenueEvent { + + /** + *Pre-defined keys for non-mandatory dictionary + *Code ISO 3166-1 format + **/ + public const string COUNTRY = "country"; + + /** + *ID of the ad unit for the impression + **/ + public const string AD_UNIT = "ad_unit"; + + /** + *Format of the ad + **/ + public const string AD_TYPE = "ad_type"; + + /** + *ID of the ad placement for the impression + **/ + public const string PLACEMENT = "placement"; + + /** + *Provided by Facebook Audience Network only, and will be reported to publishers + *approved by Facebook Audience Network within the closed beta + **/ + public const string ECPM_PAYLOAD = "ecpm_payload"; + + +} diff --git a/Assets/AppsFlyer/AFAdRevenueEvent.cs.meta b/Assets/AppsFlyer/AFAdRevenueEvent.cs.meta new file mode 100644 index 0000000..cbcfb3e --- /dev/null +++ b/Assets/AppsFlyer/AFAdRevenueEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b73b301ad8b6f4b45809980800a9358a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AFInAppEvents.cs b/Assets/AppsFlyer/AFInAppEvents.cs new file mode 100644 index 0000000..daa7602 --- /dev/null +++ b/Assets/AppsFlyer/AFInAppEvents.cs @@ -0,0 +1,73 @@ +using UnityEngine; +using System.Collections; + +public class AFInAppEvents { + /** + * Event Type + * */ + public const string LEVEL_ACHIEVED = "af_level_achieved"; + public const string ADD_PAYMENT_INFO = "af_add_payment_info"; + public const string ADD_TO_CART = "af_add_to_cart"; + public const string ADD_TO_WISH_LIST = "af_add_to_wishlist"; + public const string COMPLETE_REGISTRATION = "af_complete_registration"; + public const string TUTORIAL_COMPLETION = "af_tutorial_completion"; + public const string INITIATED_CHECKOUT = "af_initiated_checkout"; + public const string PURCHASE = "af_purchase"; + public const string RATE = "af_rate"; + public const string SEARCH = "af_search"; + public const string SPENT_CREDIT = "af_spent_credits"; + public const string ACHIEVEMENT_UNLOCKED = "af_achievement_unlocked"; + public const string CONTENT_VIEW = "af_content_view"; + public const string TRAVEL_BOOKING = "af_travel_booking"; + public const string SHARE = "af_share"; + public const string INVITE = "af_invite"; + public const string LOGIN = "af_login"; + public const string RE_ENGAGE = "af_re_engage"; + public const string UPDATE = "af_update"; + public const string OPENED_FROM_PUSH_NOTIFICATION = "af_opened_from_push_notification"; + public const string LOCATION_CHANGED = "af_location_changed"; + public const string LOCATION_COORDINATES = "af_location_coordinates"; + public const string ORDER_ID = "af_order_id"; + public const string GA = "af_ga_event"; + /** + * Event Parameter Name + * **/ + public const string LEVEL = "af_level"; + public const string SCORE = "af_score"; + public const string SUCCESS = "af_success"; + public const string PRICE = "af_price"; + public const string CONTENT_TYPE = "af_content_type"; + public const string CONTENT_ID = "af_content_id"; + public const string CONTENT_LIST = "af_content_list"; + public const string CURRENCY = "af_currency"; + public const string QUANTITY = "af_quantity"; + public const string REGSITRATION_METHOD = "af_registration_method"; + public const string PAYMENT_INFO_AVAILIBLE = "af_payment_info_available"; + public const string MAX_RATING_VALUE = "af_max_rating_value"; + public const string RATING_VALUE = "af_rating_value"; + public const string SEARCH_STRING = "af_search_string"; + public const string DATE_A = "af_date_a"; + public const string DATE_B = "af_date_b"; + public const string DESTINATION_A = "af_destination_a"; + public const string DESTINATION_B = "af_destination_b"; + public const string DESCRIPTION = "af_description"; + public const string CLASS = "af_class"; + public const string EVENT_START = "af_event_start"; + public const string EVENT_END = "af_event_end"; + public const string LATITUDE = "af_lat"; + public const string LONGTITUDE = "af_long"; + public const string CUSTOMER_USER_ID = "af_customer_user_id"; + public const string VALIDATED = "af_validated"; + public const string REVENUE = "af_revenue"; + public const string RECEIPT_ID = "af_receipt_id"; + public const string PARAM_1 = "af_param_1"; + public const string PARAM_2 = "af_param_2"; + public const string PARAM_3 = "af_param_3"; + public const string PARAM_4 = "af_param_4"; + public const string PARAM_5 = "af_param_5"; + public const string PARAM_6 = "af_param_6"; + public const string PARAM_7 = "af_param_7"; + public const string PARAM_8 = "af_param_8"; + public const string PARAM_9 = "af_param_9"; + public const string PARAM_10 = "af_param_10"; +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AFInAppEvents.cs.meta b/Assets/AppsFlyer/AFInAppEvents.cs.meta new file mode 100644 index 0000000..b31364e --- /dev/null +++ b/Assets/AppsFlyer/AFInAppEvents.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4075c6cf6f3d94b9a9f37f826e6a0e6f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AFMiniJSON.cs b/Assets/AppsFlyer/AFMiniJSON.cs new file mode 100644 index 0000000..d02bf2f --- /dev/null +++ b/Assets/AppsFlyer/AFMiniJSON.cs @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2013 Calvin Rien + * + * Based on the JSON parser by Patrick van Bergen + * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html + * + * Simplified it so that it doesn't throw exceptions + * and can be used in Unity iPhone with maximum code stripping. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace AFMiniJSON { + // Example usage: + // + // using UnityEngine; + // using System.Collections; + // using System.Collections.Generic; + // using MiniJSON; + // + // public class MiniJSONTest : MonoBehaviour { + // void Start () { + // var jsonString = "{ \"array\": [1.44,2,3], " + + // "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + + // "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + + // "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + + // "\"int\": 65536, " + + // "\"float\": 3.1415926, " + + // "\"bool\": true, " + + // "\"null\": null }"; + // + // var dict = Json.Deserialize(jsonString) as Dictionary; + // + // Debug.Log("deserialized: " + dict.GetType()); + // Debug.Log("dict['array'][0]: " + ((List) dict["array"])[0]); + // Debug.Log("dict['string']: " + (string) dict["string"]); + // Debug.Log("dict['float']: " + (double) dict["float"]); // floats come out as doubles + // Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs + // Debug.Log("dict['unicode']: " + (string) dict["unicode"]); + // + // var str = Json.Serialize(dict); + // + // Debug.Log("serialized: " + str); + // } + // } + + /// + /// This class encodes and decodes JSON strings. + /// Spec. details, see http://www.json.org/ + /// + /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. + /// All numbers are parsed to doubles. + /// + public static class Json { + /// + /// Parses the string json into a value + /// + /// A JSON string. + /// An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false + public static object Deserialize(string json) { + // save the string for debug information + if (json == null) { + return null; + } + + return Parser.Parse(json); + } + + sealed class Parser : IDisposable { + const string WORD_BREAK = "{}[],:\""; + + public static bool IsWordBreak(char c) { + return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1; + } + + enum TOKEN { + NONE, + CURLY_OPEN, + CURLY_CLOSE, + SQUARED_OPEN, + SQUARED_CLOSE, + COLON, + COMMA, + STRING, + NUMBER, + TRUE, + FALSE, + NULL + }; + + StringReader json; + + Parser(string jsonString) { + json = new StringReader(jsonString); + } + + public static object Parse(string jsonString) { + using (var instance = new Parser(jsonString)) { + return instance.ParseValue(); + } + } + + public void Dispose() { + json.Dispose(); + json = null; + } + + Dictionary ParseObject() { + Dictionary table = new Dictionary(); + + // ditch opening brace + json.Read(); + + // { + while (true) { + switch (NextToken) { + case TOKEN.NONE: + return null; + case TOKEN.COMMA: + continue; + case TOKEN.CURLY_CLOSE: + return table; + default: + // name + string name = ParseString(); + if (name == null) { + return null; + } + + // : + if (NextToken != TOKEN.COLON) { + return null; + } + // ditch the colon + json.Read(); + + // value + table[name] = ParseValue(); + break; + } + } + } + + List ParseArray() { + List array = new List(); + + // ditch opening bracket + json.Read(); + + // [ + var parsing = true; + while (parsing) { + TOKEN nextToken = NextToken; + + switch (nextToken) { + case TOKEN.NONE: + return null; + case TOKEN.COMMA: + continue; + case TOKEN.SQUARED_CLOSE: + parsing = false; + break; + default: + object value = ParseByToken(nextToken); + + array.Add(value); + break; + } + } + + return array; + } + + object ParseValue() { + TOKEN nextToken = NextToken; + return ParseByToken(nextToken); + } + + object ParseByToken(TOKEN token) { + switch (token) { + case TOKEN.STRING: + return ParseString(); + case TOKEN.NUMBER: + return ParseNumber(); + case TOKEN.CURLY_OPEN: + return ParseObject(); + case TOKEN.SQUARED_OPEN: + return ParseArray(); + case TOKEN.TRUE: + return true; + case TOKEN.FALSE: + return false; + case TOKEN.NULL: + return null; + default: + return null; + } + } + + string ParseString() { + StringBuilder s = new StringBuilder(); + char c; + + // ditch opening quote + json.Read(); + + bool parsing = true; + while (parsing) { + + if (json.Peek() == -1) { + parsing = false; + break; + } + + c = NextChar; + switch (c) { + case '"': + parsing = false; + break; + case '\\': + if (json.Peek() == -1) { + parsing = false; + break; + } + + c = NextChar; + switch (c) { + case '"': + case '\\': + case '/': + s.Append(c); + break; + case 'b': + s.Append('\b'); + break; + case 'f': + s.Append('\f'); + break; + case 'n': + s.Append('\n'); + break; + case 'r': + s.Append('\r'); + break; + case 't': + s.Append('\t'); + break; + case 'u': + var hex = new char[4]; + + for (int i=0; i< 4; i++) { + hex[i] = NextChar; + } + + s.Append((char) Convert.ToInt32(new string(hex), 16)); + break; + } + break; + default: + s.Append(c); + break; + } + } + + return s.ToString(); + } + + object ParseNumber() { + string number = NextWord; + + if (number.IndexOf('.') == -1) { + long parsedInt; + Int64.TryParse(number, out parsedInt); + return parsedInt; + } + + double parsedDouble; + Double.TryParse(number, out parsedDouble); + return parsedDouble; + } + + void EatWhitespace() { + while (Char.IsWhiteSpace(PeekChar)) { + json.Read(); + + if (json.Peek() == -1) { + break; + } + } + } + + char PeekChar { + get { + return Convert.ToChar(json.Peek()); + } + } + + char NextChar { + get { + return Convert.ToChar(json.Read()); + } + } + + string NextWord { + get { + StringBuilder word = new StringBuilder(); + + while (!IsWordBreak(PeekChar)) { + word.Append(NextChar); + + if (json.Peek() == -1) { + break; + } + } + + return word.ToString(); + } + } + + TOKEN NextToken { + get { + EatWhitespace(); + + if (json.Peek() == -1) { + return TOKEN.NONE; + } + + switch (PeekChar) { + case '{': + return TOKEN.CURLY_OPEN; + case '}': + json.Read(); + return TOKEN.CURLY_CLOSE; + case '[': + return TOKEN.SQUARED_OPEN; + case ']': + json.Read(); + return TOKEN.SQUARED_CLOSE; + case ',': + json.Read(); + return TOKEN.COMMA; + case '"': + return TOKEN.STRING; + case ':': + return TOKEN.COLON; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + return TOKEN.NUMBER; + } + + switch (NextWord) { + case "false": + return TOKEN.FALSE; + case "true": + return TOKEN.TRUE; + case "null": + return TOKEN.NULL; + } + + return TOKEN.NONE; + } + } + } + + /// + /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string + /// + /// A Dictionary<string, object> / List<object> + /// A JSON encoded string, or null if object 'json' is not serializable + public static string Serialize(object obj) { + return Serializer.Serialize(obj); + } + + sealed class Serializer { + StringBuilder builder; + + Serializer() { + builder = new StringBuilder(); + } + + public static string Serialize(object obj) { + var instance = new Serializer(); + + instance.SerializeValue(obj); + + return instance.builder.ToString(); + } + + void SerializeValue(object value) { + IList asList; + IDictionary asDict; + string asStr; + + if (value == null) { + builder.Append("null"); + } else if ((asStr = value as string) != null) { + SerializeString(asStr); + } else if (value is bool) { + builder.Append((bool) value ? "true" : "false"); + } else if ((asList = value as IList) != null) { + SerializeArray(asList); + } else if ((asDict = value as IDictionary) != null) { + SerializeObject(asDict); + } else if (value is char) { + SerializeString(new string((char) value, 1)); + } else { + SerializeOther(value); + } + } + + void SerializeObject(IDictionary obj) { + bool first = true; + + builder.Append('{'); + + foreach (object e in obj.Keys) { + if (!first) { + builder.Append(','); + } + + SerializeString(e.ToString()); + builder.Append(':'); + + SerializeValue(obj[e]); + + first = false; + } + + builder.Append('}'); + } + + void SerializeArray(IList anArray) { + builder.Append('['); + + bool first = true; + + foreach (object obj in anArray) { + if (!first) { + builder.Append(','); + } + + SerializeValue(obj); + + first = false; + } + + builder.Append(']'); + } + + void SerializeString(string str) { + builder.Append('\"'); + + char[] charArray = str.ToCharArray(); + foreach (var c in charArray) { + switch (c) { + case '"': + builder.Append("\\\""); + break; + case '\\': + builder.Append("\\\\"); + break; + case '\b': + builder.Append("\\b"); + break; + case '\f': + builder.Append("\\f"); + break; + case '\n': + builder.Append("\\n"); + break; + case '\r': + builder.Append("\\r"); + break; + case '\t': + builder.Append("\\t"); + break; + default: + int codepoint = Convert.ToInt32(c); + if ((codepoint >= 32) && (codepoint <= 126)) { + builder.Append(c); + } else { + builder.Append("\\u"); + builder.Append(codepoint.ToString("x4")); + } + break; + } + } + + builder.Append('\"'); + } + + void SerializeOther(object value) { + // NOTE: decimals lose precision during serialization. + // They always have, I'm just letting you know. + // Previously floats and doubles lost precision too. + if (value is float) { + builder.Append(((float) value).ToString("R")); + } else if (value is int + || value is uint + || value is long + || value is sbyte + || value is byte + || value is short + || value is ushort + || value is ulong) { + builder.Append(value); + } else if (value is double + || value is decimal) { + builder.Append(Convert.ToDouble(value).ToString("R")); + } else { + SerializeString(value.ToString()); + } + } + } + } +} diff --git a/Assets/AppsFlyer/AFMiniJSON.cs.meta b/Assets/AppsFlyer/AFMiniJSON.cs.meta new file mode 100644 index 0000000..11ec5c9 --- /dev/null +++ b/Assets/AppsFlyer/AFMiniJSON.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc3d1c806d507463e9b560eb09d8eb0e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs b/Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs new file mode 100644 index 0000000..6762c97 --- /dev/null +++ b/Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +namespace AppsFlyerSDK +{ + public enum AFPurchaseType + { + Subscription = 0, + OneTimePurchase = 1 + } + + /// + // + /// + public class AFPurchaseDetailsAndroid + + { + public AFPurchaseType purchaseType { get; private set; } + public string purchaseToken { get; private set; } + public string productId { get; private set; } + public string price { get; private set; } + public string currency { get; private set; } + + public AFPurchaseDetailsAndroid(AFPurchaseType type, String purchaseToken, String productId, String price, String currency) + { + this.purchaseType = type; + this.purchaseToken = purchaseToken; + this.productId = productId; + this.price = price; + this.currency = currency; + } + + } + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs.meta b/Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs.meta new file mode 100644 index 0000000..6d0024d --- /dev/null +++ b/Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d71b3864006f94ac08938b2ebdc940bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs b/Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs new file mode 100644 index 0000000..f159eea --- /dev/null +++ b/Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace AppsFlyerSDK +{ + /// + // + /// + public class AFSDKPurchaseDetailsIOS + { + public string productId { get; private set; } + public string price { get; private set; } + public string currency { get; private set; } + public string transactionId { get; private set; } + + private AFSDKPurchaseDetailsIOS(string productId, string price, string currency, string transactionId) + { + this.productId = productId; + this.price = price; + this.currency = currency; + this.transactionId = transactionId; + } + + public static AFSDKPurchaseDetailsIOS Init(string productId, string price, string currency, string transactionId) + { + return new AFSDKPurchaseDetailsIOS(productId, price, currency, transactionId); + } + } + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs.meta b/Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs.meta new file mode 100644 index 0000000..f33ebcc --- /dev/null +++ b/Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44bb6c4472701416080eb050732075ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AFSDKValidateAndLogResult.cs b/Assets/AppsFlyer/AFSDKValidateAndLogResult.cs new file mode 100644 index 0000000..e877fbd --- /dev/null +++ b/Assets/AppsFlyer/AFSDKValidateAndLogResult.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace AppsFlyerSDK +{ + public enum AFSDKValidateAndLogStatus + { + AFSDKValidateAndLogStatusSuccess, + AFSDKValidateAndLogStatusFailure, + AFSDKValidateAndLogStatusError + } + + + /// + // + /// + public class AFSDKValidateAndLogResult + { + public AFSDKValidateAndLogStatus status { get; private set; } + public Dictionary result { get; private set; } + public Dictionary errorData { get; private set; } + public string error { get; private set; } + + private AFSDKValidateAndLogResult(AFSDKValidateAndLogStatus status, Dictionary result, Dictionary errorData, string error) + { + this.status = status; + this.result = result; + this.errorData = errorData; + this.error = error; + } + + public static AFSDKValidateAndLogResult Init(AFSDKValidateAndLogStatus status, Dictionary result, Dictionary errorData, string error) + { + return new AFSDKValidateAndLogResult(status, result, errorData, error); + } + } + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AFSDKValidateAndLogResult.cs.meta b/Assets/AppsFlyer/AFSDKValidateAndLogResult.cs.meta new file mode 100644 index 0000000..63d4835 --- /dev/null +++ b/Assets/AppsFlyer/AFSDKValidateAndLogResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2df1c6f1eab2e4849bf2762a8d78933f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyer.asmdef b/Assets/AppsFlyer/AppsFlyer.asmdef new file mode 100644 index 0000000..381ee00 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyer.asmdef @@ -0,0 +1,13 @@ +{ + "name": "AppsFlyer", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AppsFlyer.asmdef.meta b/Assets/AppsFlyer/AppsFlyer.asmdef.meta new file mode 100644 index 0000000..380f36a --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyer.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2a37df438292d4903b4e5159c5de3bf9 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyer.cs b/Assets/AppsFlyer/AppsFlyer.cs new file mode 100644 index 0000000..670932a --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyer.cs @@ -0,0 +1,1087 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AppsFlyerSDK +{ + public class AppsFlyer : MonoBehaviour + { + + public static readonly string kAppsFlyerPluginVersion = "6.14.3"; + public static string CallBackObjectName = null; + private static EventHandler onRequestResponse; + private static EventHandler onInAppResponse; + private static EventHandler onDeepLinkReceived; + public static IAppsFlyerNativeBridge instance = null; + public delegate void unityCallBack(string message); + + + /// + /// Initialize the AppsFlyer SDK with your devKey and appID. + /// The dev key is required on all platforms, and the appID is required for iOS. + /// If you app is for Android only pass null for the appID. + /// + /// AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard. + /// Your app's Apple ID. + /// + /// + /// AppsFlyer.initSDK("K2***********99", "41*****44""); + /// + /// + public static void initSDK(string devKey, string appID) + { + initSDK(devKey, appID, null); + } + + /// + /// Initialize the AppsFlyer SDK with your devKey and appID. + /// The dev key is required on all platforms, and the appID is required for iOS. + /// If you app is for Android only pass null for the appID. + /// + /// AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard. + /// Your app's Apple ID. + /// pass the script of the game object being used. + /// + /// + /// AppsFlyer.initSDK("K2***********99", 41*****44, this); + /// + /// + public static void initSDK(string devKey, string appID, MonoBehaviour gameObject) + { + + if (gameObject != null) + { +#if UNITY_STANDALONE_OSX + CallBackObjectName = gameObject.GetType().ToString(); +#else + CallBackObjectName = gameObject.name; +#endif + } + +#if UNITY_IOS || UNITY_STANDALONE_OSX + if (instance == null || !instance.isInit) + { + instance = new AppsFlyeriOS(devKey, appID, gameObject); + instance.isInit = true; + } +#elif UNITY_ANDROID + if (instance == null || !instance.isInit) + { + AppsFlyerAndroid appsFlyerAndroid = new AppsFlyerAndroid(); + appsFlyerAndroid.initSDK(devKey, gameObject); + instance = appsFlyerAndroid; + instance.isInit = true; + + } +#elif UNITY_WSA_10_0 + AppsFlyerWindows.InitSDK(devKey, appID, gameObject); + if (gameObject != null) + { + AppsFlyerWindows.GetConversionData(gameObject.name); + } +#else + +#endif + } + + + /// + /// Once this API is invoked, our SDK will start. + /// Once the API is called a sessions will be immediately sent, and all background forground transitions will send a session. + /// + public static void startSDK() + { +#if UNITY_WSA_10_0 + AppsFlyerWindows.Start(); + +#else + if (instance != null) + { + instance.startSDK(onRequestResponse != null, CallBackObjectName); + } +#endif + } + + + + + + + /// + /// Send an In-App Event. + /// In-App Events provide insight on what is happening in your app. + /// + /// Event Name as String. + /// Event Values as Dictionary. + public static void sendEvent(string eventName, Dictionary eventValues) + { +#if UNITY_WSA_10_0 && !UNITY_EDITOR + AppsFlyerWindows.LogEvent(eventName, eventValues); +#else + if (instance != null) + { + instance.sendEvent(eventName, eventValues, onInAppResponse != null, CallBackObjectName); + } +#endif + } + /// + /// Once this API is invoked, our SDK no longer communicates with our servers and stops functioning. + /// In some extreme cases you might want to shut down all SDK activity due to legal and privacy compliance. + /// This can be achieved with the stopSDK API. + /// + /// should sdk be stopped. + public static void stopSDK(bool isSDKStopped) + { + if (instance != null) + { + instance.stopSDK(isSDKStopped); + } + } + + // + /// Was the stopSDK(boolean) API set to true. + /// + /// boolean isSDKStopped. + public static bool isSDKStopped() + { + if (instance != null) + { + return instance.isSDKStopped(); + } + + return false; + } + + /// + /// Get the AppsFlyer SDK version used in app. + /// + /// The current SDK version. + public static string getSdkVersion() + { + if (instance != null) + { + return instance.getSdkVersion(); + } + + return ""; + + } + + /// + /// Enables Debug logs for the AppsFlyer SDK. + /// Should only be set to true in development / debug. + /// + /// shouldEnable boolean. + public static void setIsDebug(bool shouldEnable) + { + if (instance != null) + { + instance.setIsDebug(shouldEnable); + } else { +#if UNITY_IOS || UNITY_STANDALONE_OSX + instance = new AppsFlyeriOS(); + instance.setIsDebug(shouldEnable); +#elif UNITY_ANDROID + instance = new AppsFlyerAndroid(); + instance.setIsDebug(shouldEnable); +#else + +#endif + } + + } + + /// + /// Setting your own customer ID enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and the other devices’ IDs. + /// This ID is available in AppsFlyer CSV reports along with Postback APIs for cross-referencing with your internal IDs. + /// + /// Customer ID for client. + public static void setCustomerUserId(string id) + { +#if UNITY_WSA_10_0 && !UNITY_EDITOR + AppsFlyerWindows.SetCustomerUserId(id); +#else + if (instance != null) + { + instance.setCustomerUserId(id); + } +#endif + } + + /// + /// Set the OneLink ID that should be used for User-Invite-API. + /// The link that is generated for the user invite will use this OneLink as the base link. + /// + /// OneLink ID obtained from the AppsFlyer Dashboard. + public static void setAppInviteOneLinkID(string oneLinkId) + { + + if (instance != null) + { + instance.setAppInviteOneLinkID(oneLinkId); + } + + + } + + /// + /// Set the deepLink timeout value that should be used for DDL. + /// + /// deepLink timeout in milliseconds. + public static void setDeepLinkTimeout(long deepLinkTimeout) + { + + if (instance != null) + { + instance.setDeepLinkTimeout(deepLinkTimeout); + } + + + } + + /// + /// Set additional data to be sent to AppsFlyer. + /// + /// additional data Dictionary. + public static void setAdditionalData(Dictionary customData) + { + + if (instance != null) + { + instance.setAdditionalData(customData); + } + + + } + + /// + /// Advertisers can wrap AppsFlyer OneLink within another Universal Link. + /// This Universal Link will invoke the app but any deep linking data will not propagate to AppsFlyer. + /// + /// Array of urls. + public static void setResolveDeepLinkURLs(params string[] urls) + { + + if (instance != null) + { + instance.setResolveDeepLinkURLs(urls); + } + + + } + + + /// + /// Advertisers can use this method to set vanity onelink domains. + /// + /// Array of domains. + public static void setOneLinkCustomDomain(params string[] domains) + { + + if (instance != null) + { + instance.setOneLinkCustomDomain(domains); + } + else + { +#if UNITY_IOS || UNITY_STANDALONE_OSX + instance = new AppsFlyeriOS(); +#elif UNITY_ANDROID + instance = new AppsFlyerAndroid(); +#else + +#endif + + + + } + } + + /// + /// Setting user local currency code for in-app purchases. + /// The currency code should be a 3 character ISO 4217 code. (default is USD). + /// You can set the currency code for all events by calling the following method. + /// + /// 3 character ISO 4217 code. + public static void setCurrencyCode(string currencyCode) + { + + if (instance != null) + { + instance.setCurrencyCode(currencyCode); + } else { +#if UNITY_IOS || UNITY_STANDALONE_OSX + instance = new AppsFlyeriOS(); + instance.setCurrencyCode(currencyCode); +#elif UNITY_ANDROID + instance = new AppsFlyerAndroid(); + instance.setCurrencyCode(currencyCode); +#else +#endif + } + } + + /// + /// Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage purposes within the application. + /// + /// instance of AppsFlyerConsent. + public static void setConsentData(AppsFlyerConsent appsFlyerConsent) + { + if (instance != null) + { + instance.setConsentData(appsFlyerConsent); + } + } + + /// + /// Manually record the location of the user. + /// + /// latitude as double. + /// longitude as double. + public static void recordLocation(double latitude, double longitude) + { + + if (instance != null) + { + instance.recordLocation(latitude, longitude); + } + + + } + + /// + /// Anonymize user Data. + /// Use this API during the SDK Initialization to explicitly anonymize a user's installs, events and sessions. + /// Default is false. + /// + /// shouldAnonymizeUser boolean. + public static void anonymizeUser(bool shouldAnonymizeUser) + { + + if (instance != null) + { + instance.anonymizeUser(shouldAnonymizeUser); + } + + + } + + /// + /// Calling enableTCFDataCollection(true) will enable collecting and sending any TCF related data. + /// Calling enableTCFDataCollection(false) will disable the collection of TCF related data and from sending it. + /// + /// should start TCF Data collection boolean. + public static void enableTCFDataCollection(bool shouldCollectTcfData) + { + if (instance != null) + { + instance.enableTCFDataCollection(shouldCollectTcfData); + } + } + + /// + /// Get AppsFlyer's unique device ID which is created for every new install of an app. + /// + /// AppsFlyer's unique device ID. + public static string getAppsFlyerId() + { +#if UNITY_WSA_10_0 && !UNITY_EDITOR + return AppsFlyerWindows.GetAppsFlyerId(); +#else + if (instance != null) + { + return instance.getAppsFlyerId(); + } +#endif + return string.Empty; + + } + + /// + /// Set a custom value for the minimum required time between sessions. + /// By default, at least 5 seconds must lapse between 2 app launches to count as separate 2 sessions. + /// + /// minimum time between 2 separate sessions in seconds. + public static void setMinTimeBetweenSessions(int seconds) + { + + if (instance != null) + { + instance.setMinTimeBetweenSessions(seconds); + } + + + } + + /// + /// Set a custom host. + /// + /// Host prefix. + /// Host name. + public static void setHost(string hostPrefixName, string hostName) + { + + if (instance != null) + { + instance.setHost(hostPrefixName, hostName); + } else { +#if UNITY_IOS || UNITY_STANDALONE_OSX + instance = new AppsFlyeriOS(); + instance.setHost(hostPrefixName, hostName); +#elif UNITY_ANDROID + instance = new AppsFlyerAndroid(); + instance.setHost(hostPrefixName, hostName); +#else +#endif + } + } + + /// + /// Set the user emails and encrypt them. + /// cryptMethod Encryption method: + /// EmailCryptType.EmailCryptTypeMD5 + /// EmailCryptType.EmailCryptTypeSHA1 + /// EmailCryptType.EmailCryptTypeSHA256 + /// EmailCryptType.EmailCryptTypeNone + /// + /// Encryption method. + /// User emails. + public static void setUserEmails(EmailCryptType cryptType, params string[] userEmails) + { + + if (instance != null) + { + instance.setUserEmails(cryptType, userEmails); + } + + } + + public static void updateServerUninstallToken(string token) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.updateServerUninstallToken(token); + } + } + + /// + /// Set the user phone number. + /// + /// phoneNumber string + public static void setPhoneNumber(string phoneNumber) + { + + if (instance != null) + { + instance.setPhoneNumber(phoneNumber); + } + + } + + public static void setImeiData(string aImei) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setImeiData(aImei); + } + } + + /// + /// Used by advertisers to exclude all networks/integrated partners from getting data. + /// + [Obsolete("Please use setSharingFilterForPartners api")] + public static void setSharingFilterForAllPartners() + { + + if (instance != null) + { + instance.setSharingFilterForAllPartners(); + } + + + } + + public static void setAndroidIdData(string aAndroidId) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setAndroidIdData(aAndroidId); + } + } + + public static void waitForCustomerUserId(bool wait) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.waitForCustomerUserId(wait); + } + } + + /// + /// Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data. + /// + /// partners to exclude from getting data + [Obsolete("Please use setSharingFilterForPartners api")] + public static void setSharingFilter(params string[] partners) + { + + if (instance != null) + { + instance.setSharingFilter(partners); + } + + + } + + public static void setCustomerIdAndStartSDK(string id) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setCustomerIdAndStartSDK(id); + } + } + + /// + /// Lets you configure how which partners should the SDK exclude from data-sharing. + /// + /// partners to exclude from getting data + public static void setSharingFilterForPartners(params string[] partners) + { +#if UNITY_IOS || UNITY_STANDALONE_OSX + AppsFlyeriOS.setSharingFilterForPartners(partners); +#elif UNITY_ANDROID + AppsFlyerAndroid.setSharingFilterForPartners(partners); +#else + +#endif + } + + public static string getOutOfStore() + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + return appsFlyerAndroidInstance.getOutOfStore(); + } + return string.Empty; + } + + public static void setOutOfStore(string sourceName) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setOutOfStore(sourceName); + } + } + + /// + /// Register a Conversion Data Listener. + /// Allows the developer to access the user attribution data in real-time for every new install, directly from the SDK level. + /// By doing this you can serve users with personalized content or send them to specific activities within the app, + /// which can greatly enhance their engagement with your app. + /// + /// + /// + /// AppsFlyer.getConversionData(this.name); + /// + /// + public static void getConversionData(string objectName) + { +#if UNITY_WSA_10_0 && !UNITY_EDITOR + AppsFlyerWindows.GetConversionData(""); +#else + if (instance != null) + { + instance.getConversionData(objectName); + } +#endif + + } + + public static void setCollectAndroidID(bool isCollect) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setCollectAndroidID(isCollect); + } + } + + public static void setIsUpdate(bool isUpdate) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setIsUpdate(isUpdate); + } + } + + public static void setCollectIMEI(bool isCollect) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setCollectIMEI(isCollect); + } + } + + public static void setDisableCollectAppleAdSupport(bool disable) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.setDisableCollectAppleAdSupport(disable); + } + } + + public static void setShouldCollectDeviceName(bool shouldCollectDeviceName) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.setShouldCollectDeviceName(shouldCollectDeviceName); + } + } + + + /// + /// Use the following API to attribute the click and launch the app store's app page. + /// + /// promoted App ID + /// cross promotion campaign + /// additional user params + /// + /// + /// Dictionary parameters = new Dictionary(); + /// parameters.Add("af_sub1", "val"); + /// parameters.Add("custom_param", "val2"); + /// AppsFlyer.attributeAndOpenStore("123456789", "test campaign", parameters, this); + /// + /// + public static void attributeAndOpenStore(string appID, string campaign, Dictionary userParams, MonoBehaviour gameObject) + { + + if (instance != null) + { + instance.attributeAndOpenStore(appID, campaign, userParams, gameObject); + } + + } + + public static void setPreinstallAttribution(string mediaSource, string campaign, string siteId) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setPreinstallAttribution(mediaSource, campaign, siteId); + } + } + + public static void setDisableCollectIAd(bool disableCollectIAd) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.setDisableCollectIAd(disableCollectIAd); + } + } + + public static bool isPreInstalledApp() + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + return appsFlyerAndroidInstance.isPreInstalledApp(); + } + return false; + } + + public static void setUseReceiptValidationSandbox(bool useReceiptValidationSandbox) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.setUseReceiptValidationSandbox(useReceiptValidationSandbox); + } + } + + /// + /// To attribute an impression use the following API call. + /// Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard. + /// + /// promoted App ID. + /// cross promotion campaign. + /// parameters Dictionary. + public static void recordCrossPromoteImpression(string appID, string campaign, Dictionary parameters) + { + + if (instance != null) + { + instance.recordCrossPromoteImpression(appID, campaign, parameters); + } + + } + + public static void setUseUninstallSandbox(bool useUninstallSandbox) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.setUseUninstallSandbox(useUninstallSandbox); + } + } + + public static string getAttributionId() + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + return appsFlyerAndroidInstance.getAttributionId(); + } + return string.Empty; + } + + public static void handlePushNotifications() + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.handlePushNotifications(); + } + } + + public static void validateAndSendInAppPurchase(string productIdentifier, string price, string currency, string transactionId, Dictionary additionalParameters, MonoBehaviour gameObject) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.validateAndSendInAppPurchase(productIdentifier, price, currency, transactionId, additionalParameters, gameObject); + } + } + + // V2 + public static void validateAndSendInAppPurchase(AFSDKPurchaseDetailsIOS details, Dictionary extraEventValues, MonoBehaviour gameObject) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.validateAndSendInAppPurchase(details, extraEventValues, gameObject); + } + } + + public static void validateAndSendInAppPurchase(string publicKey, string signature, string purchaseData, string price, string currency, Dictionary additionalParameters, MonoBehaviour gameObject) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.validateAndSendInAppPurchase(publicKey, signature,purchaseData, price, currency, additionalParameters, gameObject); + } + } + + // V2 + public static void validateAndSendInAppPurchase(AFPurchaseDetailsAndroid details, Dictionary additionalParameters, MonoBehaviour gameObject) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.validateAndSendInAppPurchase(details, additionalParameters, gameObject); + } + } + + public static void handleOpenUrl(string url, string sourceApplication, string annotation) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.handleOpenUrl(url, sourceApplication, annotation); + } + } + + public static void registerUninstall(byte[] deviceToken) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.registerUninstall(deviceToken); + } + } + + public static void waitForATTUserAuthorizationWithTimeoutInterval(int timeoutInterval) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.waitForATTUserAuthorizationWithTimeoutInterval(timeoutInterval); + } + } + + public static void setCurrentDeviceLanguage(string language) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.setCurrentDeviceLanguage(language); + } + } + + /// + /// The LinkGenerator class builds the invite URL according to various setter methods which allow passing on additional information on the click. + /// See - https://support.appsflyer.com/hc/en-us/articles/115004480866-User-invite-attribution- + /// + /// parameters Dictionary. + public static void generateUserInviteLink(Dictionary parameters, MonoBehaviour gameObject) + { + + if (instance != null) + { + instance.generateUserInviteLink(parameters, gameObject); + } + + } + + public static void disableSKAdNetwork(bool isDisabled) + { + if (instance != null && instance is IAppsFlyerIOSBridge) + { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.disableSKAdNetwork(isDisabled); + } else { +#if UNITY_IOS || UNITY_STANDALONE_OSX + instance = new AppsFlyeriOS(); + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.disableSKAdNetwork(isDisabled); +#else +#endif + } + } + + public static void setCollectOaid(bool isCollect) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setCollectOaid(isCollect); + } + } + + + /// + /// Use this method if you’re integrating your app with push providers + /// that don’t use the default push notification JSON schema the SDK expects. + /// See docs for more info. + /// + /// array of nested json path + public static void addPushNotificationDeepLinkPath(params string[] paths) + { + + if (instance != null) + { + instance.addPushNotificationDeepLinkPath(paths); + } + + } + + public static void setDisableAdvertisingIdentifiers(bool disable) + { + if (instance != null && instance is IAppsFlyerAndroidBridge) + { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setDisableAdvertisingIdentifiers(disable); + } + } + + /// + /// Subscribe for unified deeplink API. + /// This is called automatically from OnDeepLinkReceived. + /// CallBackObjectName is set in the init method. + /// + public static void subscribeForDeepLink() + { + + if (instance != null) + { + instance.subscribeForDeepLink(CallBackObjectName); + } + + } + + /// + /// Allows sending custom data for partner integration purposes. + /// partnerId : id of the partner + /// partnerInfo: customer data + /// + public static void setPartnerData(string partnerId, Dictionary partnerInfo) + { + if (instance != null) + { + instance.setPartnerData(partnerId, partnerInfo); + } + + } + + /// + /// Use to opt-out of collecting the network operator name (carrier) and sim operator name from the device. + /// + public static void setDisableNetworkData(bool disable) { + if (instance != null && instance is IAppsFlyerAndroidBridge) { + IAppsFlyerAndroidBridge appsFlyerAndroidInstance = (IAppsFlyerAndroidBridge)instance; + appsFlyerAndroidInstance.setDisableNetworkData(disable); + } + } + + + /// + /// Use to disable app vendor identifier (IDFV) collection, 'true' to disable. + /// + public static void disableIDFVCollection(bool isDisabled) + { +#if UNITY_IOS || UNITY_STANDALONE_OSX + if (instance == null) { + instance = new AppsFlyeriOS(); + } + if (instance != null && instance is IAppsFlyerIOSBridge) { + IAppsFlyerIOSBridge appsFlyeriOSInstance = (IAppsFlyerIOSBridge)instance; + appsFlyeriOSInstance.disableIDFVCollection(isDisabled); + } +#else +#endif + } + + /// + /// Start callback event. + /// + public static event EventHandler OnRequestResponse + { + add + { + onRequestResponse += value; + } + remove + { + onRequestResponse -= value; + } + } + + /// + /// In-App callback event. + /// + public static event EventHandler OnInAppResponse + { + add + { + onInAppResponse += value; + } + remove + { + onInAppResponse -= value; + } + } + + /// + /// Unified DeepLink Event + /// + public static event EventHandler OnDeepLinkReceived + { + add + { + onDeepLinkReceived += value; + subscribeForDeepLink(); + } + remove + { + onDeepLinkReceived -= value; + } + } + + /// + /// Used to accept start callback from UnitySendMessage on native side. + /// + public void inAppResponseReceived(string response) + { + if (onInAppResponse != null) + { + onInAppResponse.Invoke(null, parseRequestCallback(response)); + } + } + + /// + /// Used to accept in-app callback from UnitySendMessage on native side. + /// + public void requestResponseReceived(string response) + { + if (onRequestResponse != null) + { + onRequestResponse.Invoke(null, parseRequestCallback(response)); + } + } + + /// + /// Used to accept deeplink callback from UnitySendMessage on native side. + /// + public void onDeepLinking(string response) + { + + DeepLinkEventsArgs args = new DeepLinkEventsArgs(response); + + if (onDeepLinkReceived != null) + { + onDeepLinkReceived.Invoke(null, args); + } + } + + private static AppsFlyerRequestEventArgs parseRequestCallback(string response) + { + int responseCode = 0; + string errorDescription = ""; + + try + { + Dictionary dictionary = CallbackStringToDictionary(response); + var errorResponse = dictionary.ContainsKey("errorDescription") ? dictionary["errorDescription"] : ""; + errorDescription = (string)errorResponse; + responseCode = (int)(long) dictionary["statusCode"]; + } + catch (Exception e) + { + AFLog("parseRequestCallback", String.Format("{0} Exception caught.", e)); + } + + return new AppsFlyerRequestEventArgs(responseCode, errorDescription); + } + + /// + /// Helper method to convert json strings to dictionary. + /// + /// json string + /// dictionary representing the input json string. + public static Dictionary CallbackStringToDictionary(string str) + { + return AFMiniJSON.Json.Deserialize(str) as Dictionary; + } + + /// + /// Helper method to log AppsFlyer events and callbacks. + /// + /// method name + /// message to log + public static void AFLog(string methodName, string str) + { + Debug.Log(string.Format("AppsFlyer_Unity_v{0} {1} called with {2}", kAppsFlyerPluginVersion, methodName, str)); + } + } + + public enum EmailCryptType + { + // None + EmailCryptTypeNone = 0, + // SHA256 + EmailCryptTypeSHA256 = 1, + } + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AppsFlyer.cs.meta b/Assets/AppsFlyer/AppsFlyer.cs.meta new file mode 100644 index 0000000..48d98d5 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45161025a517d427381d3d06153a5ad3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyerAdRevenue.cs b/Assets/AppsFlyer/AppsFlyerAdRevenue.cs new file mode 100644 index 0000000..1c9baf1 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerAdRevenue.cs @@ -0,0 +1,178 @@ +using System.Collections.Generic; +using UnityEngine; +using System.Runtime.InteropServices; +using System; + +namespace AppsFlyerSDK +{ + public class AppsFlyerAdRevenue : MonoBehaviour + { + + public static readonly string kAppsFlyerAdRevenueVersion = "6.14.3"; + +#if UNITY_ANDROID && !UNITY_EDITOR + private static AndroidJavaClass appsFlyerAndroid = new AndroidJavaClass("com.appsflyer.unity.afunityadrevenuegenericplugin.AdRevenueUnityWrapper"); +#endif + + public static void start() + { +#if UNITY_IOS && !UNITY_EDITOR + + _start(); + +#elif UNITY_ANDROID && !UNITY_EDITOR + + using(AndroidJavaClass cls_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { + + using(AndroidJavaObject cls_Activity = cls_UnityPlayer.GetStatic("currentActivity")) { + + AndroidJavaObject cls_Application = cls_Activity.Call("getApplication"); + + appsFlyerAndroid.CallStatic("start", cls_Application); + } + } + +#else + +#endif + } + + + public static void setIsDebug(bool isDebug) + { +#if UNITY_IOS && !UNITY_EDITOR + _setIsDebugAdrevenue(isDebug); +#elif UNITY_ANDROID && !UNITY_EDITOR + +#else + +#endif + } + + public static void logAdRevenue(string monetizationNetwork, + AppsFlyerAdRevenueMediationNetworkType mediationNetwork, + double eventRevenue, + string revenueCurrency, + Dictionary additionalParameters) + { +#if UNITY_IOS && !UNITY_EDITOR + + _logAdRevenue(monetizationNetwork, mediationNetwork, eventRevenue, revenueCurrency, AFMiniJSON.Json.Serialize(additionalParameters)); + +#elif UNITY_ANDROID && !UNITY_EDITOR + + int mediationNetworkAndroid = setMediationNetworkTypeAndroid(mediationNetwork); + if (mediationNetworkAndroid == -1) + { + Debug.Log("Please choose a valid mediationNetwork"); + } else + { + appsFlyerAndroid.CallStatic("logAdRevenue", + monetizationNetwork, + mediationNetworkAndroid, + revenueCurrency, + eventRevenue, + convertDictionaryToJavaMap(additionalParameters)); + + } +#else + +#endif + } + +#if UNITY_IOS && !UNITY_EDITOR + + [DllImport("__Internal")] + private static extern void _start(); + + [DllImport("__Internal")] + private static extern void _setIsDebugAdrevenue(bool isDebug); + + [DllImport("__Internal")] + private static extern void _logAdRevenue(string monetizationNetwork, + AppsFlyerAdRevenueMediationNetworkType mediationNetwork, + double eventRevenue, + string revenueCurrency, + string additionalParameters); + +#elif UNITY_ANDROID && !UNITY_EDITOR + +#else + +#endif + private static int setMediationNetworkTypeAndroid(AppsFlyerAdRevenueMediationNetworkType mediationNetwork) + { + switch (mediationNetwork) + { + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeIronSource: + return 0; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeApplovinMax: + return 1; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob: + return 2; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeFyber: + return 3; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeAppodeal: + return 4; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeAdmost: + return 5; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeTopon: + return 6; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeTradplus: + return 7; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeYandex: + return 8; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeChartBoost: + return 9; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeUnity: + return 10; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypeCustomMediation: + return 11; + case AppsFlyerAdRevenueMediationNetworkType.AppsFlyerAdRevenueMediationNetworkTypedirectMonetization: + return 12; + default: + return -1; + } + + } + private static AndroidJavaObject convertDictionaryToJavaMap(Dictionary dictionary) + { + AndroidJavaObject map = new AndroidJavaObject("java.util.HashMap"); + IntPtr putMethod = AndroidJNIHelper.GetMethodID(map.GetRawClass(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + jvalue[] val; + if (dictionary != null) + { + foreach (var entry in dictionary) + { + val = AndroidJNIHelper.CreateJNIArgArray(new object[] { entry.Key, entry.Value }); + AndroidJNI.CallObjectMethod(map.GetRawObject(), putMethod, val); + AndroidJNI.DeleteLocalRef(val[0].l); + AndroidJNI.DeleteLocalRef(val[1].l); + } + } + + return map; + } + } + + + public enum AppsFlyerAdRevenueMediationNetworkType + { + AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob = 1, + AppsFlyerAdRevenueMediationNetworkTypeIronSource = 2, + AppsFlyerAdRevenueMediationNetworkTypeApplovinMax = 3, + AppsFlyerAdRevenueMediationNetworkTypeFyber = 4, + AppsFlyerAdRevenueMediationNetworkTypeAppodeal = 5, + AppsFlyerAdRevenueMediationNetworkTypeAdmost = 6, + AppsFlyerAdRevenueMediationNetworkTypeTopon = 7, + AppsFlyerAdRevenueMediationNetworkTypeTradplus = 8, + AppsFlyerAdRevenueMediationNetworkTypeYandex = 9, + AppsFlyerAdRevenueMediationNetworkTypeChartBoost = 10, + AppsFlyerAdRevenueMediationNetworkTypeUnity = 11, + AppsFlyerAdRevenueMediationNetworkTypeCustomMediation = 12, + AppsFlyerAdRevenueMediationNetworkTypedirectMonetization = 13 + } + + + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AppsFlyerAdRevenue.cs.meta b/Assets/AppsFlyer/AppsFlyerAdRevenue.cs.meta new file mode 100644 index 0000000..af22f2f --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerAdRevenue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 644005ac4602e4b78ad3a8d4d29e329d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyerAndroid.cs b/Assets/AppsFlyer/AppsFlyerAndroid.cs new file mode 100644 index 0000000..0e085f6 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerAndroid.cs @@ -0,0 +1,779 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AppsFlyerSDK +{ + +#if UNITY_ANDROID + public class AppsFlyerAndroid : IAppsFlyerAndroidBridge + { + public bool isInit { get; set; } + + private static AndroidJavaClass appsFlyerAndroid = new AndroidJavaClass("com.appsflyer.unity.AppsFlyerAndroidWrapper"); + + public AppsFlyerAndroid() { } + + /// + /// Use this method to init the sdk for the application. + /// Call this method before startSDK. + /// + /// AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard. + /// The current game object. This is used to get the conversion data callbacks. Pass null if you do not need the callbacks. + public void initSDK(string devkey, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("initSDK", devkey, gameObject ? gameObject.name : null); +#endif + } + + /// + /// Use this method to start the sdk for the application. + /// The AppsFlyer's Dev-Key must be provided. + /// + /// AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard. + public void startSDK(bool onRequestResponse, string CallBackObjectName) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("startTracking", onRequestResponse, CallBackObjectName); +#endif + } + + /// + /// Once this API is invoked, our SDK no longer communicates with our servers and stops functioning. + /// In some extreme cases you might want to shut down all SDK activity due to legal and privacy compliance. + /// This can be achieved with the stopSDK API. + /// + /// boolean should SDK be stopped. + public void stopSDK(bool isSDKStopped) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("stopTracking", isSDKStopped); +#endif + } + + /// + /// Get the AppsFlyer SDK version used in app. + /// + /// AppsFlyer SDK version. + public string getSdkVersion() + { +#if !UNITY_EDITOR + return appsFlyerAndroid.CallStatic("getSdkVersion"); +#else + return ""; +#endif + } + + /// + /// Manually pass the Firebase / GCM Device Token for Uninstall measurement. + /// + /// Firebase Device Token. + public void updateServerUninstallToken(string token) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("updateServerUninstallToken", token); +#endif + } + + /// + /// Enables Debug logs for the AppsFlyer SDK. + /// Should only be set to true in development / debug. + /// + /// shouldEnable boolean. + public void setIsDebug(bool shouldEnable) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setIsDebug", shouldEnable); +#endif + } + + /// + /// By default, IMEI and Android ID are not collected by the SDK if the OS version is higher than KitKat (4.4) + /// and the device contains Google Play Services(on SDK versions 4.8.8 and below the specific app needed GPS). + /// Use this API to explicitly send IMEI to AppsFlyer. + /// + /// device's IMEI. + public void setImeiData(string aImei) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setImeiData", aImei); +#endif + } + + /// + /// By default, IMEI and Android ID are not collected by the SDK if the OS version is higher than KitKat(4.4) + /// and the device contains Google Play Services(on SDK versions 4.8.8 and below the specific app needed GPS). + /// Use this API to explicitly send Android ID to AppsFlyer. + /// + /// device's Android ID. + public void setAndroidIdData(string aAndroidId) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setAndroidIdData", aAndroidId); +#endif + } + + /// + /// Setting your own customer ID enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and the other devices’ IDs. + /// This ID is available in AppsFlyer CSV reports along with Postback APIs for cross-referencing with your internal IDs. + /// + /// Customer ID for client. + public void setCustomerUserId(string id) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setCustomerUserId", id); +#endif + } + + /// + /// It is possible to delay the SDK Initialization until the customerUserID is set. + /// This feature makes sure that the SDK doesn't begin functioning until the customerUserID is provided. + /// If this API is used, all in-app events and any other SDK API calls are discarded, until the customerUserID is provided. + /// + /// wait boolean. + public void waitForCustomerUserId(bool wait) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("waitForCustomerUserId", wait); +#endif + } + + /// + /// Use this API to provide the SDK with the relevant customer user id and trigger the SDK to begin its normal activity. + /// + /// Customer ID for client. + public void setCustomerIdAndStartSDK(string id) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setCustomerIdAndTrack", id); +#endif + } + + /// + /// Get the current AF_STORE value. + /// + /// AF_Store value. + public string getOutOfStore() + { +#if !UNITY_EDITOR + return appsFlyerAndroid.CallStatic("getOutOfStore"); +#else + return ""; +#endif + } + + /// + /// Manually set the AF_STORE value. + /// + /// value to be set. + public void setOutOfStore(string sourceName) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setOutOfStore", sourceName); +#endif + } + + /// + /// Set the OneLink ID that should be used for User-Invites. + /// The link that is generated for the user invite will use this OneLink as the base link. + /// + /// OneLink ID obtained from the AppsFlyer Dashboard. + public void setAppInviteOneLinkID(string oneLinkId) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setAppInviteOneLinkID", oneLinkId); +#endif + } + + /// + /// Set additional data to be sent to AppsFlyer. + /// + /// additional data Dictionary. + public void setAdditionalData(Dictionary customData) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setAdditionalData", convertDictionaryToJavaMap(customData)); +#endif + } + + //// + /// Set the deepLink timeout value that should be used for DDL. + /// + /// deepLink timeout in milliseconds. + public void setDeepLinkTimeout(long deepLinkTimeout) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setDeepLinkTimeout", deepLinkTimeout); +#endif + } + + /// + /// Set the user emails. + /// + /// User emails. + public void setUserEmails(params string[] userEmails) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setUserEmails", (object)userEmails); +#endif + } + + + /// + /// Set the user phone number. + /// + /// User phoneNumber. + public void setPhoneNumber(string phoneNumber){ +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setPhoneNumber", phoneNumber); +#endif + } + + /// + /// Set the user emails and encrypt them. + /// cryptMethod Encryption method: + /// EmailCryptType.EmailCryptTypeMD5 + /// EmailCryptType.EmailCryptTypeSHA1 + /// EmailCryptType.EmailCryptTypeSHA256 + /// EmailCryptType.EmailCryptTypeNone + /// + /// Encryption method. + /// User emails. + public void setUserEmails(EmailCryptType cryptMethod, params string[] emails) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setUserEmails", getEmailType(cryptMethod), (object)emails); +#endif + } + + /// + /// Opt-out of collection of Android ID. + /// If the app does NOT contain Google Play Services, Android ID is collected by the SDK. + /// However, apps with Google play services should avoid Android ID collection as this is in violation of the Google Play policy. + /// + /// boolean, false to opt-out. + public void setCollectAndroidID(bool isCollect) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setCollectAndroidID", isCollect); +#endif + } + + /// + /// Opt-out of collection of IMEI. + /// If the app does NOT contain Google Play Services, device IMEI is collected by the SDK. + /// However, apps with Google play services should avoid IMEI collection as this is in violation of the Google Play policy. + /// + /// boolean, false to opt-out. + public void setCollectIMEI(bool isCollect) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setCollectIMEI", isCollect); +#endif + } + + /// + /// Advertisers can wrap AppsFlyer OneLink within another Universal Link. + /// This Universal Link will invoke the app but any deep linking data will not propagate to AppsFlyer. + /// + /// Array of urls. + public void setResolveDeepLinkURLs(params string[] urls) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setResolveDeepLinkURLs", (object)urls); +#endif + } + + + /// + /// Advertisers can use this method to set vanity onelink domains. + /// + /// Array of domains. + public void setOneLinkCustomDomain(params string[] domains) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setOneLinkCustomDomain", (object)domains); +#endif + } + + /// + /// Manually set that the application was updated. + /// + /// isUpdate boolean value. + public void setIsUpdate(bool isUpdate) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setIsUpdate", isUpdate); +#endif + } + + /// + /// Setting user local currency code for in-app purchases. + /// The currency code should be a 3 character ISO 4217 code. (default is USD). + /// You can set the currency code for all events by calling the following method. + /// + /// 3 character ISO 4217 code. + public void setCurrencyCode(string currencyCode) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setCurrencyCode", currencyCode); +#endif + } + + /// + /// Manually record the location of the user. + /// + /// latitude as double. + /// longitude as double. + public void recordLocation(double latitude, double longitude) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("trackLocation", latitude, longitude); +#endif + } + + /// + /// Send an In-App Event. + /// In-App Events provide insight on what is happening in your app. + /// + /// Event Name as String. + /// Event Values as Dictionary. + public void sendEvent(string eventName, Dictionary eventValues) + { + sendEvent(eventName, eventValues, false, AppsFlyer.CallBackObjectName); + } + + public void sendEvent(string eventName, Dictionary eventValues, bool shouldCallback, string callBackObjectName) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("trackEvent", eventName, convertDictionaryToJavaMap(eventValues), shouldCallback, callBackObjectName); +#endif + } + + /// + /// Anonymize user Data. + /// Use this API during the SDK Initialization to explicitly anonymize a user's installs, events and sessions. + /// Default is false. + /// + /// isDisabled boolean. + public void anonymizeUser(bool isDisabled) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setDeviceTrackingDisabled", isDisabled); +#endif + } + + /// + /// Calling enableTCFDataCollection(true) will enable collecting and sending any TCF related data. + /// Calling enableTCFDataCollection(false) will disable the collection of TCF related data and from sending it. + /// + /// should start TCF Data collection boolean. + public void enableTCFDataCollection(bool shouldCollectTcfData) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("enableTCFDataCollection", shouldCollectTcfData); +#endif + } + + /// + /// Enable the collection of Facebook Deferred AppLinks. + /// Requires Facebook SDK and Facebook app on target/client device. + /// This API must be invoked prior to initializing the AppsFlyer SDK in order to function properly. + /// + /// should Facebook's deferred app links be processed by the AppsFlyer SDK. + public void enableFacebookDeferredApplinks(bool isEnabled) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("enableFacebookDeferredApplinks", isEnabled); +#endif + } + + /// + /// Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage purposes within the application. + /// call this method when GDPR user is true + /// + /// hasConsentForDataUsage boolean. + /// hasConsentForAdsPersonalization boolean. + public void setConsentData(AppsFlyerConsent appsFlyerConsent) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setConsentData", appsFlyerConsent.isUserSubjectToGDPR, appsFlyerConsent.hasConsentForDataUsage, appsFlyerConsent.hasConsentForAdsPersonalization); +#endif + } + + /// + /// Restrict reengagement via deep-link to once per each unique deep-link. + /// Otherwise deep re-occurring deep-links will be permitted for non-singleTask Activities and deep-linking via AppsFlyer deep-links. + /// The default value is false. + /// + /// doConsume boolean. + public void setConsumeAFDeepLinks(bool doConsume) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setConsumeAFDeepLinks", doConsume); +#endif + } + + /// + /// Specify the manufacturer or media source name to which the preinstall is attributed. + /// + /// Manufacturer or media source name for preinstall attribution. + /// Campaign name for preinstall attribution. + /// Site ID for preinstall attribution. + public void setPreinstallAttribution(string mediaSource, string campaign, string siteId) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setPreinstallAttribution", mediaSource, campaign, siteId); +#endif + } + + /// + /// Boolean indicator for preinstall by Manufacturer. + /// + /// boolean isPreInstalledApp. + public bool isPreInstalledApp() + { +#if !UNITY_EDITOR + return appsFlyerAndroid.CallStatic("isPreInstalledApp"); +#else + return false; +#endif + } + + /// + /// Get the Facebook attribution ID, if one exists. + /// + /// string Facebook attribution ID. + public string getAttributionId() + { +#if !UNITY_EDITOR + return appsFlyerAndroid.CallStatic("getAttributionId"); +#else + return ""; +#endif + } + + /// + /// Get AppsFlyer's unique device ID is created for every new install of an app. + /// + /// AppsFlyer's unique device ID. + public string getAppsFlyerId() + { +#if !UNITY_EDITOR + return appsFlyerAndroid.CallStatic("getAppsFlyerId"); +#else + return ""; +#endif + } + + /// + /// API for server verification of in-app purchases. + /// An af_purchase event with the relevant values will be automatically sent if the validation is successful. + /// + /// License Key obtained from the Google Play Console. + /// data.INAPP_DATA_SIGNATURE from onActivityResult(int requestCode, int resultCode, Intent data) + /// data.INAPP_PURCHASE_DATA from onActivityResult(int requestCode, int resultCode, Intent data) + /// Purchase price, should be derived from skuDetails.getStringArrayList("DETAILS_LIST") + /// Purchase currency, should be derived from skuDetails.getStringArrayList("DETAILS_LIST") + /// additionalParameters Freehand parameters to be sent with the purchase (if validated). + public void validateAndSendInAppPurchase(string publicKey, string signature, string purchaseData, string price, string currency, Dictionary additionalParameters, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("validateAndTrackInAppPurchase", publicKey, signature, purchaseData, price, currency, convertDictionaryToJavaMap(additionalParameters), gameObject ? gameObject.name : null); +#endif + } + + /// + /// API for server verification of in-app purchases. + /// An af_purchase event with the relevant values will be automatically sent if the validation is successful. + /// + /// AFPurchaseDetailsAndroid instance. + /// additionalParameters Freehand parameters to be sent with the purchase (if validated). + public void validateAndSendInAppPurchase(AFPurchaseDetailsAndroid details, Dictionary additionalParameters, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("validateAndTrackInAppPurchaseV2", (int)details.purchaseType, details.purchaseToken, details.productId, details.price, details.currency, convertDictionaryToJavaMap(additionalParameters), gameObject ? gameObject.name : null); +#endif + } + + /// + /// Was the stopSDK(boolean) API set to true. + /// + /// boolean isSDKStopped. + public bool isSDKStopped() + { +#if !UNITY_EDITOR + return appsFlyerAndroid.CallStatic("isTrackingStopped"); +#else + return false; +#endif + } + + /// + /// Set a custom value for the minimum required time between sessions. + /// By default, at least 5 seconds must lapse between 2 app launches to count as separate 2 sessions. + /// + /// minimum time between 2 separate sessions in seconds. + public void setMinTimeBetweenSessions(int seconds) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setMinTimeBetweenSessions", seconds); +#endif + } + + /// + /// Set a custom host. + /// + /// Host prefix. + /// Host name. + public void setHost(string hostPrefixName, string hostName) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setHost", hostPrefixName, hostName); +#endif + } + + /// + /// Get the host name. + /// Default value is "appsflyer.com". + /// + /// Host name. + public string getHostName() + { +#if !UNITY_EDITOR + return appsFlyerAndroid.CallStatic("getHostName"); +#else + return ""; +#endif + } + + /// + /// Get the custom host prefix. + /// + /// Host prefix. + public string getHostPrefix() + { +#if !UNITY_EDITOR + return appsFlyerAndroid.CallStatic("getHostPrefix"); +#else + return ""; +#endif + } + + /// + /// Used by advertisers to exclude all networks/integrated partners from getting data. + /// + public void setSharingFilterForAllPartners() + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setSharingFilterForAllPartners"); +#endif + } + + /// + /// Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data. + /// + /// partners to exclude from getting data + public void setSharingFilter(params string[] partners) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setSharingFilter", (object)partners); +#endif + } + + /// + /// Lets you configure how which partners should the SDK exclude from data-sharing. + /// + /// partners to exclude from getting data + public static void setSharingFilterForPartners(params string[] partners) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setSharingFilterForPartners", (object)partners); +#endif + } + + /// + /// Register a Conversion Data Listener. + /// Allows the developer to access the user attribution data in real-time for every new install, directly from the SDK level. + /// By doing this you can serve users with personalized content or send them to specific activities within the app, + /// which can greatly enhance their engagement with your app. + /// + public void getConversionData(string objectName) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("getConversionData", objectName); +#endif + } + + /// + /// Register a validation listener for the validateAndSendInAppPurchase API. + /// + public void initInAppPurchaseValidatorListener(MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("initInAppPurchaseValidatorListener", gameObject ? gameObject.name : null); +#endif + } + + /// + /// setCollectOaid + /// You must include the appsflyer oaid library for this api to work. + /// + /// isCollect oaid - set fasle to opt out + public void setCollectOaid(bool isCollect) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setCollectOaid", isCollect); +#endif + } + + /// + /// Use the following API to attribute the click and launch the app store's app page. + /// + /// promoted App ID + /// cross promotion campaign + /// additional user params + public void attributeAndOpenStore(string promoted_app_id, string campaign, Dictionary userParams, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("attributeAndOpenStore", promoted_app_id, campaign, convertDictionaryToJavaMap(userParams)); +#endif + } + + /// + /// To attribute an impression use the following API call. + /// Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard. + /// + /// promoted App ID. + /// cross promotion campaign. + /// parameters Dictionary. + public void recordCrossPromoteImpression(string appID, string campaign, Dictionary parameters) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("recordCrossPromoteImpression", appID, campaign, convertDictionaryToJavaMap(parameters)); +#endif + } + + /// + /// The LinkGenerator class builds the invite URL according to various setter methods which allow passing on additional information on the click. + /// See - https://support.appsflyer.com/hc/en-us/articles/115004480866-User-invite-attribution- + /// + /// parameters Dictionary. + public void generateUserInviteLink(Dictionary parameters, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("createOneLinkInviteListener", convertDictionaryToJavaMap(parameters), gameObject ? gameObject.name : null); +#endif + } + + /// + /// To measure push notifications as part of a retargeting campaign. + /// + public void handlePushNotifications(){ +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("handlePushNotifications"); +#endif + } + + /// + /// Use this method if you’re integrating your app with push providers + /// that don’t use the default push notification JSON schema the SDK expects. + /// See docs for more info. + /// + /// array of nested json path + public void addPushNotificationDeepLinkPath(params string[] paths) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("addPushNotificationDeepLinkPath", (object)paths); +#endif + } + + /// + /// subscribe to unified deep link callbacks + /// + public void subscribeForDeepLink(string objectName){ +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("subscribeForDeepLink", objectName); +#endif + } + + /// + /// Disables collection of various Advertising IDs by the SDK. This includes Google Advertising ID (GAID), OAID and Amazon Advertising ID (AAID) + /// + /// disable boolean. + public void setDisableAdvertisingIdentifiers(bool disable) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setDisableAdvertisingIdentifiers", disable); +#endif + } + + /// + /// Allows sending custom data for partner integration purposes. + /// + public void setPartnerData(string partnerId, Dictionary partnerInfo) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setPartnerData", partnerId, convertDictionaryToJavaMap(partnerInfo)); +#endif + } + + /// + /// Use to opt-out of collecting the network operator name (carrier) and sim operator name from the device. + /// + public void setDisableNetworkData(bool disable) { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setDisableNetworkData", disable); +#endif + } + + /// + /// Internal Helper Method. + /// + private static AndroidJavaObject getEmailType(EmailCryptType cryptType) + { + AndroidJavaClass emailsCryptTypeEnum = new AndroidJavaClass("com.appsflyer.AppsFlyerProperties$EmailsCryptType"); + AndroidJavaObject emailsCryptType; + + switch (cryptType) + { + case EmailCryptType.EmailCryptTypeSHA256: + emailsCryptType = emailsCryptTypeEnum.GetStatic("SHA256"); + break; + default: + emailsCryptType = emailsCryptTypeEnum.GetStatic("NONE"); + break; + } + + return emailsCryptType; + } + + /// + /// Internal Helper Method. + /// + private static AndroidJavaObject convertDictionaryToJavaMap(Dictionary dictionary) + { + AndroidJavaObject map = new AndroidJavaObject("java.util.HashMap"); + IntPtr putMethod = AndroidJNIHelper.GetMethodID(map.GetRawClass(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + jvalue[] val; + if (dictionary != null) + { + foreach (var entry in dictionary) + { + val = AndroidJNIHelper.CreateJNIArgArray(new object[] { entry.Key, entry.Value }); + AndroidJNI.CallObjectMethod(map.GetRawObject(), putMethod,val); + AndroidJNI.DeleteLocalRef(val[0].l); + AndroidJNI.DeleteLocalRef(val[1].l); + } + } + + return map; + } + } + +#endif + + + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AppsFlyerAndroid.cs.meta b/Assets/AppsFlyer/AppsFlyerAndroid.cs.meta new file mode 100644 index 0000000..d7ce722 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerAndroid.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 172d18dd98e7e4ed3b30110568b0fae4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyerConsent.cs b/Assets/AppsFlyer/AppsFlyerConsent.cs new file mode 100644 index 0000000..341e530 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerConsent.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; + +namespace AppsFlyerSDK +{ + /// + // Data class representing a user's consent for data processing in accordance with GDPR and DMA + // (Digital Markets Act) compliance, specifically regarding advertising preferences. + + // This class should be used to notify and record the user's applicability + // under GDPR, their general consent to data usage, and their consent to personalized + // advertisements based on user data. + + // Note that the consent for data usage and ads personalization pair is only applicable when the user is + // subject to GDPR guidelines. Therefore, the following factory methods should be used accordingly: + // - Use [forGDPRUser] when the user is subject to GDPR. + // - Use [forNonGDPRUser] when the user is not subject to GDPR. + + // @property isUserSubjectToGDPR Indicates whether GDPR regulations apply to the user (true if the user is + // a subject of GDPR). It also serves as a flag for compliance with relevant aspects of DMA regulations. + // @property hasConsentForDataUsage Indicates whether the user has consented to the use of their data for advertising + // purposes under both GDPR and DMA guidelines (true if the user has consented, nullable if not subject to GDPR). + // @property hasConsentForAdsPersonalization Indicates whether the user has consented to the use of their data for + // personalized advertising within the boundaries of GDPR and DMA rules (true if the user has consented to + // personalized ads, nullable if not subject to GDPR). + /// + public class AppsFlyerConsent + { + public bool isUserSubjectToGDPR { get; private set; } + public bool hasConsentForDataUsage { get; private set; } + public bool hasConsentForAdsPersonalization { get; private set; } + + private AppsFlyerConsent(bool isGDPR, bool hasForDataUsage, bool hasForAdsPersonalization) + { + isUserSubjectToGDPR = isGDPR; + hasConsentForDataUsage = hasForDataUsage; + hasConsentForAdsPersonalization = hasForAdsPersonalization; + } + + public static AppsFlyerConsent ForGDPRUser(bool hasConsentForDataUsage, bool hasConsentForAdsPersonalization) + { + return new AppsFlyerConsent(true, hasConsentForDataUsage, hasConsentForAdsPersonalization); + } + + public static AppsFlyerConsent ForNonGDPRUser() + { + return new AppsFlyerConsent(false, false, false); + } + } + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AppsFlyerConsent.cs.meta b/Assets/AppsFlyer/AppsFlyerConsent.cs.meta new file mode 100644 index 0000000..5a881de --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerConsent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a97c986fe4ee0461badf7042e08db3f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyerEventArgs.cs b/Assets/AppsFlyer/AppsFlyerEventArgs.cs new file mode 100644 index 0000000..511db67 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerEventArgs.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; + +namespace AppsFlyerSDK +{ + + /// + /// Event args for AppsFlyer requests. + /// Used for sessions and in-app events. + /// Used to handle post request logic. + /// + /// Examples: + /// statusCode / errorDescription + /// + /// 200 - null + /// + /// 10 - "Event timeout. Check 'minTimeBetweenSessions' param" + /// 11 - "Skipping event because 'isStopTracking' enabled" + /// 40 - Network error: Error description comes from Android + /// 41 - "No dev key" + /// 50 - "Status code failure" + actual response code from the server + /// + /// + public class AppsFlyerRequestEventArgs : EventArgs + { + public AppsFlyerRequestEventArgs(int code, string description) + { + statusCode = code; + errorDescription = description; + } + + public int statusCode { get; } + public string errorDescription { get; } + } + + /// + /// Event args for OnDeepLinkReceived. + /// Used to handle deep linking results. + /// + public class DeepLinkEventsArgs : EventArgs + { + + /// + /// DeepLink dictionary to get additional parameters + /// + public Dictionary deepLink; + + /// + /// DeepLink status: FOUND, NOT_FOUND, ERROR + /// + public DeepLinkStatus status { get; } + + /// + /// DeepLink error: TIMEOUT, NETWORK, HTTP_STATUS_CODE, UNEXPECTED + /// + public DeepLinkError error { get; } + + public string getMatchType() + { + return getDeepLinkParameter("match_type"); + } + + public string getDeepLinkValue() + { + return getDeepLinkParameter("deep_link_value"); + } + + public string getClickHttpReferrer() + { + return getDeepLinkParameter("click_http_referrer"); + } + + public string getMediaSource() + { + return getDeepLinkParameter("media_source"); + } + + public string getCampaign() + { + return getDeepLinkParameter("campaign"); + } + + public string getCampaignId() + { + return getDeepLinkParameter("campaign_id"); + } + + public string getAfSub1() + { + return getDeepLinkParameter("af_sub1"); + } + + public string getAfSub2() + { + return getDeepLinkParameter("af_sub2"); + } + + public string getAfSub3() + { + return getDeepLinkParameter("af_sub3"); + } + + public string getAfSub4() + { + return getDeepLinkParameter("af_sub4"); + } + + public string getAfSub5() + { + return getDeepLinkParameter("af_sub5"); + } + + public bool isDeferred() + { + if (deepLink != null && deepLink.ContainsKey("is_deferred")) + { + try + { + return (bool)deepLink["is_deferred"]; + } + catch (Exception e) + { + AppsFlyer.AFLog("DeepLinkEventsArgs.isDeferred", String.Format("{0} Exception caught.", e)); + } + } + return false; + } + + public Dictionary getDeepLinkDictionary() + { + return deepLink; + } + + public DeepLinkEventsArgs(string str) + { + try + { + Dictionary dictionary = AppsFlyer.CallbackStringToDictionary(str); + + string status = ""; + string error = ""; + + + if (dictionary.ContainsKey("status") && dictionary["status"] != null) + { + status = dictionary["status"].ToString(); + } + + if (dictionary.ContainsKey("error") && dictionary["error"] != null) + { + error = dictionary["error"].ToString(); + } + + if (dictionary.ContainsKey("deepLink") && dictionary["deepLink"] != null) + { + this.deepLink = AppsFlyer.CallbackStringToDictionary(dictionary["deepLink"].ToString()); + } + if (dictionary.ContainsKey("is_deferred")) + { + this.deepLink["is_deferred"] = dictionary["is_deferred"]; + } + + switch (status) + { + case "FOUND": + this.status = DeepLinkStatus.FOUND; + break; + case "NOT_FOUND": + this.status = DeepLinkStatus.NOT_FOUND; + break; + default: + this.status = DeepLinkStatus.ERROR; + break; + } + + switch (error) + { + case "TIMEOUT": + this.error = DeepLinkError.TIMEOUT; + break; + case "NETWORK": + this.error = DeepLinkError.NETWORK; + break; + case "HTTP_STATUS_CODE": + this.error = DeepLinkError.HTTP_STATUS_CODE; + break; + default: + this.error = DeepLinkError.UNEXPECTED; + break; + } + + } + catch (Exception e) + { + AppsFlyer.AFLog("DeepLinkEventsArgs.parseDeepLink", String.Format("{0} Exception caught.", e)); + } + } + + private string getDeepLinkParameter(string name) + { + if (deepLink != null && deepLink.ContainsKey(name) && deepLink[name] != null) + { + return deepLink[name].ToString(); + } + + return null; + } + + } + + public enum DeepLinkStatus { + FOUND, NOT_FOUND, ERROR + } + + public enum DeepLinkError { + TIMEOUT, NETWORK, HTTP_STATUS_CODE, UNEXPECTED + } +} diff --git a/Assets/AppsFlyer/AppsFlyerEventArgs.cs.meta b/Assets/AppsFlyer/AppsFlyerEventArgs.cs.meta new file mode 100644 index 0000000..056bce2 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a0fc241ad5a9b43a7b461a6147dbc74c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyerObject.prefab b/Assets/AppsFlyer/AppsFlyerObject.prefab new file mode 100644 index 0000000..f3bbb45 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerObject.prefab @@ -0,0 +1,49 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &7315102894599890749 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6207133488976360133} + - component: {fileID: 4405976200006927252} + m_Layer: 0 + m_Name: AppsFlyerObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6207133488976360133 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7315102894599890749} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &4405976200006927252 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7315102894599890749} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2a2ec6ba1ee8b48749524f015ed572a6, type: 3} + m_Name: + m_EditorClassIdentifier: + devKey: + appID: + isDebug: 0 + getConversionData: 0 diff --git a/Assets/AppsFlyer/AppsFlyerObject.prefab.meta b/Assets/AppsFlyer/AppsFlyerObject.prefab.meta new file mode 100644 index 0000000..1acd1cf --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerObject.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0bfe3b149145747cc92dc53bb4df4e9b +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyerObjectScript.cs b/Assets/AppsFlyer/AppsFlyerObjectScript.cs new file mode 100644 index 0000000..266a848 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerObjectScript.cs @@ -0,0 +1,70 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using AppsFlyerSDK; + +// This class is intended to be used the the AppsFlyerObject.prefab + +public class AppsFlyerObjectScript : MonoBehaviour , IAppsFlyerConversionData +{ + + // These fields are set from the editor so do not modify! + //******************************// + public string devKey; + public string appID; + public string UWPAppID; + public string macOSAppID; + public bool isDebug; + public bool getConversionData; + //******************************// + + + void Start() + { + // These fields are set from the editor so do not modify! + //******************************// + AppsFlyer.setIsDebug(isDebug); +#if UNITY_WSA_10_0 && !UNITY_EDITOR + AppsFlyer.initSDK(devKey, UWPAppID, getConversionData ? this : null); +#elif UNITY_STANDALONE_OSX && !UNITY_EDITOR + AppsFlyer.initSDK(devKey, macOSAppID, getConversionData ? this : null); +#else + AppsFlyer.initSDK(devKey, appID, getConversionData ? this : null); +#endif + //******************************/ + + AppsFlyer.startSDK(); + } + + + void Update() + { + + } + + // Mark AppsFlyer CallBacks + public void onConversionDataSuccess(string conversionData) + { + AppsFlyer.AFLog("didReceiveConversionData", conversionData); + Dictionary conversionDataDictionary = AppsFlyer.CallbackStringToDictionary(conversionData); + // add deferred deeplink logic here + } + + public void onConversionDataFail(string error) + { + AppsFlyer.AFLog("didReceiveConversionDataWithError", error); + } + + public void onAppOpenAttribution(string attributionData) + { + AppsFlyer.AFLog("onAppOpenAttribution", attributionData); + Dictionary attributionDataDictionary = AppsFlyer.CallbackStringToDictionary(attributionData); + // add direct deeplink logic here + } + + public void onAppOpenAttributionFailure(string error) + { + AppsFlyer.AFLog("onAppOpenAttributionFailure", error); + } + +} diff --git a/Assets/AppsFlyer/AppsFlyerObjectScript.cs.meta b/Assets/AppsFlyer/AppsFlyerObjectScript.cs.meta new file mode 100644 index 0000000..65ccedc --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerObjectScript.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a2ec6ba1ee8b48749524f015ed572a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyeriOS.cs b/Assets/AppsFlyer/AppsFlyeriOS.cs new file mode 100644 index 0000000..e117a8e --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyeriOS.cs @@ -0,0 +1,997 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using UnityEngine; +using System.Reflection; + + + +namespace AppsFlyerSDK +{ + +#if UNITY_IOS || UNITY_STANDALONE_OSX + + public class AppsFlyeriOS: IAppsFlyerIOSBridge + { + public bool isInit { get; set; } + + public AppsFlyeriOS() { } + + public AppsFlyeriOS(string devKey, string appID, MonoBehaviour gameObject) + { + setAppsFlyerDevKey(devKey); + setAppleAppID(appID); + if (gameObject != null) + { +#if UNITY_IOS + getConversionData(gameObject.name); +#elif UNITY_STANDALONE_OSX + getConversionData(gameObject.GetType().ToString()); +#endif + } + } + + + + /// + /// Start Session. + /// This will record a session and then record all background forground sessions during the lifecycle of the app. + /// +public void startSDK(bool shouldCallback, string CallBackObjectName) + { +#if UNITY_STANDALONE_OSX && !UNITY_EDITOR + _startSDK(shouldCallback, CallBackObjectName, getCallback); +#elif UNITY_IOS && !UNITY_EDITOR + _startSDK(shouldCallback, CallBackObjectName); +#endif + } + + /// + /// Send an In-App Event. + /// In-App Events provide insight on what is happening in your app. + /// + /// Name of event. + /// Contains dictionary of values for handling by backend. + public void sendEvent(string eventName, Dictionary eventValues) + { + sendEvent(eventName, eventValues, false, AppsFlyer.CallBackObjectName); + } + + public void sendEvent(string eventName, Dictionary eventValues, bool shouldCallback, string callBackObjectName) + { +#if !UNITY_EDITOR + _afSendEvent(eventName, AFMiniJSON.Json.Serialize(eventValues), shouldCallback, callBackObjectName); +#endif + } + + /// + /// Get the conversion data. + /// Allows the developer to access the user attribution data in real-time for every new install, directly from the SDK level. + /// By doing this you can serve users with personalized content or send them to specific activities within the app, + /// which can greatly enhance their engagement with your app. + /// + public void getConversionData(string objectName) + { +#if !UNITY_EDITOR + _getConversionData(objectName); +#endif + } + + /// + /// In case you use your own user ID in your app, you can set this property to that ID. + /// Enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and the other devices’ IDs. + /// + /// Customer ID for client. + public void setCustomerUserId(string customerUserID) + { +#if !UNITY_EDITOR + _setCustomerUserID(customerUserID); +#endif + } + + /// + /// In case you use custom data and you want to receive it in the raw reports. + /// see [Setting additional custom data] (https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS#setting-additional-custom-data) for more information. + /// + /// additional data Dictionary. + public void setAdditionalData(Dictionary customData) + { +#if !UNITY_EDITOR + _setAdditionalData(AFMiniJSON.Json.Serialize(customData)); +#endif + } + + /// + /// Use this method to set your AppsFlyer's dev key. + /// + /// AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard. + public void setAppsFlyerDevKey(string appsFlyerDevKey) + { +#if !UNITY_EDITOR + _setAppsFlyerDevKey(appsFlyerDevKey); +#endif + } + + /// + /// Use this method to set your app's Apple ID(taken from the app's page on iTunes Connect). + /// + /// your app's Apple ID. + public void setAppleAppID(string appleAppID) + { +#if !UNITY_EDITOR + _setAppleAppID(appleAppID); +#endif + } + + /// + /// Setting user local currency code for in-app purchases. + /// The currency code should be a 3 character ISO 4217 code. (default is USD). + /// You can set the currency code for all events by calling the following method. + /// + /// 3 character ISO 4217 code. + public void setCurrencyCode(string currencyCode) + { +#if !UNITY_EDITOR + _setCurrencyCode(currencyCode); +#endif + } + + /// + /// AppsFlyer SDK collect Apple's `advertisingIdentifier` if the `AdSupport.framework` included in the SDK. + /// You can disable this behavior by setting the following property to true. + /// + /// boolean to disableCollectAppleAdSupport + public void setDisableCollectAppleAdSupport(bool disableCollectAppleAdSupport) + { +#if !UNITY_EDITOR + _setDisableCollectAppleAdSupport(disableCollectAppleAdSupport); +#endif + } + + /// + /// Enables Debug logs for the AppsFlyer SDK. + /// Should only be set to true in development / debug. + /// The default value is false. + /// + /// shouldEnable boolean.. + public void setIsDebug(bool isDebug) + { +#if !UNITY_EDITOR + _setIsDebug(isDebug); +#endif + } + + /// + /// Set this flag to true, to collect the current device name(e.g. "My iPhone"). Default value is false. + /// + /// boolean shouldCollectDeviceName. + [System.Obsolete("This is deprecated")] + public void setShouldCollectDeviceName(bool shouldCollectDeviceName) + { +#if !UNITY_EDITOR + _setShouldCollectDeviceName(shouldCollectDeviceName); +#endif + } + + /// + /// Set the OneLink ID that should be used for User-Invites. + /// The link that is generated for the user invite will use this OneLink as the base link. + /// + /// OneLink ID obtained from the AppsFlyer Dashboard. + public void setAppInviteOneLinkID(string appInviteOneLinkID) + { +#if !UNITY_EDITOR + _setAppInviteOneLinkID(appInviteOneLinkID); +#endif + } + + /// + /// Set the deepLink timeout value that should be used for DDL. + /// + /// deepLink timeout in milliseconds. + public void setDeepLinkTimeout(long deepLinkTimeout) + { +#if !UNITY_EDITOR + _setDeepLinkTimeout(deepLinkTimeout); +#endif + } + + /// + /// Calling enableTCFDataCollection(true) will enable collecting and sending any TCF related data. + /// Calling enableTCFDataCollection(false) will disable the collection of TCF related data and from sending it. + /// + /// should start TCF Data collection boolean. + public void enableTCFDataCollection(bool shouldCollectTcfData) + { +#if !UNITY_EDITOR + _enableTCFDataCollection(shouldCollectTcfData); +#endif + } + + /// + /// Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage purposes within the application. + /// + /// instance of AppsFlyerConsent. + public void setConsentData(AppsFlyerConsent appsFlyerConsent) + { +#if !UNITY_EDITOR + _setConsentData(appsFlyerConsent.isUserSubjectToGDPR, appsFlyerConsent.hasConsentForDataUsage, appsFlyerConsent.hasConsentForAdsPersonalization); +#endif + } + + /// + /// Anonymize user Data. + /// Use this API during the SDK Initialization to explicitly anonymize a user's installs, events and sessions. + /// Default is false + /// + /// boolean shouldAnonymizeUser. + public void anonymizeUser(bool shouldAnonymizeUser) + { +#if !UNITY_EDITOR + _anonymizeUser(shouldAnonymizeUser); +#endif + } + + /// + /// Opt-out for Apple Search Ads attributions. + /// + /// boolean disableCollectIAd. + public void setDisableCollectIAd(bool disableCollectIAd) + { +#if !UNITY_EDITOR + _setDisableCollectIAd(disableCollectIAd); +#endif + } + + /// + /// In app purchase receipt validation Apple environment(production or sandbox). The default value is false. + /// + /// boolean useReceiptValidationSandbox. + public void setUseReceiptValidationSandbox(bool useReceiptValidationSandbox) + { +#if !UNITY_EDITOR + _setUseReceiptValidationSandbox(useReceiptValidationSandbox); +#endif + } + + /// + /// Set this flag to test uninstall on Apple environment(production or sandbox). The default value is false. + /// + /// boolean useUninstallSandbox. + public void setUseUninstallSandbox(bool useUninstallSandbox) + { +#if !UNITY_EDITOR + _setUseUninstallSandbox(useUninstallSandbox); +#endif + } + + /// + /// For advertisers who wrap OneLink within another Universal Link. + /// An advertiser will be able to deeplink from a OneLink wrapped within another Universal Link and also record this retargeting conversion. + /// + /// Array of urls. + public void setResolveDeepLinkURLs(params string[] resolveDeepLinkURLs) + { +#if !UNITY_EDITOR + _setResolveDeepLinkURLs(resolveDeepLinkURLs.Length,resolveDeepLinkURLs); +#endif + } + + /// + /// For advertisers who use vanity OneLinks. + /// + /// Array of domains. + public void setOneLinkCustomDomain(params string[] oneLinkCustomDomains) + { +#if !UNITY_EDITOR + _setOneLinkCustomDomains(oneLinkCustomDomains.Length, oneLinkCustomDomains); +#endif + } + + /// + /// Set the user emails and encrypt them. + /// cryptMethod Encryption method: + /// EmailCryptType.EmailCryptTypeMD5 + /// EmailCryptType.EmailCryptTypeSHA1 + /// EmailCryptType.EmailCryptTypeSHA256 + /// EmailCryptType.EmailCryptTypeNone + /// + /// type Hash algoritm. + /// length of userEmails array. + /// userEmails The list of strings that hold mails.} + + public void setUserEmails(EmailCryptType cryptType, params string[] userEmails) + { +#if !UNITY_EDITOR + _setUserEmails(cryptType, userEmails.Length, userEmails); +#endif + } + + /// + /// Set the user phone number. + /// + /// User phoneNumber. + public void setPhoneNumber(string phoneNumber){ +#if !UNITY_EDITOR + _setPhoneNumber(phoneNumber); +#endif + } + + /// + /// To send and validate in app purchases you can call this method from the processPurchase method - please use v2. + /// + /// The product identifier. + /// The product price. + /// The product currency. + /// The purchase transaction Id. + /// The additional param, which you want to receive it in the raw reports. + public void validateAndSendInAppPurchase(string productIdentifier, string price, string currency, string transactionId, Dictionary additionalParameters, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + _validateAndSendInAppPurchase(productIdentifier, price, currency, transactionId, AFMiniJSON.Json.Serialize(additionalParameters), gameObject ? gameObject.name : null); +#endif + } + + /// + /// V2 + /// To send and validate in app purchases you can call this method from the processPurchase method. + /// + /// The AFSDKPurchaseDetailsIOS instance. + /// The extra params, which you want to receive it in the raw reports. + public void validateAndSendInAppPurchase(AFSDKPurchaseDetailsIOS details, Dictionary extraEventValues, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + _validateAndSendInAppPurchaseV2(details.productId, details.price, details.currency, details.transactionId, AFMiniJSON.Json.Serialize(extraEventValues), gameObject ? gameObject.name : null); +#endif + } + + /// + /// To record location for geo-fencing. Does the same as code below. + /// + /// The location longitude. + /// The location latitude. + public void recordLocation(double longitude, double latitude) + { +#if !UNITY_EDITOR + _recordLocation(longitude, latitude); +#endif + } + + /// + /// Get AppsFlyer's unique device ID, which is created for every new install of an app. + /// + public string getAppsFlyerId() + { +#if !UNITY_EDITOR + return _getAppsFlyerId(); +#else + return ""; +#endif + } + + /// + /// Register uninstall - you should register for remote notification and provide AppsFlyer the push device token. + /// + /// deviceToken The `deviceToken` from `-application:didRegisterForRemoteNotificationsWithDeviceToken:`. + public void registerUninstall(byte[] deviceToken) + { +#if !UNITY_EDITOR + _registerUninstall(deviceToken); +#endif + } + + /// + /// Enable AppsFlyer to handle a push notification. + /// + /// pushPayload The `userInfo` from received remote notification. One of root keys should be @"af".. + public void handlePushNotification(Dictionary pushPayload) + { +#if !UNITY_EDITOR + _handlePushNotification(AFMiniJSON.Json.Serialize(pushPayload)); +#endif + } + + /// + /// Get SDK version. + /// + public string getSdkVersion() + { +#if !UNITY_EDITOR + return _getSDKVersion(); +#else + return ""; +#endif + } + + /// + /// This property accepts a string value representing the host name for all endpoints. + /// Can be used to Zero rate your application’s data usage.Contact your CSM for more information. + /// + /// Host Name. + /// Host prefix. + public void setHost(string hostPrefix, string host) + { +#if !UNITY_EDITOR + _setHost(host, hostPrefix); +#endif + } + + /// + /// This property is responsible for timeout between sessions in seconds. + /// Default value is 5 seconds. + /// + /// minimum time between 2 separate sessions in seconds. + public void setMinTimeBetweenSessions(int minTimeBetweenSessions) + { +#if !UNITY_EDITOR + _setMinTimeBetweenSessions(minTimeBetweenSessions); +#endif + } + + /// + /// Once this API is invoked, our SDK no longer communicates with our servers and stops functioning. + /// In some extreme cases you might want to shut down all SDK activity due to legal and privacy compliance. + /// This can be achieved with the stopSDK API. + /// + /// boolean isSDKStopped. + public void stopSDK(bool isSDKStopped) + { +#if !UNITY_EDITOR + _stopSDK(isSDKStopped); +#endif + } + + // + /// Was the stopSDK(boolean) API set to true. + /// + /// boolean isSDKStopped. + public bool isSDKStopped() + { +#if !UNITY_EDITOR + return _isSDKStopped(); +#else + return false; +#endif + } + + /// + /// In case you want to track deep linking manually call handleOpenUrl. + /// The continueUserActivity and onOpenURL are implemented in the AppsFlyerAppController.mm class, so + /// only use this method if the other methods do not cover your apps deeplinking needs. + /// + /// The URL to be passed to your AppDelegate. + /// The sourceApplication to be passed to your AppDelegate. + /// The annotation to be passed to your app delegate. + public void handleOpenUrl(string url, string sourceApplication, string annotation) + { +#if !UNITY_EDITOR + _handleOpenUrl(url, sourceApplication, annotation); +#endif + } + + /// + /// Used by advertisers to exclude all networks/integrated partners from getting data. + /// + public void setSharingFilterForAllPartners() + { +#if !UNITY_EDITOR + _setSharingFilterForAllPartners(); +#endif + } + + /// + /// Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data. + /// + /// partners to exclude from getting data + public void setSharingFilter(params string[] partners) + { +#if !UNITY_EDITOR + _setSharingFilter(partners.Length, partners); +#endif + } + + + /// + /// Lets you configure how which partners should the SDK exclude from data-sharing. + /// partners to exclude from getting data + public static void setSharingFilterForPartners(params string[] partners) + { +#if !UNITY_EDITOR + _setSharingFilterForPartners(partners.Length, partners); +#endif + } + + /// + /// To record an impression use the following API call. + /// Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard. + /// + /// promoted App ID. + /// cross promotion campaign. + /// parameters Dictionary. + public void recordCrossPromoteImpression(string appID, string campaign, Dictionary parameters) + { +#if !UNITY_EDITOR + _recordCrossPromoteImpression(appID, campaign, AFMiniJSON.Json.Serialize(parameters)); +#endif + } + + /// + /// Use the following API to attribute the click and launch the app store's app page. + /// + /// promoted App ID + /// cross promotion campaign + /// additional user params + public void attributeAndOpenStore(string appID, string campaign, Dictionary parameters, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + _attributeAndOpenStore(appID, campaign, AFMiniJSON.Json.Serialize(parameters), gameObject ? gameObject.name : null); +#endif + } + + /// + /// The LinkGenerator class builds the invite URL according to various setter methods which allow passing on additional information on the click. + /// See - https://support.appsflyer.com/hc/en-us/articles/115004480866-User-invite-attribution- + /// + /// parameters Dictionary. + public void generateUserInviteLink(Dictionary parameters, MonoBehaviour gameObject) + { +#if !UNITY_EDITOR + _generateUserInviteLink(AFMiniJSON.Json.Serialize(parameters), gameObject ? gameObject.name : null); +#endif + } + + /// + /// It is recommended to generate an in-app event after the invite is sent to record the invites from the senders' perspective. + /// This enables you to find the users that tend most to invite friends, and the media sources that get you these users. + /// + /// channel string. + /// parameters Dictionary.. + public void recordInvite(string channel, Dictionary parameters) + { +#if !UNITY_EDITOR + _recordInvite(channel, AFMiniJSON.Json.Serialize(parameters)); +#endif + } + + /// + /// Waits for request user authorization to access app-related data + /// + /// time to wait until session starts + public void waitForATTUserAuthorizationWithTimeoutInterval(int timeoutInterval) + { +#if !UNITY_EDITOR + _waitForATTUserAuthorizationWithTimeoutInterval(timeoutInterval); +#endif + } + + /// + /// + /// bool should diable + public void disableSKAdNetwork(bool isDisabled) + { +#if !UNITY_EDITOR + _disableSKAdNetwork(isDisabled); +#endif + } + + /// + /// Use this method if you’re integrating your app with push providers + /// that don’t use the default push notification JSON schema the SDK expects. + /// See docs for more info. + /// + /// array of nested json path + public void addPushNotificationDeepLinkPath(params string[] paths) + { +#if !UNITY_EDITOR + _addPushNotificationDeepLinkPath(paths.Length, paths); +#endif + } + + /// + /// subscribe to unified deep link callbacks + /// + public void subscribeForDeepLink(string objectName){ +#if !UNITY_EDITOR + _subscribeForDeepLink(objectName); +#endif + } + + /// + /// Set the language of the device. + /// + public void setCurrentDeviceLanguage(string language){ +#if !UNITY_EDITOR + _setCurrentDeviceLanguage(language); +#endif + } + + /// + /// Allows sending custom data for partner integration purposes. + /// + public void setPartnerData(string partnerId, Dictionary partnerInfo){ +#if !UNITY_EDITOR + _setPartnerData(partnerId, AFMiniJSON.Json.Serialize(partnerInfo)); +#endif + } + + /// + /// Use to disable app vendor identifier (IDFV) collection, 'true' to disable. + /// + public void disableIDFVCollection(bool isDisabled){ +#if !UNITY_EDITOR + _disableIDFVCollection(isDisabled); +#endif + } + + delegate void unityCallBack(string message); + + [AOT.MonoPInvokeCallback(typeof(unityCallBack))] + public static void getCallback(string gameObjectName, string callbackName, string message) + { + GameObject go = GameObject.Find("AppsFlyerObject"); + var afscript = go.GetComponent("AppsFlyerObjectScript") as AppsFlyerObjectScript; + Type type = typeof(AppsFlyerObjectScript); + MethodInfo info = type.GetMethod(callbackName); + info.Invoke(afscript, new[] { message }); + + } + + + /* + * AppsFlyer ios method mapping + */ + + +#if UNITY_IOS + [DllImport("__Internal")] + private static extern void _startSDK(bool shouldCallback, string objectName); +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] + private static extern void _startSDK(bool shouldCallback, string objectName, Action getCallback); + +#endif + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _getConversionData(string objectName); + + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setCustomerUserID(string customerUserID); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setAdditionalData(string customData); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setAppsFlyerDevKey(string appsFlyerDevKey); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setAppleAppID(string appleAppID); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setCurrencyCode(string currencyCode); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setDisableCollectAppleAdSupport(bool disableCollectAppleAdSupport); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setIsDebug(bool isDebug); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setShouldCollectDeviceName(bool shouldCollectDeviceName); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setAppInviteOneLinkID(string appInviteOneLinkID); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setDeepLinkTimeout(long deepLinkTimeout); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _anonymizeUser(bool shouldAnonymizeUser); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _enableTCFDataCollection(bool shouldCollectTcfData); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setConsentData(bool isUserSubjectToGDPR, bool hasConsentForDataUsage, bool hasConsentForAdsPersonalization); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setDisableCollectIAd(bool disableCollectIAd); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setUseReceiptValidationSandbox(bool useReceiptValidationSandbox); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setUseUninstallSandbox(bool useUninstallSandbox); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setResolveDeepLinkURLs(int length, params string[] resolveDeepLinkURLs); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setOneLinkCustomDomains(int length, params string[] oneLinkCustomDomains); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setUserEmails(EmailCryptType cryptType, int length, params string[] userEmails); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setPhoneNumber(string phoneNumber); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _afSendEvent(string eventName, string eventValues, bool shouldCallback, string objectName); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _validateAndSendInAppPurchase(string productIdentifier, string price, string currency, string transactionId, string additionalParameters, string objectName); + + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _validateAndSendInAppPurchaseV2(string product, string price, string currency, string transactionId, string extraEventValues, string objectName); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _recordLocation(double longitude, double latitude); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern string _getAppsFlyerId(); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _registerUninstall(byte[] deviceToken); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _handlePushNotification(string pushPayload); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern string _getSDKVersion(); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setHost(string host, string hostPrefix); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setMinTimeBetweenSessions(int minTimeBetweenSessions); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _stopSDK(bool isStopSDK); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern bool _isSDKStopped(); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _handleOpenUrl(string url, string sourceApplication, string annotation); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setSharingFilterForAllPartners(); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setSharingFilter(int length, params string[] partners); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setSharingFilterForPartners(int length, params string[] partners); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _recordCrossPromoteImpression(string appID, string campaign, string parameters); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _attributeAndOpenStore(string appID, string campaign, string parameters, string gameObject); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _generateUserInviteLink(string parameters, string gameObject); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _recordInvite(string channel, string parameters); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _waitForATTUserAuthorizationWithTimeoutInterval(int timeoutInterval); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _disableSKAdNetwork(bool isDisabled); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _addPushNotificationDeepLinkPath(int length, params string[] paths); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _subscribeForDeepLink(string objectName); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setCurrentDeviceLanguage(string language); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setPartnerData(string partnerId, string partnerInfo); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _disableIDFVCollection(bool isDisabled); + + } + +#endif + + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AppsFlyeriOS.cs.meta b/Assets/AppsFlyer/AppsFlyeriOS.cs.meta new file mode 100644 index 0000000..36b719f --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyeriOS.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b34371b3cc09641ebb007ffc4e9500f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Editor.meta b/Assets/AppsFlyer/Editor.meta new file mode 100644 index 0000000..a768212 --- /dev/null +++ b/Assets/AppsFlyer/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9f84c02aa78da4ac9b444d98d97f7cc4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef b/Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef new file mode 100644 index 0000000..a63b527 --- /dev/null +++ b/Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef @@ -0,0 +1,17 @@ +{ + "name": "AppsFlyer.Editor", + "references": [ + "AppsFlyer" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef.meta b/Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef.meta new file mode 100644 index 0000000..f61dfd3 --- /dev/null +++ b/Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d008146f00dea44d38752b4289e5f65b +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml b/Assets/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml new file mode 100644 index 0000000..4a7f376 --- /dev/null +++ b/Assets/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assets/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml.meta b/Assets/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml.meta new file mode 100644 index 0000000..b48efbb --- /dev/null +++ b/Assets/AppsFlyer/Editor/AppsFlyerAdRevenueDependencies.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6110ce30bf7674268814dc9e0395f8b0 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml b/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml new file mode 100644 index 0000000..458e853 --- /dev/null +++ b/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml.meta b/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml.meta new file mode 100644 index 0000000..1e4d57e --- /dev/null +++ b/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a03558dbbfeac45db9afe9e9c2df5a85 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs b/Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs new file mode 100644 index 0000000..f18e3fa --- /dev/null +++ b/Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs @@ -0,0 +1,84 @@ +using UnityEditor; +using UnityEngine; + + +[CustomEditor(typeof(AppsFlyerObjectScript))] +[CanEditMultipleObjects] +public class AppsFlyerObjectEditor : Editor +{ + + SerializedProperty devKey; + SerializedProperty appID; + SerializedProperty UWPAppID; + SerializedProperty macOSAppID; + SerializedProperty isDebug; + SerializedProperty getConversionData; + + + void OnEnable() + { + devKey = serializedObject.FindProperty("devKey"); + appID = serializedObject.FindProperty("appID"); + UWPAppID = serializedObject.FindProperty("UWPAppID"); + macOSAppID = serializedObject.FindProperty("macOSAppID"); + isDebug = serializedObject.FindProperty("isDebug"); + getConversionData = serializedObject.FindProperty("getConversionData"); + } + + + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + GUILayout.Box((Texture)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(AssetDatabase.FindAssets("appsflyer_logo")[0]), typeof(Texture)), new GUILayoutOption[] { GUILayout.Width(600) }); + + EditorGUILayout.Separator(); + EditorGUILayout.HelpBox("Set your devKey and appID to init the AppsFlyer SDK and start tracking. You must modify these fields and provide:\ndevKey - Your application devKey provided by AppsFlyer.\nappId - For iOS only. Your iTunes Application ID.\nUWP app id - For UWP only. Your application app id \nMac OS app id - For MacOS app only.", MessageType.Info); + + EditorGUILayout.PropertyField(devKey); + EditorGUILayout.PropertyField(appID); + EditorGUILayout.PropertyField(UWPAppID); + EditorGUILayout.PropertyField(macOSAppID); + EditorGUILayout.Separator(); + EditorGUILayout.HelpBox("Enable get conversion data to allow your app to recive deeplinking callbacks", MessageType.None); + EditorGUILayout.PropertyField(getConversionData); + EditorGUILayout.Separator(); + EditorGUILayout.HelpBox("Debugging should be restricted to development phase only.\n Do not distribute the app to app stores with debugging enabled", MessageType.Warning); + EditorGUILayout.PropertyField(isDebug); + EditorGUILayout.Separator(); + + EditorGUILayout.HelpBox("For more information on setting up AppsFlyer check out our relevant docs.", MessageType.None); + + + if (GUILayout.Button("AppsFlyer Unity Docs", new GUILayoutOption[] { GUILayout.Width(200) })) + { + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/213766183-Unity-SDK-integration-for-developers"); + } + + if (GUILayout.Button("AppsFlyer Android Docs", new GUILayoutOption[] { GUILayout.Width(200) })) + { + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/207032126-Android-SDK-integration-for-developers"); + } + + if (GUILayout.Button("AppsFlyer iOS Docs", new GUILayoutOption[] { GUILayout.Width(200) })) + { + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS"); + } + + if (GUILayout.Button("AppsFlyer Deeplinking Docs", new GUILayoutOption[] { GUILayout.Width(200) })) + { + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/208874366-OneLink-deep-linking-guide#Setups"); + } + + if (GUILayout.Button("AppsFlyer Windows Docs", new GUILayoutOption[] { GUILayout.Width(200) })) + { + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/207032026-Windows-and-Xbox-SDK-integration-for-developers"); + } + + + serializedObject.ApplyModifiedProperties(); + } + + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs.meta b/Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs.meta new file mode 100644 index 0000000..53d8abb --- /dev/null +++ b/Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d248a134cf494486fb1d6a2e95a05d87 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Editor/appsflyer_logo.png b/Assets/AppsFlyer/Editor/appsflyer_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..01c2b8cae0fa888c39bc06375382cb4d0f99ab12 GIT binary patch literal 9426 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 Zqz@UJ#ov8pVgr-_sVHd3m&v{h{U4`cTj~G+ literal 0 HcmV?d00001 diff --git a/Assets/AppsFlyer/Editor/appsflyer_logo.png.meta b/Assets/AppsFlyer/Editor/appsflyer_logo.png.meta new file mode 100644 index 0000000..90005e8 --- /dev/null +++ b/Assets/AppsFlyer/Editor/appsflyer_logo.png.meta @@ -0,0 +1,92 @@ +fileFormatVersion: 2 +guid: bc7fa5a6b64b944a4b2900fd877acb8b +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs b/Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs new file mode 100644 index 0000000..b4c8188 --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AppsFlyerSDK +{ + + public interface IAppsFlyerAndroidBridge : IAppsFlyerNativeBridge + { + void updateServerUninstallToken(string token); + void setImeiData(string imei); + void setAndroidIdData(string androidId); + void waitForCustomerUserId(bool wait); + void setCustomerIdAndStartSDK(string id); + string getOutOfStore(); + void setOutOfStore(string sourceName); + void setCollectAndroidID(bool isCollect); + void setCollectIMEI(bool isCollect); + void setIsUpdate(bool isUpdate); + void setPreinstallAttribution(string mediaSource, string campaign, string siteId); + bool isPreInstalledApp(); + string getAttributionId(); + void handlePushNotifications(); + void validateAndSendInAppPurchase(string publicKey, string signature, string purchaseData, string price, string currency, Dictionary additionalParameters, MonoBehaviour gameObject); + void validateAndSendInAppPurchase(AFPurchaseDetailsAndroid details, Dictionary additionalParameters, MonoBehaviour gameObject); + void setCollectOaid(bool isCollect); + void setDisableAdvertisingIdentifiers(bool disable); + void setDisableNetworkData(bool disable); + + } +} \ No newline at end of file diff --git a/Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs.meta b/Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs.meta new file mode 100644 index 0000000..8157bc6 --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cdf9d1bc41a8244b3bc2d249fb6cd7aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/IAppsFlyerConversionData.cs b/Assets/AppsFlyer/IAppsFlyerConversionData.cs new file mode 100644 index 0000000..454eaa6 --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerConversionData.cs @@ -0,0 +1,31 @@ +namespace AppsFlyerSDK +{ + public interface IAppsFlyerConversionData + { + /// + /// `conversionData` contains information about install. Organic/non-organic, etc. + /// https://support.appsflyer.com/hc/en-us/articles/360000726098-Conversion-Data-Scenarios#Introduction + /// + /// JSON string of the returned conversion data. + void onConversionDataSuccess(string conversionData); + + /// + /// Any errors that occurred during the conversion request. + /// + /// A string describing the error. + void onConversionDataFail(string error); + + /// + /// `attributionData` contains information about OneLink, deeplink. + /// https://support.appsflyer.com/hc/en-us/articles/208874366-OneLink-Deep-Linking-Guide#Intro + /// + /// JSON string of the returned deeplink data. + void onAppOpenAttribution(string attributionData); + + /// + /// Any errors that occurred during the attribution request. + /// + /// A string describing the error. + void onAppOpenAttributionFailure(string error); + } +} \ No newline at end of file diff --git a/Assets/AppsFlyer/IAppsFlyerConversionData.cs.meta b/Assets/AppsFlyer/IAppsFlyerConversionData.cs.meta new file mode 100644 index 0000000..3133eaa --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerConversionData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2f1d4dadb7cb44628f25f1ffd8fc104 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/IAppsFlyerIOSBridge.cs b/Assets/AppsFlyer/IAppsFlyerIOSBridge.cs new file mode 100644 index 0000000..86211fb --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerIOSBridge.cs @@ -0,0 +1,26 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + + +namespace AppsFlyerSDK +{ + + public interface IAppsFlyerIOSBridge : IAppsFlyerNativeBridge + { + void setDisableCollectAppleAdSupport(bool disable); + void setShouldCollectDeviceName(bool shouldCollectDeviceName); + void setDisableCollectIAd(bool disableCollectIAd); + void setUseReceiptValidationSandbox(bool useReceiptValidationSandbox); + void setUseUninstallSandbox(bool useUninstallSandbox); + void validateAndSendInAppPurchase(string productIdentifier, string price, string currency, string transactionId, Dictionary additionalParameters, MonoBehaviour gameObject); + void validateAndSendInAppPurchase(AFSDKPurchaseDetailsIOS details, Dictionary extraEventValues, MonoBehaviour gameObject); + void registerUninstall(byte[] deviceToken); + void handleOpenUrl(string url, string sourceApplication, string annotation); + void waitForATTUserAuthorizationWithTimeoutInterval(int timeoutInterval); + void setCurrentDeviceLanguage(string language); + void disableSKAdNetwork(bool isDisabled); + void disableIDFVCollection(bool isDisabled); + + } +} \ No newline at end of file diff --git a/Assets/AppsFlyer/IAppsFlyerIOSBridge.cs.meta b/Assets/AppsFlyer/IAppsFlyerIOSBridge.cs.meta new file mode 100644 index 0000000..8e200ea --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerIOSBridge.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6847fb337898040288c165e3667101a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs b/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs new file mode 100644 index 0000000..fb1a9cf --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs @@ -0,0 +1,74 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AppsFlyerSDK +{ + + public interface IAppsFlyerNativeBridge + { + bool isInit { get; set; } + + void startSDK(bool onRequestResponse, string CallBackObjectName); + + void sendEvent(string eventName, Dictionary eventValues, bool onInAppResponse, string CallBackObjectName); + + void stopSDK(bool isSDKStopped); + + bool isSDKStopped(); + + string getSdkVersion(); + + void setCustomerUserId(string id); + + void setAppInviteOneLinkID(string oneLinkId); + + void setAdditionalData(Dictionary customData); + + void setDeepLinkTimeout(long deepLinkTimeout); + + void setResolveDeepLinkURLs(params string[] urls); + + void setOneLinkCustomDomain(params string[] domains); + + void setCurrencyCode(string currencyCode); + + void recordLocation(double latitude, double longitude); + + void anonymizeUser(bool shouldAnonymizeUser); + + string getAppsFlyerId(); + + void enableTCFDataCollection(bool shouldCollectTcfData); + + void setConsentData(AppsFlyerConsent appsFlyerConsent); + + void setMinTimeBetweenSessions(int seconds); + + void setHost(string hostPrefixName, string hostName); + + void setPhoneNumber(string phoneNumber); + + void setSharingFilterForAllPartners(); + + void setSharingFilter(params string[] partners); + + void getConversionData(string objectName); + + void attributeAndOpenStore(string appID, string campaign, Dictionary userParams, MonoBehaviour gameObject); + + void recordCrossPromoteImpression(string appID, string campaign, Dictionary parameters); + + void generateUserInviteLink(Dictionary parameters, MonoBehaviour gameObject); + + void addPushNotificationDeepLinkPath(params string[] paths); + + void setUserEmails(EmailCryptType cryptType, params string[] userEmails); + + void subscribeForDeepLink(string objectName); + + void setIsDebug(bool shouldEnable); + + void setPartnerData(string partnerId, Dictionary partnerInfo); + } +} diff --git a/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs.meta b/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs.meta new file mode 100644 index 0000000..dd43257 --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 409b8302434664a3785ce55d075e7f58 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/IAppsFlyerUserInvite.cs b/Assets/AppsFlyer/IAppsFlyerUserInvite.cs new file mode 100644 index 0000000..aac109e --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerUserInvite.cs @@ -0,0 +1,26 @@ +namespace AppsFlyerSDK +{ + public interface IAppsFlyerUserInvite + { + /// + /// The success callback for generating OneLink URLs. + /// + /// A string of the newly created url. + void onInviteLinkGenerated(string link); + + /// + /// The error callback for generating OneLink URLs + /// + /// A string describing the error. + void onInviteLinkGeneratedFailure(string error); + + /// + /// (ios only) iOS allows you to utilize the StoreKit component to open + /// the App Store while remaining in the context of your app. + /// More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions + /// + /// openStore callback Contains promoted `clickURL` + void onOpenStoreLinkGenerated(string link); + + } +} \ No newline at end of file diff --git a/Assets/AppsFlyer/IAppsFlyerUserInvite.cs.meta b/Assets/AppsFlyer/IAppsFlyerUserInvite.cs.meta new file mode 100644 index 0000000..8530528 --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerUserInvite.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5a4cdfa023cb8497b94bb39720052fef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs b/Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs new file mode 100644 index 0000000..a5c02cf --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs @@ -0,0 +1,19 @@ +namespace AppsFlyerSDK +{ + public interface IAppsFlyerValidateAndLog + { + /// + /// The success callback for validateAndSendInAppPurchase API. + /// For Android : the callback will return JSON string. + /// For iOS : the callback will return a JSON string from apples verifyReceipt API. + /// + /// + void onValidateAndLogComplete(string result); + + /// + /// The error callback for validateAndSendInAppPurchase API. + /// + /// A string describing the error. + void onValidateAndLogFailure(string error); + } +} \ No newline at end of file diff --git a/Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs.meta b/Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs.meta new file mode 100644 index 0000000..459cc85 --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a5adb7eab3284dd39a76ec56c06457c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs b/Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs new file mode 100644 index 0000000..90490e2 --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs @@ -0,0 +1,19 @@ +namespace AppsFlyerSDK +{ + public interface IAppsFlyerValidateReceipt + { + /// + /// The success callback for validateAndSendInAppPurchase API. + /// For Android : the callback will return "Validate success". + /// For iOS : the callback will return a JSON string from apples verifyReceipt API. + /// + /// + void didFinishValidateReceipt(string result); + + /// + /// The error callback for validateAndSendInAppPurchase API. + /// + /// A string describing the error. + void didFinishValidateReceiptWithError(string error); + } +} \ No newline at end of file diff --git a/Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs.meta b/Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs.meta new file mode 100644 index 0000000..38efa67 --- /dev/null +++ b/Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6385b1d184efa400a98515735e1f17bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Mac.meta b/Assets/AppsFlyer/Mac.meta new file mode 100644 index 0000000..fd182bd --- /dev/null +++ b/Assets/AppsFlyer/Mac.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 96a328019e42349aabc478b546b8605e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle.meta b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle.meta new file mode 100644 index 0000000..a7aa6da --- /dev/null +++ b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 682114f7790724ab3b9410e89bbc076c +folderAsset: yes +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents.meta b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents.meta new file mode 100644 index 0000000..4b06604 --- /dev/null +++ b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 28175da64865f4e398b3b9ddfbe97b24 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/Info.plist b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/Info.plist new file mode 100644 index 0000000..3303ccd --- /dev/null +++ b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/Info.plist @@ -0,0 +1,48 @@ + + + + + BuildMachineOSBuild + 20G417 + CFBundleDevelopmentRegion + en + CFBundleExecutable + AppsFlyerBundle + CFBundleIdentifier + com.appsflyer.support.two.AppsFlyerBundle + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + AppsFlyerBundle + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 13A1030d + DTPlatformName + macosx + DTPlatformVersion + 12.0 + DTSDKBuild + 21A344 + DTSDKName + macosx12.0 + DTXcode + 1310 + DTXcodeBuild + 13A1030d + LSMinimumSystemVersion + 11.6 + NSHumanReadableCopyright + + + diff --git a/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/Info.plist.meta b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/Info.plist.meta new file mode 100644 index 0000000..dac263e --- /dev/null +++ b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/Info.plist.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 58a86b0b376564c06bf8ce29e1dbfb04 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS.meta b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS.meta new file mode 100644 index 0000000..b55a757 --- /dev/null +++ b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 218a2e7ff5a4c461981bc41f7d7bfeba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS/AppsFlyerBundle b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS/AppsFlyerBundle new file mode 100644 index 0000000000000000000000000000000000000000..3376a474b6e3a7d2b3c481728ba41215a89be2ca GIT binary patch literal 1132768 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∓F|H;Sl(6yaudL-0s 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≶*?i zMOh!kn8`1XoOXyPpF?YqxQi`G*La-89i$Rq_7{>eyGAc86Q{@ zQp0+L^dG$@74gubMJ4@L{LyPlJvC;1d#^{b7gd=154ZF@lS!~Blv7Y13YBCB$^%P6 z%!ngJcH|oiMS1f|%ZnDV zJ{0Fw1eS(^c?(wL&0dP{G9Y=5DNNNPhC5gkoXT`&WuF`g9Ec$av z23E*ozW_c~ab~(zQYA~OIQ7g@ajjqx6ScG?P_AaGUbrjLSZ49jinIb*DATMeryy%? z?z9Pd>C^dx2+J&8QdS)5HFZ%Svx*tLBvdZ*Zu%6ZQ${dYq#7(1Luyi4S;e&C6->a; zQZtB4sH9*;CS6cbBW|7MASgQ^ol96 zdMm7FVrFTvfee1LY14%%!}h#S;R zvx-X>OHvPvwsNLf}}d+zipmIO5sJ9$MV zVu(hIDhnm2(raLk?y6$Wlo|7wIS3RJWtCP`s^wk)E9$}`-Q`(DCAmdQLX$(4%b0LE zp$e%$C)AMSRF;;N$--V#VW4y_v%IuIGC)~vr!OgE8IU?@1%V}H0U}3QnRC`Iz;acU zEOwH5N$m_WMzR6qm52JRBe{aUO7}}bEHEKG;&aQ3)jVJXF4Y&v2l_XquFy*pIwamP zl|dr6StfI!d_`HMUhBA+T}XO)xteXN_p+FvGU=1fE;2|&NWoD^GHbQg^jz+@g3T=s zp_dWXIg^XV`tCFAS&$tN-@_C(A-ZRQs3U-xy)y~vRe?o%2CF$>A{O<@f~qP=-SyPM z)24(L5?9#^OVH#;j72$E42g^Gg}DzEH2`_-mX@usO4S~Z?${w)7FzOr zHH34t&CBft05_A7&9tYq{9*I-gkqa8eF;NLOjK3G8H$;qJ>D@Hhqj4|V=~?x)WK3h z*OJnuA+wBWl{Hu*{N3tLcyG>1$r*AYb_6zk@)G_OrRp!3LE1Y$xJe}KK9UI zCd*5+@)i~c7Fl^qm^*aB%99ys}_vV|Of`S^L7vClSA=yp|gi6IQh z{!%U|QTj#8DGbX0gB)vmag%6*WilC$Vf< zaiAc?D3=pDm^IT&^p$0}nrThqdeM?9)|=9DHS?B+ic8Cuuux5|Dk=^_QakTZIdirs zXwhbYFo)9kPh4Vpuj^Q|Plepc*r5-NC14R}1bWAw*WX`Pi1o$rm+Ni29>YnqbMk^k z6=i|Sfk{z#hKidl&&Ln`)U?h3G5JOEeQpS0y(8D&>^OQ zPIRWrjL^^uEF>VEqlQ-Fl4`*ZS($ z_qsBh*0=8^Ew;D*eR-5+?f&$=*kj)xyC5C!drf!roFAc|`y=%8euSR-BXkUjr>gkY zGnBTAn$;yxzNkuqDbt@2HA}BCX|m#^6;)(Ztl+qyytJgWitD(mmB+G|SzJT~BB@>& z?LVE%WOQ-sB~hA43pj)p4HGo}S?nucj`SLmMJ*fKzQrnTUO|3fn8`_0iSWEMn73 z?5>s;n5;NdF?*q@z09$o4-I_syJlH4o)&E$8JL1CLpwPqvOct+4pGIe5PseDtdteVp}W*X-qTtY17`}-mDk1i+ zK8H$jTq{v)_Ch7a>}w{kko}z`q|(V~wq(aVSz7}Y1)&nXd#S+JLcxsk^1zC@a@=EY zeM{vmPlvPVq_svF(>GjG28_5RYrFR3A5BpdOP;Jwawfwhl`)YzZ2RodK0J z*7R9Zg#eU+RFlt3YA!g zNyqt&zSpS}x1gGpGA1RVWwzn^(GO!!wi{IIuH2uj2%QtqonRlwH>$DEPacQ({UHEl7ojn$@dA^X^#{Y<64$5l>_SO;EYs{FM!%S!FvbpEW z8Bs8;B2dhX6*rXuviZ!>gF3vBCC8@Qd?Hnyz!NYu*1=TfvY9S~Gn4C!;LIb>Ol=33 z&?9Zw**Yhsc#-U29rdBn8Fe_I>WR$k(jqwkV*{wcJe7cR1ZN+R+K2w4AxXP1leJiR zW(R5I5w4m2YWDTqAyCX}^tIh3%E)HOuGDj+;Ha$FrJ~K;t7RSYSvP~~UZ#3hpscEV zQHV6FLhc}9M0Pe>T$^94PnGqVf zbiBaens5_C&f`^SPfUGRBRcnG-0TnywZACHK?{?K`wX(cN7oB=EZ{hY zWnRg#qS|KKYAT72#YddMQAK&aggkC~7M5~uC*x#mbCkGOq+>f><8Ul9K>ko{EfnvN zqzd^mp$xPgLuseh7S(8fSGDdW^dgCop{qYKdC8en_GFHlZJ#u2SRZPhl4tYep_(Kj z6|x-3{frDwY?kSiRh@O^u$x*CJ!b6jK1Vpn&Fy!bv`+RBLuF-gnnRB5rqRQZ{)U=+ zHnSY31$YjLriv`eYL081Md&kF5+ZfxT`u={Y#cp{?IFq0YtJ9{v8%O!6IKk-bDAOf znIcXxXR%hEqZ4x289mF$vo&C+VvaI;jv7RnoZWQZ6~!P#P(6 zk4nAbqdrw~>ebI>Thsn7*}C_0%{Hg><|vmP{W}Vm>hV#o_t>Bx9@{GYT$0qZ$4>oR zm#V!j7v0y`iAU5a`|GCD0nE{Y<6zicJ4*Cz9~1X16Zh~qosdY}Gx2Mlz73a_&XxT>^JkWZ!8r@6d7{43f=*$+`$`dd1bt41ek;3gkX4 ze@xZv>JCwbj@vvq#+l31p$9+Nj&Xs7ay}PHSik>Vrm($izWf~8?s>7JHQu9o!Q!jOAaY{(i zWtGt3{Jjijv8Unrl-VVds}`~#>ph?jm!uflF5Ii`rxV0T64nZHCv$4gVGHUhiCUR} zJrG!>s<@c(AfqiUus80;#uaL|hHR7bxPc_^Vm;^Zain9<47;96@)tN%?{Q4s6X`bt zVY448fK8M1Tgl0b4s>3>J!W-RkJ}n=Quq4$Wt1tAF^!u;+N$=mz)X%S)xO9+Gm#0Y z8C6Grl)F!>Y_2RF;pIeLHd;~5i2)_SKzUG}f#8%rz=9O@81^6XFjkp;frlsbqgOoy zYe~@}LbiPz#K8#<`0@0YB>c)*OH0iWn#56aRlA8?7B+iQsgRj5CntxA#^afC_s>43 zVPyNgkaomEF8#b*_Ithb7S}kUFIL~q2-mbDIw;Ss^%j;cm*pEH=T%hq%fi2ba`Hjfez@o6 zGLwB_MQ}0ER_-wrEnFcCI?a=Tu^VJlOisgNbCXxt(-w9aK3RoBCXVzxT1T7bq*+UX z=d0$=J^um~c=eb^A8P6KtdS*WW2EH&kG;2n&+4l3h4(p0fTonvN-M3@9#Wuzl21Yi z6iPw@g_e&%0;K}Y*OQP)NJ2jNXsgl@9jw(-Z9Aw{Q9H`(a1}eP(|S>H>{J|UMWYh@H2+NqYY?|-em_BrP{c@~dzfA{^}`+IMqbU$bR_ugmkwbx#I?X}n5hqiR7 z4jJ}8hS+torheJYc;${3+PP_>Y1cYW+I5sfL9HTRw1!*B%nsS$EIEz6BIGgc(8n8mG&Km(RdSQbJ8g7El_71ZW-c=J1)O-YckBSz56P z#10VHnziDQiof7|4R0$uMUZbwFZpG$#ikv8i`eg@sn*bB0hNzL0PK`7!;qXogp)XE z7!!jCL`oBF+{Ct0u%aDYB@U@*k~Mepel!dsDQjN^zt|Z9I|SRvg3a|NFT_l%R-s2N zVDuvv=j7QQ7QNP+!0ygK#C%AF^<7%pZvltG^O%ZsJ1k_kBcYZi0n_Am zH~Yocg6VCA>`-mxaUD4U6GyWo?W9IHw_V6-!OA$at_O;8IE1V;4mW%- zK#3z5URFnAEQ6)GD@|%asKCxdazHFvL>!!<8nj0Uc-;fB+0NEMYCgGW@?Ia2h8cv; z-bm&;SCw#r;JToiB4n80H9aXinJnu;hql{Y6^vr`-L)$Sd5Frh?g3pYFH*lZZ0YK& zt6Pp)3Az3Lz)YxxUib6gIQ(Xm9Pq zTmy-OvtTs5u@;~cTJx;wF<#&fbVf~2PcPVV;x=^X-3x~IY9)@|9`Ii*C4I!+d<58-0S4ysW1z_bgI z+K+u?nu()X5K95t%_QCvze=}bO*0}UJG_F%NcaMpFAM!?bkV!SOe} zfk=&iG9c!~EYFdEz)a88#Dr_K-d47(e6f}vNj*yK69J?1>` zcB)8?v_}}Ak7e{?A4Zn8v@L%}q-YT+-PmOJP^bzS#xlE@aMhTvd30rT>1V22+2x4a zL#sa8uZ#)4Na1j<7oo&+n?OQrGIxs*#qKTd`ar-tHII6Nwu}uEt3LDwT-FoKB|OuB zYk3q#1a#A1%rC=vUGPzYC0+eaII(cXqLz+G@Nc^%1!V-{OjH<98Ee~cx*$3VC*#!^ za@OA|tYOG%BmxscEmk8LB+&ZlxaP3aA%>=5WBqQ3XXNKPF;s5F4hmcVt-mbl3`bWI z!1b^ZqI0&|93l-NjXQAs2>$R};BQJR3-B!{4R;7qj{2gL0yGDaxTeieFgCekkYu)U z+zgXQve38ZVkj>&4-ICk=3?IjejBJ`c&L|2ObKl>tO(~>K&(Kq7-vSP<4r>6b1zdM z^0Zh^;p4{k7=&3@zcQLEMZ>^6%h7NSr}I;>j&vfU$=PE6zdF1?GdomycUXsN%&rC* z&g~Etc`%0T1nwfc>=NL(J~C4 zu7O){kf61ncH!wAG&SPD6Rk~C7HMxGS5vWKLoBl{78}YSFfVL7XuR1W;}$ATr41)4 zxaSOapdt3DrEN9Lcg#9#Y1@PTBYjWR9=7%l7kF5wG|>7kN_7i1#^cL#tW{|BIehKG zYB6IZZHD?-CmZY?YU^~zFWUJu?%HLI6iM0~lOj6L5YfXr(qX{ie4jl7qj>vaMk#Ng zA?;WfA~za;G%)AI1PC>gR5hBKwztDsWPnZ%r|jV|cwvH49T@GH9Jjy%geetRpLH%m zxl1xbvel`gIHZ7cRg17z>%`e1oXQ8kMyeT&N?J{4JQwE{7{p7|mb6XZrY6|ENph{C zV=j)y=ypo&Rsu9vXJS-$;6yYvw_i^d2T|Fa5(m3hKP|3_XWQ8kNX7+e%CX^KpmSnj zAnf6CQ+ES#ZQZye& z*ntPZtV6#Uz*?B*ftV*a&5|fp^AWRpsAkNQ^#Icc zY|K7XWWbTNmYtMosTD@?sXJboVu@$znqjzHc)O02a<_j%3XJpu`9HGbV=W{u89C|h z0<5SpmS9NgqCrb9CfoO*HCoKGhAJ}s*@aE=;2r$(+zOm29Jhh2g;|DGd?#1IKWwg( zK{vpmWd=J8u?ECho_>%X{YRhNaC*X%F}$vTdTm{DF+14e97D2!5F(ZAgyDXX zebu5}p%jl#FLrxp2Q#Iu2QPL+O0Vizap5_=!Z0OCx?hidc}C^T$|^e3msVsX z!l)sx1oy%S<$;m*YL|vyE~v|XfeH*SCu+hxOm>(Nade&Z1LwkqF>Q}=#^RDjE|LJ* z6Jd2i(*jJ#nBoV?YaFZ``HYFlIx3606%KF>?jD!$B}o8kbhr!VNPdw;11pm@xBM@ zsr!kE=1yt^60r#g96+UjcTwA}8rVc}Lb`1W-T}*dbj~@!N{tst6XU51B(o&%Lf>OQ zmiD4)XPasg@gExkwssB915M=`2dh=VQx>*x-d<(1f!lfK>KLIm^X;C5HZ6V)I2BcS(8iN7nAW8 zm{@+OF~gR@G{uoowFW{3s?QML*%B8*7f@|k4YZmI?-J9=CFdMY+B8Te&Qw-V;GQa3 zI$=347IeA4DiM##gzyZSJjrcdyvRjYEo^#;D%{xX6kb#Y6|^kD(_3Fmw90OOT2FB$ z?X?0_d&-G&>6QU#9mveTpcSz^T8mW`rf1&OZ|&-aMKqe*z`@vIr{Y{)SRLc}gBEmg z$#0eQsQxh%0n`U3E1CH1B?_X)VR0nWUUa7hYcF(5Svc+0VfNq%h?;OG!Fj$?-7*>J zxoxi2GI4U;($EHvkyj&Ij?~0u?g7c{mLJ7Bkrvjbp`DDGq^q-1?p_g#h8i8aLCq;q z(N<(Xb#*@#4vEYga<|#2d1lEX&>OOzOx> z)%?6NzB&N)+{P!pXqkK9)qvwLLLBQc!$rH%1VvBtOmW-Jo$&sEqBjIP3+%NJiKe@& z6}{U>`WrhG*dvVL`T{3j(LbOjT(*RfVs*9$V&T{Uw=KoI*Ob0@;|hs!Bl%gWW+DQI zail9Gv1x?5MkZ6yww#5bDP61L#|s#FOjD*VqvnEjXeS!faPq3D6RylefVi;{u5K9@ znN5kEEqNv(f`g=q{W-p&$X?Gwr%W-W4kqs4flHm-Hewy-P(pI}qoOjnxyr=%;c$;@ zxjZ0f;ol?+#q^baQ`~$iZ%teiVwe)p(r`%)+?6xi_Ti_J*;W(QPDBYx3*`t7Lxkp8 z)<&BmxdNlVJ+c@U5EB&WmgIg_*gh7dXl_PP(zGRAaG0h{0s@Eiqgz)(mswfc)5-pD zlr}{JG4hup6NFvZ#GI?FQ+2HE?4Lu5y|_81QvxVEX@vx_slrF+Ty=r5fg-H`mPq1Z zm2nj2n%E^At1&o$o<2d@s)oy5NtCb(C6ys~e$iMW{)_h-@|$bSy6{F}$6bnFQ%9;oK}UjB-gX8eTHwn_O;`p#fG{kZ_QNvv|s- z3p1=ZhG|Q-+izA>rpD`LS~knb)UlUbNJL7qjDiyFWUh=24`GJ15#y5C5#v&%o5q6>s>e&?gHCRvS z!4ntn)XMZy?BTP_QeSA2VM5OEmb4inq^4CDC%Xjt|iF;b>iR6{KK;;+7vs0vJIRKA(Y?w-H>m=up^SB5z|J~ zu+*%4ugH*tfiO9?a>=F|Kj_zpxM3oLc-{7RR1}$btj85>yWrh$$6rn~phc{H+C!pr(9E6^HBIiQ zCI1S~iHh4cxMhHMC~PH2D!Nm!TpsFYYa->MS9wlYQ|q=WT=MXR-0@CE+RR}UGGnny z(G4i<3F3-nD>yk{u(cF>L&FXm4zOL^9jUK}jT*FBELXYFqCS}kJ0fuW$9=K{!oq`J zkxK~kijCx-pa}U8ZDpTleiK=0DAwL9MfX(kOIlmWY%1PPU{UIIdx;eY*&g2yu%4l0 z@1W(e>_k%;wJq>?fMo&oW3S~^9ejkF4ePE!yg5Uh=$2a`O?Uttb|<+#0o>ARIeC`PPVDHlQoi<^3g(lhJ;hThe6FcEI%w8YiwnYP6pO_VmJe6OO3t;SZ%D&W(nA3W(WR3%BkXR>0UT&>`61(bF*O zumb?xGnSw>mib)!A}%H@x|UBi#L&i;1d}-qfdXQW*-(MB`NtfAJv6qKV;F}H#<0p+ zrV99z@nh|D#@+6U(k*+jO#2{jhdNta3lyB6=cJfhVu*P3a>~8+pGgu z;eH!zW@CKO8u#Yt4qQ3@9Cyedxyv#V4dqhZ)p*QK;mVpX2eUihJHTf)Wpw`ry@w_~ z%H-sNJ2@fFa&i6wRl}|1GLG;cIU~qX}SM2d+-1H4$$hQTutWqfzE= zGN86(*f7P^fP0O^*MZWKaKoxXJXY8*Vr^{OiyC5m?c&p|>(7Sp&IR+B*q=>eVq z>@&%}aL%L=N!K-y!ki`)N$L;KnHLs~p$3M+A{p7$vt6#mrmn-##~l}8N*;7kTF_KZ zfnqk@4mUjV7qSk>w#!V@-~~1T)yDIjCga@DwAN4iZdk{|sxjP@>fE+WO-erfU>R;r zdxxo^YnkCP)IvnVMbgdyow1+@&EROjs2?& zs6srty+VXN(24j;cU`__&57|~YaGeuFe+KM3{AG1#ZX{)1Jw>BbUFWk$RL2VQ1B1` z-rPGFpr7oCVe9<^E({g~Q}LN6oF4Brk|KWks1S3|beo1y66A6|p^khY25`qs4IM{l zkJ8{B;v8Y;p}1d;O$Acgna6e#K5l?3=nV#l^UE^Z%PXoEmeR^2W-_XZRw8AUu_Ta% z;wD|dN$^~N1hJdX(&h(XTy|KCbhOHBmjo*tsHFIFyfU#0ur7diASuP< z8FnkVTvt9Up8P2?UQ3=aQoJwB+LgDiTy@(@vt-rUm33zEnl-D|n3bysOLuo!1zP3Ml{t?Z>=WJ-%?m(rh^JGXdlP{@l@+F~Z%A&a#gBnL+yG$aa-=n+5L{W&+J%MC)arTe|AtrXIHF5xlAUmhw;J>W zcD<(FnJU7tY-?*Pn_DrvtZY_Ud3#lBORA%^G*#I?XI5)jW!vo1N=i_E;RIU-wl-}q zGpW`&v&!eTw|7*`nLVq$w7jFdqq3}}eRf4z6@FKi&Z?ZmF?o z8e8N(U2EO7*E3^5hzo1^q8oSRt(>K38pOOpcl7q*GhYaBQ8X8VxVJ#it@!1tPOX`n~W z2@?a(a?wEy9CxN~LQyInmH5O8zW~ozuVI?SHFGuw8QnEusiwAWZgmH4P?pBJf{<+c zU{huQvG~LSPS*_55;82#m4?r}kcbBwE3CI0)#sMMN0Nzxm~N&?Yj+E7Zx+;U6;ZL> zeN6-XZS)HPT7@rOL36+(l#m|Vn>+dk-Ajky2;R|z4PnX&hsyYBfo?g5!LuyBcS~_N zhMtUqX3^i(Yo!^0DLBx*g?SQdBEGthP`XTcYrAxb ztEmjW*n84ra1DqxT7na|f(xbh$Sea}%OE<{&RRARwm13*nJv?L1CtRLLv+FR{)qNz zQCo+k$GTD-+rw6F=l0w4RDBqiJdSD87O&Z5qT$NARS* zZ2%OpvA8A@i-uSM((L zeg}h{?E!L;D_HNAZjR zE7QT2oo2(-yZUepwX5wN)tiFox0ykIW&>@lZVHxTRo9*h(iX7uFr^LU;~*8xhgd{H z=fP1017qtzIsQT7(G3*EfWzNu05XLDvWCA=QuG@m!4*UWW76E&mv+;E`?wJZ2*p19 zG)-)Y>Y9)}Wxh*FcV`52RWeM~Xk~Q>tn3Yl9*px;9wM~v8wjvEC=P5bNwx3DH=zqF z%~3F6$VyYlni&nIc7^5gx;aSowhs`CS$UHR2780%%z2xkV|3wo7$yn&-dr)+E-(ai-N9db}9 zDFqt@h9l(TIhY{_%F7UoIZ`}qhnIvqPq7RbXoqq_$~dT5{Ptt}-Q(RmemP}a)kVO-qLR&T|-za==Xu2txT3pdlZ1v`1T>V^ASJPNS zpDE$S;)f1GE(;Uoc1E}*r2VF+TgeFBuww?Kc zOXV$FBIhC{K&Y4?YQBhuA zSuq<+v#N^Hin_{Kv&$+gXIE6#%$`%Zcy`U4vRM^#DrU`@GpD?4PEGmjidp3~21*~! zY?GyqMzh&I+gd3?x0v|wayp=q+e zWOHu`wCxgHYlM$H@~YR0C2yLo3I-= zSc1tX^eRyva4~jSc@=+Ct{1&=Lp0;ZkpK#3^2k7YxiAux@00oO6rijSg2uF<~FmDl5clsVFCur}F znnsnh`iSiq>Lv0erVbmx*vD1k^pi{plHis_b=;BZy_o8j4%}WwJ>NTEdmoYRK6)yK zR$5(~({m1NX>lyXqmA;j#=j6#181VKo?1ZMG|kzMG8TbVLd5-4Of(paK#ZaGOeMlq zgzoaA7s;+7>{f6Xuu)wt_`GrWDDVCgZp|VPv@a zr%9P&T}|v7n_@6uh+JVjovd~)0Z=3U$Uuk4YuKW&zCs*s7&~l!8b*Kq}}Ne8nE_g6GdynEZ8ig+wXydDjL%!gVlQ zo_FpFt-@H2uK?G;IG9|s%VuVZ7VbDt%^zftRr}QH!l~8MgAG$@oeOQf#?9IR7rx1C zs9&>c{q36qx=IczHaXCc)i%I%wH4Z{=-79rO!#qy|H9kxHe6K5#!DEr?X@zFH*h;B zqyrrjryEtm2UH)kCWetPf|=S4Hv#;IBJJp>(F@%Ldo-a$X-oA$T-Y1%BMrwTbn_*p zBHcw#Nz%ZSY%eP@B`y(E^d&cM3a|>cV3EP_J_b#-dzb=9`^GEnDv_ zLMvN}S~`kw4{Il_rrh>=%w2-k26WjI+AmZ7yqKzt&U4nUTDiat{u9)vE}C36T!vUQ zyCq3{EZSYmPFWD`Y)oMZHrlyNxN<2(YIKG8azyD7?UtFeqwN4h$M=_F(XLnQoB?s` z8q!31cKq4eC#@AR9^XTE8pR`Uf9K|QXF-K=o~C+;V$?xAL$Kyt4lRr6M(?+SE4Gbi zJv!_jA}>s67jdDPhN4J7-3lGAd1`fYfIUz6`lX5kTu?RC*T-LWl969*CeOIOaQcn& zs;4cuVam*sg;THFu*tL$LmO})3=_Bv2eg985q&oR5soY5G1Vj%=e#q7jX&IzfJJ=~ zmReifYATEkAlh*aCRYgzX*Xo*>dawfKo5)eW)^5H}oU{>puZFA6ZMffa zGwcBN9Gv}3Y1823;nn2^+tUj9I1S6&^PqRMw6iyY;!9o-D}0^~Hccna*l`X74kK9p z4~ty`+SrL@7(}iZvW4uf`-@7;co}i{uC&ATYx(>((LTzamH9$BQX!r1cuK>hqZEv;i;e=1P>FZ)i6^NGE%@)7FQORnPM}wn)JKvRoGNFGlH;G z5^0d5)@%YTIiQ&yj7g^Cgxz_Fn6#@WfZpOhxQm5hcsuOmUHF^iPCC)%NGfQ7k(~^3=nUEg;A@&f z(H3vKFv!+SGYWE12InVZ`GgB8 zd#au9e-1GDV#Gj;BKlph3Nr%wUqq6K+ac?5yEc)qrLQk=Hd@%qdnh>?D(jX1+F0oA z=bMrzC6p6Z-e{m%tv{g6QvSF+@pZyxERx(QQ>;maO~4OKiG3!F$an%R zMDc?KF*})ru~vrjjrle8^$kmw-@bTFQ{A$LnnlYOH!WXvb3;^ojr$yIF?1-}h{v46 zhEecRc;R1?tx0#nW|0&9%p{^MqP=!b1RwJXHz4)b%&DZA8y$-dVZ|04Cbvsda)?cc zhE$@+Fo~TJi-XXH+1UxN2HMT2gE)!~sS@Yn{a`#AHzLSL>6cp;uw_IxE$mTSGlHQD zAFzY#KImt#doHF%{33M$f!x@IwKyp*_AXN+PwVXB!96y>rj1!=YH2xGJUmd;3^B^D zEe@8E(n8|_7rY11xUCfgqm>krke+qCWM(($XnAB4VH!`-mJI2qn<2>43be(nY2OT^ zI0jExK1to6kkkcR2t7}aUbm)wnXQMLk!zP&=Rnsw_grT;U76Qh943Q)cM+sj-3;gs zn}8u5(vAjOukIGw8glDpgLC&?ZP3Ee``w^A{D)(^)yq<5_-%eEC~JwDf?3053g#~m z&P`q711el8Ppqy&;PemLMX*D6fYYU}v~0jd=;YRnO3pQPNZ^^kG5@+o61QF#lPO+{wK}{0!YiW} zlXMfJV8?73}njwQqeD@bVIdxu$s zT?^rN5;RBG95*v=HOpq_m_qew2F-%r4wkwFQ>zPz%^+=I;tw!w^w`a%fVTRA>!(&< z4?iroc*A}ZEDS}9OUpK4pTwT(rvcrJ?V4uVuc7S~o`I|dgtxlV=i4w_FTUjB3>nm; z;^sClCbXgi;JubKH8+ANFK&f0`Y)?H^26FCjI!6P8k4ZmR#Q5R1E zOsPDI znvq+M!LJ;JX`01=-RZI|w3&G43A~0KC$7IvPTKyQw~1-#_JhMw01Hw&?V;8~3Y)G0 z-iC}spC1}Rm=~auc)d+o2R(u1^c8@SdfbcdFun-ym>DSfA zP6aq##xgLZRcK9gGg!DW5>7YpB67|E^{W~h`8bwYwsOg;$P@`}lMjjnbQgBmsmxI~ za$M|m21&=rLwWdl{VKAGgxy0AG$m3iL{!+p5oa+w2M)9~xi6~H?9s}`VqY-CA3*{ zHcfim04P#hq8@@nbm)zbiGsfOHaJ8JH&SsheE4E&?D-HOXt?nuD||YHcIetu%$vk( z!Y(vHgf=LmnKNg}^c~SZsgUAG1@l^XW@$h~J@2yyx7Dm!xoqXl^8&XcU^ld7=>eas zS<#wffOLDBngYx{w4iDUXfEoeg%vj1EnBV(%u>lL?Gh(=@-LThM zs~w7JvFZaaGjTcU_O@6b@^w_{SDF&(yTEOz8@9r0uxjtJcb6a;2{NV(`-k%eDyb*X zhiUVab!InKncWBJ8{j+ODj6Lnu%eIEqcpLYS!K2|1j|F~>;@Hrj(F42T6TSBD^tC= z;J|uIUsgcx^37sFGuEmpTn7~~4l5GPEUrjvp)U(!UCJ&Y)Co}iGM7uYyHf?gXjren z@CfJ zEv4ntH+_S)M=(nJTi`1U*EGBZoJTvr6-aVn?*Sr^Y%Ce_rJGTb#WI2DWn!=YbImLHxPBJj zWdP0i!ty3)d}gMZT3%}ziKUUjy=ImtkPNS&?@so>(oUu$%>TTf#9WFkytHSo6nB3z zWnc%rO)h(SEJ3Jv;aYSmk1sH0M=RfgLcLDoA1*r_2Y)>`JuaNTy?P;OJQ0r-+*E}v zsqpe~ES>1`zad(eW0MAg700R}Sn-yaIBhXY$jcw925-T_n1o+&?ZOzgJA9-IuXSGe zv{Wx4Z!4-5$*XV`LGl6X6V`ZxHq1T)PPdB`^_srERiGs8RLU#lgo`McpaoWlSc#$9 z{kz;LiVZ7j8sVU~28uYk!_8gIvQ|&ABB4}}y*fF88R^9t5a z+*3Wo25s(!u)X+$a_PH0?-nJdf0IZrW5iIB(?{$vhI%0YEjp>bQEE`!mQ}M6IR%klG#|d6?WCr*FJ6x zYU|eq_BR~3gR=6bvZgXPF>PrNR!KR?at&%NAX{#@ zCMphH6rC@iJI7$xpBhC2X8FSzqL<5N&7>7y>ADVRL*+ggSO z+TAid%IH-1@V(dsOYOq95FtcZy%{h#l0&X7G>gNp#jTiQKf}Ca?!zAPaRYjVXleJ#6a4Fb-^fias{ z=AMBT`$J#;T9vP?avK)BZrPN+y^0f_0BQBiCph6`=++*QS54G$%du#1gI@09fbIvW zh|QBo_&9BxIA|uDT!m^pug<&dwLrkA{Ti_TRSjfu)n@fmQNUA{Pa%@SOV$R zlfW9Qlw91%Sib~?cH4kV)alke47$OkIE`e#+=d^}=CGNBm0mN=UzljE_K)>kINLY# zUPd$Yl#Qtw3o(t7`vqfV^NaQp#E$ulSjb>!{ z`L*u^S!FApEgooBhx1@6GIwm)nA*6bY13V0Gb?7lV@k|YBpp_@x~%e!MHn8?+RO&H zJ4J>-q7ZgFIF4?WCW*txyIJy)TCkjy9One>k|KT3(hZATYF9uKnK$R`G}DgV6Tn4@ z7ljV&NQDh@d*EaEo94kc!PcgMY)k=4$~VqlhU2-0*L>)Il1x2#HHIZ*F$+&?j|rbh zZN#cpisRKgD?IsBdD7h>s?hx6*&PGzZTW^BN$jgJlg8;1isEMEBvDP)k$kL_VfQ47 zN!vs$6^BXjd7<9l66)wA0PqxF9^}LAtfsCARj~dnn3<*EuqMz_sLGhUVXaHM^qrTM z=x9Uo*yR(`Y7nXmbfCcQYN5JJcIfWgx1tmV6L?jV4}wIMdNauoTLS4tPqz0 zleC;Ym>JXRdF~=z$L{{oL1md6c+G%C0+Adq2A{I0*D`E7@-ZA50nOGGkyJ}u-~*Nn z1tp0E9EOJ7a{yv5_Boj_h25(kex43C`eA4AnltU*Hj8r~-j3USpla9(;syB5aEd1n z2tz>9ZPuh6lX9@#!Y~339>_P=MFP^qdL}l@H+L4=2Y) z_=z|LC~z{@PFLc@$6G+nz1=AY5ikI4D8cEGj+kNUjmPndJ6t@IwJq#Na%n&tsrt@& z!ZcVvWU~Ug&DNobRxP@vwyAb` zO+!P|l%|@7$f)E#gO;A4(X~G_TqmAyX_;vJ$q^ir0P0(Ik=NI1J_?$|teFenI^hAD zp0%bXwvLVNe=#L?@l=Ar(2wuumW0>m48VgNhwsEZ%K% z5xER4ZV-jOBQOm@S2;2u4DV~9oAa^Z0anAZgz6-o=+2HvXEMm7h|?M5X9~0M+J+|B z?U$`LyYN@EVntCZ)wFc!)~y2rZ;M3*OP9{ux^*7b^lKYyWAWEFUhk0Nh6cDlWazyb z*CX!QV5^$THTqzbI=~yT#-R z+rF~|JE_pyTI?1FUH(RFYX|h2UNT7Vb{<7y+_B1rn=j_#AK8B}nZXXh3aHyRi_Q#2 z2L+j&VzH4q3G*zQe~O?@;&^-djdVy8ZK>L`a>aDI9s9}i-+9A3vE*u4ys|F9P$UP( zAV`a~%5!Fn={76}dVE+M=IUW_tKhl;ziqq^vmt1WfA)X;KsC$$KP0&+pV|UPc$gkB ziJB5{qBBYil+^A@b+u66B;s*tLfe-9ma?7<*pikl?X~bsgFQ9_x~y$irdZfLps?X? z9qe>vz*p>S9BOUP0IY#8Cu*DlX;{<{bF)s=A73s5b1mv^=}+0LZgAW6e8W&HSP2V= z5*g7J#@Box1)yn=2dSLl48=m$oa@juG#=E&l_@1KXm6(%;0$;PWCYGcWr%De@~5Yj zV{op%Q7cOt$)^TB;qj6OutnFI9yPeNuY}8`v-ZP;n_GoJ9q1XrQID;~u#)U5Zf)%y zbTv87GpiMPgt@Di-mFm5qd#e{Jb30o&w_DSl(){+XEBd8hcQFj&EVocY3ttm_D(1z%a zs*(s}dm^@laTWkQ$BSPl*wSr@aLIRfP4HQx?d6yp7TP0Pu)lXh@j*s8kk=fhZH6y# zL+z^i#dS?hIO*DF28Vh~7kr}IOdm!d7Cm;^pKc?j%cbmgdbl)l&$!}=mr9GUl`i*F zq2jP0kcw*>Yu3Oap=nhE{=feJq{EmrlMJwrXxtcHX!STaD^3qYlZLeK*^G!y;tv6X zTd4N(f|`^dniDt`O-Pt5O6YbZ1I{jT_f=CL71fhzH1S2zVm8Xs?d4>*chem$BHd)y zoFNkHYqFMeAKO`vFKmX|+8+BVDNc%Pjwz{_WD>6YYkRiz^zMKo5M3M!_vNzUS&;O+ zvYU#H9Z|^G=>`ja+iUjH|{_`lDFSx&?EK8jf>TB%OHGAXuFyG z)a;UIV2F*d)~As57HM>n6dBtR5y!yKWeIEq(fX3PRrWtyqTO9~wI()U9QW6=KXwy7 zSl}3VRsTBhLrc$~i&$s39BT%b!{u=hR?o<>i@e;5+l)(D9xPZ8)Gx1TT(WA-il!Ac zwb+-NHZ3TKt>OA)U$X!gK5xfjy2XA-FTF^!rFKaTE(nEVMQ=Y{v2JRY(9pN%Z>jct zDgMgd+TOlhz#y6-c?Wkb$MheiVPTO8TmnhHe#LUZtx^(YtF;kf;n8M3ybaiphd1IU z?eJpRTf4-j&ln?RA<-I)Y}}kPObdqmYA5+ahtowv7J7@m-EYu3^6ZglGc{Gr|Bqxe zq%kBo*#>c`E!N+7cI!XqCXCosyzn+rHn>ycSPo|7*ft>+C1I9O$UD3Ha0EMKe9%F@ z$`>9cUSZD;n>X1QxSf#i4>*)P^2ou)0=2|IxIsG1xG21u(p+XEd5MkcQ&&SunHZ(DD-t%;-l68LxZ z;_L6+peS)#^qN|*F1eA>MhMz!48 zapSwxtTjZXlFlu=f~dkJE)}^xpjIu$n`NWmjbcxsnu5!1j6LFGCK%M5$U)X09KB6z z9-735g9J-U7!qw^yf(NXjtaAdhe;A7jIjhGaT|MjAE5$Hmx){d{=7sHi0z3duu zc8#svnp$T7F}W@#rpuelCPXdbB^L~hvQ&bl(te&#^100ck`g8tl(q4sL5MY;9O{X# zQIRnv6^n#)UdWh{2pWB`&b$0FBUENvn`2k|X7?15o)*WY^LR`AI;;Tj(_r;$LkrEL zOO~-v285s0SQ=F0{7Lu($j~~Oa!O$+$o-_u>u6m>Fm@n0yn`+^qA#>8zy(L~jMW9M zURaIrK>APcFR0g?To3U>6A=;O|0E0Bg)|@ zkg;I*da6n^%@(B7X;@As8)8?$8MHvH5S7WI8pSb{hLsbgK+7&jCK3a9(}fe+mt{*8 zYbKHkH*;5{bz618vX!L4_Y7uzFCFdfr&M4ry`j8RkXv<$XrZs7?Sq?Q{FRYVVUI>s zqbwJqZQ_*|N?dy@PdaWg;5J7+i-kn!enBj~2%OJNU4(}_7Rr#6(Lm4P$UswK1WyNS ze<6-q6iXGomn=H*JmI|Q^bR|lQySNiWtA9-5KBBT??|yskZ~^~9ij)g69HB%tcF++ zI87pfWGrqV1W+u7nAu+G8os)`w0}l|pLs(F-qpM(`09TV1EGlU4 zDWG~tzJm6h1*w8m7yi?}odL^@1zQISY76MV1_JnYwS`V#bR}j1isO4qk!=~SbK@%_ zmf!?W!5s_VVN$l*OlDkZXPZWCLE}IYTw3Rtwybgn^;N;JZY^M1S^fx9qt=mrhAxlB zL5$d$5+N6@(J_?eLk6{-*j>aW!R_HV+(v~V9Tp+%2#+@MfQ)(|?bW7wjumOd`U_pt zwpCOunq9dF46+b6#8+3kxgp;6>V>l-UX_pcL<(c1?c5{{jQ9nsdaP{WgUwcgn`nee zrA1|>kG~YSdd(NCpnBm=R7ZXue$>u-OAn8~32lnF1RaNm7!OvI#@d>}=Q@#`9&Kmd z1j4x9x8Ja14W1es%EQ=uqKw;6qbMi$l~5>@iwSZNEtw?J54MAmiMk`%HYo(`nP@2P zxNz;0G*O*yLRZqIjd7KLID8>k+Q8f8|g4z*lF#orD=vyJ=O>3MNw$c_zef|~(S)b4Pl2-!x& z!Zxw}WE-4ww;*a^tXAj?vyD@Qs}6QLusMYI{24HDoV0vr7bsD}pY@OeC8vS<)lvDaO{Bl3>Od{)TXNOe0(Z9sozWm(0NHi7RYBIK2e_q;ajH!OhhSm7~@6b(EZ5 zi?ZA}2^&UqkfLaEZeK8kh8#8q`_FW1}7~;C*z;+ zvf~Bt%N^YPmX*QqZU&237izKOf`G#qt-1s97}FU_Pa6QN9?Pg>14~4~OeP;DW5z)m zH8@<$4Ab`UY6zRym>_a7lY_KzIu*ENcYvWu!l3r$cVJ3%eBMRs1ZI3Nx=62hO75x* z8l1fngW7-;mQAu)uVQSYr3_72NQ-Lmz<2To%?jl;u@CDB=u-`s#OWzG6AF$B10E}l z`#Az34Dff9{^Q}_IQoIV-Fu2_Ops$A=)V(Rsm6c*o_^vFu2}YO_cIMO{Hyx@YIF4} zi8Yv&`R~BoH(nsTxhMYwr)&T2cWcaL7hh~lTR4vUuWA$&yOR%u0F>+9iaUP4^KAcFv2MXAP~Z12u~u+onp*cgv+NHGi7y-NnLNu za)hSPm`;R`Al!qnZn`o15k8ObFv8RfV~!y-HyCr8o)Mlycno3gnjAB8Cg_0h7{XF| zE;6PX;XZ`*2+tvGM!3G%m_CFPOV9>{XAmAlcnCy)8sX_OW6mHvISU=tkYnmAP#(gW zvr$ikM-Vn6T#v558=;wldLn!t;Sq#YRmMDv@DYS35$4WCc?gdq9N&m^^NguNSUn#d zfN=dnG<_|~uLk`PK8>&$;e$0OA7SYtl#lQ}ga;8WuSGo(POL+@2#+sDdFyga^Acm0 zB0P69@*#Y5sWJNyj#*~R0fgNM4O%a{id9^K%X*AO1q=$Q$(qn?{RvmfE4$2=3fEyrwJ z=9_&8CwAAQ{7L!a@XO?)dq!1*nd>|=suV>%>YGtZbIhpaxh8i{uE~FPl*vCm z+Kk#g#*CVDks0&!MP^iEz8Q5I|8`$&#+=5#rDM&QLt~Ne5`_3Sew-OIh<_)>nNj;M zHIuu?n^7|_Gow8Fd2xcE1_rPBdel#J@>bnK65= zGNbCRM%-IWe&HnJ9i3$IPh4yA4+Uma-DERrLV+1|xWJ4Vdz~5eEdK4EV)E;!nNg>v znf$>*GiJ(kGiERTotbV%9hzarG~QrFoxQ<$FU>TgI*UyH%wohBoBX~KbM2v7#+z7S z{KqSdw|=(qgE_|QoMZgLDwB79p7GD!h_Nx>crzEEPZt>PL4*eunA}tNU3U}4$4zL< zO(r*3X#7X2jkmGJb(mpe?Mf{{l!*^lx+W-dB?z~n6bjPZ_r#`qf_#rS>H|GI@vo7HxbS-2a5}cRvC7fbg{^jCc0SsMD9t=(?wjX@1IhN1ie{Pycsd zM=-{Zn7rq|X>#iR!HllL*j@fD^uf1G?(uIKfB7+!_vm*(%V$B$XHDMD?-{@PxEX!? z`^G={17lwL0qFZ9I~goJPA&qwfF1 z`1k$7#(6#_tkI8;_q;=wdpQqI@cgqAyqu@6@ciIPFX!Bqo?riF&!pb$jomvD^6Dzj zyZb87KXsLtcl0fuIsO*U8#BqvEuG|@3flP~rKHRCwNLgx#~f+=H_{zqHab&6S>a5aH2EFQ;mb zXX@v8ImZy5Lb$%lGksMk1L4^!FL&Zx&#a&8d3)!2Is4{$xnpkhyz2ShrNIJk+_7pe z=j0;KTVLy$?pkkjYKiBaS^~L^aO_fV+{Ah>=V-m>Kfc<_JKNxSsYcHXHhMYTYdvq~ zIxi+-xQZ}%|%kZ+5ZcW|qBdEGY8 z+q2CZJ!Sy&z<_sA)m@%ff46tZq<5hn@AAyPcX>Gnc6;W?ZqKW_#~Xd_Jy0~>>*Y<{ z3%c#~F6z6_%e(sl{Qi)4_0ms!dFD|scmAW$RQ}q#sQwF{Kjn*_ss5tp?L@fui{9w- zhdnd)OP)Uy^UnOoK)1)dvB&-vba>qJCq3a^eCi2r^vtKc+yhT}-ub7zyzZ}imkb{D zF6#b{H~RVSdO3%lL%YA{`4hhnUi!Z09sa(Tclw83&gma{{@@Fqck~7D#|z+}6W&E9 ze&%@-|JA$b+{>O<@oT*A*WT!{zxTZRe(#wFfA9Gf|L)~I_#bH3Yu@NRuY>>2dwGZQ z{haw@{m~P~`QG|*zTbVRpHn*C&l`Wa@9n+Z&)Ge}_s?AE=RIJfAk~Q zB7U;(jW0mDX@1UY*Zck>g?>)+bl*EU-5-B=rtdcv`Ce7AZ|aJD{|Lh42pdZtf6?;W{G7e(eecQJeZS&u{^+F}egDKp-<;X#kM3?ly;^*8 zw8i(=xB7W!Hv9hBPE5vKer|J@k2BJ~Klbf@&dIm?=HwPX_uLlWm~KCJVz+P3Z}q)X zy?9r@Z_f4m7vDGFn?nPB?n?-RLEq~f^mAWBICIF)J--9A+vQ)h?@r$wyVLh3-R1iS z?()6rcl!R!cOl&E=RJLopHuM{zF+umKezMUzW3U@QP20_J@4^z9)GW&d*Z#Q>tFig z_TCE`-Roca$oqZs==*(d@IF5;^+A91@%#Op{SP4S0e@WIL%u)pVL$KLPx$`)Px?9M zKI!LGea6qJdeqN5|5<9N`&+GyfmopYnM>_vGjOOUEDb&7?zqPW^vF zzy3G>l1IMe=T3Ue_m4g1kKX&ZpZo0Ne$LZRpgmvq^LGB7e`)8FsP|KT-jT2RUfb^K%Bj z?R)3G?dKf+N6_ax=*#c;-r;9KkMH{4ecuHiJO`RS=liD+KKMQV;@7_Cn~LLp?#APw z$8mr3;phFljW2))U-11$Paw}f`{v+3`xh7f*!TAR*uQxEi@w+WqM!Tti~jg0Px_bc z{t5c#rzq#AzBlHSZzi7dz0@f`ckd~@<7epSfAw?D{M`5Vo<{kn{k%Odq1=~2mot9e zqi0e6??CI{`Qv83>R&eLHQzt~NA&yaer^@?zdD2)5$=55_l_f+bl$(}6!gKD&ifN9 z{^XnafAZfv-{f4`os)CL-8nfBqnMYB$-xwogQ+YBQ)v#S^c<{nph*~mbxaCtpVWB6 z>l|A5&|0XGFvRhncPA8;op1HVkG+=HRud6hc=}Io(4R|V>c)-#g!ggZJ;(DHcc;{xKi9=%e`+03X4>@uzJ1Qc|+% zZ{xV5UZxBmyZDi@fG6SK^Y}OM=QbbJkN<=|?(zSo5X)8m8~YEIh_7Cio7VivS@1yc z63L&I**?@$KXr8gj2iR4EalU>l>YW6$`3f!n2%)1PwP_pJEr76 zoFzZ4XX$UuqV)D5ire43iD9#Iac2A&)(7-H|gi9stlyI+v2PHfv;Y$*Z>CW8lXTN0M>*^=f zp@8dO_gFe!DCI1buv5al5+0QBn1nA$m@N0cze_LI;Z^eE2=prYOTj)se~uoZY~ol0 z_dENy^M^JZ^CKJXy4<#R@+e6lf$PWDp0nld`;ZM6oE0HvAHz&qdRM+t((jdWUHRjF z^j|AK9B+y89erNy3Z(mSL?_=EYP{%!XCNxpIP zI?-zJ(-OM!63sELe)FZDU3*-5*WVMDWai)fy_xIb=+uYx1pOVB(3N{xq9R&7YR_b* zlPkY;uPvxqLRY?#Y>sMFJ$<01gf+B@ORwxB)X>%)#}nG>K{n?cR5_1V*ywB3~WO5SHB|tg$qyEZ<3$G_9gh!rBAjm zeE*->K3AXQ_;vib5jHjYbNm_BC&8ZwI2G1cJ8k*{61w{QZc=)M9Q~5~8S;OEe%S8h zza+iinU}eL9KDnCUs(SHKf3fu`TSo^e_)i%TO;-)t=Zm+Qa$Yc_xL>hyH3f0O-npDWL13yX8( zJIVi#xbzABcl}ilTP6K9OL$1qj}J=@e{g*dNxCGxU44`MviP#}{tQc#{@eKd%=D|4 zg!6x5@jVhc`Qs(pUr4lHOYi9A)=Qnwq_^YPX#1k(r)`06i4lN)I{a?I^A!9q z1iwbX4+wspfp=UHiHOzf8gR2%Z?GVgC0DuF?N~!7o?J|Fqy*{SIX*{|Ui0 z`uz7S`Jc}6{^tbO+J8Jt{vQjj@$df-T;q@536A}wv_IE>qmEhr(b_*&aBcj)N$?=8 z^oTzyvfyh4*T(NA!QHyfy~fr5py0L@4vpS_NN_igxD+n`4+YoS|Dxa;eSazVC9Yrz zUHPvFuGQ}kf@|_+)VFO;4S$p1TK`-vxYoWvaE<mBHe>d&V@z;xj!^bu4 z&*8rnoV^TVDIESM!LN*A^wZ&2{G;VR?fp{)*V;EnaE<;;1=sYGI|QGo)NhC2TKnEB zxK{s%1=r-`-w3Yt?-PP+HyCuvT!bea(Vv{L?46R=;-%uE~!*f@}QsLBTct z`Kv7DKa!>V&t@tAi-K$I`5L}zzKPI>~e>^6* zM&BcXYxR3B%ll6Xu8r^C3a*X6bAoIA_n(4m^&kCR%Ng4HuNGXRU!maI`^yB^Y#R*8a_c&r>6I|o}e-vEn-xspv|9KYtw^{Jlv*4qT+m>ndf0N+a`s?Z}`KJk9pzy~s z!DlG=px~PR^8vv%`TIG+->Q`VjNqF5{E6Tif4?EPv)jAZIQc*K`96fS z1cFa-9Vemdzr})It>DdqlaF-#&*guI;9CEFP;gB?d`xhSKOYl(TKwhs?cV>-f|o1! z*nhJ0xk16J1lRhnPH;{CTPe7GOY{;~zcpF#b%Ja9=?1~I`Kd*4jXrw?*YwK=1lQ>E zRlzm=;CF&+{C)BBmNM5xq~TwVJ|%){^x+VG^nX%tt$p7Yyhx$n8-i>4@1;Mq^w-KS6kHp>a|PGr&nm$+`7$WDHa>O=uJzx$ z1lQ!peOb!imnHwl1=q&krv=yK>(>OY*7`?qt^GOTf34|{qXgIHxBM4u$(sCLBlvYn z{XQr7bOryu;M({(CAe0)#uBD-_|^Yx>t7Wj>G>N3uTk)a1iwYWPYJHoKlrhIzowto z3a;gUx8U0R{87O*{{6V%g-ZRO5nR)Mek%CgO8yNm+V*Ms=|h4qQu3b=d|G0I*7e^T zCvEwfesJ+mEUwA-34&|#?Ja`aQld(__g^cx_Wm0L*T&ae!L|OY7hKbSTLstT<7UCN z@wY7tewX0d{Cbbz+W5aO3;tJvYxMn?;F|pUjNlr5o)BEqUruIu|EVnRe<=%oR&Z^8 z9`#e(at)s(ctyl|{LAs*YQZ)6-z>OBpMJr$@&7TwHU08?f@}Qo!z}oVf@}KC8NoIE z;tzsr<7@Q4So&(?^G$+l<7cAa8h=g_T&sVP;F|m`6@04Fzv~3o=KtM-YxRFm7W`hp zHTm$M;F|nDB)Dc@|GMCs{q~;(*ZBWef@}VFqfcFU{9GfrCSNPE;J0SMTeIN1vf%r& z;GfHae=Q6C!z}n2!L{-8N5QrAOTL^3)cB)7aBY0d5?t&5WrAz+WtHF>|K2XR#-H7S zYxCE`f+y6EQ2*SY1^=kvTKx|Qu8sd^1lPvTkF%72N^p%nFK5YrR&Y&!`h(z_eEd(r zHT&hY|7vq;<9mVNGZp#xcEJM$f4|@w{XUr`|53rU`Qur^uT|cEMsUqOH{s{D{o4Aq zRB&zl)CjJPpW6i2)^GiSYxTQda9rP&_UH7E=LFZ*FTcxzPdIJcUz}EYWIwDGT1#1A=Sz_rro~d$Q~KwIU)uL;`dhK! zbCmoYg5Rv*Ul9Br1uuQczW+J}?-E?2-wwew`LS1UP5ypXa814(5nPk6#|78)uU`tT z=?`yY$$!JIEPZZJ=yRLkTK~OGaE-q26kL-(e8II0E)`tMf0f`G|6MP*wmz-QlD|%HP5vztTpPc439i}y_hrfd_kv%q z@Yl zlK*RhYy9^E!8QHjb-^|J+a>>IYo@IqiUil>*CN3+{#`Bj42Ax83*M&Srv%sJ&+CF~ z_SJ&l*!F4kxm9p&e%&d!wtw)L;F^5?vEZ6~uK2C3pZ#w{1jnCMf@|_?vEbVHS}nLX ze{K+5oB!Jc*Tz?m;M(|jr{LQ9@}q)l`peUTYxR3p@E{@`|8n&Ew=DTz5nPjxW6s*1 z(b_jra815!6I_!IcM7h}U%Lg@_~)a7YwiDg!L|Lx*9F(sf7krZw*NYXzBPht{I^2z zSxWwU1lQ>Qpx~N*en@bQKFDY#}I%X`J<)XKk1a7}-nDY#buIa$iD6*T(-h1lPv*(}HX3-xGps^XJQg-=g&I?EkR+ugza|f@}Kc zM!~iAr3BaXuPuUW^7AgiJ*EEd5PXV)e_C*DeEyB#ntpjS%lrRcaBciPBY1&Qzh4PH zQ^Bu%&6ce3-(;M)8$>JPSMn*6y+aIJqz1lQU>PjIb&77DJ>w^nd%e0FAe z|3H@VcVsF5oq}uif4AV8{P~#R+W7jK;IkF}J|}pof=~UUrJUA3Hwu28lD|ptK*4us zDgR-?wf_64;F|sND_QU#3$DrEmj&1Q=eL4u{PSv-{I3hH*}tZ~ZdrVK^~+kp zHTl$<1@9GHo8NW_uF>x=1=sYGhXmK^|5?E``~O!3zhB|673VGeH2ryt;8T_S4+yUH z?|#AGr{pjAPy2pNeiaFRosxgG;F|upLGTtO|5pXq`tKhEx3!E4ar*VQ1=sYmX9d^l z_aniz{y#0aHvhaPxK_XOf@}4ALvT&MnE5ALa!J&5{^i=gQE+X3+ab92{yPQN z-&&RB{p$tS`oBYPO+IZCT&v%9!KW$o|9F=CpB7x>?=K0i&9Bc1uJP9o1ix9S-_^Oc zWg2}0!8Q8aAh^c=Hwv!Je@g||`e&Ws+Wc~d;9CE*39jki_Xw`ZpU(@f*$=)dxF#P@ z2(FEfp9!wf|CfSm^gAcGHopEN3;xF}_`^-$iHU6s#75V?2Ecs6euJPYl!8Q7g9c$^Y z&3`il*T!$P;F^8DS#WLq?GjuYUmq4+)6WkJuGRlJ!L|8$%q6z{l?weA3a-t6je=|A zXN%xPO8FlVT$AsI1lQ)jZwX$el>Z08=PP*SINN?rzSIe>_1`AJHT|tya817T3O-M% z-{%FNs^G^3*XsXM!EaLXUnAdb(&$?yxW<2L1=sY0X2CW2pUQ%F3a-hQo-FylD!A?C zhzQR9{r7@v^!wm=oAdf8EB|u&zbv>m|9@R@P5*mYaBcqjz2KVs9wpzY()eSh;F|ne zB)G<(ErM(G=@ne-pCQ4M`pa=?@VYWfUr(X$-I8DHzk39qqU8Uq;1vq~n&6uJxmdne zt-XJI7W@jqHThm5xTgQzD7ZF0*9l&rwC~GrvNhM{*Pjcn_1~`q*XCDmf-PUG-z34c z_05ffYxCFbf@|ZeRd8*7+99|$em^O=Cf}bFT$6u46kMDCU&(@BafPK{p!8p57W_8B zHTl~rxHkVkBDf}B4hyc$Prnv?j#B?M@?ASkel%yndj!|?_jd`dt?wTYT(h4(DYzzo zzLEt$k_G>o;8hBJ{v%8NKV-pQ&w~GF7W|DYxc6qupW6I2Q*e!b#aZyuEO@!#$@#<0 zzjFoGJE0Y<#DLPf9rE z12%rWga;*jO~R!gwD^7rUy`uuej9&S!V?k}?z8bbB|IkK#0PAAr-Y{@9P=R?zh1(F z5(XcZ`1Lldm*>M0E`89(ACz#+L-x5-!ebH^K5XMB{*?`PN_axTs{J;8zl5(zXg+G= zX=GJL!)xT%2n9wcFhYS53XD)-gaRWJ7@@!j1x6?^LV*zqj8I^N0wWX{p}+_QMkp{s zfe{LfP+)`tBNP~+zz79KC@?~S5eke@V1xoA6d0kv2n9wcFhYS53XD)-gaRWJ7@@!j z1x6?^LV*zqj8I^N0wWX{p}+_QMkp{sfe{LfP~iUx3RKUqCtR0HxL(4Pgnbg;E#agh zo4!!OyCrNcwDH{%?v!wkg!?3XM8bm-R!IJ8371Q_Uc!`weG=}KdORrM0SOOD_@snS zOL$zulM=op;W-H(mwFtP(A;3#F;>Ef5>An@RKocZE|suR!e$A(CEO|D9trnJ_=toD zC45}MqY^$V;Ry*(OL$ho^Ae7kY3n;d!a%~A5>`oACtHaJPi_Nw{CaM`lfSlWL?!ebIXFX1T(&q(;1gt@}E<0Yi~DCkax z)tfAR?tg3g3G%l|{6`b<%@Y6VM0~r%e?AevUE-fe#D7TQznO@CO5&eS#D7ELPbT7z zEAc;*_+-0Yk@#OG%DLzcONV5;#!LL~6X_=^>8D8i>xuNG5}$KzI-O@L>E}s&lKzV& zK3PxdPdekiTEXdl3wpDAU#p~Z@7XNRuKaF!cICNeM^9HTR}a_kuAg1Mx_)&1=E5t4 z4z3?uIgZZm+0oI_%{{yK&yaFl=+61ObK+<+{}FwP@b4YcuK9_6_=v>coQVIT#IH@n z|AUhLq>}zsiFfp~wKC?arp)87QsR^EU8}@*OMF|Ro}W_6|AEBsNTkncw)J^WB7UO8 z?@Pp2N_>)TgG&5kO8iNQPts>pi>*)cy;CGU`QBTV_-zuOq~|9k{u7CIJumTx6Y-a{ z+WI8lTdKsTBtH4xJrbX6?^h)L8;SS+Sc(6G5<35oyT9Xk2#?)PwV@*eys zlz%Rc!lPH&_PMw*W25^zTwFX1@WAhQw@vqw^!HQJeo9OD|El?NH_D>Bf0FmtxO(pu zeazLnGg1G2@;suirT6oQzGmg!|DW|Wx>Kt3?V08JG9{kI3FT-~@F6AsLlU3VdtMZ| za8APH^O)-_Upl#!N$(`=i1OY-$?xvZO5SILto(Nm{+mhu{fEfE6Cy{0ysOjSd+PEF_v>zyMSYR% z4_D55>5pvXyayG{#AgkO`ruU;{0o3m3vy+i-P3L9`Kcn?E_&kn3VyHPH3@vI;2#$J zXaXNE_(zodj^8gHwD13GNjF}e|5l!_`LM;Gljn(opO)u6pbOQPXhVN(LJvomqmJJ# zY>vMvy}#B^u+Lh5xBtKFy$^U@Q`W$JZj#n5p=lKv4bm!;p$Ll1OnH+gB^~_}O{zgh zk~X(ZNRunM)s&dI2!bH3ASi;;3^jrxD1snHhoELMqef7~C}I>DExxtS`t3G3&29R= z^M23sJ@41sp0o1XYwflFo_+S&=bU@-7k8BA12+*xSTt_^c`U3SPjEzxl%Mm+Pvw7@ zAL}P#20V&L`S~6BY1qm9B#K{YGG`S1+%!|s@ylvlzlX{Tr4+1Rg#UqSyFTzIR--z})}aKiV6ZF?t6+UD~Z^=s?7 z*;CK?p8EFxOzS^Vdp&`_j-xewO(pU^QB>wTeJ4;~Uy@I6d!?Y?jNW^EPei}ld77@b zJyX%|7eSwaeryDNCi>$e=%=DjkD$*&{{s2<<}U~Rj0o{_(a(;cpMyRxf<7Ppf(ZIT z^kotBroWnYT1@^IV|NLB6I=&B4&MU539o{`g>8N8U9Rocf_^-_7S4ps4?%0p@7wNeDEBR^PNk56=(Bv#gzxf06 zC~v>6M8772z6gD11bqqm4YTYyO@#xM)cnx8CjX|Csj}6ee;56F&vkAs`j60$@XTB7c=n&(-?itxBFU5aj2^A+ zV(YDDg0_pTw+8C(AnZ~P*7}Teej9^bCw?@Q$osIU20Fi4Kapeh*F?(CF*e`FX}S8x z+MdD^G*Eu5pY3A|91D=a zJ8!r1qBA+p$6#mspV6C70qNU(G<)i${gD30Zx0-)JoEks8Zbv(GI_ zkoy^Op{DPBe&zlfH2g{YSo^CRHN1v(I~(4#Y~XU#hc*0Nj~|}9A zXU}`V@jISRt)c!q@uR6k-iJjs(EP>vi5#=PCer-n4f50TALhsU>7Qz3ij<#j^5Z{2 z>p8Lq)r3V1R6o|wVDYU!QhxqTep3F!{8&FWy}@Lp{0wJ4QS=|?$NCv8A66e}es&o7 zv37&WL@_W&{wj|5<|=Jx?|icv{gddu>rt!GzkuF*{nmp1b@bCbb2&dzu3`0!tp-_}Eer(IH#`;V`!aHRU2guh;opGfs;>eJ+`jq;vOKE3x{ z*Pt&zpTK=^6W1I+t>_n^_tvK=x2ZE*Zac5F`Hf4_`VkZNQ*(6xa@+7o<<6ztl^#Df zo>wMHfH?=YlkdYhuX@ibYtjD_{l%VsVB6C>U$^;b^5iFc%zv+30m_y5%l`G_Esy0y z`NOQwcaZOMF4lP7{=W|W;t2Xq^wkmc>(O5mLEnY`rU?2C=vPG0ccX8Kpx=o8r3m^S z^qmp(o6w*0z`*s>i~jux@wcG=GJ@Wz)^@h{9dkYFJLXt0?PTwR{D7ZmWWptyFMD6) z1b7eh+34oof95WnT7s4^uLAoyHxe|KIIAU*&G*V!1j0u zO4-b(ivDZ+af+uO=N{`h9*$Fvbe#VVf9iekeWI9{`>Qdu$3Gv}a(IsiKl+a;$57As z7K{Gd2>LkmKSj`wLceGA!0E@MPl%vTK!0Qez3ES;oEcB6|Fc?DE+apw#JdyDh5rB- z!;itghuh#r_-(iiw(XrNX`9crw2y74o?mG`RO>iJ$M=rJ_F@y|+InqCW@y2cGy7&RwjG;2?bzUH&(>dR`$if+?#5r|#QyzKiZb9QQ9{jcA!kq@saI+| zZ+&K>KOMc_Gk#1(KR1Ft3;lWMz4NOa^cP3a=c2zJy*Gbz(BF>U+h6n1{~?0D5dDLk zFOT$;uL%9K#6QKOx8qYwjn?05*ggLTiJAnkAaL64^&H2q5Z&qLVt{8~BE_0%KS^`5BtCYgvLESiC?H?5zD5j_esULGu4 zq~~Hktk?X^=D4-d8<%Rh_x{_;n>F0~yzB+6TX~|GDM7yC}0^R?yr zg!;7WZ#H~>qvq2azBxkpk_h2T8wU3CJ?n#B{|VGjt7n~a1b*^8^_g(D`nT_G+Wdb@ zxYvIO|K9p(i(r3x1p9wPu)jTm{l7S#z4`QCt@(ed&-*;43=8hnaBn?aO}MxJ*z=h! z_gMVea#^%binPy-kD*_sBhNxsAnkEr^L;bn){nJ& zh;Z9aUxIg5+WNBn#MZZc-`4scjBPyIF4nKjznSZqkNtgSB`4zZpD#1cT03Wwj>}uw z^GBkvxxO#qyi`qlEIq3Kx^WQwjS=+ryp@8!33)cM1Npz*Z|r%?yRKmCA^s%o-?kp| zJ@wH9oA|q)Gm=W+v+F*f_M899_W{ij{tV-M7vrC8|4#`2+7rIpO05^~d|({mQJ(YZ zaQHanX-I2ljysc&w{BCv-t*|n`5Nv$k3PqI$ZOw8xYyo{PiCC6=}aKM){o^9@^=x^ z%XU1D^gdgL_3L?0eJTD1i@%Wg4`VM`c0ZN}i*L`X_B>+aTefF|%A54BPGm}has#p# zY2!z_PW+nlO?;}hQ&y%;!N%+_69rRb3voVq`F@S(y^mRm{x$T`o^`=0^zWe`>(PhN ze~#XJ9aoLMH-f$fee5dDpErIj`h6nk>(Cz=L0^yl#0dHZ^jQ(~%h4~4pl?KfNd)~0 z^fyP)H=%ztf_@eHwg~!W^dCjguSUN)g1!a)P_Cm>Jng#%eI?gp-gTc=^a~>B+t9~F zSl4bxzc2b}p7htEKbPxrZ~7hRFF@~I*ItMIkO=-e(VrM0f9ugtL+|z9h5n2P@i(B4 zw65Qc{`?5>H=@5Lg1!g+tr7H_(A#yAB2WGHqJM(;mw5DB(7%e_+dj@^Iu3P3(8r+v zHbVaV=%fFr$G^9IW6|#)K_7?yQ1o|t@;?gwN$9=(J0AV)2=Nop7ooq~<3AC72)*|{ zO!2pM?H8^xo%g$D?mR@2&r2^ber-*53s5t?0e|HwFFc5#moo{}K9cJ^4>X z|1Em&bHN$tV;|J^-P`lra3=bnq5ru@KNWovdhdPpEcC~r_qM;8k4%*9Hr6N7u-l9E zoFII}eVV^(;g#qggeRka1GeMQ_plv*MmMXUGq6vCXE$m10{DH_KN{c`)}fz{0sUI|HuRst73BBlt2Lcw^uL0i@Z`s?BcF!;RqQW>54%PEJPfZ#|2Ayr z&pq&W%-i>URO7Xf-xJ~KLHlGJ*AKOly znQE_E`TmZa{?|kCvv%Cx5B?9^J4k)~iF|tRYlYCiiQfC1RwepQ^xpQWLf?gcmS=r1 zj6TwH1J&p^5#Ku>s6oG@_XJG8w(ki3?PT?v2+dJ{}{_X9bt$eZM-8|D}pX;*y<3;@Sdi+?uSB52Ep!;IhkJmmD zuk-Y?hEw~OBT~Fn6p_ZOPdt7j`LW@N@`q{HTG~I-^J8`Bzo5PL^7OxY^jpw-$D;=H zBRC&>*Bh3jx7Q;Fdi*z{Kalt*dh{#MAA#O`e3prK}!>;?BS`U%dMR(oj)cI}9W745a> za~jWkU%DB6r0W<{zb2;lI>39K@K&q(A5A*;yll>^=3}43x8+Fol%qGlfBU2sC`YP~ z(>&jUuBk-cCyL5EZ@HTCKK8uk_kGViqy_yN^xo^LHR!w0`}kfyoVoAorm2B z-%oivY`*W(^6k~8()Nc;@ohf&w4ZIqR!@KM&(-!X#4dTBvguD|zPsyt9ZfB6`^@(o z4=sgSU)wDD{}mP-XuPt1x@Ty+4d%zTyX`M^^n=Ze2kC3n&sbzE^4q60{7cps?qeO% zt|wjx+x5mpuw9Ql1D=9RM#duTy60Q0f7*4?`(V57YS&{I5^mRbr@?l8_ypLlCm#s! zj_hHb&#w2`bwRtHXxAm}dZ=Ajw(HF~#6J~zBytF{hjr#Bkafr<$b6(-kKP~N%>D4c zBOgNEf-JjQ+u>~F6r_C)$v*dHpFcbDO0~Do!|o67j`Uxy`k#2-dIR!pD=$^Oecs=` z2Vmb1uZbk%u6UL!OB&LRKKJL*9ja6!{9W6Zt7}cb;R}7kLcw6yzDmGURng z`~1tZa3^xl1)A@Jk;fvZAm<>@L0*Eq4QbcWAB8s{zebKNQvbQgQsmXhTaiy9*CIbf z{)qf-vHH0NxdQnj^6$t^NV~pgzyHHNf3?p!v=g!e`7zReuIdj$9*3NboQo_)Rv~MU zcOX|GpGLlk{1CYb8B?O^?T@tUhDX8ndzJ0?F5B~cCi*$Z5HgD6;6UVWkY^(=MP7%r z-^)6yRP!+xc@?q&X}=HiVfZ zk%liu+TVSug;yZ$?>IdJe~a9V-0yt#a}e@4WF~SBGKhR0Idrkc+Xs0(au#wS^7qK$ ztao1pHzDo!mc9hPi~JrrvQpEz7P$iX6w-db!)AEc61D#s@@DdTE%I3MaU$|i?0${R zM4pDsM=n9y@BgsxegB;A1Ia~}Bkx2$iu^P3UF1KJ-yox_G~dIKqmgMyd;fGgd^U0k z@@ixQ^0154-?7M(kiTlu@J#qT6&h0!lVu0-1BT%z{6@Z9|_1~kS8PUbFlN_5b{#w^~jY-`<~aI;g68^xm^2RSJai7?!2p1 zRwD04K8$<~*?YCx?Nh7rC}bKk3t50X4|zHADy03rJNr9xj}rbAvK85m{5$efWDoKi zEr%( zJkq{@HU&NtnU7q6wD*lJh3)%q55o37`JZ6>KG#>Uy|2C(&wCtzOh%?6?eie^IUD=@ z%EjpI^HBDCon9sUGo*c=%RVP%f1hCN^;%E%eYn%$JCXLespsK!$j!(R^&0;d$m5Y| z$n%i3$or8`A?@$6*xymK@6*}$3%|n7zW4XD8#KM6k*6Z<@3$1f=OFF-h4#LdeJ{_x zZ)d+ZYwsJ?uYGQ2E_^fcaio3E@N2jix!X+|e=O2|zxwg;3}i0ydgMyvlgO8loydP6 zw;=6%c84@*diFV|8E_6V54jL|0n)zjw;Z<5{n+P^+6cGLv)SjYoSQYhQOI8)?Q==? zc{TeSn|SWk{f1~}r)+-6`K>BXgeC&@r6nPvn8)?6vz8DT6 zZ$Yj`b|61M{)im0T+^9^%tp>fo{zN8QQZ%}jQj}sEz*CR`a2Q11i2Ks=p5DG3;!8u zpBwuGw$F{l-mdnek;fvZBhNzSBkk`OEr9Ls6IH_v$Y!K{Udz50V&9`3c88{W4AMR~ zXy3cHzZ;N;-hQ7)7`_JCh_ug1z68I6w9orFjhfy_^&sSNpwpP3T`j zzKMJn`7fk>Z#L#mO)nmKBJy-(3G#Qy`;f07|B4*SI(RJdSY$df4_St^>+H9{_W48m z9Nq@P?e9MAeYfV*zF&I;oPo?j+UG_~;fs+sAno@h+xJlI`=|E4oxKlk-;1{I+uHYZ z?fbM(uF(9vj@*Pyy+^~(K;DIX2>BT@`d+oO-*;ud=jxY)pNh2iqwW3Ys~^*N_CA%p zKedMNzaSraTPUQcPd`yt05k45GnOOV$g??A3bwj=+F{QVmB zTaSDS`5N*Ir0;398;P{{3lE0vb7=N?GW(p_H1zg4wEJQEoZ3gN>es$E_A>gvA=m$2 z_4a=BMb9WdiF_StpF{o_w$B~!_N>~EK^}*kkGvdtE3ygsIPxu|eJiHS0Qgh-iLe{dDwH5A9)(G7Us4)40#AL19=*9 z4ssr{0%_mJOS)X|MBL>7@oSLQ zzm*N7Z@G^2EPG{&$4{q+t$h;tYpT)obCKPiddsCemDFo5*PMU?N7FS{GM{!a@+Q`^=#|Q){pIHHlMcLZ9Ulh+Wuzi&$hGeSN8a^ z^=SL4tw&qWw*T0Byym{Xxp$r@Ti-DAcVAr+dT&^=gr~@sDqE&(S+eEImM>e8Y>Bd& zxF(*lHEH=_^S8A%VK&@KqfhJ;ZrMuX)7n~TbxEQ#>7~e)DqE&(S+eEImM>e8Y&(i$ z^O`7jBV;pa8DA#ONZFG3+k_94<}W2YRklpoY&uq2`!S*$E8D@cjg##V*$$QM=dv09 zzmV-P*$$U&ylh9vX7Xk7kt&<Y)!H?%hn=W zt8DGEb;#B!TbFFzvh~Q;E1P+!%P(7;Z1J)s%9bQsvTP}`rOK8mTb69OvgOO>muPXa z#mkl`Tas+avZcuOpXh8{EBpF4b!5{>mA{=q#`(@z9gmFZjy{RlWewu5dBjfo+ey3L zk?OB>BwU$Q_l{=xRK_9~sHM8-MYGjGxK->|DK6VplYXzgFzJ2C=L2 z{4Qdoa`>@JjxfК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 + + + + files + + files2 + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/_CodeSignature/CodeResources.meta b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/_CodeSignature/CodeResources.meta new file mode 100644 index 0000000..4cbf196 --- /dev/null +++ b/Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/_CodeSignature/CodeResources.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 724b52b308e9a4a6d889d7bf3945a2ca +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins.meta b/Assets/AppsFlyer/Plugins.meta new file mode 100644 index 0000000..5394930 --- /dev/null +++ b/Assets/AppsFlyer/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 66297743248ab4e47abdc371a59f1111 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS.meta b/Assets/AppsFlyer/Plugins/iOS.meta new file mode 100644 index 0000000..286d70c --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d8325c12a80ff4323b82e2833a8fc287 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h b/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h new file mode 100644 index 0000000..c838a93 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h @@ -0,0 +1,22 @@ +// +// AFUnityUtils.h +// +// Created by Andrii H. and Dmitry O. on 16 Oct 2023 +// + +#if __has_include() +#import +#else +#import "AppsFlyerLib.h" +#endif + +static NSString* stringFromChar(const char *str); +static NSDictionary* dictionaryFromJson(const char *jsonString); +static const char* stringFromdictionary(NSDictionary* dictionary); +static NSArray *NSArrayFromCArray(int length, const char **arr); +static char* getCString(const char* string); +static AppsFlyerLinkGenerator* generatorFromDictionary(NSDictionary* dictionary, AppsFlyerLinkGenerator* generator); +static EmailCryptType emailCryptTypeFromInt(int emailCryptTypeInt); +static NSString* stringFromDeepLinkResultStatus(AFSDKDeepLinkResultStatus deepLinkResult); +static NSString* stringFromDeepLinkResultError(AppsFlyerDeepLinkResult *result); + diff --git a/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h.meta b/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h.meta new file mode 100644 index 0000000..f6811a6 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h.meta @@ -0,0 +1,27 @@ +fileFormatVersion: 2 +guid: 4b0609ff467554f2088aee1c52bf54a2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm b/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm new file mode 100644 index 0000000..59e0163 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm @@ -0,0 +1,145 @@ +// +// AFUnityUtils.mm +// Unity-iPhone +// +// Created by Jonathan Wesfield on 24/07/2019. +// + +#import "AFUnityUtils.h" + +static NSString* stringFromChar(const char *str) { + return str ? [NSString stringWithUTF8String:str] : nil; +} + +static NSDictionary* dictionaryFromJson(const char *jsonString) { + if(jsonString){ + NSData *jsonData = [[NSData alloc] initWithBytes:jsonString length:strlen(jsonString)]; + NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; + return dictionary; + } + + return nil; +} + +static const char* stringFromdictionary(NSDictionary* dictionary) { + if(dictionary){ + NSError * err; + NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&err]; + NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + return [myString UTF8String]; + } + + return nil; +} + +static NSDictionary* dictionaryFromNSError(NSError* error) { + if(error){ + NSInteger code = [error code]; + NSString *localizedDescription = [error localizedDescription]; + + NSDictionary *errorDictionary = @{ + @"code" : @(code) ?: @(-1), + @"localizedDescription" : localizedDescription, + }; + return errorDictionary; + } + + return nil; +} + + +static NSArray *NSArrayFromCArray(int length, const char **arr) { + NSMutableArray *res = [[NSMutableArray alloc] init]; + for(int i = 0; i < length; i++) { + if (arr[i]) { + [res addObject:[NSString stringWithUTF8String:arr[i]]]; + } + } + + return res; +} + +static char* getCString(const char* string){ + if (string == NULL){ + return NULL; + } + + char* res = (char*)malloc(strlen(string) + 1); + strcpy(res, string); + + return res; +} + +static AppsFlyerLinkGenerator* generatorFromDictionary(NSDictionary* dictionary, AppsFlyerLinkGenerator* generator) { + + NSArray* generatorKeys = @[@"channel", @"customerID", @"campaign", @"referrerName", @"referrerImageUrl", @"deeplinkPath", @"baseDeeplink", @"brandDomain"]; + + NSMutableDictionary* mutableDictionary = [dictionary mutableCopy]; + + [generator setChannel:[dictionary objectForKey: @"channel"]]; + [generator setReferrerCustomerId:[dictionary objectForKey: @"customerID"]]; + [generator setCampaign:[dictionary objectForKey: @"campaign"]]; + [generator setReferrerName:[dictionary objectForKey: @"referrerName"]]; + [generator setReferrerImageURL:[dictionary objectForKey: @"referrerImageUrl"]]; + [generator setDeeplinkPath:[dictionary objectForKey: @"deeplinkPath"]]; + [generator setBaseDeeplink:[dictionary objectForKey: @"baseDeeplink"]]; + [generator setBrandDomain:[dictionary objectForKey: @"brandDomain"]]; + + + [mutableDictionary removeObjectsForKeys:generatorKeys]; + + [generator addParameters:mutableDictionary]; + + return generator; +} + +static EmailCryptType emailCryptTypeFromInt(int emailCryptTypeInt){ + + EmailCryptType emailCryptType; + switch (emailCryptTypeInt){ + case 1: + emailCryptType = EmailCryptTypeSHA256; + break; + default: + emailCryptType = EmailCryptTypeNone; + break; + } + + return emailCryptType; +} + +static NSString* stringFromDeepLinkResultStatus(AFSDKDeepLinkResultStatus deepLinkResult){ + NSString* result; + switch (deepLinkResult){ + case AFSDKDeepLinkResultStatusFound: + result = @"FOUND"; + break; + case AFSDKDeepLinkResultStatusFailure: + result = @"ERROR"; + break; + case AFSDKDeepLinkResultStatusNotFound: + result = @"NOT_FOUND"; + break; + default: + result = @"ERROR"; + break; + } + + return result; +} + +static NSString* stringFromDeepLinkResultError(AppsFlyerDeepLinkResult *result){ + NSString* res; + + if (result && result.error){ + if ([[result.error userInfo][NSUnderlyingErrorKey] code] == -1001) { + res = @"TIMEOUT"; + } else if ([[result.error userInfo][NSUnderlyingErrorKey] code] == -1009) { + res = @"NETWORK"; + } + } + + res = @"UNKNOWN"; + + return res; +} diff --git a/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm.meta b/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm.meta new file mode 100644 index 0000000..b411375 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: 18a03931864e84d86bedcc99c440e060 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m b/Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m new file mode 100644 index 0000000..017a1c7 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m @@ -0,0 +1,132 @@ +// +// AppsFlyer+AppController.m +// Unity-iPhone +// +// Created by Jonathan Wesfield on 24/07/2019. +// + +#import +#import "UnityAppController.h" +#import "AppsFlyeriOSWrapper.h" +#if __has_include() +#import +#else +#import "AppsFlyerLib.h" +#endif + + +@implementation UnityAppController (AppsFlyerSwizzledAppController) + +static BOOL didEnteredBackGround __unused; +static IMP __original_applicationDidBecomeActive_Imp __unused; +static IMP __original_applicationDidEnterBackground_Imp __unused; +static IMP __original_didReceiveRemoteNotification_Imp __unused; +static IMP __original_continueUserActivity_Imp __unused; +static IMP __original_openUrl_Imp __unused; + + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + + Method method1 = class_getInstanceMethod([self class], @selector(applicationDidBecomeActive:)); + __original_applicationDidBecomeActive_Imp = method_setImplementation(method1, (IMP)__swizzled_applicationDidBecomeActive); + + Method method2 = class_getInstanceMethod([self class], @selector(applicationDidEnterBackground:)); + __original_applicationDidEnterBackground_Imp = method_setImplementation(method2, (IMP)__swizzled_applicationDidEnterBackground); + + + Method method3 = class_getInstanceMethod([self class], @selector(didReceiveRemoteNotification:)); + __original_didReceiveRemoteNotification_Imp = method_setImplementation(method3, (IMP)__swizzled_didReceiveRemoteNotification); + + + Method method4 = class_getInstanceMethod([self class], @selector(application:openURL:options:)); + __original_openUrl_Imp = method_setImplementation(method4, (IMP)__swizzled_openURL); + + if (_AppsFlyerdelegate == nil) { + _AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init]; + } + + [self swizzleContinueUserActivity:[self class]]; + }); +} + ++(void)swizzleContinueUserActivity:(Class)class { + + SEL originalSelector = @selector(application:continueUserActivity:restorationHandler:); + + Method defaultMethod = class_getInstanceMethod(class, originalSelector); + Method swizzledMethod = class_getInstanceMethod(class, @selector(__swizzled_continueUserActivity)); + + BOOL isMethodExists = !class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); + + if (isMethodExists) { + __original_continueUserActivity_Imp = method_setImplementation(defaultMethod, (IMP)__swizzled_continueUserActivity); + } else { + class_replaceMethod(class, originalSelector, (IMP)__swizzled_continueUserActivity, method_getTypeEncoding(swizzledMethod)); + } +} + +BOOL __swizzled_continueUserActivity(id self, SEL _cmd, UIApplication* application, NSUserActivity* userActivity, void (^restorationHandler)(NSArray*)) { + NSLog(@"swizzled continueUserActivity"); + [[AppsFlyerAttribution shared] continueUserActivity:userActivity restorationHandler:restorationHandler]; + + if(__original_continueUserActivity_Imp){ + return ((BOOL(*)(id, SEL, UIApplication*, NSUserActivity*, void (^)(NSArray*)))__original_continueUserActivity_Imp)(self, _cmd, application, userActivity, NULL); + } + + return YES; +} + + + +void __swizzled_applicationDidBecomeActive(id self, SEL _cmd, UIApplication* launchOptions) { + NSLog(@"swizzled applicationDidBecomeActive"); + [[AppsFlyerLib shared] setDelegate:_AppsFlyerdelegate]; + + if(didEnteredBackGround && AppsFlyeriOSWarpper.didCallStart == YES){ + [[AppsFlyerLib shared] start]; + } + + if(__original_applicationDidBecomeActive_Imp){ + ((void(*)(id,SEL, UIApplication*))__original_applicationDidBecomeActive_Imp)(self, _cmd, launchOptions); + } +} + + +void __swizzled_applicationDidEnterBackground(id self, SEL _cmd, UIApplication* application) { + NSLog(@"swizzled applicationDidEnterBackground"); + didEnteredBackGround = YES; + if(__original_applicationDidEnterBackground_Imp){ + ((void(*)(id,SEL, UIApplication*))__original_applicationDidEnterBackground_Imp)(self, _cmd, application); + } +} + + +BOOL __swizzled_didReceiveRemoteNotification(id self, SEL _cmd, UIApplication* application, NSDictionary* userInfo,void (^UIBackgroundFetchResult)(void) ) { + NSLog(@"swizzled didReceiveRemoteNotification"); + + [[AppsFlyerLib shared] handlePushNotification:userInfo]; + + if(__original_didReceiveRemoteNotification_Imp){ + return ((BOOL(*)(id, SEL, UIApplication*, NSDictionary*, int(UIBackgroundFetchResult)))__original_didReceiveRemoteNotification_Imp)(self, _cmd, application, userInfo, nil); + } + return YES; +} + + + +BOOL __swizzled_openURL(id self, SEL _cmd, UIApplication* application, NSURL* url, NSDictionary * options) { + NSLog(@"swizzled openURL"); + [[AppsFlyerAttribution shared] handleOpenUrl:url options:options]; + if(__original_openUrl_Imp){ + return ((BOOL(*)(id, SEL, UIApplication*, NSURL*, NSDictionary*))__original_openUrl_Imp)(self, _cmd, application, url, options); + } + return NO; +} + + +@end + + + diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m.meta b/Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m.meta new file mode 100644 index 0000000..24856fa --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: 6ae9e1f7daef2427588fab2fbf8d35d5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.h b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.h new file mode 100644 index 0000000..879168d --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.h @@ -0,0 +1,16 @@ +// +// AppsFlyerAdRevenueWrapper.h +// Unity-iPhone +// +// Created by Jonathan Wesfield on 01/12/2019. +// + +#import + +#if __has_include() +#import +#endif + +@interface AppsFlyerAdRevenueWrapper : NSObject + +@end diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.h.meta b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.h.meta new file mode 100644 index 0000000..c7301b1 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.h.meta @@ -0,0 +1,27 @@ +fileFormatVersion: 2 +guid: 7fa891a95d71c459daa1e92ee7a653ab +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.mm b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.mm new file mode 100644 index 0000000..c2ff0ec --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.mm @@ -0,0 +1,51 @@ +// +// AppsFlyerAdRevenueWrapper.mm +// Unity-iPhone +// +// Created by Jonathan Wesfield on 25/11/2019. +// + +#import "AppsFlyerAdRevenueWrapper.h" + + +@implementation AppsFlyerAdRevenueWrapper + + +extern "C" { + + NSString* stringFromChar(const char *str) { + return str ? [NSString stringWithUTF8String:str] : nil; + } + + NSDictionary* dictionaryFromJson(const char *jsonString) { + if(jsonString){ + NSData *jsonData = [[NSData alloc] initWithBytes:jsonString length:strlen(jsonString)]; + NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; + return dictionary; + } + return nil; + } + + + const void _start(int length, int* adRevenueTypes){ + [AppsFlyerAdRevenue start]; + } + const void _setIsDebugAdrevenue(bool isDebug){ + [[AppsFlyerAdRevenue shared] setIsDebug:isDebug]; + } + + const void _logAdRevenue(const char* monetizationNetwork, + int mediationNetwork, + double eventRevenue, + const char* revenueCurrency, + const char* additionalParameters){ + [[AppsFlyerAdRevenue shared] logAdRevenueWithMonetizationNetwork:stringFromChar(monetizationNetwork) + mediationNetwork:(AppsFlyerAdRevenueMediationNetworkType) mediationNetwork + eventRevenue:[NSNumber numberWithDouble:eventRevenue] + revenueCurrency:stringFromChar(revenueCurrency) + additionalParameters:dictionaryFromJson(additionalParameters)]; + + } +} + +@end diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.mm.meta b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.mm.meta new file mode 100644 index 0000000..b864f3c --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAdRevenueWrapper.mm.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: 84d99cf0f930e4c80b4bc1858e042b70 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm new file mode 100644 index 0000000..e722cdd --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm @@ -0,0 +1,126 @@ +// +// AppsFlyerAppController.mm +// Unity-iPhone +// +// Created by Jonathan Wesfield on 30/07/2019. +// + +#import +#import "UnityAppController.h" +#import "AppDelegateListener.h" +#import "AppsFlyeriOSWrapper.h" +#if __has_include() +#import +#else +#import "AppsFlyerLib.h" +#endif +#import + +/** + Note if you would like to use method swizzeling see AppsFlyer+AppController.m + If you are using swizzeling then comment out the method that is being swizzeled in AppsFlyerAppController.mm + Only use swizzeling if there are conflicts with other plugins that needs to be resolved. +*/ + + +@interface AppsFlyerAppController : UnityAppController +{ + BOOL didEnteredBackGround; +} +@end + +@implementation AppsFlyerAppController + +- (instancetype)init +{ + self = [super init]; + if (self) { + + id swizzleFlag = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"AppsFlyerShouldSwizzle"]; + BOOL shouldSwizzle = swizzleFlag ? [swizzleFlag boolValue] : NO; + + if(!shouldSwizzle){ + UnityRegisterAppDelegateListener(self); + } + } + return self; +} + +- (void)didFinishLaunching:(NSNotification*)notification { + NSLog(@"got didFinishLaunching = %@",notification.userInfo); + + + if (_AppsFlyerdelegate == nil) { + _AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init]; + } + [[AppsFlyerLib shared] setDelegate:_AppsFlyerdelegate]; + + if (notification.userInfo[@"url"]) { + [self onOpenURL:notification]; + } +} + +-(void)didBecomeActive:(NSNotification*)notification { + NSLog(@"got didBecomeActive(out) = %@", notification.userInfo); + if (didEnteredBackGround == YES && AppsFlyeriOSWarpper.didCallStart == YES) { + [[AppsFlyerLib shared] start]; + didEnteredBackGround = NO; + } +} + +- (void)didEnterBackground:(NSNotification*)notification { + NSLog(@"got didEnterBackground = %@", notification.userInfo); + didEnteredBackGround = YES; +} + +- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler { + [[AppsFlyerAttribution shared] continueUserActivity:userActivity restorationHandler:restorationHandler]; + return YES; +} + + +- (void)onOpenURL:(NSNotification*)notification { + NSLog(@"got onOpenURL = %@", notification.userInfo); + NSURL *url = notification.userInfo[@"url"]; + NSString *sourceApplication = notification.userInfo[@"sourceApplication"]; + + if (sourceApplication == nil) { + sourceApplication = @""; + } + + if (url != nil) { + [[AppsFlyerAttribution shared] handleOpenUrl:url sourceApplication:sourceApplication annotation:nil]; + } + +} + +- (void)didReceiveRemoteNotification:(NSNotification*)notification { + NSLog(@"got didReceiveRemoteNotification = %@", notification.userInfo); + [[AppsFlyerLib shared] handlePushNotification:notification.userInfo]; +} + +@end + +/** +Note if you would not like to use IMPL_APP_CONTROLLER_SUBCLASS you can replace it with the code below. + + +(void)load + { + [AppsFlyerAppController plugin]; + } + + // Singleton accessor. + + (AppsFlyerAppController *)plugin + { + static AppsFlyerAppController *sharedInstance = nil; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + + sharedInstance = [[AppsFlyerAppController alloc] init]; + }); + + return sharedInstance; + } + + **/ diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm.meta b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm.meta new file mode 100644 index 0000000..2e8e52c --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: 2d1497a1493b24fecaa58bd3a7b707f9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h new file mode 100644 index 0000000..c79fec4 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h @@ -0,0 +1,34 @@ +// +// AppsFlyerAttribution.h +// UnityFramework +// +// Created by Margot Guetta on 11/04/2021. +// + +#ifndef AppsFlyerAttribution_h +#define AppsFlyerAttribution_h +#endif /* AppsFlyerAttribution_h */ +#if __has_include() +#import +#else +#import "AppsFlyerLib.h" +#endif + + +@interface AppsFlyerAttribution : NSObject +@property NSUserActivity*_Nullable userActivity; +@property (nonatomic, copy) void (^ _Nullable restorationHandler)(NSArray *_Nullable ); +@property NSURL * _Nullable url; +@property NSDictionary * _Nullable options; +@property NSString* _Nullable sourceApplication; +@property id _Nullable annotation; +@property BOOL isBridgeReady; + ++ (AppsFlyerAttribution *_Nullable)shared; +- (void) continueUserActivity: (NSUserActivity*_Nullable) userActivity restorationHandler: (void (^_Nullable)(NSArray * _Nullable))restorationHandler; +- (void) handleOpenUrl:(NSURL*_Nullable)url options:(NSDictionary*_Nullable) options; +- (void) handleOpenUrl: (NSURL *_Nonnull)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation; + +@end + +static NSString * _Nullable const AF_BRIDGE_SET = @"bridge is set"; diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h.meta b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h.meta new file mode 100644 index 0000000..5b77c9b --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h.meta @@ -0,0 +1,27 @@ +fileFormatVersion: 2 +guid: 8544dc3b3c7bb40d397b2de568df1058 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m new file mode 100644 index 0000000..c4e7278 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m @@ -0,0 +1,86 @@ +// +// NSObject+AppsFlyerAttribution.m +// UnityFramework +// +// Created by Margot Guetta on 11/04/2021. +// + +#import +#import "AppsFlyerAttribution.h" + +@implementation AppsFlyerAttribution + ++ (id)shared { + static AppsFlyerAttribution *shared = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shared = [[self alloc] init]; + }); + return shared; +} + +- (id)init { + if (self = [super init]) { + self.options = nil; + self.restorationHandler = nil; + self.url = nil; + self.userActivity = nil; + self.annotation = nil; + self.sourceApplication = nil; + self.isBridgeReady = NO; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(receiveBridgeReadyNotification:) + name:AF_BRIDGE_SET + object:nil]; + } + return self; +} + +- (void) continueUserActivity: (NSUserActivity*_Nullable) userActivity restorationHandler: (void (^_Nullable)(NSArray * _Nullable))restorationHandler{ + if(self.isBridgeReady == YES){ + [[AppsFlyerLib shared] continueUserActivity:userActivity restorationHandler:restorationHandler]; + }else{ + [AppsFlyerAttribution shared].userActivity = userActivity; + [AppsFlyerAttribution shared].restorationHandler = restorationHandler; + } +} + +- (void) handleOpenUrl:(NSURL *)url options:(NSDictionary *)options{ + if(self.isBridgeReady == YES){ + [[AppsFlyerLib shared] handleOpenUrl:url options:options]; + }else{ + [AppsFlyerAttribution shared].url = url; + [AppsFlyerAttribution shared].options = options; + } +} + +- (void) handleOpenUrl:(NSURL *)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation{ + if(self.isBridgeReady == YES){ + [[AppsFlyerLib shared] handleOpenURL:url sourceApplication:sourceApplication withAnnotation:annotation]; + }else{ + [AppsFlyerAttribution shared].url = url; + [AppsFlyerAttribution shared].sourceApplication = sourceApplication; + [AppsFlyerAttribution shared].annotation = annotation; + } + +} + +- (void) receiveBridgeReadyNotification:(NSNotification *) notification +{ + NSLog (@"AppsFlyer Debug: handle deep link"); + if(self.url && self.sourceApplication){ + [[AppsFlyerLib shared] handleOpenURL:self.url sourceApplication:self.sourceApplication withAnnotation:self.annotation]; + self.url = nil; + self.sourceApplication = nil; + self.annotation = nil; + }else if(self.options && self.url){ + [[AppsFlyerLib shared] handleOpenUrl:self.url options:self.options]; + self.options = nil; + self.url = nil; + }else if(self.userActivity){ + [[AppsFlyerLib shared] continueUserActivity:self.userActivity restorationHandler:nil]; + self.userActivity = nil; + self.restorationHandler = nil; + } +} +@end diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m.meta b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m.meta new file mode 100644 index 0000000..9f071e6 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: 1060e47d7b9e2453ba575f0b455b2bf8 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h new file mode 100644 index 0000000..d4cd3c3 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h @@ -0,0 +1,50 @@ +// +// AppsFlyeriOSWarpper.h +// Unity-iPhone +// +// Created by Jonathan Wesfield on 24/07/2019. +// + +#import "AFUnityUtils.mm" +#import "UnityAppController.h" +#import "AppsFlyerAttribution.h" +#if __has_include() +#import +#else +#import "AppsFlyerLib.h" +#endif + +@interface AppsFlyeriOSWarpper : NSObject ++ (BOOL) didCallStart; ++ (void) setDidCallStart:(BOOL)val; +@end + + +static AppsFlyeriOSWarpper *_AppsFlyerdelegate; +static const int kPushNotificationSize = 32; + +static NSString* ConversionDataCallbackObject = @"AppsFlyerObject"; + +static const char* VALIDATE_CALLBACK = "didFinishValidateReceipt"; +static const char* VALIDATE_ERROR_CALLBACK = "didFinishValidateReceiptWithError"; +static const char* GCD_CALLBACK = "onConversionDataSuccess"; +static const char* GCD_ERROR_CALLBACK = "onConversionDataFail"; +static const char* OAOA_CALLBACK = "onAppOpenAttribution"; +static const char* OAOA_ERROR_CALLBACK = "onAppOpenAttributionFailure"; +static const char* GENERATE_LINK_CALLBACK = "onInviteLinkGenerated"; +static const char* OPEN_STORE_LINK_CALLBACK = "onOpenStoreLinkGenerated"; +static const char* START_REQUEST_CALLBACK = "requestResponseReceived"; +static const char* IN_APP_RESPONSE_CALLBACK = "inAppResponseReceived"; +static const char* ON_DEEPLINKING = "onDeepLinking"; +static const char* VALIDATE_AND_LOG_V2_CALLBACK = "onValidateAndLogComplete"; +static const char* VALIDATE_AND_LOG_V2_ERROR_CALLBACK = "onValidateAndLogFailure"; + + +static NSString* validateObjectName = @""; +static NSString* openStoreObjectName = @""; +static NSString* generateInviteObjectName = @""; +static NSString* validateAndLogObjectName = @""; +static NSString* startRequestObjectName = @""; +static NSString* inAppRequestObjectName = @""; +static NSString* onDeeplinkingObjectName = @""; + diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h.meta b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h.meta new file mode 100644 index 0000000..5284989 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h.meta @@ -0,0 +1,27 @@ +fileFormatVersion: 2 +guid: 147104b04b5794eaa92b4195cc328e13 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm new file mode 100644 index 0000000..1af3464 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm @@ -0,0 +1,370 @@ +// +// AppsFlyeriOSWarpper.mm +// Unity-iPhone +// +// Created by Jonathan Wesfield on 24/07/2019. +// + +#import "AppsFlyeriOSWrapper.h" + + +static void unityCallBack(NSString* objectName, const char* method, const char* msg) { + if(objectName){ + UnitySendMessage([objectName UTF8String], method, msg); + } +} + +extern "C" { + + const void _startSDK(bool shouldCallback, const char* objectName) { + [[AppsFlyerLib shared] setPluginInfoWith: AFSDKPluginUnity + pluginVersion:@"6.14.3" + additionalParams:nil]; + startRequestObjectName = stringFromChar(objectName); + AppsFlyeriOSWarpper.didCallStart = YES; + [AppsFlyerAttribution shared].isBridgeReady = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:AF_BRIDGE_SET object: [AppsFlyerAttribution shared]]; + [[AppsFlyerLib shared] startWithCompletionHandler:^(NSDictionary *dictionary, NSError *error) { + if(shouldCallback){ + if (error) { + NSDictionary *callbackDictionary = @{@"statusCode":[NSNumber numberWithLong:[error code]]}; + unityCallBack(startRequestObjectName, START_REQUEST_CALLBACK, stringFromdictionary(callbackDictionary)); + return; + } + if (dictionary) { + unityCallBack(startRequestObjectName, START_REQUEST_CALLBACK, stringFromdictionary(dictionary)); + return; + } + } + }]; + } + + const void _setCustomerUserID (const char* customerUserID) { + [[AppsFlyerLib shared] setCustomerUserID:stringFromChar(customerUserID)]; + } + + const void _setAdditionalData (const char* customData) { + [[AppsFlyerLib shared] setAdditionalData:dictionaryFromJson(customData)]; + } + + const void _setAppsFlyerDevKey (const char* appsFlyerDevKey) { + [AppsFlyerLib shared].appsFlyerDevKey = stringFromChar(appsFlyerDevKey); + } + + const void _setAppleAppID (const char* appleAppID) { + [AppsFlyerLib shared].appleAppID = stringFromChar(appleAppID); + } + + const void _setCurrencyCode (const char* currencyCode) { + [[AppsFlyerLib shared] setCurrencyCode:stringFromChar(currencyCode)]; + } + + const void _setDisableCollectAppleAdSupport (bool disableAdvertisingIdentifier) { + [AppsFlyerLib shared].disableAdvertisingIdentifier = disableAdvertisingIdentifier; + } + + const void _setIsDebug (bool isDebug) { + [AppsFlyerLib shared].isDebug = isDebug; + } + + const void _setShouldCollectDeviceName (bool shouldCollectDeviceName) { + [AppsFlyerLib shared].shouldCollectDeviceName = shouldCollectDeviceName; + } + + const void _setAppInviteOneLinkID (const char* appInviteOneLinkID) { + [[AppsFlyerLib shared] setAppInviteOneLink:stringFromChar(appInviteOneLinkID)]; + } + + const void _setDeepLinkTimeout (long deepLinkTimeout) { + [AppsFlyerLib shared].deepLinkTimeout = deepLinkTimeout; + } + + const void _anonymizeUser (bool anonymizeUser) { + [AppsFlyerLib shared].anonymizeUser = anonymizeUser; + } + + const void _enableTCFDataCollection (bool shouldCollectTcfData) { + [[AppsFlyerLib shared] enableTCFDataCollection:shouldCollectTcfData]; + } + + const void _setConsentData(bool isUserSubjectToGDPR, bool hasConsentForDataUsage, bool hasConsentForAdsPersonalization) { + AppsFlyerConsent *consentData = nil; + if (isUserSubjectToGDPR) { + consentData = [[AppsFlyerConsent alloc] initForGDPRUserWithHasConsentForDataUsage:hasConsentForDataUsage hasConsentForAdsPersonalization:hasConsentForAdsPersonalization]; + } else { + consentData = [[AppsFlyerConsent alloc] initNonGDPRUser]; + } + [[AppsFlyerLib shared] setConsentData:consentData]; + } + + const void _setDisableCollectIAd (bool disableCollectASA) { + [AppsFlyerLib shared].disableCollectASA = disableCollectASA; + } + + const void _setUseReceiptValidationSandbox (bool useReceiptValidationSandbox) { + [AppsFlyerLib shared].useReceiptValidationSandbox = useReceiptValidationSandbox; + } + + const void _setUseUninstallSandbox (bool useUninstallSandbox) { + [AppsFlyerLib shared].useUninstallSandbox = useUninstallSandbox; + } + + const void _setResolveDeepLinkURLs (int length, const char **resolveDeepLinkURLs) { + if(length > 0 && resolveDeepLinkURLs) { + [[AppsFlyerLib shared] setResolveDeepLinkURLs:NSArrayFromCArray(length, resolveDeepLinkURLs)]; + } + } + + const void _setOneLinkCustomDomains (int length, const char **oneLinkCustomDomains) { + if(length > 0 && oneLinkCustomDomains) { + [[AppsFlyerLib shared] setOneLinkCustomDomains:NSArrayFromCArray(length, oneLinkCustomDomains)]; + } + } + + const void _afSendEvent (const char* eventName, const char* eventValues, bool shouldCallback, const char* objectName) { + inAppRequestObjectName = stringFromChar(objectName); + [[AppsFlyerLib shared] logEventWithEventName:stringFromChar(eventName) eventValues:dictionaryFromJson(eventValues) completionHandler:^(NSDictionary *dictionary, NSError *error) { + if(shouldCallback){ + if (error) { + NSDictionary *callbackDictionary = @{@"statusCode":[NSNumber numberWithLong:[error code]]}; + unityCallBack(inAppRequestObjectName, IN_APP_RESPONSE_CALLBACK, stringFromdictionary(callbackDictionary)); + return; + } + if (dictionary) { + unityCallBack(inAppRequestObjectName, IN_APP_RESPONSE_CALLBACK, stringFromdictionary(dictionary)); + return; + } + } + }]; + } + + const void _recordLocation (double longitude, double latitude) { + [[AppsFlyerLib shared] logLocation:longitude latitude:latitude]; + } + + const char* _getAppsFlyerId () { + return getCString([[[AppsFlyerLib shared] getAppsFlyerUID] UTF8String]); + } + + const void _registerUninstall (unsigned char* deviceToken) { + if(deviceToken){ + NSData* tokenData = [NSData dataWithBytes:(const void *)deviceToken length:sizeof(unsigned char)*kPushNotificationSize]; + [[AppsFlyerLib shared] registerUninstall:tokenData]; + } + } + + const void _handlePushNotification (const char* pushPayload) { + [[AppsFlyerLib shared] handlePushNotification:dictionaryFromJson(pushPayload)]; + } + + const char* _getSDKVersion () { + return getCString([[[AppsFlyerLib shared] getSDKVersion] UTF8String]); + } + + const void _setHost (const char* host, const char* hostPrefix) { + [[AppsFlyerLib shared] setHost:stringFromChar(host) withHostPrefix:stringFromChar(hostPrefix)]; + } + + const void _setMinTimeBetweenSessions (int minTimeBetweenSessions) { + [AppsFlyerLib shared].minTimeBetweenSessions = minTimeBetweenSessions; + } + + const void _stopSDK (bool isStopped) { + [AppsFlyerLib shared].isStopped = isStopped; + } + + const BOOL _isSDKStopped () { + return [AppsFlyerLib shared].isStopped; + } + + const void _handleOpenUrl(const char *url, const char *sourceApplication, const char *annotation) { + [[AppsFlyerLib shared] handleOpenURL:[NSURL URLWithString:stringFromChar(url)] sourceApplication:stringFromChar(sourceApplication) withAnnotation:stringFromChar(annotation)]; } + + const void _recordCrossPromoteImpression (const char* appID, const char* campaign, const char* parameters) { + [AppsFlyerCrossPromotionHelper logCrossPromoteImpression:stringFromChar(appID) campaign:stringFromChar(campaign) parameters:dictionaryFromJson(parameters)]; } + + const void _attributeAndOpenStore (const char* appID, const char* campaign, const char* parameters, const char* objectName) { + + openStoreObjectName = stringFromChar(objectName); + + [AppsFlyerCrossPromotionHelper + logAndOpenStore:stringFromChar(appID) + campaign:stringFromChar(campaign) + parameters:dictionaryFromJson(parameters) + openStore:^(NSURLSession * _Nonnull urlSession, NSURL * _Nonnull clickURL) { + unityCallBack(openStoreObjectName, OPEN_STORE_LINK_CALLBACK, [clickURL.absoluteString UTF8String]); + }]; + } + + const void _generateUserInviteLink (const char* parameters, const char* objectName) { + + generateInviteObjectName = stringFromChar(objectName); + + [AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:^AppsFlyerLinkGenerator * _Nonnull(AppsFlyerLinkGenerator * _Nonnull generator) { + return generatorFromDictionary(dictionaryFromJson(parameters), generator); + } completionHandler:^(NSURL * _Nullable url) { + unityCallBack(generateInviteObjectName, GENERATE_LINK_CALLBACK, [url.absoluteString UTF8String]); + }]; + } + + const void _recordInvite (const char* channel, const char* parameters) { + [AppsFlyerShareInviteHelper logInvite:stringFromChar(channel) parameters:dictionaryFromJson(parameters)]; + } + + const void _setUserEmails (int emailCryptTypeInt , int length, const char **userEmails) { + if(length > 0 && userEmails) { + [[AppsFlyerLib shared] setUserEmails:NSArrayFromCArray(length, userEmails) withCryptType:emailCryptTypeFromInt(emailCryptTypeInt)]; + } + } + + const void _setPhoneNumber (const char* phoneNumber) { + [[AppsFlyerLib shared] setPhoneNumber:stringFromChar(phoneNumber)]; + } + + const void _setSharingFilterForAllPartners () { + [[AppsFlyerLib shared] setSharingFilterForAllPartners]; + } + + const void _setSharingFilter (int length, const char **partners) { + if(length > 0 && partners) { + [[AppsFlyerLib shared] setSharingFilter:NSArrayFromCArray(length, partners)]; + } + } + + const void _setSharingFilterForPartners (int length, const char **partners) { + if(length > 0 && partners) { + [[AppsFlyerLib shared] setSharingFilterForPartners:NSArrayFromCArray(length, partners)]; + } else { + [[AppsFlyerLib shared] setSharingFilterForPartners:nil]; + } + } + + const void _validateAndSendInAppPurchase (const char* productIdentifier, const char* price, const char* currency, const char* transactionId, const char* additionalParameters, const char* objectName) { + + validateObjectName = stringFromChar(objectName); + + [[AppsFlyerLib shared] + validateAndLogInAppPurchase:stringFromChar(productIdentifier) + price:stringFromChar(price) + currency:stringFromChar(currency) + transactionId:stringFromChar(transactionId) + additionalParameters:dictionaryFromJson(additionalParameters) + success:^(NSDictionary *result){ + unityCallBack(validateObjectName, VALIDATE_CALLBACK, stringFromdictionary(result)); + } failure:^(NSError *error, id response) { + if(response && [response isKindOfClass:[NSDictionary class]]) { + NSDictionary* value = (NSDictionary*)response; + unityCallBack(validateObjectName, VALIDATE_ERROR_CALLBACK, stringFromdictionary(value)); + } else { + unityCallBack(validateObjectName, VALIDATE_ERROR_CALLBACK, error ? [[error localizedDescription] UTF8String] : "error"); + } + }]; + } + + const void _validateAndSendInAppPurchaseV2 (const char* product, const char* price, const char* currency, const char* transactionId, const char* extraEventValues, const char* objectName) { + + validateAndLogObjectName = stringFromChar(objectName); + AFSDKPurchaseDetails *details = [[AFSDKPurchaseDetails alloc] initWithProductId:stringFromChar(product) price:stringFromChar(price) currency:stringFromChar(currency) transactionId:stringFromChar(transactionId)]; + + [[AppsFlyerLib shared] + validateAndLogInAppPurchase:details + extraEventValues:dictionaryFromJson(extraEventValues) + completionHandler:^(AFSDKValidateAndLogResult * _Nullable result) { + if (result.status == AFSDKValidateAndLogStatusSuccess) { + unityCallBack(validateAndLogObjectName, VALIDATE_AND_LOG_V2_CALLBACK, stringFromdictionary(result.result)); + } else if (result.status == AFSDKValidateAndLogStatusFailure) { + unityCallBack(validateAndLogObjectName, VALIDATE_AND_LOG_V2_CALLBACK, stringFromdictionary(result.errorData)); + } else { + unityCallBack(validateAndLogObjectName, VALIDATE_AND_LOG_V2_ERROR_CALLBACK, stringFromdictionary(dictionaryFromNSError(result.error))); + } + }]; + + } + + const void _getConversionData(const char* objectName) { + if (_AppsFlyerdelegate == nil) { + _AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init]; + } + ConversionDataCallbackObject = stringFromChar(objectName); + [[AppsFlyerLib shared] setDelegate:_AppsFlyerdelegate]; + } + + const void _waitForATTUserAuthorizationWithTimeoutInterval (int timeoutInterval) { + [[AppsFlyerLib shared] waitForATTUserAuthorizationWithTimeoutInterval:timeoutInterval]; + } + + const void _disableSKAdNetwork (bool isDisabled) { + [AppsFlyerLib shared].disableSKAdNetwork = isDisabled; + } + + const void _addPushNotificationDeepLinkPath (int length, const char **paths) { + if(length > 0 && paths) { + [[AppsFlyerLib shared] addPushNotificationDeepLinkPath:NSArrayFromCArray(length, paths)]; + } + } + + const void _subscribeForDeepLink (const char* objectName) { + + onDeeplinkingObjectName = stringFromChar(objectName); + + if (_AppsFlyerdelegate == nil) { + _AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init]; + } + [[AppsFlyerLib shared] setDeepLinkDelegate:_AppsFlyerdelegate]; + } + + const void _setCurrentDeviceLanguage(const char* language) { + [[AppsFlyerLib shared] setCurrentDeviceLanguage:stringFromChar(language)]; + } + + const void _setPartnerData(const char* partnerId, const char* partnerInfo) { + [[AppsFlyerLib shared] setPartnerDataWithPartnerId: stringFromChar(partnerId) partnerInfo:dictionaryFromJson(partnerInfo)]; + } + + const void _disableIDFVCollection(bool isDisabled) { + [AppsFlyerLib shared].disableIDFVCollection = isDisabled; + } + +} + +@implementation AppsFlyeriOSWarpper + +static BOOL didCallStart; ++ (BOOL) didCallStart +{ @synchronized(self) { return didCallStart; } } ++ (void) setDidCallStart:(BOOL)val +{ @synchronized(self) { didCallStart = val; } } + +- (void)onConversionDataSuccess:(NSDictionary *)installData { + unityCallBack(ConversionDataCallbackObject, GCD_CALLBACK, stringFromdictionary(installData)); +} + +- (void)onConversionDataFail:(NSError *)error { + unityCallBack(ConversionDataCallbackObject, GCD_ERROR_CALLBACK, [[error localizedDescription] UTF8String]); +} + +- (void)onAppOpenAttribution:(NSDictionary *)attributionData { + unityCallBack(ConversionDataCallbackObject, OAOA_CALLBACK, stringFromdictionary(attributionData)); +} + +- (void)onAppOpenAttributionFailure:(NSError *)error { + unityCallBack(ConversionDataCallbackObject, OAOA_ERROR_CALLBACK, [[error localizedDescription] UTF8String]); +} + +- (void)didResolveDeepLink:(AppsFlyerDeepLinkResult *)result{ + + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + + [dict setValue:stringFromDeepLinkResultError(result) forKey:@"error"]; + [dict setValue:stringFromDeepLinkResultStatus(result.status) forKey:@"status"]; + + if(result && result.deepLink){ + [dict setValue:result.deepLink.description forKey:@"deepLink"]; + [dict setValue:@(result.deepLink.isDeferred) forKey:@"is_deferred"]; + } + + unityCallBack(onDeeplinkingObjectName, ON_DEEPLINKING, stringFromdictionary(dict)); +} + +@end + diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm.meta b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm.meta new file mode 100644 index 0000000..3799161 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: 2bff3788f3d8747fe9679bd3818e1d76 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Plugins/iOS/SwiftForUnity.swift b/Assets/AppsFlyer/Plugins/iOS/SwiftForUnity.swift new file mode 100644 index 0000000..521d0e4 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/SwiftForUnity.swift @@ -0,0 +1 @@ +import Foundation \ No newline at end of file diff --git a/Assets/AppsFlyer/Plugins/iOS/SwiftForUnity.swift.meta b/Assets/AppsFlyer/Plugins/iOS/SwiftForUnity.swift.meta new file mode 100644 index 0000000..b24f741 --- /dev/null +++ b/Assets/AppsFlyer/Plugins/iOS/SwiftForUnity.swift.meta @@ -0,0 +1,37 @@ +fileFormatVersion: 2 +guid: a631431c30cca4ac2bb4b40fc67e4005 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Tests.meta b/Assets/AppsFlyer/Tests.meta new file mode 100644 index 0000000..8217a6a --- /dev/null +++ b/Assets/AppsFlyer/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f19f272c71674582bed1d93925da003 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Tests/Castle.Core.dll b/Assets/AppsFlyer/Tests/Castle.Core.dll new file mode 100644 index 0000000000000000000000000000000000000000..268e311c52a8240efd3f50806f391bf05ba3ba9f GIT binary patch literal 442368 zcmb@v34mNxmH+?xy{cE$RozW0-Kow3>1OHhsHzSSc9c~`K@f1k5EKH65)>X*5l2&2 z867te0-}P(1&sRwt{~z%C@!eb>gYI%K^#}y7j$OS`2T#*eXri@PGFed{2NktJNMpm z&pr3tbI)DgDeJEG0?+db{QJj0JnvRq{T*w+5B;;57U82|cguVlVs_{%QO_#Pz&I=Jy@mim+IDrc0hj{MWt_ z(ysL{7pVTv+$5+d{_2!_syvi?wTQ6OU&$LG?$~dJ-jjDqdx(hX0qO=+Cj7V@`07i~ zf5D}M7kw;gm)Z*6`M+t;Tfe&9X+MKV!%b~hLvPhj_IE7kt!|(H+!#RN>UoX^-e-1# zJKmCWKPQQ<{0TSTD|+i6<9p@H3*NBBdfo+hhu&K7`W*D!oWwnpv(oRr((@_}+*ipx z!;db*^@E_58^4-})?{>r#Vc=U z<;GXyZPXjzoc^z+Z~V*jeouMIJJ;nh$6H8Vn?z@M9R(zQB$DTHHrILxf$IQ4c#m@qZ?xuy1}`5x(PJ2a^}-b zdBd)LGrFDnpPzc^Ji00KF6d^tc15?N=Fv^L{~zh58vdW@c9XxP2e%gnY*taA&@0L* z_F&_JKUV0$7 z9dz2{A|1e1KYl!gZr?2}^-L@E9^o*A%=5iHyvLpI?It`{`kl?AATWMF(Z(^Nu9j3V zTW+r(@-C?~!}fdRIvT{Ur@H7`e&Xx+X{|`2-=M%)`_DjD+he|W$w+ggeK2mdeVRh; z7xBA18Bd`GhLLpJ%+k`fnPuf|(HkkCvz4Ds?I3=WN?RPnZ^m_<62Ap+BWOIak0>h? z42}4$#MO5UHA4P7J5Yw}l_An^bb~U~8*5xJew%_T9X~YgT6X0!8`*Oj;L$eHKxuAm z7Fas>--EzrRoOr`l{_HqFXgL3ajY;_91A;dr-&YWQGl5i%PDMWl?xG4q}eR?p>?4* zu4tbO5fY}^gQEy4bHu1^_Q0gjSmy^SvOh+^az&B&L(%=wG)_fW^z-LMFU+*!fY93n z0&rTb^G@)qbl$~pwexO%N6bI!$L}E!%~HvDp;p+qAB`R_)`~}di)Ir3JK>qxYWt}L zIPJZFZkmbThcjM`-;Wc2K>pIs<4@p(@ooH;%wLW_iGSGq9qS|T-d$tvZ11gqbJH;6Z)oQD zA(%>XTcZ)0Xxwe28-|$gDECv8GF3UK6vm&%*YH#M@i$fOSr$<_66 zYI^lE5C0Cy{-p;{O#B(kcj^B4tEKp}gf@zXGb2YpV6PN^PBDU<89m~9Vus^?AtnMo zJmM+~tArz7hPOOyrNy@s(Fj_X`j;L^KJkm?i9b&~{x9IfckmN^k)QEm9XcnmM(0v< znr;xC>y8b|wPLMIW4}aHEu35nyz98xf1BTHwPK@v`=EE747=Hz{gI>RI^X2c90SS? z<><>4DCw>7sBs&3Pp29B3ugU#!w(MfCy~+`r-A*(Um-{9D8H*Q8rW|iNm+=Hht1ZE z-_>9Z>^C|X3bhvdU5(ekek}@7b4#xDd7|j6D%~o+l#ccz$QKGP-#gx+#e5)SOh`>% z$(UW|P>Bu!^4v5=NJNL`V}yf?fk8CCoKJaWiEZLSQ1(%aY3*emoC&kQyTbf*3Ed^UPthpy_e58J* zb!%VjgAy+Jj?H2FvN^8NlH4?^dOa~ zB#Jbh#XNAiCEVr*(WA)g7ox|=vDl!qb;t{0UxCJ5{DortCY;8u!3)LC^$Rk@HwgUp zU6=l?1;E9^SRww7GJIy&8SYz}XRX_TjkEmJEzF2X7^f*wMEwwKp)GW4-sYtiFj$f3>f1}d)yZnUF zzw_&8!Elq3m(t>UB(UI$Zor*g+`hHyUE(`xe4iLf`~or6_MQAXDwT{(VRQoZj+7%o zHE#0bdvN=|^}WK(?BuHcZ}990Uj-j`en7&^W~D?$#HM&Ox>uR#qeAq(f=ix|bFHQN|JVceQX zYRpebMDbZ%iGPN#by}^`YPC-t@h&0l=ft2JF;Q1c-X!Ho^jMFNSDWMQOGXE<(Jx4m zzSRCJk)8VqZK7-xmtW$om6>c&(Q2hF8;;q8l2kSUeB^I;pf6R*t+4Ebd_s%^U)cGT ziW@1#zs8M!qrhnMq{XArZ{;1UjX5$LUK?vK8}lxSf2Zi(Y9qDX`qx3uh*_`MTGZZ` zv>ZZ8kN*JZDoXkz?(B`*#}<$7s6Rtu6@gi~C+z<|={*(qo4AZs`&;9xi2oZoihi(54^9g;02)#qqY*tECq6;T>gktv&=9x-_n$Zlcq5VJ3&w6E+ zRVlm9ibO$4Xf`I1rGfW4sEG!odEF5qpo(g91KLOd-_#!Ay3v{0(N&9!JC6H=)!Jw=*#LuvLmu;q2O8jQN#i6jUotY$ z%_p!Rkas%CE6U{Zx;2{1Ye_C|e+hY``k;Ulf>z0oZc(TC(Z{Xt#M@7%-n!MRerZ+P zql;)M951ttx(`Jog#RWf$e}+GA%7~ZQQx18Zl#=_+T@Z(Ol1wDWdPh$PIz;7uk|?B ze${u}puU|7SNpQU>#lG`x~4BEoN`iqxOGTce!<&9{G{3wM4te;N-$gYwJHyrp|5p( zSoOPN#MYV7aVnJOQm`|g|FcXo{Xmnl;S-V<#6@9y}aq;z5S0OC|+FyuJn7YvllQkLZmD1 z2h*-bMZ7oBm7ujKjBWz2&OQX=8GaacHtx&ViTxx{IA~V;mXap;^G6qMqssTF0c-8ADXtZ(dMAyf0{6dLpew zL3FgYieoHKl@aEPq{1ZopL5xT$-M09LX=L6x9sI;KQ%HeM-5y*j6MYf>$4`IvePle zYs|5=&K6{TB@B9hLg0s;77)D$@H&YQ?g+2aoG?ptyqce|Yj9nGLK6?rhGguW z;T`jOH!nO3S*j6^MKU-ix*1xrNI8PMjWgQAOT0@qOXjx^luv@6>0(l5xn#|Uof4)s zTT-|y)%jh1=Sa%x&5|{d_t|Pl3*C_McqfjQlE~~Z`ho(`Q~JlNaP_xyAwl~YU^ItN zcchIUK`obBP^I}n`y!>Y0M4gd@M|vp#Y%r7bTRqv@+;VD3DuyD(f5-0k(3%8r5~Yc z>!*Xk2Q3?ZUk%`F6Y?oX=gk206t#V6rTuF%hw;(M_9ogdV7yr_!{|efT zbpcc4Nu)XOH2OA0KWz{l*wO?|`(l-1@$*V~t84RYHCZfK4;j@1Q;PiwBYflH1g=zv zF5XZhAr<1jf^ot!w027(rMcF31lYfzzhv$kabfj=u8aIlb=~Mow8ad5Ocm;%P?ona zIu4SXGHiV`v18~8)SRI(R*$8j9MGKQ)Nd~G>lUfsT;$yrso$uAx~DoOQ#?0;Cj+tO z8&(dV*`VHBl(5eAG|bdXQ$HR1D1B&hZ4x643?hwC?M{{m5Mio_c@TyQqo=u+Ic9a| z4$?O_#V~g!HlH;F2KwAV7J%_F3j6IZ(y7ZjKQGdldx>fsI<>xYyhg?>dYgv*5yVEQ zR$=1_em&57IP4rbh=Vm%c;ks|QCKZq6(7XUQU($gYFzHmtxJb;VD_!P&?`hg2I`$k zYHZpGq)^NyAFWLZ<#CaSxnM$j8d~3mjT1;MT5=i#&lEkh0}mxfa{mU%&d~VHfT@eH z_@bpL=Z`74au7@mJ&zItEovW5yvu29U$g~tB?#k3D}6<~PkLaBX_F?dSOY~)sm2J^ z9UEHv%K%33Ao8yevfYA~ij9KJnnLt5nt?@KV4Hfe^IORP#aTW=L8aG z3O250-0-RtjiXy5q4QW;*vL`rSEA8__JL9#q7SmkS{96mp!ES~&^}p|JdYDBBicr?uBVlWz z6hD!g>RZd!@$r)gG)gYuxZv#ksEB?)=&AYfe;C9+KL_8()KCe`n342v+Yc<#M#|)s z$S!}TUf3pchX!{p(dEkVkb{AztN>IH%L9LEoV_67(_M|TvBJY2Sr0K>iqRqsmWeS0 zfW`{@W7$}_Wv5nWGRDm{g?Pt+M(^4+G}d&@O2r)H*#oiS(hx2xW69pHs+Qh$%E|#}YgfU!-=p?=L z!RRDG|9>Y_F~S&OR4PW;DWFjS8fkaF1R?_(6&#JU26+oOu}G{jAP0%{DNe+#nE6Ur>*F$ZVzL2sF7}B>^9iMC>Y-*yBNR7 z+g`|?*aoWJidD`wp#9885I+s=%ofjj(9Lj#Y*sXiGyQ!8ObY32=sd}6$oL67)PE}{ z$a3cAQ+76KX~;zCJcEfe`XSNURk}c<{{%k`)72L$=IB98{G0{h=Pn3uP#J9!V?2|uyHN4311zWFhe2jE@BLYeW@8D9oH{r@3$}?y z&=^@ozecO*rz>KVh-zsfI)?z-(l=D|diqExYht}F9%mGwU(CrgE)5}Zgn=i^HfWT5-bk2(&}hwYu##@ zU{P?woa(cMp>IkU6pb+R&~?5$N~G;K)(&U;vU!EAVlZ*~WFzn+>^$M=b@Wo(pcB7o z9V?f`ZLM>S*&F=cU!Yf?m1H68$_tHND;hlm+~Q{%8OY~*=a6q-Yu~lt&y;k&$N>?a zg^NaSSjW#MKugEN_<|&PgOUrA&7t~87+#<#EPjWq!4OZi4?cVj}36bj}4GbZxx{^rs3#EP`gdD!FvOXn^fpfLc47V36GiI>eFd;+Lg!7PdZmg`^3)|;g6f2^uhtH z7`S=rzKMhZA3cB2eU6VFH6QlwK_QP;Le{NXxTY09W`3UE8cwdqPavtUZr{x4D)a@p z`EmR-?w>m&9W?FTrg9^K$tWFIlXL%-!XzW&L}k^uLJ79NIXEX7SBK?Gc_59}SY^GN z6zSS{5~Vz>jO?Mz%lP<*n=ur+|` zGPj>IfIC$MWC>T1Fc4@DLL>y*LW&^~3ytk_t#rJ#ucw@;rLK=pR~1>(dvi%oRK6qq z=%3(EtTRtm5Q~ht=xM&!1b0R;^Yi{l=gtd&t8`w-Zy0al_tFbt&uU&lE2Za5M!fN< zbnm8Ua}(sKb-GyzLHr^ssK;-$|0L?3wDr|Yy|k^X9CD>`h?$=uf!Q2Gfi(B z9Ps%m>)WAe%2}HBq%&(P*gMPWjoB3ld+X$nFv5lCKV2afn5lcR9=(M2nr=nEyM4#@ zK@=H{(V9xwKO5NirNFetIF|A>D+kj%^KBnxWv3+e5!gPObbxFbC`h@fPK1_KGn)C` zwJORQ=68jv9qF=TT-w6H4zG;L_geD9ju;kC6<#7?#cyAf`l~^IJ=xv<=9m>8cD@DB zNb|8l|Gb@&?zW^>&_8#lr28zX)_x6T2d0m>?ay*4kEopli~d<;1HZuZng#8$^KA3- zyveZ6wX5hMf$b08c-o#cY&Qtrdpbz@UHxL&%Ijku!pg zIMUdNm>6XyYn>9N2Rox=>FO`m^`xS$*y`fCvH02AttH{SX zhy4%5n-Yzl_Hrtyc3#16azwj6UT8kPR4Z(?^Se5nZF*j4Ydv;NjO(1?v4ZnTavHOa zhn%mCUqx`3Gqzf9)i~FrRVSx@*4*T3EytG$z%6ty$GghW9)YCuZQv%(Y)$y>H>+*6 zq-~g6;YK6p?5y9uNok8oW9L`wXN};12U=!0l2lZRT=753HP;GFX2+R{=+)HETIN%f z*0};d+vB245MN24F)yPiy;H^)?zPK|?POqPhHaydGo(6MvR@|7SODDdcD%zH#jZy!}uBis#N$| z+--$HRD?A(+{Ur$3TP_ge5DUM7s|W?H$Ez6{-bu#EfohNPiBM+9^}f4Pd5Ysl_(u}{&SQ&}woN2Pd^l7%x2qU)R#=ymiANB#KLxoc^ zJ&GB26Ejda7-X~JFEz zt`Gcfh3u<`8tp~<5cxVP+qBJPm_>9>sS3-U0baQ(1zd>9GaV+PP}l$yg%eE9Q{^C; zf^e9`7PTu9cMrKI`F6U)njA!y1-ghnNHmXSW3BT+vpEF4VR|$4dlfld{SG#*mhP7} zZt+mqH8=x^-b>d0`Jhz7Lh&I2og2iIZ&T-KF8DZg98Mh*h>2}Pvb!3;9hcynA&ZPG zug9%UjFcSbAb|&lzEboKLNncW^6N(ox8`W~-S~&MasninIw0DgGiBq2ItNi#Nz!Z` z5A9ec)53d{C4Pj?85e8J>|?bea|Cltt-vJlO%6t!14L_adoNnXrt`Nz!rcSn@M5`v z0p%^kpwYb-u+3^<wC|`Jwm*<3lb*fTt@}7wf22N z!08U}C1#V|VygJn=I*7bN5&tZ5)O*RH{vD~q6;zRWCjQ~Uw$*R8#-zIG4&(UYW{3! zgQn5BiEJ7Hr^5d_7;=NEKf0Ww`Y`o;5U5sEwgbJRnxU5fq-?eptwkQpOxb#{Wb?X&I8(t$j)PJSh>zuCR*9mdKIvuI>g`nir& zm%u`tMc0^EkN~f0@#czI5#37uhl1@4svN+|F8&hw0&TEXSh=1RM`(rvnOjXoS=@dt zxv){%Xt*7Lv&kz>6irRpe#%HbwcLTS;il2{`sN_Vu#2<%Q=b66jZ0ZR+p)LPTPcs% z3JyqoI)pVrtG~)Y-oyri=6|d=abfB|%bR%)e#sHd&qs-$k>$G+ha!qMx{YeW{wSi# z4(*TN*%96%G4x4NW;QD&sv|f;j(#{+*YKI!L=k4avteL;>h=tnq&Ta~FxlG=SUrhz z2B)Y-%0#W^j!b#mWOgCu-;(u8;Oz;H#|X#x)6`+A4QSTm&lr+bp)zTx0H-!R1y_G| z-gPsU!h)UYpP5^hnjP%u{LI|)1!3g7!#+vJ)SL@%ezv3)<*L6A!aWw8`YN7wrROpG z0_uEDMDnc^%auQanXa?T-gM;F!N+G4afG#sNzh91?Ye40L(RG9jJ3|kZBFrfV>H{q zm>+Ic$I#D}Xeo4Pyfir(LVsr`Ltq50fiJ+()TT5$revNA{Voil?cCL~>3r#;bh1ZD zsM+txl7gP%RE~;mJfRrG|3dY%!`k1}LRQMd+$kwDuyOce#jPr`MRq%YI{B-d1aH*z z`&Ld+?4bCF)e^@h+7qksv#?=O$DW}5na(REg>FlCtoF(8SWUJYz~_!>6x{sbCA6$4vOFi6cXeplVREncqj zH6}vuByiE6A8k^pYd90sdL%OWE0Et*mZ+jCTwmX-su9n5XK7+a|1V)FM{8pkk51(n%AL>PX z2k@Q$rUlyuv!L><`S<29Ib2pQhc@>JYav?4)_6a4fflYwE_W9+1bEFo(DfM(LZqQKh_;B;Wa{M}gbeU$YF4V+dq%iY*2~YfGe#R{vJwfDR^l>?+ zImsPjgb^28Y89^bvVP+@8lXf^6FvJw76nxn1y#2w7~Gl}UUPMw`!D;Hp?MZB(uJc1q3tz}E;cKBnf?#_B{wcT%Y<_QIoaDkG*}$={@3tY!I@2)Cz1Gew7j>o|ozVTG{QmF`CQ8h_!Tfk?lT>De==S zxEP(uJ27F3&_sNxir_Tc*Kk{V71%o1MS`}_zAgY*x^4}#-r{_ekp`P`%Hf?S%_mO+ zQJ-6pLey<4s9%Xr=6B8zbij`rnhrXQUrmhj=gGll)g|6t!x?ukUIB9AMX0`dEWEi3_g*ix;Lt*RSU8ijm_h`K|(!Sa{>wKj_zRAWd15@yGL5yh-mf^z7%xt*Ic(iws!rXkh7*}UhOr_xzVuTGM(L;QX zInO&0{Qa&_c-RKlSRA2Vy_s#MZlf?G(CjzHvnZSSjuh5Z{kfxsV2m7{CC6#@zZp% zz2z{BR3COyJqH&<9p-$8P$~XrN+0!yH8F)asQx$+<~!EXGK6E38q_+Q)H*Yql(&N# zH@=si)$? zXA+d+4?9$ua=$|`+F}?caba|of>^X9i6ack;c$GeiZ1)LvaEJtjr&6^5`4}{&K#Y- zO>vcX zT6(Aqvm_T{i~S|=w5_2g@azabD<=Jdn!Z^nouA8_qrx~xxyHGmTE&owUa=Kbqfi@h zNQ1(N!}O7UZDfEcPmxeaGs?9eI88mX6DT+?nGChku&Lp-DtZPteQOnD(^g0C_&#hbNX=n15y*7x!il+ zUmc%#-e-pR_P93W1W-N#tC*G) zc0gN83Ql%O+#v0pG$}fX!^G(JeG9VPc~6kcFjlpxz6HduBA- zAVB+3d(t2Sp*$D}A1mwK18y~KZR~QV#waQkwwot1M219i)7^(wotGgHs)pRg~Xy$I*RyA(5 zCaqN%3`pFX>~0T#Fw`^{9D>P!2<8un;{1Uze?ZVrPL96P+nBuZ<9S~gn)vQeO=CiH zJ{^>-9pB8_(Xn5gUpKNC&W6at8ak}k3f|ewho_0R7fZ{40Q0BA3e#cbL8ik>HXX9c z18fSRdQZZDnl}Fz(;@TXHYy)4+PpZ!grxatoMpJp%9Z9p2^tbq`6;qiwMnuyju3X< z+$@=3_yt%mhhct}ERoI4h51>MmkpRDncn8lk{oLVsrj>H=|N}7VP*q2OWHkSn{YDrc zpPg6QY~|_Yj(@1Im-@kEAsS`EwCkuraWXJ9oD+zh0<|Q(u`{V!XxJ5H_LsmA6fwKE> zhioE~^JDhy-t_0)m=%ZLE6&5zx6|7+@Qiqe^^Nvx(V%4jt4wHBcvx888etCR?HBpb zGecIav*ltCeHMS!4L-kIiat%y4K-Uh>e-;rH_j;dTjM@#<_DdlaXL#i%1-cutpR$- zr^sRkq{ew%IAQyNn=YS(a?w-2|^Ei$83jX9r8;R{+6oo`ydU9bryS5Ks+f zlyjDSSSmTo8+fdI?aw!h*|KvcwUG4V?SS-`r87K8qUzqE8D3WDnaxTu+q4~KuE+NZ zeEEFvFADsJ2CkF{0ortjq`8V#DAv)}oVYYvvxu<2VxOIbOkQRu@)8l4J5Zd&{J#oL ztQQiT$Kg1^d3<(EcC#fKYp~7>5wqtB8Vto3m_D^9Q5!4vcTd~A0?&@{E143cl%15I zWC3NXA#u}E*%(-snG!QhpGh+x*cpDrT%tD|AAvkLL;YQJdc$H5ofma|fn2CE*H<58 zu1^e_dd4tk(A;^hUmWm=iis}9e7e}RQ(wIDm`vtXCUaL0iIkQJG{<@|&#+aVH>fvB35sX{8$ma^lEma&q z(N-zWJn~iXTHZWjbH_IDTnnBY6~fREjukuiAr$hH+B_aC=`zv^yNsl_8l5styNnSB zmyhm+-)!++Y#tz619Fq)I`)Z(fgiSZM+-A0ewOz;!=w;NAaOJB)4rWqUtZjQuA___SaKpn)x>(p-xI(~0@t4>e({pH@VcR2r@L4Qwp%&ZvGcy@$$ zWpYa?JIO64hu9hO)@cmLuu~aJSZpUtPPJh2ZNwRSM*Xl*9;W9oAYlPYhz1LVtzHtC zBapN3l$xgu7Pk<=Ef1#{`_5O@;6{i_T(h(OC=~kLMSipGa&A>b5ZG+zToU76yh{ zVsdI@Ep)lJS6BJ0cby%k=$4&~MQ4CX)}2n9OzkqKht3egSas!xz zYZh$P+7ruSC^gQtZBKB~ea=g9&!WEU{@bGvgzm&pvd3%Zc}6&3T{sL`i-v%txE2u+ z|A_wMT3FCtGf0>^_#ro)1blJ|+}MllXYH*tPHNvuBtrdLgk0U(Twa+(uAiIAb?JCd z1K&(u{_3IR<-?h?Zwjy>{fuUrT@e3I<^M9pc7D2`Y#yyPqMC8ny=mPk0mFVe*ejoH zDmFec*zec~;_P=oWTL z0C8m#;N`~m{H`$4W4UqzUI&Hm*c}cVTn@Kw9&2uqSI2p!*t_n=Rb%a;cVOCpQFw0bX&kQq)li$mx2kl6yL1OZKs_R z;WLJ9Q)nYyIVce)gvF5OF5J&WB9i0UyN1x#ArSczHslFf(eAFivg@7KU?eX)boL!+A47u^j!DdUjpMNv>sV zIuEFott^pYed@xojd9it2@S`SRZ^{*t0-w@?l1=W%&_-S`V?CVg@_t7Pk%om_NVIy~z!v*)oz&haws-%nA9=lh>_Je4Q`$5OB4=E|n!K$P*~en!(L! zkt0De!8%WM;Td?W!aUYI$PXLA9O9R&k*-QL(g#CQZ|B*WRXh3(*S(PP-LX)WRnq>E z2vBQ3^$710X5H6o@G#&52sXp%9dVj&yyyI(c z*8X_bw*h+g)WuQM?M{5#b1^3lf}9^`p3+3tmBU2#LUW5f&K(jCqra(Oj-@GHZeK38 zo1S?t^t&%2f=3t4ZM4r+(XXSGn}AgroD^^%Vdqy2+fCZswJIYf7g zi#t8wK6h+7IXbB->qu~^MfzkjdkiKTy}Qm>5t=sFPDBXjihE2di?w3_>0|CfZ)ey+ ztih%)zZp=+ zD-sxC9JVdOj)Jkgu5VAWo`oKP4PonG=I4rF-Pz*aW(uS0*)`VEwkAjK>6ptaByu^E zj}wLbs7GHy4(n0#5b@G9!aPL$a~feDB3_n8n1=|}sKkGKpW@fax1G8{|u<)Z0k=JT*po9DUb4|&U5FGcOlJSyJUyvtMp^? zNeYYHlY(i0`s7&f*PkCPCo&UdbfO~iQY_kiA%r3l0j07KtM4lTMZ99xguI>f$*>nil15yd}BTe0Q?(-ve2v;@!}3ouFQ8 zL0jueC-cVvj zj)Qm~{?-xh!6IG{#Cm%sF{?^bt7B$WJbttq!e(I}{IGaCAlV38vn#HAfZ1lIuCFz< zpZQ4d5}xpI*DCm8QxdT}*cSbrZ0s3GE?I04?NE&I(mHUvP`D+RPppb$y>A#E<4>LC z5K3;caQ1%7hLPs-QvJYTf2!ruc*bh0Ls#F|D6jdEKlOB%0?+FF{w37&9O?^?pRW;q2_ac|YH#Q3PYXUzmG zjG5`V`_8lYCHL%d$epTlBBXAZyaBt?JL)Vq<|KEZ_k?!ru4Dm0%uAi!jUXTc!7!^8Ifl5_C$>RahkhM5{vkeM7(wO~-%J(~12PCrU{@M&_tt5PuBm_ZFy z`!yV6jf;}~y0FrDp*lu=B3{3%FQP35(OMhY1+kL-a?(4M>uxlS7VLT$pPb;VIhF+@ z6W0KjX#-`e&VOxXGRHD)V^$T`A`@^yWy86RlU!`FTC9^F zVeAeLtnM65&dt~q3v6=2cVmSK`=r`&D)4qcU=eW;Ue*|I7W1M}ywTiZZ>!uw?@bmg z_1=K%)R(6#+gO)U#;b*R9j@6KYRO==f^t?N%-yozjQW%u3`dVv zJ|;FTg0=q_9Zn*9g)Sy~oT6D1YJaW}ouE+3XXhe%ti0va_+Un;VHc_mW99EWg<^8G zCg{^SmDUngZMl|mEax#4R%232%omwytTx;~7E0!~&2{8uJh6IU{<4ccxxASnNd`Pu zPY`{Qe$D}9R-FW|T^QVscsFcA{YTBOe;oVMS3uYGJTkV@IyZ?qpGsz*?Anl-&76U5 zETPRhN?SZjyt;}pzN;EAEAnBavqhv(eBml&?Sf}oQ1|?>K-1&qB z*IU>rm`dQv%n_Xz3%!7!1!qFO?|_Q^N99OXa)xBHIJ+Ko{gd7MT9FWG7sQ>JG+U>m z*UZu}Hu^?ZYE~C z6g0~l;})*R*bpj#RhC5Ykq||-Hy!O=f>jnsceGzon^Q^)t~eQ<*85C{F}mkH3Us~&ZF=uA z?`P$Ghk37-m+2XRd*wyy;oT}P0|f61757fO9O{dt=EY`ksJ7n)>5{LWxcKwjMBaU$ zfMwJ(4{V|0#UAfXTp^*b@Pa6!?<2r}qvTY4w|0;BG5RhI<2~^poCH~N7y4L`@&L;; z@!aRjeZVla&yRTf9N=iHa>a*?cGgla0(BOSDk#P0;n-l(#f_AL}EoMHmDQJO)xY*1;fPbU9N}-#K zr1CiUN#L=k)g~)Nu60dsCb+%=Oc-4-fZ3bK<5i}$QtJW?4VBKmh!F@Xu4BVsFDst* zhMwS`k>DW7m0alR-0sj34~FsH2G7I9(_aJ}JM;$C$DXMRN6)qDDX(DP{7K8}e17Lb zw7x+p@-_|X?EKI{iLqgdwg+f(fUP!Xp}V5`e}E{=&Fp)pI!E>J9wJmEaL2T zqPjYW#gcTe`d96J5&5z!w?6nzQqpTk=zRg>t538e;0BSW zJ!kq^d@T7Lk=nxQaEnGcU${|w1A9va+kMS_mCr3wbQ11JorD{9GmEWvRUgMP2c>-{DNRDjgb*^P zVBdZl2lqhJhQp?^{jm`f1SYH<%k3j2?RP=h!FP;;SgO7~?QoYUt|31Y&yu12;YaC; z`_&}Jm|^G#Cyzkg8yoW;i)5K9?5rD^@8sn zFLH9)_pb5w_+aY4!`tIW&ad&l5A@nBdL_pLbO$7Ge@^PzJA{(icHFQ}ASpPDSZL5G^3A}ViAKlT+BiD-K=jo2>4RptJMZZp> zb6&X2!az%KKZ_!hB#Z5>VE z+h9;>PA89?=buwzL9JP~6l1GMb%yWG8#0#8N1aGVG<*Qgrmb$CZ+We?jt`L<(OSxp z%3>fVB-8QtsM)^hs`GTdozWQ;Jx@z+49^6oWd?%QWcv=uh|}!ewYv>|B=v4GRXuG6 zW}xp-Di1pwVI^)__4aX(<^uV`e2EOWE8ig7vvBx7!aMYN**Mw*n!XI&*s&d9ru!q! z!ThLR$GQg*KZ7J|tcw2R;?;SN0Jofl@g``4b>&7!B4mG2@0YrFUs5ZiU<%PcQwG#D zli=>C$d9BTm+yAJ`$0fv_e2j9Yg+%O)*+V> zdr@WCIr?DHoqlv31@cIS89?HHrnJ`XNkH!|IB$M8{}nC^uN}BF5F20G9W%@JcYR(?vE| z%V?Xy(6p(?3^1@-h&neHB{br@tR%G}Df&x9#8~T4W~}@?fJGR<@uDeDz6CqNN8#;k zBUf}IKS?BJseGjA8m|Dqm&3!!hRExYhpi|1_PkZax5HlPurZBeh6BZObO)bAm+ms_ z`z$vP;ti~ikx?(5eN?WZlJ~GsZY(M(-wK)J!A2_twTnVpobojV$WP>T3!FxT6Z2Cl ze<$_Qo`mBFPeBIJduUZAeE-9pF%Tco9@ZsKCmEZmxm#vS^$x}`ZNDg_xhm%_Gcx(caIb?tv~h! z^+TZrZ?g>g2LcpJTXoJQBY+-t`8fpCn>kmI=T+7>(lmLPQTDPh`k=aiRp{GsbX(tnoK0u!Fq5z8VDMa8Cz)eJNA6Z4HZuz!*L1}m^ z!T1RP4bJOd%f0?ZAm#1pJ@x``1pU!;$-$c0x<=nuN*B)TGP9mw;he0QPo=bEx>&Hw z?BiQFvzixt0P2`cH3oke~vnHf!=mPKYXMM$NP8BNd5A~TwzmZgvxP1k3U z8BGVZKNL+rYxT<$tl_6Pm)W=TZ&Eg;Z(zgrNEGlj$qiGtLthpHqPs zno;0i@cO8!Uo*E5eM3p63tT||UT*!1EEQM~y^miVgVcUPXp*1L6WP8O=dYvpk~)ee z;CEGN7`>Zt?>4;L%(CK3R=Teb89f6uhRe}60rAVx-8fPaJ}G3c^}C4I7I%k4ma^l$x?h6z#Wt1XjjmtO9DPme1xU&(Q z?x+Qt$zH6-upEZv_yUlaTwAt#k7b=bt;8FM8ZGCZ2rD$}NN9;hZiyg@50I(kD}WL^ zP3-J_+$qUD8|+G(_7J}3@Zcs#eBTfW>0`n!tR_@jV>Z3x|p9)tU6X-5yI?PE?s%(VE*9_ zAK(>-6_)?0UhxoIkJGdDdmU|bdT%)PHez2N8n9kWnWkUy-4>v)gl+}9!pfMsgtS8Z zJbqF36yW<@8}#(%mCuJm=sj~ecu{N~%*l!|ZHZf69pm3>Ip}#8tx~pW?Zdcp;J`VNVmXJyO^OfVQU~ac` zMslYIP7LM_njdpm^l4!bf0AElD)AZplQP%aXHsa;KA+#{1;n`9HatrHLIP?1#y6vW ze-m**+|8w!&OATG@4pBDm*2JXV%oVyV`1Y1^g6dm`aLV?YB3lRhI%$?PHIg>w;Gzp zdAA5x7OU@6Qv6~ER@o&OdQT8-R;>o+c2!*6*HHIWs@pNQQS60DHC6*t^-IWEEln*s z^DzaWeg4VHas>adet6AC>upmN97I0=r`BWq{!3MtQOFPX2FCtk7Q!gkI*qx3g438As5Onbfi}{Z8|Wa7 zxq;@9bkVhbmdC{MY|YPrEQZ(GQ#Ba()nG6EplaWE0mH;rfFS@QOJ)F=n&xN=XImyF zbP=M``?Mx&3<1o~^2)|l(enPY1h59&r;dIdBV-d(qY4^W0|el}?4zMYJAxAZhj@kT zpL5xVPkgZK0&rmY>_1U<1hP;G;w{4Et!ZJ-O>77bJy(CumhdDsoWCT`o=Kj&DApC4 zM0|;e_$rD|8VaCFOw0DtA&Tj$_LkrUjxieYmIBN$N{(XbC3gO>E|E^Y}0>j zmVLlL{nurYnO^+*EHcxJugxL{44SWfz=`?V2RxateZZYr?GL3FYdo{axE(U${EM7* zo%@O0EdPrYpXkLaP#v_-q`%H};Jf+rB)YSPU%4Z1FuQ!a1hV^OS9Zy-WVQlwR0Q%bC4Q3VXW0rX%rLp@F{hsnh`W9P`w-Q+%&A-TO z@AaU9`5ZN0eWb3fPj34__}jK=Fhp?fY^&d&NsohYV2CTx|El94s39B& zQHpzs`5K<7w*z()iFspS(Vf*9xabd#es_Q`LwvKj7_Qw~A$}8>Mley>=;tkt*mU5R zFt6RR+TaX|PQ!muMQ!rCa%~f!;5Gp)0ayE7YTex^mmm$2p3!!P5w(NM!Q+& zNe&E1hu8?snWd1Ye-+xQa z|JI!U`kem;{H{!}OS1_xB-xYx26jbPAW=vX`A#oP~An|n^o}lk4IIm}v zkQCrjxnU%%kVF39+llN55U1~9yixRKG-24^wK@21SKpk9Wi?8+gG%t>c`6f$tK`5j z0({~^+8_%07@iQ5%I9>h0kA{IuI2kqr_{g87X|T<4*IWvu?}=N6`DW3P)Z#-Rw|KawsPHca6c-?OzIXt0v&>jvYB7 z`!z_$+`R8egD$7cLk1zn=f6<`MEj14*7$rR^x91S6tcnQca^I3?3meQjpx(l<(gj= z`tLWQs3b=eBv5v|un_59tA?)gSGqwa* zoMRKyGj+XHQD$U!MOy~9@uyT}cd1stE6ylxi-ip?zbn#Ws_kP$r>!EWtwxeEv?Os0 zk`K`A*2+TvMr*!Rprr;1f&6YkROsI{Kee$_MNy&uL4&adsDzAouBbx9Yd^XMn^7W( zayt1%j%?gmb;}!9X`<@p?BuP{q^fyKqW6hM>Wp-oXaM;TD9qE7{rJN~wMOP8WmCrY zX|3_jyTIeM8ryzXanTf5Q)d$Tp4c?;4+zigGY4xihW=qmhWH~?S}F8DierZg@ZXHz zWw0g``Yef(#Cb&Wb|Zgw;gg^yAf z?Vbdz`rVR%8tOEPmAs}y+ob7h@)~IT^iwjK-J^aw((lSm1{XTB%?k*EA1F3vJzL?v z2%iX??A=R@KhgWEvfVa-+pgIE2^3z zc`-R)7XI^+g8ru$#N>cKvmhzxe|A9(H2NG-0~+0w3MHLb%}tEGAE}Xr-hFb4y&tLx z^I?yAd@50U|FJWycnVo6`ztFVcuVC$Q*)gn(Bveua$-O+H=Uhg?6l(g+i}A9^J+j> zXpp`JnqfHmg2f3Z<&~SHHNGRwPe&*k5o2SKE|+=ODlb=UHB_HnJCUIa95s3AYy$9R^IcugG3ZCNh2u)^3hQ zsdoBcS8G*v^+i92R0#|5B*5NJu5R3aGMWbxq`zh^%r!cgN zr+y|1ywC3{n5vY5NYz9Zq7*JDCsdeIbA?C8sBBckWKR7BaFqRX98SS@<)(!yDJ>K$ zeL@8t8Ij7OV=k`qP2Bcii2~PO`g2yjLORaH;oiVRt>2v&^^FBkNBVXWoa;3wy0Tr+ zZj>Z(tQB}a8EIN{Fd2P*O=YwJ8?)&1OCf^z_>EjGB+TQ+)l=#C%{H!-CvB*5JgAc5 zM<;<%YjL6fO~YBW#M1H_srr(|TsR=>Z-GKlgTE`i-{Eh#`kz7lFd#b8x2!OMSz&%x zPy?;{Mh&uC(Ox&DkV>}x?4O8_VJ_7vw7hO|%|7Anx*g^5_ds%PQMmGup}mn1ohtIO z-wq+M}?upfB{1 zxUPD?tD@3ePUdUY(r|BpXJ(aM-FX^uoBvxipX7$0&DhBa{AcYH1-3S$Gq%jt*fNh) zhR%OV&%xcGiZXfqHx&;r%5~!{m-u%js^50d=Ib;ra!-UNN}Q9Gg50tp$1ItqYYbE9 zOQJYsuU~6Gcsc ze3#MOgcq87^SM0wC_887)bWyRX4JLP#GI+^`!I!>dvl(^6?<#{$h?VqumV07sn_a+5 zIlRwCMLILFlSW|GfR3yDiNJIjvoonJ;DLG7rU!E~J}oHv@>JR?l<<}0Z2wf~>4ZMY z++_%LSicBNBJxV+y%)${DDPyii~}BB0m-%SKnTBFWPPF^y;3N3mD`DF9lbK!%M#ot zL!+Q`93T)w#fI?@sUf6e>aKk48wa|xuDu52xPapOfT=V`k=#GR#~XMQK;Sp>#7oj%^Rt?$G)8`(l!_d{qrXEW%gDf z9jZ)>+aQW44CgxX^4MXtuY%pfNHrQ|N1yoWamn`gM}o53-G3g9PmaEG^eH>~4imY# z`B-o29A{Hr=XZsEF=q1v-bKaSk9wp>mrNmsJYG=fp9GtyZ;sgq$!+{4*Yo(clG=6! zKTc82U31L6zvQ6odwkLB)fHCVweq>XKppemEPBj!;KOK}I6-$6`OwwIc@fo#{$U`L zj($fKyPcTa$_&DC?#AgvAIUO+PGyDE$`>lVc%C+aVFSjg6f@ zQ0Kz#FWK9_V zg7_9kOn$GJdi&Mre#z$|SzaY)5RmNbTrnIc^wi56RLAMk`-6g}Bk z$9qK|hAxO>4o_$%9>Zy@#5h(h+HnICU#DRdcZdn?u7IO9v5FsIQkWV_*~`oc?jBG1&Q8DO?=Yt^$<5G zJt(}+f-+}%H&7SfV)IuOD%iwTX!6~MpFzy*F@i9D4z=+9#WwXKhiqdk1fgv&*oy|d zb%AY#BU5(OStn>G%EK;>1Ft4h?8Ivdw&uQ)9TPLzgAkLD>SVXx-D@L_HLgja@yzet2{GvabI?`>*xN~6+)&}bx2`7(X-PF4B^e#Q!=&atB6U5RP%eYA3R0)mL@ zu$k!6`3;Z_=7{4M!uAS%=g*39GM)L&Ly*@x+hM5+kB!g5Oguf#lLdNnoa_F)YuH0s z;kj@H?9IgL+-a$lv$@XImnwu|S7lhI+L^;``G_xoVf0eEbc5+q!a6CK0U#g|* z$(hYc(U`LSRNoW_-z3fklN#_4gDFAPhLH2uCpz!k^}ySSWmNV;mU+xVmNA`7Jo9$( z%&!xkc?7t_GZ??bGe^lO_Kud*Rp3E*Mipi}qcZ04OcwEQc;+|rc?LWS_D0e>gy(M! zPrru+P4DR+E2q#yK^LCK%jqiM@Jvyf8(}UrC1=}6*i{~Th|NBRQ+7N%>Uee-p8efU z^@pb4561kBVg`A%pdgqBdI>eH@{MCj&GDQkOQgUVf)n1r1<*Y zs{Q%)&H3IqG*7L2AT>9zaF$`Azz{6%FXml9M)$j1b@?@p2TxY#2bEdBGB+YqC6uGIHtyj72PdWeq( z(!A20x%ItwdChO6{!#A-_d6Krbsr%w`)92GL;@pErMXXNLRFN`WpUJ(ob| zb5J+>BtHp?|C-0d@2U~j$dTrvvNe&Dn!|Dr6|Njw+Ce}dx4oO1&0)*rFFjmFYG zh6}@>ScrM$jj_bhj$B(w=Bc+_GN(Oq$w`@KxFS{NO41AQB)_dGGOxg+vX|lR2wA!2 zG8f{dDcBzKz|enlVAP>IIP0i`#k9@goQA&*0OO3(4hD#=}CvM{>$z$i>`}A*8{w%Qynd}CQp>WrO?r|zuz^D`Q#wXDdjwdLFcTpUTPdRN8+<4|Q*v+Bzvo6K7c1 zeY2Tu5$IF0ce6&^d(`DQ)DLG*vqO{9Lqojw_bT%7-5SHm$~cb**v0gOm*b*4s#CVr5xy%} zRZp%BkP7*n>F3v#d3!0d-+aV9sAe>ckkOUa(&U!i^Qf>@#b7g8cZQmY#{Jp19F96Q zHL_>BD#s1t+!D-vCp!9zx*)Y%9*@qIKEt+q!bb&r7yJW88^tl79U_W+#W>3OO}p4k zZ1Ut1j~xi6G~%@T^quOMEN+P$WNmcxXMWhpMpbuTw5!N0m9&ye=VsZ0&sTyAyB~WP znl^SHOBpwUXU@*m6%@~ea-^HOwSL2Uk6{jbD$&(Z4Z+ zmd=$V%j}3{cK@j=KnnjEcy@%tV+g=6lV@hLQaayJc3Uj`1m6OAy>@=yit;+8PbqnM zUC^4}yNS9xRiGrV&jbVsy-rS{cb1%Dk9{NLwE|Ap^}A|tYwv;WBGY-1qQjX2+|0h@ zk%6EVtCmdO@2nP&2G^UBy=TcO_MR=Lt3XOqHR=CAQ`PcNG@YDJQ^!8{i9{=d&UfWrGniNR0TtMK zUpd9zj2tfgufnzQUbM4+AEJ#A_W=xE> zI*SsPMy7X11WgP9x)`Ul#JJtxh%&2yhN%yDGg;|W#CZ7kYb_fix$ z22|Tz2T*NS_*8a4AXbH{k`$e)B<3Uf){|r#M1SSiJ&;qu0v>sbwb_MsCmY?R)}%TATh5i{{F|I? z>UY+3AQS9h1+(kDw`PupPY>_KDm_)9F5! zPWR8*=}L2?%i6u5&!^HwE2%Bzht8Dyti^CN>LcMqJI7y&=Y5%*X(L}yz43Hu7-vGn zypeD;?!m!BY(v>>+0r4321#6~xLm**)5Y}_>RBzLLR&J?ld=HNc*I~1w{3xMq1`-k z;v@Derq5uAv{@C|fmwBlMnt+{X?#X8(Ks?r@AR47KuZObHz37C6N&z@u~0p?K#aA; zqMhNpfih8!BB3R|y?pyd`bP%Z@(@qXIr94p&U$^V6cl{WK(U_fl}V+h+C{qz@3NAV zKvnE5OUIIr`;@D6RY$VdcrtS*}K*hx@`t)fMMKEA}0>AFW675U~v$BsdaK> zet=jvHlnlfa_KyPw5t)iT@7l=3v)8IldYYeufNbScgyj~;=`RWSQ|z!htB#zVRV+h zY`bT`H8rwM`(MbC?0>l`!jP&%VJ3k#$NS|t@8w!=7@x(eSGg9{0dNG@D9W&|6cB!5AarvvycPRQ>*Lb(PR|C+6O~5*LH8_-_&;Mt+v!BzN5V zGdr(NbWcZSc0Sv=B_S@O*CQdGrLiDvoz2JTN)DzBDfw`r1kbJcrBLi%(d!82O9<;0 z%!8)b)Rq-544PsgCSJGZmkGg5q72V=ZI7#4on@fQ3{CC1UKYQ92~X@T12ZohFMv_D zag}Unxo4`J_+?{+Wc;s?zA;XrB;!v}9OTi4KD^hbPp-95pQb#CJSyt`7xJib`B(Dj zga+2zX_s!hX05A4{{+{t+R#bc1lgjm@<3`GnR=PfBIizG7MLsPrT!ii&iYQy^j}}K zcB#OwwZ7{0Q7Ugk#2cP$;LqxMU^!)BvoC&uXk80yAV z(~IF@ddRg0%Q|(?-uTh9<~Dw07z5R#g@>w`_i%NJ-a;j!_39}6bG~Zx#Cb*bED$RVuc%!2!okF!& z_ItMr)qP0CN|?~kM!8WcJz?j3Px1`h$n?6@ifIc{mJ@Af>siJ}M?2@%y?SR+d3KOf z>S*zlW|G_feUs;IS-3Thx*(*`=^!Dmiw6OoueWpi^Iz_!i2C zaHeOXb$BY-)VQU4Q^ObiRSC~+RpVc>+C~J)WbXgkf2_5qf1@r)|35WY?hv^cW$1{nfQ*`iFtoVoa-iP8~)CT zt7o>7Eu6Y&(rfqrFGyNF8%@yExbrWxeHi*M*~c}~Q66KeP>U`wC0`}Bwtt`5XR-$+ zmBz|~nPrgMEkDC9-ul*}1x70S&iSk(Rl}W`fm<^=oOlVLri{u#1^!+6NT$ePNj8zU z(YN{s4W9C>;;2)79~N#INt#r23zS$MD?QH8-r2l~e(fab=yVWkRkqx%%3@{%Y|Eqk z&?>QLa&~)#c3;X;W|=;KW?)paF)Len^)>$+o!>0RPyLc{$Aw=+M_g+5R+x4upH7Op zKljd-A#rBrJI?4pQRId-)PdsG-qi?9GVK!qf$&Rc~ zN7n{XKRf6O(CbHOt?l#*N%&%Qw1V=}WodI$(B;e$y5w;cSS<3aqR>tj6zsPDkW8l53M5zw<=Ll~JLS6CTB&j*nA9E(lQ-v9I z>Sf0!om!WICfdFnzFOO7&(iMG_PVVMU83at8_mVW`Pa!|eTk7U^BvkpV>iFHJKvUZ z`UUH=J7}6JPwf?r-GS>XCa#3b)8)$%X`A(AOtr`!k!McYJ@{NO)$^`{Ywdlqngs^ms-z=_IR(X>* z^}L4Y=|h2_6OP93CN_u;Rcc-3a{cF^h~omK_%K3e3{rJ5WTi!NFI%DqXgX}wdVBbT zgcIM}n<)s4u5g%gKcKOWMPQ1bpg8 zr}Mqd%B|4&+dxED^8*7d;5)cSFP`A0!gzUXSs!<$K_1Jl*%%3+OUI^dVB9m3gf^oO#(( zJ#Q0X(d8nAG)gO75L4n%V=tff^?;+qc|#h->pY4z-6)d0?@;=^efl@06TZ@^QkZ7Gt$L=pYpc{jHA^gqT?vsIq#96l&_Du+N`Ha7`hTRI7fl~ zxqRy=5^0xH-}ra}-4HN2bq|T0NlNy|E!%0wuhMfm{0f@N)K^ME`C(Ig0Fo{+7;aE8 zv=F>ejz>DO{vp7+CLT_66tm{VH#IB{}W61sA7XzEKUhZ`?HA|gin zlGqbhN9{DLx8p#Dh~gufg6U)UZHXM#oaeLUe7tXRtDn!krnYAt*Zf>tHCQ^8l2~G6 zfj2*Y4t(;m4Etccwk-A9#`8(A!QRPj@oO32;*z_#vfB7`g zi2%2Z_0v-ej?0`qBSNQ^$R)N|XP8lGk}+NL0ec`rjeY%?{GaJD`9J)aykGa2Oqygq zxL0ZS_i5h@IP<|pX%rWF6bE#pNalkdDE)yxJ!*>1Ty(Kdcu;r3RNg;S+Jk-Cw*pSy zZ%d;zXjbIEZq#paUd%Hie`nz?*3JYtT<7IgwEI|7LPX`VP9MBY*v zzBAiC-V0QP4o;mxG=bhn`cU(nvG6TX|<7$irh@I}w3dTZ>Xb84Z)ld@rS z5&?rfVRR3e=%fn>Z>c1>+2<;?M1CmKIVHX7VaaxJ!_q@!k_@~-;}jrdtgYk+D4S{8 zqv2uJg3@D(4Wd61`D?Qflx^HDci6a1ABLh+m7@ln2kE&QaWEs$i^T}U z`nvJ2dkJa$Ry$?0bEt8sukUxHEBfueq7Un?XwoF@^v6njxKH~oz-cR&rcu1pqd1}) zg%(;85~4>{vNdgy;n%L9%@aiY+Q7c9IvS5D%D1sa&rP?n4FFpkQ!3xaj7In7jdVfX z?TIZQkkNwHf+y92o~mUzA%h#wR?~e{4c5`sMsyU}8iz>0ZH+@za6uV>c@l+?Yc%KW%PmIe1%4*5nmf-W8ZmSgg5FJK-ieC&mR6|=*FOY zsupwX5!fuhG)ntI=Yyj@+`8+Flu+f$XI?-X)n9Zv*-V{BQw%R++~Fun{2 z+Dguvt`hB05yJ!{(;CJ9-P?>N(G=C4uvt`hB05yJ z!{(;CJ9-kk}Iv4Lj0)Doo2I(nSg+ET;o@i@kyyDr_2DkC#>C46`31{_568`5y%XZxY7 z3m@jlk3)oGpt@iv>p^ggAPd*-ahdfxcB3OlmNaV7#*||8Go@a=|v}_FVVg zkuG!271Hrzcf1YE?Qm2wrHSNv_&pCS9LjHep}>kmMed0g-97QS3zU93pmHF}f9o6&Ds*+; z!phiKWo&+BI}$0$jY*O|qI>x#aOE#>OVT$sSXoXc$^z$P1I1NoMlG{F03(=5-c6Q) z90zxH_{4YgDXak$#90%!3@kJDw?niNjBQOyXZtf)v^M{Rz7y)Gf0b(oMpNr)tAZ%f zje=ctFkwGV9-~Joaq<}5inb^t_?e1CL!wBOCv-IN8GBiohiuKwt^*e|FWNx=t4{>+ z&tX;a$Y#V&YCEp8@1RFEg+qHvKQSCe32GjIFRAm?S%PGUEsThwTX+Y-uXIKs$gCj! z?w0;iG98ULA6<<`Jam2<)ib8(%bS4hu|1224R)mg)Ho!F4yY7y!bDH8AGG41ui@1W zu9KE#ETIOhrvYl3tX<_eHo(wfJPt%m&Suhj6x?Cv0OchRu?w|3!0(dPT#J6}eo`|uc%A2fK z(}hc{lpI1YH2T>p&PVgKVf+av4g_kv0|c~;s>X*%-ik$F<0|mA&c;bSWYs@3Mh!Kn zXa*a04E~BEEA}kqJy1Px77c@^*2|g7QHwNQ6fZer)q@81Oo8Qe@bXDg*7m_60*CYE z;X;+6bf~atxR@U*F6fD`go@e#ZkRXTXUK+d4i|Wi2FKR? znbI?U7zE=piiuXki|LPb!@N{5R~d|AB05VoqP17mcS5`CMsYJt&*BO<5Km~SGO86O zup)(=&Fg4Bfj|q$!}{ub+HEv-i;ac^(-cEvE=f6=CX{{1%rD@py%%`6PVyD)VTgg= z=%0)!+?$F@B&@T;5r0s#*cgth#UIRt3Ry9}7Hrj`9{(Ez(%PGtbe+}P;o$$J+D%in zn&sHoN0fNSd=qw+f~c1ys~6^*@TxRD1<2~2ihbF}bxA0|9 zVOo)`b8(B^?_d% z1d6%2!E1TPAQvAtCYAJp6u#L22MT~~4nrs0ZI4K4dqhg*Z*AT+p*6>xGuk>I7oTZ9 z731dDfb`+U&9CD(D5hXxyxH-!cf-I&Q(OjP1*zKgF?m@NETC3kr_EBad4% zTnL{YwXwottfjg%3`O4su9nUBJ#fYY3<(CH_IaOoTSaUOybni2ZUqeS-I7>Q9T=7` zhydXtAE&Y<=)~{)3ee^374>Dx+b6b|PRi}dO;hQ06M>I)eex8UG&2cP&(xiisSeCj`bV9A2a)-wCC zen?C+DY@@9n%U(5H$DcLzRbbLINCckBPMee!UoLodI2$#vqmL5wf=pgSZTjbjf9ct zZb42?)fpiD8Hu22aeGYPBginmR}eHHwGAmuUMkS1G01X~q4fhrp6bp=^Mnt+P$rH_ zjc2G~!w<=dvMKT#_!4e>oDRfkjzak1XHdRMK34Y5ZLmRx#aA~hoy*V~l;I|s#634} z?+-j!WxwEu;G$^u?aSNY?fU$J`{wLmH;20>#Xa`9Z@} zwjdc?kuOa7CW5kAM=7waLhfY7(`06(nl&OD2#h4D6@)8$VNEsiim@@GR!%_|VCxk-8d)A5qK&!ID&Vj+!w31yS5N ze9EN1QjF>=w6%z}|8x%XU6VEb(IXxOyfz$N1lRIJSu?&^oGf!-JDtu^mbCl`;E(%{*$#cPEUvz7Fw!~xsPK(mN z2el?FWLE6#mdqCfi=L7Rk1NmP0$(Ceee_#}p5Dbf&($YfOc)pDZZ z^?RJY-u|Faeoe9=pnoB@ek%eN7baLu`Ozd_+bbW3^xlE$ z=z=iH;zHiE7Kf0jl1>m@B)I+%X~V7M7q`=@KliZc4|t$&&tsGE=giDbmpC^w#GBo) z(!9ujFV>f(U&|Z-T#^Ks1JtxP1`NCFfHwMaaoDeMY>Yvd)L z@cq5D!@m<+sxlx)|G>p{hWLE2#ya~}%NF_{SW3)RVz}DO`x{%!tTa8JM=C{sr=gJ9 zdD8I*t-(li0SI(4=Ul$zJEc!Hdc8uSM`bm7&T#>a*Xp}p5XXF(a{ozYUAE@`0G**h zvG_Y1pnQxOvW2aF^3~KZZ(RRJ5%VRSmtFd zW24m@d;a1BBfT46NHt2ShdwRm^l3qitqjcczLgB33&CsU=nrCSXOv2k&xm|WDA?}x-dG~TNS5X zXAWdR-t)au^{n=t)7@R!?9`n3Q9`A$;2pUw1zPso^fLhd7?Tk+{S)#rhN3xr8(je; zkF1}Tt@UQHO-W#FpTdG5`nbZeeOoBz;%jhMCkpZEqF*nY&O#>43c2`dMfRHWDx7{C z|KI})@-;k+l?ZKEM!K7JVQgd4}thF^bHKjX5Hm93QT+yixX zGLGHyBHEr^na#WR=nwEuCA>>xg`Tqf1|?iy-Ps3UqhKyVe4kLpmGY+b)&A5Aigxqp zups&r^iQ2tVD(xi0XNfNrt^PVC8Mt2mejR5Hn=2u+l)Pu{rtWK^)7wRH0AgU<;c}v z?W_BJR5zSiMSaB;jdl6@iTHQJKhl`wx37?G+)7UIF?c3?s*7DJLB$udN#cY5li))9 zAiqgS3Vq&P{i@_Jqvo1gDl(oVZ{326zMxXE4rNh{Bo%$$7xL{%A` zFM60u6Bu*QhqS)>N;kf*dDwR+u;!q58NTEQU${BCsXLu{VfK5Hbmo9wr4zlP8+yO3 zWE>JO?^Fv(IgCbVNG<{d?@bVx0|d7?irNMDh;Dbm%}oisIoS5RjR~P@dKh-gOxep z5h^biU=G@>#;jkV-$eU3)R^|?4$NCf`jNs z1di7SC-P0DnU_U2dWfL@V)P)Ny_N%1>}XhPRXV^Plywbv!ZNuv|Ac@frFH)J_izK` zXhxHC*2gjOsxDrRZswPGJ|zDdzas-9!y15ub+6YenZ1BJjmF1mF;Op}#k@co$}&|j zKBJh3ErBZcM_!}gQ8l7H37AGdluq|F@s zz-CRb1B$&>u>-|U#ibHqOSw1ZEI38U)y{SthzpcpIG@`{cu%dIJ4fFbGcP6YT!OPu z8z?yNTznt!^RPzZ7;obY4{VxucFXFvww#mv;$-^Q_dNH#TY_{JXKtrq9zRnn1d`9N>Jg<^xL@S}teXL&S0LwR{q>+^*29M(6J`M_javAkX;c;~L*y)L1c zy-gu%ikSGXw5{4wVEec1O_kY%QY~#+leqhba(mIANTX~zt#+?>DsXH5jcN`{sfFQu zcFWU~REcE^muj=Us_f4ejt+5Cgxg`IbNC6?SDy)u$8^zH$1wDkrCmX_U1rk^z3q}g zZ=3f1qJPZ%`Ng@2s1&w*r3-U?L17C#aWkn~4WPDev!>p+!M!*gQ?qjoP)fVs@1;gNkLOd zWU))%F#aK(gk_}5ze)bjQ~rJ}#HAWr2l*zAeW6l)uPxg1GA0C0*w{Jf^x+aF%B&|Y)98e=(a)hBzBaE&#$$6_;zxTlL05t- z(F8@m6*scc?|h;UC5g-dmMfD0bG$u>9#;Z5W73A{r=mX)6up;j6k|F`_nvZQzxPS2 zk0*$n-V7FZCy<@ZGpu;p9G%E>H497U*CIzS{1n69a(pNJ-drsfic{A@=jP(*@%=^Z zk$k^U*{~?NVOYCtd~|HZWi!IdGRw7{v0C&OUyKhYRGY)vNKU%J%-^92+9m0hay1q! zAB60D%pJzkn%js^iFtc{S$-QQ`U3c=j_m}t+t2#i>nU6(5^k>R@k#1dX9$%ai=iJbM z&}MyODdqSF<<70!C}|g~bMta2F_bp?8$SrGwthYVxUImAw%3f~FsHxDn|oR&4&-ZD z%$pSpp}Ty8Rdg-x+$zzVMZf!jk)m4+GM2I!%(?}FTLyOKhWVM5`?)pQ+FWj3JshbP za_bBmv@j%SC{Po=Dyc?utj(>f_2)2zN(V({WOS?VKO4H4?&h8aZuZB#P~)4xdmrHT4~uXU_G4 zcZm;d-IcP|AKO65=tfcgD=CUO2)H^4Fh>H3aA-0u_gE+)9dm?_Sn-hr+#CcjuQ_qc z90V|-xd3wz@UbMo9AN$c>|x~lIN^w$pHMVl^6G1Twgu#mSJERnqhuaufsP$3Pb#}5S_8bs#?BzKAN4of)h~C==d4TCqo67H z+6wn|-PLsy$Wc@--hn!!sk3s}5OhYzXnPpvMo+DwP9+Z{J1&67RU+am^urx-){?xD z9M$A~H$OExRojCW{kMeCZrDTc;aWto6KOD7IeDjv+FC?-S z7I)@=4)vj`=n?&$1`x8P5J7isgn=c^grhW8j%fbLXAUM^_!Q}Cq{D1On|s;#Xj1kS zHmaoPrwZp-k&l8dWO_HBiH}+1W7!%I+7A@xTNg@HDpY)@H=5mD{~WL==Akt@0z7rb z+IIJ4Phc;?Fb}7BO(R!Q2f54z;K-AH`zCy#~57I9#s{C#Z zepse9<@B(U$=4H3A07(VO&#}qEWp*Moce*`y0+bp+GTN_FrB7b9B{tL`oqSH4I790 zM%)28gz?c6Ry`Qz&9P~HAbTmFX28H$U-MeNBU?k(MQejlf?cjL3Cfnju?!TgfeAIN zRmiXRlJ$)-o5q4aAQ3~)^@7yUV-B^K4@0;9f@mM5=CZg_O|vCWYi>_f*QvcRN-0X?i(Ee zR@F$qDr9#Owoi>c?jYhl2;|H@=`r)Ofe)gQ@%8CMSku`PM|r>R!b7zqJn8$wAU+6xt(0{Y$l9#k_8vt0R@Q?R)+Lvu z8eBHaH7Y7G(K>3ENxJ!2BAjBBbBrHKs#>8`wLVtW z=0CytZ5~uz4?%kv@2g3S5y=D>jg3vmJ)N+2G69#0B7pjIRQo9SQi!XXY`p!eT!s_i znFZV8>H(Ew3}@94>1>Ju*EoseqpjB5oV#xZ0XJ%g%K zIUT56l6hYMz54SAp5+l76+M$QZ7in?%Q|5}2V0%KlhH0UGkq4y8taK2pHWQoOkg4w z9vspquwvKIUHi;t-b7x*YG;n%SNr^4(YOI5CCpRZ1BTR;7Us|AELPTuq-m;I5fBY=reS68EFsca{u zmyyvKWb0OsNSkcMY!n%C=A5$|8qHL-v(_9U&obrDHlC}ZqL}vSwQe0#uFp}16d~)p z%4}BtXSefLf6CdJ$5F$%saKO$*f<{CjXKz-YdQk04Pdto9Gxk22>&C|R6_MgbdGn9 zWSvv(k9IG8_9E~$zGUq#+q#!Ff|YvC^htfe5hhu%=iD8OcX{SG0^}k(dmUIZIFp*2 zGGiEzGHag~G`~c}J2=|wm(?Oqfc$s^KOAlebB;dNGS`Vrqs^T)Tnuefw}7tkJYYwo z6ZxGgo`h7pJu#Cr)UAH;jI*OcEvkMkz6_rjlO zUAHWzeVMv`bKe%`dIwU7W=NaB1hy;Jm?o&76D-Tp$=hnh%>!G`PEhswkz`ktsYD(IVqUAikR`bKza45@h zuo(h|bGh1zAvm~}h7hmkXQDS3@6R_nPHi0g)q(8vm#K(C)Fc5q@snWYaBsD|pf@^M z&Qf+kDLMsLbUpxtz5sXqC&+`nTgxn`ygZnVs}K}3{~%8eIZgW1&8m}Af#1TC(QSUj zFT{I}yu*cXD6i`hA})F^q~JbM?&Ia=v6({SauuRDl(*84EsDE=fv z{yGVHhFl+BcGibys|ryIdI~OuWsK3WG?UIq@+?drM-t1vFnuS^>945)T!pJJeP##h zr5)$XaB^(GAX34fAi!tXw78c8*X!VldaxdZ*YQgiyWTvX;dh$^bOFQM>rtWhfnvd;Q0bS;syBnBi-E_NOI4C!g_kq7QRG9wc zY|>MlYWJT+CmwO7{&bC&i3+#R$qkkdZ2)6bD^p{?ex-~6HL6RRk56bL$o|B)>3T&&4yD`qu zSVoE5DKa!VjdR5nP1^o|qty-i3;XK~hEtEx;3Cc`m1Z=tbmrISSi;JiW;DbmQ|K0C zA~%L^p3yL!Li1;#d4kf;s7t0I=AE2Gs1ey4>Ej*cc+AF7X<~fKc!D?yKoam9eIDZD zvjZx#lYDwM#N=#<_7vc9nYj^)7{@}hfq*oEEdQSr0p;X{@G{6n7wN+jewXmg)k?Ye zPzJT}5~|#6{Bgpfw+etMNbbw@^LBnJJ~kh{UqLCDeDr}f5KEtLDt|3~%t64-Nq{*B z_*N2N4gzjT0?a|cx03*K5b&KOz#Ig8HwiEY0k<(P~+7h+0_A#+BaH0?a|cT}gmB2>5;yU=9NAP6Et9 zz&%NTIS9Bn2`~q3>3amU+mbvkh_)1D)=|a@wb|&S5Q(Z)TK#-<3QdW#i|VoY=mmKC z3-yA@-&GWbU!co3R#N4hI5QpWI@}Y*TCun2rEtT|yp(~l+Mm+iz>$UGhqR3~5DsU{ z=x6Ig*`eH~Ub{aZXTeZg$o*oPbmO(uUJ3Q*1$?XXhH_lF=B(O~o{0Kxdt2etc5w5* zppdoiBYem+YxWC3Ixt!v8i%%BI^{+!IE-4*B?;mXYTD|+ zU#QJUM&`V={UvRp^#k!T+xnqCK~o>M;_m3SJ+9H z))j7(j>8(p(D@L|=C^smcu>AoLG(q)w!<*4Zn7Daq4wu>S61q+`ERIn7pZioi*rwO zbME`%oYP$?X112-LdUi+dNFCstJruDK`dLu4X4;bH>5UzU1;%J%T0{6Iyk3VN=h*- zy8Q);wGP1Z_7Y*6@_6F6;ETT@QST+fcm_Xu4Mp71;XHkrDoyFw=84h6*}u1uma*l2 zU@F*{(bwMmh|UDd^zW0hb3=@lc(2O-c2bPbC?&5xrz9?-qBfz zs&Z+e+T-p@a&A2Zmv#3o-zQwh1JcB);fnsvw$mq;V2YkD(CFDpe^N5+b|@29h{2}a^c!O zh;#}r2%A5L=$3wf-&^7PI2i3xM{D>An~xA%qa~Q5@j+PBQc$+GIBfnRiIbyox#Hwf zwNC|+U1W(qMg2%6>-_F2^ixG%td%0H{*{o3#pWR3(Imhe)(%kX*;$Cd3Nc=vKjCCZ zu6e3JCWibvNoEf4JeCBQgMi;80p=j!@g%?;1kffOE#`1-PRSr zAa;E#n^^SIpMoqeA^ba`l+Skj0nK+=03g z_c$uW-qpLYbTA~GNKE33N&MWXs<-4hJ+&EPTzd%2&e*OhyLOZP+vl!OZJF^=6-xJZ zcco0L1Y4_x@rP8R>im3sB@R6`WH;En`r=n<^@Z`o>3&O@rQ>d$BEEA0C$m~SN?J;_ zQIr>~#wyUyBdf{WDvu*<7r%PQ#kdY)pzWOh70~-Q@@!GPWy|%OSPe zmyiCFLFk;1N@1V@v%;E*>858!1Guc{niin(VSrm#@zc2l+W4<_7~`A3H1i$NnYlxk zfUa)|lP?m5{PESomUxgJIv%zoJ0A8OJ01kzj%R(^^ATY~auVt=z9x3o@mc>AT}$tm}9f;W{3MxQ>SbuH#{Zvs-<_#(2RVmI`9X zF;m>-JFgq`e0dW(IK!19F&lrbE0SR@9f_(TmE-5T zKu_t4`$AV7tIjl<8@jVxrP!odd{J?8dcM?!^2=SmuXOpo+T~;AmCpQYitLn^Wmu|6 zU++qJW0#M`SckH2C@LZIrY^W|%6DxdytHn{i)8jKeR8c^^qH4!ecQgd)_3^2u_(0l z`)-T}jqehuJ@i}o=CkKi8Gc%~DM3?MxC+peFTXW^JDH$?E}KQ2S_g-KIp%TB_@iOqE_TT#J5BKPw+v$0%5e~lGj4-o<^_Y#AkgypT%v* zXYrO&Se)bY-o6yZ+}Vsy$IZcMU*Zm{uPYljMHk#uE}Szo+PN7KJ*;4tdGyl`2z;@E zQ2d`M1>c|h?<4w(4Zo1%;b39wmpJ(R%6%Tyr#%rJo1Tb%O%%$c$M~qF${YVi9`0W- zFUils(}h2d#}0{HsAkS#u+IN&Q_3R}`8(mjY#Y@M!4c41!sxePE+@93omHav31zKy z-XwLlm+CC~9YGZ2_k1K_l?y>J`U9TOtOwPCq7&Zos~%aX%LBG{Hr(LJW+L#g7n$HG z_hms57HO8kai#jRgc(T=1yG2va}aTtW}`n6FQYks;>-TepXG)9f6ik@GN!~aOvNOLt}*97ereHai4HI8xF&n6|3E|gS`GKoRN6jB3WW4`YEN!RaaxK1^2;mRI&o zovKED1>*8~zS)HNUAsbkmc3vP^Q*DwsCvuB%59?J>ogme%-gBBJ`n@cRChd1BA#Vk zFAE*dcxc*qW?UT*gpE6+o;HfCwr)?$F`(zI$Wkr&Ld~=MPEQyj>XP=wBPbTc^}TJp{rsrJ$1_E7d|t(rYcl21hMfYJDtQl9|Y4_57;q z%h-K#Ia&S~>oZ~&gRNb%CGuR80;}=LwSn<=i04%-AkPuH=`tnZyPdw2Q)9|8eD|fi zTh#0Az(;C3yr<$UPHp@YoriT<5A9(&iRYhr1$+V-QQTtK**?6#m9BRwyr_uIujhHrW2RVB=8MPyhYEQYgEF0~Fvu_Dn5~`ul z7{}MoGinojE9Zv1s$3h$#yjJ4R=GJjs#c@h&>DXv>%3n2G}jhiE7pvb9#}Bpz&0s^WGbU`C-96<7gB;|c+8T-XJw_P4fOB`l@CzezGtaK1v(-@lUe z`!;8bXQx{W?dSZPbgVBk2c+`j_70;(P4sLCBCE>*>atNM#MMnFxV$hGOtYH=MrT)b z23&3q2J2(1c>~fhUo3!*b0^D<4zkmu|NiGTky6Xov(i$-%7lg$ z&~TuYRY9?8`eL;bdZGfj)}p!7Y~~pNY8qL03!`0eV7!&z)@nJU-4w%QDqk4y-sRh) z%lGsy-=1B*y}EpBx_o=f2fdO558-=|^(~ug-7tr0V`nc7VBAfF6ytsPMKMsYfjU2W zLaCZ{8jn?X`#BaXtbQIFRU4KpVN(NLJB&1d(}d%F^*uFRI?io}k>;?9y>0G_t=uZp z4vh0{%3GtbXUcx~Ib+{OBfsUMSpzg@IlzPn1IMFTRcdr)5%14W5J|MKK3|6qXrbAU zh9gc9@Pg9vG(WS&;xk5FmH+aJUsP!kdiSE*dpz8zwm4vOz1ep=hMQhzDc|K za#^vduZyzD^e{!cd?(1)^*w{#E`dE95WNTB6Lb1lX*3fbX^B-f?b{tHn%M+eOK5F> zm%6sA`^HBRX!5P|7vrM|!152jUaf@*79%!@k5LpEM9;)A(H<8LGoGv?EH&PJ*Nt}y zWxPY3vh8>`JDrVp|0W%L$Q+)^uQr?yrq`26d@Mgustjc&NsMPz{49lLThCS~OALAS zHUBZrkNhZa{2aw0L~lf|yEHmZzB|L(%IW9g@{pE3KAwQu==2E|uB4$uumLAMBjrL{xrO?kF@OY~xt{-%K5%L{{Q;84KPqMN+f5JS%tj}vq(pr1 zsUnnOeqhki$pFVcCUufx+lW0}9wQD6pAdWBag8@a^~?|<(aTxM&xiyhy~ZhGybi!u zQf5v*km6fwA&{)>S^sA%H+M{-bYR5ktJ5h)lp@vwB6$v%4ka|AG%T9DMX-?n zB<*gX*V%RFq#u)Gue0ke58_6BD8%+D3Ass!c}XE|ZxMW%@yYEau&#zzTL5EV(=Gk_ zJT{Oo#ldG2ADN?2?IP@2W%v?u{rZn0RXjgj%;GO-E&`BAx^XH6Z^=_7mA;`f48gNM zB@82Y#-?JzNIZ^DBVGg4Ry=Uo5=DLL-i{}s=?>Pa4Lru4w{(seBGttStd6ovRL20z z*8FdDzF?f0m78?BCodV}DAELMedV}BiyG(?&|bshtW^htoT_174mmBZ(Til_Yb3~F zj3@dMfHGH4QPk|LPaN^flePb#NXEOot;JP#(qTJu z`amUReO|4<)Q9jQRyLYZ$O-8Xbeq-s;XY(v!Cat_-F?W>3VEGEc1(x7ULo3_RbB@3 z20~a8G8W`A9P%+67rBiakm~L3Q}QSdf+^gt!*UYO%SCS_*+uB(m#Stq%JE_Sj9VDC z#-m=f9`ohn7t!O$!p2u*w#+lFU3aYSMAyN|66V6~h5$_wZ+tq5xV-Rf+&a?zV)g39 z1>4)~guaB(c-&a~ojC!MPyC!UV zHtEg`nhN9GhJ90l8Pi;R101rkbWiA6PuUxf`|*vFGcstC$@0mydiaDJZ>B9^Sz|$g z!S1&j?C#K7=S)~(IQ9ky=fP3>yp*6)espqPe$iwpzj!k5m!h@hG_ueQRKp{KJu(d| z;|KG5oRJvU=8gu>vs4e|=o`?ddwe_$WRnHsjSd=Sxyl@ow{6#l9F8|bEjnE=knb&) zu{mP{Z4pv-qJo*)*~rpZOMCi*ihPjsj?n7ee8PjNvQw)3Y+ZC6G&~y`g8Cra{UepB z{Z461e2JNhbWFe6HWzLn&WPzNbR`^6biuA7_7}Ti<|(EazYLD?qS|68ez}|sJsZhC z7$2zRdWZ85>`cT8nqvI{3^b-JaixeeOhb$zZV&ye%)~o8Zz+^1k7St8m65TyS4xR* zs=UtTUC!>1KS%W!#&=K-$M@9nPM%9}_fnT&OrlH&G$s$A!IE$hR~@HaU)m?gWR4U6 z+Pe;iwHYYUY+c)jNE?wHVkB*}mdYJ8egm@B&T=;%W@Kzl$eG>9*3DAc4$L;rf=jKP z2puVn^o{hJZO@V6+{kc#WVkRg%q?S`>K*Pa51015hQiAR!KUH9p*}|GH!)JJd5Z#N zKjc5;)4mWsBez;V7pJ{6P({Jk8{H3=s;3f$wQPW8=R%}WC4Yg;>Jh|n3xJsVzBu#I z#d5B~S%@x4!x!RS=DF%3Vu}&@S9QM8FcsqxF+-?#Fra`5g-g!Z|0pbK6>B@7zAI3W zMy&EK6BmkcZ#!T+k=9d!W91%M`+MpYXKqkwNz)0YN^V>Vo9~i>Bfn)R>@TXD4m|MGmbUUAkgEKF5cwP)N{JguQ>! zR6uKceunZWG_eZ)YI1GuBCw|W6+hy8B@ZBmi!gmvaD7!?eN|4WG>isA+9)dtK}Njg z=z^9^pY9VWTj`P2YV4peE6eBs@(-G7Uc#%)^%W`Fo8o^|Qc4iU8!1!e1{YT=Gf5b| zF3nhP{D_)=NMVHo|4-$&c}23!bJh3aJ7~(K=?VajblT!5WXDfP8rdPRg47my0I>>y zMF{{?vb~z*YU^?a12jQlbT0+q;csn0S1TLV~;_*^(;H=*1fvF>ghud%>VNFg9# zsnzrGD*^4R?m#zu6)u$3(Ss0FY&-y`=p3q--uP#DfOs_!^}E?M<|PI81O2XXGTtrD ztUSW)6Kj5j8<`Wt^Hdp_#;v$aZcOEkUH(*_V*EQ@wYa>acgaUX*QgoVO3M~8YHLA8=Mh=2YHdZWl=9KfptLR- zel%XM!?5QC@d0>Vt@8G8<9w#K`jT)XN9%+7f^Z|^M^GYh!ugPad*X1h@c&$^T1)|oZ z0Zrp4MGyEhdUPMJy%qA&Z-MbkpC?$- z|6WN$PA@2=YGUsoj+F)n?zB3Jo)BozOk&^J6^q?g!{p@Ry}o=lXxLyk( zoNj2EpB;q1(URf|2n?DcK71Mv0B{0uu*b@RSZm{tbd}rUkxjAqNf1Ob-8RrqR@kKcfUEji^~Xb#e95yC`Jt-n}k4&gU!eouN!`eYwColH{5 z?6!Aut}kmcu%k=$pz^&@=ti>Pdg)DerJZD>5T>E?HuE%Ao*b5dGMVQ?o8*YoX#q|V zm&5m}j?a?Q{&S>f>CbiqdF0|ZDTl<1338WZE|*=sv=Xv~f{cR@5Rizb*!XYQ(^mz& zkVjOF{^=@5I-zGl!%5=Ly7-5T7cQF|Yj15>ty_Ri6^EoZH@%vSWon1BiL9Vi97^Ys zx#F?>@6Q!=h`lGjp4(blcO41-ldX)XEi8-KWyvOGaXCyDa~o0b1l7DJyP$1LEWM3H zTib0amzfXVQ^1Rr_K@N;zx>r=rLRD|&%A)R+`8=Q5^4oZhRY}rfYILoB8Uyp{0O1r z!`b!dcK%yQG2W`0>MJ-N%n9KHd9-b+gyMKToXD+P5IWv33VI7USIt4#8~q)e%D1{2 zdnAPkR~U}bVoZCD!%vy)51W7r`%k2X6UNY?S`T?F&g zBe^iwXteMw_tBRU%~%Gx}qU;*idW5 zwl?ErlGEYE3*l)P(p<#}>B9|*4TV+G3Yl_I_Mvtu)iE&-hMq$Qpn-G|f zda0oEq)(9zw0DE|w07CtGHwLDi3-_YUCa2ULJsscM<`}(O>d{T(puGa$@VrEhym=Y zm1={8^m7kUQc!g`_rQLII?HNX0&BTs%=kDm87}~Lm{F)L%wekGKGrEHBXjFUW7U@A z*C7t;ySZRt=D9CRc;WW@Y<=q2{LI67^#EkHyt&xi?3~a*M?1ZWN-^z>y06W>(i^;p zatBtYQdvKpN%}1+b+J>%aP@Wzf})ksg_fg`CXg=_i>a?0Y9Z zKM?MPTt{CVh~7n5<5GS~)m|=yz8hEld>rq=F+rO5^6j)*lm>@sT}q&o2Ay)sWJ|3& zq-)E{WfGIiB8DZG=0G%ly+Es;hw^3XaA2|8{4}+h?W#@FJghl@1!?+pRJ+D>r#3PfK;>ud4a z3#ovB0~Z!ytARz#5v8((+&zIEJ-LjU&wCc7Jxk29HbmU>pr^EyqLK<)v~AE5AC%{* zb<1J-$@MWXh@kjuDvewo<#Gq?$=#sMNPF; zc_nXm1z$otWuzTMiR;RH6EnxjjKdBAQi2{#5eA-&!YLH&YGrc{5kgU&5I0XrW|V9( z4{h)%wWkG$*Uxb2-2fDS{rRGRU6&-(z;#3zEYQ1cGeP1a0d482| z7~jTk5xf845OC|zL_Gwg3-1nlZrQXyRZ56EpC%Zuh1ugTz@Ts^xklXko)($o;9YrC>!OboD z6`UQ^X;{56XZZvV)O%&tlELjS@L_`Z6~x!?ePAKEzECK5znu3A3f{bE{4KB-jf=^A zbVR1U(YAUs8UuDGzH$NVTaKe~G(Y2`wyQAiD6`F*$`ZF_H9?cM)|CYONMcO%B2sbc zkY6{7OeT9EY`m>l&W-%k0zI3r6saX&AqcVKRD!Qik#S<(_ix%WxY3Qb-9pjB_MJ z5fGg#2n(~#B#mW;?l^=nqn|UWHvr>QQX8hZ-o$O_0a75 z`f!_vwQ#iBvzP_Ar?T7?P+t{JUzNYIVS0OG+hVcpBZSOor;@W3TTnnbvpmx~ z01+(_7Iyo5OPKRB*?2xsGq%mD^~56Rm(Dbq&~iZxn`x|NmjAXNr`+|#r?G#7sP zkVH-h&0K+dN;4lVK}yhB9n)_gEcWN(uY#y`h-h9LG%c(tUzghWFpgjmrX4_iE2a`g zyBfcY#B-@#}lcSe|#7_2|g#)qK(rXQO7U^9g zZCyw=%>1M=iZMoM7I@?;h|?=G%F2U{)G&$xsm}qTJ#uG<(dnu0WZo&|Q<~xd`r0xQ zo2J;UmxGMt;#l--Jll=y3;jU>mP`_R##SH?^+5g2zCD?^Uf(`FCaxaZq7mL!c$~Cj z#R2>%`*Xqhs*!MPFlvym1*jO|*a{bLGf$~#eIi|sGRvK;(>zM!_L;-%dM`2Mym<9S zUzJ^8+-6t3wybg~kK}g_17s)>e7=TOU8y2h=2fKB_J-!Sam9;sr@mnw$ z_k-v>vUAZ4XpKjSK;ZlxA6pw_GpL<24QL!YyX5LTfAZJ?TYG3@wL@LHAUa(*tf_kZ zLNjVu(jeBfw}D7h+UlQfX0o9RTP$4z;)dxRZQzSE@O_f1ojF_yOmF(kgpUkVO6<2U zj|2dj+GMd5SBDd>HU&_yjSk-$e%{SU$H(!^*ddOOepieAsbhoY5hRXpqfy15f||wj zImU|~8$-{rHempFXs|Hh>wa8xGmS|x^y<$cL4r*o`?MOf9onGQ&qJ1@46LP5gFz-<0q7LG*gQ?6Ue{Wb4VcigHcU z6L>QaK~uPx3hnD;AH<>8DX|V$`wi){-2525nQ%SG>b)1?m2C=v+ga?372qRla&w$o z8MqaOTsF_zNiFMh+9yG0sy!xS@GnRtZ3~J&SJlzAaIkWrCrRgkY@UvE42xk)iK6Yq zA*ZL;oNedDnnw}i=j^JRvlZg{K`yf$aFUA_JHZFZ#!z`-FYk6DyPK@ZQ=&JOZpkTg zr?k0-8|3zv-Y%R+FKAB!HI@UB?Gpypc#(jAP8)EShSbhEh^5iN#`N~?;V2tFo;R0E zK%du6terS*UmD5{(;TBiMqQ~McAa{d4kkIdFxx&SnQZM`4?ycP{BUphv-a_;h}P%i z3tOMpC)@gheWDv_itz{3oNpkYitTVq+Z3?v(KNm&*OvtC0&R`)1Ig9Gq_0v+1)!Ai zm*rv6(E5rTPVUq`&_?Tf0tw@<^2^2Jukm35v~;MLc`EAbghV&$=NtTtm*SiF@&4w`gal2|<-)V^6l||?GsnnUKm$~^mT4DU z7&ic{xKw=}ch=A%cQ~{jMWKVj=>eVry{|NSjiuifaYkF`&W z%SPV;Vq1b-%C>o?Z8@5aH>wG?RFM#0o2{zz5|zTZz~f-)jRpr{q1ek^U3XP$965OJ>k+(xP0Tg zNaEkS=+7*RGV>^g&6k?fU7qT>@qCihj`oQh0psN82(VsPu=*=l2eCSFEB=J6JKd%7 z4p}hH&7F%gtB!K{{@yVssiKNnORhX|3le#z*kXh z|IhB;+$1+4KnMwh5~QwaDyS3z!Gek%jRFc%6g!K#V7uNJ8#YjEDA=$oc71l``Rw{E z*bxy>5e2dP)Mvr}_j{(?O+er8e?Q6Y%y-V5nK^T&m!&0$-fdyy-jW(;qNx z%kl7=Zi1)qX9m%9N6xq)XIx~B5}BVsseK07NpQg)_UJ<}n)L~^o+tH%x2-!4hR&hj zVO-Mz3p2>x_IP34R>o1uunT)4LDUu?^hid}`Oyk+)3*+Cq=mU!0zuSJzlZ?9 zj{stbhCVNyv6W&9BV)(B87U`|0rjcdlH1J~Ra~vP60|k=juNdAIi*(t!2|_K&M1b-lBt?ufbFV_A^RiqK_yoo>IVm?v5O3Vg+1<8-dFA zAjS44Y<0#N)7+tluCleGg0F~Hf&d*c>Nw{gPD9$vNc4X&#pIu258QGs0=s<64*c}K z8^#yi|KNpt(hX9z!c397)L!EWd z<9qHo&LY0$smA`$?WA6u!Tx+!?piv+4qw~m^|Cb|H2E231$$}CBXsd74i@0hrvd!z zT$99GsJV~h6U2`DOGMh7zHoF+q6<^O&Gc_e(C)G8rQH5V0LF2`Vc=X(blyR z8LQK$OF9mhbi{S~b5J>*CZqHhK#)L^ir(mXpl0!Z#3ugN#r-qn^m^@|q)FZqLPm9+ zOd*oR50f`vf>83NJ-k)l<7eoluJfjpxG&6*=7puCm3&MnOsT6gC}VFE8B3`7$l0&p z6IVcr{*(U9zo2K>r2kseb2JhlD7~?B`=$ua$cAksbgmIh2d}dzlW3i&e)J7I*7++B z4Wjh`it@3C;#)xR1<0f&8W==hf~dFvMBjlZ8GTRRc>jQRRoek;@fl-xHAc(%30w-| zW2Bri=U9C;Om!Wn$JjjIdgxSbMk|y(l95hikHU*%09yGL`>3X)>3RbCW`5L*$r>F) zf~Ys4iNP$oqv8y1p&_g!icOuG)KKjdw{ZdujS0gF^u*+^+Gc8PU6JWXn99J!Ok<7P zqof-j8(HU>yq=1;>^(q3Hze24RSk&_z@9*yV8y0Dvt^MdSoG#W3+OF`1KRrK$>>0k z8{9{&A)5>>t|KgW7Mr7=$5Li2LtHCl`1oEYr*-Rs@|sdVLuZ3TKO*Z=uyBsEwrjH6 zlw?)ssgoRyY>Oq$WE_88>0mO$xQ8!2n_B6d=mSpT@mq?byt+whnsiUNG&BEXN29hL z!;^Xnndr1;Mh(-4-UxX26QHp1@bQKT|Nu z&k&SVPG0TNiG3eIK4ZYv!p+Xk!Wm^AyCfT#gwYigj$1Tg^mJi~VRkSz`B0VG?15-=W@PZ<}R`Zcte{MWN#Yl&FT(dThu z*5uA7YjI~`ZH+L(eGvg%cq+#VZIw5C@<%*jmX2HTKHtK9Pf%H_k|qg zY|z+QkOQxfJCW~>*_n6+;nm1Xv%4c{uwHxE4H0=C->6seB zUYQJ;Ma!YBvb7Ggo*`+kGX$N`sdW^7hWx_INZ^OJ^0iq;QY3KuItftR7&!JdWfnrw8gh$*SMS?V1m40{#!dKgR)k;@`(V=S~OVzveAJn#mZT$8jRxg?`l^ zVFo6wKKbFSzjiul6KZUpr$4`wewQN)-izfG=AuO-WNK6!qo1IE;mPF0>pdz&KowYn zH_ks>XDzBTL0HbsL6ZMZLeQJx8J=RnxF&>gX5|5B_COUQo2#aj39Fr1%n}B$VsL1lfnxusU3cS z@be2LGAtT8&WD2E1rq1$q|{?XA_X5cPDfdn5MAS`HqkYU#wrC2i`YWxP$HH_7PBV2 zp(CgBHQZ#LsbHjU!*TY7Ooz@0ou|1>FcK`6*w*xn3rmyMcl{gjE~TvWTwM#D-#Bj9 zJcQd0{~rG342Q8JuGAnXxX1}sW`549%WPeu>W>;%SW#&-lc-#aR#%^>8H|GdhMd*a z=EO~uOydZf@$7*&*NCy+19lkvM$C&`wTm7*H#UjfI6l>9VozfJqtkD`0sC*H2{i%H zzdsY3^A|r8yNSPJ{0uRkiRC+fCYEvD1M%R`RII3JMFp#VN2^+<6-Nr<64rRhu$@4$ z20(NsoJ;XV=i-UeSm6x3Wl`z^0;pE$Z0ax8M^g8N3ju0IxX}`dhf4rO>3GZ6g>aK= zB<7Gv*Mg#$BD>?kV~#63GuJ?3Xy%wrShCHR#;912DbYb6#g05jAYuC2tE zc9S@W2^6~^VY--cY%Rat!RultzZ53(MP|4?C|?AGk3l9PpP`!qzlof1^d=@6)@M6_ z=e*W(X~~)i#}`srrxql16(K1#RR_zuo@crQe1a%I1msl2%+HX)ept<<*fGr;P{))V z{8%snADG>dGRY0fmfxlSo8QvS@ylz$@0d-bfaulUw`O62S#=G!>_s_TS# zoVt7&yzK(qWbZC>6jQ*gF~Vg-jE2zK!X` zw||iQ#wK*01AWwvxr`f?qkOzkR0>2o=rI*qI+@t3>!A@n?*KL|xWdNH`*GgUQ{_n0 zdfpB?8}T?>*KTw zO&k-%E&+1;$2)Cl_l2204h9Hz%r4#k?Me1N@ba4AV$2mGE#DYD(>!D{j-O@cjY6E_?W%{f)kr)7v_3QN9jLC|Hb`&{~C9LvaD1^OkM&Q<))JVb2wtgfJR{n!Kiu8}yL z%Bqob*cJ7KH6?!dB2$gM5qy>78x*1kW>`sDz4pViQT*8sybM5JhM(FH<6R?v8FmUN z_pu5mX(07zOLKk;eG~F6uRgP;vmH6I7{9_8*nwkEx2Bw1=)|X7S;>O1X)}omk@Jkq z>I?{|m02+WIL!iLpd36o-+nFRfHqLvi)sq<(aZc6VMF#m%B2xm>rV_Q1N6^z@8MXZ zrWvCeaT=qYxPy#vw4N!Ltz!~IouLMX0HaS5V3~mwu{bvYl{kw5aX#GwVgS%=0Wlyl zbl{;=l%+FaWYzWsx$=hW%o#vrqiDE}7^Ojo;vumBVgPWK1;l{7rQY-W|8=4#XA3KS z3#k$b!3q=swv-tfYPZtws0$o<^#nn&R17H9w(_Ve+@e)FauwA-8K2m`6eGrIblPIX zx^c*Xk|>r-?lCzE@9P;q?G1gvbKtwi1Q{+us}$aV2c|j6!35PE5h>zV7^@f~W|R5m z=2!9cAT1;2CPk!kQ}6v4pejb|bsWZlcvNIJaBP5o^_vKYl!v`2$}W~WX^+^ zEFX-6yfITvK2cwIs~E?gOU?>)9j)z}IO+!?#JXIwfIO*toFg)G)#NC1)ifkythQp! zA_2z0ZFpWzyo?iu3^P@iDoI^0MyPRT{v!&_B~AJN0SUJ=?U!pVqR zXKUZlduKVfcq9BK_QObIFzAc?rVEhX1b4I7kUp_rvVI6Akp{uBIDrG~60dI>ufr_L=Li`MlT@$NoJ7<4EM3*e zH=Y%aYG9E34b-;aeXG$Up-O}|#T2L#2Ou>+1VV2)h0$$0`x@NWp_MS@R~2e;bo9H3 z0e4uHi4xQ#%6UO2rqyl+e~f}fF^e!iM7_iv6}oJV0KXE>^FvN4o6ydhXK_%Qj}H;A z5V=y=mH>xdfiDLhV3UwIH<=tpczSz^R)_t4(SQo{RV3#F`Q(bhu+AQ>ArpMx7O(1i zns%3+z&k-_(zS?XGsS4Yoe9gX5dbxY`1o&9Cn zf0+d6hyB3@r&o~pYXW75J3_&~Q!TROoKi=2*IzG_>p<2FCe zz{*DEZ%pE3cITcz_iC^(oCrrUnP@%{BzhD8b|OH-&NN(rru7531<{9imPI=vsdU^G zj)`alY@3jbY(cUUNgim$#gJ5lyMPVYm5U(}2{B~FJm$WTd!#&a?1b`&YXB&iJnUh^ z9#rO@?mtC(9N9^aBXO6xr7F-=W>C30KBz>-YT5Nuz4z3zp;s`WPYcsx4XI z%w;vMdxL|_W2JBscV{LJe(0C`68M9j?#Wb1T^DQec&cvG?3J#B&0gt3@Ya*fbLjt1 zy^ONEu$OuUJpk4*cOcw*MZZSFO&ZCRX>PVP$|kuOPJ*-Es3pZ_7sMY|rFTnyruYV#h%NI|;5a3%i>&5gf(gIsvK_b}_2g`(;=;u>GL_xpKht#8wVy zMZeLk6^LzO+$PiMGqHJ_Gyl@3;WEPJgtEypf)KG6i1846pU(bQ%LqcS8$6(0-*gRu zJrP+$AXyOYPCE2{#nT?NKrg5td*Cg5xg*YVG&O1{O2Ug`f>6hPR_xBsvC{n1utxv71td$O!xEz;&#i!?^Y5_W+&pw|gCnu5je z|2}?MOX+uZqX&s94Y~ z!Dxt1*E3^eb1s}{F-}td?IO8|yATSdf_+!qVJ0__PIVvKV_EW+XmJrxk6x2u4^+bTqL11N&bLSd%l*Q|rCx#T znJCixIs!EUyjXXe1z6m#9dV1ZZ|t)2i5>Mx@rBNV1lbmsDf29Xe92hLXuRKaJEAC& zX`F=E>-Bb#PY)9Y?>LidA%!4?t7>q1jlPna2ip=SOD?|4!o8N|Z6IqrhN5{1clm0J zUd7tj*jik7z=;zC&#-``I&s7OXmdfuv*-$!hvAuF~AJLCNzWM(A(4q{!t5c61j-eb zx}VuXjtf#DBVT_8cNsS0Gum=9*-YYX3iIWAyCr#r`{xu&zGCcjyMk$m zOA&%jhX17qsM~D+gjNe9r(4E@mV@yiG73}%?}tp9x=NZby(X9U>90rVt1q#7-xgD- z*CJfGT^1=d5^ohqaei(40=dW_U!G9`vqcA7ATgcEQ1C^J=mS)ZlIr^Od}i^TEwY&N zzFZgMndXOG9)_4`P0d_S{STV%frs<}bfKYf(HQ7We2Bz0RF9FmslvW`jKq6LdB*t> zonFmH*c1ingTSb`K&D{x^1*JOEfaGW z6N4!R)(^gk>VaU9y_*iGEtod$v3!(i%OwTfLQ*871`zZ1WekHga1el^_&Q&{JGp3=OLY4?!GJS=>d^`wZztB&}bHEg$-}Ubx>!_xoGA<61@M{vh2S zpgU$rb>?Lc1#672CNKm9Jkih4r~{5B!YIevd3RZcq>!~7f{zY^MIZa=>30q%!G@W` z&f#Plq-m@b=#iS@D4LJv;}|@eAJ!Dd z5;zVIP#;h8bUq?Hnjg^=GYFi32Phh8PV+GnkLE`;#Vi6R;sJ`2Xg-;bQ}AehOjDdn zAcF@ePNO-?M-v{+k86t42{hvYiZf_FlaI6TXnsOdoK4^yJU}s<=5zTt50B<2HO2V^ zF2Dm67t%b3kGXg>Kcy)yB5*MtpqNMVC45|pNAnU*aT$Tj@c_jYG|%VbN<5nXsVS}^ zumBHGETs8rKCZ!|`DsmYErILs0LAq*FXH0{JevQdDQ+Zi6CR+rndV#gxD}7)XEep* z(5duon&JtXZzshaq-i>|-wXD9Y}RIV3`A{;Rf8& zfmCV(dJd!>8?e@aR9yqsIgr|Fz5G$3yFH)*Hl8SpR%QrQf+ z!HJIgWxz>}k}73DoI)}@sYM1n2`#S{G8M;wUpY$Zh=4MugSJL>;JU272pijqd6R*3 z*9?SFU25>oAoC*(60wDMDdv-PsJhA6KDo3@OQd&lDb}CkG^NRvaTt)^dBve(kU$wBo^BxV-c%EVyCvGL1Le8LBn;tPMj+=B84<5W$7^)=vZ`&07=t_ zRRa*iCcTiQoa&SO^!4rO$)?wlh1GugMwCMo<(FBMUnArOGD*imZ``^!Ry#LWQyaIc!p5DPqiY4MW2$j4=jf_)>xd7(I7e5lTgT$Y zM(60Nck9@uvDrDgYTi1QG|r>rlhE6xuD-U8Z5tOlpRU@sj_n%na*nQ{u#W8;mpDgP z<6Fnl#%0d&D_eb7#}18ao#WxQ=F*Pgtyp|+ruyr4Uw_jcMFu@=mX}=7{2naKH*z*# zG~WRe6wP<}%FDh-me}THN+`Bzmtz(RmkqBsMU~_%s-)*zJeUe0a3Qoi!iMTMVKq9D zei=m~`#!@+ze3|O8iVWyEbdz~L}Ck~*I~stF;Be-eovr&)!w5wfH&>Q z*e`_%bpn}2Z^9hCg-20M9j4^oh6(4xk_EUh{T-O=N(C~m z5i@MOFqfy{Vie%`mcwv-g<%>G^fw%^%ffvn4XTC9uzj5R88TU6dl$_osXd?3W>jq=FMPBE{#nyeGPnij zBU(qr5+2?Ly<=t9QWSHTn7@J#(w_=j4wiBVvH3%ou&*aTF8@lcLjEUYzR-v4^KduR zSd7WqVUFqz%v?nG;eoj%_i@c+GzOD9eX*>(58uXRE~o-bF0H~FF^+bITVn_5plmcMEo`wzYcEYcfU>i3L<`4mor@POW63u zO=8&L&b{#I8yJtu^affh(-r7&5M3#G(KrcSeEm_4%Tds)M>T%a3K`$HdKze=FW?*_ z?B6)_NWkg!^wqy{Ufhy8%DFT(Ho>x#8%U)u6Js-kF{y9d2zU9GEzFl34YS0fzVWx1 z`G{k3_y;lb0moXL^WW^x9E?0~ybZ7~`i*m6u_@_T^v5@TBSg7W&7pk8H;z26Wnu;H z-*^sTo!I)uRj{O2QGoT0`N!wX+tDo1pWb*S%)UN1TZ7pW@aE9@RK` zI=tvON~k;G>*XjPxO*+U9q&`CU)QxUciH_5w7MSl%hOLHhqE7pH*N^VGy5rxL3Ry8 z;z42#`te<&wZ!xokLy+3e<1r{KL?Hr3~*-k3sNL!k@^-s`iRH6!oGA| zr@dpYFHc$F5)0T)4}S|)|TnK{b}RaRs925NWUPeCr4FJ!_DK_h}VVi{QY z$5NP|%NNIAl9r6VW{m8-VU;Qypu@lhe{_+sdhTOwysy8pBTJc_lrdjbToN0~VZ}$r zaZ53~9v{YVFGTbXl(T#x?hlNO2J?Mcn!qyRe7Hs&4&r!&kcM}#+HRC{ke%7(r5<^5 zA4VbdzNRuNC!JEEXr)s@fug{DhX}&O6SW?+q2X}GUK!)(zwnbKgzA9)5NF08BYeFtL~|w;&RK|GSsmnN z597ne?^lLyEx*MrzsD_q#4S_+=Z9CoIm^bl%b#%zZfWC242f6}d9)2NHXPZf)kY#{ zL78Y_%WLT`*}@TDV9s$Vpk<6v15^rLRdP!9398R;7CP&gpe2@P9(D(dWL?sWcYDZ5x4&g5vIH z7(k!8j@tW}BcTU=rFgEXbe?q@xuAigie!vrGpe|)hOd=qDY}a2H&#l00WqmP_E4#g z5Ht4^a@~qQKb*j%@GHp-kT;{c(AxT)D&tYLL5$lp2+2G08;W%+hOy9Z+8aZPK6Mp+ zoA#2a;xU{WZU^>#n&}cwMR53>VbeY>$qvYo(M6N#I&l~Sz|X{)SGBu1Lo^AIGr(~! zA$cO27Q%pk>KT9i`|G%}U(Pd9PeV7-V-bD|AE`V5fhQB$1Nq9!HsIwaHzvo~*mde0 zPGbUY^qcmDTP&RiT9Q7^bm`nl6M{eGejo$JZ?kFG#t#nxQ=Br1B?6mLOg6;RYc!%o z(rmhHK68Gn2g3Rn(>30t>mZYoLu@p|qnQp%`wVFhHM9pC+6kM|VmebjOWKKs7K0he zYn<_NSW7RcUv*rbqn}B}&v-*Txg{}a>%sqd(oQk7hiLwX@|BmJV0=z(>67)i_WJ_; z9&Y?j)P4`sekU2fM{Le7<@F-{PBVTd8|oulQrmD|BJELzc8U&Xst)IHxCd6Z1h>bRHnP0Dv_Bca3O~>^}DaYh4LRT`HJVs;rpW z1|hC(fk^a$e(&P1aqK;YpO+!#Fh1 z(!)VH4|FLnPve&9l%pQglKS8rHC-yY#HcBUQOJ`Lj&F2Q(Gg-wgQyHV`=s#2T9HOA za7xADSjA7^v`Z4J_qj@*`=f06A2LMi$TZz7b*VQERo4OLEEP81NrM&OvM0HT0jEa{ zfD;^SO?bJYc0v0k)jgVcX}^xqV?9_mfDX5W=i`IB*{@)Bdl2NDNrukinDWK!XGoMK zxdtLk)g)J95{r~caj<>cV%5DGpHRn-{j$+C;1?u#R5hp#@VOGR;}bn;_TEET`FCI> z%SQM#(b>qxggnE$I5a?q{$+Od=bJ0x=vNaLYvOP_#0fhEZXnfSJv5Nvh8}DbaaE+) zmwi&_tQcKG5i27r=qPLpWr!OGsw{g5~4>D z`w0}$U?1tUPS5xmgp~;IMv9vL3zL+QUtrjnoR3JRE5WEwGhM=anCklU6^uJ69FtK& z)CFWs$o)jrjguDBoT~f^LVQ;R&e`ATN4Mu(57N3qcid_CM|~n$F(9Q@q65DW0iah% zo%V5Kklz7aVEnpZeE~D&>UEaq4EB2rZN*QYyz7FXM%3MR317P5@4o0c0t7trYC}vPJ(NYkFAL3Dy*El_2&A72o z=cVW{>m4K7H&2qL+9%V`LKjcP*FL)V?ens~G3FH#am-q5Z4+VQ-vd5|Y>kiCYQbS& zEt7@G2uSiON|KWSBe!LG@SR`$r|>@m|FiIqewCNNo4-DgAOA(zuupfwBtzaipydS) z$oULoWhU=VwN@#!1L5}#mq%3_2S6gsdQpM_MW|FHi&8cD<>@OCK@PMw!aYl|iDq60 zG^Ro-a4O`(h~&sPIj2J;Xr)6p{gn;{>P7fpD)FN~qeJHcgbtw?P=_SMOaSMohv<;6 zEnC1ct0!cJ!LHBYzWFkDe>UFY>p} z@-bX`K;CtC`yo?=%q3@?xi>J0$Xu2a=HZehI_sEkIsv3*zUkPQd}C;_d=sn7w>OEt=k4jb-rA(H#;)eR zfo>_JPG)5<9~DpOI$A1!snv6JZ+-d!gxp+2>C~qmqPbX0O1B=^m&Ph1Aq>c8}Y`NtUc7LEeQQgJCfteEXl^DGt`U#{vvDLI@GM$ynXUw1@j9 zek1f@lTojD#K-uVQjnst>VQ`wx&{=G&Js$e42Vl%Wz(;SE}Z^Fr}E7@Jx8Zbai>wi z(xdG{W4MS#0&TSP1(@!}!x`;zL>qixqUSDg&n8IQb{^wry1^My?T(k9slqc6eV`-! z8h!WJjPLsNQabgFJM}lJgRR{R`E3&PjuVWD=~jq-gWQjuYh?R^)-1^u9 zPNt1rh9EZE#wJu76qC259-u!|A6Q>X6zA_6K$qAy?1uj(_(yfQ1~1e$q$|j@^{|e3 zQGn@`0^Wv!%LEg=?8DDsRVcwLc$2uowjaz;M*65oeROlqKfYPt0Suydkqy~eQlUB} zSLWW;~UgFn`}Ic}_TCCXLc3Wd!u>{y*ER;f=oZ~Bgt zwXSoSgSk3axTb14l&9ZCOjzeKJFEgq)~ytB4_{-BO=j0Hr&imLM)%zYzz895?2>DD>E24OKBc%e*LTx;^{%9q{ve`l z@%mf6B3(hIJ@u*<>eE`Uwu7_PtNt)UujnJESG2XztAPZdS9G9W(H_?;2K9f?t6ad) zD+#%i30dovgsYkNFnUF~K(82})~k;xsQ;5*<+xF=B+6E=76CDK&s@@c_ zwI%d%2l(|fL-Ev^s`YW0pu=-+t@P0{I29jz7NQaI94XJ8@C@%{$T_v$nJ!vwQE4S` z=_+Ir$X)60i%dv>CTSF2Mf$3_VYr&1W0rV+rW5t;PSoOk@^kfAF>X2E4bEEM3bMPv z41J>yTpgjk@>3HTI>fR>ta>cVvcAlPuk(cQ%jJngT=L{QlP8Q~mJj5~?ldzFk|#gw zJo%M*vIoGw$rCF;gwL}qqw(g?&+G|*Q6ck=;}>m@q2*=iTObBMvlr<6%--_c2hWV; z&<41*t}*r{jTZg>Fv`3@uD+matA4sy@)z}mukJ-0(U@YaM}JWLF?iurNKt-8{jq3# zE@2uvW+ljYJYJGtke_E=rVM1`T4bW-<}etC>jZ3L&-{BOJ9i(U>Rw zka2{@kd@Y$5=L6u06T`8H!r6%IS$kriGbA^h8NQru{xbu;nJ#gh9b=AjBpj5X@k&N z?^7IEK46|gGgBryQw9pBCsKFh^8auU#q*zbe7(z}_&gVknO?E{pC%MX%2OO$<$ry; zGs0^|Gm=wIoEq4g({gxYNgzJ2bS(L39XXypTK7%p-bzQRDDKVmO?>qzbmSwE8~s7t z)A2HO%}mra3*inmkwD{WastSxCUmGd0NJLSgeQ@tk>>=BdWUX)=o_|33HtxUu$v^_HL5)nrNI1HykG&0yOG_ z@Uy3ocr9+DwJdApZd%&<(*0C=@H65sLrZily1m&9OnPU8_9?+k^o0VqxxzKw58mf6 zLP&ONoH>AgMs9Av_6OGcnJhdfq7c4skqyCH!o*dFX5g9A@QA8`_?adcakndh8UQX+ zv4iUjaXJ&vvhZF+*SSr>9j@Ybwmi?lvn2tJz|R(^bLB~MW;8N9yeG~E2|Z8T&&RWA zSGvCwcSkT6i2H@|oP%de0x*~>P8Z>+8NAzy!NuY}Po9_H8MYt*gGja=X^XvA;1UHa^k2@?+Hb0z7noH;DnQha!+;Z%&AY0A=yv6+ajm0+(uP>E2Ks*$i18Z3Qrk zPxz)VQM(OZHG}+&STnROlmm(UPKsPASsCO z?JD>vPmjX8kDuL*R)n%U-YtXELDSRUodn^6$Obt6=U1^`8QKp&FPml zEl$6n#%_mp8ckr2e)jy!9^i3mWf*_eH@=E#KE1&=7xmGMK+E|JLaq7`dji^QA0kkz zktd%>p3onf+zpTo`Vd^AnhiH}BmRjOx)F4T`s~G5L1q=mqP=0x?n3~*3A)!z^iQKb z+!v2FrI-i#2y|H3+zG z2Li6U!Vj4)4Q=d*16a5Xg|Wj&MZ+J#SNAm0NI5|AkftQ{$s6~c-iabr9 zf(3mPqU?06=3|Rcgcm-f4m#`%I+ct4sI5@?xI)?()K&!H1&Aarwhb@j8&|~6!MnNw zHPWpAKuv4g`ZM{C#!M`A)#U>cH7D`jxv?m#|Jw}>O_2nuETqZn|S3*R%o*^ZD z67AI%()#pViUxbH6S(-v7VUB1fpah8`NH=C58*rA84JwWLutfyRe15LCt8DOB5jz3 z7h57aj5OgSf@thD$>bd7yiIB8ZEB9hc{@CZp-LdD=o6fSFx(xdBghFSG)x4h(TXZX z=-&rDTTe9lIx0uPl@}y3g6t!WGK9-OI0wghyKDwQo^l=p(pGDbw?XZ`xe7k)4v(pz zVlMpR@(v7R!T8#!4roz%aZOcz!9r|XVA!~Kq9;&k4vgiri;HZc^7mqy$yVYn7OIRzJ!p_f5u(8z)`4PV90sd7xBU-h5k6bQo+7PvR%Mi zP;UoOUwuwy55)HctXVZZgub3XpiNn`7{WV1!u~QDg?GY|G8R8Wrpa(IFm4YKkGyk= zK5)q@`0-4@6udt}ewU-=W#pn`5c{H)`E=6`m8ikH>GMa^ai7dc4h4A!tdMelCu%EP zg3h_g0f^gLX*0j6SY}fjK`~4pdH4P#Uh9n;t-WUIrUK z^9rA*{hKlS7GX_dDW@%n+997%mEI4J&94D*zEO&>31$$Sx%GAYQf&IrTjPUh0D{xC zaDQHt9W5u1a*)fOe^x~?qpg$hY3$59i~!DVn>3YN@8Quq5xIc`3=0kF!z3F3^WOoc2Y!s4bA-Z$~W$4pPm+*ejMD$aX zz(w{*tY#bmF2#3esG3xOp=T>n$k^hry8&ygRB8~D*B91oiC5Iox8Q#lXN@*p13 zP=t_Q3h}KV(F}wi4Ivcmf@k;-lAHjrLtae@u10Ev5mzO3h8t`>&}`JLTUm^aCHb&& zHUOty(62z@Ig~yb$-aJOB@n&#T$+f|U{O01J6^VhV>B1-Mj+2{5xm!;%~lX%ZDkPo ze3!<3=SR&{k(SU*@H6KaR;ez(>T@Gl#ib@vvM#s!2NCXXfQ-3Me*0h+@(5Qx1k|$@ zPQ#n9a~1KO1;%vDRitac&UE_Mk~8z)mop)H?-AXle}}KljH}pA?>>4N5kU{nmf;TQ zu<3pd_wXj6C+kEn>9;7iD0(V9Jc0k*qNoIp{d=H`&|^(y*TKZz7aay&30my8qvKw1 zEH0SUgS#7!_6ugx5Pc0j$*!l5^6Zy*)u7~xHA5TPpu+5Dbgd9}=-8cLS)+)M1cMB| zv_<GAC(A(g6-lIZw0a;~L&nLzB8mha8C%^Ge33G;^&ID&{`f=7 zi0hy^9-McQB-(i=M%nfT(K!^W8_%qFa@FG*W?61LBV1)X^8y0rc;*YZXDMDO;I9Ei zg|-y0W^}w;sL_rr8V^Cit9#dfSYgd%~{SK$wQ)R~_iiWXC|dqBu(&2#1iK zQTN}#v`YK}`L>-dD@-8f*1}~V!Y$?|y>>6_mrMgCQI6Vyy;J#u6sO6s|4x$Krm9VH zeBoH!t=I!--6t!{@@Gv&A>(2UY9s8H0_=3kN3+>;Ykd^zVZRDpE(VCL8tgYn49DtB za83ygu=co~EzLcy%Y!C>Jq5lZOi*DOj)2(9qx)Dvjn+0y%#lVQ+ZbJh67(u)GB4s0 zol5tNcqdqqJq>2citWlc)D2h@LsE`Kjg?Bu2Wu+<;!pjA|A8=^i#IAnVM)(*#~I5D z;8%NC%#w((FBb894G!8IJq)8BL^r_+JJ;})BRZ!~hZQHba-{jXTlxqbYV$aX!!!C@4y=VMZaY^*c2(ETp6BaEdZOur670fH7!7QYB zpd~^ZEppapyiZo0FVW+BU;U^$xA9VlzRC^d&m^@eV}a~*#C|ZWBNB&1e*#Cd?mJkf zdWhpzjqiYG(Li%-el}h;_;@S6&;(QX1D(#HQ$?24GNmKl#2reG`j(WM9y6aX_kUXE za_G%gdKkyhs^@a7j!nV-P-wSSZtR7GIeZ@XH0dx^NQ1Hag8r-)^l3Ziw z(?!n%;&X(kj9SiR(7DxI#t$gUe=(Oa4XXOJ$c+9_jpGxpTo2(~#)ptKnmNqGaxO!H zP0vQ6vIU^=)7V9y$`;a?(NC;!B%*tP_Qe`HEttgk7;)#9spzFJIv2hR(4<960Y|(} zB%2}wG?rvP=yK6cLUIF2hXm#|TS5y^z9pP^ar21gf$;b=(TRD%nMb!9*D z8M!u9xXN12w}=SaRAzIQ515lQQ;wpDKZ61@0A^A_u7%9Dfg|>NCc^(R*+I6L_A{|3 z5%0PpKYanUf)))0(S-mo-tpy|Kx|jaQ@kgdB*|zF9L?>Q{F3b-3^2)$Q)q%{F5LUS z72s@!cnHLUHD3hB7#&7`WfC$jSkJUI(YY8jSz0uN5m?&CC^ni09A!Q z<=g{*0SDnJeHTb=9}LVdg*7~ZeuC&Snj5wGa+rlzH8ve0Ad2@2U|Cu;6h!j@aPEN^ z=8Ckz4eqmGp0v! zU8}wn;V}BDPq(FO)h4dHXxCD@_SnRAZ@O~)dl+QFdlHc9F2KUAv7aG`$uWqg0d}9v zH3G62FAcVW>Iph6^dKj6^jl^!s3a!m;wi7tDX*NQ(_WwM#CUG8Nj%5Uv#qZ6x(z0w zcFJ9DBzMTzOY6+tb$|D&PggReo(!oz-H+y8@lbn0u%|Il=#xmq2%{Mo6t6dEp_sdK z3;wOhXWBD+a1T8n2GHWGqL1)A@>;nW>1u{Czd?pvg|*RMnPI@-h`C(PnD%KMQ!?RF zX$Xh9azE3TZ_K~+2X!?*bf90`@`Ze6`QH)mZ;{^>D72)GJ_8GMXxI!709~qvLw#|1 zlg&Xt&{$v@NV9a}2VLd17;!GIJ`wlRKog`x9z<`#m}QLoP(t1a|Fp{YJ2YCXu}fP&n%OQ>I-b$m)(g>%dP&!ypfd#|QJjl_<|M&REa=5C- z|4#U?dC&SHyJS`UcD2c>p4)Xu4n7Z*Fz$dIUuw`bV(DFfP_n9D{iz_UuN|ZbhHckA zS+!MtpJdgL`Y>5FtbT`@#$?rq`rgT^L+S@6t0vSBshNycQ__ob$ok#cyerMSi+Oi7 z?{4PZ-Mp((#?VQmIj9?3#m?H?9_C~?9LYsT0XyxGjzNEHBsL7#kndr{Nmzl`3cMrX z4+)1uVMGowQYNFSk-`y6=vY5Qjagl%3t1a7>H6HQ?)a;4O(IGtnO3v~TD5|M7+9UfgxQ<+`{{X^sa6<_t~ zT}iP=oWc%Gdj{p{g@zqh^mI83)CtJo@1a8|4k$+GYx7mqv>Zj;e$)hK%&7k;jkvZ0 zlc&79D3A-D@P#r^N4?=p7xVd(+MbvMWsO_g+47;yfWoI*=3FVa-4Ol{2wy05BzWJu zg!m&zNjjw5RZ_K;$!=4URh_3!ibW*qg#adF-LgKtJ4G-$E`o_o$4HEsGMzq&arLMe zE)3v%FZ$k-zU$Nb)4W%l6NI@FZ(hLrYLR6SjWG6WjQv{kE{@B38j3N`jAP54Jb7YV zz7OOwl9Ql3eH~pF_eYfHtfTAWD5pkwq8gj&=(Z^CMjt#m&Ff3pWs%-kHN)o_X{<}g za{?)DY)!$F(0+yop|RzQ6gR~w$ayl+o8u@sPZ1we<#{+MZi!RS-w{M_jiXG%H1TmH z-END!(Z^9lZ*PqrP4o_;xuM)*TJ^kLZXYSZR%4kv0d00H=Pz8-j^=ddkz3L|vmhe@t-5U1T1@9HG*J943*G|VpT)*MZSDtt9 z^$*t+LJI0vZvZE$82T}I?10AbWC#$eQ)+N~%)ANUgaOH)!!YgX!l3YuvdZA?d+SS3|6v_xy{7=)q2 zEr;yKN)AqOuKV@2u5A$7n(r9yl6e+;4~13h%ZW~3CVgOCe|*cD<|6hwj7cu`9S7Q2 zos6Y#Ez=R5EWfg~*7P&{o$EI)e@8mkX-;3R zgGT5Q^*llgC4Z;7&`xxwJzO5`@rjMWA&{DuX`ajTU!SqD%DS{wqi)h^+inLN+M}p5 zbh!5nwp?Ctp*@87Y2E1Juph6oKJpMt?KeBaa_-^kgR4QOWA)?pHW%Lf)0#d*$LD$^w@WSOtG2hMMJD%4)Q~w!9o7q@LA7v#j&q3`bdxRd z`=K1^vR@B5Yg2b;D!^j3#_s5DO&)SVW2Yge+BC|U21CPiJ^sLW8<*pOF}L1V!x0z$ zR{6GWDp5s7&KPbZE+HAF`&yFS4dBf3T(n zE`IgSbU{1o`VROp9Z9tSn!}iusDn&sCF-Z=EnT}kE!~aaqV?~aDK@t*N7}SBD!`dC zC{@=WE`LBvO4XZVlzM5Vn7+4Ibf?9J?5MG%x^4+_6|qRF!w>@<#!c62Q>mIbS*g9? zTB>HDmeQsvsP$+nQCm3K=TEXe4n_Pl-EGKyZTisp9q9NS20f)dm#P5TsZE~_w@I0)*HwE!Tuy&nsVy2AgC(fpbT9H& z)J8hxZ@^Wze*I9QbWQ#5YprRdlfkI=*2jdKl)CXx@@sObeDhN4y2Qn50dz=*cH3dr zG}4(~n4)7^s;)FzmsH-fHrxa-9lu0xZ7NY`Y^zIDQay?Iu_jEa{a>{{+CO7W4@24y zucqtzD=n9*sn&E!M{9be%$go_sqE)Wr#rf0m-0uQkLfPGPn=-GJ^gZ9Lg#&BIp5;s zT;e#dH1%_ds_kIw#NMy#zD0@J?mOKICDqz;%jGzfL7nIKBfVNK-y*lPUX3xXActJ~ zU4S(=RfYJ`lvLAE8nutU&6dkz#8mUE-PyWsi_%T3L><@3N_XfEmhQo~tZOvW)@##H z_L&PMYAtF#nv&`#Q+iVBUi3UzQc&`8DPL||rYle`si!G*?a#I(U-zvozsFvoO(p87 z<80m8{UK{=gAo__&f~<6nG;%Ln4^2PQns!Ah zwU6IWKD4a%JCQdN41t?RCV40P*! zr8BKXz02}ZqI%bB9}2&j$VUB>kutWaUs|f|4M?|#;bc2?yF&sD{?EWTcqOLte!!Na z28^O1pC0Yh@26U%SZx7+?bLkax~6HPLP7Gbwn#bd5pD+O^A=d76L!`?CDa`&HKJ4} zd=r<*l7HloJq3CA{v5KGATv#T=xc95dYjOR94aw98`5EX)&ZFy$WUl4k^cahB)--z zw45u|5rX{Nqzjs)ju)iqz8uXAK_)HEAqym>W1-VJ?Um{pLGH!oQH^v{Hw)6)NTaK& zQBMo9zl&jwdPZV+7RsOYRimC0nx{~*e}IQJc>kp{$ZfJfcv`?f_Us@;Uoc1Y=tr!f^% z)$Shk@FnCsk#;~15ab$%9FBc2jA7(_9ib))l7GGBbA*~K2xova=V|H)Ah<{J1f{0F z$*`uWnZo%ZNM0jHsZ%7*2mNA^>yB$n}COxmWx89dqEf2vYQb zMy~N2@m(0oXEn4=ht-I$(i6GC@oB{O9+}I<&|cE4Q;qn-9#c97sj$AD@NQ5z^?_ap z5q!@@JtN43hjYlYf_wzcv@|bDSXa9kHe%k1p^r16|ESWqL5oOd7oRllWFa!%`1(=J z#0j7?fV^yw1|VMuO(ptK46B`Yiu$i0r=l*>$my8>C7<32&miZjj)E*0t!Wz6#j2N2 z&b>ah$fek{L~XgyrTsEhC%)=Y3zKt$x=d{)zDB$FT%iUCO%|GW*_yK`lld)3;i+7PcpyW zH>nt-o>FfMa+0Ch+Ivd9<2Qq*&`IMdwM=N9F}@ChuT_G4;5a{}R!e-&aq;<=TJN8M zl$JR@&#G_4*CgX>g!h8_Nsy<{M$J~iTlQa2zX-ApbqkTue^LD^$c8l<>FU3vJj`jf zQytK6Ax&5R6%`0F$I-l|@&x&OJ55vIzoGI4+3g&SJn6luiUgUqy+%U+9o0sV-(2YL zV!4Z9-RC&Jr^*G{4}CNp=VhvsAQK(u4^>w|PH?_fs2%}J0p}L!t3j<$J%#3)7)@_M zmbf^7r1}aHx|FU~b%I>&!dk7i3aBj`Zql4F%b@xT%?>UVYt#Ti-orRV$9at!EXYQO ze5Q5~q_a!c7izd5w>tT(S0e@4;6ndWjS}P;hkT><7G$8~^PSpP5YB$;(7#s)2(tKW zi~Oh>1X<;z@rxQO$S@bfU(|R(u61Gksty&YwjHGTG^pRyVM0^nXnt2m3o_G%{)akN zkT+ad8`bfGTwqdKfHHc5a31=ZE)1=H&>7vv^%@LrPMWk%DYIA#~#wiT|nju za^fQz+0QTW76zrO@r#}y&AB0`t|)9xyJA6y(KhtsMQ&t2G!Mj zM*7aE#ozqhwRkZOZ8sNUY!f_M%Iy`Q8EzHdUuo(b;{k?Phah7Cae6km_tqf^?| z>+iKiyV*|dW%%sp_xDN#>E+VCz1Ka#dSi*poq=92q3LZn5A}z5wF%Y$d#qLJ)B|Bq zL%jZi9Q$Jq86e0C^m{GMw!-JXr5b5~uk8}-lYIQRMTUAq6JC#Ys!!V-GAzNCsQyNa z4D)soWPwA5d*g)jf6!Y#VLtP8NAE-l{R@LY0^Y@vu6~1+dH|)j0m!A`gE1r?MAmtu zyoEy3&d{vzM|sx?=a1k{nic+T-pzvSV`$d+yL)#CQfv4$s6D-h1o0f7J-x>SDR(q` zdrv34E!wGmC)@b!?L8+nKbo-C_y>8f34(%e;yl)SKS9aAXlO8E^*$72CE7v8kjN^L z;hK4x^Ex1(2%kYNK4ZPLg1qU%8t1JS zTExp^ejOI0$rmJxaX)De3=Z|$2y#;l=^#j3!>4yJ!RwmGbd@gAz7%@lRe~%!IfrZ^ z$Tu(KkUoM8Fr4YDuOR6CO6Wwk6r^K}rcRKXV>A=FH# z<9#j&`@@uB@8CG^hdh>)N$A^D%jo8K@4td9e8nQuJwHhqHbdu0gM0nFd`w_r{N;R2 z_X?7X;fEuwue4V#zMgWvPV_n@Spy_6zR+Qv=v5{akX5JTkY0jp?~s$ceo4k~XBXDV zUY*b^Hk=#O$zHu6qm8e5!KvOhg3NI=8E>c{?>OXi4_}f1=N&P_q2qIgw@b1aNH3T6 zv%I~8Ci{z~xz<0++gtejSz>*i?Try+tm8A=8=GXlPr5*z8rcwB;@u<2xWhEEKwauREWR#u$YtJRLQ^xr(p>31B}lQOxyt*O zAaf^Kng!nTf}ADN01X; zShsq=3G$su`-b3F?+-x+J3hC0em+Y|Hykz5PT&;XjTL(y_Y2Pjwa3x zxMk(_d?=*y4Z?d@-VkKCi4T#F1Ubv-Dv{3x>3_TCOk{%~yDZEhUkkF}zd7U^LC*d) zhkPr@W$48*73A}sAmd{+KMS&Gb&lp2LE6P={uJaXlsL=BD=bBtt#ezJ4P!4G;$e=rONJl}gi-q2~fO`0q34KGb%BvLQ zVnm#&SOKI;kS6r3hEvFD99Wq`QN=2f-FHhX*qu+$jF$lj|C}>A!`KTM@_A-&m`@$4NU{WT3f)@>ME0V zjJEtev1hEEI?>Q9!S3FD3Mu(~N0aYQDP%AAdGw9Rxj_~Bk@y;d8gk<4oCR&;pCrCc zM{TT;c79fn$510_q`iNR@R_qrBMsO%cwr$0ezHL@KjL2|oKFEvUmJole}N7Qbqf)E z+0TDLkfU$2G`0Tcf;%77K;1p$;GQQ^I4fcl#a)a?TCvTX)iy-efWVpYVAm2D- zM}LeU=Ne>2-cJ4m3H@`_V+?CX-p>BvLX&hfyZNUHvcw^~`^_o#i11w%BaOZN`Kbcr z;9kgO@>$?D_z!3rlZqvn^?O*5YJ()bvHqiy(r=#AzGnGj{l`;m9V-8AIUfduQhoe; zjbMj_|4%^{n>Z7BQINqHv1-X5=D#k;2$VRBydlUBJLHfz1vxH8vq4h&gbC}_yuuEmtkIv3|l{k;Tv#?f5vA1{2q zMIEIjcBOx+AO(&yKBXc^)A5$(8iUmIx5y2Cv(OAZ*&;XlXGmBzs1M2csN`aQb}@73 zxmzr9r+<;q_>SgIf4(4BI-0xuYX$krA$R*X3R32fd;Qx4xziw%lK1&{3DVhc9+bS_ zzfX`AhGtOm0slckZZYNSsN{qG!;*^OhNc1Y(T@wwEEm>G{!_)QH#*hpRLt^U_Mee- zjd8wS1H!y$8m?(7z1RGgh0m6b&+GoH#Vm1+fhY38jGX_bAYYHxzKFanNXBRjk#{AA zFS^`$!(S#eZ|s-z^?@K4$9ydpUu$B%K9cx+W5Q|x=aqsyvRw0NP;dI52(sF6ZonM+ zdO==sH1GT02xs;)wf?N||69zGn{nl9m7i$Cl;TqZCZ((V9)jS8Z-;ClNXFF?tNdPV zsNp4!^D4i08|w3lQXAGPzfT*6wU?v$#IF@!d;Mu?KJn`W;W$pm@DqP4;WOYWjhqpD zf;)7`dCek?oD;0|58`sW%9bPI_%*06{pL0S!rJO`i){rcOXi;4FzY=t$cKs$H8H~&Diy^+K>gr$1bkZt1C9JO>l|IGo z+)O`HB1}vDT#0l#=$B=f$AUfBS-&QIehK0xnSBhuw%^aaukzpc&8vY-> zn)GQD)WflQy>g`CD{1)3T1?Ozl=H%8YtUz+{-BJ7?;)u$S$Z4k^CWB_{bI#)dRys( zSM!xmj^1AS6xV&4-ckA#mpM=GEPaZ{#Z0|xiF97jyOl`iCB1uzbY9VWlt|}Qy;q5J z=IVW9P3!G&O8C0oPx`FIj7Gm$F<*aF`utny_$<(4WIFi6Q~8S(Z|L#TXKc{tT|Gtm zyb|s2#u|^%yw@9DvLECav z|5*AI*YsO`oAmjPvqFn~r|&3{@>zYC3^T8kQ=SWYVTmwT^@AmRe$|i4dOfv~W1Z7~ z*N;n|xMNN_H}vx|VsJxqf#(OFm#yvEa>tKIDzggbu zQ z%v^6>qfto8bG`M9CM9CkGn&bo{)p8w{T68TjTW+|#}n9Ryr+@T7P;e}B!WIIl~3+8 zCrn%NL2F!H#y+v)5%LLXjlRaiC4BlBJ!QR`EplS@H~LDSp2693fHAN{tbvAKhM63k z9iolF(x*~TpW}=n(r0(jC*DYuKHY-Wc(9QyeTwJYAx5h7DGJ)vp+-RZtPg5bvXLQu z?g{3eW(<=)bAvtsV}$him8*sR$}~nwpC-Zb3^PVapKpUcBaFwT&xBwJA2Xi32Y*pS z3n%$opp7)f$}l&A`t0}=TY$%nNhMnBN&Fj6Xb(PROt~jqtf?zt8NO%NbXtme=-oJ^I}r#_L4kYBqQDk@N0-iZVoKq z7^J@mPg};reYFYp3n)i2@~cukTs(3B&lwSJ-xMKoA>VL~%Gpl*hPgP!YKKpgk*kRx zdtsbHzIFk*;i61m@(&j^9d|r)3*|Pzeq#>8HJyYjv2aVjP4x>G^Z&;4q(d%r-=fjcN^!cUEx-_pWOyuvitL4cKdIjc55d*Fwzw6_AquIM1K*V$Yi&X3imwr z))anSb>)wKI|#O6=P3Md->`d0#T$2;<@4c^{63Y>p)>41{1NtFjdmw_h4SqFah%;( zRC&fkF+Z!qCn(Ol&i;2NliM<=2hT$fzQILt?)PxfejeWKKzsfK`*#X%)knGC8-C1s z*w)r$zq|oGp!UCv_S@G;6W3y?f7*%npvR;Kn^Asp)0CUuin$W%lVTa-Te#G}>rlQb z)mw`9AHp}UQLg+GLAwnvC-(07*qw_bAo;WC}N&`YO$1+rY>B0h%8-4D9>P^osJ ztgMIQ8e(`;+&)J7K9uWkS3YwlQu~C9MkqJw-K)5XAo_%hdGje;xcFxYyPQ7i5BB!a z#CuY&H8H9oZbWW4KxxJr>7NSQVr@g~f zJ0M(hAtL&;6P?@Q*)-xg^?y1~hy-xW>FkodN(TS>Jh$_`utVwKCtyDo_YN03_v1g~ zD@0}|qx|>4e+$OZD7aLvF>uM=On^(}%YnNX@$%pn)P@~^OXbanJN!){-bB6pNN*9` zd(pnj`b1|BM7paW{{;464DuuUwhkPPe&2*}0~g>#5IpS-A$G!b^r08}i{!^(PYdAo zYe8;Hk%sa48Qd0~g}7Uh`Kusv`rjZOrySHj#}R)h@;w88%KrzrtyTIjx8(HaOPABT z6ig3x8Tx(=?CASfjk(|N??COUiP5lIYoON;7YT72>295Yw~F9q-{N-HXS4jF5$x~C zXkzVRCCw}yFv(%aMyPqzAo3rdH^<4cA3HWk>!xS)BW$5{%e3ENNo ztjY04^MKQyPQFiJJRL;%L1>4vh`;s$u1{Uqt9!whCbR35%ZW$%Qaww_dWVbfKZLjs z;Wx|tO8RT!DWqSmZ(UVR9=|j%Qhli1DxuwI{Lr|jaa?y0>t}!1+i;}22zpQDKR=4| zrGBLP(tJqc%^6S5JlXwwcl+|VXoBx}aDK(@OzqYJ={WV`dbShg9~Yt>{MU6QyB98I zsd_o>=eP&f;r(`mEAtheh{LTV%Zv9Mv6!IxICeO<3fHe&cXBl`YXkRF3yi1!h!>fU zaSPY6o1t7+@cda<+RL83oq67|5C3g9IGxDsXA5||vArx#e|vj;&kXtPnI}X5?pd71 zQh6QwxhRU;+X=^Z#0bitQuB+GE|;%3{gU!S$S)c8wL1E1cweXdnplSVk3#-rH^#vw zJChBU?8{5g7pI+_a{Y^Ty$1atJG21d9Q(%QES`7DR^@(k=9lDOp*L8+b%Xs_ueTIE zVJF{tfb(67bUwif@+++0#x~=2c&9JL*Tjq0N#8W_GUBgAx&OeppmyrJ4{tv8Z6o~S zIb3u$J~fMUQaWONf^ZM3__mU#N;h0|=_15lgp2M&@!E+ki`f165q2~F=JYnG_PXSW=mnmCW}q(|Q)Jh_!ini}+VP4&3!%cIFZE_)^PgIqdeCHI$C*=;qC-FwEdOK*;y=*#2n4ASfNF6?Vx zUME}vr*^;_8>l~*qotUN@pT(~Vi(3M+%pF-uKR_HDi}w!P9?jt2J4KPZ76^)}r=pS_fhM`V4lS{n)Ka@e%%J4b0cIxWAZ7`fK9SBq3_`)5IHf-Qk>g znw$@RLOOR5?q-c}abIUD53ghU*9;fk(SJkXlK$i??vFoMt9e|A)o^#Ceru{nW|xCr zk-emKK|Pf3#5COBLB6-JexUx%uTL(@w-fIO!aolF)UO)m7m{~_ybAhb&O%BjE_;M> zCreioZ^M3)o_>yS6mJHY_9Jan{QIRFF8 zLOG(44z2T^KZv(P!0}l3P>k^k^R9FEh+e1`JugWTztRgNZ@)?xqs+q zh?;2UtEkVZFSwkI(GGbiS5LU42abMrmHmhQMZ1vyUbs}R9jIpy}k}C#*ts~2e2a}8gsg^k0-{uhOK5N?<`(uSD-5(z#?}~Lp3r(bTr2fIY^$FGw;8oD;Fv$09#&>c0!_J`o z)V@x6zKY~|{cn^%9P%^W*tIb~6aUkj?ZY=uvwL#_y9bqjQ{}(EP>4pzr#;4FOT>F- zC+r1W+JAO~OXcbbm*%ZM`n3_MsBb^i<8SEKp#E$>qao*X!bLE%@Tw|F1l3hLh)_w%vl zLjIM|u7lt%ljUIld?jCm_!NF6T(Z+2DF3Y}FZIJ7_?Pa(cJG302Ter7UhMDh)Q{8q z65+VsnratK99W6{xk~?AmF_7p?YCN?-$+l%%~^r-9E{gvaC^ZmvkL1C^y z$>W*(yS}(6{p*VkBhXHIeeriD^>^|7{a`<;Z(MeF%%|keM7_xE3VkAX!o%#|hW-pf zd-az36E1ca;lD3XzRZt>xB~YPxTHsm(7rdob9V^wC*1onUz-DPu7Y(L^#iw0xZw8T zey#v{`#5}WX#mfc{m?(ox{mUpdW}Q+RS=HaxjMqJemngP`!SoxCG~6V0nWMr>nOB; z1B9<5`_<9&HsXTRH$$egx34Dkp()}~zqEwgHXrMIxJl4&8t=v}?pLROo27DnX`e&k zTcX~b;g0#1-9ym(hX=G2>!j z4zADG|EdqyM_l%|Qa@XZ=2(yA3@GVelG};F z7-vsG&wm_E?*EGSzx?B}mqPDoJxgDrqIAx|juxlG{hFux_eJH-M)_&n&I5l3{eMIG zzoXnG%6(tCYZ3kx*!8E|hKs*Wpk8g;iFU9D6OrG+*V(O>&hE>V*oEnq@_iNAZK~v1 zN^UFpCM92obv30|SGl*JWge*VInyFW!ry|s zH;U~h+uxRAG{!}R0g>6$Z&QCoX5XjW5z=+m$E?S#JBH(K7uG>=op~YkJ{~9il$$#r z-%B3oj908zu->-@YU21Jc4@qp1@ky-t-X$RzZc=@{OLZpS8vkzYbOR&#`gpVRu)xD zV?92Qxe0idj{P~@EN({Qxt~%XO=pqMCHE2Moh_`ai<2MZL0+-}}6v0lp%8Q7Pwl?|F7YzB zyr1RvS%vu2J_$JYqxM@@f;WNZK)*kRdmiO0Q2Blt49DqyjdXdxADaHR2v<`Sr+-TE zd6mvj;3i&5KeT;+3AQh%e*+wbakK^fQ(C&*&VM3bK0k26nPSb?SV!R%2R;w}zti8lxI)5&% zC+AD?-FjNG9jpFV`c6A?KDCe!^+!_Q%3>MDNy++F{jd7|-}%-1pZOKngY>c<(haQ- zm!~nxQw05P4tD{@b?5(&`t|w$nO~p($`9wOYq1YN{I4*+BOm4U{Sa^>{8Ql8`;+a~ z16W^nhaPUn`gu6gX$<>~zhDsazsJ52oHY*nM7ZC>4orYc^?MdBpX>ZL^Z81se~QJN zT_T>F-SNnOPfsdeaXg3J;ii{J&&?c;?aK>~vipj1=c4{@y;_4g!m)pBmrU^x=50DB zCi_SGFtTT4FaKA(|2Ml?9ItpiItuOV*!Km{gHawK-iCVt`mhoGMCT-fke@rBWu3Vl zPU8Heh0DIa0RJBr)B2b7YY(Ld{n`)rW7xUVXdjlF;@_v(o>D*lhI~dA@P4>E?Dj3y zE_dMHLh1$f#jEHXqj*33_uI5@tS`PXHSFh2Q5)+(+IP^tQ5*E%?l~C_=kQnu(SEEm z*2m@`u7?J9?^{%EQ+%-=f3N_KM7_!n;(AmYR9SS!cr6b%7WO`AAPGpNvg({=oV5>~E@dHkYF}9RiMcV&Gd{g{XPIQlRd z>5+Y&2KN=zZyww>kgtXtE$hqevjcn$`R*B{sq?pR@!~Nmf4KPlI-L`6{nAk%=1_fF zqqF?M#+vAbb|<|~kmX?i11K-;SE+xf9f=)1;`R+q?=Z^Y)R)iqO;Pz#);Eez`|rBQ z=NQ5bKt6PCMD;!g?t%3WtqW+qy#_At-+2H26Xc|)HwM*L^5Xp+t*fh4=W+EfMH z{{_!!XLh6gZd`Vq9_-Rh9pXX1v76qT-RTq9eP|cCywBAmxSh)?_g>}Rr`&3|ut)3J zaK-f_cz@VLaf=A29wyH0XzK_R`og#3SFpd13eV!(oBOR$%%Zv59n`)n)aH;+JDR+?a zk4C%hf&LGM`vT@|at*9=$-Sfe_bLB+Ci$CcpNe%-6BkopCB@7~+QF z5y<6|Zit!T0>3=#6s&Ln*NbK=Ub&ajH^h8qmA)a?Np{jV#Vy60zE3o*P3aX1PTwbX zNzRq=C*eP*uS(97w@_|Z#8e=Eg=Iabv6|sOZKU{RCq-eG=Ul)9-v@aE@J$)N$WH$T zyE3zk_($<&l%L{z>rjG4b_RAW6uvC8RtAi z$ZvW?S^VM0v4RaXaij-;Sst)+sK7e!w$m@gcM7|4QO> z#oRxY#kZ34WPjk9nm8+YPL&bRpJmY2iuEXemPZ(s#Y7jcjHo7Faq*UjTJp5l37=8A zt|*Z5e6e~udNHED7}0>zn7TzX{Xe{(@+dlsreQ{~o8$5zRygJe{EYU;YI8;%_eI zDt-ripTC8$nvgt4)IjUi_T#ClWT!n^i!qX&_G&FAySSCVwU{rt$gchtZqfPMh((GU zf*%6EuXt5IoQC?_iuKIey_gOAgU>0R{~d7$aZgh!Pmwkr9Ov&W9#)*)isaqIlZu<3 zA$~->FF8jn9)MGO(MxPpyaM`^;qNVKVOF5}&D#m<5fwOU#mwWknAx77(dDnu%j30}**?Sum6khB;WoOJ@7{iaA82x#WxdiDDwN^(NmR9hkt*gW`6aMlq&oE}%lerXWY*7OX8jB}axd#=F|&SV2IZ`u zBZAEOIV#AkpHBpt?bFyGv;8V&wr}GcxhgM~dh%CTmdjhrH{QV4CjC!4a_>Hjm$fB$ ztAA36ywH!Ok^B|P@Q3_ULim(_S_ogJ4|~a9p?5XLU!i|i2(R_O62e>kb3*u(e{KjL z^24afAE$TOk0p!ZD2%7u{&z!IL@o|tJMz5{t{AyAgsVj^58--|?}u>9$kid-CGvwH z7s>Y95W-vin?m@Me@h7WkK7i*gXyF4@>l4k^a}lZL--I~VROkZ`wxV0MkI`el79yM z7Lizbx!8_89>Vn^PloXLNEj*kEA&$QsgdVHxLV|e5N;V+6vAC1FNg3;k=KHJ5lIgh zzXkbEX%CB8`x?8@$lt|69*=T}^3VKKL9nWunh-$56dRV&SmQLg!qOIbiP{qQ?TcQWEn%{4WM_pV=+!paJ zJ`nk*81Le*BmWk&Tzo1L3(7V!KkFyVUzZ~-%~E`LBIajsnB-}e7xwNZxC+ZfORy)( z(%LG12wW=4)_O|L7ZstZ6{1ROTUc)8_Q38Cyi4)FJ!ySfT05jT6{pC=Hxz%U!rxI` zr5A@UgLa|zo}$9HWfo5&d<~@ESMeT%uM$;8+oHHZZ{{l4ebIb*Qid<16)0}e7pH_# zWi_L{OkYg+oAN8CJ?Y}6QRTF{9XNg>RKI1^J=!?Qd13_W-yteYYtxbAe>M=in5gm^ zeXR=X6Se-TsAaHR^>Wk()dSi($weC7Mt{Y8Kr=f_xwZ8f%qLORv~r3+1@{NjZ6a##C)VSQ zm8j}kO~qN@A>f9J*I+?W!Kk6pEmsQv1=ufYXdM;*0Mn5gRa5J(IHn42Er1i5#r+r` zeo<4KqxeDa6H&Fa6^eg>9;D+dZr@7I5g)^}r+aE^^bZTjPYk<7>-RcZ)h?X>?-+k^ zqK?)q_CB{;8{tmCWnG2~l;mrIK^R@0cp$L_KYTOO7*JZI_EH zfsaUb){FJEQ;KPfw|RNq)-zA8o&j`$s;Z zopSNu$Z^{5E-v&>)XKqbIPnkppVjKS__BYB)>#B_@_LakX%Dz~eB^Acp^K+R&eb})xLV}vT7MU}j9j3_xwuQ@LM=mbp-lg!$VJ+1 z$+@Bl?Ba`2OSO%#lcXP6m|xzEdSAPsxDKZ7#ZjxYHn5u{uW<_Nuc$RzmSWx3#P+Cl z+DD3cJ^7(lsF>G}o3!JKdHuLmyQG-ckK44{ih2FHQ?vR|e)*zXE>4G{KGkZu`0J=W zT7lv(U=O~F+N)hvTnqc7b5Vs_YuIs$zZ>oOr@c?>tJsX8{pWsdh~lfzo1&=Cv@tHe z7WKLIyo)bK9MI-U#(oL*EYJU?c0h3+?EB@2ue1)BH)%h$q&cN`P|H)Cm_>X@TOoOl z*bMm}QHQlN%xXUPTBCWF`k(h#Uu#-_;sR}Yb=q%zquGj|k$glet$4NMqgq+X&i?h7 zRzVtJQ{P#!0l%k!mmOq<4RjmCVLQujtm>|46$g7%u?@>q|yi2hMKp!k(xLbQ)A z(k@GO+V7%vvjjJdrS$T}i*s>)5q(k1k~~K|cvOhq(U-L2E>4KPqE(Ee@N-1JOd*Cv zU)2&7ci)2BLDAQ=Hu0QZU^i|xM*pt$bn(3C8(NIyIU@FX*puj++6E=3{NInhr5$nc z2jEL8{Hk4e8Xx_qR%I}y&;7Y8`Y)}S!mNFg=e#h&*^(TI~8;KUeDKxIeo8(N{8`k@Ohutb5hFl1&@EP z=X=GEOZ#DZep1Z#$LIM?@h8xi@1iY_g?^|0sR}**A-a@jl;k<$d<)!KjV|M9K7`~> z|CaM~mYgr1miDNeCqr>y3)bt=_joQSzOWVJEjrATGL+LNHecr4^uAooy`Hv- zET^~m&P7%9^izL}Eza+mV9)X>?98tqlC7I-N#5ez9K98yC8LXJX_l^no%w$&f zv$p4|cUE;c)S&~`5l49z4)=18? z_&lY7XOm)Hzcuje;P6%k=EuyKhMp6Or+`O-Zz_Hk_3!0xZzxA=R}e}=xMGv=^@%rwe&nBxj=hi32xiOwDt^Ba-Of-dFCtT`MQJW zlH$?Lg;)~P$@7Pb9}9h071P-hmL~Aa73G@}7G{9q@l@57!OiYslv+a)pGJ?qjr{nrlTt+$w-o~w#0Z^YBam_DAh87v?B zA^!g$roZPS#k`*!;3-f%ekE>o#tih((`qVjS(M+86Zj>H|A3wRJ0`+Y3wDp}$h^N{JlIMxd9r08; zHqkRza)Fi&eQgn&>@h}?yg*xv{_PT*=IJnsI7jqH`QMDn@Qjem>BYtl^Xz99-3QQl z-bhcG(Z%rtu_HYLpWyhh=${W`MtPo6%;}BxEKyAPPmF!S({v1l=k#-8$9TF(E)Z`W z!S@$qCwP`CE`{(Fj7grgidVMB+eNXHJRd85`4n!CgRe<;?8|eWe%h@ zSTGp34`L^K8cKHBFUQkUG4HRYdLktkX?#97)f26l&j+V^VioiGV6JDlWX=yOF3%G# zPKwF%%w-l0VyHedJq41v{R6QxJ^rWM?e~IbqGE2Z7d_|36}MNIc*%3w#WT#8J-@s7 z6?3*njHmGVqS8SjcE`TziI+S_v@gQ{xyI&uMk{U!J{!BhGet4Yr`KW^dgd!`@GNd4 z$G+`3DET$fQ^VW6af>_`6b~#-{H~f$3cX9vzGdR*|03vD=+!a4?vGm<FcdxK)n4Yzo#(mm}9W>|N3e|Eg;j^K{s&%aLn6i4!P4ZvQ@UYdxbR zJNopY=bU2Jr%j%VidmmFd48Ad=+7pP@pN%|Nimx|B z``&YbS+&>qp3YNbc?6gDqG!0|9P!I(+{TT&wTjsBk{@sqd<;haa_T-KycPhzqM0e<8*?6JH zOk*Z}t{(5v^Icp&-q5!wo{jRijyLr?ib>x)#ryQWxg7ufCHQBScuQZRcs1--bbJ~8 zxZ)VZPmd4N2Ttek+sauddHk zTxU1_i2=Nj<6Eu3i@{5k{MLI|&&Jo#cPaiA<;w@}XBMA=SH;xO|B&q1%bI$_8B`u; zKB}d^Cz+pzeh^R=A??>_B`Y>jT%C|edzW%u699h17;HQ;* zH`*gkG|;Cg`9W|c@JuD==Wz}7*-B1->it!GLw$jgN27fk7>)FIm3$cZtN2FxN+rMB zgT`}X{X@mCKTP>G)<0I^mx3#S_b7QU*qb=fME^p`W5AWbM^=+nSpk18y_zwILvqjG%%bIQU9g2rmrTp6HpDBKE2=fue)PFbQ+vvY2 z{#n}BHhQTSW%|}=$nzn;SMftFsXf~0%@l7{@(#@6i0tn+dVyr8zuW4!74!VqPVYI3 z(&zgA9p6qrAla#Jd%g5aD*vO{tPF0iS5W*0>`hs4RmGjRV|@;;!z}7v!@r+{TPi+) z{%kzBgWgT?NCR(-4DP5u%B;?#JLwZ7vwiT3PWp7o)2x;MQhRmQsWj*hAM0aheT9_g zi(_cF4ud=EJzpmI9C3XV&c6qD)mKZ-7lkNq-@)DV4zIAh^IeSB!QJ)El3AZ|_e|f( za<#tiq0@5@SYlbel)*jpE6f(_V=w)-;^`f!KYFS16?nh9h5i2EUb;1#;u>>%+VogeY#iDf&nej4o8!(Qe1bU$I{;3)lR#ngZE2gm3y zNzM@kJ4ha@FOuxkCthD6*_jXH^^Gq1+k@lvLKklsoTT5DoGWfL!THzV486l^lz)NX z`V7}^%p=Ybdk^C+=E48b59Kr0fqlI)_z8XP>&yk|ZMcX+}iJza8<&FhC}bo%#6*`9L!@QnV6VqQNytM5_abFR^S zq-XU*lF!?>{vrK&RzIS`)BfyD?ODCc0#1+iXGcVqK40;mwYa5+Z{#hNd|oqA4-LFp z@dmWZ0q_RJFFr=`r|2Im_8|UqB3u7dvQxio{kUY-r-ljHI(;)8{cjz?d|biE(H~R1 z1M^e!gdBa0oi=*J`A7Zk6qjoWnKR~7F^z7gPs%pwW) zYh=t+ot^{0{%a=(Q2x{Om^Wp4#3I0di{CDU$({DdP6?cmndGf3(wz%Y}Ah^ zp7;yio*lAD4_nOX)rTER9`cd?u;PQGaeg^ui#}E|>$fJh>d#1K{eNP}R(+0(rwrMy zuW<3JLq65JU>Ke6^SVGyPG?)2ugo(0Kk#PnBGtoke+<4f#yJBYBRX zarW_$FZ6nt2WdX2T}z1T6%OmoB|GEsu-;zsbZKu64LPj)B~O!la>zIObjgKw1*G@m zkfZuX9N$X8xEWaasJ=sTk$sEoocE|+sQ3*(ji;mf*OGIrQ+=ttNA(Mm3pM*0>c6A< zeM_l)g>pSh+)=VqzN30i7hggCZ%cOaJE6a;nDaZKzt7>t)(7#tB;ka9TycGj=d}r^ zbl)<{uSn&8R$~Bm!-X2%H=14Xypk7cTfw)7d>`Zwz{b!Y^?5SA ze6jQ!oaYTK(pS2;&d|&HF2%j0FkcV7s>fg)kp9lth532t&-yIIi!jd&9eQ2ABzcZ_ z1LI-j&|mc%D=7RN@zF7SonYuqz2W=Jl;5nOf9i)6Pu?xWyF>5j4Og=K#~pZUdFa3T zV98GV-j(G?`*lc9I@S0v|K zwK_u|hYBNK@s2jQUjcqgvNJymW20mzJz*5AcBdzdA0#{JX~s{ADZRp>n(?b-Cq2!u z*2wr$pYcrzBTO>u`|}kwqo!om_X9&cMjID@JJf6VU3_t9DWgDgo?PGF7+TIaAeqO< z-{9Yroadu*#$Spxj2|troI&#<^iPeKaz-h|+}`Dk`y@N#rJT`7a-LxOT+V2(cmUQ* zw=3Rb443STr!ZrYV(yi>H4^u& z6B`;cF%Oac?;M8tDzUL)V4fxZ>QRz6HI^v8A;Ujt%*DJ*`fpFe`XsT1(Qy-V>+*D- z+|o#q?AYH{#&F3_`CA!Jy7-yIR>pG4PJgsFRx0NHXm4!h@Zt{a#|w$=jUpGXP3Ua= zp_uL!y^#2jQST!vPoBJIv^D|X?^MkF*URW3*|9&pjZuoZzj_-7Bs==w+c>pZrl-bJ zZ{u&tj{f&CJeYUUUKZ*9g2X;}OOEiSHd~^q0)zX>;PEMzZ8W!S-X2F&Mt zH#SS={3|9sX&g{;PJfJXQZc7L*0`jY(|^kN#T7r@GtOwVozo|MJeD}#Xrh?Yn_#q3 z%;`OCJgk`0n`jJ_%;l+?G|9+SaxU+)#sQbSe$sQsITtrinqmmdQ`A2keyY)7C-EGS zRvqV0Nx8;)$(+7l%rJIIcEZmz#_gi;*q@E2^1oo5QvAZ#^nBt)qdVrs;`C=3{UmdG z_=cB3QpmlW|H}qnxpeHwY$L%HzE{$0V?;=LbBw25@_|XO8Sl6_Drv6q6|>d#O}syn zG|xDuI2QVt0zMOl>X)$9TanWziwnI=JL)rMoV_;^M*0r#TiL&81K4x zOwwD%p^*5CO4NU`(Q^;w&*@E0T4FpS*(u*rBTF&s!!qLq#azDS#(c^7Vh#FZdeRDG zql;fodf&JpnbY@*mBtMfpX;;A*i%rP|AM47#&H+Fm$c5fDcR}&4MwfK#o<3l+GMnG z@#dt>Mt{jp_^rkhF1cTPVoX$W*8gqBEXAz<+l_Y=bA5LhA1dbh?lksF=KAbT+GQMZ z@fS&-8kbyrEUCb_?cxhb`;1D3vi#Qi$+TYn+^DX2HyCf57!4&m<^RHXk>zrI^Huzp z#)=U6SH^w&WO^dwf)KwZ9Wv@Eem)n^N0Sa4Z6rJCeQnHSxmqtBG2V3X?W7~d`jGI) zjH51j)uiLb6&K%4I%!zgmluz>)5f$AK5NXD?C9%xW4?>aB%e19goOXWsPh@6=Zwc6 zjV6+v^8aXbknGHV7mc1F;V&BTF5Z!N(HJ8+&-w=QMdjp6#w5i>;2nvV49bn{0r&sq zAano!6lCuIE5=kApZ7Dz60aJ$ipNjK*DaH;8M74E%wwL*`N{U)k$BB`kLAk#{cNmv z$!jNHH+F@{e>Fb;oXY34-|xoPF5Z#&yK&ydy^?Mi*Cjjcb<-I91;uyT^Olh&*%{xr zj1h{tzPF9>in+dj8dD`Z?fqA2(tt5td&{$ImBK;?1D zC%pGccIxNxJ|LOX^9zr+u8Z#^>fSaS-kQ;$_McvF7gv10@OlSGcG5S!kGtX@OSHW7 z^#yk54E>O>lD|u60@|5H%-nmLn&zGJ|uI61RxlopGQgU@~-Gh{V zf%x!wybYXO)7wSywko*4oLt+xT5^u~2K-KPeea4x6h22R0>7W!&>MD`IU4KsRWVJx zbrt^y>-tqOO}&21%M|_!!he+9%v%%tSf@UFlAC+mNiGo2W#R49PV0v8tNnU!c zNb<$lU$swp&Rh31F}H8;lpJpx$&P+Z^A1$Z@pHZO-Y3Q9{+lV&FFxOSQ8AzItW9_+ z$aKCFkup2TbiR|4GOtAZ{Ggo9ht9^$4>H9ck@7~6DgM(bZ zeBkYQmfNTDF1+uWvfg`CGPkc^eCRzR*|8rRyrs`k_#!PM24AC0`N-Q_vSXjOcn7)o zgOn}aRLRcslTW-`U2?zJ=`B!lzR$AD`-@AyEoG0_Ixp~Z@-OrzO3o4Ip%<@2eCD04 zxB}`|nDV)Is|wHK?F(%0L@W>n(+Ofzspf-+LdF%<`KlMc#*$ob$Wn z9UKz=vUj0mC;e;Q-ak@$PI<3;BPACIF5mCo1eg47$_;O}tu z%=cIR@|G#0^oumUzw)n_zEV#08#ayZLkaVo;w^h|9-pe2RW7oe?%PyN)y+PVxqS6g z4KqWslfTa#t(fz-%_)jGf7{Gg%=wo!7fQ~-vr>HJB=sKCy2SZ)1wWKp9#)rrg!jrS%z-kzvtGF0d`q%p-ySfRDrWokfVoyNKi{otexjJ4?^ZSUD;|yddIncD zk4i4oGGX8PM^!beT&D8mh~Ku$_jgRc;@4r<`$ttbXDXhwmAHnvOEEnU9+XuFwAJX<4s+uPKxbNHuA6ZbVcO6K~0kka2ADA}p+qvm`S{(&htFHem$Pboe>8DE!4 zjWXN(%IQ&iypN>k-dTzJ znW>3p-`|<!jS7Z-<#5O6L0c@&A>dNG=qte~+05 zI6bxA8)?#4D=Gh-Z)3fgI@+u(xj?g^uX|G;H)~1G5l^6h`$s*Y^2hzRHhBJ>`ecyb z1%I77#^JK7=i_?=;4~SZ%af^%F`s6(V$co&@sv45ahnI}dlyfcGbB6TuXxH_Et&6M zJo~^?=4~bC?`w=R%iN~&JNI+On|&qYc?tCUa>RIZs$}Q9bb|SUZ1mzbvn!n4Xu6@IGgDQru!H-d8C- z+3c>k)Ny>J>Va%?km6 z`-|#7M{F66R!E&`)^`~8@LK8%W_QKc9>RUh)ECWo$=sfIQ)ijOB%jyjqFt9+FPY;M zkFSRFZTn^OS;Y@OM)KL_RKB&Z9d5?&;Lhw-!UgEX8l-XzNDD- zW3l;$V%Cqv=5onJHtXABbEA@PmHM*S+|4XX&87ZbY#vhKS)Z4fr&V~?-zDZxidnyx zn725*#`?0vH11ISxj!|r#H{J!FmQKf>s{FK9>!9$pW>BZuUKkEDSovt-Dg{74pAJ} zjP!e%8Bm-7t_1#%;t8-fJ&fh%48>EyUa{Pqr}!M~eVkZfzNPpIxDt4U>HYJ- z`{utcu2pr7Y5ha>$q`wQ*Q&bKydaswN2GmVHpMtbeXZ}YKDwl@Gdn821`ZSJ%sz@I z^&$CsGe&V9I83ZJ1B%OIeR)a$(0oF14RDzF(9D)xpgkXp=fP$}>l_hWvVkjgGzca{WTNR@E&b@`$vpW;YqX(C#*#%JXqh{@8rj zr?gOh+{OK%|4*lVV)mBti?sAOvNzkzSjh#FD}m!B^L&ao7|j&Pj(y!O^DEw;In4XB z$!R;4oS(nvx|sGyFQ@G`pXB_+@llljr{*Hbc~;A8Azn}W)LfzX5%62!^^yw(*Kd!x z$HkAQ?Jt zqvi<7PWg|S>m(OxS1`YQk@l_msp7Zev0g|!ZXR&)cWEbZqoTMzn)uGVSb}f3cuCrK zrePF^$G}dxQ`oCZ z`USJT;)~;$TS!KKyhZllg84qa!-es!?q~jJ9+2$l&yS{sb&;bltI~>0+6Op{uVtCJ zF1}@6HVY&>>#-~5HD-&){}uD5l5=}rF%7I6Nk1w~Bz?MS#wdPW>f6ue$CBrW#+YBf zx2~J?o~Dz(CVn++`@_KyZT=AEr>ArO?UX^C}uDclj^6mTA#kWkKuWTtQU!m$h z+gFKM*$dm(P%)2(Qob0;PJfp2otEtMUm2fSy12gh4?7?JLWXGP@@Ew-S<+B4de80Q6N}y&)dCCXE zL%2?$wy#PVY7ZyUdaB=6rgTCvM3&dYfVf_?n;Y%$m^+%+@ z-jolt@vV`}>4%B7zE50y%WUVn;^KsA9emZxx#M^C^^)wY2fFxTBs=SYF1~ThD*vv& zuzM(efttU&`yQ4&N8~<-^=Y8HFIsY;ApI#Hc*K|L;yQsIzHySB_UPsGSJ~Y;v>zyD zT0bwadk5vb-tFtKm)GOPoSskixR^J=J`WBAS*D*7=;y>Q`_*>5uN~+g?QE?ciA%`g5ScPPPAOYnda{A3AE4rMRvLoj_W z{fk$ah;;IkJT?#&!ZXb1AdfnZ=grk(LpUoCAHsQoAt5|FkQ8M4_pmUL7Q$l#fe@Zy zrU!YM%r7&9vjW3II4>|Vgl7jv2bsR=8Yaes@YulE5T0Q^733o_zwsfQ6?i&?^8(L= z@a({IL8gCC3lljZJT@>jglCx3g8ZS(Z+Zx41!jbBUf_igo*j58$gSp4ese;2Y~a-p zo?*TgOkZ*@3r${L8D9-@73^Hn2E^XPEB=d56qzX$WTpmWOa& zU}Xr;4y*|>*#|qYK7`8$J`CY1fej&CC$PzvCGCe}zc>3{adDW~?0etEZ30_-dtBT( zu+{gC{_4_!Pq z@Rjci7tb&c`pzom@pjnvuZyz+-}tJR=kk&~FL2D)!Ns!!CwwuASszdPM!0xv;EXTF z#WT#azIlpSAJ6+Xx;QKFgYO#`=LL#7x=@s#Kp4%fBJSQW_$9F?}&@X2LAP3bMXxGu1}-CDo6ja zJ<+UMF3t+*RyP;t1x#y*i)ROHYl337CuOY{Ts$^V&U(+qGt7Ie&5GHcl(&w#I4e-W zy6NJ)KxHeeBA1WC&ko#gHD$JW{;6(tQq1#Db*rypo?oh4af*3pqo|G#WT!@ zt#HL`KOV8_xHv1&)2ip&u?E}k72VzpPy<15+f=;E<~6sxm~XPBv0SH(QO0#-K{X9Y5>?k>&? z47Yl?cy?f<)k`tk$H%QcE*=|r!s_SZ8RnDL0L5${$6AlNI4dyDig0mW;Atz;#j^v? zSka2vK2Ek`T|720#fo?F3^UtGP|Wsmsx{QbS%F+D$;Ekr8CHsmX9r%e(j+_M^=0cZ z$t*9k1L&PsObv)H=m;xMt;Dt{m4$MVjB z_pC0Go%EMly(H&|__t_(v&>4D?38D@wMfbNdy=cHruS2Nb3~Uu_?)Y?%JM6oS4)Va zfz{R`#S5{%I2Bl9T~*w8Ki=mGthH)B!0~%W<9)rr2bP~%oiDAk5+ytJS!ZRqxJ_W4 zHBqu-FV|ZiO3uNz0I2*QS|7XQbpji#0+$@?E$d6kc;6!x@5=@@TPGDigy%7L16!=0 zT=FvMTdi9zdByaPEvqV(KVRe}Qv6S>fr{7d#=lXdZ?k48ezGg>>!okEwkU4<9_|yQ z@32lucJythbxp}j;e51D^_|uqir=4%=UvrzTXz+o!Z~Hf^gUL^YMg(API%svUSOpv zeh=sI1Jn1a`Kz#OD*7W%?6WROd5+Z>?OnmxXWdbphVu0QhvA<`aK2_`58&|CBR^3`GA9j+S?;p1MN}eN{M$-E=Ut1HDd`oqldZd42<+5Dq%Moj~ zWJh0)So2HBQ91kyy(2o}{j~HWPWwn+?&8}x&tIEkG+_{WxKL$!w?AqW(Ey z9g^(S_k?v^vZGHYtP3UL7nO*AS;@IQPFUAnygdDcbxX37{z>buWGDTTR_So+uY8df zj(_b=KWR0V%;68Ge`m!@cFKR+8po{4f7;4&h1bMsYqn&5f9FK{Y3m)yg@XIzjI}~B z_s1D)y<+ZJ7#rGIwf1INcp{$vS{JR4m_`01`oEBi)?SXUo`+qwjwpF)jGvRGE?aZ! zQu*>k7Q&w_b;UZMxDw7gJoYuqUytP*ARn#$Y^6xf7Z+jgFQ;F(#;{zr#{}=MR*vLC z>ng_YaPhnKyy9EnbkFbBJZAO1>l@Zviuu094QrKTZjY1-H?955Vjs>6KCk(QbwTj~ z@R*vntg!mrzI@-}w)L=LO0T>2r}d&_M_>Q87D{&X`EP5bi@oA+Ym19hD%`O?b#YG3 zf2>QAo%+fo0J{@k@h16dxMo`*lD-L+aMrsv^#;I4{y=ivKB;CRJ!9+;^K zdm^)T{5I|zp$FzlKCk_R`uviv+uthrtYOq2hW(pjdj9=mP1DvIQvT;Pde8GYVcKOR z7isi-{Z6`RCn~1r|CyR)Kc~WvuZsJ}8Kvykl$@Ub9}%VPHA+5W1m$1G-lybzK3Ud2 zB{@gXzo>adS=(wv`R9pKUz0sAXCIPWXxG_|?~`PdvyUr&70;(@fX_)TviZEBoP9}h zu4VP4{Z%>pS0#TlgU&zivHw)^rQk4ek8L!j{0cSt{$<^aFxxNLv7h(ak4tv?`(As3 zOa6*^ubmwtuV~M7ag&US_FQIp|Dk=N1^;{i$q2e)}@vn^;b?q%psXSOOb;0>^Mm_s0 z$xi#$w~t9KQulxA+ou(?zBF{&%ggss8rm0>ob)$dYh+(xw)uWYBPV=WzCY5){!PjG zzDXndPZgi;VovqztY6^adLdl!FMBLjRCpkw{#rrHvGy2}bj7wF|I++cW(3D8Xc+07;ASbu>1BFXOH3XlK4 zwg*TqvL9JU>)~WOTE&kAdm&GhT&VTAi|5N3DRxRo{1khHiz|r~`)L)w73R}8k!nwo zoMUwXR|3y;g-`dS*^68}BRyb$pyKD{)A#Mu?aeCwZ19ZqbbFU8ye2a2{Vomzf9v8) z8JYHVX3K~6y`&GbZ%fXx?g591VYb$i^@-bmxNS>z#`j3Oyo8*f9!^e zugd=XkKIzT)1Ra4Zm#&Z%qQ&F5cwGUG08<5?Js}M7-x@lh1bLc`xzyt`+fT}CfJ)o zmMB|G!|v-Zvs@_jD$i)ZZ{F2;RITW`hs%kOVJXP1_oW6g%X+eiErUd`T#WT`p z+Ou73WuAPH_8*d`iTg&<{mVIaSbHwt z46M&8Wxi^^F4^htx%LvtIo3I(SHYNTuU5?I&$TzX!rwCI*(aE-e#c3_UboMy@G;;p z@w)w!lGA|dy-_Qe;3)aB|GI^ zWG`a2X0F2bz%m!vD-_drKmOBok-br}lm5H*>W-AY(>}}WBa-pG_c1~=$y{j<>_l?M z-mJD$Bs=-7vxhUQ`mVE|P|WpRXHS&uq`%&tB{@foLHeyTH`!M?ys}@L?HiI=|2t=H zw*Lu{Z?(Ohxx73+x7xKOJLTDCH!i`gn60xl$o_1zJ1M>f#(g-uhvHq`NWR@3p!guT z5;%rgm2Zcg=;B-E4tuN$-|c6Lzsr6`abIvH@HEA@&Xat%{i0$W=M$B{a}}pgAbt4M zUMM-o8V3#&pV~{6oac)@_8KMU`C^a#5zA%ydS({b2UPeh*ykG+3hg6`{fbXXF0^<( zQD|RgR`+8IZC@8^-$HfYb)Q{NF|QZ)+ifIsdk@O|-0mUSnJ>Pu2QsVi|An2enCFW_ z_5#IqI?#RgL-sls?}|KR*XYXnM(g#}8HeqLE{@Io+Me|g%jx{@>(nFm0vGR!JYp|* zac1UGd%uex&pc+=?N%KB>CEGH8yDwhp0HCTbN%LKeivLnMcj|?wPl{N&vAJBRoowV z7ko)_j`b#ZF8GE@ug0HrU+=Wt^kLbaS~}Jv%QMf|S(5R82anSC>d)CL6ek(e*!kcN|+vB=(dFh_pn#>FKI>k*P|0wgKeMd3fTicO&+3xa)%uoG4;uU*|V%i_} zFs|BFdXPL<@cHFcd!ytzVxiDPVdho4d{3F5{pwlL*PreBlJl&$!Ii)rmHcOn-#GD$ zJyda`4F8LruJ~yg{ug_c;uF|!#fj^7^eu`)IVW#hHQ25!3 zlNHZbT;myhk2v$Xy-2Z%^9>5WPVqUEmw1=tT=Bd??R(uW)tA!G6*JI&-)8=1H&;9r zd@l2*JxKBTTNt02x9n`mMfP`(V?UUA+uox1y5v9Y>x#R;z8q-qm))?REWhoS{I{K? zxEJ&zPTa9GCFfbu;7Z`fmAs9V|6@;M))Hj>{;^+FyzC3A&p-B?ipMElEjd@%PvHH7 z%zy0LidQ24yP2X?hyGk&;xM6?8m9O>_OI43qZIw)Ftx`hv~PuBzEbZ>F0z-#QF(o( z-dDT{TnYT4;@fpdZk4*EIAR6aGpp3#0bKvxIW!)uQdgKYdJp^lVRoq-O5X1<&WneY zDs}Hb8D49G`Kl?njpXU#1oG2F=~4?N=ZG`qF@FpzU22u$7!%(o8CIs$X2p$sIR6+{ zw$v`k`C?xdzV9`x-2cPgyT@5MwU7U6@0qEYeee6e*QO{%NvMcP(+N=|d4$f2(s`yi zpA%Az$p}d~j3SgnLXw_xOiCGf3Pn;*HE2Ylk_yrHTGwIUd*7KSKF{a%`n+Dh-!t>a zdcE)KTIaQ{b**(DcIXG>n!ty1VgEnc4b{1V@-v(_T8APr+&lf4P-El@W#mKB>xa@} zI6M8gQ12N18`B$v%rDuS_0s5C8U zM$ga_%r(FhfuAG&6Xw@CM*xnbUrS_rWsyh8i(n3j76dbLL{u-=5JgbS85J@J`^4%zI(J z@6G5R8bGYfdq2Me-^%hlD9^rQ2ZZJz!|$0u`4h(s2qg}p{+kc-uzmsox_ z@D0E#SWf+$8Ct_~>fg-J29{I%Wre;cR;`zs@st(naV@pq0!XiHOjhVQwJ(AUUiYG6ZS5A#C}27B%K@RnL*;C-?&*N5(9u2)~FW15c(J;Pi-(X1aghF(Ud`F(iUO`*4utJM3;;r`Q@@uA<^cPy0Jc;&y|G+v)t5oOwui(yP3%! zE)UH|o}rAt*R;j0q2=rQ?=Q$#^6~}*!c}v(P|9(xB$)ER_{CSVbpO119`P=VE{3P&c7XOGE$_L%%)mBMAA?C6#SvnGrx%PT^-FN~^gehf^T$wwVa9&a``lM%?g^#FaJ|gEp)SbPf$Qn9m;$gdSlz+1rDmCCp@Re+g|vu2kFMd}VOvZ=oH?l;7yg zL!raO$$Rj8@^Gl`a8v$@zWwO$xN^wjN#ixCRs~jxFoZVHFyNJFQ2z3TSJj6lCSH5`zLEW z^D=y1CE1$AY~ITopP6jUMJ`K@0G9zj!}2!3@VzW+G0QInt`EG7<b30%SQ zs&~QP2A<2j1pM!Xz{{BD1HS_NF|+aCRs-*4HvZoGzQdQAmGp=1Er17(SHQ#G1{VumS94R#R&$ zat+^aIoaBQT&7Nj_JQ9+v07x9^yEDFWUC#r%)gVZ9xjp4DUL>nRNqka-BWk zUuT_Sl_A%pRPToG@wGg~x}BNs2cBY8B3Gv@|K0TWDc0l6#eWblVlK=kew}#**e9d^ zFXkIy{$>Dwj9im)`96|=ja-pD5V$_b_p*HQHY0Ct9cKAG!1aOcG1xyTzh)Wvsn!X| z70DsUAAXP6YQfxelaZfhwPQXHxIXa3$ki#EJ~HytE%=FCXwT{t^E)qwhcG{sPn^XZ zE+)R7`K)HdlbJ`>38ow*fKO1gk zy~ErT`lDO$3~MvlDf2;oWiZX^!F)W(`v%)tSCf9g_{$qr2WvFR z169C-f*q}5mXFOf-}mTbm9e}x@O8m+t-D!n{LgjjJnIpb)AueqThFoF+#fGi7h12f zoSyHv(0ZHYsZie$Am7NG2b=`_CG!QyU98>A=J}6@0$r^?kgEefG&beA$O>m+dj+zf zeHXR3*lL7a9cTyKH+YHFish{~oAfWWIx^GqB0a3`tbZWW+z-3V>c?`r|NjqbIC6z* z58rQsFBVyO%;TUvlYqw)<9c#p*5%d$j&IiIE?K>-VOT;dt|6S76ANJ+2(%S z2;c@Nm-mVLSUr&CetaJbe)1Xg$v*VR>SGNheSE%Rgz9VM#K;4{B{7`PvadA>xh93q zbNgAL9BMB*&+TWO&P?aG{j846biUiqn$Jw{mZ)MGSwI($9K_ z^(nvp)(&DWPk*a4m&!x=_qT3kru_R`&ofj0{jHanDgXY~8_1G>f9vfSe!O@8XnT{r z8W3f&Pacy!^7#1MjeYPqxgegeFOKJX(4KhuYtf!~+-I7xCmz%M_L%1P)l$ABnjZtB zY@V-e7xcI#+M8>l@)gL}M!5{_&)_K62ZrYbgl$?cqMT&L>u)WiY&U%rz7NxCXjGrp z6OYOMcue+ZnCNr)M?~4o-;K&+GhhGFYGhPy=3|l?9c7w-=}{i>nkj#j?bBdA8W6+V zcA5JnQF+oWFh57s^>_wyMl`)J#1E)3Q9cauW4WPEemmTs*chWfG0%JtDKi@XT^J7! z1+t_3>d8vY3Fbt30M!41U|y6@fc14wurSKcv;}*WRUBoie@T?7{vOwd`x}FT9-HU0 zGE}MPvwev&_HUQ0DBJ(M$+VyO3Yht;N(w{&2Ryc$L;0@BipuRa$m8PlN2nX3-0d3p zJ;9*IlaOzW$~R;C+!V*71LLjrG4u7uRuin0JhTV=eW;1nam+McCt3}W!QYq*=cBDA zS|>Bpc%5iC~v7U(}sv<5PN%;mY3c^~>S6Rqo*x93y&hcows z_B8by#hj1!XQGwCJRj}PL@SH=>}kgSOtf;D$$y$?6)=l;ah+M_~#YAfw$=Sb{WX(pd36OtLW^H0Q`4_iXU$dP2i*l<$z8Mel zJ*``<(~)cN`$@&>Hmg0$$-lVGx`5;Uum6* zTooYuKFhj<<%jp0`8&(%gIuA;!Fc`GNwchU)+c}HL2Dc{`AZL3mCR&cXIoDoR|hTy z|LCE>!`4D(@|Pa5RwKjrv(R69)M{2p?MwdBT&oQ-d_M{8-Q!jo%P&QK!s^U&vTsjX z{aHTlWMj{svW6j71<1d8+A3!``B%?a_pqG&v1hFX%w+EtSZi6o1={-s)@J0@0kW?P ztZJ6u3FH5vz;o7jEGK)q(AvlH%`hM41Q%JV$kb2#pT*Xl!~yb07F$m;lmD^UTFgxT z$71VqX7WE4Ticn*|5$A8MlMtL!u{EY0*kGl#U{Tpbu;omt^1fWfRAau#HwMw>mv9) zqE;_ji6x}p3D&1uTD@#_W9|&=`9}4s^&IjHH8wGz?r8Oz^%-(a3i%Jqta_zXKk^@5 zw|XM44m5`R9%;4Q%0`~7S^;0w>J94_=FnDS?^jy0kSmh!Z({7pO6v(?RRH@fBVWQi z0rz7ot#6Ux`5@f?th9DA*Fpc|O=}l3?T1!bKQcdz^3~QJX4+4^WgTSxrnT{J-nI@i z)BfoltIk+czv{qs=+CURY-ZX|y=&ED-V5V7px(6_A(KBiJnLPnBXRPGHSqgUN$**s zm}&iZ&nk@3|FPA3)}6>zc)qn!y>HDzt_hq5`ycC!_106&-HYlr5v-Q=p8bt4E%yeK{$xe|!k5;m$khRj{=!#QD$B`#_}Uu5 z@}4N)Zsj1u?{kB{GD6i@t607<+q7Q|=eIg31>~d8sIk_OehT?B-&lz^V*OIcpV?uZ zkGwk25B!^e`qoNErty=L^{q9Y7~c=MDQl-Snc4jQ*Yc#D)>P!00QomNtvSf@`>Ees z3t4W?)0dvH%leAt^nA|`)-gAk^2mA64^|6g%3rG=tN}56pw5rhJ;cecmcsd4)*kCY z<|^jLm>;~*%;!DUGt5r`*9ZP5vh>&9X#be^1MbT5*!-STAa$?x8tPZ2eE$aA&jk6K z%oSC}-`;DjW4@6YDg%F2N#^_94}$(CluP}7w!T7^{D1c4?{RuhlmE}wPSmeXDMx?x zXX^*%Ig?ENqWVeS4uboUSwCBQP%hs$-EaMZToYK30MBD(?YE8@PvhI1|38;?&^m+p zHIToU^{ds5`C*X1n03e+!u$xxho}BwWizjCuYeC*Hy}&>R2Zud^{4ziru>3YIpvoa zWy-HklqtXDC{unZ;kz+E+3$wJvtxL9Rw%q8hTqDv!h4ZxQpn%8!znk@_#bl~oR?UC00q}bOW9)DjX1ZUX!;_KA)Re>UdzM+pgw+I-9(W6cfKZoZP7K}PBT*-VMwBN|!@!=)R55WEL?O6@NbtmF{P#M7AXEh8r zMXnC~`iHsyc0#xxGd*v6V)zMWdS19$csIu{KB&}BS*L{)CsFwx#rn1g_hP=4c{=mi z&%pjSt3`Ml^MU#Bd{y?D;i+X5|774}vd;=PxW(fp+2@4EGaLQ1><;0?a*}s|@?VmD zZuny48EQG4C;yUiUieDpXOYhj4`RL@xpR0Fa&>_0*#+SOGvCG0=GhYGY z|Ln}m!#^<>wlnv~t_UaIYSODxbpNzhxGr*~>JQ~l&+Zl0F`S#-JG_ng%BD({X7>#z zR+#t|s#g;HI&OCVa4%v!Kf5*i>hR1dMqZOLySI6MWKehxas@sQd{6eE@O)pKdPiO9SGCZG@ zb6a=^^N$l?Kag`rIB`1ZkB9f$?#P)M-h^DH?t}CybEbzAXHfpxAfKCaZ+JFxg{p${ zPIwKoS%1FB zc_O@b<8J1d4A4$COqjrBcGw}hw-d(p9{}pZV2P= z+pC@ruV${_-^dq*8{bd*w?g|T=PnNSM6OWAKdqm;B;2o(mxdxsG&3!A%3xKc9eLKqL{$+OV+9;d*mpA0TAD)8s zCx7bp+>PPyk;Q&)3hzU%NGAKYDSU|K)E=9{i4U0etVyBv*c1*UPforF?AtxLo5J;x zE0SNBYTD!D@TtgEDYrExZo%=X{XP!2WBp^mpEUXxv7FlT)T};eE{1 zexHTA&BXfR`?oD~w}mT_%hXSh{+!(H;q}N>_`co^x!;Dvvy6UKfcpD~@V}7DlzBdA zLGHfrZe;K;vA+(42R~@^C#y-oFXsLh)(=s98Xtdz8zN6uSvXz}htFmC78vhv24;6< zz7jcTU(QV9BhiM$V}5VB4l{l4dCi&0Q8vGavohC;viaWghFop;!Su*~+>#ryZ%3}d z?`40LThD$zhQG_LZ@*6YD{BAa?Dfo4pX2P!%vAp4?H`cE-Zr$8W}Es;ehuwYkSV`C zxsC14$W@BQ!-@8V%+&uU*tyd|rt+L?M;^iPqo_RR+f9&b0>-`^&b`1so!Quz!?_pQXEPi7QYWvA z-2qw3+tt1jS@uU=?a|0p$uyt4+GB_nm8Ywn&rIdH$R5i~<>_YM%uMam-JXmr`Sq}; zBa40NVK0f{ExG@&gO8f}(fjmwWnE#{M;8C=3cE4##YVW$<^FW%sqym@`n`&mN9U z@!v}6Z{LeNS$z)euhjti3FgkAuhrG|QjXvBRCr!4Z=n4R%WtWH_W|>+wZn5wev{Q{ zZz^?a-e7w^vW$=G>=nrH`#s=q!Tma0Jx1m01Kct1Iy;B?P1v7bm^ajZf_azOud9)E z=y9Vj?LX2!4q3+kNV_Sr%(u~YGiK`FbUQUJ{usLlvh?2=dkJ!N%4=5|e>%&4jhX!0 zEPFX}S#n^RvHw~2M&=f)hz}yu{OFmNWfwnT%1higFWWAQ;cN18?7NYreRAz}%w*ql z?XApY-}CI>kjs<;eU&W+)(vTwKVL6-ix(_Vl~{nMb$opy_- zFn$W{&!^d`$Q8UlpJsPtIo*$)W?w>#?;roxa+=+XRy zC+!Z*bbt6s`x0ilKm4TK3z_L zzd@S?_Cn+u?*HfQ6>;+C?e%f;#rBuTm8vEOo_Eh%Y=6((=|gz`A#aJjkGVd~zoNXQ z_95mR@K1{JUbGXRGxe`jDR&xv3H=4|cWl}Zzbu?|;bmsO>oM&QJ*NHPD^Y#g-@Y2< zlfd8WoA+9jC&B&5Yx0&w`6PIr?S{P9qg-#Rv1iMp+~{7jKl8XnYa@RnDmTw#!|&ro z+4yI@)QTvZ^KiJI5#?7PzgS)b4EH~x@^|;c?+502JOO!?$nCjb8U44S{OZtnUVn2u ze*#=TMxVZqQWcF)-$(JdVxl>ZcsnW|0qe*6Ssu5A^SUW{QBHbq7@YUSa5eD#d21wo z(h4a5l$3u(c@eBvQ&QGO`Kz|@ecilu!glc%b3gKZ;iO;RHvY87-N2r{pS3Q zC7e&i@IuHxhHbK^TkJ57cbc!CMSuk5AF)Zbs*8v>^qRFk~=~92B>}ZUBqf2aPPEz_H^bux5M{*+Wc(KL9S57UbMlRf#vwqG#iqxk3NAGRAa8+rHqfO95tnaW%a_8~vP z$ze9XqkJ9kv&dDd734pyO@i|g^Hhjm*(S+JTuk+!1N+5kZIYcd=F_46m2E=KNMtA< z+B4fJM6OhcU~hBs9cL1=dA?z6zIK}b6U&R|RR`)E`OCe zFmiR^{Vrf%@|!uMkXPgVL-@rsx_`d$S{N|2& z(d)l}I?YK&mi9T#sTU*Plz*C&N}OD{8h(ELR zS~!`^)E+IINz8PAr-gGDGp$c8oCld{eQM!6#Z2o{3ug&4txqkS*O+O2YU!+DruC_% zvx%A3r&i8a%+w#PoZZaSAFZ64fH|eB>7O&4Q<>>`v@@J@ zi244<8BP~w>W?#>D_Q@&VP^en?F?q7_3tbvo0;rks&fM~t$%Ht+n8znJI9$Ra`Xq< zIj=C2ztPTllbQUJcFtO6@=w}1pE1+=*xpHcnd(dHV|(XVW?CORIHxev`gpFB%1rCw zxz0t*X20@b-UUuCW?KI)bcQg0xYDe57dlzYwEkV_T#sC#o`U-HQWrY6v7G#+F3vP& z@|U_g)0xR%zsPx*nf#}VoJX0-f4azd0-4sg?fDlubzU*`txBfx*xhlEE0Q1k-q`={ zPD7T{`0ehT%S_|FyEB5B#(Q_CoSDXRcjr-N8qeLG<;*mmyF2TdX*_p#wldRrzSQ}d zna1;_&L7M)o_jd@RV=@v_U_>{N3IEwe|VXbfegR@3HE+~y3CoxY|a-9FJr!<9dX~+ zOnR#W$9zqEJ93$7!Tc1&cDoQy3C|krp~(7@IRb<=Askf z{!ISm&JE08gTHwwzo#>q`JC1!y(^rJ$Ta~PuU9zdzfS2DfIkbrsO$7(UUwbwBIKF? zjsGj1ddrP|O@PM#l};<X+B@&>_L|M znZ2Cw8z#TiitIrzXE?Hq=U&cus&O>emO_t7BeYX9+U> zeo!yf&rvH$-WK!|3i>YR);af0P9M&XI_3>= z1~M*QQ{EbNXtNU!`i02H)c- z80`#ZeiHnXdyW zO?h*jW0|{;g8TEpry*D2_cZUy%5^Sgrum=iT+U4MKi9dIndX14lg&)?Ki4T{rum=i zjAy3#pXW?vrum=eEMcbkpYNGoRx>596WkIX5{!Ay);c|8H{k zvp%gSH#vuyX+0V5gw{}bX+4?fG+?InVxrTEnbwPm&iTx=UQBd)G1K}p(J4c&3XnZ4 zcV;11sC(f4MBtps&Ro`~^Us6CdI6Zb-<@iL@fvNH!+>}!Ry zj`gcZw>uBB{5aqnf#?qYKDoUq z@7>N==Bq9yp2BSAQ%1qv&VwA^%%@!7$63Av#>bR`>CUq(UkN-7cnQl#qI`z4jO8UL zpW&=w`R&VKJ{8>K>_Ud~df)--9_RFR)cHL9Qm3+)}Gd>=0>bz&lQqFOEB;MKH!|n@*?n;emds?rz6P~ zt+x+2-AJy;A9=vJm*uoRKj6$`xjDaBSnzj&ueTinB%l&o;twrV@`MG2PPYS!Wqll;a0=* zocYZ2Dh$tezGl7?`5C9_21@@In14SOEO5p%KYO0x=bdHDZK1z^FIen^KOp@`H_Nc62ne#C+_$O&* z|NXl21+k*@mDinLSx)B}%bmI(n(|cfdB$?5J~N$Xyx}xwrt^c9P8u_vFRXShMy^y> zbOwK+u*w<4{Kc6{omKd@lgGSZxZyQUIrAQ{f9(q2ah_p*4*aWjh5vF^F+U3S_JYE- z&JJX%-zA0XobruWUiQy7ICmn8f4;$)!+Zz&>l>VBS)cs%4bD1d^4B*wUoz8ry}?QN zh|;I^dV|x1ne5F5=K^M0uQxcom}$M<;0$G^_4)&+l$qA+51a|iv|fMcOebc4{X^#o zWLZx(ItP)<)C8>0Mki;JDPNf~<6~gqMrStjx#%Bna-KvM|8|q}GBeGuP0m`@Uk2&H z^V&`|b04txh7U2{4(VN-xXC&5W0Rlw+nb!p$m0Kg>?~s@|97*q2U+~zElzl|i7)=| z7H2rJ_`h46@yO!;e&RgMO#8b}oz2K)%G}QhsLz~%Td4kXpnQg>FxS0?cpvi&khgF9 znRCJ?q`wsAzmFw`auxay@cgxt zOU(Z39_J2bnh$%NdzfiH>~S7rrunePSU%rqbNItQ6) zKK$e)e}VO3fAuG42y^u?@=TH!J7_sr8f7gB={-RGIRonZXG6Wztc>T=-aAYa35?iVjFZ0d%$oBXSk zxnI1t@Dz6!@(k4#*4Ix9Te!(JvGr@^)Ztcr9Jw&kB~m6*Uz2H@hQE2 z?uX1&zN_8Pcd`9D*gXze(i`lage?6#*gct8QF?>jc5(5Cx?SVq4|Ol&_|*SH-TprP z;XeILpMI%NzYLk$@2z%2-3M5o#{Y2lL1Hf7aCb2?)pwNpF7gaDq!7MWQ<&*)Vty6; zo9_y<+-=0{?`FFJ>Dt4bimh_6F^MlG? z>@KGGDKvhI-KE3Xd2;Y2rcPi+5Ba!Zj#f0BDMveb8yJBgUE41|lS1{I<=(+e`Ok9ii_s6LS?(d^>Xflq zzgcd=PbR+#Wu7l;S~SaTiA?V=Y|ehr?HI#fWzTjmWxjGDd=J0q5%)S|`Mr`y+%d?~ zACI`Jf5!B2|9uYV*W2&$1x0h+*2waF;XJn;Gu3CF+nJf_Gta#wCVnq9&z;P2YTu{a zmr0KG=~48Qn|y%km-M0WKc99J4;q&DGoE&jjp6sQpLLrdSExP*;C@Web8Z^TO?|Hh zz8qQV`1>R@6xoC-7!+Z|#}?1@UPC|co8XMPXX;}u0K-I>gXZin|Z&wJB-l=)Hc-wn@W-qh6S zzv(Vy&iTafDt86*z`ll8yB`R{{rk6z-g3WXe(y0OuX6V@rz|!6wwv&)ssFv|dT7rT zMQdEmd|X#}zNP3LHzO5 zO_1Mw=Fj1I&bN#H<-Wl@40)})iTOt06-DdZub8jzZqj?#{gHVs>_-j%#;kf1*Zqy^ z+Z*b$wdh^<6y~Rzz;m?=XoEWhne5HA9Y1hq5aaI`j17F~K8QRy**vc}I=#Z%oyuSnTUY)kM$-fh$f8FU*HwU>=eV7n{--r6#y@B~& zsL$b|FWhqGjUT{yd+}EHF6JdLeu@WIyRS2Ue3juZ-Gj^yjJIulzH(3ggW59#>ig|g zU%PFQseX~-?QV}4ZdCk@y8wB$GT+mM{i*vIa+&Hj)7X!l?qSkTe!HphcXzs>!&IN` zz((E#d2(_K&`)i<(`}7hmHg5`rN(#K>2_nL^XQ#!Z|1a~@O)jzi!fh zp5-STPrQto&X;$(?=aJO@=kX0%&RyobWT!ipc>>2TXMPKwk2PIo%7%7*=niT^OOxgTKo8RqYY6TigV zUX1)y0C*b!K+#i_V8wTg4jec+s#qgArAKg&E)VE3* zdBYQSyA7G?yl}63I&&)+e*yKAo5uVP=zqhPA=7vnp8AtJ23f|(K6eQ+oL9|(=c$T+ zb~h3ypD@?#clWz0i0z%c2IPj%V9v+-?|0iXFZ{vOXTRH(dG(pZJ&~)DE5JTY>$Kl3 zBv!9%H{)}^dqWHd)B*Q)=IVdIdF%-X+}X?u`g2g@-`sEl_5b@{LVp$i;T9mn_nv_R z>ahC&^H$~+tZ&YfIu;*x8z-9hRq9qK|DeV}J&<`Ho=+v|$;f4D6P&-DS)8QzvHV!@ zf3>QknkU!4ZOpH$~~om!XD>jmwrRYN_P zxd)s#YjuL2f?TF%zYpKXDsH3?vi!{w(|#xEv}B5ZBg8j6f|UWCfZ3c@ypZ=(BDIgo9HGnoL<~icVag88-^A))0ZLB_$(+sMUO(R37Gf$;TKT! z%gEJ%JK_1zu7T#-37Pb(1Gk-PzR!1>PD7rdeg=Cww)k{C6q(Wss1`bd>B{YadCOFfVE_a=b9GPI?Bg*mq_JYQ9OhJKTIci8ZmdTm_% z*7`%1w@HETdG=|oe~pu$t%H`SU%C1;8Aj>QvvqxBsZXjtk>#C2@cS~wsrpJ}@!#6$ zYvT0V=n<^H8}uJ4ZlgtsYDq*!~5{N3y&xjMog%&tdt&1z-E)=5;D~<3G_FzoXV4?!w&T~ zl_yQ_MlMrS9+0~z=klcKdc<6wG~I~hRGu{5oaI!WG@ZdrfWKFKo_;q@-dTUd@?|i7 z-%9DMcg4vs&<9yQ3d$GkbAg^0i7o$ydLeSTIsoy<^}kTBLYDG%)$hmYchw)W{!*Af zTL*O2U&QHOtiOxXzgX{$)4y2%5~qKOPC6#GJeO!2xm-OMG4;7bH(~znSo6GUcikRY z%6F;0C@%h``X8)+KbG%O-8)WxnI6P)s_$jG1Xw`Il@?W7B#pz$Em&NH{saLc9RY^wwO1&jUo}{kQ`;cXR_tIw`i}Qt_ zH|wQG)iW&fsh6IFT%A$`^ZWhcUU~{K&!=AcZkE%0>ZND0e86+?eGkz8hMDG5Fa0C3 zjQ3vp0CKr%isPx5POb0tUy|yrdm>AD`{>EcH2?ePWyi&qw~yY8EamN^w-IxB`{-|2 zPUY>Rce9+z+ecq`Jhcavw~xLQS^Be&?u#tt@1w6pE{E@Bnf~mfbD1xJ@xOIIKRq!{ ze}KM?OV+NW;xY=kp7UF>OV+-iY)aXq`yIy`VZ1SBA2U=aefTafreiH1=O`Vj9jj$ zKG*6IG4doeSdT}R{vD#1FjIYo=t(EU_U{lq8(I2yh<<{Y`*(I>rZhwC0Jr}_@p^JC;m zYJ^^mEcG3!4>41HN9rYwW9vIouSb^pj?|lpxxORyR+dwJN9r9cr}~c69Zrm`??`m&ECh(#u%iY)iHkkJ77|{|Wxmj^fdJU5tK`O4mD(rM?-u z=}A-`s&9tghb;CcL+d6e=kc4N8xV7SGjtP{Q++dZ3zk!TGxYV$G=4MmL}aONhMs~f z_07;bV&uDv$LIsdH7N^&u=^;^)S;%PJT)oi_h2(rraqn-pGN|2&TO8aG4k_?*`8+V z5zO>FO{UIArtE9ivpQYc4)6deIh*K#2Ed2v=b;_^b!tX1UWa+@kSU&#!`YfG- zEcMOO5g#{1E?4h?eR3dvzc_i09?bGn!5^J4JVzJ!qA!JNe{Yeeyv*`EZ~7M&ug&zGw5kIr?Vi)LY>Fw3J*u zF)n_-z71LCPrkmF_38Pmd|gQ#p!>u5dM5M8N^_o(uODJw3JdLj6vhexd#-MxLY!^^eFhUyJlUW}2@>`kqrv`&XwF ze`n6$iu8lTJU@%{T$a=PEYgcu-W&Y=V$lDIndWDa{tcPxlLYem%`tu6e-!Hm%#?qz zeu0?tFV?THoYuEuy@KVGf3aTAa>~D0AA2gLPx%+?M#z-^oM5qTgDmY?syoNX1FBSC zf(+|DBy(IzslJB!2e5xFO2+CDG5RZ;T(1j}Yxw)ZXZ(DnDdZvx{T!f{n~N* zK4x=1U#xD>kCT3Y%6o%ez;gOt?G5@6%U^G7&P#9738zv0R%M#+d5+g1=FSh8{n*Vq zf(*~&%{S+>H|rCTrTuT#XRx)NE&?*#n_a=AJT>uKAP3Hp6xY5$4((>VQ!`YYBS3;UOgN+#+(%&Wn_ z?^`lS{}QKPrUNZZc_qIxoq}AhLf~Izs4{(WjC@o{neK>O6QJ*1m+OK!o~-Xeo}p&J z`OhyYx9X>uFKceNLa$;TbeG}V^q0tz{}lZl$@%&ox0pmCQ3B8s14;YVa)1TBk zkfs0U>D|cXssXI8GfL*^aBGu(xf*y3tS2S&^$Ex_{-4&TAxr$H^;xXn4d%PJ<WJ0QPHM@G^T;7xW^QKMMZFBk6D&ahBKq0kv3%k;~QTHk@~t zEY?q)ZRAq_C3+FElxK;48M$1&23o61mgu*b3!%N=FIlQTWL^pT`&A_`>TS&PAlbK4 zUeddfDZM21vJR)3{A9g*MfYGPd-saYX=CJK?_SYUkgHQR?=<$~6+NAp?cFQ-0hW`! zdqvM-`Eu9~Zz_33f5lAp{1v?uS?c?WK7cIseMKKeE>|oa$T{#B*RbTj55*uSsq*2t3na@`48(qFE-vi^QZ)+t@CFC)3y-wA%tCG!oPgS=YN z@87M^Gnw1Bh5NaqR_Qg&XMnw%IjTzUM=n#zcpm#N-LWmT-)c;6tscz$J=~8xwsf6d z!F(R*pHTX){sCFa_rBgA!@JIZUpGrL>B)RuuiGJu{(9XRxm?``<1we@dOeEyI2d0g zEkDpZ+L`#IpQJYG1IW_mfya>JpZsoU)+h(r}4Q(Uye-m8J@aD4~^lj zIiKi!Vr9PfH$3$-J)QZC_VE40($Dq!7(S!)3;hSP`TpNIrCarB=bHTJdo$;jeyPu5 zZoL}5XA0b&7@xQ3n)9XZ9>eF9eys<@aIeyDbZ!h^Q~I5rj$DJ^8~ZNzd;KG_eBWo6 zKK4A5f0d%|>Fm;HA=CG+Mwb4l+cTT*U5zZ=tuJ6U-@D2x-J`oB%lz7_`yfmI@732J zm#f9#uN0N;)uZC{f7S(Y`akP&tiP=e?7vEX*0;pzAJo(0^bhJv*53)|6L*vz)N^9w zC*}R7t@EjV^uEd=Z8KAS59wCOQvN@5dt@p9ANm61a@7LtPi5&Jx(Bj6-xP@SLayQO zRRkh^iTQgLfye-6`hGO{68%lOfe zl+HMQaeTg9sv}*ItN43nk;p%gCI4e017h?8>X^uN$mOaMl6j-_m`Dc6`F)%Ek?F|r zz5nx!KT<#PDRU0&7Y%>Q+#GmqY5hpu3ru;+)Q9&Q`Eij;k*R)ge=w3ooIJQ3e($^V z_(&1+?mcGzd3@wPV)YB~YmJVNEMWN?`^^3F29YH!H}5k9RD(#DE|gyZ>@Q9q-5@f7 z`3Br?G>A+?o}seSU_I&FAX3TvG03m%+%WP8^Ah9}BJ+sZKW-FRj4b`rDDo=jPDa82a)N1PEF~Fk#Sv3 zed&7>yGxry)*?&)HjR9YEb*I0wz9tY9>syurjY|N@dIO6`Du~Mm^UDw9_h_|HrSiA zb}b@M=A5!TbRb}b_}#mQSm%31y@%3DQd#L3Ty%wl;8_>XDr&WJn}CqFat zJj=g>^)Id6nUPg-^45{HEPoQyZynhZCqFAv&GH@?|E$Pwaq_bx2^X98Emz~QJjhxEzTQGiVq-~tMP2{{dd7DW8IQcn|AuOMU>7NtHj+3{I6tnyQmcMP}wm5lO zphM&vmXm+bA+iry+6&T027eUFJ1E#8a`q*$=D7`Ygk z{MT6}9V6E;8~-(w)d{?I_zLtA=pq$V@2oLlKwU6~!fkb6lEd|dZ^d74mqOQ1hG(eE z*Gad*y;wL6Ro8rE!ay{XbWYxHt_P#(5(nUYXVSmAAIW>&7tcF{$I9gzd--|HVKr}&Ar#1E)fZZqiz)b9r%T`G$W&dO7b>I&!`2A9P*X@8M)>@5?YuP^;IGyteCS`t%p| zG5U$ocz(I0SKIZE;aLJxZ|NuDB`fIquHPtpxu*$(sx#&fPoFfP>!L5=p4;iVq(|c* zLD6{f#-EH6|M+>mGsUMcsD7V8+yT~HlmB;ng0edWc-wMaoBdN9JFf9+js~w0|UjO2_Lbe}1AT z*QNbxs~=tW=843sEgk=LDgV*hLFAO5*ACP^0rlgnG!B!|o`T)wbwpUgnQV6{463S& zDPBA$sBjN+JyA6&HDQu!f?P+XA_tUT|JTb%pW=Z&>eb4b)3BTd%;~t{xhq(Mt|7tj>9>;Pes8iVAsLjsnn<&2D-uqeXr9Ujbg5qC0 zkiu^5C_J$@h0@+qPH9(3hx*AIcfvBhWL$_{Ah|cL{MThX_~XfVqWIo?l=yx*rQ;t@ zQcllrkof*`Nj;<-!nM`QpTETOr~g;$=P$q5TS=GXQlEg5d_+%J^o6CI{_97pm%rT7 z9+Hl*KOM0fk}v6b{U>s|F8z|I{Pw`FSDW3EbfjGVc>a2b++RM@^TyB7^r$@l-?z); zKL*w19~t`~ex&r5=NEr+DcO%LD@+(v!nKVPYHx2m``er3-Z+>3`cM7L+VY`&T|mkH zPVA)EM}H{$9ofg3FbMx*w?&==XI*9;pmy-~eG>1Jvq>)dg4)8{d0lw%L8Bj3bD3qo zO<1IZn+6*-x`GV_}-Tdd;8XtXHvX{b10 zC+kfj@6VH>`|=Xr&(Syva(~yZFa0F_C@lHW{@n-j7 zE$??_ALI`yy`U=TX4)q~RpS0SF?!xW`)f%be)aJQqZf>}hm=G5)gRLM3My)^BlnN# za4*iJ*K@836V%oM69&{841-GMO>KI9|7qeSCVo&g>1)CS)q?#&si)W#zn!^$meH5` z9X%BLBJJ_hV#?2qM=zbAYJ}rA0mo_V^+`DHVEsBHR$u(VfI1$_9aQhXLh{#m9u7Td zIH(4~GkzvL84og^h^5}%xrNB7J!IX4_~R&je?O64FnaDm^Eb%tnV`teg|||moMs-U zbA9Bxw71NANuTUzf+BlN%zaQue7tYqpSxXX3dgNZy}Vcuc81l4-9`w7wcEAdF4 z!14fxlAg>5kHyYN_#F1Xj2CZwEZ!JfF0Z}ssxsFTxSbQZ-R1mK>?({4v`YcDA3?5{ z*Uv}mUuk!;9|8ET9+hVf&Zh*PXNf$|lA_~J?1<>md`OJS{ppgPH$TKah#ix3XkH(g zpN#jT#jc8iYhf136S zD1ZI`YCWa=GG1go^s}t5|I>Lb=}|v;<5A|jjK3MFram&?lcM8L^lGyUWG8|u2gkQJ zuBG24K8^o?FJ1V3U7j!0k5azG=y|2Ym;A{dB`PYfm!H@v(Wi91^y#|HGtYiDztYq@ zK@G?CDN)@&({Pgd9oP3d>fTj`z4dxFUia*soYPbP1l3PyHxpC=pMU(bi;174KL6Z= zUOI9PaI{d;7kl_Fujf?mMD@kvl>T-M>!@4bG+Z}o*J>+o!7igG_B^2IK21Qi>`B)t z^wyhY=ok3?uwe9@<;n|8Jn%%>pO*Hxj{S0(U(_$M?t1f7#({sF`tN)EU6ys-A5Y3h zet80~7m4cn3R90HRTt+&o#?uGH2o&Gns{|MUfpOssTakU@$Ic6M{5tV6A5g;64h&% zPe4W3|CDquG$K0VUVJ zV}DV`vGFTRKASndBZ|MC`!lEFGf3(pkC@_ z^b^&J74h-tdV(6~yPh{NUXSK`f~xI0%|GuxWqi53@<{omoU$K~{Z=viRTMvvY{>DPz-(FyVLn=oIQ?+NU$Cq~!D ze=kpp+JV2OS4XvPO8Lw9q5XmQ4FUCc)9H)*@}QFQR$&=`m+*X{_J(~3+V#ZfIGoVU zlqbm76V!v9sC-jvx!&~?(x>?sQ2UpYK7~Q{zY`Sc!FPJUBst9sDQALujQhK`>+fDg z`H0@8_u_d8)+?aKqCF4tyh~7*qh6v~iJ{ELAT!JZ^poNI3Fo6Hr+gCB;peHm!{<$Ve9JkLLpaVhN{c$D?r*RvBlAqXRslQzJhjc#)cE&hg5>(>7rXJuAuc7+*(_Px0uKUvwK3e@n zPy8EMU;O#VKIG!9l%H@4j=uyY*ZuKiUQ+ucMEgtH!LKjnsZH+JudTgheZBIbf8Rd- z^rWA5!1}3mf@(gI;!{3B<-hKa@8{B^^pA|^qSq)N=`Vje^888&*LU%AU>@*uQAb?& z&5w9Jf4n2-leE9|M{S{h-1u4SIbBbP`Y*LzudV(R|HyK7=XI&JaZsIO+BK-=uzm2i z>(C`6mvJxiIFrw1<#paK_cPVs+Yi>(zH(j0i9em%$|w4@wTq}xR-Jc;r5g9C+UlwmGwd5QU7_*;fcQ|ayf68 zap^y|6g$?t(v-tHFK*a~$|dJfvagbJjkWg~c~G6!(1Zy}?9H`kZ-R>C;BV|Ta_{^x zUJhSZ_)~q^A9|tGo66~(14_B&JV~Bwkox-fm$D!KbGhUv&x^tNFrH_4=LCNqFHuRl zvVM`C#0&B{kL>$vzy2xiOMDx|FnM6esX_}#*^26(r!{-v4_;J zK{e!NGoAu`{_gGPWn9WRrJT3WIgi)wa-Gh5yz5e~zc*gIa!Y$lx&Q7sq;h%X@$aw1 z@2t%qjlT}(gX2s)B^|N<@~12FTG~CHz4LYdKJI@j9cg!JKYxGv&x^ob45a>-a!Py4 zb-CXz>H6(mZRcP#e-qT}9VmSnC;ssu`N=q|Eg!PqLA7_;_a>1KQeA4l=m8h$wn@ge@DgrdI{_jv(z-5%4QL3JUY8_Rtox&I;g2>aIo zKZ_pihrH)8HWL> z%zfVYa!EYzy4<&rP|D}OuR-}789)B|k#b2->iZ}@kL>O9qaV6N=`GKrbc;(Ve4&s+zrREN6`Z$XIlc33$zReL z%IE09l5Q7n7m-sKRKqx5xi0!5|DNSb_nC49mGCidP&w&5F{mWIoG%JXz8%p&45;|f z%U`bd<@+-J@{2q^^x}X1FqKC=LZRd@^^kh5!utyWMWGkpU+*uu-YFQu{9%^*$CpFu z<)!y`%P-^XXwTb>`iSc1Pyc_bzJIlTV&7<=Am`yh^%C!wWd9)iclE#Fev)_;`qTH$ z%_Sd+CoJ**YB}$XE5Db%Tz?kjL6wK&6#VzjrauzZ+xJkv&~K{cG`rEsrH zj2xbW;Oi1k=Ks<1k@`u!{OuiYH$8hS<4oj#w|%6Xl1{GxJr5}3R@!0PW>ddl^!$;o z!@7gly>rR+xSk$)UGzx~@2g_G#Atf|&EK?dK>fG<|8K_M-<>xyPibBU*nR|6JbQl2 zf5-QK$M^rA=l9Xpzn|Do6g`?R3DI>}<`0Fnzi%${(!YNGcb%j8C++y(b>{zOo%z3R zf0-A#lW07|bApn6$e&+NRPSU{Jn?Hq@4~rsUFI*%x7z(_is$*`NArJW{z`bXd?bDG z$0hyRLeY;8{reM-#b1z+?z77MS=m2%A-#X*$=|?p%Ak5^0JWQ+pT_&=0o4@Gr2^`; zwWT+ zDWu;3_wDdJH_QEca$UlB{RFiuH$LBZ`H|;FwEuy99PeNJJm*eI&s>i^=aTx$a|_3x zM|x6!IS1@I$BS>)aXH_U@I~&QPq}{%@OxDfj~LE-eCbFzB|l>C`Cxx}{pVx;_;N1i zPv;;$-{|?Hk{{JSs1~PF{rvA?ik{31zrI|j(A$^#IO4k8|MlztZ(rYq&#xxdn*X261B%K|?Y2m5mT-ju`-@^>W?)b>%P9pF7ylqacv{M@UwlfxpM-r& zOnP2<7FQBWD080(t9c8 zQ`@+Z@hIs_`1SP^FYy4CPp;P%K6se)i!hXR&mVf_>iamQ`&Zjj#;L4x6vF*Cw0q)b zfd2t)iR)fJDv$8iZImA|Jg>kk?^{c~Zsq=_5XLFn54leL8BijZc+&3i{VnfXiGA`| z;>o%!<&yM8E}_ZK*vHf{R1bfCe|{bAH~hu^lYAsyvO5V;yHneBX_wmMl5P*4r`Eev z{wsLgXRtlp$M?S^q;XMuf6Dx)c1uvBaGck!-;M2$#1pQ2K9xtV$Fq#9U^IQvlW{0a z`6qba^NSmQUinDhOLyU{`26X;0#9GwGoTRecP$}(VQN3`xkR}x?LlEs-MKJ6-lhi) zOFoHe%S(SvF7+L|-i*ft^)rNKzKMM~7oWd{?*JsxJd|?C_&yt-`}6XZ_xfd={HNjU zU#UE_p9)6HCHpJ?b*ayd5VZD-+si%40kJgjA{2hX1bv2LQ|7m%p90@B; z`Z6A5{CeY!=1WlhjDDZzSNQX-ZGPPlqV(xICEk4znYYw00d?MNvM=)fl3{a2@)13; zPw}CrC)Y(^@}bbPr=sVVOMYTcNY8s8BmVl4_EhHO-(4SM98kGsd7fk;aD1% zM&GP!vY(Z95qlymQoBKP}if7V{cUL396WSq)8ix0i|Dtao{{(eDa-wRBVUjvwE47RCx76dstLgg2n<&h_D?SuG3IA?Cl(9XDufI2MBweY0 zJj3}Z@9!m){kwlZPaI%B8@}(x@#6L1dt1Ki!Zgo3zrf#4QZ5M}yN23HLOHLZ5b~c% zaZi)Zp50BjM#@j#7-pRZa`?u!KKOcW$fB$MI<&}C$y`&vwK8jrQkCwj7n|~LY z?_J5fl6)nU^Lv?Rq9^A7lD|9;_X)mt0MGlf9h7wFdxYZ8Cq(m;?-ZJJO@H@kPVM<; zY&2r!N3vIsKa1~A|H%0M^yAYrehk$=sN}s^I`0<$)bk(3uE}~#`$#wk=Y0`zKuIXq zrM=|3gyNt0{a(pO{0;FdXq+D1uaNmc@jd@8o)gsWi%e@Jsxa>(B4*2zVGOX|Kks(-6Zte6S^+#@14iXb+R9DKLY#5JHM6o{kwj(%nu6T z`*lreT#J7y{q1M!@1R=4_bKUIQ^s9D-IGA)6z}nQv|%%@k7YL3WBCcV&tdp5f6qhY z!t(tCNsr#=3@Fj--jK>IatY-=lhjZ4;qtsM^;%l-SIp-Np(Jf>a_{|Txe;Z z-V5Iwc@q0ub)x6Ms@MNx?p?sDs@A^mG3J_U&b1Z?K~PapL9j&efZzcI!=Qtvl}VOG ziGrzRrAd~G27#JonT3`~g=v;$C8fJ8Gf1o`DlN-wTVdM4ogFO8EZV*QdyIQvuJUc~ z?|I(q`mS}&`#0}#K94cSJS^?cw7+1kQ~Mz3pV``-(SyS`_k&JmZ_;-%d)-dFE$Pzz z==lG6==zgl>1jG02|1en0h-2MhmY?sak_)kY0_cJJJ>$BJcHe7d%LB)PZp2Kk4e{m zTQA1FE(eczn&106S$x6eulv1e*BBGIo()Yn!S#AFJ@`Emb6?%Gce76UYx9%8*ZbG* zkAG*`jK3z`ranwM|IWW@FQ%QGES%tQb-s?bzmvri?C7%Og1a|FnF%<37hJ7z z{hU0W;PEK9-XG@u7gNtC)BkS06r4^|AOExcm*e&PNKf4^^!1%t|Cn*k7AM*t-|sNx zWBQj_mzeR{&|Ehf8h@r-jJp$ceD8^$V>0$9D~FSr>;FADKF^x}K{**szcA}j(=SZB zGc?zoCLg-pn)?}MeTnD!ZqVgw@?~_BA4A=Ljz2$X%#C~Ve1WD37uOSNU2Eby-mgd3 zQoQ(n`}4%(|No-XZHd`0X>)CFw|uYAI9l_;e>gS;vL1~?sPqP#Cg0PGWjs(HN5|9@@Z(s zKjY8n#{G%m{5ig`T1ro_d9dyg#+|9BD$Yk8=i|idbt&}tZraP=|Bqhqd(Woczvkx- zhF0rz>ikI&>|VDgd{^;v?as7g!{GFq`ZVpzxHB~MWpqOmzbR*9ZqjSoiz#<)e!Rb! z@8Owv|E|Aidk^=gKlhj5{%>?$4wg8Xf0J%QQ?IF9-liN|?thNeUBdQ=WgwJH6j>d|%a=oA&VkQm66Xl-r5%oM=w#VpC4W-5>pty=gbb-t2=+ z-%a_ogz1k@aKAL|#f0;tn&+{9!SlTtcXYVN$L$l%Wy|};^LT&rWHj-Z_M_{^!{dt0 zA*fa@Av$-x=FwGZ@xQh)-T7y?Ubn7nc3gd z=|8@nG40F5uhVD7=Rc1Rrhfl=95~)SjJyAI9x?Uuzdb&f`qksfpX=Auo2i#znsk}+ zIdQ*B3bS4hHaG6|b)2aeL;Nq(TwO25ovsJ`A0oHk|IXazeKT)M{|vq_`rn0jJe~hp zy8ayh|4w}W({TUn-_-Aam%cxT^Z&~KlIeP!{Dq(U`JcvP#x2ADX?Xvg|C6<&KbNPe z7sLN9o(>nC0xn0*`Ba^L3f(qqO` z9qw`e_nxWSgRAC4k65d8Tf`{c+min67wGZCtRu~S(cj%)GV_QocRXLq_c#CA9RCx6 zYb(0GGWQ)%q}4Khnfsn6(h|?}{iqYo&3)A4^M`rQ!tie1Uo-dd49$FD+y(R1p!;pX z?#+B|XvT5VU(9_#y*@MdNez#uSKs&4=G1P?eSUL4^kjM$+()DP_cT8n(pgLV>bdUY z`ynPh!TsdK{R_MYuG)!5yvysTx{kVin0eW>x6d23x%rM-u>JIQ+CF%lX2LV;7yZ99 z$M;>nSL+V!d#dLF@P9Juxq{=@;kv)ze+fB$^B$rm{-;r0pLxVHe4S?2dnfZ}uB&J9 zbCF-%L+Q4}ONu64QaoIx&Gr77M|{uk|DDWyIJei6*_(8m_)WPQ-Ej79U5?~FBEk}n z#_R8Zcez`en{qJMr?2vJt5f;8Rb#HdPx$Bk0@E(^ypR2fXLY#2`wHg!c!s8Zn)YVQ z`||y|XE>aXxgHG7_vB1FH1`8dI?8ANb^L)+GPhdNXTo=5w0ldHhb5?A&^YsV-}Te^ zGv)DT_kS1OcYGaU*pfd^kJ0}w9VY#TC-e7r_QCN4yEnS2A43zLu`hj6m!BEWgP*7P z<9PMQ@y5J|Z|qIDhPs_#UyASRoA^!nnfDRRco)15HRgsUT=U+*75u)5(e-`9*4p_j?Z5vezQ-1qJI22J!5a;Gwuvc{(`^rXP(#9^W*XNs7!tQHIF}k zbGv$;K=OM)7O(Hka}dYp-|)V=p1qxk$NSBR^D_Rggs(Tu`%m}XsQsDe@eDg$rOnNI zQKnu^J}x*%+mGV$A(+O!sn-+Jf&T~EuKk<(J$%f_5KR5m zchT{g=XXuM+7Hs^KYXWY`iprkF<1}IpB}HUKg`cV8hgEtmHgZrRtDT}f@$vO=<(Fd z|Hq&6*Xxqw{!ixaWaf`zJxlGwTwj`fLbJ{`_p6P0FwMNC!}kcY|MlOR>viSv>jD$+ z$-*)F2WH)7?kAb`nn}NL7p(uM`7rBU6Rt_8xes}=^cnZ74(oQ)`&&&tj+^=DIKSul z#>{WQ^Rtdeiih}q#H)Ni!t4`IIikb={~Jwv@5t*fGcFNr(FafV(7TH3WjfrPCOW}I7co?vB2E|G#aW^kT=o^i#h2n7(I3Yk9LwbS zB2Qj`V=Ru#aa=2Q$b~p6#l6-Fgt1a|5NpH%@i30ZVfLixX>AY_#M2_xdRkl|o)P`5 zXG8{$WpbmqQfw60;J6OQGPwy)eLX9Do@d4Fa*GJ{Y{gNB<7Mctg0G3Qah&gI!0|ec zMwssuBRucm{5^1w$i*?j^C8TeaO@YQp8eow;Ai0HVzK9QoPUnI36AwRHrT)7{CAlB z4hmU~qr{e=1T9&Gqr~>e^*Bmw8?-@3ZopAu`=I+kKj>H7Uu@}W^X*m}S!~DPJO<}6FprV9%Q*Op zgTFZVi-W&7_=|(TIM~O*Z5-UjA&#za(-m&I!p*6Ow;PUR9NpozJKXlbc?ynRaNh?^ zmG|PP!a?T`pv6_&{czq7>F$R-^_LHc{_-vy{c#M!u}t=tKf~Pb=`Vk?`paWDGOPhI z+B;CL6$53ccM#kUg8M;mKM3vzAx(pjra?&4V4M%e`Cy!9!fz)0X2MMt{A9sT7W`x> z{bxH1abzKmp>Q)4X1NIaEE(e+jx-I2`{8gu9PWq1ZaC639PWq1{czbHJO*aqsKK!b z$7UQh{5~&6$d_^S$1w=UGC5MdB1R(IbLH#eT=^EhshH&%B}aNLkR!Z#D4RT#M;^)} z59N_3@5FHnj*U2CU|;XOP*yk>%3>V1;J6V-i8Ds7vB$vQC9=SKDUN(O6$f#$_j38M zxLkfJ#-VkOm*3#{UKApXLWEI>FeW05i3nq&{7Fodzu@?{xI$X;3dA)T#}ph>4a}~A*)-_WpihH74f=I*1CA};891(&0Xb8K z%Nt;K1MFtWjX0jeQH!I(nFW8dU^fePvtc(IcC%qO8+Nl{Hyd`dVOIjP5}1|1tORBy z$_%Yvwv}_?XD;mL!hSC7=fZw2?B^rA`LLT0yZNx254-uWn-9AMFk1k#1u$Cxvjxhm zty~~m%Z2c_5dIdz%|f_Y2saDiW+B|H!ucAM;ln7yhvkRjVbt+jxLFJHM^L_x$WHPR zm^}{nn=rcmLk7f)vNeun@SPD;7Dm^%VE2~1 z1iT$wDtEwa2h4WBYzNGCz-$-HcEM~H%yz+S7tD6UY&Xny!)!OqcEjvLn0*Md4`KEp z%szzKM=<*cW*@=qBba>zvrlA}^$FM{XNo46HR1e_9O(I4X5zSAej~Fz-=bZA3xD6r z*&xPBxcLrd-@)uVn0*Jc?_l-=`oIq`{{iMlr>Ij`dq|X z8@#dB7VoK67un4^MGl0&fp9YrZv0|w4PE0#DtbkG))N#1B2_U$WGJ@5oJj85h*63i z#8|c;&z!=X&YZ<8V=iJYWv*bZQj}t|V!WthJzBJVO^9?6Ekf}1r%cfxDgFp?SW&Vr zF$0*{5o`GfVR2(M!9p`&Ul;hF;q5k zei}JHQ|!&~H%3giDV+1<6r19^NbV9J{7m8P5)s%nn+RQpze_B>LWrxO*Odt|6YO)d zwhv&pVlMQa`0B#~xmWpH34YQ*;q2vf?&WX}aJmk0I@gI0aMd8i5!Q>@zM1pe%;7Y1 zxXm2SRMw-V&hI)ev*3+df$HQJ-Zil@lzn@@tj`Dr)H&ouoy!QK~=gM}AG=0-F zZ%YxlYbN<3#?_9;VLQ@dK(bWl6$GV&b1DE zsk}ymR4!w|nO6&OIY{M9yb`NtvZwMcw8lHS-Q>!OCLRAdSp8Buez}sE>S*&+N1LZQ z#$4wk)zSG#b#y*b9i5L zsJ4pbn<$T!vRHON`BlT6&UdP#^PTGG@Vs$sohTSxZ^@tP;!(*3oF z^&-~uE!}^MnCryk=|X(zS?BISyZzQvVl}C7OROy_+!|N+qkW?Fxk5zQo81}cA2D`= zxc?nWZ;kZ@{EZRXf4p7C?rW@)x5#{_NLeDpsrF7WAMGQ>uCR1JSSO}jK;fbCu`55= zUZ?tD4)i&v3vm|KniTJO_8#|wqsX_tn8%SyW)*Xv`wr}P+Xs0(I_OSVD8xthK{pw@ z3;XRgmTvd!E!{81%PAG)eylu-aYJ|yV+}8b*SpxFcDGViGLI?qFmDy>!{mkUV!ZWk zz9Cs4r8Wj?*BPBHv-o zUe5Oc&UcM`0C!>1ojR%g>-rxA_b>k<#BgVwdpg?1`A&_Dei7k0hg5u%oIUPW7`Lx> zc5;1bE@XX)bA;2?%(T^bkNHLTpQm&*bA8wzJ^nU`Hb{qQzlR;&4vspuM~}y$?BDj# zxa@VK)jZO{jq~XC&>+%NF@CvwTxys7+)xj-gIywy=cOd&e-h$dfbr`hx7nicYl3Tg z^tgY-((yD~x}1+#I-Vnzo;NDlypsK;aCm#%^FI_~zMI~nPt6nJA4mt)-+OMQDsQhZ zlhc{2+^v+ko}<_e#JJ~)|CH)8lhb)bg+Eh{Q0^qIICtJCL^t0E&oi@Vo*Lm<4o;Lc zG8E&?5TEqvem&GWe7z87_=Z|n#R@UZ7wP+Ft`MWZk!KUvxqH!$E&+cA$AQ#eC-~a? z&RiwLG+%;`^c$cbY7(N%m+Z69zwQR#Mmt#H+bM5Ed!_oJ@?GoG^|R0!X62*ZJaCG9ZcTx%`_oh||75EH{rp;g3CFibQa>*9?~(H{zTV<*P~+Y0{+;sPEK2Vl`69ww z0rP$;{ks3I@sCyMc?RaA`%*nOh*vRBZugJ(QNMq~ugAZ=uzztR&6`tvUHnoU^H29Z zwMT#r;vja3{_S63QGMBg6&973KQP_*ChVgEvwWG$Fn&WnBTa}{=&Br`pN{odN}xeJ zx>JbMK&0F{1mhX>w`$Q|0+rTwqSsQ-i>}UGf=_hzsK#1c6)mOksw_U1=gwXB1D<>^F=~D27kLyj#2hvc3O={+W% zK8MPwQH@tCWur&WJ7vBhaQAV@F;%`{-swCa9}_fR{1kH7dT*By;h~4E+tGfa?8DX$ zjPLD3cX{;qwO5U66Wn9gcWVAQrsj)DDA!`7e~efv_4@dL>K`-2As(Nk=e-_eFFoVb zc&y9m=1}Q*AMN~>&<0WHmEw-jV=ncxm7zPW(Fx@K2-kBn*K>_^57r4(e|p}j@#Uhu zejYl^-t?RhheMZ2S||Pl{qD`A?-ci`^+hw6OM}>kd6e2gAj|&1vfjqL7ar*uKZ?>3=}D{;A{x4$ck4XYBi$Xsr+9RG((!i<*ZnvvJW`Ew6wdc! zDgAMrt`S_`Nvx-+>zx@Q-PZGBCYMvDt^0kZO4mx6Y3p{D%l0Ffdj9OwszH>f{+Gw* zdF(IR*4IUmp7+r{!<+4FrewA2~||ez^th_=47Z z+<6}gaVgBHT~3s`e6dr`@#J#3Z{hIATGKLwSkk&de2#XWWBdKnzZK%U)?+OiuYQF2 z6X@S#M7?r9$!TPNyExum9M3K;-&H<+9kAD?ub*T_P33jtUYpnJYCV@5RiesompI1# zZ7-Ko5s!xlR6OIN4z;9Hx63tr9eae!vx2Wz7c<9N(OrdjG^&}?Q^n@%nHjbYr`gum z)yzluOi3*)v9nBT-XSzJCg-;QX!UblG0r?iaHj z%6bLs(X3ao9>@AvtLj$T&lqbx`#DjUON6N4>#?!c{ZC_^7G39A`J@ojqid|^>xH-> zdU1>Wz^}1i5Z&OZ?St_jd|Pp>mG+hpcSaxdXzKFxibGs)4Pp%3y^QdvUB4Es>;IkT z2Jr#<)mPCOo}=Jl=wIM^KFrDRybb;weTd69gU5?XPDiqTN3;;XM^~!yo+y+3zP6+% z`wuGfWPdX2MYeXQ+i$YJE}-3wh}7K8?pv|@?^y4{`bX^ka&~XEA%9gZ>d{#V0i0j%!dJd~`3Gu<*tTt;nJ!@Lp=e3w`?`+c` zE}l%``fXajJlIC}>ve5vJg+qgv7t?}Kl?_?kJg`sUVgPMmnWV*Zr;G|cOpGqP!4*YeOmnN>a7_PTttY;`aiT9V*`Ez=zeI~DN z4=HN@W}+Nx&0H(Qh_=c8=^Soem`?Yttu+^LcrUlpx*z$c_Vy5$SJ%T@zj?Xlk-Lbx zTrNSlzbHM~pZACIE^Mp!AFwm!Z=6T&{WkTF2T^XVuzsQN8*u$e3}JoUJES)VAL7Nl z;OQ_2`;7>Hxk{IgZw~YkT;4m;?kF8;SSMiREoeTT5Bqj8+ML?KZO|i>p6tH~>qUxh z7IOjfcEuV`u?nZg^CRY;``~Z$AL6ZUTjP;)u`Y)ByIhV7LUnjQay|9natu-ZDA_-V zSpv0Dbu~QkAmw_9``c6dVWpk zc986U;92c&9M@MNbM=SXeBu#ejpq#H_rA8d>@SzY&*kt(aQGuQe5@xh4vrCd>@Huq zn<0wWU4yuEnGn~stFd;f`Fkq6o2vE|cZoe}-g>It2v5l@x{fGj|0V3dg7w9$SF&DZ z?0LVT&hr7r?b~7wGS|7Wi0{#uHJp$2%#F+~UOi9MGaH$>j@XL%y?ujt_0e-< z@Eq~dzrfajw0@e?VVxT}6YG%OZ0*D-3J?4u5GYJYT+Gexaaa6N3(I$*MQ zidt`e-(iYcFA(*8f+@D%Po84yeemhLu3W_Hm0We5KS3;2`fnXpDNb@$*c}suh>Trf zzlwem16K4DB0e^W)0e{OTV#KVe)FYgk^MCoAr{%Q)b-FJdjUv#WM6IH35*ac?1)#f z--+;UM!9;Szk~6;4M_Vll9?CV;NLM-@2^zhYc5}UcKXTwl3300vFqFo7<5uv+TWplq#S#ld&yDE&#|klX6Rla1G5kh?I&G@^1B2) z1^Wf(J41bwke)Vi4Jw}zA~K-&UG#n+zDcO+72}Sh_q);^z5m@lP=s*!dN;+l)4qKm=ApQq9M4X>AM^;J?I-w>15}Pjo#a6F8QPrO zU%>9if(K?${&w1ZU{CB0d*bjhR6jfII@HIcxJ-xkOD2fJDxOPXHODh&BE9;4*J1nl zVya)iinlE8m^~Ky;<%xKLX7iwLGSss5ch)pV}w{0m+R<$0(VH~d(idu!7;lC{yu`c zwiq7|#0?AR_B|{>{bjBg79e;3id*Mir|NN7Kwm!%3sC&INazo7SJJRL_U z-77{oL(mRlI_9yS=fvGBL{i80-YKdaun&O#e^$q(a@{=aZ*%-rK9 zpq;hpw9`t@p>e5%%c+vXtK{%Y9DV&*qWWo;ze@Gf(f&26J#F=_arAX#m80jgb=U!> z{mu0%o@#5e|8&H&y3=%(z9+yP3x(L&DcScS=Cv20pMvt;)+xaoiTMThGri&9>(D#1 zPWARS^b3=`5fLgO5e!kvc;k6w10Kl;`|QtA3JU2 zd?t8xJKM19($GhiL#N)BSVefg;s|55b`@o9B?wQ zo*v%$fVyrTDi1kBt8v}h`H<7N4A(axxO_`uB=v zZWl)!dTMw*+|ho4*R|FDRULFaKQycMG!yZ@iuhiKIq$zadY)_Me1|H3UJ>f9c?I)6 z;-P-=8QkmsbA;LK==-@xT1ZbbKhd$-(f#R&vlr__DWYBSkNXC$o`>RG-ClOaOP_Cn}o66!_c?;$9lWpt=SX&1m;IzKG|Es{`a^=7Yh;EC6D!Wsvk;G zq0){0C|8e&w35$*Q< z#4?NO?e)Z^UaD6+X@z3zqz2VaBg9_LpA2+>zwSu~SU<$vqwe!uoOFcaYgX~Cl(vuB z{|pi8)9pW6?RP(!w3+K8PU(}JB%j`|*Y|NE#4wBQ1AUsb$1OxVda7ND3Mb2-uEH7Z z&-CeXNcZXfwAuOw^Ga`br=a@*le>>$bxrn9;p?LD z%n@PwdLx(lR6DJ|&U}RVpkfN|+mGP%=lS$~wS3l_dEYqSN98$DCb9dX7V7>xmGxqu zZdb)VJs+0%^nPgtm)~M8zf7NQ2Pr;X&r{X7Nb{o(FIUAkQ&w_1s+fD+Z_%z#J9Q1~ z>s!oe|M2-!SEzcPg1@KQ?c{N+ z-h{{NgMG|KpL*M`+b*A8H}Cb)_&irO`Z^sGBEH)JpWY|j>(l*lFXwBRHwx}H#17;5 z4{|%y<<+BGv5If6U*{js@i_F{$A)f)xV(;VdFAuC+U%pZDSqjubx*SG*X5lr^>ZKj z^5P@3zRKt4MDpcb==Y@S=Rxvi0R4mXcwB#t0SAL^M6+)n)+=q3^W_;o2oVR4W`2S3 zIT89%Mcc3I)%H`pZRlqEb-ryst(P-}?brMJwqN&`d`ZubOh7!>fL?HjqV3o9Z2NV7 zZNFY0*?v9l!u%c@Z}Me-)D!VW#E1FJPhTzXn;hz=ua;+m^wo0G>8s_rAbqubL~^uR zpJU$g)BINmo!(~nrCYSW(uezU$?a8po8(0M+oGQoCnvC;r=CxkKu=R+9+x7{|Bs8X zPn4YG*X!F9fB$cApE|in>T)mQ`7PbA$A#(MJt(I!BHge1bBe!tx)86zJ%zW|pW@f! zR*GMbrN$W7 z-Abfx7bS8U+Lc83IzJ_9p5Fz1o@#d`{G3sVoQwXrQkKZOncczD5x#!@2;r*sgK(KQ zg0FWfk=$O?{se`~?aHF|G#vhQyDH)5mP(|4ZmC3a`%?3SSJ;+GUqH<#wlx9k4@$Rw zzNv(tZ?dgZQ14^lzUgba&a!LgITCY%GXSc^S5>%rrPJ-Fpq=32f8GnJP&t$;O>>~32HrCoUHv*x!y3B+DV?DzV=P^c=0N% z3qfk1-*(UEeiLfZSFf!eq1GK2Q$F&!pXd8&y&uve-=E8D!%SuV(5UUBus$bu)Xym& z-2b_M=X3ww<2Iwbo@y6rrOl-N5o)=LMVyWz9w(;yJ7T?eevhes{rp%Fk2gg;ZcO#- z=gFq}{b=tKdld1wSj6L1rTkz9wX>=IyhO^+RDUSkO#sJ0zp=+Uhn^Q$)MKnFuRD4a z`|0b{)gXN>yv9@FC;t;=v0vRUgZX>tM=$rNP&%HM^S=UpUysGCSEzlUOtF|*>DTMg zRlcjnApR76zbQN=nb#R(dHkv3d{_DPdbCQ7vlHbSx#&Vl|9UkJy_S;a)B6H>YW*-l zRQdJ1lj`X4dYBV>4%$b`MjnT^@c2}(!r$x9Q}Yhi-A=x`o~;YqawhFlYm)Yc#p&Or z{7sZcxZayN{dPc)uLs!O0WP0i+@21wzfg5O;PpkfxYzwXI-tknP~Im9Rr>%F+|Ym? zuR?i$;DCznv(9nsKPkZLlmK5(sP*2ssPupyH`CQV!!D5&(CfGcWsmE4F2{Xbe*2u- z)2N?kD*H*!VdpMY?uXevm(52ok8wF4<8Y3#yJH+qo^mHeo{E2^%x8Z^D*rR^AAo!J^KDoSf2{EU(E4T2IzXbZ=cEl zy)~B&($`+j0O>1;{~1n$-PqcTAAeP6iO^S2H!Jhf8kF{z>I`Im3I zM{+-2r228!)SZFtL-0Hi_(pEPI|H>p5!VNFKdy0F zl^}n(KTrFSd8r#!IZTvWm>W49%^uyhu&&vo+ajks+S?tei=4%G2(cXgb+}uY(xvC! za39Zo7vpMes^8r-m?+&2?Z{lZ`g*&@q5bUFQj@G_=8$=v{Y?tmOW!*C>}kYN-aGdT z;r3n1_0Zn^4dZHC*x!fxBzF(O{Rr?Zv_HCz?}G5r&I0FPo}1LSy<38MyB4H=ItT7Z zC-;whhJBE}$!;3Le;Rx&ALA{|pF?=>fe#naer1BY1L-4wy-|J?{y4PHAE3ASUh9cq z1fCn#>0j#1*hBj`3GPeq7nhdc9!9uFojUsm)YC2gI(wmpZ56`t*ms&D?)7_&U0o!?i&g)NUs^ zaZKGlG1EC2Xm?}4i@{Opi=5j~-g&7*U0r@lo!^j8Jn!VZdRX(&c+Hpzns1?B;Qa=N z+R4S~OP%V^wK-lMROa-2=MQKE>xlPzj?)>h2gf}+M?;g2?-1}X;oT&7- z(SJ!Fg8pA-oGE^-f@!<3H?U7%fa-1W0m{CV5g}IbI$_Vo`{`Xr|=upa6Arhhc+aVNO51|+q(dj$Qg)qoV%(@$`hI3TmdT`b)7 z8Ia5Rh!fo94#;b9_YKC=3kT%0UUY)HYX?kiaW@q8Upk%S#8Q^K;{McGTU}&+IU&A1Okab{JhZOq8KvH2+VOc9@>O zLYa1$-VcusqwCPT#3bc!TvQ7CPYToP=Op%@!g>npNnv{3kgnX9bxz{&GC925Fj_xt z^`>)t>Fh5zOs^x;mAfqe2<2|HKQBzL|MJ50dT|81OJe^i%w*LbBg8DV?u`(stmlWt zJV5s`ia7oGVYJ>#%g7I-uPtSP6E32C>LN}@e%Pfbm$PC10L;$^=PMR*JhRle)kb85 z{DyG_&l85xd@)lF4fzt|@)$f9@C@3ir=#TYP`Y}(vQ+JN-r|=o-A8F7Y68ue|E|iA z?z6ZKECGkir0ZYl>iJf>dOVh{9;c<+*ZtBX-BB3NX&rIf*V_HOb~GPL_vZcDT+b)c z)$@sTY204x)7%s(-C-F2$^TmgbYE7J(nWgv4${@*xpceZx(z>9-;eZje*Bz%e~bA7 z%-45h_}$Hz=WzWOM)M`E2UU4ba*D(B^;EH{#|ffXnXi<7SI-}H{9JsEEdLezsTn0) z&w1+kGm8#uL5Ro2j9_i8V z<7~EGMZGQ@lw?!-?if_2?tA_eQpNt(u)liMk0#1>_QS~6B(VY?E~V$(m)iRN*9yCL z0^P4)ANDcqpXj(g>}RBdNMEgp>8S5B_VKR|dn-bSQwFaOn-Qh$8_@2b@T^z)@QU?e z`abCTuufjbS>RjU3L#Fn#}YBZspkOt0s+gz5XA zCES0C)qGlQ*)H7&J9ltB_tW|?eZAGl;WdWQzTW!IHs8;&-6^=Pm^e7p)%gu|zem0> zp16Hl)AdC&-}ei3DWA6v-o^cPFW2K0b+XeBJ1tkN$vf`-W{tzuf9Q zpwcl>9tazUachD&6h>cd8Rt6`M*k}R#^6I?v|s!d_$&JLKavlHJ^LN43yOH(t%&!h z4u$oHJAB)Q_p^$mUe^`zK3WmqA1mU0x+30>E8=~uBPt#AUeO4Ia&T}nk4ttqjbEev zq2YQw3JurelO3+}6CJMCg?hh#NoHKQ-p@-?{_vh1?_;O<^f+wubFf>~z5%X7e0%Z! zBix1Sebtok+uo;gE>`!YCWxUv23cJRSN3F@o(!gzNp~ z5#hQ#N3gpQ;rhBSl-Jv#yiPvI*V_mAdix+>Zyz+*+Z=8lhg%n@xCiYst1j>mbD824 zHU5mw^1GjWO6|q(zFe$1Ta7z@H)=Yy1HU^8{q-ui8wgGVKg9kSna90}aT=VuMf+0Rp zYFz}m-pYq8vd7c8eZ`P)QS7}6=M~<&AaC*B1G(5+1$n1;6=bD%E#$r4$04h{8{odt zy9siKcOqUu>gM#$_2CH$@_W9Mj`KVx12WV%1oCWO4&-{@*^q~P6!LdI3a7|V?kD@n zWU8Oyn&ziiiv1(u@<#tEgr6U{AU9kT1TKY~9H@ev8h8Y9THsU2;=pH+6@gx7go|4O z{UGlQ%!I5A%!Rx+u;UD*Ereo8387f}gj6BSX(4-HTO9Ho3y8kNZo zW%7YC*{e*Nl*xezD%&qrjE5qqOumcQ0C^;WO6+HqhUN$=HxZeFxa`PO$Q_Xs*RDuP z^9PZX=Dm>=PE+LCA+5#q)^|b9g|x)(Pm$G>on^&`5%Z!)WUpBLVIUb~NOIgpcbUvCu zGRH^16(uu)nFvyTlWnX)MAls5yJFtla_}qBwwyQ^C>h%ZaF;U4d$vaozVGcknRUtPW*By&%w z_7@LQeA&zbW+9j+%gRex->>xL<%wZrUQ?c<_*!{lIO*?|uU7O|*sbu455h|X(`0-_ z5$kmz#Z%9E0_I%Ohca_P@;9FKGUh5~9djF)Ci_;@gXF#_QnQ|EV=hqU%mYTpTu$aT z#!6x?vw~^kT9M3$f|RZz)=NREPa@SrHS0vu>p>M>Tg^g{%D0?Z!R7~;MOfRC`&y8~ zB~myx#%eOJV6Flw9s8IE*c_j`5dVaEJV^H0%mQW+Na2*SUd^m!ZUa^QV~t0&L2_Tu zJittf<@7MOfz;0S|ACZlPaNeVvx2Dd0aAE{Y)&NeA~r8)b0V290;xZ&W^*E$uK_8X zZEQ{?^Zg*D!-H!+6)#BUHc0Lh*_=q`Ijj>&FJzradId=Ss=@u>YLLRGFSSzndOGQH zN&?AUA?y2@iJhr`-(QiVSYJ`D_*KPfMeqD=ik;{0SG>Q%6Ho3l<|ir^%+FC=IKNQw ztBP{wYQgOjaB0j~hDhf5{mn(Ljzgn^Nf^BTSUom5WrwjRiYOWJ==>@xqUOUnFY)ukiscty_VU;+z(QGqMNSIc#z^r0?A)C>qV^BGjozT z-(Z@oT0nXa&npXZLGo7({va04B~p3RDt*sfBI)%Yx!Vs?IeWTuc{7VZvR}hIz%1&a z&1*pwE=c7@`WqB3+c&X2k?e_NFH*EWBAF9k5IyE4fhyf>zlQZ%*0+IFP6yar^wiuEINZ}N)c_FiuS9)@RYA2kj!ZzLHYsKb9-y^LXgbsS8~SI74CY`>3nnWn?FLGqWt`cP&Oo7b_vk9mO2Jy@GleiA@R_jqO@o0qX(0aEy@ zSg&L5W6FNozXw#|u|AYJo>|6R4U)TUAhnDAtRDndiY^QBp(mA|M3CH-v0lzx1zu`l zzG8hpQx4#CFcX-G%pB%;W+Ahjxth6+DF$+Q%y?!FvyfTNT*X|?tYdCt?qlv}$_x&l znZQhB4rS&r$1@9=Wz2HsD&}hDHs*e&XONCBftko0%FJPoXBINcnB~k>%+<^~<~HU& z=6>vtAC;ys(Y+{Y+1e_BWK7!z^d+XRglG?zS-#&(L}fvyfTNT+OTn)%e8vex~P4 z?LU#3!z^T$GgmXWF+FFoKV}ZI=xm+edS>=H+Fb#2-?>_^K3~tjL^W?*pv{{u)9Vg# zxlV69vlOK9yqZ}$j&u^e$)y&+5+FjBunz>6fExiYF04q2eh91kY??A9bVHGF6S3D)BAHh+o0!?P?4DW5tlrM< zLCSwYgKjsapbDpv;wvkQe~as#S->o1#_wW#rg&fL^lUD*t0tz{&F+{5%qFJzK-(8E zOPOL1hsUgD)-tpI$^Mw7%xYu)k+v^o)-s!z;$se6@Sv~7bAjOB* zXLWfplR!#$HtPkKrY+{PKrw13k6=$;>? zr->Q=GpCQ43sU$6tgm4mpRd#TW7dLH-?_hN^EFI-l3KfC<~FlE)BcU^nYsUFd#3$6 z+cR^8RN<{*;?veTd}gl2_Dp>0TH7;=a4(1QQwpl~%dBPAvpxMo0NKa8nn|E4XVwdt zrOayP8j#%8vfjiLJ`RtW%`5`ReLXV?-}oYZ4YMe~_RORZwr3WFvOO~?jP034;cU-L zYQ^@c)zMI7fRL88fbygB|Q&ekz@yu*y0kd?Cwl95{;{#VyduBGVxme5LFteFW zPiyz$8O;J_DYKec%WPtbjoN)Yvy@rQtYtPa#U|}O8>D_(z^r~=o7XbqUto940%j?* znklw${LE5jHM5r4#KdQ`Rk_4(+qAoCrl{9?JTseFz$|4py{_GfH#i<<0kf1@&8%fMF-0T$V-_$= znbpi%CO$Wge*falO(3;9@wR3Gvy@qF^!K=*eW2YnF|+ruKV~VjnptbOm;Ev0KhkidQf4)?mf6G$fl4lLz+X9LNh~84?R1yGW4m?e}ujlD#BvI z(!xfET^V*y*aKnDggqD55cbcozTszupC5iv_?6+)!{>zG9DYyum*Ho%8rkZmR?oG1 zrUyn|0VIFYR*<0D5$mPXzhd1vIZ$d!@nB43ECi)@IDYdxU# zX|0P}FKB&F>s76vX#G-a5!E_scvNvzY1Hzls;Gyewno)Qy&knI>cgmCqJ~Bfiyjp{ zHv01D710kzZ;t*T+HMowrgxh&+l*^d+vejo-nN6=UeNaHwv}yb+P>WO{kBbQzik`R zu5G)X?M`nux83}9x3{~m-I{iiv?jMct%`~3FTv@dVJxc!dyAGP1#KBPnE4m~@hbr{kix5LN|lRMnf;n5DY9lq}H za|dtisj=tAUKKk(c3JGo*j2HQ#MZ{{i#-(kTdXI}AJ-}_F0M;lx4441$K!sE>(()~ zV9qa z=ezIh{z>3VL1JYi6&?UQhMf+UwO`iM^A1r}ZAv`-~%?9vnZo`{2yMR}Fq~ z@VkTCXO7CeIP>z%Co?x?)@8nz`FmzaR+p^oth2H%%__=TkQF7Rh>;%ri{<#?c_A?g$ z^m8fx;U`~=z{byFy$bu7ZoJ@oeO^;v#V!TwM>_5;0E969u9S&t2Rsri*eh zTg=DV0&%NYC>D!bL?zB15x0qTVu^T4+$lDQrQ&I<5}tw0Mo}d;!S-30ZWcA-CD_!8 z=fumu3&hm8GRp!X<@=V!Fo-O;zb7UI+|0P|XC;Q0@@Xt0Aux#Ds+0xz|Bdn1ayh}eR~B0L$s(&tUSZuYCs_~3Db|DXDr=RTYCR;c zw${jNtcT?^YptAaJtB*($L00blkx`ZX?dgdj9h5pUs0^Ba*6elTxz`~@3!zyC)O@` zkF{H_us)P4t&imW)+h2ot4Xf54#|hDujN|n8~KR!t$ft_PCjP+AlF+*F8fd+QeoOy#=$nbY{2KZ#NLQMq(|_cVeiL?_T7wT? zfVXYHEaTnC-)Mt z;}9VV!0H@)9T~LFz*DziktG%X!RB#nUe4yu9K2-$cQ4oADQ)m=SEuWXI=poP{o)wB zT>&0Nymx}Z>6(smu7o+2%L>qxgUP?i@5#(fc;$_FI~o43AFj){5TyLIL%mTxvi_;# zKbgMdUOd4CceiXq-GckpAWh(ppfTSB{aw^Q<-^p|fxWukZ^sTl#j`G3+fPJ($Q{)) zwUcqNT3>RBCWZe3%;{^_)SjMRt>d9P&7|*U{n7V@sDr)&_16fF-U>VL$$#r`O#F*7 zv_F&YL)hW_6z-nK&JLv`Y@}`{yPv^ZJJ28BDa0Xg2-^Mk;EP?*M!=6(Aa9^)rw^ds z$$tsVy*J?Ly8E!R1hzqWMS|k%PgYVSkHFTvABcZn%h_VK^&(rz(SAVo+ z=o#GKUfzIzOM(84N2+|Ac4!z}U#1=xKZiaAe;ZJK*Mb)x*5l8>UV6Nt^0*%6rvCOP z>iDa$Lrde#om}sfpPS&W!w2}+39ztU^USNX`)^9|v^mV@?#9;v!3VbCUsb@9`7`0Z z$o@_ICSH?{C$Te3?P@u<_sKnVd<&2dGXM4_t%p_U{&4GAnqB&8CcUcdbFSC=nMmh@ zNY@J;wE2gpYwkw9P@#G+U>R+F;KjS}`lt0RMOZuTd4E>!K5f*qE^V3(*=b$Hd z*70OA7ckFb7BeR>Yvu~^9Q>L79_&BZeQwjw9eF&Vc2^I3YIkpfRPOJCG=6?W{>pKO3N+`yx1zk!sFuo1f4mRIR=8(FOF z*Du%ecFHmB?mKpG`aPwK`eDox?cZ<@%7enC@tOFK$MN-Rq|2Be?xe$i_cYCaqCZpn zrmwmYcf&3DGwHkQcYHM)W|NsF|0cgC-QCe|eu29O(VoSPLOk?|4)6QvnsZqHsH4^| zLcS=zfy~WgwBF3)%$!GcIw&3o;f>sh@gDqF2J#DTz?BH4YwRW=IzvAn>wvD{lpR>- zfRz8fVC*j#tHFt2F1QBq4F`YP0zcq&=!X=JDc7%V)#aIt_-Nf^!ZqQgA^c0>&%|T= z|EK8>F2CS%Gv#@*^834TGvyQ<&yPjAz4Vx*8LW4}ctZ7I;=hr{yISto?_xbV0r@@$ z7bWEGgR#2YOnW_NxAwpG4b6{1D!+lN@pjf9%9+abYUo#$pqYTLzlpCLfX}^+x4ppi z;0ln+cMVA8{S+8Dj5P%K*>~vgpy_Axc^v5Vn~pc(D$TpN9gX7oD*uQ!U*4n{&hAco zU+Z_irx|^VX8g69%dXSho}l@?SBlpW|IFJlwt&<=-v+2Z`BaeklUayIp2 z>etk_ssG^mHsxUI#gzYw&N?5PU&ERj`8D}AWM zd=dt8T6ac)b}in@1aHOoN9&JyOyllKjPvB~A};^pQXP(om%jcH5Bo_kpx=P6jMC!} zjn^sAX}l)>)?d?vTXmjJ$Gmej_akl^zn@0@{osD;OBnyaPrt|b2hzHQ^3!i0#zF9K z6UI2uxHs{pt;O4?FgN}daK0&i>i@=_i9gu=rp4ObZSk7Mf7=|bn{bT1$&bm$*(gu? z@~KH@7U$2T*NgF+(vh-FGr0Ur`!?;swCmu0Vf-1I@_Tr{4)?8bnjg>Aq<%!@`{+%Y z&wsA#ZOZd_`wr>7VUHePO*sdLdpGJ~GTdFAuEUeOE;aM6X%D7+gTpuBcHEAyo+BKi zoANXDVf>r${-^md;jBHR(`~{Jj`u%}$COiUA-+C`eB1@j2LHc?N99lo|2>xDUpK+u zmuX&vx}yG=o~_eu)-|TwP5s`|U)zt)(WH8&@V290E(UL8ZbQ4f3%ZFfXSt52?VUOv z)9%dmSRKlX^3@IXP3^|idvJN)@xNTIraVpgo~)hxr}cGeFMOo~`8XTvJnDDBdc)It zyb3lq`pIbg8J^5taJ<3oB)HwvdX~mD(@sgJ@h;fiVIKd2!wdFj>dVZdYFxp(@eLl| z=3>5BjqqQ%7<(_EX?GWl!1@LHJ|0gxwfpOKNN-S4`!M6ng$J~|B|LxM%=Y_-;Oj03 zuhS~T1vXY|&KR%VKmCp7Yblzyj>WzW++}@H${(oEl z3hVWE5I$Ys&~*&un@IiTkL>vc)|zlf<^5OJ(+|O()>|fD!Mf>>KQ(i?V7&hH5BW0l zgK=lp%}0@cO2^5<-Gz9meHnY2x4(f-*P+KiGmli1>%GksjQdo-u|Mf?q95wvc)Ibn zuxsHC%1B6kkHsg>b#0iO2T5jL;lsZ}Ixu+_(!!k=7be&Hd@z{_X+iVjxWN~I$&HW} z?#hI~WRs8X(EJ0EVhDrDC%$l;H9=bVNK7l3WcVXsG6>SbJ)B6GO!c>h$<>gSh{6x= z^!lS=vKi9CJ)Sl&=^fG*CVe0+(GEY{yMn|U&LMO+Xc(l0J3#GWGC!mPOcp>|q7UA% z^@)C=aWLr*Y2gjhj_{iaY2l7gXULHv0rFgt2zegv9$C2ab1LL0+(EK%2dD?+XwehC z@*pkT59$p$9(S7Po%~ds7vgRczA6A|iHV{g&aZ&9@TG_WkkfDvO5!e22F|ZT{Fb;M zFNqu%{dIR26v<^+#ebV`3zEL;qK8WNc>|X!h9Xl z!aGbC;=B>k5^v%z6~2T3Y2j|sSjZi?t7YL)*UKP3#(gV^yG7%0-h>=jqPHxB>?bEe z=E+Hr7s@G+W8_tkm&mIjFO}Cq=F91jv*iqgFbC4YS0=B=`CLd#%#$}jzA9%y?vQgJ zcgeYs@5!4WKb2*W`(-)gFLFNQuW}*$HbYwCH@OJ%-|{v{uXQ`j9Z0k~YYEPMke2XU zOK~26v_yz?H_k&LE&LPuGRSc29+*t^AUj&?AQP>}A(N~pAiG*mLH4j}Ak(d9Ap2RHAkVR$g*?~V40)dQ0_0fh zMaWC6mk{rzkSHsw4)QW<8|3BIcF1wotB|)@4UmhiHz4n}-h`~Q-iBOe?Sx!zy$gAd z^&VuEwHxw&YY$|N^-svBt&br8VSNJmthEpFIcq=U3)W|lTdXf2U$hQF)>~geZnwUM ze8u_}@>T0F5w-X@y+li0^?5>cf+owXFVJAbLY4?CU%kBwzw%r?Y z7#`!3VmKt~$WDVCVfTX^X%B$B+|GdQI7mwr*n=U*+gXrT*{8vLDx@W@wueGqW9L9# zYo7r*%{~kAI(r!84Er3&VtXXyjrMu)H473w!X5=V#~uxn5=cwTwJ*f^JV;C2WM72y zQbALm8L4Cf`tLHKWIjP1@g$ZTgjWRCMH z*D59D;`pD@1; z5^ccw2f~NYtkD73AH{*N~OYw~))7 z!;tqlKfukskSHtXN63}VQOGLi800GFSJ*xTX^AJD-*EmEB<2O@cbwNiVjOTJRyNN; zTH<-fgYy?4E%B1$#d$5HCAK*(&g&u3W*k4x8z3=LI3YNH3(^uFI$=2fC!{6zI<0X2 zk&>S~kudqniGs-?NVF@b4bH!Xw8VE#JDeYew8T$Ndz>GI#CYz+;{4x`s7JRW&V7)m zN4GQ11CSWE-2|M6Lt^FNCgMB-5-S9^E6!U(VjOT!#d$O&Mshb9vYp!lGREx**}?4% z+gM19-fk*n4>t`m#q9_4o{(r2?f{$*hO|Vcn*o{S4u;7PNK2gNW-Jhx1z@F~Yl}aK0GQ61Tgf zaefD+C6>4s;`~lXODuIS!ueg0Xcg{Qoa28YaK6mF6z9t!(Kg)6aDFc&dXqa2a-};S za+O;M^M@cUvD%%8^EHs@W$q-LuZ2V}bEn|^QAqSM_bQw}28mwgUXAnhkmzOZwK#tg z66+0jI^=Wi447<&L|byNhkU`k0dk8w3v#PF2eQGP3;Bk76I?bzVvXUJLGEz>4{dJ( zA7@qdk3Y{O&`D;JWF9f{>5N|ww z5ny}#qkzZ8F9Dn#{{&*^076p5F9n<*zYK6;{4;>Z$3F|WDE>L{oB#+J6~6*-Y5YpS z&iEGrm&Lz~*yVtjLE>LUcm-h0TN(cv;Hvo7K{*)^5+nW%gx3I~Z^XZe@H#;Bjrg|_ zehpyE>yBTI@OnTCO1%Q_|yc6)#4etW{X~TN}f7b9mz@ImK0Px0!4+8$8;X{DGY`75criP0E zZ*KS~;4KZ80Pbt}1mLX=mjd3_a2eq34W9wLqv5lFe`@#~V50E~z+~fqZ_}8r#l8P<{jJkZNOQLR|C#&yasSi<8^>@8@~tm zy2c*>4mbV?aHR1Dz@3dh1{|I<%cUR*RfWL113*g<2PXXT7_zd758=nRIbK~=XPd2^?SeN(*V0~gg z;1LPG9`jV94sd?r5Wocqe7pc(a&G`UK9K-ilxPB6o|p>Qm1qTAk!S~8nRpf8s>Bh1 zCnu%>u1*{UxF#_ZaBbok?1`-dgp5keLija+kWq;_fa??U0DBVi0XHP@8453xSOl0& zoCp{s76T3^mH>_SzrNkDb{W2h0KGBEpR{s};)|-hO!VduAeI<4w{2(Cub7B4e+2mL0enw*%gh{1xD@l6L{#oxB_Hp5$);?@!(f_`BqNfPYB-4)D*(KL9?K{3GDw$v*); znS2;ZbjGuW9lR!H8(81KiMb2w-p16u^y54S<`P5`d>PH36R0G!^jdrdGgnn%V)+ZF&{p zc}+(EzOHE+;H6DR0bbTL6Y%n;V*o$jGz;)cO>+Rh+%ymH?xy*GziC7^&1(S{G`|{fVRJX&@y$Jei<)}@ zmo#qzT-uxhOf{c|UExy!G0QY>0UT)V13bI=bii|)`vHfVcK~La&jcK8J`1qWd=B87 zn$H7#OYzj z2A`t6M!qGz6o&E)VBccp87Vxy;CnZsy}phMNv+*^j$t>svhk(}2GJpMZz@ zH#Z&L631PphqW~LPcr-~C<*_cfK7h9xxQtIe{xH#rOW?LOCP-RzuR&d;I%EE0ldED zvw+`k`5fSFEmr{E(Q+l=oh@Gk{B_Hh0q<$~D&YUNd=2ooEnf$`zvUZ%zi;^_-~%n+ z27IvPYQTqDt^xd8%XNUywR{io?=3$7^jd!eSl=1|##>JVY-_y%@bK230?ugtxwq0^ z(0Wztss5dv6zqZ~B_;l-ifPZWK9pH1Ve*k=;^$Nhhw|)ljpRJbx zdTo7xv9`|w*0+5QFy8h9z+~Hx09)Duz{A>31DxJ=9pH?%?*Sg$_7&88ZrdLbUeNX@ zz!TaY2JC9P2ykWF4S;LfehT=SwnqUsv^@rRO54u?x3>K^(r#~i0^u{-{sQ=pwr>Ld zTia8B?{51x;CtJi0epYkHvs>?wr2tVz3pni54SxJ_>s12055KP5$7y^+4c{>eQo;z z?`XTW^>n`lhcZt0+uG~k<-V@{@u>s;YuaNi1OB%5`w`yWei*_7?S}&v+OKUL@Za2i zB*JfPpAPu;_8BcZ{7<%DK5d8p`Sz;-ztH}rX=nJiwIAAYhJQzUyd~q`eAwmFGX8Cc zT{SK6W3T!=VEwDUG;NRn+QTxst>8Mu&EMX#kzfMsV))e+kZg{>|Xr=kEjO z9sUF0yu*JGoOk#Sf%6Xk5pdq&{~4Tj_>Y704*yAT-sS%joOj`)WZi)EGtL4$6pr9` z`SBT>02^nV1DKp~ns<*sW5%lij|S&G{%mmGJ^pdvyvJVv&U^gh!FjKLGC1$` z*MRe0|25#e*Iy6Ld;JaIyw~3d&U^h+zTfKjHrm_@D5vn(-dMZ-M^_ z|2yD+!vF4!_W@oD{wMwKgY!xMhv0nD|1mh9^nU`*C;gv+^GW|ka6ak(5}Z%@|2v}( z@b?^kaK=RlKQvk|`+uA9QNZVr&(r=3$md1>M3s&ZgKta5lwmoB1BVJHXi#yAzx( zvEL)MCH4SfTVfB*Jj8E_J%ZSl*q=G}@tIRVc@p`oj6Hbts{tQ6x*PD%N52Q~@uPbI zpFDb#cN}(Q&c->NcjCOwML1h?x%U-F`s=(KAjN-=(=mVbUi1$2r{bK-ESyW}^f&qE z;dIGo{r~c>!6}kk{onYH_^`Oe8gWwM$k?pd&e&LNZ|v={_r^XHyE67QoS?Wdc3bTJ z*h8_u#9oNi)g|j*Rd;mV{JN9sR@JSqJFTw2?wqHyU=eD2FzN~#m`y1Ln*nU;}%)^d5Z1G_$4_k8h`oph2{HDVnJUn*9 zyd%y%A~<6A5iLhfJ974si;i4&z%d@a^SjYk4*EXpFjPQ>ED@t z)AV0We_;CZqt+eOF{3!+7c*LB&X`%8xo75OGq0HWotgK~oO1NpN5Adp4<3E#(RUtw z|Iz+2^Nv}3%&KF0j_E&U&oLi7=G({YJ7(drOOM@r?7NQr__6e)Y={lM%OXCE@Bd(NqIUO(q^bEePjnEUFvnYsD7Z=3txxu2i= zlexFfT{rKPdE4imJMW%(|D1Qoachs;c--rb8#(Tx1xGBHw_x9byBGX*LG!}n7oM~5f`uPh_+JaZxA4w|vyVUS_`8mO;rP{yPFeJ^ zMPFWY+oDGn{dLiT6TWuB_fI(X#Dyom?!@a(yzj(^Pki#kc*hYPCv~jqct^(vI-cv8 zvbc5e^u+^<&s&^dJihq-i?3RI?cyIVes1w$C(S(R_>;~$>BWVr^TE!m%YVE4(dADq-@iQBby(N2T_<)e z@9OT_+I2?PP*<^QPuDxUKHT;3uFJc=-gR}?4PCc&-P848*Hc|Dc1>Av*oqk|7OYsl zV(p64R-C(Hc*X7&?^$u-ichY%e8qpQxPHYgEAC$L@QN2!)URw`IeX=zm7OcsuH3Y8 z+sgA-zGdZmS6;mGKURKab@8f4R~>TltdqB$eAda0t6Nte zxq8{^jjMO8K4OGeededHEY*wTJyFwpIURpnw!=ha{Ck3avt_KgFAX)0l#Ub_r_9`Y|rf4Abcxe(W<*M9yTirwTc^yToA zl7DVKSFWA^eod#pRFjXtkwV|Z$w$mz-nVh;@jL!u-qrrAyzlzcy=(Bh7QgHK`Iw95 zd*AaHdEdwH2mT4(5Apkvf1>wezr(x1Kgs(Een0h>ct7)3ct7{ocsKfMyOF!k^ z)P>$H`0evA@@~cNHvDeK?+*W?*d6_-cPD;#`Tybl8o#^oyT|`e?>G4UuYV=x zf-ic%#qU1<8<-KU@_y%k6ML!O#7^op-UImk5x)oh?|Xm3?;-pi#_tjTC*Gs@{n@|U zdknwF@q5DmEu{Z%y}$Us^Ztt8Q~r~X=r|RK^L~HB?^*nw!|!>V{d)mt|6atozrXwK z{y*^hCw}|!^I}j<@QdMBhhKf{Raj=d%0CppDfq=>NBRx1X?|mDiJyqA@RRs8#ZL8` zV*~zF{90l={MOi+ej9%6_#GBI7iaHY=O2#W5wSu4$k^-sX|c3F9lxVuL;j3d)}I** z{G;(Z2ESutd;M8BuQxmP7Jp9c9sXSW=HYi->=J)I&eJWxZ(-~k{_*%N!Vlk|@=wIC z1HZ-iorK>K{FdU^i68cK{pI*|;kP1omA?|_=T^m@_fL-P_gBZ}VtGTo?#CaK{!;J# z5h40_sQ0v@9qQetXhm;7JZ9+Mm~QCgjKD**tGv>?>zdY4D+o zNxASUjp^1cn9!IBl}xB?Lc2}qjVAO~6MDM|z1M_3U_$?HLLWAvkHm&nOKW^2_QWMp zzl%-m$4uzsCiF>8L7bm5X+NdXws@b7U3s?T@;@fUcVqW{L1@1;w3|(6p9$S&LXVly z33a-K22AJ-6FRp}-etXaZrzRxq>SI1*!xZB_bOEHJ*ZN^^RQ08{f7+gAw|Qv29x&i zdR>DfO=!9b)ngxB_olIW{Z{{2FKy7`{mFzLR-tO6brtCiJWcJ#RuUn$SN? z=#ZpNJH><&Ce&m?3stDzyS-`O4r-x#ue({NO_|UZ6FS|5`b{WpLbsaGT^yp(cvthq zN=DpmLccM5_nA;;sxJ4ksk*JcsA%=xw@vIdCiDXny1|70U_yT~p+`;VF%_!!KGPzl z)q9!t!7HVYXWDg73{D;&<9Ou{}D7&=-)BZb?hb+N}13(CUhQ$ zQvO(d0p1k_cvXB9;p_Yhu%~|Nl>PpHOsR|QgZXaXlw|Tt4UPC+9XoZ(b@;tMc46ZE zu`BTV8h&H-?~nZ@v9|7u$&~-aa{Vh!o)c>mK8;pTeGB65K4c$g`%vyTr|tKDHmxpJu75glOZ%KDx3oWp zzkkK=1^iO}E$x5D-@hfgXD&wE68u)+x8HweX5W;Pj!yZjk6w@*tKaX>oK+Wl&8+?Y z(5yLA!dbU9eG0$-oRx|nH@hx&;_S`Mx3q7^uRnf1@bhP%iNDwRzn;C{e|+}Uv1br| zW;XJglk(qy-z9S{ivIz>XXaez&z-y9Upco9ZIJRWOk5G4JGVc6;oLb>E}Z-8=1b=8 zL!Q^f$Kbg#HZSGxp4T70W8QxM;dyhWJcIBUe!J&g5nplKr(1T<8=5*+KQwjsyrzaX z%&&|6`~3a>SLU}jT$tGJ|7QM{x(gGt8pi6+L|#{;jraRc&Hn?Jw`IW<@%{z<_+1e{ z3xChT-$DEx#9zvLY~H6^wk)_P{)^);Xk54`P{S^T{nf9W??|Hxr)U3~8J3lnGKw{iL{?WatCV#(Rl_f0t$zl{iQ zoSy7V`ImRDPF~*m&m#_5_Rk|O?>u|@`emnpzB>8Y6I1@BCmxM-_ciUC@^I7cRS!44 z7e?E$`p)JVCtv5!IQjPGscZV4nfSdHzq9Z=2fuUiI}g9t;Wvoi>+yRle2U(VG;jBA^De;O zcYA+7gooGQV1GGX&SknwrSwFqkSh;Nj0OF3phC4obu6Ob}Z3-qBonb1_Xh zm2w%$wYxMjJ{lCt4%@oS;NXT_IF?UO^yJfFDD|Kkb?O>zD;39rQh8!S5N1lbF%-_} zCB8C!ZR#@4tEUvC%R#CTmP_Lqs(Cn2+>+iEoRJH2L-}Cc$l&1iU^plR1w2VlIxOdd zo?&J6> zG)#FQT^b3>y?e(>K^USwmZKw+(T&e3`irHqjjep>CCo!5FXfO;EjZqkt_fu##L7%M zC6kKxv8*O_RZXf8sWUC5=kF=z^FfCDn!IqP@~h>Lt!1anuWFi;&LmM)b(O3t>uL(% z02+A1L?Jy&y>E0VC~d_nrCGQ`b3|orJB3Qs;n2qXc({{aPfd1VqH;L8cI`PT6?PXU=-q5A6-Rdz z!rVw9$aaSzdRcyg3aFXC5Rv`TF7p^0$MgA$N8!k-M-eJLicO4!8;ThgsQgqMV_#v- zjA{})SLhaA#-W~kG30(IXk}%DO5G3E+_NEFPAdXGAEr@sx$bOwj7EB3BKvn1$Mf0l z-9>3f~*!cNREOx1o>bDvtyJh z&)8RpQd5Q9#SHX`qD$`^DyMS=2=Bc-G~8!}@=+>BTAQB&$^&}O8+FyxxGv|)G?_-z zmmnn-h5KDO7*(ju>8AF@ExElpo=0`7phlR@LuBAg{5mn_^ns#6j7&mG$mX7OW@n%z zF27BkA>_O$AjDTLgRO5U3`)C68E{{4ag?OCOWK~^qtJe|UO1c!vg=u1ASY2bI(mwu zW5oigNF5t;tfQn$6RJ~mq%5fiHSaG&LkmVGkZ4S2!;RQK4zW%zld9TVpcZwjQAL$5 z){_s?C09+L=PN;7LVrZ(43(BNP*jsDziP>Mb2eYhplkP+1K_&oSG_Gj3Oc}VaYt{<}y}P+o}?+;2cFVb_YhrCk{XS*vupcRtz zxMsah2x_LqYJV`AhRDr?psRP@H$?A*`0$4ChnAK>R>DZR70QAjr=-K35=v3yf^~DQ zuq((aMDZ%D7q$TEe+o@G6-PoH8>JGj?IIh3q4AM3a={+(Bk%4EP1`Uuq-k+50b&Rn zMu4%kZpGl>9=z!#URt!JC0WnZ`{gKAb35@WxqsA~yD`@E}w6QjlPkcR$AudhX20xC<*rMmaB#9FGQ3|<39M?NSQ3uHtJ3Q)w51f!kX zXj?i*sFrrJ$Ob{WJa<*Z+M#NqqNIsJW@o8bfU25}L@2=$p>ZdrM^T-0sqUmp(G6YA z2_sf78NrSYV+S<1Rj27s2pzOPDbAAy5jbdnQjD1I5vtW|I(4tnoW$sKA7Hy-D}%V8 zegG_|{wm>okatg6)4T7K_elk)7V7j^X_Y0C8mnE)^jJlR2d7Zbn-Gw$jX$gmF4IF% zBDT{XiaI+u3#bgf*rq;uJ_?o~@yt?cdU?OL_8 zx2LmrdG88PmUMUNT6Dc+xrTKGvqpQ=3dv`sYM#_e-EJ#A=oY&NL7;}+t{D(e?I#hi z?yRIfNuBJaMmm_b6tm;7sd{U+m2$fwxXpT=7mgdSz|CQm>=iKGbbGrB#XY>3?DmGR zRNhg_b$i93H*|Y>OcCA8wB9nU*G%h)X+1No_crx-)TcM?NNw;o^lt3lv3X!{V`_8n z;MVRfy@t}=-`~4s{pPcTN(p-VHgZBX57O#+$M%%RiLk@hkAEoiPv8oFJ%H=Q9<`(dRE&PiqsaHg0f65k_I&< zo610qI4K*Vw?-1KR+N4QX0_po)G!rddR!RgG4v>TBvPk=(gdQRhma{IOYJeL17I8^ zs%JGaMz;s&kHbQw(s)pxbkOGHL7~!A=pg+;rdWVnoY1tfQf|~i_e%L*PH(Va!-7hd z#j4UQRb6DBMNux<&P^^=g~7{dv&PcE=qQyi8fJ>6d~V1qmio)%L))Nilh+L*;PN)ec$Twq4Zjl466-js$MQsff2NGD%?>Z5<#+eb%&UY zr60?9k&40Kfo``YT}WeXHLw%=JlRwh!YV&Fn3GkWA&zMa6&T78_4uO(4+S~a3?`0) z)q>s{U?JE`e^62hyA$gt5T-h!S!j{s^+EsO0BMW|dE5?X9k50%uTOQXo5_rf)0qnuwFo-Xs|dJgniUV|!bRu%1D>sjVh8+%%TXW(P^9)p#iw zE$$8?q*GvVlQo)V>MOWOqyU#fnWApI0jtxfj4R2Kc_o!*`pnKssu)fysVOPHk~~&X zz6b`%0Hi zvlxj=EKFD%L7WpdlQp!jQKVCvxx%o4rFN_OdGE@T-iYNfv>&yf<)ODaSPCn`;T-n4 zyi};)kEYNI*o-Fa&hP}7^{9OfQj%#=H)o31pOlT#5|mvFIqxZ!c7^EOwEdLz)O3n2 zp$PKYX`RRMN`cU*Wj7qylg02xE0(l`&w7~Q;NF16JXVVtOk7x=Wd~_yAyzCTK~dd1 zO6;Sl&+>3xMEysKRJaL7Zc2;B!Asl@g%HT3Z2B)DV^C4}K1?<<$G$=$irSbHn^{Il zJ1FNtzQZ-rSl&t1x}qR?HIpwa!jCuHKRz}lHKiC)Db(;(NP*Q1-6^&}u>EV=cRLG7 z=?0j*X+O&J0E3HUBg>c}k@Q#Grg3>ygpmu?8=Xsxc)HuuLu$ib&AHoA3g}%pHiud> zz00i{(@ilpK9tiXLuWwv4D27OVa|JrUN{kgvZDZ>8g0L*2Ad4a?89{|}QITB|rA_OBLQ$Er3a>E}%eq~I zSjJ^`p(?6oMh;g;iIl0P_vN!>RpkxYs{HhZKy@-`*=n<(Iu62k?*z4fbrh{htEp%O zEIIPfdaC2t#8Fi-o-@h4t9CTkpmr3Rh`S%!v$`-*W~)lu9+byRlnmy`s>qE&IkU5x zY**i2l5Dpku&mg5CS7;~@eL6s0D@aLahUoZB4i4)U~hQk@0FR~jtU5u|!l zQ?U*i&h4$HW6^YwsA_(UXMRf)HKK|E^hM~S80#Z7;`O$gmVXE4)Ux|PIiV6rtkhnu z$W~X#E;6g*)TUB(gjQ{y;W)-QC~-U8MJoGXQ}K*D|uDhq2G2R6_?s;D(E^FY~`Fq@-j zp}-3>i>1j-#dL0D>_aj_GL@L+Az2k-M`~^ikM^!95>Jv3UcwWoLjT5Ar=wIJSjlHT zYRc0n0gR5+T{#SsJO3RJlO!wODj2en5>_%ca&N>oAZ%T{HJHjm8VG?hmF~t(p@JlM zbr8l3UWRFBaHZc@(%^S)IHa9mu2FfQ3Kqe_O_9f-0%2`$nKlHOd>U_7QF;sEcqx!o zq$0s{Q9K|H=4eQc4KL}9=%Le;O1W&Ha@K1^ns3C1j8~i<4@mNy+od^kE`lD%8{XuI zu5)5NbPHxi7=Ku%q$^pl!(B-d#kL{~TJw4tl^-K$N=*MCm7~SUdPpS)Qv@&ZVo62P z8<&QLN*pPVRH`AU$~Kn@N+!xco0h5@Y%`Aajtm7$35p^Bz@q2daY zE@W|pEP{+JBAi;fTlxs{17jpVi-XT12w5bWpQR%|l~-s&M%`2~)ECAyn;2(|w2o9n z*(KF{rlKI!$oEA*ilSylr6Z1s=-P&b9}F%cxeW5!FzXF)QKawFm{;}*KJj5As8Len z5+Ub4#H>b1&dil}%A{Z;r6ml`Qz8kT$@13XGc6`YNy(EZAXCodB&k&sR9ljtBWBqS z{%bRXk5oy#8MtN8A$cuq8FHpECMChG-3N77UQ!)uDufA&r$iQ!W^KcQ)ncfDMP$@l z94}53yS`yd+>CY5_?X49tkfHoT#`~MqeSafEW3mbjuK#;+8sEgROleoNwC_?>|(2` zvt711Hyo5FAu6h9%*a2BMt>1Ib7%h``!46BSf&_tX3>_F&{wiU<5X_MPBiD0$3T{T%6Ju7NR zOSZmYOXf3B79AolZi`ZL!K@YJ9UA%1SPmG1(s_&KqbPeP+gQquTfmYaO)E)KsAb88 zHk=X_#uE5_R}xdo>EE*bU*D~4EZh7rF<4}iJ`-k1cm|QDmL!U{#g%bjpxCX>*F~a2 zC;v1Z0JO0sr*qKijmMgp)gCWa<26~b z*$^PRupy1aWo*zHsxHtFO1eyC4E0qeA!frCM84S_tSwllpvy{PW*t(VG)=}kD zOFIzA^OdDl1<81f<|FF7TJ7qlWb;A@dFYm?Bg2}pJC!AtTaqX9zA5HxL5tvQlB(zj_4UL!O<3G6&ToL4ZJA_Hy)15 z@T`HAAlVjF>10&2>I)M`Abg9SdzbKE<(UAe#)TYC%xaT2+uT z+zNjSlbJzM;ee)#eG`J4x2JW^wrbS%GE|!a0nAz3u)xM@MY;N^{gB?h?D*$FRAu|e zhaeQtY;1hd7^+LI?)~ZEK&{=?HZ7cEh(?t~BU0tNM|iB7_p^f*ZzK`OTvtJ*WNLZm zZNYA@4r4u8#1SxF_rdK*{*q2W2TVOJN73-IhTUhUtndJ5;4A^BAeo-u9T+_I+AuFdaW6!tV%n_(s01WB3M;2!2kG98 zSID_waEqq3H77?rxbdNFYqX#P{7`CZN7Q?bz`a!O`RLR-iiVcm5rT7+VRX)sKpPa< zX-|>BaS0-a50H@4Gi{@*hvsd2o|u_HwZh&xCP#MZN8j89=~T7^C1)H8jWl5vVFLCo z<3bo!f7J#(YnY}OR=OAyfuZ)Y#1G4@9bTk5;WDXZ9bQdG%BB&?+tE#ZLuZ33Iv9F^ zJ&lc%5z<+?2048KJ4z-I8{tEfu}5NrC~X-bg>L4mReH#JPPQK)!Kg1Q)1`H@bh8APevK-98 zT1`zS-X2&zbB8{oh_#K-)p#@%No&wtXo4sJB0xlXcRpX-!#gqX4Dm*3ONIiHSiEbM zuBWyJ#OE2tQ9246rBNcgYmrr)oRzbi;nHb!L}E?TvN;~E;<2OBi!!YcGDVC8aMzqb zC0UU;ozioCIY2{<0}`oSqnL!wY__^hDy`~P$I!v`i6}W79~ogM4NlG*031qdJ1t|b z36Tko6^U`xI|qtdzgEdauNRh`H0yD26YWprB|NMHAj;cemYOYZVk%nM(6?YJg1Zyr z)NU?5>cmm*)Wc0eRsVpG3ox~;qeZ#Xuf!+=%!E4cDCBSmM`OLi!=!ZW7DA0KMOHD} zqr6e}w`VJJP^yTdxz=G-+Q{Z2JC4CyOa3094BbN9k9d*JRis9-n2gJD*xW4*6F0e@ zSVC`slrf7J&=eNi8|J7XEdfoUY8s_eds;42vLzv*MaVhdVtKMEaQ*4UQ7>i$y`TT? zRezy~rbn3q<14n^3mncA^W&ou#GVK%#QJ608%C%(F$y^Wm9Ycjo)Ky=gA{rHgz2cQ zVODN>hTp|UXgNrC_{beP%mafbrgW&xR1ajd9s`iWg)XDvb<(^|T2vQyycS|DVn4p3!9+@h^K z(7dpI3gwON$%V9W1PWKqxXy@q#G*NJT32p0bWl+T<&m&H@o1rd^+Z4XP%+h2E9??M z{36Z;mr*U@5_DNQT+WH1)Cx6)Ha7@AkAtIqO`LYKAcq1&+=eSrBp;|laFiAA3(blp zpG0EGD1m;6R(=9VXC0(MA==OlB?^Pbgr)u=Cm}u>$=r4vAnln0)DM;_LxRNE-9pAG zExasc2q+2<2M+TK#a$?jkY47V<-*|!d$3D{n01oo6q_8QvL?8;wS|xV9e=ktTWDY zD~DLzbBN2(I}l7Ed1H1bn8K%YqNH3j2^-o>ezc%w#Ml)C6FUNjWwB{e=rs}(>>5R( zRtc4~=+LzLSZjZi8Qk4XCP>S2ke*ljTXnq=^Pv! z(wJycoOOo%kM(JJCXx5Ey&r}8Lj;GPP9aKxd#$-n1?*zTGZi;eKU32B9vTzR_v(yG z+mn7I8ykJY%wRSE*jPn+yBHVn_~U`%K?Sw&RTNsov4!3gV)kyClI1OP$OXorEa>25 z?A;h~9hJkbm*u#iSO@JpbaRFHB~K~_z4yft-^eTu12Qb;sG zbQ=;C#c{(}m~ntC0Xh#^v%y=9M6cf;^ zFYRojc8pOYi@ztMcuWU_Zvq@aIRdNm)ASKhwryGrMWAUc4p!P_>JBYwYf-hmCG9e~ z>5aWUR@jwEkdz0wbO?zm$!k?vrwTD6<~7TK84!~g>||VFygTtXiIPRisEuaR0zGoJ z*rWHP!<>QSMP&389ivVn^PwZMxaln_F<3($aK0oZcmuF@G(D3NODe&L2q}fhULxG1 z`0^ylaW8M0;6_9;<1$G$NKjSAXnt07^_NPK%`0Yz*jOAoR6|@E1zlDpllhL54B@6k z$ulcbj;TB!K?A{xoN<(^G-XDqSgj^AL95A{nG6Nc=?aos^c9m*8FCrVh*6irFb|RD z6>wKzit@arqp5iB=)8b^1~_tQnKn?Oc8G! z2o$Upa0mpeOD1EIh6cw$+Crh-3WvTvz@ms6Ng1L%I^2cTGWHo@su(GxA?cK135#af z9t-6jbZ$*lT~d<(hrvubJLS7^CX60x!fXr8U|bqXR_VF8)M})}8ZVubhqoc_ z+zEs3uzLWTspMkf>0L+kj4|bQLVC134bB@W9a*olkzxcr0v7r#%`(tT*ojlwx594n z5$fiSAklnE6Yps~w0^OZN-8XNi3OakrEU1OLX5Es(!BC!d zH`V~eNtuzn=bJZ>jt(}mh?ao%t~l7)XXPKeW`HCMpRA^(8EM6-h?7&rFsiv7 z*mHId*!SIrB{nZF{MN4BnN3W?Z zxvH<*C^GIi{oO|NJDX0H3SC9*Bw3o?3b7Pz3>?6{tWNDx5N>qth`XV(kK06O64ELx zVUuWgmOzchQ;a2v#IiWf+ha4P?Bv4l)iNLtgO~tB%qZsIN<1}eDdOgU$q2)%&!O}A zGRwvTQ2DofS{)1e5u);&@%4kp1^8sh3wJ{f0I;lb(MVSceRJsI08N^P9HXp8e1 zJd3hhp+(g?QEb1KOdZ+YU25r7%9V|xBxn!XXoZ`m5n(okK5=H_wm>!7iGG8#C+cEi zCC4ouvRt>g?pfP$)smA;L=R@iahJL=pB{0T*yTcBaBH*7IV{=^jH%MthMj0y>A>ZI z-W(Lf^j;1*@#xU1K^>w#PG?J$+Cn!%2eVY&JuuT{aYWHZK#o`hb4h_tRy!n}kWLkp zaw9vPsOYIWCzs9rylNx8+fq?|rTAMKvGK~$lE6l*085a`H^plMOJ%_YQR&=-OcNUR zF0jF5*`&YHX(mgP2BKRzEKSW)14TaBWa*N=f@qj&SyIUxrBS~%rvfdj7AU0W<5LYb zLJKWRfly74vLLfGyWGm{xv1&`ch~9*W_5U&Nh1zZBkH5c}@tXm-SvB-Is{9av;lm zmW}j^6^h9aYe`8%xxy7z5FGQ9z$UD%h1uNTuhNl zL#HutqQSA=DX3bZdgh&ItDodTF=~U{6c{ByFCz_5VyPBbM+kxqbP3SP{^dZR>i4f_K(w< z$<3BVKY|lO269Tt5IZS5)z0TH1`%S>2rRjdx`IBXhd5=zyG>3Mb{RQ&}P#O_62 zq`zb1jl-{n{Rnp;<#pt5q& z7e0u;Z+O_Nx>9La+5brQf!%;MhgDFl64nq&3q(~W3KJgZUNCf<(sIMhTcMZ>{rudz+rT*cXLT$f!2kW`Vzrf!$U4<^c--TC#way zhgZZ_QY{cY4J`eHiCodOI{N7I=$DMsDR=m$$iX$PZa#WP!#WGFV zdEla`Xm|wODZA;4Mk)m~6+$zrkh)JzVQlbXUbuSWa0aE?LR$p*YcyQktIzkh(K3U* z^$r(?*W4Ta==*^elY^8AwMQR1gUG*LPB56uzI$wIoHVfjKR9}4wNg&&# zlg{lxgAVh7Q}0O)IhABm4^dGpUYH$llP|hfvPl*H5^cyD7d<{LHfaK+FcpTKN>6(b zco@V5I6hO1_8Z3B15XIqX&_153-1I`@98_3aBw2GSN==6u_>H=3M8b~WP%LSJ#1WP z|DGHLNwZQxIc%fpnSioY`|LQZq(lAg{=4KvR|P1u=y-`dQ#sded~TFK-KV=L+f&Gz zpf`l%+#~0~WU31Xc(Yj?F&RhqXAeh4=(vEevr9CzM;K9=Kn~Fk%8dbL5+)q47EJ~p z(h;(`O*Jd2H4^jdWs?+6vcn-`@Z%7&C5p`$S3^-YRP-hY6CFmQ=`jDrlk#73a_0cP zsil%_4hka(Qd_7X&KDF5WN_eqP!2iBw(}4=fkaG5?8)%HE6@rDwGARFk)fdO%szEvyr^I9Rq2gKW*H=fPl1Rz6km^YL846QT4(y@5^pXU{+l0d) zj`B6D%7+5E=5XCH6#P83VTE2GMC_c42!O~C3ZKQTpy{NM{UL{)7ijqjp=^U+4E1B) z8o;^bU0R_~=3Zz_dnY=8NFW3Qy=S_-lcfmBbe=jmd6j6_R&6Q7j3x0o6Q%gY%|7 zx>_EmZ+Tl#-A<>L!O)_ix*>LJP^PVDjB<9J1_cLYaQW~kLKwz6DEaaG;8s;GUOaWSbA5r=4&#M>i8ZO;+(JE)kLGAD-u;HGs>V<`B^A5dWi-EbzG`3U99f) z)7}eiwCOz`M-hHJ%dX!H@JC4oQdIAucOZlvw5{|zBxS9^@5pU#BpRU zqOw$XU>d(W4xxW$F<|)t)yt$ggCEnyjTVh=nniqSm?jM`Cx7%t5&9LAH_3vsuf&+H z45maZu=+*;({5f$gqquPLghtzXHufOa1LC8%Mt^Dkpuapv=m=cq z5R?ePtiV!#aDB1JnA}_iCpwRh?}W52<_78I?+^5ck~3V#C`cVb1;>SAp96;~s5{VS zQgHtkT?-@%sb~SXXNtVwN>E0*s-ib20%aQ^WWdMEWnzcn28RJPt7H)^_CUgs_lljS zrYhFvl|C>0n=#@7sU1zOa>1#Uk+Skp?7)F| z)PS4(mKZ$IC8`WyV2^GaRCYh!rTy&&z91R(k~(4yZi5r^zh5Ev=Z56Nk|2 zdSt6jqy2^SShy1o*i@68tqu^jLD-Bi@Pc%KW=|a)DDt&G@KzwI36BH? zPC5Xkw;&gMYE?u?GGutCPzal|W#*+9%1ajPJ}UF9LHW@Q#tupb6Z5S>GqlE`EGWMX zMRLk#37~>F@~T2yp1c4>IkgC02pdyjv<8bBmnZ~z3d1O$*v7nGpj!??;o-Fc)TE>k{4hgFYSctHjor0NAV zZboyM&^VF%jzK9lSKD$Q zaw4g|l{8UytrqLBtH#h1AT|u-;=qBT!z4y{hd{GqPZ6KU3CXFU4|^cw^XV|KS=GD+ zC&IL=L*q8xPF`69#m&KRxiX4qxcY$@oG7UjslE5NcV93q~Px{piZTZ!nbjnX+B zZi+%P@QS25mc7NWCWUZ`i_N|j79wA`0*OTyH&b)_gPNRJTpZiwC~k3>RMhd+(FB#N_A?HVy=L^Ol1sV-HtRQrn`NV9avR`MeMMpt>EH&fn>vsyL*KI_yg?N-tZXkkb(yhk)vu zUh0q|FRT^=wJ!I<10{0kd^nQ49B9A6p`(ycePzU<;;|r&$`fc3_Ws7nC|iH-I{0{( zc_76NKP-nRnm-?6bf~6(A54~5{{^*Q9l7+`$&I&D931{N4yN|+97@L4c~TXr*lD6K zXvys=)FCDz!=edZNs-jn(Of1`Y;_`f@zHGLx<`5rjB)M$PkWVg!=AxitC=AVt0S1Q zM#jshPr*a`Al*>iipGM8ZZbjsR2%d%h4EU|V5;}(NLjxqmtmVGWB50zt3LEM2%z1u zsZA9Vxr4-sv&l#)b0XMajfq38Pby-OjCPS6etH)D1tFG~27&hqMx#NIlvQs-pp>c< zUMAC7bQ4J%f7mNhpC*zPll6e1Da#^UX|#rj)5<1xOeYm(MxFPxMq>Ilr4i6Ul&-|C zOI7>Ye8-6~Dtj1R$c8^CVTp=WWLh=3!kA$h^i$Y-GHskv!_`#;=1NV{buE)D3hcCM zW6&e_%8HXG1shR0+g8Q!D?`7tv!`W=%odhRUBi3y2Z|zC@K=sYV7nGl1E@6| z0KxJZmn{{o7}nE~V^Ff9UmKJx#j-`*T9tT(xeOAm!aaH&?2BVBqfF~3df;@9VxV*H zk=;uctO4||;i9Xrx?~=p%%C+_@Jd@Um5hcQ5N%BQDp(+$OjsRTci1Gz+l@x+Fxg4_ zFd7*VOo`}EOwnsYuGi=g-BXL8k${Y)Heg?YzrM<-(~lYFNnVmEt%Q*rWps8>Dtcvp zAf*r*brq(2dd>(AMT>MMd>02Fgh71etvH%yZX!{cD8a4A2HY^lNZn%eZ~(8?{VJp(K^EYnkQP;~XDCLkIruPkh7`52I-b%FZ5$8xFc3#!!TB1dmsHCOv#F$bH&u|n)zq4u81p)Ha42@8! zBEMV;Z-L`}87fv{U5X#IyPOw9-(cc^UjcH z{P}guikvM%8SyMQr0T`D?`b3hIj_Ui_&S^?j{=S03K4u37w6E>(P%rv@hYLwQ4w1~ zN;%vWoV-)u&{DnF0pKsqp&<3VB!21JbD)IsXOkZLqzX}uDsUMJv=xiUA^Ag%5dBOk z3-Jn)Dzbt~(@zD7XPF9`oNdq-yR$2k`Wz0?j5$@)oIX?)r#Ch=FFL2yw>44S>%sy@ z)M$Pr6-@QgN%<^YXG^!gc)TMIWe002L*t1b``j`Nc~eGliz!4>(#XJul8T`fh6;+L zRLF*08h&HgM9aWogiFlJAAOkBE0$p>w0aF>27TAQM5-(MG}`m&q7XPZ1S_ueW^NHK z)Mt=1FMp_cU_8UVaEYk2lE*xP8kgU=xjVQYksBiSw^|Y&)_ng%q35Tt_%~ZRFTRi z5}E3ix1q^|ZBSWO8B{&J!K=Q;V!br9lF2n-9~&GWF$qz$bRCD5(GN>g{V)RC8H<7^RVKBXoS;Z_^A~=4^r=oyyrL+Xpsy(&rx7u#D{`olL#3 z>IiF7Ceu{5ngIo7_y|vR6cn{;qSlS7W2Dz>i&A9`*(O_^2o|DhVz%n}(yDpr6_e5g zDJPe4u$YfhUs-mIlPKvY?gm_cKQV|rUC8?r1FQ+1A1a-&s zOnKE{QZZm6hEVaPHq%KlT@xJ^DWtJcHil?SzaM&BO~W9BM0P1# zlO6lKCaotOiY@k zZ>IV zDaA($3}F%i-*rB#crP7tOyLxq=QlaRJix|ILvUWJp$!E))A+uZj3hRudG`Cyg45E4 zZm73CRp@D$VMC;3g-xB)g+CaR=p#D$VTF;oOa)=Cu?QzLxl787{23762g+TBuEFKK z8Whn~lEJAgi@?dlAmol_5U!Hh)iY%D2>X;SRSmuxkti?vCQUM`iN2Xex3`U?gFV$$ zbGK5hDCNvjD~gAARRsJ+Oo3u7GAP803Cksn8;Suw@@BVtWaTXisbLlEUGK}oLz~v~ z^hpR@E1RaxD8p&CjcP@z<}}P%S;iZ@(ty;v*G8dPwQMoOG=Cily@iyU9(Xe00FzwR z&Im>;1Qb~!5#x*kOWbXuGbQ-If=&9Fxrj%4xkU>YH6zT3hsJbH`Yk0R`D8It3N1!< zSBr%vjsCzFr9YTGQ_UgpT=^GmOQ5^!d1>-R%l98&e!9sBIK11cE9dz$k*~P8i04Md z96=0c_J2n(cudp1|9YmR)L>{^;p^wl-GY4-rXCzcG?+Tn% ziaTPQ3dU;CZE!?DU$SlE zt>iKCg|@n&81rHDirnODqR5Ce`8{d609k$0-sXt9R#!sh$D)f)YKd$!<=E8PbCeV! zOReet6=h+?tZv z7K8^0Ue3|7=(edK+rlmDh};v5eAsdk_Q8N7QkZQN`0x%q%7wy8!+O3lMKa-l_$QWE4wGk;&o}9FR)O_1euJy`^-k?bd z4?>hkoAkJ%4s#Ue5bA(w`bzNuCDwj=T=Pbdgg~T!1$)ghwa?Z9LTbsU|!>0lvnbKJ!DBU%|uD`WL?c`8_Z^1 z%@u8U;xyBiTlFYgbvC+r`1Mss+qzW8Wt?t+?T>V+7T|KvVQ9(l~L`NmGqmA+9MA!A)wvj^O%4XJZ`&l@aazElu-MD~{rDHBC86wLd|cEdCUR})I9 z^c&iK(;1<8=qU&#waY=N7`eZ$f~dU*95VJ3>ACesQ7JbXBQDOSU?&OJ5!PhV;%ptL zP&u&T5V1HJbx zNH^@B%C~W4s-*KK5?3JUgpbVP#Y$&!KNw0QQuaH@F`t}iTy6wXF2?!G=pb~@1aGL3aM#~)uji7g+9Rz{C zpw)LnL$gRED$AEV>iC#aX2tHYe;5c8ogSSB^JJAU+ zbfga$6TFOb2W6$j!DZfd2&guW3+m+~y0sHWa_GR3WJBgx=cG`L;7~-_atJKI9ejjd zyU`1r2&*hOM5#a7#T=sP^!DA;VPuDc3aK!Rq913oRWv+66)h8WM-0{X>74Af#m?C4 zc=7BoL_gLcFHOC2)AJm5sH_KxRRcA267ci!3vsD<7>7qo1if7oV*fy7gr)FCwUb5( zOZ$le=x~<%V0L_~e`q^CW;D#v6~_kT>VKp8s}Tjg(H=o?EVu{HiW-6UXhV;cbQLCv zse(KJRagmsxwSi#%LL`c@YhC+F-kDeR#2175{U`}shl>%!SoNj_Br#+@NY(7ryEQsFn0>t`fwJb>6G2!eE+s=y_npw_$uFM$-p&=0wnP zV9mN^gM(!vQ5tId$}0gwKBZGlC4Te0u*@#393ja_x#8tA=@-%aD{jKgrSQCsO#M`!27TCLYMwy!%Qv?`e@LvQIEIEyN0KV6)??L@m1>P)cX zL;6O@w`Zxll|tM#HrCJHr0nl1Eu&;8&A2ROi3;m(j=#2UDDVr!s6|K3;}}B7S0|t= z2~Ava>@y2h79^Ea^!Z9sjx(m$JVr-6^fE27U&n4A2N!@gTP*-B#l8hNg|KKNw~>l3 z5Ky;D=L-MwQq*g%DcR{j*nvxx>xc{oH4)qAOqW&|uZTl(kU;HexrL+dP*R|f$=AR_ zkKV3>R?OZ`jMUO0@Ggsk<7rTiLr}|nthUrqbtlfg0fz{CK&gnU(|GCa(2=dHU8Ao? zBaPk?jj?m6GAui(#MgwU0Eenx2%S6XfKmbvYx*jhG^&g17pFe&*0If8uR*O$=d<7? zVLzP3l8w&7QijnOT36PNp?BI%-?(CBNNJ`H4&m=${534ascL7N7#cW#LsK8K#ssg< zSz}C*@eOry20Jtz?7x!rDU_?nvr9ILfjC-iu+OYH?TPGB6HHoE%`$p1+3cWP!sRcI8>T!AW_zv-uaFLw$(zI! zSW=b{2}1PfiQC@!VGTwihSlB}6dN;{^RsFCC?BP&Eu^?{Y2z^LP#%jRhPOE|MAeE4 zR$3*o>mwFR+uj6=;qk(wF zvl#@ta;i6M(>uqQE$~G(^0lju;pwEBO#N32sOs46>>IEwKzxX$AyXB5>!GKxJq%`Pv^6b(J=%Q`KXZ8_$bjk8ZYYey$}Sn1@VJqpeTh8$p^EBH zFGzlNag4%9%tQ!O3fj>1+Z3)UBB~qZVq;Y#GumC#rU?|5a}g>?JDo`h7Q+hCB6@sd zaN@X!ayblT+t{LFShBdWTw4;!0*lexwixU_4hF*j+t^DEjZY#Bnc`t7#;D~Xs00e3 zyG6E8@ZhhA6G|_KC5QOc>vQ+4dDupnGCVF+3Umg%6l^Q7xm-3PAegI3qE|(@(5WIg z@`~U&GW_c-!EF1f-UY4wgs83F*~9*gi_rQOS_SWc@ko^rf0Gza+W1-&zL!n=q}(*A zP{P!T8K%;?a#6t9Q0ANiRMh@)cI4xm0XLA5k}qn7fKq?W@>_OVc%g>tQ%MM@B|NVu zVBAA@ERO=R7^irC2iQxaJ*Z569QN{FxkQLKVXYyfqSPCU9x*iWQz*G*i50@qMxcqS zn5lRhU;O8V3zHq2+1NmaZXr#j1(4&rcDPx?wCnczu-kOy3h7>F61?kyWDox56UB- zHg@RCku|wHm>klY>Hm@oHP?Z1GI5nA1Ci96tU5~TtF>bI;$zhcq6sUcM9-+gO4KV1 zZ$gCvQYvY{l5U{7vAk(g5qL^x=|!#+E*&{2ZZrG3(Rf2j%Rm;q$mMHGu?>UfS3y>T zN%kn5T1J1cR%Xv(6_e8eNII;Wal{0lY$yeAkRNAjvjp}yFI%7WvTMyr+vK43{cAF! z=i$sKfTcQzcTw)J#&wsmYN5k22*{}!1fVhiq8(v8XDKJcg&RW!VVlCvmO^O%k1k}x z4lQ4P0dXPQtBR(CFV=F^G1%u+Tzn6>3e$BiIz#C8D#!;5RCrj5HA;()!lRQhX?+p5?yIyZ`h*TG5frX&XlF^NNK_YV zd{M+)VH3RUprFzADWASoK@?A`a)n_wERNb35ypK5OG)i0@cs)PUlE~+(5If^o>44J zjG_xFI;x>U&_Xe)6oQvZ*HtPE?_Y&@3e*Wm(y4G!Y8;NsU(qlyJCb%vk3t$0_HqkZ zXX69y#;1xs9K^)#KNvs}0ZgB5z$0s87_KWv#{;U?(eyEEOkiZLaM$~aWLEivQ#0FD zx2DLH&s|gnc}u_2hgR=aVu7gGa1Xr5ScOyeY|x5OvH0biHgG~(@fmSsy^hqW025=h ziz*gYeQHLNCRD{9&9N%l=H^6g4`8~4=2A0~7nFKRBVmqiRg)3N#nXAGWpu|>q!5i& zLCWNdIP+0KG$wn}26m|>Twg&qrQFy^I#$hivVB)2LT9QdWR&${lPkSQt9(>FLsb+q zB$0>n$*O);9OfycYgEP8>~X4KQntv10;_d#PhVkcQPC^5gz+AnnnKl57&WxTb{aYa z9CssBUU6y)28PW^g-k!9eq#LJ4%%%G&K1oEOLkq5yio`XI=&B$3FFoodeZZStUg5- zA?ei8&Tdp$5RIZ3JF$AR<(#9C(}AKW6*4hwIxHVqks>DHi==j^=y_<5 zfkhSPX>5N{4b$Owm?!1-$j}D6OZ2rD9IMDv1TbY!b%^?6E^%I?p(v|z!8g*? zjh5D(-OZQCE0&%j**78yfPOT(8D%Cyt1X~@Av#oG_!(lDsz z87Rt4JgQ(rrQ6dPAW<4-n9ObHgZ`ze-Y z6h+r!V58+05sTygIg3dCTAi_Uo@*_t*>EkqCGsiqyhDJVYGXrf`;iWZCgEq5jw<=7 zhd1tSrmO0ghJnHtz8D<6#)PR=xmy^DeQ}0#0GkqxVYT?x&+b)h;zcY*m62rkGWH`f zxxwCJGQvE|UCz^oZROK5eB%#aDIj_{4+ymsmQ6-@HwqDNlrInnjHG1WEEVexD0&b@ z#xPQ$G0DZuYBiS9_PF6I-QAVzaP_p~>Jh48U43HGh3GxPT5dbo+sid5gkEVukv)ov4k(9cU)cjh^K~rEHIC1|%o5ZalBMp;e(nL7P!5{NRYG4`&1!W; zl*$ur4L1c6BmX}Ybnwpn3JO-51&ix8Xsp#OZ zAP4E>FOksg=n+(OT!X~0%%`HM|=G^9BPma*pD`ddIts%)fc+B_M}d-L5%~dN4bK@ITzE>Pm2Uf z@DhAfqTz+|mE}Z4rLRg#4*ZoBc@g;BHDxLrF!84X7z=68QR6UH(7CYSM2-}#!}u$@Jay?ZarWe~ z3eZSDUjQxMVH^t~h#R3D0=)?K8q`VPEmOv6amkFoV6G9ld`Tkk%$n?cY4`uJ_ckzg zRad^}xwpP<`J-HQYzI5JMT#UmOb0tvA){yL*2B zwa&ih+*@U1NcWo$4V2H>-+S$~)?RDvwfEVVtHmFAgbSy<%w+OD5q-@Sz?UW-y_(5@ z^k+W=nww)UiA{JSbW$EM`@+JGJSY2OnFO*Kq6&H&)*L@hsrdUlqq5xG^yH~>Qwm*v zBAXxW!*(QEG#j{z&RWWgE1H#Uf!$mo;-|GcxwoHeen0OHT-UNJE&1h$)-2Fx>NCm1 zy=0rTCw)rkP}PS+rG8*am9JuS5Z=o|Ok~R{>VG zxDHtfti%d3FTS7L@$_jXLUNSH6GSn%!y}9<4eK}YLM6klJ9!M>2-|(rCtV+T(DC4! zn2#1M+tU=WPid1>TP~wqo6+?9nKY^C;ktWYl4yWx4?T4J#SpoR-|IecIIWu)eVKYJ zhcXq@*jJnBhrQif51r&E6!!AGmt(TW_`-!viHM)S=Ah*aeh>LUOf_f^;MSSrNhG7m zg*A2zypZ3>?_ob{%^s|k&}eYWSr~hQsD~%Cd6)z(Q+F}5KgTyKoTJ@!h>Mtk17j3T z*!<{qCc<9HM%DVQho)xyT%0yVnm-b0$^I)57Tl|1GT@D_dTZM1jU^)cSHbM+2J*>% z(UGgsT_^Y|c2XrIVL5(rER&+oUX(Q%0yHT6Da|){6#8;$;;VX-=|{H?9aXf+_6zuO z(i7Xk&4N-vJhXrH6kt+&S2YdOhN+Sqq}6>^Y9N_V3VxM;!m!_z=zB(%fM`!*rVyL4 z%mzlbv^kvtow@L^quu?`&7@4dwj6bDCsDbYnFW*GrP8dX&M%wk{>Vpl%tjx0EL1DA2+;3_yvdV28 zPcu5LpGLMR8zsUfL?=QZ+Yo{d2d#bBeZ`5GF7U!cOjFWhOiY=}`J!~;=?CivkI;vx zlxTzxRTuEzuU_)A-ye7|R}gYnK$=tPLm=)$R%{~gL)JG0zJFauVp};Eml~_?iwHvY z)>6}>q92X(pY|l%G&i5aAntXtB=O6$PGq}GXOVX7Q=T7B!b$UiwL(^6@ny#089s>n zYAO8egC$_{7?d1V^2>NKtNb*LQ&CB-#=DDOFX!5xOv#YK1;Un-FiN-)<=*TiVe7C& z{JxW8>saDiL#ZM&U@}ojs7y4Gl9`k{XZ9YQp2{THvJ(W_9L}W6Gs6LugWMF9N#(3W z^SC^B6-_3$l(ZyHv$8#`4_l69lJDgZ*aFFS@Lg@%pbM`|!c>|kOy17@0f)e(Mj668 zaKzb4Atc;qThuK{I?~x*4C{e)Y1iDo4Ey^oNG z;$SVD#!81nIQcn}W^{YY?~jD!aJX^dTytIe&xeEx-eGH6=3=PUjL>>(YDRM>AJB!y z_a)R2Wm1)xXm9@+QxQwqvI1=b(p7tFrp|x2rflcCf|-b4%<+J`dM(YD9G-lz^r#0? zhVgjGicU@(o|we`i4GlZnoA1rI9N(7qoDl4$-_ug=hsPTMfH696?gL?xnfxY9?fQC z;{5vAi31b~Kb+w|`!)p_YR0}_y;Zk%HSfJ82ou+Q*u zTZzT)KI$={I@y?yrjL1A>5;<#p&Zr;_W4n=tV<$pxM?NO%=c!}ML}9?$FcTQ$?j%F ztiERW4*WH~P|hZ4UDLeu<^v1pFNM>@NcRbTm&a^{# zh*B{n$r^(MqAg`~0EQmZTq(ZG=T19-Y4Om9H@)N7-Cx*!=+@HReojUw#?~*<4?0ynFi*}AhZhwrbY^7u9&V!t|(jj^8>#+40MW6e6^z~>c znv9M|hoYl|ZsFh8qv7aubQ7V&(FCcFM8}#rBjgP6?{pM>!RsET#34$Scpr~unk7RU z4_p2TN=!%mn)SkMm49*@T^;0qevi~TR-=qy&8Thj)RQol;Q12zCY?*!0;JooXhWF;mjzc)HT z`VeVqF+eg2Mn`zawfeH_P$aZ9w7h(4VyITSt07`)yI-hwDow(^z+<)8$BhN5i{;2^~wA!jlH z{Um9lR2L#Ol%vsSi8+@JK_che)~;_LU%Yw)B_FkZCV8sXD5)a;mx+ssM6gx@emz=G znLuDCnnM^!Co~_Rw)zyq3H^c50@{6E1Qr$?o+BiSJVK40LZy%-)=*y}zgSjGxR-xo zET32J$Lfv;??w1?9Hy-+GJOsqy1RuLGnxnugdlR6|0< zUgO?lR-$#@xWw1|6E%e@2f%q&2$2jI@2@p9IBEiEHIE!z2^Hyrh0uKEA?3>d2SwVG&)!%B|BLN{)OMHDIigHo)jSpT?vu+o|P(uRg3v@7po*w4^(P+%x z3J(+Bl!U(asnp z_wjF-J_WDx*HdpV|J33>(l=2}Myaj;9b%1Ay^T_SBiK}#QQlLOFVU)coTRr& zQqWorO|JD;5CU=Uk za5hD$4YVgn6xUP#)SIxS9yL1UX#CPE69$)JqP*}UOsmIH@`Q&ClowVsQsoMx!j-tD zM2g_hL{X?jX^m%!G|wp|y=}4{g-h|+xb?nK4E^ODOcj?B(%A=K`agw7B@JA{ti!}Q z^ns^JRQdQ$nv*>i)a2pJ1aLJZ87^Uz?OvkC1=S;jj?%&qQ$;GvwSy#jIww>6WGMPG z%D3jq#CX5qX>e;2L*&NjL29@iCfOldQLqWxc3ITkm!wuIliWm+4wSx=NPie%>qe1C zxGu^qPNiAYCG8fKYyTWVGYeJ_ej23npDV~f>7fX^1-&m(H1oO;XwSGUE2aUxHd%-?faaW7jCsBH0l^xANJmLy+c@tGp@eU_QcRB&Eno z6`=r=c77NzTwSKDlA;4p2GiPNa}i5`ORgM?qNPgv8pF~gjLQGr)q%Ybn6kkHka%9< zK}SG((`KuJ558@T(`B?R!s=?sovLJRtSZhT{hQbRji}dK?WX`e{(Np zti*?#XCm#_XiPI;DEecYS1WD_iCtVQiKzl>X&Bu2VgnLYBuEr*Un9vnNDU&9Aix{Y zk~M0aE5y3(LMSS~bRQi|m<1#&TI=f2gmb(2e9D>^62dxAv%+mB*~MzXMS>*NP^30h z`h+o=ud5eo%`JGf6Y5{7cdW7NZUY)EXk5s+^Kq53XR2O;SsEM$Yw62#hd`Rd_zgAzQZACoDesDqCPcgS?(4533~Sop zN|*A17^(Pcr=buor6koRgnpILiZ_J(bj=x{a^WW4JD5y2@mV{!1f0kiKZqgq(YHMNT6qG0s{|3CeQkO3B5h^Dzr6lM9 z;z4|?)rYB%L@I|1w za__AcOFH=XY56{H`GY{LiSs_K4z#mERDRLtpE$~?s+rebEUTt{rnti`UHplog0bL8 zm(msY%BLfa6_2{Ykl~m5VuBKxk6>|zFBy-?pt>O|&D{r;O4U(HOc_5#BbW0}U2fSI z^-66oY6dhQvJFey@33vOek* zZjD2*htavhP1_26M>}?BdRu7f&$s^1UoD185 z_tcB)l`z-ccjgve+DhtFho`na$Mp;h@R-H`CPC0@z83MJemj=~C05M({Jw0rvf z+m$+Z=(BZQ8fhGE+yvNM;Jb6bRn3TxvkvOdvaGq8mR0jW^dBJ*|I>D~rFM#h&0&E5 z;EqNyVVD9=6yF^ac~U(z&$+lb?Je4z3ZnL@^gd#!{BMHFO`BV2W~Ek$gQ&R@mV4s1 zbiXHycLzrFk=^Zb-Sx&oS|gZT;t5F|SxW6vGL;(eM)^A*oF1*9hCLyfDw6;x@#*$~ zXyQu@(MK#QP@MVYt_dPGxRKlOei@I);BD|oa7}L`q$v>A-qFXT1dk(B(hZ5AnxeIy zcP}N}Coi4-7r^WY-ATHf$I3U!qRT*M?kUabN1@3b>7Gt7=e>)CZGnedhTv2Fc+$LF zDA~>6)=BJZaQ0ws7y+9z+&=t#5cG~9N1CoAAqMy6IAT`5`G zCi6f$x}v4tqDV7=v}}rcaayYk31CQ4Xee4nia%0=O%l*WzW{J#OI9q5)RaR~f!&VG zu<{lXhZwpzA*HoY8mKK%-}ET{(*pnD0KFUy+JIi1+Dg$U)9||HifLWTkfTqh?FO6o zvSmMi^<~#BFqNZ`E7g}Jcbv6PmLSn`P4q`w1z`2-G9P?e_)~`7<<`8T? z1clcNXFhaLA?xXKD0P}jCbxFh0;Oc-_^SV(_W05ei=nU$7pw|jVq~R6R%~hPqNgyI z#i|6J>Ud5NvRQ6HCRA;6$?*B6$#s3;D_Z7&Z(f{9{-!XtXT*rOe}^TEhAN zXFiFERMvfP=3AH}+E}qSSPW75hgV*(E=(|K<8VkQHD9!>P4#Ek^lg=C&i>kHku=cO zS@vL}q_H1DRIOd)`o@|hh1f3~Kk~W8ochaPS*1{T4`E5K7E@K0Le~ma>nJ4)(xXl; zC4W^Yry}@)eTrf4T@57 zdD7T$VZYCOYHClvl|h}U|9Pnyo!AAL+#&S-3#Iu!yP#ua{G=Xj#RB2QCSnB{$}(59 zgBm^X!FrXZ6K;hyHwV;1P|Th#sY%N#{ji^weBAsJmS8Id&Af%;M9BAzm-%NRF7MoO zSBuy<`1b{y)6bWE@;pXsQ-k6CvFi(6VKg{JWP(PO2c7+Nbmz)wyAuRyS0>49|(Ky_R`1evVW zysT>9DRLsVLLh5VL>95-`V0&tdFq=fT5z~E>Xvob5B56QZ3W*PafXyB<7YsE{T8-` zv`ZFM;DYRuE@;Vx*2`h0NRqZ6I~JmXt8V^!{7Op>m&^M=ju4xAm%|qEeBMn-61KfX zkaXc7rK7nf6MsIWN|PG)x^l&(3z4lxqL3#>nlHpto_09=K&+&dq@IiWw9My0@y>J` zYa!m8527Q}k2d{(8=0-!WG?1(zW7S$d@<~~N!IyRsjP*-eZDY}JkmsTug*eyNzQle zQc(nws!l1mkbmi)i=SQR&1VSrwEM}lz}wnw%t9&T&6q)=J<)|sNtvLU7hwiy&dCv~ zG5e;ww5=Pde>~n0F6HNU(6lUGm(1eppwNX@fg=Bb1C?6B%F`s3ESAjFn*1oLQ}vxZ zn(mJhOWO#Z+`tG6qhOvj{dsAZfOfTiCDP9Kjzkl;14%fG6J)oOD@&YItOho9>8$ZA zEPnl*CP-YG)ke`Z3u~chWwxE5*rSzO7+bsQk3OD4mKFZZTIIhE{!D=vwod}UX=U+| zP!{&zoLD+=Euy*7nNNmbGr1IYa^6cX;yW!P*0pS|Xa-A;>zJIDEQ&j~DmClm43L7d zwcd7s&b`kfY`T<5M;5Us?hYo6MbJs{+g8U{J!ii0kY(EW+en(1BI*a(M~y1y0{#OB zr|8YP&)uUN_5;#kqzZdJ#j}D!-YS`o;?=O17IS_ z_K;^z&KZ$Qc8x5T;K!3Cw9r;?Fmm0rb;u;vU7UaT@y=(!FzOG&Qn~H786@H8=`Kd8 zWrLp#TxWYD?M^A#S3cXn!du!rx^V|%51X=DHH(#HN8U|(b}mM1Z!^g#bHaCC+FNfa z{mE?U02{Yx0dw={$0ys*K;3Kox0G2N4gz6#FViFrDua0W2iu8iM!3#wXHT)6au$^P!}-kAIC;v>y@t{8B|} zTiHWeS?A_4_S0NG=#ZA5%Rfk3RQ{fZ>$9x2f`;jfKsPa*f5vdWRmvmz^S*gq`oAx(ynLD1tNvOb4Lfu#MTN4^qV|K?V4VUi_p{nPq(bLCk0c%c;%2*@`s^V z>Y@z;;_~cXM{n&y}ifKNTl)*-;*(MYab`^AwqGR;aWbo>E&{fyoMTX{1RR zwu_@1?&Ltn_UK-|CAbSUB_s~Rd;YPbK1$R7x3Yosb_%j{%LlX1UHmP){s_(kH&xw= zci!?zp`Kc=2k(f1Z1TVX5sdj}2hs?cJ zsh8@{ZTvyG`|>>4kHWrkf?#RKrX;Wok8nObC^z}t0v*+s96^CqgPk|OtxzLu^QE&b z2vmp5k05&5m1wUoaPx3rj%lzh|7b|4eix28s;cuHr!+RFzj1$mx5LCT4!JF+cYso(c$r_%LhV-^ugqNbf# z*(toxiZb2vR_%qRv{=Dg_n|mzwhwpyTGf|`zRq5#X9<+{)61GdcM{oU~p$B0`NULW0~4wIo^H!4^ulA!TB>vBrFO z=M&3Gulgd(e3xGK0Cngew2#~d)1_NJ(vX@BLnvKtdZIN+RyQql8j^Xocy}Tt*x0$l zdkrUb!c6hCyR)J@;9d0xi7ZCF8|ic#y$L_j`c^1p;mh444RTpHZqR%eJ)|$Pc*{EC zf!E3f)A&l|vX;Kz#IPGE^p)&E?qmqgt?2Vxfh>Ez*0Cgs<`#sYmM2iup1%-|maAN= zK^EPzgR)rzE>I|7OqlYO&-~t^&s`~Zo!KXj%?0Z6ol?3$j(T0MgEc-9$nr%iE#1VE zE!+BesBe7u@jF=x&qfbKB9@e%3PZvv8z+zhf?B{h#?oM;Wq;bnA~=c4NN%q^bMmT4w_^ zUZ&AVySuM1s{E@U#!?an_xJog4vDWFFs&w3>O%^L=Upeck$8u(ZuanbID#MiB0(T& zDEeeJ81(8xi*+5qb~9ckNb6z9){n1crmD7ThEXUyAO3)>%a0*U>Ht;PQeJo@?)Yql zHnbptlOEp_A=Axe_hGlwA)Ax?k~+_4ZqDl+i^0AI%cA1 zx#nKBZFyyWkQF|mfKDmh2L4spH}`k)PCxUIDoG9ecE_IR85{%RM3KU$vlcHO`~awq z#<~*KuAUE0pFck<2`2MQ>s6(T*c_X1I)gbdkv~}Az z>m^H-j^|}}q|(K{oQmGtj(LdFTu0b;V1|9BRdQ`5UAPN3RHb~UwhnUJRWJ{uE=|a2 znRqPykSV%GMuFP!8zXiTJIN@bWv%Ia1>WA3obq7@R(ei*D>}d-YA@tiYG1R;t`)i@ zT7yqOq<8zpQRzB&loFb1vM>F7j>zSfgg(FA4_C=IBe4yN_#o90Ey<8YPM987vSfo* zEMAR1*FNU|pRvil zQ}1UIxT2*h6J%sm{%<6^E^i_TVKVE2FF1Q5)6pJy+{Ltv3z^97^$WF>Dw0XyiwHWq z9ll?cDUlLft-1V@n?rh1y&xvmZ|AK((j&NDF3h}EhBAVET4U44GJ@&K#1dN4veEVJ z1lVC>Qz9&UgwKZ9J==j$ET^59_8PJfBx+mhwA&}Ge)#A<&Gzha;6B=&Ht(p$Da|ek zqZ#hgN>f0Vhy<@xs2hgiID!l7sOPiMXZT;U-{}yozdZ?E87nO;JkUPEh!h>`;MWO_ z?e=FT+d>9od;R&i5cCOztJ_OA``8#@znV!QGug2bjofD(^Z`cvnf9_0NUmRfAtZj5 z=<$}Lk7p;pW{M`iG``Iol_E@#bs<#J=cTn%5$ z2V=n{$$Sh6W8-SS<-PNdxh%TSFQsiM)s`O`A8>)u4 z5K&`NA(zspVUp^gX zTo^oe2nRtktuvS;UM0j_jLKf$M$4%}(&CP5(h;;1CWwWd=+mu-i8Qv>c6O2?3?GQ1 zTNY|>$QFz`kR%LilDT-7e@ynW?(Bk-I6On^YyHHCCy()UTmd z(`lIQJjgfZEoJu{r8cE9-Ab8%ZYIZd6s<7qPAD8LPWz0?j|T(3RcoqKH6Vg$pkkLS zlU#n4>yjX=yVaHkozA?_w$G>ZmfvWpv#8L6b$QJi>$~-{z8jgF4)Z4yNg91!ayDI{ z_>xl4Yx7o6ODbmBI+%Vb)2E2{Wr^D(euG)sa>Ags-|I{C@4T$fQrB?FH+poSxc;)Qn>-=5|;*kU4&Z_nUoVj{$#gccA&zBGB?ahf~s#nY$??#j&h7keYdMp z*)QU~qhKoiyiEM5aYDgm@+cf_&N#&--zC{?Ek6(_8|p+IhmmjGq{A1INtuD>xpc2j0?O2eqfm0z?pyYP)ZCaPpzQJLCXTWK!iM|w#gPRi)e_wKIl zJ_FW{frkT7{y2Eh%r>s+4e7c=7a85-w2RtWz7i)c%uP`bKQ5~l!IIqNNXZ^;^I$|+ z&NMk+0!poiqED*qbdv__;LLDk`xl{-C?Kh#^ZH@*!jhYEGQFZ@`WQ)GMa|KJw5@Ff z(I;9h4p8g*H4CkCwNYj{TpFUoq<*M+AX*)cDCml9Kb+@A zUbNKlbssDF9q`#bO$`za25wyt&)2ltBu#u@6C`bVep|SUmU;S4;4@8>#GCcXkB4b3 zweI$t#J-$z!2lA1MVizWcQuhJpw^FDgOw@P&>2FZOej^0YB?BEI@K6V1(8Ai(|<2r zoo?hxPwD)fEF#xE!uV0ml5q03UX||KS2htW@y&3b99Ebvt$67_Xg4m+U!>E z{I*5vKng+UT&i&j9(jd?b>#6(X!B~yFQnzS;ZXFdH?+!j*b%1v++kMbvAu%n}E8XS{&ix=teaV+h!v_M-UyUI3 z*(DRf_1xwA0B<+!0J>}q87tzu1Jq6pfoN@exsaEdv~t|an4r}O$6~9gun<;LA6Lq~ z3sJh&=%$B<14hEqFiXckEzNtG{O*=1ucPXjm#paY_lH!X|E~ygSi_ zPmNjv*6%M&X_mT5)RGjg)Tzr9{RT-e6H>VpdWgQ_xM~&1=@yPJaIzakVSy8%4gL7s z57=|H&Ip#dx6;)Z3-OO>0U*3AU_@W%is@dI#$HMYVMok{W7z3>O?oONjZb<_o7A4%M@-Bd_J`WPix9cxDik78*KXRT zAoMjsaPJ2HRuBsApGtrAVmB>{ee^w#Pbi_+MS;+vQOKMO2cTVGYuah$AR**}Moj1< z5=z_QPTO1v!XOZ2A86!0IfZwr0%v>u7@ID-*74gl^yETF$}|1#l^fYRfgK)pc2g_9 zwijEw<=}VThT17*(p{g_0M|5(W@arWO{xPFEKbZLaAk z`it+p{p_DydUe|m{^fuCzklj)7yYj~Fp%pU%H;}OJO)-O*r!L{;@8{rf$o*@iCnyj zSGkfa_6+6o%cJEHd4=Usx9U|^`>Uk#afwFrJrsVCN}WR#C84N&};K~gyk2DhCQ|6CJ zHP}g|^`Fz~mJqme5e0sdk4pp9u8=kr0tZ6iBmoVh`kVrQUwv+=;9VJ4Ul9^=T_B@q zW2+<}#O2ojA&RTF2!zM;eL@&{%X0-oT>tVM$XZTHL6{KaA&^_F_{xFu8`Kgimq$yi z+ayVm7el^Ue~}Wvlhjckz1F8feQC`QP3jsfObL#uOR0i_gdFdf~@r0(UpMLi7KljyW2F7L(l z=Ak5oLY=}Oe5TpJ1nkSh9Z^SLTs_h^C;~6BMy)XqcJ*}h^)dUSxYQFdS00Q@-BG@e z(n_1|8Dg#tk|u^zk-R|HWG|?AX`uGYc&IxUm(LCs2jdw%P7fBB_UCeg*J{fD7&>$; z$`v~o<>DDVPH*iIlfs5G_9}Yhv`6Cd^Kto`%?zklekm@0rx?$~DxvuEHt|$nYE#)he;A*R%YPG>UzHpPl{6EI#X^)P5ecU$QUqxr@JL)*-Jk2oQ&RXz zUln54^mJMa$@EWNMP#ds2+39m-QoQdi>rDh%7C-ALZPszM;-hGsiLW5fjpCxuC%vOI(uLT!@%1;QK#w@dwM$J@>@yjTV3LpzHT*Cep|BW z=M4F6lnDb~wY)!<&kXeEfROKk56W*#LiWYwUzsQ=|7M{4yIXpeQyW^A4BogT=0HBd zRHb5Ea=43PpTCDIR}NIVU`8_HX~tvXOS0WYt44$tB@_)nMoNEu8l7q{7KcDlE|?oU}=|t5H^?b{(0VLWa$5B ze?SZKI@c$rbzay<+|P0DlzA6_?Ot`R%^Aa(!HWuPch;`pP9k z9Tt6ipuSoLNxl!AKm&b!`Nc!DL`h{C1S|V&BEAiEat0KNYfyYyxgK#w2bMqkj`$HK zD4*|RWYuSVWJ^qi5EG$4($m4vZ?rN_9}34M1GoGZd=8@y!e#kR`1=WGksGaMZ?m4I zqQTW3sf5%cu*Ic5_&ctw?Hj0!i1%R3Roz4RB0VrdrjVqlkL5k%(4r9jkT6&@sksWo zq7r3rZD&f`+(7ElHetkxCI&NHTtu=nA^fyF8t6$&4^(!pD&#>+UK5^JXEzTGk(Z)T zZdEbgy=qa^QCQVaLjNj3uxb?<1>n`xM*iiBsD*Bm7v06Uat|FB`#=vt*)CXi_ZV^R zf%f@$_T6}z!4Jkq82t0n3BV}Ej4MwkY(1T4UcvN91~21ilakZ%G~mRQt(xQ0!pdD; zw0c)jgrEI&5HxS)2^q`2m0vc5zFV%=er}{Net0mS@1`E|3R{es4ETt^BOU=TB5Oq8 zA^7nu@wmR7B7+0<9V&8KuuEk2(MIJFns#ntoM7NO1Tm?DU2(Y~c}9x#CX+%DDMe9^ z%)F8;g?ZJJAM7jeuZQ84`to@cWM3~0A$;TV@8Jk&N?M+Q0vpnj=c=9_Nx&lj01Nr6 zScp#-d-%0KX_SPyj-c)(Fpr2SI-nOp1jL|;zhZHqN94=uYEyhzg98=UfflTQu>vVH z`iOEQA+3mD$K315)A9{Hu7MZSB6A&0lbqRs9tXdjaYWNm!=CC zCD%rMOnAfMX<_s4NZlL~Pe@~YhI2~8M z8CPD6D=%p>lz(LeJOUR(`PXC{B)Z~AAHcYUguZY+a-_Sb0}~tW0Gv{$z;{#tgo_>G zGfOo5$C>(Z^%*5pE=Zf!Pv}`I-O#fPG(N_^vs(5Pco+CDu6)nv5wD6@fu71^y^_V{ zv;5iIuE@3-sLw2txcy#%P~VcMOF$R&4^x5}P(DlKY_G6o^F#!piOLoL??aqv%Ae^+ zR~UUvgJ|9{jeC1K>D7!5)j999TtSGnPvr-gr{#C!(s&Os>B{Oe{w~FpC2?gFJrIZK zD;JVKnFm-V)o0@B3(j1G6|h7Ftn^q9>jDL*d^tIaZOj%Rn; z)fG^8g(i)vVw887(4hAnn0io#rsh{MzZeBwopY>w-cY#^%oo68N}w$C87e(vlXndS zzXmZ@Ej#{UcFMcaX-s^2;{vFG{?-Sq(834V=GR)igt#Ex+cyT8i>s%az4%}>*z#E$ z9y3L3xs;)5m4gF<-q!RiQLJ*FdOu-GR^Ev#?+Q!ICY2%jg5K}CZJ`3IAdPGYg-!h{ zpnq;6Bq7WK3)#fcG&HooBGoo+!6^Y!nbL^qMQH<-AIdhWJ%DW>GhB2U(oCBksJyx~ zSncHoDkhl;9ssLoBwMtZGlj)lMa~qxkIL3RIK~=TBM69qw6X0TVvwA=6-7MS)wOLj0Y$@(LJKs?)6#YcP*GPz4n1*@2!e z!!Ssu`0qtX7w?b^6jk0pv}+Qubh5Ps?i@?M3DZIO`v#??V2>pZ{y(lC9iUBYm+%S`k40Or*dneN10;y#D_>_^lroXEcxJ=)WWnP#g?)-JD_ z*+sm1Bmsj~1P%WRg>E~ zp?Lf|2%ZV+3#!K$O{Uu(D`?MXRf2HdR-%s7lhStJQPm$DzV$1Lrye z=enfOK=nEw`E}NOb&cefG;Ni6hqr^pD?wl35|9C1U0q<-tINu_Lg7M;l=Q;QvLPVD zM$_wgqyknUv&&hWNt(#Y3o9gl5Gnk<+x%Ot#K-I}OdNy>fA6YS)MVvCm@F3Z=AU+-VMR1 zv92fSz4{!!>txn;BIc7I3oyxL&3Cxk&?=av1uW45N(nAh4=BY7Tg6YBwX9&KWi^-S zWB{-#ER&`@P1YyFK65`X8j*&L!1X7wAX%89V!D!<$2gefQNGaEx0Jjp=3{k(p7Er|mZ>B7)wC=v8!+!C3T=il$P#6pSG^G& zB*_q|Q$hGX6AXn(wZi6Jn<>OICe&tNEwi$!H^P`Vn(bV@kwhydEqIMMDM29kU8V8U z{%5bMjnOhZ;9W6R${XS2fB|!sUVjK zL=-ZRcXH$zI!^|4s=cawi75pj`EP^vzVJ~DI;nAH!#n(WYn2PMjirDZKg}8y`BC+q z6C5vC(n$m$ z3f(}!EW0yi5T1ELO`drQ^jTdw=QV_UUq^>rMyT6Ptg=EMt54D9Idh(9N4MF1XI}B}5eRUtoZ}M9I1UstlsvA*O7-z&*t(>u z8BE4&qkiHl)=WUE6$;mClM3I-wc2cZgcq|Fgq$N(z{TQDF~y9(th8kcs0+-?e7Bib za)E0#D}T1-6jvvxk)#x8n!x^ELAlh`oU}8LI+c?YHAgY;rr`eQ#z+c@Wy>GEh^k4c z-bMKE46en9P`rPVEtvA2s*OZ4i-WI3N^;{BadUoT)XH2`b^K9q%+cqMJyX<1U%VyDiM|0k5X+(7_dT_68WW?1kDQGNG5^mG}4+Ni9xFZ;%BC7&-{X^P0LUF?mI6N zEh8pc?AbtncA_+j1+9y$5_aQDJ;>?mOXeoTjlQ&pEikZMc~axCCSEcP7?(cEDt9h1 z^XeCyNCGiM3;?`t;B1avrF_S=49C{$3XpLvGT_==H;ABsIc6?0PfRpb-{P%qKraf6 zw&V&%wh86cakhypF+Ow2U>VnQu3&Af3WQpfUyRh#;AO;GV}~)?T+b9%NUjXV_2)D( zjKJy({{rfhoxkdj1uV2ct0wy<)b`nGjLkwO0P$8M=w`Hn#Qdj)6?+eEO~1`rhzfss_DIC=j4BZ>VoVC}q<{XCw7zGhmVVe-7~pfYH4N6#&>qXe>y z>gN~r=YkeXFjPN}K*!}oo@AQQ^Stt`e4y}o!PYQ8My^-o>ieDB?7i58oujW??S~6E>gNx(G+luw6nb3kP;{mDT4PVd0nU`R%4F zvVKbJ@r|~4d;ZJp5ykbgOv?TyrEKe}ehP)ALx;AIrZtG!T$D^)IMvqK zDUJN6iFsy6(2}zn$+0pH3F^!SW{J)gK>4Nq8c@BTktd8n)B-18ggdmg-YCNYW@T;A zgw|Yg{>$Dn46UY1*4lN+`+6CiS`pOWNx-2oOR)Fy#O`4WTNc=IR;@o!;det}9h>7I zkmcpO*`jgR7Sypue@(X9@B(QY29D0D`M4W8Zs$ibWviklghB8IIA)?;%hlhfdE2n!2eWWK)l9Nwx@{Ikc*xe;M?%* zY@Uxf9MeN_`q0C+;ftYSf(B; z>d}iyUS^^qnaG&~CH5vC3%gl-Nz{qeQM(6cb-w`B@jyXT-?PLVW2`07YEr96c+^5; zw{qt;>Df3e!>@6;sF5{Zi5uVLsX;Xk<7?oV*8u@Dlp0T1dbuDqbUJR-EpQ}moV37+ z5SWP@rT)W&V10G6MEKfw&xamuF$h#DUEFw-Xf427ZskZ z+wF%ZFygM5z;vY z6b&nnZKBIA-bL{XWrD04n7gYOdcMn-k0gCG5&8t7jt!Wg%I3py4I%~o6Z?tjhI_=` ze=pDtUb7xF%4WdApe|`CV^ye_8*K^!4tVl_H)#Cy-Ck{4G6AIUI_b1Xuf>%;g}9;h zSmV3cZcismFPeZS#nDONlo9k>AzCIN`>1wW#N{cJPlen%IKm-z(Yk$Qd18>skT>d* zqoGRe>;0m?Ik(Kh3mdZ}<(0!cHVw&XVpyoDA!ko=?pd(RiLVXDCv0MDRcEtNHz&yO z;)J}X5(ziZcn(=cZ;fX%63$bRV~zcKd{>WGc+?LovxQ55hqn&Wbd7& z#{_IQS1%Y7c_Wfa@JsD+^;5(9I$>jBJC_CJg#Rh4`Xaf?s=la!RVOqs-Y@!}x$zWM zx3hKfHLzx5%`o8TAVTd)1M+Dd1Fb#ju4R0yL?eOIk$`)y^3Y`Ob=e4Uxb%dlF5;EUz`7 zJ8d;kLi84}L6CIVN@t2CDEnlL*1jnzyhqDyov{CC&tkp(kBt2Y60$McIj?SJ%zm3B z>`gr_3Et>bRFi#|{%|{L*1Z_d{>bNk#drV)crc!Q-IE$7X-Xsk4h6MUL>+B9z!epZ zZuWJbo{b`>I}xmXI!`rwKVr|8U2;43B_SlXP{_J11eAx@a-jB|fyN0!1Q_iJEy$8% zS@}McI?d&mBLu86bwVR5*FkqQ+0jR&Blv1Myi$h>=oAnII#mD+c->Af(5V95p4P1b z-Jw9Y7wA?2I~4PC`hAuDA zr2?kff1dAAfu2x6CIT(=s6ek*>Q#Z>P(XO4K(7ic_5zDlU~wq0*b6LHfhAsGi3%(U z1(tY$B`UDg3oKQErJ;aqeY#l6bb>N7vb8vi+TZ{ym%#Dz1Z6>53KH<5+61+tr@iRu zw5WYxq@tk=R1fXc|!9CO}3JQ?EgiartkA8>7alX2fMstT>D;Vf}l4+py`R5-Jkdid~-$f3DG$Fda4R% zPc|17vnNT$dn#q2u-vU7EFH_&P-uv>czx7PH7KLbs+ZDU!lOFBZ|T}hBEY|R_8Ecg z6}&I6;eC17eR!(j=Aei4g%%4y+oaLZRf%_(b|Mp|T`_BSR58 zzCF*|^A&quu;-8L`MN!ACuYt}$+@4pQ+=SuBHZ171htRL{|))jx@8r4&MNNF zUIa;VarL+*>`%(Pkd`^lWM&8wslcr%&OWdl2r@D|x(7K^gp9Q`<-H;yZYc^W zMs3B}6Na1ng^k9r{Htpn1<9VAFHDxZpHut=Tj|tjvcnbvurMhwn%to(2J<$zn>3cW zchtF@J^AhqEbr>Lyl2&ybSOY`&77Dx9&&NJD%J;gHlD(YOKx+U| z7r(Nm5&`{7CX$8hTNw`}B_JqEqa^~ZvUZ5$a;jsf#qmdjc%3}~=BU4t$ddXgcUu1e zSw#aa>@cMQz^ z8tstpkj_Ww%Nj(6@keHX7bbd6Co^zRxu3WF~Qcy|@p<78Zr(KmPDC+EUq;jjK; z&!4Uy`^DM9%b)+sUk?0a(Pzuwh&~lXo#iNcDvF}+JP+bux_9eH)EPxN{(tnncMlK$ z?ayBScTe2(=YRWGFP{0~^uN7-^|LES-h1fefAZ~1XaD<4KmR}e&7VZaKYQe9bfp?FaK3_I;V+ub|=x3~YNouByhzpT8s^X`ieU%zqb;Xmp6?wL)m-}vT#zUFuT?a@DZ`^En; z|9^J=yBq-i4*=Gg8`2|}k2=SQ{)_CV^xOE%J-rfCcQ}L#jTwe&>7mheB6lKe5gtsV zsI!|#^Z2KY2-y5Ti+;BP0FB@(mG)$f0Xd7SlZ{s>!{lA_5Hj_3=c!Q;H z<(9LJgf?4^TPdj$w~;zd$_QcoKVndfSlfblBYEm&DO>~DltY2n<=%yO594`R#McSLgPGdxA;~oyMY!)X=BW4-)=44YVZz|zn+}+N&BLK zk8Bg|2x`H$jZzz}ZDB$2QTtyQ6$Kn$N*7#udXH*N)Y)cF$I&>W6t4&uo9N*-TG~vB zVV-Jr6D?>A!lB|Cf#RZ-a6C%>tx@$ym%BIQ4!HIpC0l=lVD$g7oIGj#vC(etm^6Ip zUXm%syP332g!UR9#%+3!GQ~Go`UGWtPVFPKH;E~4lA7Yv5z8N^1z}D1{Y}u<2GTXN z_VI6$=Oi)bOXaVp-d_Hx#eJlU`_<=0gJ_i6`d=Kqk>`5rP4wFcbSg8-dy4WUTJ@ic z8KKOS^|aaA8KInJzGm7urBrf)w7sMVWz)u@!=u?Z$-hmM8X;{T|8Jm-XrYi}MI%+N zFe+S0K9xw3%+e)=3Y93W@l28CIi;kxP1c9{68^`n_l;3!8S&fskN^0OpV#9r_4vom z9;I<~C+aNlD1^Ht|cry3$3R!(20%R{TtqKN;QmPj$g-x8L^J zHnJ;0v+%W{*3NYFrK=y+!tKnz%(kGrVopHUkA%zl(u;?5$xojrhkGoO=0nt{hU z$KbD=R8_{v;rAra83G0Mpp_*jE~ja!dcT?*QfQAJZ2ytZ(6v8Yxmk~Gws0gVf#M;H z>qJB4obu&RuN>E7ZI`|`vBbK-8d2igdJOZZjw$p@J*M=qp4DmPJ*)Q^!RjVG29$Uz z>6R5=UU6kt&g=1x6<4r2sQ8Qh6gO)YEjWn6|AmNaFxou)yys^B=T_BI|&&! z9s=y@^@9C*(HR_08^Smwuk-S9vVa^vFds5>d_9D9GTkr;dcrt8R?dCX@onW<@p{sX z9E8Lh1$fOCT`v)<->h?=Rj5H1E)Tr+OvvA%DtpM+%q0RwH*q{ z8Sc667FRWK>};nVB0z129_M(}wO=^%%^yif3MI@dJG%DZ#ci65ss_R>9Nf! z0fzXvvPnro@tJK33B_mhsFoE1+4znWI&7$ADEbN~g!S2tO1z-QEwpPV*92tsO`A2i zlN1rXt2_13R6A2w=+``Iksda(mzD8dJ-)BUk5;xKIV-Hv)A}m;(-mG4O`Gu#C5f37 z@>Tq2JgOrKz00G1S0EdnoIr5SP?I&+8R#sI(izlzD8RYd1o3Qs(#Y9(q7+SbxOg#(@B%lX3QSJ91AqCna=2{NhB?Z$HZ9?nZrxGYQ*v5pkDPmmj z-kZQ}J`>!9V`)0oI^U;5$;7m}o}-f(Dq z1RqFlDHZI9s$H#>iE+o)02_L%m;_I18wkl$epaWcbbr?KJ-QX9{Cpl~K23JfNf|dY z;Z*~i5TUq?vgFmv9u7eWv&cirTQ+RRq7>8@ExK$b7w=X>wYvZpKlNP#eYf_k{j-z! zA)pK4Qv6UdisVux`H4%~lt4THoX+ehiiqK>V453d>s@$Z_`LKTkQGrMTNVL}PC}5e zWLQU>ITY~_5%%rbUK2V&t3sB##KN5ORYu=X7a59JUeB;T`k{S$lkZJ?9-ocTJ$>tK zjjDO-s+@IYTs|z;^#FYw*yQtT@cOPIM)`M*Y)>rF_aMQ@?t$g>p(vw; zWzHkZBJQkFL2hdzud*_)mlVJdTaQNaioT{I?Ja=ENJTJIMvQpdL?(OOWbvB}WV70p zv&(C5wY)8S8P2%)) zAf=OU-uNbsHj2hyl?TWo?}2`8fnjSupo99RDN$F;B6_P_-;7fcHU}3xz%f^v<%%pP zGytIOHn!o?9_F3)L81;|WSCr!(+{8Y4;GiOdB(i*H2N!&^|46beAC5`DOjQ43StDMv?^PA=}Ipj;082A#ve0q{J{ zx-S{xN}YhKuQ|aXlz{XP8OlT>zz#9yS>*z<$g*tlpz>QN$c0d#RSQ*r#zX4Ad_H4mFfp+| z)COY9&L4TOS4Az+q@1peVp^>-{?&9OuG88Cxre6wt~JBBt;WhBF{w&ri!j?jr{<>7 zj0F!%>A3t39L@k9Q~&*p%%4>I%OyUrRM%#YXi?==; zKeR;6z(XRzW6pw}4>kz*;fF4(naiUTxkBIa zXzXO}NL*CzL~Q<0Ivdhm0Bcw)9^fX!B*Yg;_BGHHMPIdfVOdj@hOMk7VJ@nqyqB4_ z@+T?(nw7Dhw@5FccRGh9eHEsol#~|$Ts<>3F)K&u?G4hU)GFtAYZ9-;`V$H?eA5HE zL<|Zm(XJD-pxwc6wpR?G$@W%LW00n1RaoqycfJQDLg1{;jopkYnZL0ZITOc@ST35k zCh34vQh__glF-VCh1=TplFcdhHdCL$+Kd%$s$(XVE5l94br5pFiWfI?OCSooKgUxs>rq`HReLXK{g#Qr@K**R*X}&{rgO%t$CQ5?G^PtRX?j^uT~XI8@PMAj1OHA~~`p zB%Ta?U>`h`&!&ib%q$mXiBr@o zJ=e}*z&68$_#xw%w9y0u<#%Cf#E4BhWXSJ|8m{lk}z$-4*!{CrlQf*gn9j1yPR z0Dtn`Hs9l$^%TBOEiP6K6H(RVCK+yn0TO>cVAOtqyI|-yuJOG9d3Hq%oX}*K>xfvT zUpREh>yqKEdI{*j*mazDw|7hmER}PM`P%G0{O0G}E1jWQhYL|a)ndBK1jfWt*Co)`PF#0Yy%76(DNe&ojCE$u~V zTw4IezLfl1;)Gh+@L0AfQxZqnE(uZfi@IHQ zNT1>zmd6=C2nP)h_vy4DAMfbuiNnljVj4sJlp$D`KC9KiVqYXJVD0zEjTJ(g=wv-` z*@m6eHEkvG(GoYDcR))R?dc8*t4CzJ8oMa&70So?v-;JSY#o^ym^&HCrwY9g5Q+8O zHZJ08BY9Zip6YlK_i^5DfbX#yEE zmVHPE@Us5`j=c{GvoiKbh7ae3WH>Ky zje%O#tykJ!pf1y?C~k&gOe~v!OX0P2+b1}`HJ#!6-`J^p0>3LFfsvecRft0ho2fM> zdTF^!8^ZF#**1*U-=0Z-bPI$CpTpKH#oV^89~X0ZCew&x{ryEA?D}wxSvcl8ElUT{r@$&D$Y4dqg$YUdi{`SoL(-pM6^SCV%MK{^ zw3s}^bb6ZW4ty+!5fi3JpU!azUL&eJZLiu|&#)8L(l_kz`)BH$WS8lb#58_RB%tp( zE)BnPFu`b3+YbF}GNpKJH^MYt={H3m>!VV2#nBHTR^OkSwB!?XwYJAnHRBS+vBxJP zf`Z)<1}-h3cODHO8uH907nQtXINxQ3EM~_OuFdt^)|1M5LIf|z92%ECl4uks$gl?F z>l40+D6p$Y&wAkv!Q3QAT&1@xN|?+j0aGWRwrdo#PuW;rwy-&zIGL{A^wBe;*LN>S zM7{ds**c?OU8Il_!6m_y%|v{g;zs+^Cdxka2Q2v%R|X9}6-QL2!jYz#Sj zD-%TOJ8}M`Tos}~vmK=wEPU0j5zTEgYeAox^Xb7Zz7bX$5%$6;Xti1Csr7zh{rS** z3CR&zi6Y(w%Z7`RRvY3MnY4!c{kDHdF4S%8$>-VA1BCA;Q9w2x*l&1r>hJ>;Hf}Ex zSN{%{&`0A*6?1=tnBfCJIB@f_4ar`D2&^QPw6lk{qR)~BUXF*H~^;>17UFJJi7v}WSV+S3A_FBwnUQ0G*&pUWiYb~!AM#b|D471=D|TXR0^ zsSEM28Gk_KrEm6^lcuqSmFd|BM3^T8r~=NgvP2Av+^Fpgfm_5~8hLGJGjz++q(M(_iQNJY z)G&X9oPIWkDXT1A`~etGb!{)3u@8`_FG%PnDP@e^I8RgTTQdav>|5F1egVi7!i|nZ z{Z`<_fH|5&UCJES*V5M3Y@Gxx?Zfxnw#?`2>Y_48mTpW&MK5#F7OBNLM_7^tqE@?jT+zW zqXQwl$tXmu>&7cy;uYKWnVmwa71gnX68q;4g+(NhA}k+%v4fiWikO!^A?^Y8S>zOB zM>lBFc#uyd=iHU2p3xD;?Y<)7OHE^Ij!SX6j2wzssb0F&;R2NhS$sKZ)}7Rk=9S9V z7e~RyYV7KZkY>QgSa)G^*_hlgZ%Anx#<5wrS4PZL-y=k$SnGQ{XAcpLMh2OPQ{N*l zL`K`F@EVjj1EAkpQ9YvkhMor+e@FtgXZ;gLn=kR~%Ubg1QF6V~cJ^sz;Mp1`(m6E8--=9%zMRuh)HlSpyws?dGIOuLH`(B~``qz5zKtqo z)u6>UG@ue`It{~_IT?woTugz^RfcDIA;=tvG-uB& zt@;Dca#Y~SgDi$_WS5taE$i%8#KfgG_HFI=G{%m9x{6S|_InEO$$YpXt&^Bw!oBH^ z6qwV@EeUPXd18A4E4GERI2JlG*t)Y5WzwA>x_T~g`NR#mYfu{}oC38I%%8Y%(p9sC zPi4a8Ot_v2KjC3#&ZiJGG)m7;Sp!dbCP|2YGot5`PQNFZ^`SOMWj63f0$0Ku_XOs= zR)xAFrgIISUFwnRSQ8ZqaB73cbk`czWD4S=BF@<{o}BpNxm%Ady=#PO?a369kQaQ{ z3O=z!iQ%Y`k}50dpifn|>2Z_Qm#kl<=q@tz1USK8NP2k4YIX9|E;wZ>cUt&W3!hvR z`e#?X8SG4h1zIdv(Yifv?$(Gn)}og7+jFg+)iDddEhvuktV#CR3bw~qpy>TwdhYSs zk6DdPR^vU(IMq?$hc(pBpjtR>LGSmi6qpN^{QcenNa2&YFN zdfrdpTotI=wiZ0E7TqhM?2A_DxD6fugB43$4$6MUvY)VLJ#A#p%fBFW%qWxfZL^0{ z9`yBXGxZy3ftSI%YW!TGa7+(LHs8-=*W z%?1+IpHyb*P??LD)WlXn&x;5X+@5;^R`P~$Fl7{BiKa3y>&eA9dY-hWG1u&z<({{c zB|K%gQii)}cydpQp3mwzYvjTx5jx!XA(>O&R-~dZmj&o)oL_s*(i@iYhLF5U34HNR zk?K|r)@8be8N9lVK9^aBb(2}DG51&@7Zv!lC*rb7zVF$c|Hzk*P8|N?p@Z8`PL>WI zpFVVO_x_`Y9zB+$oW9GAqRM10syukx#IfTCO6zVrbhNZ?cj?&iV>b=$IseK#v?j4<=t+DkJ8%H*emBz-$CWl8it{)rQxNmYpsWiEM!`Q~Ly%U>C;}h#Q zjjkUV+c-5kGB&z-Q)z79=7|mKNA`|P>?@T!rA@#!HZ`_yN)^Y~ZycW5I1EJNd&f3y zT)$~@a&+_5@aEA`+MAfzI668(Pn#zvhDZ19jiN4n2(2e?o?w1QF8b)YFK*v``_YL< zN{=2o`qi8Mv~=_s^tt70W9!DDT;Gaj*0$+mhYw85e36o|>I^k=hA2Cfi$3P$8`^dB z(4Utkj}P5;=-~0A(|b=GKXmk16fMa`JzpvvC`}wIMbTZk=#JYC9iBNl{qX+dLu)2) z9D;;nYe%8vP+Kc&hxY$p?Hp@V6xaD1g5V=cg!-zFOj?4VFvvrcmx4S50zv>64X8W2 zGb{tMGwaMOh^vOA*0h@HF`=n8rcE?CHWq8r;HkzS*7!`xOQVTFPt^3(S1Uc9_%5d3 zomtpL*Z62p`y*b??9ANz-S2(B@80F?r)iF)=;*q-I>xFyh{GVj$cinR1}LSV&^?KG zP9!ZzR?*1`l8w%+msq=CMULjxN7DJS%|?3DEvlxlR^o>$%}N}dDd;b(QlHMT4vkj; z`clv}X+{ zwOXADtLYD@bHO5rf>uvkt9WY-YNC6&Ic88$(v89$gH*;d z(H$Uf?a9V~Dl7G4Q!t2OOr644v9$t5etoeZZ__Bqy&J^&f~ukKk_>_o)Ewi3&k2aG zh=M2X2Hgz1$lz7LYnbRYR>zjB=LeoEt#|N7h{G6HNI_mVLfn6JTh5p6P?zoyfjs)+ zP!Go>+X4(T;xgF=^-mW?xvsz|YJx-LA(Vng37PK<>-}*np_eT@7bA6Aasfm00!Q|I*C`j@eZWmVVzhv zZ$uoeO2F-bnSyd$ZmNLdU{)h(+FVkP$UJ+9y_AteG=an){Q@oNdTWd;0!EWwK z7PMSRn@O)(&*=&;Vie?PBC3i>A&i0sw1(fUW+?UR<4%4&MP*@Bt5XO5aid?;h@)384+$MqbbS5WD~FZW+O`#P z?`=659MaG^@|En3Q7;_$)YPj_Vrbjh%lSEM$E7i?!q$jUpR7we5wd;Y-_{=-IO&C) z{LB6od#?(!hDBQ{5_Y!s)1nTpY5sfjQ^J%La}PDOCg(buKZtCLH3dDN{m!|(J!=O< zB)$(>C)mm7ulxOe^2|eHmj5ESGwQeF*~Ve>lV6N(pI~cPx75^o$f^%km!1U|M(S>1Qh z;lZn#VpqH}Vr9dTalINZ%|4d3=C7`lGb0+WMV@~ARgO(bKJB`oL581n7A}1JMe43b z)0s&bW0Ur`ef!#nk63C<+#6p%ckJSaqvibPLYAxuf9Bbvg;)HyRKMLfy6wWRfAaI! z2VB~ac#U2*xOMACUle4Rr z{_@LqDQ5b_V<|BgYc|mnul~8oX`i*ZU;ee)>WHC{`Ppgt8~4}_ zZHy`(Gkte<>6zzV3rGukv^uqqz3-L8rLVulPmC@bTr|7o#?rZqqU|sJX4q2P0^xDt z`NQjhDkviEU5;1dfdFW1CdIalMvf^Vc#X!Z1IIeN#s~x{9OB)IOEOD>_H;@~NvjH< zeQaj)^n=4OaR6i_RXB{Df?8q4b3uiwSS!48c!g}Ku5h0@DajE&hvN=}=kXnF z1S7incIY$f(GsjK1JO%Q{)=#q4AnT7;5FnSk`jGcP!bJC6NPJO7%U^kV39HW+6+AuPnNpQiBuBuFM3JgO~X^% zkwHy}_y^F8-iqIsAq|^8lW^fcT@h|=Kx%3cJ>1+!LpVwlfm$#MJH|tl{zTr0X1wiw zv)-Z*!gsAMtJgdSa^TT6qwB_o)yQb%Cr6jL(9I+92_kcszR4T$!k+f?CHq9(P6mG* zT9DZF_V)MKXPj=Ip7UxMGRLJeDPM#&usPz=QU`*T5$M=oJ7W Mei!theg8D@Z_nK1?f?J) literal 0 HcmV?d00001 diff --git a/Assets/AppsFlyer/Tests/Castle.Core.dll.meta b/Assets/AppsFlyer/Tests/Castle.Core.dll.meta new file mode 100644 index 0000000..14cc646 --- /dev/null +++ b/Assets/AppsFlyer/Tests/Castle.Core.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 7b5b4579db85b4cfd8395bfb19aa309e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Tests/NSubstitute.dll b/Assets/AppsFlyer/Tests/NSubstitute.dll new file mode 100644 index 0000000000000000000000000000000000000000..f32e491936a3886139a7d13e4b3b17890dc1a3ea GIT binary patch literal 152064 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 literal 0 HcmV?d00001 diff --git a/Assets/AppsFlyer/Tests/NSubstitute.dll.meta b/Assets/AppsFlyer/Tests/NSubstitute.dll.meta new file mode 100644 index 0000000..b716f6a --- /dev/null +++ b/Assets/AppsFlyer/Tests/NSubstitute.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 642cf65ed2573419bab7e7d44fc73181 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Tests/System.Runtime.CompilerServices.Unsafe.dll b/Assets/AppsFlyer/Tests/System.Runtime.CompilerServices.Unsafe.dll new file mode 100644 index 0000000000000000000000000000000000000000..c5ba4e4047a15b3adc61340c781307d9c6e89413 GIT binary patch literal 18024 zcmeHu2V7Ij()gYv^bRUTN+>EKgcA?}6{QMDm5zcKLVyS)m;@;*Lgb=Yu_1~|v7lb; zT~S2E-g_4-7Pz9qwd*(MB!S$k-gm$M_ulV)zwiAIp4pw*-PzgQ*`1v^F=%utq9TN7 z@P7M-&>l#M$DM?K4GN%G(`=t6+M#mRd=D0Q);uDWE2L)%_$dNb2A$2~@%SQoB8M)> z;?cQ0x_3x8J%gXbVQ6TmT1i=l`XCgDQPINyAxqX8N(ea) zA$3SfA#W@#`dbOTOLVfjGT?r44H+U%jtKB8y#PQNIaZKc{-Hzf41rL<1|lh&J7g5$ zHG)^}aR=!c0!}&~DiX31G81z^@`Xh9xFh5#%gfR&#Js{o$VNd5$h!|hLv;{RA*tOU zlrEXtZpx2y2@e^!2i)nG@^zo-qMNH%UdnN3(w{PA!Quw8Hi_^Dp~hubVA*Thp2Dx z1HLlapV|}TAMusaF;YEAzEF`0>q7$sMx#SfRkR_-DBB7Yvd{1Ft~Ji>o&!?%Nm(T` zb9rq*WeR3~NrF`YunNXkql`2HFHQ9rRi>0d(suAkVS^iR^|`y<-_ z9H&ww<+9@p^c9n=2eHE?574MTpee{`UF+VfnQTm~iA*nhk$Ne&´RVDkZYh5I? zu@o|;=+DuG_3hJ3fB6(xFPhC@DV-`oO(iJNIXt8-z=A>v9Vmmh4$j^>5GX9%JKSyW z9L;9q310gmR*#waw6+IuL*9eqSaAv2d_h_qGfo)C5{S6TEVf7($4?v|7oIB=aWWWT zSv(OpgTwIRXJm5IIf8JGU?P{z5i%lqLRK;-j>i!V9K^H>*g^PX~Ag?3iUfLN2gT7J;%`hKmGTUW$;YaR#Q3FmslX z;phtF!D1mx-$;LNNFM_p0~2rQna(HrA|99*EV?H}S)~UcANx2Wupz`e5Gb*3MBX0W zV0g9Q^@5k6$-kCT9A+CM=tN5!I3*QPCpW1r=?;S=mhIBw2CqnT0E9wTLGh>&t2Gb(CZ%N zl9~;ad9cf^rPy`A6p?!uRt~EaBgLLls$rf)UD&U1%9Kj6mz14I6IDsEPRc=8g)LI- zE9Drh?@=kHKs^oEjV|m8(nGCM%n-_YA)19mGDGSWWQdHVm@V}#+(z&&>QQWUc<+D6ymr-;Z}f z7oCD~|C{;6a`ol&|8qXafinf2Bl+JY^AGe9k>MTuNrRfl9>LyL$geB$nkfvVJ)JK~7N>hJn8X!%Bq-lsW9VJb}rD-Ij zI><>fIYWc^Nm=QfVdx)R(valV#u9P)Jh-8;a>$&}Lj-rI#4Hg9G1wx$07>t7L}jRu z$W7;pa=Yuu`rss|bJzqYE)Y|l%9?8vSpOs=cRSv zDvkVwVH{Rc2rpf3c7kEyCUX3FB2EfN&@G=&Mj|IENnYY0E?dAC@{>j2AtZ4;c&zkX zAyl7gR5aBNTCYq<)}@#B@sN-PMT21XT;=b3qCL z3Qyx^`t!IV6wb}#ge1c(X6C}(o}Gpgb4464K8&lI*3E@zBB>@6frI0blqBE?g{X_% zUDHE|_|RV%CmBVI5b!flLA{A7lix>#w zkWzxP($fjKWod+f#S;?SZ$vr^TqTbL{BLTMteQ8MmBQo003)aKq52R3Z_U!LeZAyAl1U45Gp~IXhx(oZ44!i3q^@WYUF13zNwB5k5HTihWO%%_! zd-6Je>}IW_Wo~_qXX<)!4Con$77h#=eQ6=N?4y)rff2|MUOYmkgm4j*UeN+pCLCiv zIcyGT0wPic{A?kngCX@n5Fv12GMpS7m=NGo#gGC)f$RVb_5ITk_mhwXgf=nMlM(C# zyBszg5&n?b0+696hSa1n4npN=5dt`wNUFauLcq<)kfRR7kp1EH^sXb2?!^~m^5IAa zv&Ep(L51n$Mi$cH%z?NGCy9ZO5p@2;76_SP$f&F6@FqGTBfU#Vh=>r15BDuhTN$mB z#-9nwK_X8la^F9)I5k2EAf0!5dJqfF9MWiTIHUm~+I;JS=BH;m8$ z+N-aUd$b~YbGj$AkwhMcOBoR?iLEdHcmsj~R~8ZgA1)lW9N@`A$zb@1$BH;0z-kMi z1`i3LoP|VCj}MsS*+MgbDj3KFHVR63DCGy7I!ONyhjB~(2BJh_4xpcY(AEq1WxyW? zT8p3;1l)2V6#*p!ytXiuMV4^MI)wK{)X$X43l{;XCqNScXG2a1Eh3@55M)gToOl8u z{v+!rlN?Jf%p8m4N0bMVZ3V!WF!{;QGo9>30KM?Z(RYt}A}O@Wr^|5>0#!h+ zghUhIG6_8+luwR3L|T*3PGa1$IV3Pb>;Ad=CO>|6I0Z0>0~4B+1X|375qHn}kMwR6 zjD!Jod|=lhBnI#E&+Y%b^0IZuVXOm@3%Twbh-I+hWx<~_{BdBv5haQ6CIfUN%UuBy z+L8=$UXt6CH^=_Vo+Sb7Gp5yLii*0Va}I zRR<_yG)(MF!Dv;%cp$DXN72Gns2HlE)ldo$&iqqb8oerW>D$iTuRisAit&|q4t5S# z%S!2SVO&$*q8GMHEM~l`5^J>MVnrSh{Z??KI)2aSa0kx>to@z8pmey@^J5LF*S-&6#N^&u zu5w_++%qGcL$(%-8sD#zT`MTk@6De}-|IE9Z0Y#c14;LyqkF`?q1@l}I`FXlB89_! zn{Q>+c#d0LwYYkQ=KP~x%{rB>+Y>2k%hgOXQeS-DIefas^Ho;CZgtmM?7kKzES^of zFhuprizc%j_Ej^>l+~7u%DL&XzNy+^*=_#vS>u`8-&|dwy4(@%eq8-3)cEii!5O`G zVG85s290eld2p~WV1gp``MHv13um!*?NDQC_gb<=bI05Z2b*s72rON#;uY;S(SNg> z^}<=S54H;0?T=J-lJ@$p7}<6-g3GKJ@aekQZReXqc@}A@)BJQ2#Q>NS6f&Cy}V|wVYLXx*iG8#iiZ-#Iy8UWceM}h#q5vw zBXmJcPtK1E$s_`E;Kd2)p;;V(h))mWviZzjcn_kgf}X~}K?5Be90w4ItD{6BOG2W8 z9)7%}C!q?L#T)dUoh^1|tUHxOS&T;zU7FE?@BrMu%D2j=*eg{e${cKOpPik}$moio zvH2PHnQ2^prqG@(NVkW*1Dgi64D1$Svm_9}4tKW0T^LY~vt(n&Fj^!Yj*pVzIHlO< zA9eu468?iOM7TO3xE_Xmqfy{0|Hrd~DyCp4X4;3Nq5-v=nZAqa^w8?P?C4D+)Cay@ zG|Y0t!P)!6!*eS>*k4jvY&y*rQ%zmkn6~?7%3Ip!sL|U}TrNMUnXCPDm)SYjb0^lk z$@bYedQT0Swt2|1dG|(JwqDBIbE{y5!1#bysc!4WVNCxaz8|OLSed4Rka+;un-QdA>||bK6+AvFF;!ubw=ZwXy&3 z6@KfU#w(4(Cfl&UC6T{u+hv+v8%CA292Uq2Il{m_)6a z5lQhryiH|`W1mvyJW)AwY*1xdBp#c$R^`~zszGT1HN7Wy7%kMw+OgC3BMlcT<>6w5 zM2W>wWoedPBCiBgd1X-pLsK~8UviRzoglU(Rj+@yr3vH1uP41gzq!d=HpETo9$BJP z2)2rHyKD|v9%tOe0e5o6T?v~rh(wtcOXS^L8SKX^)#J*;iq&i-bQ_k8dwwB#x_l55t z-BZ%I8kf7qzkiFy!79D%gNxi=eR?!tw6pjmhDZvU}2+S$c4cT=FliD6s7ej+$@o)aQsR zFKKG{zU5jQ4K0gKckH7U&v}>7ej%)3_M++ahs;HN5)7<&o#|)o(x=>YADw=URZ zY+1WLxs_!${(-gsii8;t`@~;14;U79bZ7K%D{A}2yfOAyEgxmZYmFL_z5P9UP+vz8 zC)_^NbNhkbS0V#iT&uO7Tl&` zI`@9-n99wc?`}zc*tn!{Qroq*fENG$wR+ZTYp0|XJe`@Cld#Rc=z8?>xQ1+N>(^}= zN37@B&U1GTX?*aDcgazez@{r}yzE7b-|^n(&|_@%;>RssHY~)k=+>4Q`uA1_ca&|Z zA5oQFeyRD|jM-{3bJzyv@Hwuns3N^o_QYs#??ZC-?}x_7u&Y523QgTq6#^<*;O2QD z5As%IqD3Rv6ysW5XTJhY1rzWGGbgYcOktLK?d_ou{NP3HappzKl7aYWiJ1dSgojiG zRRt9LORW%CtMAPmY2)BG&&1a^(h|YGgH6j?85L+JXnT< zvGe>ZV`tBnS-QXAFTx8e3E}Cq!XZ*Ca8hc;PgBxU4%0*30p)x+9Et5}z%! z&xBwxOOVUX6f#mp8Mu2F0}4LS)PZgy7bi&|<4);hR4NzZd_*jah`bU0wm2);Hx%@tX4Hh+HGaMi#+yTQU~&60RdQR$RfBSIr@s4tj&$tb}1?NHBIVHdW1NqaO*iP68} zsax+gS9Y3YFLHhOJn5vjTTY(kTfHf3OGVS>be!%>8DVpHruP2T>lM^1+EPEJG8R|a z47W*(@n@TGwOzRTR&(=G>m}tunr>=u zluNFe9dR&t*xqD!Zp_LZ{;sOWR1Y89xarBZo40$;808b=;xM6~(bTOS{odcR9Zctz zZ;LHSjfpN9oin$`C#5uV}8#mKD85{xZ7}69f=Q1EIwkw z9<-$R{;jv~-}I_p*6+dDHA^o17SHy0G)8Ip^kItGiWe2PW|{Rk$YSkmzjLfN?cjZn zeGxR;(HBlWppB>{3llWnP}e zN592pzkc$yEa+VMz9DUQz>5~Uc2VaX^?st5z;q}`7lijO2 zf-5gy4YgZj=6&p71P}L=Yp%{5h&xpEDA4^r{8(*NVDPg&Ex+x+64S(3feH2WFLj69 z3=9vqt#zqT9#b*(#-q~bO=s;?Ua!U@HO=daj>h&qqqJml(#lzlelGL3S@wHsqPoXK zdv50L8{(+wlJ-v?WidCec3fNXCN#CQIreeOgagGDrJdtKJ%fw$Lq4`ezVZLC^=UG1 zOrqM+t*3(L)xBxH5vb2v`+CQ(nHk)I90QlhadTgnl@1>DspgIL!pSeA_l=~eR8F5- zkrO*6Z=F`fvau;q6^*HL4^2CH+_SD#UrGN-NmjUi#KM*L3nF?AJa!^3yESpky%nq0 ztvS1JaVOp8ddH`psh=nP!fY^4Ri9U~-`$~o%(>avj94#r$x27l=T9^0CtRWpTf(S& zrW$#6L&MEQy&uxeE;r<8d}V}qF|6_<&pL#a>hY?!g`d^72>aZrYfPV>_^XAV*Q)!!H%` zdAemjO*Jih%$V%;aWSocBK;!>#?Q>=RtXlJ`L zgb2mx9t6@p3P$}t6eGq)DXPh|P#dB#V$2=Zb|{!s7uZcw)0@Ox?Y= z>TUnrqj~*W=i?^7R23_6kI{z? zBcw-!htqw+g9m%~IC$ClI68RRF+E0jF{SLN^6VnuSK)TyB34EwUHZMWN~{U>Q)!v-Io)qvd-(wx*_=tLGGY8R>pdzj8bMSsi0b1gn0@=H2Jd_qtjdsG|PW zr#H7_)12{xovSQ7Pt3_0ynbE$UiI+&BjQv&aXTmSTjjs`^4j~iu>l6 ziEXY}ovUnle5{t*$h8s9(MhOe>*$IWDxzV(_kc|`9f$JEikWJKaolG|_y4q=}v2>W!! zWd7c57_=337bq$b_QA=p50ktJkCxpe;U-MPkVndJxCsyYnHeMEO5Hc%pYZ;3yho21 zK_8krt}5$-s{E(z3xQG$CF_^O0EWWG*O^rRuU@$(*w+g(3oPBV8C(uU4;To|=* zl*ne*=dY17=+-x{TbMd$?T^{%Rb=?GSI2u3->mtgw71vjD|Ku$xp`f0rC+qtw2`Ov zUbN;+e(%})neMO$om)Of-1}ylIjwQLM;{2gPk@6jRu%+NDU|$&9Lk?2>wixWggp3| zI7B_*Wre~1* zsEb<56^Erv?MyyIE%VNQbs^vj@5!=LTi3nGvr%QX-wIZoziWoF)3Y4oEzg&p9ok~= zy|1?8PSSzZSR-9!Vb0ml^@mP+$B*r`98(Cf2$G#tPvN9`_?IDoA0AErln}tx-=j{? zdsY*dn0nD|QR$fL=av~9{huCsT`s!x&>Lju;P}rv^nSt{T>mQKoP*!aeWQUBRk#2z zoc9OszYuqmoqyo{GkZm!>%_W1a@-%sTsegN)mWij-88+A?Dyx9Kr zyS~sKWL7$i?Dr*dv;EgyPv$!APfS>LJKFvE>vKz!OJ{!@pE&hy(@3@XeIL5E8jhU6 zUNOl$2D(SV4RjYG)*$qwKWd%(a&emRdHDy}+gCP@C z?#GMDEtFZewuGAU54?VW?zb?NRxcdhl?b}0nR23W7@-2PgTl*27VMCNsDBo+GTrw|ne$u*}C zU*5ZdCWQA&sZzz2iDp!#YI?OSj}=$RUrj({YGENNnxES@X>fGe)ZoCzXqBPQADKV= z_;!l$(UIVC*G#>0wgz`+?yFBJEPbeOV7ZIom6!ReKFypZv`w2-;$If}s(hLKnGC(V zt{SJt#BO+Dsc-Q`d#rP6J?=Es$583pipl{oYFfgEwl|A&_uWi$NS-t#X58oTrjM>? zxIA!Y?{NP;R)Z;~YJl&kLTdEFfA5Ntv8*4tuJW-gF*Xu6>WVl(FiYbPF@^8qRq?Uk zc2`^zx7r?0&@Yd~K5M%-{a(^2i1O7^+a}CVt;GvJ$}ynWGYenfg)MmDW4!PHjlRCr z=*8^Z>W02%Pp{kwZvVh8J{a8)-WZt|5>?Q6JM{)$SpL6YEBtukAXxWouGK~KYsE3@ zrS^c+Vbi87VTJp*Ur3F}O#kG6b#iQ|yh1`;0D>`S>9x?<>I>AKm)LK74&oi+5$o@r z^XHB%S9lau+%Wyh8$;^OCoX7n%cIFPr6C@X%GvZo5twaSLAxmX@Q~CiQ;y&3c%)-x ze?|GN|Gq$txKRzC&8J-*>7(db?-j_kvd{_$AKRR?r}SW6<9;UloA|-xz8`j_M6Tei zd(f=VhE-OtxIOL)r;>5AsO`qlmW4wt#4|=EK0R70cqLMP-T(Epr$csFpRD~B6U?it z*IjiYkIvF_SFL~f?$xZ}Lzk(zUCVdy@>s8*r!)H0D-{KHkBj$O_rG_X sgb{9K#j|kmwXs@qxw(vy^6;@AzjJ5N!ov=`F7)MpD$l8B5&@I{0va}jJpcdz literal 0 HcmV?d00001 diff --git a/Assets/AppsFlyer/Tests/System.Runtime.CompilerServices.Unsafe.dll.meta b/Assets/AppsFlyer/Tests/System.Runtime.CompilerServices.Unsafe.dll.meta new file mode 100644 index 0000000..fca3770 --- /dev/null +++ b/Assets/AppsFlyer/Tests/System.Runtime.CompilerServices.Unsafe.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3a5ccbd864ba94a9a9ba47895ff14922 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Tests/System.Threading.Tasks.Extensions.dll b/Assets/AppsFlyer/Tests/System.Threading.Tasks.Extensions.dll new file mode 100644 index 0000000000000000000000000000000000000000..dfc4cdf62c8f7c243d694ed7b96424d3f2e457be GIT binary patch literal 25984 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 + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.startSDK(); + AppsFlyerMOCKInterface.Received().startSDK(Arg.Any(), Arg.Any()); + + } + + [Test] + public void test_sendEvent_withValues() + { + var AppsFlyerMOCKInterface = Substitute.For(); + AppsFlyer.instance = AppsFlyerMOCKInterface; + var eventParams = new Dictionary(); + eventParams.Add("key", "value"); + AppsFlyer.sendEvent("testevent", eventParams); + AppsFlyerMOCKInterface.Received().sendEvent("testevent", eventParams, false, null); + } + + [Test] + public void test_sendEvent_withNullParams() + { + var AppsFlyerMOCKInterface = Substitute.For(); + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.sendEvent("testevent", null); + AppsFlyerMOCKInterface.Received().sendEvent("testevent", null,false, null); + } + + + [Test] + public void test_isSDKStopped_true() + { + var AppsFlyerMOCKInterface = Substitute.For(); + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.stopSDK(true); + + AppsFlyerMOCKInterface.Received().stopSDK(true); + + } + + [Test] + public void test_isSDKStopped_false() + { + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + + AppsFlyer.stopSDK(false); + + AppsFlyerMOCKInterface.Received().stopSDK(false); + + } + + [Test] + public void test_isSDKStopped_called() + { + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + + var isSDKStopped = AppsFlyer.isSDKStopped(); + + AppsFlyerMOCKInterface.Received().isSDKStopped(); + + } + + [Test] + public void test_isSDKStopped_receveivedFalse() + { + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + + var isSDKStopped = AppsFlyer.isSDKStopped(); + + Assert.AreEqual(AppsFlyerMOCKInterface.Received().isSDKStopped(), false); + + + } + + + [Test] + public void test_getSdkVersion_called() + { + var AppsFlyerMOCKInterface = Substitute.For(); + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.getSdkVersion(); + AppsFlyerMOCKInterface.Received().getSdkVersion(); + } + + [Test] + public void test_setCustomerUserId_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setCustomerUserId("test"); + AppsFlyerMOCKInterface.Received().setCustomerUserId("test"); + + } + + [Test] + public void Test_setAppInviteOneLinkID_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setAppInviteOneLinkID("2f36"); + AppsFlyerMOCKInterface.Received().setAppInviteOneLinkID("2f36"); + + } + + [Test] + public void Test_setAdditionalData_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + var customData = new Dictionary(); + customData.Add("test", "test"); + AppsFlyer.setAdditionalData(customData); + AppsFlyerMOCKInterface.Received().setAdditionalData(customData); + } + + [Test] + public void Test_setResolveDeepLinkURLs_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setResolveDeepLinkURLs("url1", "url2"); + AppsFlyerMOCKInterface.Received().setResolveDeepLinkURLs("url1", "url2"); + + } + + [Test] + public void Test_setOneLinkCustomDomain_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setOneLinkCustomDomain("url1", "url2"); + AppsFlyerMOCKInterface.Received().setOneLinkCustomDomain("url1", "url2"); + + } + + [Test] + public void Test_setCurrencyCode_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setCurrencyCode("usd"); + AppsFlyerMOCKInterface.Received().setCurrencyCode("usd"); + + } + + [Test] + public void Test_recordLocation_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.recordLocation(0.3, 5.2); + AppsFlyerMOCKInterface.Received().recordLocation(0.3, 5.2); + + } + + [Test] + public void Test_anonymizeUser_true() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.anonymizeUser(true); + AppsFlyerMOCKInterface.Received().anonymizeUser(true); + + } + + [Test] + public void Test_anonymizeUser_false() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.anonymizeUser(false); + AppsFlyerMOCKInterface.Received().anonymizeUser(false); + + } + + [Test] + public void Test_getAppsFlyerId_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.getAppsFlyerId(); + AppsFlyerMOCKInterface.Received().getAppsFlyerId(); + + } + + [Test] + public void Test_setMinTimeBetweenSessions_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setMinTimeBetweenSessions(3); + AppsFlyerMOCKInterface.Received().setMinTimeBetweenSessions(3); + + } + + [Test] + public void Test_setHost_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setHost("prefix", "name"); + AppsFlyerMOCKInterface.Received().setHost("prefix", "name"); + + } + + [Test] + public void Test_setPhoneNumber_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setPhoneNumber("002"); + AppsFlyerMOCKInterface.Received().setPhoneNumber("002"); + + } + + + [Test] + [System.Obsolete] + public void Test_setSharingFilterForAllPartners_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setSharingFilterForAllPartners(); + AppsFlyerMOCKInterface.Received().setSharingFilterForAllPartners(); + + } + + [Test] + [System.Obsolete] + public void Test_setSharingFilter_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + + + AppsFlyer.setSharingFilter("filter1", "filter2"); + AppsFlyerMOCKInterface.Received().setSharingFilter("filter1", "filter2"); + + } + + [Test] + public void Test_getConversionData_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + + AppsFlyer.getConversionData("ObjectName"); + AppsFlyerMOCKInterface.Received().getConversionData("ObjectName"); + + } + + [Test] + public void Test_attributeAndOpenStore_called_withParams() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + Dictionary parameters = new Dictionary(); + parameters.Add("af_sub1", "val"); + parameters.Add("custom_param", "val2"); + AppsFlyer.attributeAndOpenStore("appid", "campaign", parameters, new MonoBehaviour()); + AppsFlyerMOCKInterface.Received().attributeAndOpenStore("appid", "campaign", parameters, Arg.Any()); + + } + + [Test] + public void Test_attributeAndOpenStore_called_nullParams() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + + AppsFlyer.attributeAndOpenStore("appid", "campaign", null, new MonoBehaviour()); + AppsFlyerMOCKInterface.Received().attributeAndOpenStore("appid", "campaign", null, Arg.Any()); + + } + + [Test] + public void Test_recordCrossPromoteImpression_calledWithParameters() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + Dictionary parameters = new Dictionary(); + parameters.Add("af_sub1", "val"); + parameters.Add("custom_param", "val2"); + AppsFlyer.recordCrossPromoteImpression("appid", "campaign", parameters); + AppsFlyerMOCKInterface.Received().recordCrossPromoteImpression("appid", "campaign", parameters); + + } + + + + [Test] + public void Test_recordCrossPromoteImpression_calledWithoutParameters() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.recordCrossPromoteImpression("appid", "campaign", null); + AppsFlyerMOCKInterface.Received().recordCrossPromoteImpression("appid", "campaign", null); + + } + + [Test] + public void Test_generateUserInviteLink_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + + AppsFlyer.generateUserInviteLink(new Dictionary(), new MonoBehaviour()); + AppsFlyerMOCKInterface.Received().generateUserInviteLink(Arg.Any>(), Arg.Any()); + + } + + + [Test] + public void Test_addPushNotificationDeepLinkPath_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.addPushNotificationDeepLinkPath("path1", "path2"); + AppsFlyerMOCKInterface.Received().addPushNotificationDeepLinkPath("path1", "path2"); + + } + +#if UNITY_ANDROID + [Test] + public void updateServerUninstallToken_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.updateServerUninstallToken("tokenTest"); + AppsFlyerMOCKInterface.Received().updateServerUninstallToken("tokenTest"); + + } + + [Test] + public void setImeiData_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setImeiData("imei"); + AppsFlyerMOCKInterface.Received().setImeiData("imei"); + + } + + [Test] + public void setAndroidIdData_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setAndroidIdData("androidId"); + AppsFlyerMOCKInterface.Received().setAndroidIdData("androidId"); + + } + + [Test] + public void waitForCustomerUserId_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.waitForCustomerUserId(true); + AppsFlyerMOCKInterface.Received().waitForCustomerUserId(true); + + } + + [Test] + public void setCustomerIdAndStartSDK_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setCustomerIdAndStartSDK("01234"); + AppsFlyerMOCKInterface.Received().setCustomerIdAndStartSDK("01234"); + + } + + + [Test] + public void getOutOfStore_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.getOutOfStore(); + AppsFlyerMOCKInterface.Received().getOutOfStore(); + + } + + [Test] + public void setOutOfStore_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setOutOfStore("test"); + AppsFlyerMOCKInterface.Received().setOutOfStore("test"); + + } + + [Test] + public void setCollectAndroidID_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setCollectAndroidID(true); + AppsFlyerMOCKInterface.Received().setCollectAndroidID(true); + + } + + [Test] + public void setCollectIMEI_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setCollectIMEI(true); + AppsFlyerMOCKInterface.Received().setCollectIMEI(true); + + } + + [Test] + public void setIsUpdate_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setIsUpdate(true); + AppsFlyerMOCKInterface.Received().setIsUpdate(true); + + } + + [Test] + public void setPreinstallAttribution_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setPreinstallAttribution("mediaSourceTestt", "campaign", "sideId"); + AppsFlyerMOCKInterface.Received().setPreinstallAttribution("mediaSourceTestt", "campaign", "sideId"); + + } + + [Test] + public void isPreInstalledApp_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.isPreInstalledApp(); + AppsFlyerMOCKInterface.Received().isPreInstalledApp(); + + } + + [Test] + public void getAttributionId_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.getAttributionId(); + AppsFlyerMOCKInterface.Received().getAttributionId(); + + } + + [Test] + public void handlePushNotifications_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.handlePushNotifications(); + AppsFlyerMOCKInterface.Received().handlePushNotifications(); + + } + + [Test] + public void validateAndSendInAppPurchase_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.validateAndSendInAppPurchase("ewjkekwjekw","hewjehwj", "purchaseData", "3.0", "USD", null, null); + AppsFlyerMOCKInterface.Received().validateAndSendInAppPurchase("ewjkekwjekw", "hewjehwj", "purchaseData", "3.0", "USD", null, null); + + } + + [Test] + public void setCollectOaid_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setCollectOaid(true); + AppsFlyerMOCKInterface.Received().setCollectOaid(true); + + } + + [Test] + public void setDisableAdvertisingIdentifiers_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setDisableAdvertisingIdentifiers(true); + AppsFlyerMOCKInterface.Received().setDisableAdvertisingIdentifiers(true); + + } + + [Test] + public void setDisableNetworkData_called() { + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setDisableNetworkData(true); + AppsFlyerMOCKInterface.Received().setDisableNetworkData(true); + } +#elif UNITY_IOS + + [Test] + public void setDisableCollectAppleAdSupport_called_true() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setDisableCollectAppleAdSupport(true); + AppsFlyerMOCKInterface.Received().setDisableCollectAppleAdSupport(true); + + } + + [Test] + public void setDisableCollectAppleAdSupport_called_false() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setDisableCollectAppleAdSupport(false); + AppsFlyerMOCKInterface.Received().setDisableCollectAppleAdSupport(false); + + } + + [Test] + [System.Obsolete] + public void setShouldCollectDeviceName_called_true() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setShouldCollectDeviceName(true); + AppsFlyerMOCKInterface.Received().setShouldCollectDeviceName(true); + + } + + [Test] + [System.Obsolete] + public void setShouldCollectDeviceName_called_false() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setShouldCollectDeviceName(false); + AppsFlyerMOCKInterface.Received().setShouldCollectDeviceName(false); + + } + + [Test] + public void setDisableCollectIAd_called_true() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setDisableCollectIAd(true); + AppsFlyerMOCKInterface.Received().setDisableCollectIAd(true); + + } + + [Test] + public void setDisableCollectIAd_called_false() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setDisableCollectIAd(false); + AppsFlyerMOCKInterface.Received().setDisableCollectIAd(false); + + } + + [Test] + public void setUseReceiptValidationSandbox_called_true() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setUseReceiptValidationSandbox(true); + AppsFlyerMOCKInterface.Received().setUseReceiptValidationSandbox(true); + + } + + [Test] + public void setUseReceiptValidationSandbox_called_false() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setUseReceiptValidationSandbox(false); + AppsFlyerMOCKInterface.Received().setUseReceiptValidationSandbox(false); + + } + + [Test] + public void ssetUseUninstallSandbox_called_true() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setUseUninstallSandbox(true); + AppsFlyerMOCKInterface.Received().setUseUninstallSandbox(true); + + } + + [Test] + public void setUseUninstallSandbox_called_false() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setUseUninstallSandbox(false); + AppsFlyerMOCKInterface.Received().setUseUninstallSandbox(false); + + } + + [Test] + public void validateAndSendInAppPurchase_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.validateAndSendInAppPurchase("3d2", "5.0","USD", "45", null, null); + AppsFlyerMOCKInterface.Received().validateAndSendInAppPurchase("3d2", "5.0", "USD", "45", null, null); + + } + + [Test] + public void registerUninstall_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + byte[] token = System.Text.Encoding.UTF8.GetBytes("740f4707 bebcf74f 9b7c25d4 8e335894 5f6aa01d a5ddb387 462c7eaf 61bb78ad"); + AppsFlyer.registerUninstall(token); + AppsFlyerMOCKInterface.Received().registerUninstall(token); + + } + + [Test] + public void handleOpenUrl_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.handleOpenUrl("www.test.com", "appTest", "test"); + AppsFlyerMOCKInterface.Received().handleOpenUrl("www.test.com", "appTest", "test"); + + } + + [Test] + public void waitForATTUserAuthorizationWithTimeoutInterval_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.waitForATTUserAuthorizationWithTimeoutInterval(30); + AppsFlyerMOCKInterface.Received().waitForATTUserAuthorizationWithTimeoutInterval(30); + + } + + [Test] + public void setCurrentDeviceLanguage_called() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.setCurrentDeviceLanguage("en"); + AppsFlyerMOCKInterface.Received().setCurrentDeviceLanguage("en"); + + } + + [Test] + public void disableSKAdNetwork_called_true() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.disableSKAdNetwork(true); + AppsFlyerMOCKInterface.Received().disableSKAdNetwork(true); + + } + + [Test] + public void disableSKAdNetwork_called_false() + { + + var AppsFlyerMOCKInterface = Substitute.For(); + + AppsFlyer.instance = AppsFlyerMOCKInterface; + AppsFlyer.disableSKAdNetwork(false); + AppsFlyerMOCKInterface.Received().disableSKAdNetwork(false); + + } + +#endif + } +} diff --git a/Assets/AppsFlyer/Tests/Tests_Suite.cs.meta b/Assets/AppsFlyer/Tests/Tests_Suite.cs.meta new file mode 100644 index 0000000..c20a62c --- /dev/null +++ b/Assets/AppsFlyer/Tests/Tests_Suite.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b1a24aa01166451d804d7c03c14a3db +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Windows.meta b/Assets/AppsFlyer/Windows.meta new file mode 100644 index 0000000..859b3f2 --- /dev/null +++ b/Assets/AppsFlyer/Windows.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1fbfcb6aeaa7f40e69a0daff450a2450 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Windows/AppsFlyerLib.pri b/Assets/AppsFlyer/Windows/AppsFlyerLib.pri new file mode 100644 index 0000000000000000000000000000000000000000..f3993bee8d6162a8ae52777697f91b353f4144cd GIT binary patch literal 672 zcmaJ2iG)KGH%FJBkSFnie1MvUChXWT zNx@}T_Dpu{U9V%)7*#jr8i>%vKmwqXvBEG2U~6PSuCq#&)&6bA(4RdEbGjtRwaxTl z(y2WLy|7uKO)7dKA!nV;pEBJ3Mq6dldab7Ybp*6Q|EE6l(<0}wn?uCoe3oRR^*`VJ z(z$tNTI~Aw*-v~(VnE=`v(z7ZqeZyFh2S>VdsS4a(RP<4iNw8au0Os4H?X)tidy`D zd)$g|+?T}zUhxi%22UvQA_|UbV`^6;1#Fs literal 0 HcmV?d00001 diff --git a/Assets/AppsFlyer/Windows/AppsFlyerLib.pri.meta b/Assets/AppsFlyer/Windows/AppsFlyerLib.pri.meta new file mode 100644 index 0000000..ed4fbf8 --- /dev/null +++ b/Assets/AppsFlyer/Windows/AppsFlyerLib.pri.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c621896ec81267f478e98555031271ef +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Windows/AppsFlyerLib.winmd b/Assets/AppsFlyer/Windows/AppsFlyerLib.winmd new file mode 100644 index 0000000000000000000000000000000000000000..381ce32056f48bb1577a824b46040fa737234738 GIT binary patch literal 45056 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 literal 0 HcmV?d00001 diff --git a/Assets/AppsFlyer/Windows/AppsFlyerLib.winmd.meta b/Assets/AppsFlyer/Windows/AppsFlyerLib.winmd.meta new file mode 100644 index 0000000..728454c --- /dev/null +++ b/Assets/AppsFlyer/Windows/AppsFlyerLib.winmd.meta @@ -0,0 +1,38 @@ +fileFormatVersion: 2 +guid: 5186898c6f4665f438e46763d4cff3ae +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + XboxOne: XboxOne + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/Windows/AppsFlyerWindows.cs b/Assets/AppsFlyer/Windows/AppsFlyerWindows.cs new file mode 100644 index 0000000..a44fea4 --- /dev/null +++ b/Assets/AppsFlyer/Windows/AppsFlyerWindows.cs @@ -0,0 +1,145 @@ +//#define AFSDK_WIN_DEBUG +//#define UNITY_WSA_10_0 +//#define ENABLE_WINMD_SUPPORT + +#if UNITY_WSA_10_0 +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.ComponentModel; +using UnityEngine; +using System.Threading.Tasks; + +#if ENABLE_WINMD_SUPPORT +using AppsFlyerLib; +#endif + +namespace AppsFlyerSDK +{ + public class AppsFlyerWindows + { +#if ENABLE_WINMD_SUPPORT + static private MonoBehaviour _gameObject = null; +#endif + + public static void InitSDK(string devKey, string appId, MonoBehaviour gameObject) + { +#if ENABLE_WINMD_SUPPORT + +#if AFSDK_WIN_DEBUG + // Remove callstack + Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None); +#endif + Log("[InitSDK]: devKey: {0}, appId: {1}, gameObject: {2}", devKey, appId, gameObject == null ? "null" : gameObject.ToString()); + AppsFlyerTracker tracker = AppsFlyerTracker.GetAppsFlyerTracker(); + tracker.devKey = devKey; + tracker.appId = appId; + // Interface + _gameObject = gameObject; +#endif + } + + public static string GetAppsFlyerId() + { +#if ENABLE_WINMD_SUPPORT + Log("[GetAppsFlyerId]"); + return AppsFlyerTracker.GetAppsFlyerTracker().GetAppsFlyerUID(); +#else + return ""; +#endif + } + + public static void SetCustomerUserId(string customerUserId) + { +#if ENABLE_WINMD_SUPPORT + Log("[SetCustomerUserId] customerUserId: {0}", customerUserId); + if (customerUserId.Contains("test_device:")) + { + string testDeviceId = customerUserId.Substring(12); + AppsFlyerTracker.GetAppsFlyerTracker().testDeviceId = testDeviceId; + } + AppsFlyerTracker.GetAppsFlyerTracker().customerUserId = customerUserId; +#endif + } + + public static void Start() + { +#if ENABLE_WINMD_SUPPORT + Log("[Start]"); + AppsFlyerTracker.GetAppsFlyerTracker().TrackAppLaunchAsync(Callback); +#endif + } + +#if ENABLE_WINMD_SUPPORT + public static void Callback(AppsFlyerLib.ServerStatusCode code) + { + Log("[Callback]: {0}", code.ToString()); + + AppsFlyerRequestEventArgs eventArgs = new AppsFlyerRequestEventArgs((int)code, code.ToString()); + if (_gameObject != null) { + var method = _gameObject.GetType().GetMethod("AppsFlyerOnRequestResponse"); + if (method != null) { + method.Invoke(_gameObject, new object[] { AppsFlyerTracker.GetAppsFlyerTracker(), eventArgs }); + } + } + } +#endif + + public static void LogEvent(string eventName, Dictionary eventValues) + { +#if ENABLE_WINMD_SUPPORT + if (eventValues == null) + { + eventValues = new Dictionary(); + } + IDictionary result = new Dictionary(); + foreach (KeyValuePair kvp in eventValues) + { + result.Add(kvp.Key.ToString(), kvp.Value); + } + + Log("[LogEvent]: eventName: {0} result: {1}", eventName, result.ToString()); + + AppsFlyerTracker tracker = AppsFlyerTracker.GetAppsFlyerTracker(); + tracker.TrackEvent(eventName, result); + +#endif + } + + + public static void GetConversionData(string _reserved) + { +#if ENABLE_WINMD_SUPPORT + Task.Run(async () => + { + AppsFlyerLib.AppsFlyerTracker tracker = AppsFlyerLib.AppsFlyerTracker.GetAppsFlyerTracker(); + string conversionData = await tracker.GetConversionDataAsync(); + + IAppsFlyerConversionData conversionDataHandler = _gameObject as IAppsFlyerConversionData; + + if (conversionDataHandler != null) + { + Log("[GetConversionData] Will call `onConversionDataSuccess` with: {0}", conversionData); + conversionDataHandler.onConversionDataSuccess(conversionData); + } else { + Log("[GetConversionData] Object with `IAppsFlyerConversionData` interface not found! Check `InitSDK` implementation"); + } + // _gameObject.GetType().GetMethod("onConversionDataSuccess").Invoke(_gameObject, new[] { conversionData }); + }); +#endif + } + + private static void Log(string format, params string[] args) + { +#if AFSDK_WIN_DEBUG +#if ENABLE_WINMD_SUPPORT + Debug.Log("AF_UNITY_WSA_10_0" + String.Format(format, args)); +#endif +#endif + } + + } + +} +#endif diff --git a/Assets/AppsFlyer/Windows/AppsFlyerWindows.cs.meta b/Assets/AppsFlyer/Windows/AppsFlyerWindows.cs.meta new file mode 100644 index 0000000..66f10a1 --- /dev/null +++ b/Assets/AppsFlyer/Windows/AppsFlyerWindows.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 034d11e52b599954181d7f08c0d89ca8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/package.json b/Assets/AppsFlyer/package.json new file mode 100644 index 0000000..ab16c90 --- /dev/null +++ b/Assets/AppsFlyer/package.json @@ -0,0 +1,8 @@ +{ + "name": "appsflyer-unity-plugin", + "displayName": "AppsFlyer", + "description": "AppsFlyer Unity plugin", + "version": "6.14.0", + "unity": "2019.4", + "license": "MIT" + } diff --git a/Assets/AppsFlyer/package.json.meta b/Assets/AppsFlyer/package.json.meta new file mode 100644 index 0000000..e9b3d87 --- /dev/null +++ b/Assets/AppsFlyer/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a2b3ab5da7dda473b8791503604647b4 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk.meta b/Assets/MaxSdk.meta new file mode 100644 index 0000000..7d1ad1e --- /dev/null +++ b/Assets/MaxSdk.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1d1ca9700477e4b43ab8edb535f588c6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin.meta b/Assets/MaxSdk/AppLovin.meta new file mode 100644 index 0000000..0bf781b --- /dev/null +++ b/Assets/MaxSdk/AppLovin.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f4c20985b26094f70b0bc44cd95eb1ba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Editor.meta b/Assets/MaxSdk/AppLovin/Editor.meta new file mode 100644 index 0000000..2b930dc --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce14de298f23c4bb198d6f1bded11d72 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Editor/Dependencies.xml b/Assets/MaxSdk/AppLovin/Editor/Dependencies.xml new file mode 100644 index 0000000..0b7abb1 --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Assets/MaxSdk/AppLovin/Editor/Dependencies.xml.meta b/Assets/MaxSdk/AppLovin/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..3360fd3 --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 746da98302dc0402aaa37e8f7bd97e77 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Plugins.meta b/Assets/MaxSdk/AppLovin/Plugins.meta new file mode 100644 index 0000000..172ac9d --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 44d1cbc50e8ee4a5598c77229b695fdf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Plugins/Android.meta b/Assets/MaxSdk/AppLovin/Plugins/Android.meta new file mode 100644 index 0000000..1c1fa28 --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/Android.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e99b4053620214bb792c53550c79838a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar b/Assets/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar new file mode 100644 index 0000000000000000000000000000000000000000..e0f8bd72b2c0384e93eab05f4bc0c3b7df36a650 GIT binary patch literal 42544 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 literal 0 HcmV?d00001 diff --git a/Assets/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta b/Assets/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta new file mode 100644 index 0000000..224076a --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar.meta @@ -0,0 +1,35 @@ +fileFormatVersion: 2 +guid: 1db980bd612824d2097f78fd779e6051 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins/Android/applovin-max-unity-plugin.aar +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Android: Android + second: + enabled: 1 + settings: {} + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Plugins/iOS.meta b/Assets/MaxSdk/AppLovin/Plugins/iOS.meta new file mode 100644 index 0000000..7922667 --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/iOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 125fa3d9de30e4a089c720e502224457 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h new file mode 100644 index 0000000..debdd3c --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h @@ -0,0 +1,106 @@ +// +// MAUnityAdManager.h +// AppLovin MAX Unity Plugin +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN +typedef const void *MAUnityRef; +typedef void (*ALUnityBackgroundCallback)(const char* args); + +@interface MAUnityAdManager : NSObject + +- (void)initializeSdkWithConfiguration:(ALSdkInitializationConfiguration *)initConfig andCompletionHandler:(ALSdkInitializationCompletionHandler)completionHandler; + +- (void)createBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier atPosition:(nullable NSString *)bannerPosition; +- (void)createBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset; +- (void)loadBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)setBannerBackgroundColorForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier hexColorCode:(nullable NSString *)hexColorCode; +- (void)setBannerPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)startBannerAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)stopBannerAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)setBannerExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setBannerLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; +- (void)setBannerCustomData:(nullable NSString *)customData forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)setBannerWidth:(CGFloat)width forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateBannerPosition:(nullable NSString *)bannerPosition forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateBannerPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)destroyBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)hideBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (NSString *)bannerLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; ++ (CGFloat)adaptiveBannerHeightForWidth:(CGFloat)width; + +- (void)createMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier atPosition:(nullable NSString *)mrecPosition; +- (void)createMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset; +- (void)loadMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)setMRecPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)startMRecAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)stopMRecAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifer; +- (void)setMRecExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setMRecLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; +- (void)setMRecCustomData:(nullable NSString *)customData forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)destroyMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)hideMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateMRecPosition:(nullable NSString *)mrecPosition forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)updateMRecPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (NSString *)mrecLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; + +- (void)loadInterstitialWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (BOOL)isInterstitialReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showInterstitialWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; +- (void)setInterstitialExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setInterstitialLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; + +- (void)loadAppOpenAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (BOOL)isAppOpenAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showAppOpenAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; +- (void)setAppOpenAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setAppOpenAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; + +- (void)loadRewardedAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (BOOL)isRewardedAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showRewardedAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; +- (void)setRewardedAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setRewardedAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; + +- (void)loadRewardedInterstitialAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (BOOL)isRewardedInterstitialAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +- (void)showRewardedInterstitialAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData; +- (void)setRewardedInterstitialAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value; +- (void)setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; + +// Event Tracking +- (void)trackEvent:(nullable NSString *)event parameters:(nullable NSString *)parameters; + +// Ad Info +- (NSString *)adInfoForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; + +// Ad Value +- (NSString *)adValueForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier withKey:(nullable NSString *)key; + +// User Service +- (void)didDismissUserConsentDialog; + +// CMP Service +- (void)showCMPForExistingUser; + +// Utils ++ (NSString *)serializeParameters:(NSDictionary *)dict; ++ (NSDictionary *)deserializeParameters:(nullable NSString *)serialized; + ++ (void)setUnityBackgroundCallback:(ALUnityBackgroundCallback)unityBackgroundCallback; + +/** + * Creates an instance of @c MAUnityAdManager if needed and returns the singleton instance. + */ ++ (instancetype)shared; + +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta new file mode 100644 index 0000000..aef1db5 --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h.meta @@ -0,0 +1,115 @@ +fileFormatVersion: 2 +guid: 4209563f82b8a4f7dabf03705ab761c6 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.h +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + Exclude tvOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m new file mode 100644 index 0000000..8cd0437 --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m @@ -0,0 +1,2084 @@ +// +// MAUnityAdManager.m +// AppLovin MAX Unity Plugin +// + +#import "MAUnityAdManager.h" + +#define KEY_WINDOW [UIApplication sharedApplication].keyWindow +#define DEVICE_SPECIFIC_ADVIEW_AD_FORMAT ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) ? MAAdFormat.leader : MAAdFormat.banner +#define IS_VERTICAL_BANNER_POSITION(_POS) ( [@"center_left" isEqual: adViewPosition] || [@"center_right" isEqual: adViewPosition] ) +#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI) + +#ifdef __cplusplus +extern "C" { +#endif + + // UnityAppController.mm + UIViewController* UnityGetGLViewController(void); + UIWindow* UnityGetMainWindow(void); + + // life cycle management + int UnityIsPaused(void); + void UnityPause(int pause); + + void max_unity_dispatch_on_main_thread(dispatch_block_t block) + { + if ( block ) + { + if ( [NSThread isMainThread] ) + { + block(); + } + else + { + dispatch_async(dispatch_get_main_queue(), block); + } + } + } +#ifdef __cplusplus +} +#endif + +@interface MAUnityAdManager() + +// Parent Fields +@property (nonatomic, weak) ALSdk *sdk; + +// Fullscreen Ad Fields +@property (nonatomic, strong) NSMutableDictionary *interstitials; +@property (nonatomic, strong) NSMutableDictionary *appOpenAds; +@property (nonatomic, strong) NSMutableDictionary *rewardedAds; +@property (nonatomic, strong) NSMutableDictionary *rewardedInterstitialAds; + +// AdView Fields +@property (nonatomic, strong) NSMutableDictionary *adViews; +@property (nonatomic, strong) NSMutableDictionary *adViewAdFormats; +@property (nonatomic, strong) NSMutableDictionary *adViewPositions; +@property (nonatomic, strong) NSMutableDictionary *adViewOffsets; +@property (nonatomic, strong) NSMutableDictionary *adViewWidths; +@property (nonatomic, strong) NSMutableDictionary *verticalAdViewFormats; +@property (nonatomic, strong) NSMutableDictionary *> *adViewConstraints; +@property (nonatomic, strong) NSMutableDictionary *> *adViewExtraParametersToSetAfterCreate; +@property (nonatomic, strong) NSMutableDictionary *> *adViewLocalExtraParametersToSetAfterCreate; +@property (nonatomic, strong) NSMutableDictionary *adViewCustomDataToSetAfterCreate; +@property (nonatomic, strong) NSMutableArray *adUnitIdentifiersToShowAfterCreate; +@property (nonatomic, strong) NSMutableSet *disabledAdaptiveBannerAdUnitIdentifiers; +@property (nonatomic, strong) NSMutableSet *disabledAutoRefreshAdViewAdUnitIdentifiers; +@property (nonatomic, strong) UIView *safeAreaBackground; +@property (nonatomic, strong, nullable) UIColor *publisherBannerBackgroundColor; + +@property (nonatomic, strong) NSMutableDictionary *adInfoDict; +@property (nonatomic, strong) NSObject *adInfoDictLock; + +@property (nonatomic, strong) NSOperationQueue *backgroundCallbackEventsQueue; +@property (nonatomic, assign) BOOL resumeUnityAfterApplicationBecomesActive; + +@end + +// Internal +@interface UIColor (ALUtils) ++ (nullable UIColor *)al_colorWithHexString:(NSString *)hexString; +@end + +@interface NSNumber (ALUtils) ++ (NSNumber *)al_numberWithString:(NSString *)string; +@end + +@interface NSString (ALUtils) +@property (assign, readonly, getter=al_isValidString) BOOL al_validString; +@end + +@interface MAAdFormat (ALUtils) +@property (nonatomic, assign, readonly, getter=isFullscreenAd) BOOL fullscreenAd; +@property (nonatomic, assign, readonly, getter=isAdViewAd) BOOL adViewAd; +@end + +@implementation MAUnityAdManager +static NSString *const SDK_TAG = @"AppLovinSdk"; +static NSString *const TAG = @"MAUnityAdManager"; +static NSString *const DEFAULT_AD_VIEW_POSITION = @"top_left"; +static ALUnityBackgroundCallback backgroundCallback; + +#pragma mark - Initialization + +- (instancetype)init +{ + self = [super init]; + if ( self ) + { + self.interstitials = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.appOpenAds = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.rewardedAds = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.rewardedInterstitialAds = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViews = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewAdFormats = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewPositions = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewOffsets = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewWidths = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.verticalAdViewFormats = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewConstraints = [NSMutableDictionary dictionaryWithCapacity: 2]; + self.adViewExtraParametersToSetAfterCreate = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adViewLocalExtraParametersToSetAfterCreate = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adViewCustomDataToSetAfterCreate = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adUnitIdentifiersToShowAfterCreate = [NSMutableArray arrayWithCapacity: 2]; + self.disabledAdaptiveBannerAdUnitIdentifiers = [NSMutableSet setWithCapacity: 2]; + self.disabledAutoRefreshAdViewAdUnitIdentifiers = [NSMutableSet setWithCapacity: 2]; + self.adInfoDict = [NSMutableDictionary dictionary]; + self.adInfoDictLock = [[NSObject alloc] init]; + + self.backgroundCallbackEventsQueue = [[NSOperationQueue alloc] init]; + self.backgroundCallbackEventsQueue.maxConcurrentOperationCount = 1; + + max_unity_dispatch_on_main_thread(^{ + self.safeAreaBackground = [[UIView alloc] init]; + self.safeAreaBackground.hidden = YES; + self.safeAreaBackground.backgroundColor = UIColor.clearColor; + self.safeAreaBackground.translatesAutoresizingMaskIntoConstraints = NO; + self.safeAreaBackground.userInteractionEnabled = NO; + + UIViewController *rootViewController = [self unityViewController]; + [rootViewController.view addSubview: self.safeAreaBackground]; + }); + + // Enable orientation change listener, so that the position can be updated for vertical banners. + [[NSNotificationCenter defaultCenter] addObserverForName: UIDeviceOrientationDidChangeNotification + object: nil + queue: [NSOperationQueue mainQueue] + usingBlock:^(NSNotification *notification) { + + for ( NSString *adUnitIdentifier in self.verticalAdViewFormats ) + { + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: self.verticalAdViewFormats[adUnitIdentifier]]; + } + }]; + + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector(applicationPaused:) + name: UIApplicationDidEnterBackgroundNotification + object: nil]; + + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector(applicationResumed:) + name: UIApplicationDidBecomeActiveNotification + object: nil]; + + [[NSNotificationCenter defaultCenter] addObserverForName: UIApplicationDidBecomeActiveNotification + object: nil + queue: [NSOperationQueue mainQueue] + usingBlock:^(NSNotification *notification) { + +#if !IS_TEST_APP + if ( self.resumeUnityAfterApplicationBecomesActive && UnityIsPaused() ) + { + UnityPause(NO); + } +#endif + + self.backgroundCallbackEventsQueue.suspended = NO; + }]; + } + return self; +} + ++ (MAUnityAdManager *)shared +{ + static dispatch_once_t token; + static MAUnityAdManager *shared; + dispatch_once(&token, ^{ + shared = [[MAUnityAdManager alloc] init]; + }); + return shared; +} + ++ (void)setUnityBackgroundCallback:(ALUnityBackgroundCallback)unityBackgroundCallback +{ + backgroundCallback = unityBackgroundCallback; +} + +#pragma mark - Plugin Initialization + +- (void)initializeSdkWithConfiguration:(ALSdkInitializationConfiguration *)initConfig andCompletionHandler:(ALSdkInitializationCompletionHandler)completionHandler; +{ + self.sdk = [ALSdk shared]; + [self.sdk initializeWithConfiguration: initConfig completionHandler:^(ALSdkConfiguration *configuration) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + // Note: internal state should be updated first + completionHandler( configuration ); + + NSString *consentFlowUserGeographyStr = @(configuration.consentFlowUserGeography).stringValue; + NSString *consentDialogStateStr = @(configuration.consentDialogState).stringValue; + NSString *appTrackingStatus = @(configuration.appTrackingTransparencyStatus).stringValue; // Deliberately name it `appTrackingStatus` to be a bit more generic (in case Android introduces a similar concept) + [self forwardUnityEventWithArgs: @{@"name" : @"OnSdkInitializedEvent", + @"consentFlowUserGeography" : consentFlowUserGeographyStr, + @"consentDialogState" : consentDialogStateStr, + @"countryCode" : configuration.countryCode, + @"appTrackingStatus" : appTrackingStatus, + @"isSuccessfullyInitialized" : @([self.sdk isInitialized]), + @"isTestModeEnabled" : @([configuration isTestModeEnabled])}]; + }); + }]; +} + +#pragma mark - Banners + +- (void)createBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier atPosition:(nullable NSString *)bannerPosition +{ + [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] atPosition: bannerPosition withOffset: CGPointZero]; +} + +- (void)createBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset +{ + [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] atPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset)]; +} + +- (void)loadBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self loadAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)setBannerBackgroundColorForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier hexColorCode:(nullable NSString *)hexColorCode +{ + [self setAdViewBackgroundColorForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] hexColorCode: hexColorCode]; +} + +- (void)setBannerPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)startBannerAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self startAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)stopBannerAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self stopAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)setBannerWidth:(CGFloat)width forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self setAdViewWidth: width forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)updateBannerPosition:(nullable NSString *)bannerPosition forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self updateAdViewPosition: bannerPosition withOffset: CGPointZero forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)updateBannerPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self updateAdViewPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset) forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)setBannerExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value +{ + [self setAdViewExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] key: key value: value]; +} + +- (void)setBannerLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value +{ + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + + [self setAdViewLocalExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier] key: key value: value]; +} + +- (void)setBannerCustomData:(nullable NSString *)customData forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self setAdViewCustomData: customData forAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)showBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)hideBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (NSString *)bannerLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + return [self adViewLayoutForAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + +- (void)destroyBannerWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: [self adViewAdFormatForAdUnitIdentifier: adUnitIdentifier]]; +} + ++ (CGFloat)adaptiveBannerHeightForWidth:(CGFloat)width +{ + return [DEVICE_SPECIFIC_ADVIEW_AD_FORMAT adaptiveSizeForWidth: width].height; +} + +#pragma mark - MRECs + +- (void)createMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier atPosition:(nullable NSString *)mrecPosition +{ + [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec atPosition: mrecPosition withOffset: CGPointZero]; +} + +- (void)createMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier x:(CGFloat)xOffset y:(CGFloat)yOffset +{ + [self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec atPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset)]; +} + +- (void)loadMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self loadAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)setMRecPlacement:(nullable NSString *)placement forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)startMRecAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self startAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)stopMRecAutoRefreshForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self stopAdViewAutoRefreshForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)updateMRecPosition:(nullable NSString *)mrecPosition forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self updateAdViewPosition: mrecPosition withOffset: CGPointZero forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)updateMRecPosition:(CGFloat)xOffset y:(CGFloat)yOffset forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self updateAdViewPosition: DEFAULT_AD_VIEW_POSITION withOffset: CGPointMake(xOffset, yOffset) forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)setMRecExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value +{ + [self setAdViewExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec key: key value: value]; +} + +- (void)setMRecLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value +{ + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + + [self setAdViewLocalExtraParameterForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec key: key value: value]; +} + +- (void)setMRecCustomData:(nullable NSString *)customData forAdUnitIdentifier:(nullable NSString *)adUnitIdentifier; +{ + [self setAdViewCustomData: customData forAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)showMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)destroyMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (void)hideMRecWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + [self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +- (NSString *)mrecLayoutForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + return [self adViewLayoutForAdUnitIdentifier: adUnitIdentifier adFormat: MAAdFormat.mrec]; +} + +#pragma mark - Interstitials + +- (void)loadInterstitialWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + [interstitial loadAd]; +} + +- (BOOL)isInterstitialReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + return [interstitial isReady]; +} + +- (void)showInterstitialWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData +{ + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + [interstitial showAdForPlacement: placement customData: customData]; +} + +- (void)setInterstitialExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value +{ + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + [interstitial setExtraParameterForKey: key value: value]; +} + +- (void)setInterstitialLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value +{ + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + + MAInterstitialAd *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier]; + [interstitial setLocalExtraParameterForKey: key value: value]; +} + +#pragma mark - App Open Ads + +- (void)loadAppOpenAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + [appOpenAd loadAd]; +} + +- (BOOL)isAppOpenAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + return [appOpenAd isReady]; +} + +- (void)showAppOpenAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData +{ + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + [appOpenAd showAdForPlacement: placement customData: customData]; +} + +- (void)setAppOpenAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value +{ + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + [appOpenAd setExtraParameterForKey: key value: value]; +} + +- (void)setAppOpenAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value +{ + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + + MAAppOpenAd *appOpenAd = [self retrieveAppOpenAdForAdUnitIdentifier: adUnitIdentifier]; + [appOpenAd setLocalExtraParameterForKey: key value: value]; +} + +#pragma mark - Rewarded + +- (void)loadRewardedAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedAd loadAd]; +} + +- (BOOL)isRewardedAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + return [rewardedAd isReady]; +} + +- (void)showRewardedAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData +{ + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedAd showAdForPlacement: placement customData: customData]; +} + +- (void)setRewardedAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value +{ + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedAd setExtraParameterForKey: key value: value]; +} + +- (void)setRewardedAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value; +{ + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + + MARewardedAd *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedAd setLocalExtraParameterForKey: key value: value]; +} + +#pragma mark - Rewarded Interstitials + +- (void)loadRewardedInterstitialAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedInterstitialAd loadAd]; +} + +- (BOOL)isRewardedInterstitialAdReadyWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + return [rewardedInterstitialAd isReady]; +} + +- (void)showRewardedInterstitialAdWithAdUnitIdentifier:(nullable NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData +{ + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedInterstitialAd showAdForPlacement: placement customData: customData]; +} + +- (void)setRewardedInterstitialAdExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable NSString *)value +{ + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedInterstitialAd setExtraParameterForKey: key value: value]; +} + +- (void)setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier key:(nullable NSString *)key value:(nullable id)value +{ + if ( !key ) + { + [self log: @"Failed to set local extra parameter: No key specified"]; + return; + } + + MARewardedInterstitialAd *rewardedInterstitialAd = [self retrieveRewardedInterstitialAdForAdUnitIdentifier: adUnitIdentifier]; + [rewardedInterstitialAd setLocalExtraParameterForKey: key value: value]; +} + +#pragma mark - Event Tracking + +- (void)trackEvent:(nullable NSString *)event parameters:(nullable NSString *)parameters +{ + NSDictionary *deserializedParameters = [MAUnityAdManager deserializeParameters: parameters]; + [self.sdk.eventService trackEvent: event parameters: deserializedParameters]; +} + +#pragma mark - Ad Info + +- (NSString *)adInfoForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier +{ + if ( ![adUnitIdentifier al_isValidString] ) return @""; + + MAAd *ad = [self adWithAdUnitIdentifier: adUnitIdentifier]; + if ( !ad ) return @""; + + return [MAUnityAdManager serializeParameters: [self adInfoForAd: ad]]; +} + +- (NSDictionary *)adInfoForAd:(MAAd *)ad +{ + return @{@"adUnitId" : ad.adUnitIdentifier, + @"adFormat" : ad.format.label, + @"networkName" : ad.networkName, + @"networkPlacement" : ad.networkPlacement, + @"creativeId" : ad.creativeIdentifier ?: @"", + @"placement" : ad.placement ?: @"", + @"revenue" : [@(ad.revenue) stringValue], + @"revenuePrecision" : ad.revenuePrecision, + @"waterfallInfo" : [self createAdWaterfallInfo: ad.waterfall], + @"latencyMillis" : [self requestLatencyMillisFromRequestLatency: ad.requestLatency], + @"dspName" : ad.DSPName ?: @""}; +} + +#pragma mark - Waterfall Information + +- (NSDictionary *)createAdWaterfallInfo:(MAAdWaterfallInfo *)waterfallInfo +{ + NSMutableDictionary *waterfallInfoDict = [NSMutableDictionary dictionary]; + if ( !waterfallInfo ) return waterfallInfoDict; + + waterfallInfoDict[@"name"] = waterfallInfo.name; + waterfallInfoDict[@"testName"] = waterfallInfo.testName; + + NSMutableArray *> *networkResponsesArray = [NSMutableArray arrayWithCapacity: waterfallInfo.networkResponses.count]; + for ( MANetworkResponseInfo *response in waterfallInfo.networkResponses ) + { + [networkResponsesArray addObject: [self createNetworkResponseInfo: response]]; + } + + waterfallInfoDict[@"networkResponses"] = networkResponsesArray; + waterfallInfoDict[@"latencyMillis"] = [self requestLatencyMillisFromRequestLatency: waterfallInfo.latency]; + + return waterfallInfoDict; +} + +- (NSDictionary *)createNetworkResponseInfo:(MANetworkResponseInfo *)response +{ + NSMutableDictionary *networkResponseDict = [NSMutableDictionary dictionary]; + + networkResponseDict[@"adLoadState"] = @(response.adLoadState).stringValue; + + MAMediatedNetworkInfo *mediatedNetworkInfo = response.mediatedNetwork; + if ( mediatedNetworkInfo ) + { + NSMutableDictionary *networkInfoObject = [NSMutableDictionary dictionary]; + networkInfoObject[@"name"] = response.mediatedNetwork.name; + networkInfoObject[@"adapterClassName"] = response.mediatedNetwork.adapterClassName; + networkInfoObject[@"adapterVersion"] = response.mediatedNetwork.adapterVersion; + networkInfoObject[@"sdkVersion"] = response.mediatedNetwork.sdkVersion; + + networkResponseDict[@"mediatedNetwork"] = networkInfoObject; + } + + networkResponseDict[@"credentials"] = response.credentials; + networkResponseDict[@"isBidding"] = @([response isBidding]); + + MAError *error = response.error; + if ( error ) + { + NSMutableDictionary *errorObject = [NSMutableDictionary dictionary]; + errorObject[@"errorMessage"] = error.message; + errorObject[@"adLoadFailure"] = error.adLoadFailureInfo; + errorObject[@"errorCode"] = @(error.code).stringValue; + errorObject[@"latencyMillis"] = [self requestLatencyMillisFromRequestLatency: error.requestLatency]; + + networkResponseDict[@"error"] = errorObject; + } + + networkResponseDict[@"latencyMillis"] = [self requestLatencyMillisFromRequestLatency: response.latency]; + + return networkResponseDict; +} + +#pragma mark - Ad Value + +- (NSString *)adValueForAdUnitIdentifier:(nullable NSString *)adUnitIdentifier withKey:(nullable NSString *)key +{ + if ( adUnitIdentifier == nil || adUnitIdentifier.length == 0 ) return @""; + if ( key == nil || key.length == 0 ) return @""; + + MAAd *ad = [self adWithAdUnitIdentifier: adUnitIdentifier]; + if ( !ad ) return @""; + + return [ad adValueForKey: key]; +} + +#pragma mark - Ad Callbacks + +- (void)didLoadAd:(MAAd *)ad +{ + NSString *name; + MAAdFormat *adFormat = ad.format; + if ( [adFormat isAdViewAd] ) + { + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: ad.adUnitIdentifier adFormat: adFormat]; + // An ad is now being shown, enable user interaction. + adView.userInteractionEnabled = YES; + + if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdLoadedEvent"; + } + else + { + name = @"OnBannerAdLoadedEvent"; + } + [self positionAdViewForAd: ad]; + + // Do not auto-refresh by default if the ad view is not showing yet (e.g. first load during app launch and publisher does not automatically show banner upon load success) + // We will resume auto-refresh in -[MAUnityAdManager showBannerWithAdUnitIdentifier:]. + if ( adView && [adView isHidden] ) + { + [adView stopAutoRefresh]; + } + } + else if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialLoadedEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdLoadedEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdLoadedEvent"; + } + else if ( MAAdFormat.rewardedInterstitial == adFormat ) + { + name = @"OnRewardedInterstitialAdLoadedEvent"; + } + else + { + [self logInvalidAdFormat: adFormat]; + return; + } + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + @synchronized ( self.adInfoDictLock ) + { + self.adInfoDict[ad.adUnitIdentifier] = ad; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didFailToLoadAdForAdUnitIdentifier:(NSString *)adUnitIdentifier withError:(MAError *)error +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + if ( !adUnitIdentifier ) + { + [self log: @"adUnitIdentifier cannot be nil from %@", [NSThread callStackSymbols]]; + return; + } + + NSString *name; + if ( self.adViews[adUnitIdentifier] ) + { + MAAdFormat *adFormat = self.adViewAdFormats[adUnitIdentifier]; + if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdLoadFailedEvent"; + } + else + { + name = @"OnBannerAdLoadFailedEvent"; + } + } + else if ( self.interstitials[adUnitIdentifier] ) + { + name = @"OnInterstitialLoadFailedEvent"; + } + else if ( self.appOpenAds[adUnitIdentifier] ) + { + name = @"OnAppOpenAdLoadFailedEvent"; + } + else if ( self.rewardedAds[adUnitIdentifier] ) + { + name = @"OnRewardedAdLoadFailedEvent"; + } + else if ( self.rewardedInterstitialAds[adUnitIdentifier] ) + { + name = @"OnRewardedInterstitialAdLoadFailedEvent"; + } + else + { + [self log: @"invalid adUnitId from %@", [NSThread callStackSymbols]]; + return; + } + + @synchronized ( self.adInfoDictLock ) + { + [self.adInfoDict removeObjectForKey: adUnitIdentifier]; + } + + [self forwardUnityEventWithArgs: @{@"name" : name, + @"adUnitId" : adUnitIdentifier, + @"errorCode" : [@(error.code) stringValue], + @"errorMessage" : error.message, + @"waterfallInfo" : [self createAdWaterfallInfo: error.waterfall], + @"adLoadFailureInfo" : error.adLoadFailureInfo ?: @"", + @"latencyMillis" : [self requestLatencyMillisFromRequestLatency: error.requestLatency]}]; + }); +} + +- (void)didClickAd:(MAAd *)ad +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + NSString *name; + MAAdFormat *adFormat = ad.format; + if ( MAAdFormat.banner == adFormat || MAAdFormat.leader == adFormat ) + { + name = @"OnBannerAdClickedEvent"; + } + else if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdClickedEvent"; + } + else if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialClickedEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdClickedEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdClickedEvent"; + } + else if ( MAAdFormat.rewardedInterstitial == adFormat ) + { + name = @"OnRewardedInterstitialAdClickedEvent"; + } + else + { + [self logInvalidAdFormat: adFormat]; + return; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didDisplayAd:(MAAd *)ad +{ + // BMLs do not support [DISPLAY] events in Unity + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isFullscreenAd] ) return; + +#if !IS_TEST_APP + // UnityPause needs to be called on the main thread. + UnityPause(YES); +#endif + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + NSString *name; + if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialDisplayedEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdDisplayedEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdDisplayedEvent"; + } + else // rewarded inters + { + name = @"OnRewardedInterstitialAdDisplayedEvent"; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didFailToDisplayAd:(MAAd *)ad withError:(MAError *)error +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + // BMLs do not support [DISPLAY] events in Unity + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isFullscreenAd] ) return; + + NSString *name; + if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialAdFailedToDisplayEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdFailedToDisplayEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdFailedToDisplayEvent"; + } + else // rewarded inters + { + name = @"OnRewardedInterstitialAdFailedToDisplayEvent"; + } + + NSMutableDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + args[@"errorCode"] = [@(error.code) stringValue]; + args[@"errorMessage"] = error.message; + args[@"mediatedNetworkErrorCode"] = [@(error.mediatedNetworkErrorCode) stringValue]; + args[@"mediatedNetworkErrorMessage"] = error.mediatedNetworkErrorMessage; + args[@"waterfallInfo"] = [self createAdWaterfallInfo: error.waterfall]; + args[@"latencyMillis"] = [self requestLatencyMillisFromRequestLatency: error.requestLatency]; + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didHideAd:(MAAd *)ad +{ + // BMLs do not support [HIDDEN] events in Unity + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isFullscreenAd] ) return; + +#if !IS_TEST_APP + extern bool _didResignActive; + if ( _didResignActive ) + { + // If the application is not active, we should wait until application becomes active to resume unity. + self.resumeUnityAfterApplicationBecomesActive = YES; + } + else + { + // UnityPause needs to be called on the main thread. + UnityPause(NO); + } +#endif + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + NSString *name; + if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialHiddenEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdHiddenEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdHiddenEvent"; + } + else // rewarded inters + { + name = @"OnRewardedInterstitialAdHiddenEvent"; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didExpandAd:(MAAd *)ad +{ + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isAdViewAd] ) + { + [self logInvalidAdFormat: adFormat]; + return; + } + +#if !IS_TEST_APP + // UnityPause needs to be called on the main thread. + UnityPause(YES); +#endif + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + NSString *name; + if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdExpandedEvent"; + } + else + { + name = @"OnBannerAdExpandedEvent"; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didCollapseAd:(MAAd *)ad +{ + MAAdFormat *adFormat = ad.format; + if ( ![adFormat isAdViewAd] ) + { + [self logInvalidAdFormat: adFormat]; + return; + } + +#if !IS_TEST_APP + extern bool _didResignActive; + if ( _didResignActive ) + { + // If the application is not active, we should wait until application becomes active to resume unity. + self.resumeUnityAfterApplicationBecomesActive = YES; + } + else + { + // UnityPause needs to be called on the main thread. + UnityPause(NO); + } +#endif + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + NSString *name; + if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdCollapsedEvent"; + } + else + { + name = @"OnBannerAdCollapsedEvent"; + } + + NSDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didRewardUserForAd:(MAAd *)ad withReward:(MAReward *)reward +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + MAAdFormat *adFormat = ad.format; + if ( adFormat != MAAdFormat.rewarded && adFormat != MAAdFormat.rewardedInterstitial ) + { + [self logInvalidAdFormat: adFormat]; + return; + } + + NSString *rewardLabel = reward ? reward.label : @""; + NSInteger rewardAmountInt = reward ? reward.amount : 0; + NSString *rewardAmount = [@(rewardAmountInt) stringValue]; + + NSString *name = (adFormat == MAAdFormat.rewarded) ? @"OnRewardedAdReceivedRewardEvent" : @"OnRewardedInterstitialAdReceivedRewardEvent"; + + + NSMutableDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + args[@"rewardLabel"] = rewardLabel; + args[@"rewardAmount"] = rewardAmount; + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didPayRevenueForAd:(MAAd *)ad +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + NSString *name; + MAAdFormat *adFormat = ad.format; + if ( MAAdFormat.banner == adFormat || MAAdFormat.leader == adFormat ) + { + name = @"OnBannerAdRevenuePaidEvent"; + } + else if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdRevenuePaidEvent"; + } + else if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialAdRevenuePaidEvent"; + } + else if ( MAAdFormat.appOpen == adFormat ) + { + name = @"OnAppOpenAdRevenuePaidEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdRevenuePaidEvent"; + } + else if ( MAAdFormat.rewardedInterstitial == adFormat ) + { + name = @"OnRewardedInterstitialAdRevenuePaidEvent"; + } + else + { + [self logInvalidAdFormat: adFormat]; + return; + } + + NSMutableDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + args[@"keepInBackground"] = @([adFormat isFullscreenAd]); + [self forwardUnityEventWithArgs: args]; + }); +} + +- (void)didGenerateCreativeIdentifier:(NSString *)creativeIdentifier forAd:(MAAd *)ad +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + NSString *name; + MAAdFormat *adFormat = ad.format; + if ( MAAdFormat.banner == adFormat || MAAdFormat.leader == adFormat ) + { + name = @"OnBannerAdReviewCreativeIdGeneratedEvent"; + } + else if ( MAAdFormat.mrec == adFormat ) + { + name = @"OnMRecAdReviewCreativeIdGeneratedEvent"; + } + else if ( MAAdFormat.interstitial == adFormat ) + { + name = @"OnInterstitialAdReviewCreativeIdGeneratedEvent"; + } + else if ( MAAdFormat.rewarded == adFormat ) + { + name = @"OnRewardedAdReviewCreativeIdGeneratedEvent"; + } + else if ( MAAdFormat.rewardedInterstitial == adFormat ) + { + name = @"OnRewardedInterstitialAdReviewCreativeIdGeneratedEvent"; + } + else + { + [self logInvalidAdFormat: adFormat]; + return; + } + + NSMutableDictionary *args = [self defaultAdEventParametersForName: name withAd: ad]; + args[@"adReviewCreativeId"] = creativeIdentifier; + args[@"keepInBackground"] = @([adFormat isFullscreenAd]); + + // Forward the event in background for fullscreen ads so that the user gets the callback even while the ad is playing. + [self forwardUnityEventWithArgs: args]; + }); +} + +- (NSMutableDictionary *)defaultAdEventParametersForName:(NSString *)name withAd:(MAAd *)ad +{ + NSMutableDictionary *args = [[self adInfoForAd: ad] mutableCopy]; + args[@"name"] = name; + + return args; +} + +#pragma mark - Internal Methods + +- (void)createAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat atPosition:(NSString *)adViewPosition withOffset:(CGPoint)offset +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Creating %@ with ad unit identifier \"%@\" and position: \"%@\"", adFormat, adUnitIdentifier, adViewPosition]; + + if ( self.adViews[adUnitIdentifier] ) + { + [self log: @"Trying to create a %@ that was already created. This will cause the current ad to be hidden.", adFormat.label]; + } + + // Retrieve ad view from the map + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat atPosition: adViewPosition withOffset: offset]; + adView.hidden = YES; + self.safeAreaBackground.hidden = YES; + + // Position ad view immediately so if publisher sets color before ad loads, it will not be the size of the screen + self.adViewAdFormats[adUnitIdentifier] = adFormat; + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + + NSDictionary *extraParameters = self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier]; + + // Enable adaptive banners by default for banners and leaders. + if ( [adFormat isBannerOrLeaderAd] ) + { + // Check if there is already a pending setting for adaptive banners. If not, enable them. + if ( !extraParameters[@"adaptive_banner"] ) + { + [adView setExtraParameterForKey: @"adaptive_banner" value: @"true"]; + } + } + + // Handle initial extra parameters if publisher sets it before creating ad view + if ( extraParameters ) + { + for ( NSString *key in extraParameters ) + { + [adView setExtraParameterForKey: key value: extraParameters[key]]; + + [self handleExtraParameterChangesIfNeededForAdUnitIdentifier: adUnitIdentifier + adFormat: adFormat + key: key + value: extraParameters[key]]; + } + + [self.adViewExtraParametersToSetAfterCreate removeObjectForKey: adUnitIdentifier]; + } + + // Handle initial local extra parameters if publisher sets it before creating ad view + if ( self.adViewLocalExtraParametersToSetAfterCreate[adUnitIdentifier] ) + { + NSDictionary *localExtraParameters = self.adViewLocalExtraParametersToSetAfterCreate[adUnitIdentifier]; + for ( NSString *key in localExtraParameters ) + { + [adView setLocalExtraParameterForKey: key value: localExtraParameters[key]]; + } + + [self.adViewLocalExtraParametersToSetAfterCreate removeObjectForKey: adUnitIdentifier]; + } + + // Handle initial custom data if publisher sets it before creating ad view + if ( self.adViewCustomDataToSetAfterCreate[adUnitIdentifier] ) + { + NSString *customData = self.adViewCustomDataToSetAfterCreate[adUnitIdentifier]; + adView.customData = customData; + + [self.adViewCustomDataToSetAfterCreate removeObjectForKey: adUnitIdentifier]; + } + + [adView loadAd]; + + // Disable auto-refresh if publisher sets it before creating the ad view. + if ( [self.disabledAutoRefreshAdViewAdUnitIdentifiers containsObject: adUnitIdentifier] ) + { + [adView stopAutoRefresh]; + } + + // The publisher may have requested to show the banner before it was created. Now that the banner is created, show it. + if ( [self.adUnitIdentifiersToShowAfterCreate containsObject: adUnitIdentifier] ) + { + [self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + [self.adUnitIdentifiersToShowAfterCreate removeObject: adUnitIdentifier]; + } + }); +} + +- (void)loadAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !adView ) + { + [self log: @"%@ does not exist for ad unit identifier \"%@\".", adFormat.label, adUnitIdentifier]; + return; + } + + if ( ![self.disabledAutoRefreshAdViewAdUnitIdentifiers containsObject: adUnitIdentifier] ) + { + if ( [adView isHidden] ) + { + [self log: @"Auto-refresh will resume when the %@ ad is shown. You should only call LoadBanner() or LoadMRec() if you explicitly pause auto-refresh and want to manually load an ad.", adFormat.label]; + return; + } + + [self log: @"You must stop auto-refresh if you want to manually load %@ ads.", adFormat.label]; + return; + } + + [adView loadAd]; + }); +} + +- (void)setAdViewBackgroundColorForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat hexColorCode:(NSString *)hexColorCode +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting %@ with ad unit identifier \"%@\" to color: \"%@\"", adFormat, adUnitIdentifier, hexColorCode]; + + // In some cases, black color may get redrawn on each frame update, resulting in an undesired flicker + NSString *hexColorCodeToUse = [hexColorCode containsString: @"FF000000"] ? @"FF000001" : hexColorCode; + UIColor *convertedColor = [UIColor al_colorWithHexString: hexColorCodeToUse]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + self.publisherBannerBackgroundColor = convertedColor; + self.safeAreaBackground.backgroundColor = view.backgroundColor = convertedColor; + + // Position adView to ensure logic that depends on background color is properly run + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + }); +} + +- (void)setAdViewPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting placement \"%@\" for \"%@\" with ad unit identifier \"%@\"", placement, adFormat, adUnitIdentifier]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + adView.placement = placement; + }); +} + +- (void)startAdViewAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Starting %@ auto refresh for ad unit identifier \"%@\"", adFormat.label, adUnitIdentifier]; + + [self.disabledAutoRefreshAdViewAdUnitIdentifiers removeObject: adUnitIdentifier]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !adView ) + { + [self log: @"%@ does not exist for ad unit identifier %@.", adFormat.label, adUnitIdentifier]; + return; + } + + [adView startAutoRefresh]; + }); +} + +- (void)stopAdViewAutoRefreshForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Stopping %@ auto refresh for ad unit identifier \"%@\"", adFormat.label, adUnitIdentifier]; + + [self.disabledAutoRefreshAdViewAdUnitIdentifiers addObject: adUnitIdentifier]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !adView ) + { + [self log: @"%@ does not exist for ad unit identifier %@.", adFormat.label, adUnitIdentifier]; + return; + } + + [adView stopAutoRefresh]; + }); +} + +- (void)setAdViewWidth:(CGFloat)width forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting width %f for \"%@\" with ad unit identifier \"%@\"", width, adFormat, adUnitIdentifier]; + + BOOL isBannerOrLeader = adFormat.isBannerOrLeaderAd; + + // Banners and leaders need to be at least 320pts wide. + CGFloat minWidth = isBannerOrLeader ? MAAdFormat.banner.size.width : adFormat.size.width; + if ( width < minWidth ) + { + [self log: @"The provided width: %f is smaller than the minimum required width: %f for ad format: %@. Automatically setting width to %f.", width, minWidth, adFormat, minWidth]; + } + + CGFloat widthToSet = MAX( minWidth, width ); + self.adViewWidths[adUnitIdentifier] = @(widthToSet); + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + }); +} + +- (void)updateAdViewPosition:(NSString *)adViewPosition withOffset:(CGPoint)offset forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + self.adViewPositions[adUnitIdentifier] = adViewPosition; + self.adViewOffsets[adUnitIdentifier] = [NSValue valueWithCGPoint: offset]; + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + }); +} + +- (void)setAdViewExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat key:(NSString *)key value:(nullable NSString *)value +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting %@ extra with key: \"%@\" value: \"%@\"", adFormat, key, value]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( adView ) + { + [adView setExtraParameterForKey: key value: value]; + } + else + { + [self log: @"%@ does not exist for ad unit identifier \"%@\". Saving extra parameter to be set when it is created.", adFormat, adUnitIdentifier]; + + // The adView has not yet been created. Store the extra parameters, so that they can be added once the banner has been created. + NSMutableDictionary *extraParameters = self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier]; + if ( !extraParameters ) + { + extraParameters = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adViewExtraParametersToSetAfterCreate[adUnitIdentifier] = extraParameters; + } + + extraParameters[key] = value; + } + + // Certain extra parameters need to be handled immediately + [self handleExtraParameterChangesIfNeededForAdUnitIdentifier: adUnitIdentifier + adFormat: adFormat + key: key + value: value]; + }); +} + +- (void)setAdViewLocalExtraParameterForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat key:(NSString *)key value:(nullable id)value +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Setting %@ local extra with key: \"%@\" value: \"%@\"", adFormat, key, value]; + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( adView ) + { + [adView setLocalExtraParameterForKey: key value: value]; + } + else + { + [self log: @"%@ does not exist for ad unit identifier \"%@\". Saving local extra parameter to be set when it is created.", adFormat, adUnitIdentifier]; + + // The adView has not yet been created. Store the loca extra parameters, so that they can be added once the adview has been created. + NSMutableDictionary *localExtraParameters = self.adViewLocalExtraParametersToSetAfterCreate[adUnitIdentifier]; + if ( !localExtraParameters ) + { + localExtraParameters = [NSMutableDictionary dictionaryWithCapacity: 1]; + self.adViewLocalExtraParametersToSetAfterCreate[adUnitIdentifier] = localExtraParameters; + } + + localExtraParameters[key] = value; + } + }); +} + +- (void)setAdViewCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( adView ) + { + adView.customData = customData; + } + else + { + [self log: @"%@ does not exist for ad unit identifier %@. Saving custom data to be set when it is created.", adFormat, adUnitIdentifier]; + + // The adView has not yet been created. Store the custom data, so that they can be added once the AdView has been created. + self.adViewCustomDataToSetAfterCreate[adUnitIdentifier] = customData; + } + }); +} + +- (void)handleExtraParameterChangesIfNeededForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat key:(NSString *)key value:(nullable NSString *)value +{ + if ( MAAdFormat.mrec != adFormat ) + { + if ( [@"force_banner" isEqualToString: key] ) + { + BOOL shouldForceBanner = [NSNumber al_numberWithString: value].boolValue; + MAAdFormat *forcedAdFormat = shouldForceBanner ? MAAdFormat.banner : DEVICE_SPECIFIC_ADVIEW_AD_FORMAT; + + self.adViewAdFormats[adUnitIdentifier] = forcedAdFormat; + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: forcedAdFormat]; + } + else if ( [@"adaptive_banner" isEqualToString: key] ) + { + BOOL shouldUseAdaptiveBanner = [NSNumber al_numberWithString: value].boolValue; + if ( shouldUseAdaptiveBanner ) + { + [self.disabledAdaptiveBannerAdUnitIdentifiers removeObject: adUnitIdentifier]; + } + else + { + [self.disabledAdaptiveBannerAdUnitIdentifiers addObject: adUnitIdentifier]; + } + + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + } + } +} + +- (void)showAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Showing %@ with ad unit identifier \"%@\"", adFormat, adUnitIdentifier]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !view ) + { + [self log: @"%@ does not exist for ad unit identifier %@.", adFormat, adUnitIdentifier]; + + // The adView has not yet been created. Store the ad unit ID, so that it can be displayed once the banner has been created. + [self.adUnitIdentifiersToShowAfterCreate addObject: adUnitIdentifier]; + } + else + { + // Check edge case where ad may be detatched from view controller + if ( !view.window.rootViewController ) + { + [self log: @"%@ missing view controller - re-attaching to %@...", adFormat, [self unityViewController]]; + + UIViewController *rootViewController = [self unityViewController]; + [rootViewController.view addSubview: view]; + + [self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + } + } + + self.safeAreaBackground.hidden = NO; + view.hidden = NO; + + if ( ![self.disabledAutoRefreshAdViewAdUnitIdentifiers containsObject: adUnitIdentifier] ) + { + [view startAutoRefresh]; + } + }); +} + +- (void)hideAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Hiding %@ with ad unit identifier \"%@\"", adFormat, adUnitIdentifier]; + [self.adUnitIdentifiersToShowAfterCreate removeObject: adUnitIdentifier]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + view.hidden = YES; + self.safeAreaBackground.hidden = YES; + + [view stopAutoRefresh]; + }); +} + +- (NSString *)adViewLayoutForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + [self log: @"Getting %@ position with ad unit identifier \"%@\"", adFormat, adUnitIdentifier]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + if ( !view ) + { + [self log: @"%@ does not exist for ad unit identifier %@", adFormat, adUnitIdentifier]; + + return @""; + } + + CGRect adViewFrame = view.frame; + return [MAUnityAdManager serializeParameters: @{@"origin_x" : [NSString stringWithFormat: @"%f", adViewFrame.origin.x], + @"origin_y" : [NSString stringWithFormat: @"%f", adViewFrame.origin.y], + @"width" : [NSString stringWithFormat: @"%f", CGRectGetWidth(adViewFrame)], + @"height" : [NSString stringWithFormat: @"%f", CGRectGetHeight(adViewFrame)]}]; +} + +- (void)destroyAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + [self log: @"Destroying %@ with ad unit identifier \"%@\"", adFormat, adUnitIdentifier]; + + MAAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + view.delegate = nil; + view.revenueDelegate = nil; + view.adReviewDelegate = nil; + + [view removeFromSuperview]; + + [self.adViews removeObjectForKey: adUnitIdentifier]; + [self.adViewAdFormats removeObjectForKey: adUnitIdentifier]; + [self.adViewPositions removeObjectForKey: adUnitIdentifier]; + [self.adViewOffsets removeObjectForKey: adUnitIdentifier]; + [self.adViewWidths removeObjectForKey: adUnitIdentifier]; + [self.verticalAdViewFormats removeObjectForKey: adUnitIdentifier]; + [self.disabledAdaptiveBannerAdUnitIdentifiers removeObject: adUnitIdentifier]; + }); +} + +- (void)logInvalidAdFormat:(MAAdFormat *)adFormat +{ + [self log: @"invalid ad format: %@, from %@", adFormat, [NSThread callStackSymbols]]; +} + +- (void)log:(NSString *)format, ... +{ + va_list valist; + va_start(valist, format); + NSString *message = [[NSString alloc] initWithFormat: format arguments: valist]; + va_end(valist); + + NSLog(@"[%@] [%@] %@", SDK_TAG, TAG, message); +} + ++ (void)log:(NSString *)format, ... +{ + va_list valist; + va_start(valist, format); + NSString *message = [[NSString alloc] initWithFormat: format arguments: valist]; + va_end(valist); + + NSLog(@"[%@] [%@] %@", SDK_TAG, TAG, message); +} + +- (MAInterstitialAd *)retrieveInterstitialForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MAInterstitialAd *result = self.interstitials[adUnitIdentifier]; + if ( !result ) + { + result = [[MAInterstitialAd alloc] initWithAdUnitIdentifier: adUnitIdentifier sdk: self.sdk]; + result.delegate = self; + result.revenueDelegate = self; + result.adReviewDelegate = self; + + self.interstitials[adUnitIdentifier] = result; + } + + return result; +} + +- (MAAppOpenAd *)retrieveAppOpenAdForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MAAppOpenAd *result = self.appOpenAds[adUnitIdentifier]; + if ( !result ) + { + result = [[MAAppOpenAd alloc] initWithAdUnitIdentifier: adUnitIdentifier sdk: self.sdk]; + result.delegate = self; + result.revenueDelegate = self; + + self.appOpenAds[adUnitIdentifier] = result; + } + + return result; +} + +- (MARewardedAd *)retrieveRewardedAdForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MARewardedAd *result = self.rewardedAds[adUnitIdentifier]; + if ( !result ) + { + result = [MARewardedAd sharedWithAdUnitIdentifier: adUnitIdentifier sdk: self.sdk]; + result.delegate = self; + result.revenueDelegate = self; + result.adReviewDelegate = self; + + self.rewardedAds[adUnitIdentifier] = result; + } + + return result; +} + +- (MARewardedInterstitialAd *)retrieveRewardedInterstitialAdForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + MARewardedInterstitialAd *result = self.rewardedInterstitialAds[adUnitIdentifier]; + if ( !result ) + { + result = [[MARewardedInterstitialAd alloc] initWithAdUnitIdentifier: adUnitIdentifier sdk: self.sdk]; + result.delegate = self; + result.revenueDelegate = self; + result.adReviewDelegate = self; + + self.rewardedInterstitialAds[adUnitIdentifier] = result; + } + + return result; +} + +- (MAAdView *)retrieveAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + return [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat atPosition: nil withOffset: CGPointZero]; +} + +- (MAAdView *)retrieveAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat atPosition:(NSString *)adViewPosition withOffset:(CGPoint)offset +{ + MAAdView *result = self.adViews[adUnitIdentifier]; + if ( !result && adViewPosition ) + { + result = [[MAAdView alloc] initWithAdUnitIdentifier: adUnitIdentifier adFormat: adFormat sdk: self.sdk]; + // There is a Unity bug where if an empty UIView is on screen with user interaction enabled, and a user interacts with it, it just passes the events to random parts of the screen. + result.userInteractionEnabled = NO; + result.translatesAutoresizingMaskIntoConstraints = NO; + result.delegate = self; + result.revenueDelegate = self; + result.adReviewDelegate = self; + + self.adViews[adUnitIdentifier] = result; + self.adViewPositions[adUnitIdentifier] = adViewPosition; + self.adViewOffsets[adUnitIdentifier] = [NSValue valueWithCGPoint: offset]; + + UIViewController *rootViewController = [self unityViewController]; + [rootViewController.view addSubview: result]; + + // Allow pubs to pause auto-refresh immediately, by default. + [result setExtraParameterForKey: @"allow_pause_auto_refresh_immediately" value: @"true"]; + } + + return result; +} + +- (void)positionAdViewForAd:(MAAd *)ad +{ + [self positionAdViewForAdUnitIdentifier: ad.adUnitIdentifier adFormat: ad.format]; +} + +- (void)positionAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(MAAdFormat *)adFormat +{ + max_unity_dispatch_on_main_thread(^{ + MAAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat]; + NSString *adViewPosition = self.adViewPositions[adUnitIdentifier]; + NSValue *adViewPositionValue = self.adViewOffsets[adUnitIdentifier]; + CGPoint adViewOffset = [adViewPositionValue CGPointValue]; + BOOL isAdaptiveBannerDisabled = [self.disabledAdaptiveBannerAdUnitIdentifiers containsObject: adUnitIdentifier]; + BOOL isWidthPtsOverridden = self.adViewWidths[adUnitIdentifier] != nil; + + UIView *superview = adView.superview; + if ( !superview ) return; + + // Deactivate any previous constraints and reset rotation so that the banner can be positioned again. + NSArray *activeConstraints = self.adViewConstraints[adUnitIdentifier]; + [NSLayoutConstraint deactivateConstraints: activeConstraints]; + adView.transform = CGAffineTransformIdentity; + [self.verticalAdViewFormats removeObjectForKey: adUnitIdentifier]; + + // Ensure superview contains the safe area background. + if ( ![superview.subviews containsObject: self.safeAreaBackground] ) + { + [self.safeAreaBackground removeFromSuperview]; + [superview insertSubview: self.safeAreaBackground belowSubview: adView]; + } + + // Deactivate any previous constraints and reset visibility state so that the safe area background can be positioned again. + [NSLayoutConstraint deactivateConstraints: self.safeAreaBackground.constraints]; + self.safeAreaBackground.hidden = adView.hidden; + + // + // Determine ad width + // + CGFloat adViewWidth; + + // Check if publisher has overridden width as points + if ( isWidthPtsOverridden ) + { + adViewWidth = self.adViewWidths[adUnitIdentifier].floatValue; + } + // Top center / bottom center stretches full screen + else if ( [adViewPosition isEqual: @"top_center"] || [adViewPosition isEqual: @"bottom_center"] ) + { + adViewWidth = CGRectGetWidth(KEY_WINDOW.bounds); + } + // Else use standard widths of 320, 728, or 300 + else + { + adViewWidth = adFormat.size.width; + } + + // + // Determine ad height + // + CGFloat adViewHeight; + + if ( (adFormat == MAAdFormat.banner || adFormat == MAAdFormat.leader) && !isAdaptiveBannerDisabled ) + { + adViewHeight = [adFormat adaptiveSizeForWidth: adViewWidth].height; + } + else + { + adViewHeight = adFormat.size.height; + } + + CGSize adViewSize = CGSizeMake(adViewWidth, adViewHeight); + + // All positions have constant height + NSMutableArray *constraints = [NSMutableArray arrayWithObject: [adView.heightAnchor constraintEqualToConstant: adViewSize.height]]; + + UILayoutGuide *layoutGuide = superview.safeAreaLayoutGuide; + + if ( [adViewPosition isEqual: @"top_center"] || [adViewPosition isEqual: @"bottom_center"] ) + { + // Non AdMob banners will still be of 50/90 points tall. Set the auto sizing mask such that the inner ad view is pinned to the bottom or top according to the ad view position. + if ( !isAdaptiveBannerDisabled ) + { + adView.autoresizingMask = UIViewAutoresizingFlexibleWidth; + + if ( [@"top_center" isEqual: adViewPosition] ) + { + adView.autoresizingMask |= UIViewAutoresizingFlexibleBottomMargin; + } + else // bottom_center + { + adView.autoresizingMask |= UIViewAutoresizingFlexibleTopMargin; + } + } + + // If publisher actually provided a banner background color + if ( self.publisherBannerBackgroundColor && adFormat != MAAdFormat.mrec ) + { + if ( isWidthPtsOverridden ) + { + [constraints addObjectsFromArray: @[[adView.widthAnchor constraintEqualToConstant: adViewWidth], + [adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor], + [self.safeAreaBackground.widthAnchor constraintEqualToConstant: adViewWidth], + [self.safeAreaBackground.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor]]]; + + if ( [adViewPosition isEqual: @"top_center"] ) + { + [constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor], + [self.safeAreaBackground.topAnchor constraintEqualToAnchor: superview.topAnchor], + [self.safeAreaBackground.bottomAnchor constraintEqualToAnchor: adView.topAnchor]]]; + } + else // bottom_center + { + [constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor], + [self.safeAreaBackground.topAnchor constraintEqualToAnchor: adView.bottomAnchor], + [self.safeAreaBackground.bottomAnchor constraintEqualToAnchor: superview.bottomAnchor]]]; + } + } + else + { + [constraints addObjectsFromArray: @[[adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor], + [adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor], + [self.safeAreaBackground.leftAnchor constraintEqualToAnchor: superview.leftAnchor], + [self.safeAreaBackground.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + + if ( [adViewPosition isEqual: @"top_center"] ) + { + [constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor], + [self.safeAreaBackground.topAnchor constraintEqualToAnchor: superview.topAnchor], + [self.safeAreaBackground.bottomAnchor constraintEqualToAnchor: adView.topAnchor]]]; + } + else // bottom_center + { + [constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor], + [self.safeAreaBackground.topAnchor constraintEqualToAnchor: adView.bottomAnchor], + [self.safeAreaBackground.bottomAnchor constraintEqualToAnchor: superview.bottomAnchor]]]; + } + } + } + // If pub does not have a background color set or this is not a banner + else + { + self.safeAreaBackground.hidden = YES; + + [constraints addObjectsFromArray: @[[adView.widthAnchor constraintEqualToConstant: adViewWidth], + [adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor]]]; + + if ( [adViewPosition isEqual: @"top_center"] ) + { + [constraints addObject: [adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor]]; + } + else // BottomCenter + { + [constraints addObject: [adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor]]; + } + } + } + // Check if the publisher wants vertical banners. + else if ( [adViewPosition isEqual: @"center_left"] || [adViewPosition isEqual: @"center_right"] ) + { + if ( MAAdFormat.mrec == adFormat ) + { + [constraints addObject: [adView.widthAnchor constraintEqualToConstant: adViewSize.width]]; + + if ( [adViewPosition isEqual: @"center_left"] ) + { + [constraints addObjectsFromArray: @[[adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor], + [adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor]]]; + + [constraints addObjectsFromArray: @[[self.safeAreaBackground.rightAnchor constraintEqualToAnchor: layoutGuide.leftAnchor], + [self.safeAreaBackground.leftAnchor constraintEqualToAnchor: superview.leftAnchor]]]; + } + else // center_right + { + [constraints addObjectsFromArray: @[[adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor], + [adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + + [constraints addObjectsFromArray: @[[self.safeAreaBackground.leftAnchor constraintEqualToAnchor: layoutGuide.rightAnchor], + [self.safeAreaBackground.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + } + } + else + { + /* Align the center of the view such that when rotated it snaps into place. + * + * +---+---+-------+ + * | | | + * | | | + * | | | + * | | | + * | | | + * | | | + * +-------------+---+-----------+--+ + * | | + | + | | + * +-------------+---+-----------+--+ + * <+> | | + * |+ | | + * || | | + * || | | + * || | | + * || | | + * +|--+-----------+ + * v + * Banner Half Height + */ + self.safeAreaBackground.hidden = YES; + + adView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI_2); + + CGFloat width; + // If the publiser has a background color set - set the width to the height of the screen, to span the ad across the screen after it is rotated. + if ( self.publisherBannerBackgroundColor ) + { + if ( isWidthPtsOverridden ) + { + width = adViewWidth; + } + else + { + width = CGRectGetHeight(KEY_WINDOW.bounds); + } + } + // Otherwise - we shouldn't span the banner the width of the realm (there might be user-interactable UI on the sides) + else + { + width = adViewWidth; + } + [constraints addObject: [adView.widthAnchor constraintEqualToConstant: width]]; + + // Set constraints such that the center of the banner aligns with the center left or right as needed. That way, once rotated, the banner snaps into place. + [constraints addObject: [adView.centerYAnchor constraintEqualToAnchor: superview.centerYAnchor]]; + + // Place the center of the banner half the height of the banner away from the side. If we align the center exactly with the left/right anchor, only half the banner will be visible. + CGFloat bannerHalfHeight = adViewSize.height / 2.0; + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + if ( [adViewPosition isEqual: @"center_left"] ) + { + NSLayoutAnchor *anchor = ( orientation == UIInterfaceOrientationLandscapeRight ) ? layoutGuide.leftAnchor : superview.leftAnchor; + [constraints addObject: [adView.centerXAnchor constraintEqualToAnchor: anchor constant: bannerHalfHeight]]; + } + else // CenterRight + { + NSLayoutAnchor *anchor = ( orientation == UIInterfaceOrientationLandscapeLeft ) ? layoutGuide.rightAnchor : superview.rightAnchor; + [constraints addObject: [adView.centerXAnchor constraintEqualToAnchor: anchor constant: -bannerHalfHeight]]; + } + + // Store the ad view with format, so that it can be updated when the orientation changes. + self.verticalAdViewFormats[adUnitIdentifier] = adFormat; + + // If adaptive - make top flexible since we anchor with the bottom of the banner at the edge of the screen + if ( !isAdaptiveBannerDisabled ) + { + adView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; + } + } + } + // Otherwise, publisher will likely construct his own views around the adview + else + { + self.safeAreaBackground.hidden = YES; + + [constraints addObject: [adView.widthAnchor constraintEqualToConstant: adViewWidth]]; + + if ( [adViewPosition isEqual: @"top_left"] ) + { + [constraints addObjectsFromArray: @[[adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor constant: adViewOffset.x], + [adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor constant: adViewOffset.y]]]; + } + else if ( [adViewPosition isEqual: @"top_right"] ) + { + [constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor], + [adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + } + else if ( [adViewPosition isEqual: @"centered"] ) + { + [constraints addObjectsFromArray: @[[adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor], + [adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor]]]; + } + else if ( [adViewPosition isEqual: @"bottom_left"] ) + { + [constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor], + [adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor]]]; + } + else if ( [adViewPosition isEqual: @"bottom_right"] ) + { + [constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor], + [adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor]]]; + } + } + + self.adViewConstraints[adUnitIdentifier] = constraints; + + [NSLayoutConstraint activateConstraints: constraints]; + }); +} + +- (UIViewController *)unityViewController +{ + // Handle edge case where `UnityGetGLViewController()` returns nil + return UnityGetGLViewController() ?: UnityGetMainWindow().rootViewController ?: [KEY_WINDOW rootViewController]; +} + +- (void)forwardUnityEventWithArgs:(NSDictionary *)args +{ +#if !IS_TEST_APP + extern bool _didResignActive; + // We should not call any script callbacks when application is not active. Suspend the callback queue if resign is active. + // We'll resume the queue once the application becomes active again. + self.backgroundCallbackEventsQueue.suspended = _didResignActive; +#endif + + [self.backgroundCallbackEventsQueue addOperationWithBlock:^{ + NSString *serializedParameters = [MAUnityAdManager serializeParameters: args]; + backgroundCallback(serializedParameters.UTF8String); + }]; +} + ++ (NSString *)serializeParameters:(NSDictionary *)dict +{ + NSData *jsonData = [NSJSONSerialization dataWithJSONObject: dict options: 0 error: nil]; + return [[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding]; +} + ++ (NSDictionary *)deserializeParameters:(nullable NSString *)serialized +{ + if ( serialized.length > 0 ) + { + NSError *error; + NSDictionary *deserialized = [NSJSONSerialization JSONObjectWithData: [serialized dataUsingEncoding:NSUTF8StringEncoding] + options: 0 + error: &error]; + if ( error ) + { + [self log: @"Failed to deserialize (%@) with error %@", serialized, error]; + return @{}; + } + + return deserialized; + } + else + { + return @{}; + } +} + +- (MAAdFormat *)adViewAdFormatForAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + if ( self.adViewAdFormats[adUnitIdentifier] ) + { + return self.adViewAdFormats[adUnitIdentifier]; + } + else + { + return DEVICE_SPECIFIC_ADVIEW_AD_FORMAT; + } +} + +- (NSString *)requestLatencyMillisFromRequestLatency:(NSTimeInterval)requestLatency +{ + // Convert latency from seconds to milliseconds to match Android. + long requestLatencyMillis = requestLatency * 1000; + return @(requestLatencyMillis).stringValue; +} + +#pragma mark - User Service + +- (void)didDismissUserConsentDialog +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self forwardUnityEventWithArgs: @{@"name" : @"OnSdkConsentDialogDismissedEvent"}]; + }); +} + +#pragma mark - CMP Service + +- (void)showCMPForExistingUser +{ + [self.sdk.cmpService showCMPForExistingUserWithCompletion:^(ALCMPError * _Nullable error) { + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSMutableDictionary *args = [NSMutableDictionary dictionaryWithCapacity: 2]; + args[@"name"] = @"OnCmpCompletedEvent"; + + if ( error ) + { + args[@"error"] = @{@"code": @(error.code), + @"message": error.message, + @"cmpCode": @(error.cmpCode), + @"cmpMessage": error.cmpMessage, + @"keepInBackground": @(YES)}; + } + + [self forwardUnityEventWithArgs: args]; + }); + }]; +} + +#pragma mark - Application + +- (void)applicationPaused:(NSNotification *)notification +{ + [self notifyApplicationStateChangedEventForPauseState: YES]; +} + +- (void)applicationResumed:(NSNotification *)notification +{ + [self notifyApplicationStateChangedEventForPauseState: NO]; +} + +- (void)notifyApplicationStateChangedEventForPauseState:(BOOL)isPaused +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self forwardUnityEventWithArgs: @{@"name": @"OnApplicationStateChanged", + @"isPaused": @(isPaused)}]; + }); +} + +- (MAAd *)adWithAdUnitIdentifier:(NSString *)adUnitIdentifier +{ + @synchronized ( self.adInfoDictLock ) + { + return self.adInfoDict[adUnitIdentifier]; + } +} + +@end diff --git a/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta new file mode 100644 index 0000000..8c3581e --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m.meta @@ -0,0 +1,109 @@ +fileFormatVersion: 2 +guid: 2973e70bd2fa74984b35aea07ae9db52 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityAdManager.m +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + Exclude tvOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm new file mode 100644 index 0000000..391d4f9 --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm @@ -0,0 +1,1146 @@ +// +// MAUnityPlugin.mm +// AppLovin MAX Unity Plugin +// + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#import "MAUnityAdManager.h" + +#define VERSION @"7.0.0" +#define NSSTRING(_X) ( (_X != NULL) ? [NSString stringWithCString: _X encoding: NSStringEncodingConversionAllowLossy].al_stringByTrimmingWhitespace : nil) + +@interface NSString (ALUtils) +@property (nonatomic, copy, readonly) NSString *al_stringByTrimmingWhitespace; +@property (assign, readonly, getter=al_isValidString) BOOL al_validString; +@end + +@interface ALSdkInitializationConfigurationBuilder (ALUtils) +- (void)setSdkKey:(NSString *)sdkKey; +@end + +// When native code plugin is implemented in .mm / .cpp file, then functions +// should be surrounded with extern "C" block to conform C function naming rules +extern "C" +{ + static NSString *const TAG = @"MAUnityPlugin"; + static NSString *const KeySdkKey = @"SdkKey"; + + UIView* UnityGetGLView(); + + static ALSdkInitializationConfigurationBuilder *_initConfigurationBuilder; + static ALSdk *_sdk; + static MAUnityAdManager *_adManager; + + static bool _isSdkInitialized = false; + static bool _initializeSdkCalled = false; + + // Helper method to create C string copy + static const char * cStringCopy(NSString *string); + // Helper method to log errors + void logUninitializedAccessError(const char *callingMethod); + + ALSdk *getSdk() + { + if ( !_sdk ) + { + _sdk = [ALSdk shared]; + } + + return _sdk; + } + + MAUnityAdManager *getAdManager() + { + if ( !_adManager ) + { + _adManager = [MAUnityAdManager shared]; + } + + return _adManager; + } + + ALSdkInitializationConfigurationBuilder *getInitConfigurationBuilder() + { + if ( !_initConfigurationBuilder ) + { + NSString *sdkKey = [getSdk().settings.extraParameters al_stringForKey: KeySdkKey]; + _initConfigurationBuilder = [ALSdkInitializationConfiguration builderWithSdkKey: sdkKey]; + } + + return _initConfigurationBuilder; + } + + int getConsentStatusValue(NSNumber *consentStatus) + { + if ( consentStatus ) + { + return consentStatus.intValue; + } + else + { + return -1; + } + } + + id getLocalExtraParameterValue(const char *json) + { + NSData *jsonData = [NSSTRING(json) dataUsingEncoding: NSUTF8StringEncoding]; + NSError *error; + NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData: jsonData + options: 0 + error: &error]; + + if ( error ) + { + return nil; + } + else + { + return jsonDict[@"value"]; + } + } + + NSArray * toStringArray(char **arrayPointer, int size) + { + NSMutableArray *array = [NSMutableArray arrayWithCapacity: size]; + for ( int i = 0; i < size; i++ ) + { + NSString *element = NSSTRING(arrayPointer[i]); + if ( element ) + { + [array addObject: element]; + } + } + + return array; + } + + MASegmentCollection *getSegmentCollection(const char *collectionJson) + { + MASegmentCollectionBuilder *segmentCollectionBuilder = [MASegmentCollection builder]; + + NSDictionary *jsonDict = [MAUnityAdManager deserializeParameters: [NSString stringWithUTF8String: collectionJson]]; + + NSArray *segmentsArray = jsonDict[@"segments"]; + for (NSDictionary *segmentDict in segmentsArray) + { + NSNumber *key = segmentDict[@"key"]; + NSArray *valuesArray = segmentDict[@"values"]; + NSMutableArray *values = [NSMutableArray array]; + for (NSNumber *value in valuesArray) + { + [values addObject:value]; + } + + MASegment *segment = [[MASegment alloc] initWithKey:key values:values]; + [segmentCollectionBuilder addSegment:segment]; + } + + return [segmentCollectionBuilder build]; + } + + void _MaxSetBackgroundCallback(ALUnityBackgroundCallback backgroundCallback) + { + [MAUnityAdManager setUnityBackgroundCallback: backgroundCallback]; + } + + void _MaxSetSdkKey(const char *sdkKey) + { + if (!sdkKey) return; + + NSString *sdkKeyStr = [NSString stringWithUTF8String: sdkKey]; + [getInitConfigurationBuilder() setSdkKey: sdkKeyStr]; + } + + void _MaxInitializeSdk(const char *serializedAdUnitIdentifiers, const char *serializedMetaData) + { + ALSdkInitializationConfigurationBuilder *initConfigurationBuilder = getInitConfigurationBuilder(); + initConfigurationBuilder.mediationProvider = @"max"; + initConfigurationBuilder.pluginVersion = [@"Max-Unity-" stringByAppendingString: VERSION]; + initConfigurationBuilder.adUnitIdentifiers = [[NSString stringWithUTF8String: serializedAdUnitIdentifiers] componentsSeparatedByString: @","]; + + [getSdk().settings setExtraParameterForKey: @"applovin_unity_metadata" value: NSSTRING(serializedMetaData)]; + + ALSdkInitializationConfiguration *initConfig = [initConfigurationBuilder build]; + + [getAdManager() initializeSdkWithConfiguration: initConfig andCompletionHandler:^(ALSdkConfiguration *configuration) { + _isSdkInitialized = true; + }]; + + _initializeSdkCalled = true; + } + + bool _MaxIsInitialized() + { + return _isSdkInitialized; + } + + const char * _MaxGetAvailableMediatedNetworks() + { + NSArray *availableMediatedNetworks = [getSdk() availableMediatedNetworks]; + + // Create array of serialized network strings + NSMutableArray *> *serializedNetworks = [NSMutableArray arrayWithCapacity: availableMediatedNetworks.count]; + for ( MAMediatedNetworkInfo *mediatedNetwork in availableMediatedNetworks ) + { + NSDictionary *mediatedNetworkDictionary = @{@"name" : mediatedNetwork.name, + @"adapterClassName" : mediatedNetwork.adapterClassName, + @"adapterVersion" : mediatedNetwork.adapterVersion, + @"sdkVersion" : mediatedNetwork.sdkVersion}; + [serializedNetworks addObject: mediatedNetworkDictionary]; + } + + NSData *jsonData = [NSJSONSerialization dataWithJSONObject: serializedNetworks options: 0 error: nil]; + return cStringCopy([[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding]); + } + + void _MaxShowMediationDebugger() + { + if ( !_initializeSdkCalled ) + { + NSLog(@"[%@] Failed to show mediation debugger - please ensure the AppLovin MAX Unity Plugin has been initialized by calling 'MaxSdk.InitializeSdk();'!", TAG); + return; + } + + [getSdk() showMediationDebugger]; + } + + void _MaxShowCreativeDebugger() + { + if ( !_initializeSdkCalled ) + { + NSLog(@"[%@] Failed to show creative debugger - please ensure the AppLovin MAX Unity Plugin has been initialized by calling 'MaxSdk.InitializeSdk();'!", TAG); + return; + } + + [getSdk() showCreativeDebugger]; + } + + void _MaxShowConsentDialog() + { + NSLog(@"[%@] Failed to show consent dialog - Unavailable on iOS, please use the consent flow: https://developers.applovin.com/en/unity/overview/terms-and-privacy-policy-flow", TAG); + } + + int _MaxConsentDialogState() + { + if ( !_isSdkInitialized ) return ALConsentDialogStateUnknown; + + return (int) getSdk().configuration.consentDialogState; + } + + void _MaxSetUserId(const char *userId) + { + getSdk().settings.userIdentifier = NSSTRING(userId); + } + + void _MaxSetSegmentCollection(const char *collectionJson) + { + if ( _initializeSdkCalled ) + { + NSLog(@"[%@] Segment collection must be set before MAX SDK is initialized", TAG); + return; + } + + getInitConfigurationBuilder().segmentCollection = getSegmentCollection(collectionJson); + } + + const char * _MaxGetSdkConfiguration() + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxGetSdkConfiguration"); + return cStringCopy(@""); + } + + NSString *consentFlowUserGeographyStr = @(getSdk().configuration.consentFlowUserGeography).stringValue; + NSString *consentDialogStateStr = @(getSdk().configuration.consentDialogState).stringValue; + NSString *appTrackingStatus = @(getSdk().configuration.appTrackingTransparencyStatus).stringValue; // Deliberately name it `appTrackingStatus` to be a bit more generic (in case Android introduces a similar concept) + + return cStringCopy([MAUnityAdManager serializeParameters: @{@"consentFlowUserGeography" : consentFlowUserGeographyStr, + @"consentDialogState" : consentDialogStateStr, + @"countryCode" : getSdk().configuration.countryCode, + @"appTrackingStatus" : appTrackingStatus, + @"isSuccessfullyInitialized" : @([getSdk() isInitialized]), + @"isTestModeEnabled" : @([getSdk().configuration isTestModeEnabled])}]); + } + + void _MaxSetHasUserConsent(bool hasUserConsent) + { + [ALPrivacySettings setHasUserConsent: hasUserConsent]; + } + + bool _MaxHasUserConsent() + { + return [ALPrivacySettings hasUserConsent]; + } + + bool _MaxIsUserConsentSet() + { + return [ALPrivacySettings isUserConsentSet]; + } + + void _MaxSetDoNotSell(bool doNotSell) + { + [ALPrivacySettings setDoNotSell: doNotSell]; + } + + bool _MaxIsDoNotSell() + { + return [ALPrivacySettings isDoNotSell]; + } + + bool _MaxIsDoNotSellSet() + { + return [ALPrivacySettings isDoNotSellSet]; + } + + void _MaxCreateBanner(const char *adUnitIdentifier, const char *bannerPosition) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxCreateBanner"); + return; + } + + [getAdManager() createBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) atPosition: NSSTRING(bannerPosition)]; + } + + void _MaxCreateBannerXY(const char *adUnitIdentifier, const float x, const float y) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxCreateBannerXY"); + return; + } + + [getAdManager() createBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) x: x y: y]; + } + + void _MaxLoadBanner(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxLoadBanner"); + return; + } + + [getAdManager() loadBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetBannerBackgroundColor(const char *adUnitIdentifier, const char *hexColorCode) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetBannerBackgroundColor"); + return; + } + + [getAdManager() setBannerBackgroundColorForAdUnitIdentifier: NSSTRING(adUnitIdentifier) hexColorCode: NSSTRING(hexColorCode)]; + } + + void _MaxSetBannerPlacement(const char *adUnitIdentifier, const char *placement) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetBannerPlacement"); + return; + } + + [getAdManager() setBannerPlacement: NSSTRING(placement) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxStartBannerAutoRefresh(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxStartBannerAutoRefresh"); + return; + } + + [getAdManager() startBannerAutoRefreshForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxStopBannerAutoRefresh(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxStopBannerAutoRefresh"); + return; + } + + [getAdManager() stopBannerAutoRefreshForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetBannerExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetBannerExtraParameter"); + return; + } + + [getAdManager() setBannerExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetBannerLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetBannerLocalExtraParameter"); + return; + } + + [getAdManager() setBannerLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id) value]; + } + + void _MaxSetBannerLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetBannerLocalExtraParameter"); + return; + } + + id value = getLocalExtraParameterValue(json); + [getAdManager() setBannerLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + + void _MaxSetBannerCustomData(const char *adUnitIdentifier, const char *customData) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetBannerCustomData"); + return; + } + + [getAdManager() setBannerCustomData: NSSTRING(customData) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetBannerWidth(const char *adUnitIdentifier, const float width) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetBannerWidth"); + return; + } + + [getAdManager() setBannerWidth: width forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateBannerPosition(const char *adUnitIdentifier, const char *bannerPosition) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxUpdateBannerPosition"); + return; + } + + [getAdManager() updateBannerPosition: NSSTRING(bannerPosition) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateBannerPositionXY(const char *adUnitIdentifier, const float x, const float y) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxUpdateBannerPositionXY"); + return; + } + + [getAdManager() updateBannerPosition: x y: y forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowBanner(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxShowBanner"); + return; + } + + [getAdManager() showBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxDestroyBanner(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxDestroyBanner"); + return; + } + + [getAdManager() destroyBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxHideBanner(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxHideBanner"); + return; + } + + [getAdManager() hideBannerWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + const char * _MaxGetBannerLayout(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxGetBannerLayout"); + return cStringCopy(@""); + } + + return cStringCopy([getAdManager() bannerLayoutForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]); + } + + void _MaxCreateMRec(const char *adUnitIdentifier, const char *mrecPosition) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxCreateMRec"); + return; + } + + [getAdManager() createMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) atPosition: NSSTRING(mrecPosition)]; + } + + void _MaxCreateMRecXY(const char *adUnitIdentifier, const float x, const float y) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxCreateMRecXY"); + return; + } + + [getAdManager() createMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) x: x y: y]; + } + + void _MaxLoadMRec(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxLoadMRec"); + return; + } + + [getAdManager() loadMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetMRecPlacement(const char *adUnitIdentifier, const char *placement) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetMRecPlacement"); + return; + } + + [getAdManager() setMRecPlacement: NSSTRING(placement) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxStartMRecAutoRefresh(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxStartMRecAutoRefresh"); + return; + } + + [getAdManager() startMRecAutoRefreshForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxStopMRecAutoRefresh(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxStopMRecAutoRefresh"); + return; + } + + [getAdManager() stopMRecAutoRefreshForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateMRecPosition(const char *adUnitIdentifier, const char *mrecPosition) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxUpdateMRecPosition"); + return; + } + + [getAdManager() updateMRecPosition: NSSTRING(mrecPosition) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxUpdateMRecPositionXY(const char *adUnitIdentifier, const float x, const float y) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxUpdateMRecPositionXY"); + return; + } + + [getAdManager() updateMRecPosition: x y: y forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowMRec(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxShowMRec"); + return; + } + + [getAdManager() showMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxDestroyMRec(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxDestroyMRec"); + return; + } + + [getAdManager() destroyMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxHideMRec(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxHideMRec"); + return; + } + + [getAdManager() hideMRecWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetMRecExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetMRecExtraParameter"); + return; + } + + [getAdManager() setMRecExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetMRecLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetMRecLocalExtraParameter"); + return; + } + + [getAdManager() setMRecLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + void _MaxSetMRecLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetMRecLocalExtraParameter"); + return; + } + + id value = getLocalExtraParameterValue(json); + [getAdManager() setMRecLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + + void _MaxSetMRecCustomData(const char *adUnitIdentifier, const char *customData) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetMRecCustomData"); + return; + } + + [getAdManager() setMRecCustomData: NSSTRING(customData) forAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + const char * _MaxGetMRecLayout(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxGetMRecLayout"); + return cStringCopy(@""); + } + + return cStringCopy([getAdManager() mrecLayoutForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]); + } + + void _MaxLoadInterstitial(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxLoadInterstitial"); + return; + } + + [getAdManager() loadInterstitialWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetInterstitialExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetInterstitialExtraParameter"); + return; + } + + [getAdManager() setInterstitialExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetInterstitialLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetInterstitialLocalExtraParameter"); + return; + } + + [getAdManager() setInterstitialLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + void _MaxSetInterstitialLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetInterstitialLocalExtraParameter"); + return; + } + + id value = getLocalExtraParameterValue(json); + [getAdManager() setInterstitialLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + + bool _MaxIsInterstitialReady(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxIsInterstitialReady"); + return false; + } + + return [getAdManager() isInterstitialReadyWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowInterstitial(const char *adUnitIdentifier, const char *placement, const char *customData) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxShowInterstitial"); + return; + } + + [getAdManager() showInterstitialWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) placement: NSSTRING(placement) customData: NSSTRING(customData)]; + } + + void _MaxLoadAppOpenAd(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxLoadAppOpenAd"); + return; + } + + [getAdManager() loadAppOpenAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetAppOpenAdExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetAppOpenAdExtraParameter"); + return; + } + + [getAdManager() setAppOpenAdExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetAppOpenAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetAppOpenAdLocalExtraParameter"); + return; + } + + [getAdManager() setAppOpenAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + void _MaxSetAppOpenAdLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetAppOpenAdLocalExtraParameter"); + return; + } + + id value = getLocalExtraParameterValue(json); + [getAdManager() setAppOpenAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + + bool _MaxIsAppOpenAdReady(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxIsAppOpenAdReady"); + return false; + } + + return [getAdManager() isAppOpenAdReadyWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowAppOpenAd(const char *adUnitIdentifier, const char *placement, const char *customData) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxShowAppOpenAd"); + return; + } + + [getAdManager() showAppOpenAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) placement: NSSTRING(placement) customData: NSSTRING(customData)]; + } + + void _MaxLoadRewardedAd(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxLoadRewardedAd"); + return; + } + + [getAdManager() loadRewardedAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetRewardedAdExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetRewardedAdExtraParameter"); + return; + } + + [getAdManager() setRewardedAdExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetRewardedAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetRewardedAdLocalExtraParameter"); + return; + } + + [getAdManager() setRewardedAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + void _MaxSetRewardedAdLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetRewardedAdLocalExtraParameter"); + return; + } + + id value = getLocalExtraParameterValue(json); + [getAdManager() setRewardedAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + + bool _MaxIsRewardedAdReady(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxIsRewardedAdReady"); + return false; + } + + return [getAdManager() isRewardedAdReadyWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowRewardedAd(const char *adUnitIdentifier, const char *placement, const char *customData) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxShowRewardedAd"); + return; + } + + [getAdManager() showRewardedAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) placement: NSSTRING(placement) customData: NSSTRING(customData)]; + } + + void _MaxLoadRewardedInterstitialAd(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxLoadRewardedInterstitialAd"); + return; + } + + [getAdManager() loadRewardedInterstitialAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxSetRewardedInterstitialAdExtraParameter(const char *adUnitIdentifier, const char *key, const char *value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetRewardedInterstitialAdExtraParameter"); + return; + } + + [getAdManager() setRewardedInterstitialAdExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: NSSTRING(value)]; + } + + void _MaxSetRewardedInterstitialAdLocalExtraParameter(const char *adUnitIdentifier, const char *key, MAUnityRef value) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetRewardedInterstitialAdLocalExtraParameter"); + return; + } + + [getAdManager() setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: (__bridge id)value]; + } + + void _MaxSetRewardedInterstitialAdLocalExtraParameterJSON(const char *adUnitIdentifier, const char *key, const char *json) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxSetRewardedInterstitialAdLocalExtraParameter"); + return; + } + + id value = getLocalExtraParameterValue(json); + [getAdManager() setRewardedInterstitialAdLocalExtraParameterForAdUnitIdentifier: NSSTRING(adUnitIdentifier) + key: NSSTRING(key) + value: value]; + } + + bool _MaxIsRewardedInterstitialAdReady(const char *adUnitIdentifier) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxIsRewardedInterstitialAdReady"); + return false; + } + + return [getAdManager() isRewardedInterstitialAdReadyWithAdUnitIdentifier: NSSTRING(adUnitIdentifier)]; + } + + void _MaxShowRewardedInterstitialAd(const char *adUnitIdentifier, const char *placement, const char *customData) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxShowRewardedInterstitialAd"); + return; + } + + [getAdManager() showRewardedInterstitialAdWithAdUnitIdentifier: NSSTRING(adUnitIdentifier) placement: NSSTRING(placement) customData: NSSTRING(customData)]; + } + + void _MaxTrackEvent(const char *event, const char *parameters) + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxTrackEvent"); + return; + } + + [getAdManager() trackEvent: NSSTRING(event) parameters: NSSTRING(parameters)]; + } + + bool _MaxIsTablet() + { + return [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad; + } + + bool _MaxIsPhysicalDevice() + { + return !ALUtils.simulator; + } + + int _MaxGetTcfVendorConsentStatus(int vendorIdentifier) + { + NSNumber *consentStatus = [ALPrivacySettings tcfVendorConsentStatusForIdentifier: vendorIdentifier]; + return getConsentStatusValue(consentStatus); + } + + int _MaxGetAdditionalConsentStatus(int atpIdentifier) + { + NSNumber *consentStatus = [ALPrivacySettings additionalConsentStatusForIdentifier: atpIdentifier]; + return getConsentStatusValue(consentStatus); + } + + int _MaxGetPurposeConsentStatus(int purposeIdentifier) + { + NSNumber *consentStatus = [ALPrivacySettings purposeConsentStatusForIdentifier: purposeIdentifier]; + return getConsentStatusValue(consentStatus); + } + + int _MaxGetSpecialFeatureOptInStatus(int specialFeatureIdentifier) + { + NSNumber *consentStatus = [ALPrivacySettings specialFeatureOptInStatusForIdentifier: specialFeatureIdentifier]; + return getConsentStatusValue(consentStatus); + } + + static const char * cStringCopy(NSString *string) + { + const char *value = string.UTF8String; + return value ? strdup(value) : NULL; + } + + void _MaxSetMuted(bool muted) + { + getSdk().settings.muted = muted; + } + + bool _MaxIsMuted() + { + return getSdk().settings.muted; + } + + float _MaxScreenDensity() + { + return [UIScreen.mainScreen nativeScale]; + } + + const char * _MaxGetAdInfo(const char *adUnitIdentifier) + { + return cStringCopy([getAdManager() adInfoForAdUnitIdentifier: NSSTRING(adUnitIdentifier)]); + } + + const char * _MaxGetAdValue(const char *adUnitIdentifier, const char *key) + { + return cStringCopy([getAdManager() adValueForAdUnitIdentifier: NSSTRING(adUnitIdentifier) withKey: NSSTRING(key)]); + } + + void _MaxSetVerboseLogging(bool enabled) + { + getSdk().settings.verboseLoggingEnabled = enabled; + } + + bool _MaxIsVerboseLoggingEnabled() + { + return [getSdk().settings isVerboseLoggingEnabled]; + } + + void _MaxSetTestDeviceAdvertisingIdentifiers(char **advertisingIdentifiers, int size) + { + if ( _initializeSdkCalled ) + { + NSLog(@"[%@] Test device advertising IDs must be set before MAX SDK is initialized", TAG); + return; + } + + NSArray *advertisingIdentifiersArray = toStringArray(advertisingIdentifiers, size); + getInitConfigurationBuilder().testDeviceAdvertisingIdentifiers = advertisingIdentifiersArray; + } + + void _MaxSetCreativeDebuggerEnabled(bool enabled) + { + getSdk().settings.creativeDebuggerEnabled = enabled; + } + + void _MaxSetExceptionHandlerEnabled(bool enabled) + { + if ( _initializeSdkCalled ) + { + NSLog(@"[%@] Exception handler must be enabled/disabled before MAX SDK is initialized", TAG); + return; + } + + getInitConfigurationBuilder().exceptionHandlerEnabled = enabled; + } + + void _MaxSetExtraParameter(const char *key, const char *value) + { + NSString *stringKey = NSSTRING(key); + if ( ![stringKey al_isValidString] ) + { + NSLog(@"[%@] Failed to set extra parameter for nil or empty key: %@", TAG, stringKey); + return; + } + + ALSdkSettings *settings = getSdk().settings; + [settings setExtraParameterForKey: stringKey value: NSSTRING(value)]; + } + + int * _MaxGetSafeAreaInsets() + { + UIEdgeInsets safeAreaInsets = UnityGetGLView().safeAreaInsets; + static int insets[4] = {(int) safeAreaInsets.left, (int) safeAreaInsets.top, (int) safeAreaInsets.right, (int) safeAreaInsets.bottom}; + return insets; + } + + void _MaxShowCmpForExistingUser() + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxShowCmpForExistingUser"); + return; + } + + [getAdManager() showCMPForExistingUser]; + } + + bool _MaxHasSupportedCmp() + { + if ( !_initializeSdkCalled ) + { + logUninitializedAccessError("_MaxHasSupportedCmp"); + return false; + } + + return [getSdk().cmpService hasSupportedCMP]; + } + + float _MaxGetAdaptiveBannerHeight(const float width) + { + return [MAUnityAdManager adaptiveBannerHeightForWidth: width]; + } + + void logUninitializedAccessError(const char *callingMethod) + { + NSLog(@"[%@] Failed to execute: %s - please ensure the AppLovin MAX Unity Plugin has been initialized by calling 'MaxSdk.InitializeSdk();'!", TAG, callingMethod); + } +} + +#pragma clang diagnostic pop diff --git a/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta new file mode 100644 index 0000000..5ea08ff --- /dev/null +++ b/Assets/MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm.meta @@ -0,0 +1,109 @@ +fileFormatVersion: 2 +guid: 7e373ed7168b243e6b706e991ab5a643 +labels: +- al_max +- al_max_export_path-MaxSdk/AppLovin/Plugins/iOS/MAUnityPlugin.mm +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + Exclude tvOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation.meta b/Assets/MaxSdk/Mediation.meta new file mode 100644 index 0000000..103dd6f --- /dev/null +++ b/Assets/MaxSdk/Mediation.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dcf2020c4018447c9b91170c0f62d799 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Facebook.meta b/Assets/MaxSdk/Mediation/Facebook.meta new file mode 100644 index 0000000..339a799 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Facebook.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ceafa35ff4b964f12b9c025f47227c44 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Facebook/Editor.meta b/Assets/MaxSdk/Mediation/Facebook/Editor.meta new file mode 100644 index 0000000..4beff5e --- /dev/null +++ b/Assets/MaxSdk/Mediation/Facebook/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 28880992a399a48b7abe95b66649d711 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Facebook/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml b/Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml new file mode 100644 index 0000000..b303ae6 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml.meta b/Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..69b5d2c --- /dev/null +++ b/Assets/MaxSdk/Mediation/Facebook/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: aea9bdf974328420db5ae118ef0d2b87 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Facebook/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Fyber.meta b/Assets/MaxSdk/Mediation/Fyber.meta new file mode 100644 index 0000000..6e4ea33 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Fyber.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d082a8938aab642cd8a004a029248a3b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Fyber/Editor.meta b/Assets/MaxSdk/Mediation/Fyber/Editor.meta new file mode 100644 index 0000000..315e8c8 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Fyber/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e076e4ef7e2874ba69b108cc7a346c2a +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Fyber/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml b/Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml new file mode 100644 index 0000000..eb530e3 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml.meta b/Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..fd0bbbf --- /dev/null +++ b/Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 5e123cdc08e804dffb2c40c4fbc83caf +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Fyber/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Google.meta b/Assets/MaxSdk/Mediation/Google.meta new file mode 100644 index 0000000..1130c68 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Google.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0ac48cf571fb649d6b44e9973e31d03d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Google/Editor.meta b/Assets/MaxSdk/Mediation/Google/Editor.meta new file mode 100644 index 0000000..ea8dd55 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Google/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8015bd045cea462c8f39c8a05867d08 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Google/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml b/Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml new file mode 100644 index 0000000..0e305a6 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml.meta b/Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..36bef72 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 053b810d3594744e38b6fd0fa378fb57 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Google/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/IronSource.meta b/Assets/MaxSdk/Mediation/IronSource.meta new file mode 100644 index 0000000..b026b0a --- /dev/null +++ b/Assets/MaxSdk/Mediation/IronSource.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0d540ee5f5b374e3ea122e65b3d9fa98 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/IronSource/Editor.meta b/Assets/MaxSdk/Mediation/IronSource/Editor.meta new file mode 100644 index 0000000..327f5d6 --- /dev/null +++ b/Assets/MaxSdk/Mediation/IronSource/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 531d860cac61f47d19e32f526470ae43 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/IronSource/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml b/Assets/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml new file mode 100644 index 0000000..ae79fed --- /dev/null +++ b/Assets/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml @@ -0,0 +1,13 @@ + + + + + + https://android-sdk.is.com/ + + + + + + + diff --git a/Assets/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml.meta b/Assets/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..f77e6f0 --- /dev/null +++ b/Assets/MaxSdk/Mediation/IronSource/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 19262406303f04f05b14b31b3c734d35 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/IronSource/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/MediationAdapters.txt b/Assets/MaxSdk/Mediation/MediationAdapters.txt new file mode 100644 index 0000000..40f94d0 --- /dev/null +++ b/Assets/MaxSdk/Mediation/MediationAdapters.txt @@ -0,0 +1,2 @@ +A placeholder file to make sure that the Mediation folder asset is exported with the base plugin. +This ensures that the adapters are imported into this directory even when the plugin has been moved to a different folder. diff --git a/Assets/MaxSdk/Mediation/MediationAdapters.txt.meta b/Assets/MaxSdk/Mediation/MediationAdapters.txt.meta new file mode 100644 index 0000000..41fb994 --- /dev/null +++ b/Assets/MaxSdk/Mediation/MediationAdapters.txt.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: 9a8f83e97729443c86120be3bb24190d +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/MediationAdapters.txt +timeCreated: 1609308536 diff --git a/Assets/MaxSdk/Mediation/UnityAds.meta b/Assets/MaxSdk/Mediation/UnityAds.meta new file mode 100644 index 0000000..bec0455 --- /dev/null +++ b/Assets/MaxSdk/Mediation/UnityAds.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 65275fe8716b147f2a622c8018ca68d2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/UnityAds/Editor.meta b/Assets/MaxSdk/Mediation/UnityAds/Editor.meta new file mode 100644 index 0000000..b66e846 --- /dev/null +++ b/Assets/MaxSdk/Mediation/UnityAds/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30751f2dc322a40e588edfb7c978c9c0 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/UnityAds/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml b/Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml new file mode 100644 index 0000000..a6c7eb5 --- /dev/null +++ b/Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml.meta b/Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..937df6e --- /dev/null +++ b/Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 9950f1cb0da1e43efbeca604db142076 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Vungle.meta b/Assets/MaxSdk/Mediation/Vungle.meta new file mode 100644 index 0000000..bc30441 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Vungle.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 83e47aa65ef684577b34edb98b63a226 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Vungle/Editor.meta b/Assets/MaxSdk/Mediation/Vungle/Editor.meta new file mode 100644 index 0000000..1ea75cc --- /dev/null +++ b/Assets/MaxSdk/Mediation/Vungle/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 77b6ea05736a9458f8ef8762ee9b64bb +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Vungle/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml b/Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml new file mode 100644 index 0000000..425b1bb --- /dev/null +++ b/Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml.meta b/Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml.meta new file mode 100644 index 0000000..7038186 --- /dev/null +++ b/Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0d8ad3a6ddc4f44fab2efe607fe14f26 +labels: +- al_max +- al_max_export_path-MaxSdk/Mediation/Vungle/Editor/Dependencies.xml +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Prefabs.meta b/Assets/MaxSdk/Prefabs.meta new file mode 100644 index 0000000..81f39ca --- /dev/null +++ b/Assets/MaxSdk/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c5c56269cce4b41f2ad38fce6fa492c2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Prefabs/BannerBottom.prefab b/Assets/MaxSdk/Prefabs/BannerBottom.prefab new file mode 100644 index 0000000..bba7ac6 --- /dev/null +++ b/Assets/MaxSdk/Prefabs/BannerBottom.prefab @@ -0,0 +1,402 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3149432657757030138 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5965516886513985157} + - component: {fileID: 3167928293195730454} + - component: {fileID: 6048907697713132302} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5965516886513985157 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4118862295226300947} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 84} + m_SizeDelta: {x: 0, y: 168} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3167928293195730454 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_CullTransparentMesh: 0 +--- !u!114 &6048907697713132302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &3829518492429360636 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4118862295226300947} + - component: {fileID: 5582763645243389146} + - component: {fileID: 1436650035481827287} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4118862295226300947 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5084927109723455527} + - {fileID: 8189983859356672495} + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 1} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: -50} + m_SizeDelta: {x: 640, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5582763645243389146 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_CullTransparentMesh: 0 +--- !u!114 &1436650035481827287 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &4772536868390647122 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8189983859356672495} + - component: {fileID: 7216515036998124610} + - component: {fileID: 3801875349924125266} + m_Layer: 5 + m_Name: InfoText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8189983859356672495 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4772536868390647122} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4118862295226300947} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 3} + m_SizeDelta: {x: 0, y: -6} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7216515036998124610 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4772536868390647122} + m_CullTransparentMesh: 0 +--- !u!114 &3801875349924125266 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4772536868390647122} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.29411766, g: 0.29411766, b: 0.29411766, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 7 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Actual banner size may vary on mobile devices +--- !u!1 &7742712311334970126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3413013686078446151} + - component: {fileID: 2511819091764556577} + - component: {fileID: 2638196187645015298} + - component: {fileID: 633018877563332563} + m_Layer: 5 + m_Name: BannerBottom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3413013686078446151 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 5965516886513985157} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &2511819091764556577 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 500 + m_TargetDisplay: 0 +--- !u!114 &2638196187645015298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &633018877563332563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &8436952342056443077 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5084927109723455527} + - component: {fileID: 7267203896389005665} + - component: {fileID: 5500603550844857255} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5084927109723455527 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4118862295226300947} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -4} + m_SizeDelta: {x: 0, y: -8} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7267203896389005665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_CullTransparentMesh: 0 +--- !u!114 &5500603550844857255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 26 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 71 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: MAX Banner Ad diff --git a/Assets/MaxSdk/Prefabs/BannerBottom.prefab.meta b/Assets/MaxSdk/Prefabs/BannerBottom.prefab.meta new file mode 100644 index 0000000..153cfcf --- /dev/null +++ b/Assets/MaxSdk/Prefabs/BannerBottom.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 54c062c0526b148efa2ea2e9489b3aa0 +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs/BannerBottom.prefab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Prefabs/BannerTop.prefab b/Assets/MaxSdk/Prefabs/BannerTop.prefab new file mode 100644 index 0000000..25d5f49 --- /dev/null +++ b/Assets/MaxSdk/Prefabs/BannerTop.prefab @@ -0,0 +1,402 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3149432657757030138 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5965516886513985157} + - component: {fileID: 3167928293195730454} + - component: {fileID: 6048907697713132302} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5965516886513985157 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4118862295226300947} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -50} + m_SizeDelta: {x: 0, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3167928293195730454 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_CullTransparentMesh: 0 +--- !u!114 &6048907697713132302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &3829518492429360636 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4118862295226300947} + - component: {fileID: 5582763645243389146} + - component: {fileID: 1436650035481827287} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4118862295226300947 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5084927109723455527} + - {fileID: 7429934296583149777} + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 640, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5582763645243389146 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_CullTransparentMesh: 0 +--- !u!114 &1436650035481827287 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3829518492429360636} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &5625059666589051168 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7429934296583149777} + - component: {fileID: 6576623406533516677} + - component: {fileID: 5405475098690228567} + m_Layer: 5 + m_Name: InfoText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7429934296583149777 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5625059666589051168} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4118862295226300947} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 3} + m_SizeDelta: {x: 0, y: -6} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6576623406533516677 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5625059666589051168} + m_CullTransparentMesh: 0 +--- !u!114 &5405475098690228567 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5625059666589051168} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.29411766, g: 0.29411766, b: 0.29411766, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 18 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 7 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Actual banner size may vary on mobile devices +--- !u!1 &7742712311334970126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3413013686078446151} + - component: {fileID: 2511819091764556577} + - component: {fileID: 2638196187645015298} + - component: {fileID: 633018877563332563} + m_Layer: 5 + m_Name: BannerTop + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3413013686078446151 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 5965516886513985157} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &2511819091764556577 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 500 + m_TargetDisplay: 0 +--- !u!114 &2638196187645015298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &633018877563332563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &8436952342056443077 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5084927109723455527} + - component: {fileID: 7267203896389005665} + - component: {fileID: 5500603550844857255} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5084927109723455527 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4118862295226300947} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -4} + m_SizeDelta: {x: 0, y: -8} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7267203896389005665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_CullTransparentMesh: 0 +--- !u!114 &5500603550844857255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 26 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 71 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: MAX Banner Ad diff --git a/Assets/MaxSdk/Prefabs/BannerTop.prefab.meta b/Assets/MaxSdk/Prefabs/BannerTop.prefab.meta new file mode 100644 index 0000000..52ef464 --- /dev/null +++ b/Assets/MaxSdk/Prefabs/BannerTop.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 6521750c87fd14f709d09a1e38ffde47 +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs/BannerTop.prefab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Prefabs/Interstitial.prefab b/Assets/MaxSdk/Prefabs/Interstitial.prefab new file mode 100644 index 0000000..10c7c7b --- /dev/null +++ b/Assets/MaxSdk/Prefabs/Interstitial.prefab @@ -0,0 +1,523 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3149432657757030138 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5965516886513985157} + - component: {fileID: 3167928293195730454} + - component: {fileID: 6048907697713132302} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5965516886513985157 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5084927109723455527} + - {fileID: 8681486192829137138} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3167928293195730454 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_CullTransparentMesh: 0 +--- !u!114 &6048907697713132302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.88235295, g: 0.88235295, b: 0.88235295, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &5668641863723001099 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8681486192829137138} + - component: {fileID: 8217482188885705039} + - component: {fileID: 3177344817093501532} + - component: {fileID: 4415703054918645549} + m_Layer: 5 + m_Name: MaxInterstitialCloseButton + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8681486192829137138 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 763654547095120985} + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -200, y: -100} + m_SizeDelta: {x: 250, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8217482188885705039 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_CullTransparentMesh: 0 +--- !u!114 &3177344817093501532 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!114 &4415703054918645549 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 3177344817093501532} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &6155160063690407013 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1672649117655046507} + - component: {fileID: 2484422763836779945} + - component: {fileID: 1332063313327512547} + - component: {fileID: 9160434328933334999} + m_Layer: 5 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1672649117655046507 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6155160063690407013} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2484422763836779945 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6155160063690407013} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!114 &1332063313327512547 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6155160063690407013} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &9160434328933334999 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6155160063690407013} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e0acf281ba86b4929a6942ecd998395b, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &6462551400748024402 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 763654547095120985} + - component: {fileID: 6719360953530842803} + - component: {fileID: 4616290306121202327} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &763654547095120985 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 8681486192829137138} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6719360953530842803 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_CullTransparentMesh: 0 +--- !u!114 &4616290306121202327 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 40 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 4 + m_MaxSize: 47 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Close +--- !u!1 &7742712311334970126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3413013686078446151} + - component: {fileID: 2511819091764556577} + - component: {fileID: 2638196187645015298} + - component: {fileID: 633018877563332563} + m_Layer: 5 + m_Name: Interstitial + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3413013686078446151 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 5965516886513985157} + - {fileID: 1672649117655046507} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &2511819091764556577 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 999 + m_TargetDisplay: 0 +--- !u!114 &2638196187645015298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &633018877563332563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &8436952342056443077 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5084927109723455527} + - component: {fileID: 7267203896389005665} + - component: {fileID: 5500603550844857255} + m_Layer: 5 + m_Name: MaxInterstitialTitle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5084927109723455527 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 300} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7267203896389005665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_CullTransparentMesh: 0 +--- !u!114 &5500603550844857255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 50 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 71 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: MAX Interstitial Ad diff --git a/Assets/MaxSdk/Prefabs/Interstitial.prefab.meta b/Assets/MaxSdk/Prefabs/Interstitial.prefab.meta new file mode 100644 index 0000000..4fa240b --- /dev/null +++ b/Assets/MaxSdk/Prefabs/Interstitial.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 3fc0c2627ce8a4490b8e319326f8a535 +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs/Interstitial.prefab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Prefabs/Rewarded.prefab b/Assets/MaxSdk/Prefabs/Rewarded.prefab new file mode 100644 index 0000000..dd3457e --- /dev/null +++ b/Assets/MaxSdk/Prefabs/Rewarded.prefab @@ -0,0 +1,795 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &288832541099509301 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6736833388881778366} + - component: {fileID: 738723989743429661} + - component: {fileID: 3366016410383180441} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6736833388881778366 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 288832541099509301} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2219183527695013266} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &738723989743429661 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 288832541099509301} + m_CullTransparentMesh: 0 +--- !u!114 &3366016410383180441 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 288832541099509301} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 35 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 3 + m_MaxSize: 48 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'Grant Reward + + (5 coins)' +--- !u!1 &2620135977249264498 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3035265698078104281} + - component: {fileID: 7277178523579209441} + - component: {fileID: 8085319417655039649} + m_Layer: 5 + m_Name: MaxRewardStatus + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3035265698078104281 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2620135977249264498} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: -250} + m_SizeDelta: {x: 0, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7277178523579209441 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2620135977249264498} + m_CullTransparentMesh: 0 +--- !u!114 &8085319417655039649 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2620135977249264498} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 40 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 69 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Reward not yet granted. +--- !u!1 &3096027301306273604 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2219183527695013266} + - component: {fileID: 3687429596110321440} + - component: {fileID: 3757577222601629632} + - component: {fileID: 87227930114769318} + m_Layer: 5 + m_Name: MaxRewardButton + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2219183527695013266 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096027301306273604} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 6736833388881778366} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -150} + m_SizeDelta: {x: 300, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3687429596110321440 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096027301306273604} + m_CullTransparentMesh: 0 +--- !u!114 &3757577222601629632 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096027301306273604} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!114 &87227930114769318 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096027301306273604} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 3757577222601629632} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &3149432657757030138 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5965516886513985157} + - component: {fileID: 3167928293195730454} + - component: {fileID: 6048907697713132302} + m_Layer: 5 + m_Name: Panel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5965516886513985157 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5084927109723455527} + - {fileID: 8681486192829137138} + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3167928293195730454 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_CullTransparentMesh: 0 +--- !u!114 &6048907697713132302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3149432657757030138} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.88235295, g: 0.88235295, b: 0.88235295, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &4010021198786516228 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3074011789293951898} + - component: {fileID: 301935380126337495} + - component: {fileID: 535359239537776472} + - component: {fileID: 1463999766055390634} + m_Layer: 5 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3074011789293951898 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4010021198786516228} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3413013686078446151} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &301935380126337495 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4010021198786516228} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!114 &535359239537776472 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4010021198786516228} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1463999766055390634 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4010021198786516228} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e0acf281ba86b4929a6942ecd998395b, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &5668641863723001099 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8681486192829137138} + - component: {fileID: 8217482188885705039} + - component: {fileID: 3177344817093501532} + - component: {fileID: 4415703054918645549} + m_Layer: 5 + m_Name: MaxRewardedCloseButton + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8681486192829137138 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 763654547095120985} + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -200, y: -100} + m_SizeDelta: {x: 250, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8217482188885705039 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_CullTransparentMesh: 0 +--- !u!114 &3177344817093501532 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!114 &4415703054918645549 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5668641863723001099} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 3177344817093501532} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &6462551400748024402 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 763654547095120985} + - component: {fileID: 6719360953530842803} + - component: {fileID: 4616290306121202327} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &763654547095120985 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 8681486192829137138} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6719360953530842803 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_CullTransparentMesh: 0 +--- !u!114 &4616290306121202327 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6462551400748024402} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 40 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 4 + m_MaxSize: 47 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Close +--- !u!1 &7742712311334970126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3413013686078446151} + - component: {fileID: 2511819091764556577} + - component: {fileID: 2638196187645015298} + - component: {fileID: 633018877563332563} + m_Layer: 5 + m_Name: Rewarded + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3413013686078446151 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 5965516886513985157} + - {fileID: 3035265698078104281} + - {fileID: 2219183527695013266} + - {fileID: 3074011789293951898} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &2511819091764556577 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 999 + m_TargetDisplay: 0 +--- !u!114 &2638196187645015298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &633018877563332563 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7742712311334970126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!1 &8436952342056443077 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5084927109723455527} + - component: {fileID: 7267203896389005665} + - component: {fileID: 5500603550844857255} + m_Layer: 5 + m_Name: MaxRewardTitle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5084927109723455527 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5965516886513985157} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 300} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7267203896389005665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_CullTransparentMesh: 0 +--- !u!114 &5500603550844857255 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8436952342056443077} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 50 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 71 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: MAX Rewarded Ad diff --git a/Assets/MaxSdk/Prefabs/Rewarded.prefab.meta b/Assets/MaxSdk/Prefabs/Rewarded.prefab.meta new file mode 100644 index 0000000..214bea1 --- /dev/null +++ b/Assets/MaxSdk/Prefabs/Rewarded.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a28c1544d6f094d5eafc8da2343c9119 +labels: +- al_max +- al_max_export_path-MaxSdk/Prefabs/Rewarded.prefab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Resources.meta b/Assets/MaxSdk/Resources.meta new file mode 100644 index 0000000..f634664 --- /dev/null +++ b/Assets/MaxSdk/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3dcc66076f7f149d0b7cec600661f368 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Resources/AppLovinSettings.asset b/Assets/MaxSdk/Resources/AppLovinSettings.asset new file mode 100644 index 0000000..ff97ca1 --- /dev/null +++ b/Assets/MaxSdk/Resources/AppLovinSettings.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ebc0ba1b5ef6b4a6b9dd53d7eadfea16, type: 3} + m_Name: AppLovinSettings + m_EditorClassIdentifier: + qualityServiceEnabled: 1 + sdkKey: rW51GKWqpT99uzHaOQH36OihVd51teKXIfDdTnAzXH70rsTUMSQuyMb7SqmEZzq2qN4B1sFZZPPdlHTOhxQPIC + setAttributionReportEndpoint: 0 + addApsSkAdNetworkIds: 0 + customGradleVersionUrl: + customGradleToolsVersion: + consentFlowEnabled: 0 + consentFlowPlatform: 0 + consentFlowPrivacyPolicyUrl: + consentFlowTermsOfServiceUrl: + userTrackingUsageDescriptionEn: + userTrackingUsageLocalizationEnabled: 0 + userTrackingUsageDescriptionDe: + userTrackingUsageDescriptionEs: + userTrackingUsageDescriptionFr: + userTrackingUsageDescriptionJa: + userTrackingUsageDescriptionKo: + userTrackingUsageDescriptionZhHans: + userTrackingUsageDescriptionZhHant: + adMobAndroidAppId: ca-app-pub-1541656156622049~4671899521 + adMobIosAppId: ca-app-pub-1541656156622049~9934477255 + showInternalSettingsInIntegrationManager: 0 diff --git a/Assets/MaxSdk/Resources/AppLovinSettings.asset.meta b/Assets/MaxSdk/Resources/AppLovinSettings.asset.meta new file mode 100644 index 0000000..40ecdc6 --- /dev/null +++ b/Assets/MaxSdk/Resources/AppLovinSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a0b013f68fbf443093317f35c3c9048 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Resources/Images.meta b/Assets/MaxSdk/Resources/Images.meta new file mode 100644 index 0000000..bb4301d --- /dev/null +++ b/Assets/MaxSdk/Resources/Images.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f910dbfcaedf94ec98c031489a7f6797 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Resources/Images/alert_icon.png b/Assets/MaxSdk/Resources/Images/alert_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..16519508598871e52f379050d7075a4aff309327 GIT binary patch literal 1154 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+SzC{oH>NS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5sCVBk9f!i-b3`J@>bnBzTN978hhy`6c`|8juL@%{VP-R?MeIDntc;3Jc_*$WSG zTjxD1#BFsXE*^2wWAXUI-g8mny_>s=${dBj4+}c0jQ%jDnMOZ%5#w_U_kPX)$zAL8O-&9QpEobK zvFN8F^L7T7IW{Z|vl-NwH`Qzpz8v;S&Y}P4I^oa447z+r%Mb1GI^Ypf%-g%~0EGDo4E2_C=)s)SYo(^v^$+n9F7|>>evu?f2}s z&O77cvclifx$W%<=tYwS6{F3PO?=x>I$ zvwpMcm}kCwXO=v{Nxa~~xP7X;YR15M@%7e~qD(I~^D->jaedLWoVBK_*b^2U&i41Nf97|a zVawJ@Rx3hw%>3&%JNv~6?Y`?m5B49@Ik4+`Q0R}nza5UobTp0S0S zc8_Xg^WJdzY)O!2IHS4Vb**s7u22>Y=Hj^OC`G~09iciI5)&2aoD!#L)D)}B~JUHh_*wHr&0u1J870;A4$(lMjE;`@& zfQ!!LpNWO%=ESI63YzwmwPNpz^f=xhe-l@`?tL1fH0ktO!Ots}e`1K3)V4~rcJ;Z| z9;eqk(my$DvYtC{?X_cNM&|b~8uC1t%Kk4u+9a*$ym_7+oHME8nbONG&yJbB7Ic>>`^TV_uBge}XWIqL zf2t*}5hW>!C8<`)MX5lF!N|bKK-bVf*T^Wuz|hLX(8|N&PEETh{4m<&t;uc GLK6TeaNqp^ literal 0 HcmV?d00001 diff --git a/Assets/MaxSdk/Resources/Images/alert_icon.png.meta b/Assets/MaxSdk/Resources/Images/alert_icon.png.meta new file mode 100644 index 0000000..634d290 --- /dev/null +++ b/Assets/MaxSdk/Resources/Images/alert_icon.png.meta @@ -0,0 +1,94 @@ +fileFormatVersion: 2 +guid: 572fee4574afa4f6dbf2846e0c152fe8 +labels: +- al_max +- al_max_export_path-MaxSdk/Resources/Images/alert_icon.png +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Resources/Images/uninstall_icon.png b/Assets/MaxSdk/Resources/Images/uninstall_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3b55354103e9a1717b1056e56871a667a98d106b GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeG3?%1&o4*=JaR&H=xB_ViXik240LWr03GxeO z$X`8g<3}LR+0(@_q=GS7fw_liWvIgjmTng@k0jM)7LTNS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5r1(g|SvA=~LZ0|V1RPZ!6KjC*gVpUoC_lxdrP(`4&0lT_d+t_+ABB_LE;hGkN#|ah@PEPoRu6AGE-s}gTTz>i1sp+Zmfie#!R^ws z>`m5_t8P5E*nRW+_jA&1l?RU>KQ6ITWbsY$Ip!-BeQGN-eK$P$Aja`U%(5t9(tWiO zonSVZc25PSmi^^MiC)J&n7GYqWj_es*u3*gu!W4w%m>|hy2_j-2NridWGu55O-q9PtC{%DT#=}A_BPU9de8TAmO^$hr^VF=Qzy5Y6waM> zt1S5==R${$?+5m&t*^Ux_3Xmr>5*3#uGVdI=-AD5n3-qY+M?*`>!z`6l4Nt8$j`A$ zwEk1}-Xjlhl!ooe%Jy_vV|@3}2Zn_WN0W7L#n}gJ=(PNB>g@KGCudGr=B_5R3u^wGuVawhZoI=!VfGSt zj(62J8+iF`YW_~yn`^Gnq|(5+o~>b@ee9j=)s06j4=woErL!Z@LojnT<7p+%k}P8e zN6m_BV$8s>WIC5ABgep*e)r1xX*@bhIhAHyv#pU-ocVXklG8I9yJlr{O?$n3QzPqa zyUyR2og_V#?3dT=(v)5iDC~PN=x@j_CX*GN%L3NT_u_;ye0eplxCColJ>SL`4V21= zvX{Q+24sb5+;y8Byl#GHmHw5#+^NPqN;{wCJ>F83{;=||@0#obuD&L&hkr$0b~vcU z7IWj}$xbbmVer+%bBsJbJ>bj^ZyG)%u$xvP|<#GS!&ZFRm-ZR zIjJi=4mkLlw7&lJ^6}%xi|6mp__9IhU+COsV5(Lvag8WRNi0dVN-jzTQVd20Muxfu zCb~xEAx6el#->)r#@Yr3Rt5&{g7sD?8glbfGSez?YcTUU-Uigb;OXk;vd$@?2>{z) BiL?L! literal 0 HcmV?d00001 diff --git a/Assets/MaxSdk/Resources/Images/warning_icon.png.meta b/Assets/MaxSdk/Resources/Images/warning_icon.png.meta new file mode 100644 index 0000000..ee4941c --- /dev/null +++ b/Assets/MaxSdk/Resources/Images/warning_icon.png.meta @@ -0,0 +1,91 @@ +fileFormatVersion: 2 +guid: b504c956e7ed744b6b0e7f014e1cac5a +labels: +- al_max +- al_max_export_path-MaxSdk/Resources/Images/warning_icon.png +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts.meta b/Assets/MaxSdk/Scripts.meta new file mode 100644 index 0000000..e5f77ce --- /dev/null +++ b/Assets/MaxSdk/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a983cd3d5fdeb444d98b53c332a04b5e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager.meta b/Assets/MaxSdk/Scripts/IntegrationManager.meta new file mode 100644 index 0000000..39f65cc --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e01816bc45c944d03afb95d035caf0e1 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor.meta new file mode 100644 index 0000000..1d8400a --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0da229e279400497786c39933fe02e52 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs new file mode 100644 index 0000000..08e543c --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs @@ -0,0 +1,172 @@ +// +// AppLovinAutoUpdater.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 1/27/20. +// Copyright © 2020 AppLovin. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + ///

+ /// Handles auto updates for AppLovin MAX plugin. + /// + public class AppLovinAutoUpdater + { + public const string KeyAutoUpdateEnabled = "com.applovin.auto_update_enabled"; + private const string KeyLastUpdateCheckTime = "com.applovin.last_update_check_time_v2"; // Updated to v2 to force adapter version checks in plugin version 3.1.10. + private static readonly DateTime EpochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + private static readonly int SecondsInADay = (int) TimeSpan.FromDays(1).TotalSeconds; + + // TODO: Make this list dynamic. + public static readonly Dictionary MinAdapterVersions = new Dictionary() + { + {"ADMOB_NETWORK", "android_23.3.0.1_ios_11.9.0.1"}, + {"BIDMACHINE_NETWORK", "android_3.0.1.1_ios_3.0.0.0.1"}, + {"CHARTBOOST_NETWORK", "android_9.7.0.3_ios_9.7.0.2"}, + {"FACEBOOK_MEDIATE", "android_6.17.0.1_ios_6.15.2.1"}, + {"FYBER_NETWORK", "android_8.3.1.1_ios_8.3.2.1"}, + {"GOOGLE_AD_MANAGER_NETWORK", "android_23.3.0.1_ios_11.9.0.1"}, + {"HYPRMX_NETWORK", "android_6.4.2.1_ios_6.4.1.0.1"}, + {"INMOBI_NETWORK", "android_10.7.7.1_ios_10.7.5.1"}, + {"IRONSOURCE_NETWORK", "android_8.3.0.0.2_ios_8.3.0.0.1"}, + {"LINE_NETWORK", "android_2024.8.27.1_ios_2.8.20240827.1"}, + {"MINTEGRAL_NETWORK", "android_16.8.51.1_ios_7.7.2.0.1"}, + {"MOBILEFUSE_NETWORK", "android_1.7.6.1_ios_1.7.6.1"}, + {"MOLOCO_NETWORK", "android_3.1.0.1_ios_3.1.3.1"}, + {"MYTARGET_NETWORK", "android_5.22.1.1_ios_5.21.7.1"}, + {"PUBMATIC_NETWORK", "android_3.9.0.2_ios_3.9.0.2"}, + {"SMAATO_NETWORK", "android_22.7.0.1_ios_22.8.4.1"}, + {"TIKTOK_NETWORK", "android_6.2.0.5.2_ios_6.2.0.7.2"}, + {"UNITY_NETWORK", "android_4.12.2.1_ios_4.12.2.1"}, + {"VERVE_NETWORK", "android_3.0.4.1_ios_3.0.4.1"}, + {"VUNGLE_NETWORK", "android_7.4.1.1_ios_7.4.1.1"}, + {"YANDEX_NETWORK", "android_7.4.0.1_ios_2.18.0.1"}, + }; + + /// + /// Checks if a new version of the plugin is available and prompts the user to update if one is available. + /// + public static void Update() + { + var now = (int) (DateTime.UtcNow - EpochTime).TotalSeconds; + if (EditorPrefs.HasKey(KeyLastUpdateCheckTime)) + { + var elapsedTime = now - EditorPrefs.GetInt(KeyLastUpdateCheckTime); + + // Check if we have checked for a new version in the last 24 hrs and skip update if we have. + if (elapsedTime < SecondsInADay) return; + } + + // Update last checked time. + EditorPrefs.SetInt(KeyLastUpdateCheckTime, now); + + // Load the plugin data + AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.LoadPluginData(data => + { + if (data == null) return; + + ShowPluginUpdateDialogIfNeeded(data); + ShowNetworkAdaptersUpdateDialogIfNeeded(data.MediatedNetworks); + ShowGoogleNetworkAdaptersUpdateDialogIfNeeded(data.MediatedNetworks); + })); + } + + private static void ShowPluginUpdateDialogIfNeeded(PluginData data) + { + // Check if publisher has disabled auto update. + if (!EditorPrefs.GetBool(KeyAutoUpdateEnabled, true)) return; + + // Check if the current and latest version are the same or if the publisher is on a newer version (on beta). If so, skip update. + var comparison = data.AppLovinMax.CurrentToLatestVersionComparisonResult; + if (comparison == MaxSdkUtils.VersionComparisonResult.Equal || comparison == MaxSdkUtils.VersionComparisonResult.Greater) return; + + // A new version of the plugin is available. Show a dialog to the publisher. + var option = EditorUtility.DisplayDialogComplex( + "AppLovin MAX Plugin Update", + "A new version of AppLovin MAX plugin is available for download. Update now?", + "Download", + "Not Now", + "Don't Ask Again"); + + if (option == 0) // Download + { + MaxSdkLogger.UserDebug("Downloading plugin..."); + AppLovinIntegrationManager.downloadPluginProgressCallback = AppLovinIntegrationManagerWindow.OnDownloadPluginProgress; + AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.DownloadPlugin(data.AppLovinMax)); + } + else if (option == 1) // Not Now + { + // Do nothing + MaxSdkLogger.UserDebug("Update postponed."); + } + else if (option == 2) // Don't Ask Again + { + MaxSdkLogger.UserDebug("Auto Update disabled. You can enable it again from the AppLovin Integration Manager"); + EditorPrefs.SetBool(KeyAutoUpdateEnabled, false); + } + } + + private static void ShowNetworkAdaptersUpdateDialogIfNeeded(Network[] networks) + { + var networksToUpdate = networks.Where(network => network.RequiresUpdate).ToList(); + + // If all networks are above the required version, do nothing. + if (networksToUpdate.Count <= 0) return; + + // We found a few adapters that are not compatible with the current SDK, show alert. + var message = "The following network adapters are not compatible with the current version of AppLovin MAX Plugin:\n"; + foreach (var networkName in networksToUpdate) + { + message += "\n- "; + message += networkName.DisplayName + " (Requires " + MinAdapterVersions[networkName.Name] + " or newer)"; + } + + message += "\n\nPlease update them to the latest versions to avoid any issues."; + + AppLovinIntegrationManager.ShowBuildFailureDialog(message); + } + + private static void ShowGoogleNetworkAdaptersUpdateDialogIfNeeded(Network[] networks) + { + // AdMob and GAM use the same SDKs so their adapters should use the same underlying SDK version. + var googleNetwork = networks.FirstOrDefault(network => network.Name.Equals("ADMOB_NETWORK")); + var googleAdManagerNetwork = networks.FirstOrDefault(network => network.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")); + + // If both AdMob and GAM are not integrated, do nothing. + if (googleNetwork == null || string.IsNullOrEmpty(googleNetwork.CurrentVersions.Unity) || + googleAdManagerNetwork == null || string.IsNullOrEmpty(googleAdManagerNetwork.CurrentVersions.Unity)) return; + + var isAndroidVersionCompatible = GoogleNetworkAdaptersCompatible(googleNetwork.CurrentVersions.Android, googleAdManagerNetwork.CurrentVersions.Android, "19.8.0.0"); + var isIosVersionCompatible = GoogleNetworkAdaptersCompatible(googleNetwork.CurrentVersions.Ios, googleAdManagerNetwork.CurrentVersions.Ios, "8.0.0.0"); + + if (isAndroidVersionCompatible && isIosVersionCompatible) return; + + var message = "You may see unexpected errors if you use different versions of the AdMob and Google Ad Manager adapter SDKs. " + + "AdMob and Google Ad Manager share the same SDKs.\n\n" + + "You can be sure that you are using the same SDK for both if the first three numbers in each adapter version match."; + + AppLovinIntegrationManager.ShowBuildFailureDialog(message); + } + + private static bool GoogleNetworkAdaptersCompatible(string googleVersion, string googleAdManagerVersion, string breakingVersion) + { + var googleResult = MaxSdkUtils.CompareVersions(googleVersion, breakingVersion); + var googleAdManagerResult = MaxSdkUtils.CompareVersions(googleAdManagerVersion, breakingVersion); + + // If one is less than the breaking version and the other is not, they are not compatible. + if (googleResult == MaxSdkUtils.VersionComparisonResult.Lesser && + googleAdManagerResult != MaxSdkUtils.VersionComparisonResult.Lesser) return false; + + if (googleAdManagerResult == MaxSdkUtils.VersionComparisonResult.Lesser && + googleResult != MaxSdkUtils.VersionComparisonResult.Lesser) return false; + + return true; + } + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta new file mode 100644 index 0000000..0070e74 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 8bcdd5226273242c5bd9ec79568202e6 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinAutoUpdater.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs new file mode 100644 index 0000000..c9cd21f --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs @@ -0,0 +1,94 @@ +// +// AppLovinBuildPostProcessor.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 10/30/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_IOS || UNITY_IPHONE + +using System.Diagnostics; +using System.IO; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// A helper class to run command line tools. + /// + /// TODO: Currently only supports shell (Linux). Add support for Windows machines. + /// + public class AppLovinCommandLine + { + /// + /// Result obtained by running a command line command. + /// + public class Result + { + /// + /// Standard output stream from command line. + /// + public string StandardOutput; + + /// + /// Standard error stream from command line. + /// + public string StandardError; + + /// + /// Exit code returned from command line. + /// + public int ExitCode; + + /// + /// The description of the result that can be used for error logging. + /// + public string Message; + } + + /// + /// Runs a command line tool using the provided and . + /// + /// The tool path to run + /// The arguments to be passed to the command line tool + /// The directory from which to run this command. + /// + public static Result Run(string toolPath, string arguments, string workingDirectory) + { + var stdoutFileName = Path.GetTempFileName(); + var stderrFileName = Path.GetTempFileName(); + + var process = new Process(); + process.StartInfo.UseShellExecute = true; + process.StartInfo.CreateNoWindow = false; + process.StartInfo.RedirectStandardInput = false; + process.StartInfo.RedirectStandardOutput = false; + process.StartInfo.RedirectStandardError = false; + + process.StartInfo.WorkingDirectory = workingDirectory; + process.StartInfo.FileName = "bash"; + process.StartInfo.Arguments = string.Format("-l -c '\"{0}\" {1} 1> {2} 2> {3}'", toolPath, arguments, stdoutFileName, stderrFileName); + process.Start(); + + process.WaitForExit(); + + var stdout = File.ReadAllText(stdoutFileName); + var stderr = File.ReadAllText(stderrFileName); + + File.Delete(stdoutFileName); + File.Delete(stderrFileName); + + var result = new Result(); + result.StandardOutput = stdout; + result.StandardError = stderr; + result.ExitCode = process.ExitCode; + + var messagePrefix = result.ExitCode == 0 ? "Command executed successfully" : "Failed to run command"; + result.Message = string.Format("{0}: '{1} {2}'\nstdout: {3}\nstderr: {4}\nExit code: {5}", messagePrefix, toolPath, arguments, stdout, stderr, process.ExitCode); + + return result; + } + } +} + +#endif diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta new file mode 100644 index 0000000..2c3ff20 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 2d0aa55f9a7d2440f871dfb256372a33 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinCommandLine.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs new file mode 100644 index 0000000..f5be939 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs @@ -0,0 +1,91 @@ +// +// AppLovinEditorCoroutine.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 7/25/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using System.Collections; +using System.Collections.Generic; +using UnityEditor; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// A coroutine that can update based on editor application update. + /// + public class AppLovinEditorCoroutine + { + /// + /// Keeps track of the coroutine currently running. + /// + private IEnumerator enumerator; + + /// + /// Keeps track of coroutines that have yielded to the current enumerator. + /// + private readonly List history = new List(); + + private AppLovinEditorCoroutine(IEnumerator enumerator) + { + this.enumerator = enumerator; + } + + /// + /// Creates and starts a coroutine. + /// + /// The coroutine to be started + /// The coroutine that has been started. + public static AppLovinEditorCoroutine StartCoroutine(IEnumerator enumerator) + { + var coroutine = new AppLovinEditorCoroutine(enumerator); + coroutine.Start(); + return coroutine; + } + + private void Start() + { + EditorApplication.update += OnEditorUpdate; + } + + /// + /// Stops the coroutine. + /// + public void Stop() + { + if (EditorApplication.update == null) return; + + EditorApplication.update -= OnEditorUpdate; + } + + private void OnEditorUpdate() + { + if (enumerator.MoveNext()) + { + // If there is a coroutine to yield for inside the coroutine, add the initial one to history and continue the second one + if (enumerator.Current is IEnumerator) + { + history.Add(enumerator); + enumerator = (IEnumerator) enumerator.Current; + } + } + else + { + // Current coroutine has ended, check if we have more coroutines in history to be run. + if (history.Count == 0) + { + // No more coroutines to run, stop updating. + Stop(); + } + // Step out and finish the code in the coroutine that yielded to it + else + { + var index = history.Count - 1; + enumerator = history[index]; + history.RemoveAt(index); + } + } + } + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta new file mode 100644 index 0000000..c622bab --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 95747c688378548eeb92aeb528ac96ff +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinEditorCoroutine.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs new file mode 100644 index 0000000..b30b73e --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs @@ -0,0 +1,141 @@ +// +// MaxInitialization.cs +// AppLovin MAX Unity Plugin +// +// Created by Thomas So on 5/24/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using AppLovinMax.Scripts.IntegrationManager.Editor; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + [InitializeOnLoad] + public class AppLovinInitialize + { + private static readonly List ObsoleteNetworks = new List + { + "AdColony", + "Criteo", + "Nend", + "Snap", + "Tapjoy", + "VerizonAds", + "VoodooAds" + }; + + private static readonly List ObsoleteFileExportPathsToDelete = new List + { + // The `MaxSdk/Scripts/Editor` folder contents have been moved into `MaxSdk/Scripts/IntegrationManager/Editor`. + "MaxSdk/Scripts/Editor", + "MaxSdk/Scripts/Editor.meta", + + // The `EventSystemChecker` has been renamed to `MaxEventSystemChecker`. + "MaxSdk/Scripts/EventSystemChecker.cs", + "MaxSdk/Scripts/EventSystemChecker.cs.meta", + + // Google AdMob adapter pre/post process scripts. The logic has been migrated to the main plugin. + "MaxSdk/Mediation/Google/Editor/MaxGoogleInitialize.cs", + "MaxSdk/Mediation/Google/Editor/MaxGoogleInitialize.cs.meta", + "MaxSdk/Mediation/Google/Editor/MaxMediationGoogleUtils.cs", + "MaxSdk/Mediation/Google/Editor/MaxMediationGoogleUtils.cs.meta", + "MaxSdk/Mediation/Google/Editor/PostProcessor.cs", + "MaxSdk/Mediation/Google/Editor/PostProcessor.cs.meta", + "MaxSdk/Mediation/Google/Editor/PreProcessor.cs", + "MaxSdk/Mediation/Google/Editor/PreProcessor.cs.meta", + "MaxSdk/Mediation/Google/Editor/MaxSdk.Mediation.Google.Editor.asmdef", + "MaxSdk/Mediation/Google/MaxSdk.Mediation.Google.Editor.asmdef.meta", + "Plugins/Android/MaxMediationGoogle.androidlib", + "Plugins/Android/MaxMediationGoogle.androidlib.meta", + + // Google Ad Manager adapter pre/post process scripts. The logic has been migrated to the main plugin. + "MaxSdk/Mediation/GoogleAdManager/Editor/MaxGoogleAdManagerInitialize.cs", + "MaxSdk/Mediation/GoogleAdManager/Editor/MaxGoogleAdManagerInitialize.cs.meta", + "MaxSdk/Mediation/GoogleAdManager/Editor/PostProcessor.cs", + "MaxSdk/Mediation/GoogleAdManager/Editor/PostProcessor.cs.meta", + "MaxSdk/Mediation/GoogleAdManager/Editor/MaxSdk.Mediation.GoogleAdManager.Editor.asmdef", + "MaxSdk/Mediation/GoogleAdManager/Editor/MaxSdk.Mediation.GoogleAdManager.Editor.asmdef.meta", + "Plugins/Android/MaxMediationGoogleAdManager.androidlib", + "Plugins/Android/MaxMediationGoogleAdManager.androidlib.meta", + + // The `VariableService` has been removed. + "MaxSdk/Scripts/MaxVariableServiceAndroid.cs", + "MaxSdk/Scripts/MaxVariableServiceAndroid.cs.meta", + "MaxSdk/Scripts/MaxVariableServiceiOS.cs", + "MaxSdk/Scripts/MaxVariableServiceiOS.cs.meta", + "MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs", + "MaxSdk/Scripts/MaxVariableServiceUnityEditor.cs.meta", + + // TODO: Add MaxTargetingData and MaxUserSegment when the plugin has enough traction. + }; + + static AppLovinInitialize() + { +#if UNITY_IOS + // Check that the publisher is targeting iOS 9.0+ + if (!PlayerSettings.iOS.targetOSVersionString.StartsWith("9.") && !PlayerSettings.iOS.targetOSVersionString.StartsWith("1")) + { + MaxSdkLogger.UserError("Detected iOS project version less than iOS 9 - The AppLovin MAX SDK WILL NOT WORK ON < iOS9!!!"); + } +#endif + + var pluginParentDir = AppLovinIntegrationManager.PluginParentDirectory; + var isPluginOutsideAssetsDir = AppLovinIntegrationManager.IsPluginOutsideAssetsDirectory; + var changesMade = AppLovinIntegrationManager.MovePluginFilesIfNeeded(pluginParentDir, isPluginOutsideAssetsDir); + if (isPluginOutsideAssetsDir) + { + // If the plugin is not under the assets folder, delete the MaxSdk/Mediation folder in the plugin, so that the adapters are not imported at that location and imported to the default location. + var mediationDir = Path.Combine(pluginParentDir, "MaxSdk/Mediation"); + if (Directory.Exists(mediationDir)) + { + FileUtil.DeleteFileOrDirectory(mediationDir); + FileUtil.DeleteFileOrDirectory(mediationDir + ".meta"); + changesMade = true; + } + } + + foreach (var obsoleteFileExportPathToDelete in ObsoleteFileExportPathsToDelete) + { + var pathToDelete = MaxSdkUtils.GetAssetPathForExportPath(obsoleteFileExportPathToDelete); + if (CheckExistence(pathToDelete)) + { + MaxSdkLogger.UserDebug("Deleting obsolete file '" + pathToDelete + "' that are no longer needed."); + FileUtil.DeleteFileOrDirectory(pathToDelete); + changesMade = true; + } + } + + // Check if any obsolete networks are installed + foreach (var obsoleteNetwork in ObsoleteNetworks) + { + var networkDir = Path.Combine(pluginParentDir, "MaxSdk/Mediation/" + obsoleteNetwork); + if (CheckExistence(networkDir)) + { + MaxSdkLogger.UserDebug("Deleting obsolete network " + obsoleteNetwork + " from path " + networkDir + "..."); + FileUtil.DeleteFileOrDirectory(networkDir); + changesMade = true; + } + } + + // Refresh UI + if (changesMade) + { + AssetDatabase.Refresh(); + MaxSdkLogger.UserDebug("AppLovin MAX Migration completed"); + } + + AppLovinAutoUpdater.Update(); + } + + private static bool CheckExistence(string location) + { + return File.Exists(location) || + Directory.Exists(location) || + (location.EndsWith("/*") && Directory.Exists(Path.GetDirectoryName(location))); + } + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs.meta new file mode 100644 index 0000000..fb8a55c --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 6b7dce7fe193a4058bc51d9f4d3a2aed +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInitialize.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs new file mode 100644 index 0000000..a37a70f --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs @@ -0,0 +1,754 @@ +// +// MaxIntegrationManager.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 6/1/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; +using VersionComparisonResult = MaxSdkUtils.VersionComparisonResult; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + [Serializable] + public class PluginData + { + public Network AppLovinMax; + public Network[] MediatedNetworks; + public Network[] PartnerMicroSdks; + public DynamicLibraryToEmbed[] ThirdPartyDynamicLibrariesToEmbed; + } + + [Serializable] + public class Network + { + // + // Sample network data: + // + // { + // "Name": "adcolony", + // "DisplayName": "AdColony", + // "DownloadUrl": "https://bintray.com/applovin/Unity-Mediation-Packages/download_file?file_path=AppLovin-AdColony-Adapters-Android-3.3.10.1-iOS-3.3.7.2.unitypackage", + // "PluginFileName": "AppLovin-AdColony-Adapters-Android-3.3.10.1-iOS-3.3.7.2.unitypackage", + // "DependenciesFilePath": "MaxSdk/Mediation/AdColony/Editor/Dependencies.xml", + // "LatestVersions" : { + // "Unity": "android_3.3.10.1_ios_3.3.7.2", + // "Android": "3.3.10.1", + // "Ios": "3.3.7.2" + // } + // } + // + + public string Name; + public string DisplayName; + public string DownloadUrl; + public string DependenciesFilePath; + public string[] PluginFilePaths; + public Versions LatestVersions; + [NonSerialized] public Versions CurrentVersions; + [NonSerialized] public VersionComparisonResult CurrentToLatestVersionComparisonResult = VersionComparisonResult.Lesser; + [NonSerialized] public bool RequiresUpdate; + public DynamicLibraryToEmbed[] DynamicLibrariesToEmbed; + } + + [Serializable] + public class DynamicLibraryToEmbed + { + public string PodName; + public string[] FrameworkNames; + + // Min and max versions are inclusive, so if the adapter is the min or max version, the xcframework will get embedded. + public string MinVersion; + public string MaxVersion; + + public DynamicLibraryToEmbed(string podName, string[] frameworkNames, string minVersion, string maxVersion) + { + PodName = podName; + FrameworkNames = frameworkNames; + MinVersion = minVersion; + MaxVersion = maxVersion; + } + } + + /// + /// A helper data class used to get current versions from Dependency.xml files. + /// + [Serializable] + public class Versions + { + public string Unity; + public string Android; + public string Ios; + + public override bool Equals(object value) + { + var versions = value as Versions; + + return versions != null + && Unity.Equals(versions.Unity) + && (Android == null || Android.Equals(versions.Android)) + && (Ios == null || Ios.Equals(versions.Ios)); + } + + public bool HasEqualSdkVersions(Versions versions) + { + return versions != null + && AdapterSdkVersion(Android).Equals(AdapterSdkVersion(versions.Android)) + && AdapterSdkVersion(Ios).Equals(AdapterSdkVersion(versions.Ios)); + } + + public override int GetHashCode() + { + return new {Unity, Android, Ios}.GetHashCode(); + } + + private static string AdapterSdkVersion(string adapterVersion) + { + var index = adapterVersion.LastIndexOf("."); + return index > 0 ? adapterVersion.Substring(0, index) : adapterVersion; + } + } + + /// + /// A manager class for MAX integration manager window. + /// + /// TODO: Decide if we should namespace these classes. + /// + public class AppLovinIntegrationManager + { + /// + /// Delegate to be called when downloading a plugin with the progress percentage. + /// + /// The name of the plugin being downloaded. + /// Percentage downloaded. + /// Whether or not the download is complete. + public delegate void DownloadPluginProgressCallback(string pluginName, float progress, bool done); + + /// + /// Delegate to be called when a plugin package is imported. + /// + /// The network data for which the package is imported. + public delegate void ImportPackageCompletedCallback(Network network); + + private static readonly AppLovinIntegrationManager instance = new AppLovinIntegrationManager(); + + public static readonly string GradleTemplatePath = Path.Combine("Assets/Plugins/Android", "mainTemplate.gradle"); + public static readonly string DefaultPluginExportPath = Path.Combine("Assets", "MaxSdk"); + private const string MaxSdkAssetExportPath = "MaxSdk/Scripts/MaxSdk.cs"; + + internal static readonly string PluginDataEndpoint = "https://unity.applovin.com/max/1.0/integration_manager_info?plugin_version={0}"; + + /// + /// Some publishers might re-export our plugin via Unity Package Manager and the plugin will not be under the Assets folder. This means that the mediation adapters, settings files should not be moved to the packages folder, + /// since they get overridden when the package is updated. These are the files that should not be moved, if the plugin is not under the Assets/ folder. + /// + /// Note: When we distribute the plugin via Unity Package Manager, we need to distribute the adapters as separate packages, and the adapters won't be in the MaxSdk folder. So we need to take that into account. + /// + private static readonly List PluginPathsToIgnoreMoveWhenPluginOutsideAssetsDirectory = new List + { + "MaxSdk/Mediation", + "MaxSdk/Mediation.meta", + "MaxSdk/Resources.meta", + AppLovinSettings.SettingsExportPath, + AppLovinSettings.SettingsExportPath + ".meta" + }; + + private static string externalDependencyManagerVersion; + + public static DownloadPluginProgressCallback downloadPluginProgressCallback; + public static ImportPackageCompletedCallback importPackageCompletedCallback; + + private UnityWebRequest webRequest; + private Network importingNetwork; + + /// + /// An Instance of the Integration manager. + /// + public static AppLovinIntegrationManager Instance + { + get { return instance; } + } + + /// + /// The parent directory path where the MaxSdk plugin directory is placed. + /// + public static string PluginParentDirectory + { + get + { + // Search for the asset with the default exported path first, In most cases, we should be able to find the asset. + // In some cases where we don't, use the platform specific export path to search for the asset (in case of migrating a project from Windows to Mac or vice versa). + var maxSdkScriptAssetPath = MaxSdkUtils.GetAssetPathForExportPath(MaxSdkAssetExportPath); + + // maxSdkScriptAssetPath will always have AltDirectorySeparatorChar (/) as the path separator. Convert to platform specific path. + return maxSdkScriptAssetPath.Replace(MaxSdkAssetExportPath, "") + .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + } + + /// + /// When the base plugin is outside the Assets/ directory, the mediation plugin files are still imported to the default location under Assets/. + /// Returns the parent directory where the mediation adapter plugins are imported. + /// + public static string MediationSpecificPluginParentDirectory + { + get { return IsPluginOutsideAssetsDirectory ? "Assets" : PluginParentDirectory; } + } + + /// + /// Whether or not the plugin is under the Assets/ folder. + /// + public static bool IsPluginOutsideAssetsDirectory + { + get { return !PluginParentDirectory.StartsWith("Assets"); } + } + + /// + /// Whether or not gradle build system is enabled. + /// + public static bool GradleBuildEnabled + { + get { return GetEditorUserBuildSetting("androidBuildSystem", "").ToString().Equals("Gradle"); } + } + + /// + /// Whether or not Gradle template is enabled. + /// + public static bool GradleTemplateEnabled + { + get { return GradleBuildEnabled && File.Exists(GradleTemplatePath); } + } + + /// + /// Whether or not the Quality Service settings can be processed which requires Gradle template enabled or Unity IDE newer than version 2018_2. + /// + public static bool CanProcessAndroidQualityServiceSettings + { + get { return GradleTemplateEnabled || GradleBuildEnabled; } + } + + /// + /// The External Dependency Manager version obtained dynamically. + /// + public static string ExternalDependencyManagerVersion + { + get + { + if (!string.IsNullOrEmpty(externalDependencyManagerVersion)) return externalDependencyManagerVersion; + + try + { + var versionHandlerVersionNumberType = Type.GetType("Google.VersionHandlerVersionNumber, Google.VersionHandlerImpl"); + externalDependencyManagerVersion = versionHandlerVersionNumberType.GetProperty("Value").GetValue(null, null).ToString(); + } +#pragma warning disable 0168 + catch (Exception ignored) +#pragma warning restore 0168 + { + externalDependencyManagerVersion = "Failed to get version."; + } + + return externalDependencyManagerVersion; + } + } + + private AppLovinIntegrationManager() + { + // Add asset import callbacks. + AssetDatabase.importPackageCompleted += packageName => + { + if (!IsImportingNetwork(packageName)) return; + + var pluginParentDir = PluginParentDirectory; + var isPluginOutsideAssetsDir = IsPluginOutsideAssetsDirectory; + MovePluginFilesIfNeeded(pluginParentDir, isPluginOutsideAssetsDir); + AssetDatabase.Refresh(); + + CallImportPackageCompletedCallback(importingNetwork); + importingNetwork = null; + }; + + AssetDatabase.importPackageCancelled += packageName => + { + if (!IsImportingNetwork(packageName)) return; + + MaxSdkLogger.UserDebug("Package import cancelled."); + importingNetwork = null; + }; + + AssetDatabase.importPackageFailed += (packageName, errorMessage) => + { + if (!IsImportingNetwork(packageName)) return; + + MaxSdkLogger.UserError(errorMessage); + importingNetwork = null; + }; + } + + static AppLovinIntegrationManager() { } + + public static PluginData LoadPluginDataSync() + { + var url = string.Format(PluginDataEndpoint, MaxSdk.Version); + using (var unityWebRequest = UnityWebRequest.Get(url)) + { + var operation = unityWebRequest.SendWebRequest(); + + // Just wait till www is done + while (!operation.isDone) { } + + return CreatePluginDataFromWebResponse(unityWebRequest); + } + } + + /// + /// Loads the plugin data to be display by integration manager window. + /// + /// Callback to be called once the plugin data download completes. + public IEnumerator LoadPluginData(Action callback) + { + var url = string.Format(PluginDataEndpoint, MaxSdk.Version); + using (var unityWebRequest = UnityWebRequest.Get(url)) + { + var operation = unityWebRequest.SendWebRequest(); + + while (!operation.isDone) yield return new WaitForSeconds(0.1f); // Just wait till www is done. Our coroutine is pretty rudimentary. + + var pluginData = CreatePluginDataFromWebResponse(unityWebRequest); + + callback(pluginData); + } + } + + private static PluginData CreatePluginDataFromWebResponse(UnityWebRequest unityWebRequest) + { +#if UNITY_2020_1_OR_NEWER + if (unityWebRequest.result != UnityWebRequest.Result.Success) +#else + if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) +#endif + { + MaxSdkLogger.E("Failed to load plugin data. Please check your internet connection."); + return null; + } + + PluginData pluginData; + try + { + pluginData = JsonUtility.FromJson(unityWebRequest.downloadHandler.text); + } + catch (Exception exception) + { + Console.WriteLine(exception); + pluginData = null; + } + + if (pluginData == null) return null; + + // Get current version of the plugin + var appLovinMax = pluginData.AppLovinMax; + UpdateCurrentVersions(appLovinMax, PluginParentDirectory); + + // Get current versions for all the mediation networks. + var mediationPluginParentDirectory = MediationSpecificPluginParentDirectory; + foreach (var network in pluginData.MediatedNetworks) + { + UpdateCurrentVersions(network, mediationPluginParentDirectory); + } + + foreach (var partnerMicroSdk in pluginData.PartnerMicroSdks) + { + UpdateCurrentVersions(partnerMicroSdk, mediationPluginParentDirectory); + } + + return pluginData; + } + + /// + /// Updates the CurrentVersion fields for a given network data object. + /// + /// Network for which to update the current versions. + /// The parent directory of where the mediation adapter plugins are imported to. + public static void UpdateCurrentVersions(Network network, string mediationPluginParentDirectory) + { + var currentVersions = GetCurrentVersions(MaxSdkUtils.GetAssetPathForExportPath(network.DependenciesFilePath)); + + network.CurrentVersions = currentVersions; + + // If AppLovin mediation plugin, get the version from MaxSdk and the latest and current version comparison. + if (network.Name.Equals("APPLOVIN_NETWORK")) + { + network.CurrentVersions.Unity = MaxSdk.Version; + + var unityVersionComparison = MaxSdkUtils.CompareVersions(network.CurrentVersions.Unity, network.LatestVersions.Unity); + var androidVersionComparison = MaxSdkUtils.CompareVersions(network.CurrentVersions.Android, network.LatestVersions.Android); + var iosVersionComparison = MaxSdkUtils.CompareVersions(network.CurrentVersions.Ios, network.LatestVersions.Ios); + + // Overall version is same if all the current and latest (from db) versions are same. + if (unityVersionComparison == VersionComparisonResult.Equal && + androidVersionComparison == VersionComparisonResult.Equal && + iosVersionComparison == VersionComparisonResult.Equal) + { + network.CurrentToLatestVersionComparisonResult = VersionComparisonResult.Equal; + } + // One of the installed versions is newer than the latest versions which means that the publisher is on a beta version. + else if (unityVersionComparison == VersionComparisonResult.Greater || + androidVersionComparison == VersionComparisonResult.Greater || + iosVersionComparison == VersionComparisonResult.Greater) + { + network.CurrentToLatestVersionComparisonResult = VersionComparisonResult.Greater; + } + // We have a new version available if all Android, iOS and Unity has a newer version available in db. + else + { + network.CurrentToLatestVersionComparisonResult = VersionComparisonResult.Lesser; + } + } + // For all other mediation adapters, get the version comparison using their Unity versions. + else + { + // If adapter is indeed installed, compare the current (installed) and the latest (from db) versions, so that we can determine if the publisher is on an older, current or a newer version of the adapter. + // If the publisher is on a newer version of the adapter than the db version, that means they are on a beta version. + if (!string.IsNullOrEmpty(currentVersions.Unity)) + { + network.CurrentToLatestVersionComparisonResult = MaxSdkUtils.CompareUnityMediationVersions(currentVersions.Unity, network.LatestVersions.Unity); + } + + if (!string.IsNullOrEmpty(network.CurrentVersions.Unity) && AppLovinAutoUpdater.MinAdapterVersions.ContainsKey(network.Name)) + { + var comparisonResult = MaxSdkUtils.CompareUnityMediationVersions(network.CurrentVersions.Unity, AppLovinAutoUpdater.MinAdapterVersions[network.Name]); + // Requires update if current version is lower than the min required version. + network.RequiresUpdate = comparisonResult < 0; + } + else + { + // Reset value so that the Integration manager can hide the alert icon once adapter is updated. + network.RequiresUpdate = false; + } + } + } + + /// + /// Downloads the plugin file for a given network. + /// + /// Network for which to download the current version. + /// Whether or not to show the import window when downloading. Defaults to true. + /// + public IEnumerator DownloadPlugin(Network network, bool showImport = true) + { + var path = Path.Combine(Application.temporaryCachePath, GetPluginFileName(network)); // TODO: Maybe delete plugin file after finishing import. + var downloadHandler = new DownloadHandlerFile(path); + webRequest = new UnityWebRequest(network.DownloadUrl) + { + method = UnityWebRequest.kHttpVerbGET, + downloadHandler = downloadHandler + }; + + var operation = webRequest.SendWebRequest(); + while (!operation.isDone) + { + yield return new WaitForSeconds(0.1f); // Just wait till webRequest is completed. Our coroutine is pretty rudimentary. + CallDownloadPluginProgressCallback(network.DisplayName, operation.progress, operation.isDone); + } + +#if UNITY_2020_1_OR_NEWER + if (webRequest.result != UnityWebRequest.Result.Success) +#else + if (webRequest.isNetworkError || webRequest.isHttpError) +#endif + { + MaxSdkLogger.UserError(webRequest.error); + } + else + { + importingNetwork = network; + AssetDatabase.ImportPackage(path, showImport); + } + + webRequest.Dispose(); + webRequest = null; + } + + /// + /// Cancels the plugin download if one is in progress. + /// + public void CancelDownload() + { + if (webRequest == null) return; + + webRequest.Abort(); + } + + /// + /// Shows a dialog to the user with the given message and logs the error message to console. + /// + /// The failure message to be shown to the user. + public static void ShowBuildFailureDialog(string message) + { + var openIntegrationManager = EditorUtility.DisplayDialog("AppLovin MAX", message, "Open Integration Manager", "Dismiss"); + if (openIntegrationManager) + { + AppLovinIntegrationManagerWindow.ShowManager(); + } + + MaxSdkLogger.UserError(message); + } + + /// + /// Checks whether or not an adapter with the given version or newer exists. + /// + /// The name of the network (the root adapter folder name in "MaxSdk/Mediation/" folder. + /// The min adapter version to check for. Can be null if we want to check for any version. + /// true if an adapter with the min version is installed. + public static bool IsAdapterInstalled(string adapterName, string iosVersion = null) // TODO: Add Android version check. + { + var dependencyFilePath = MaxSdkUtils.GetAssetPathForExportPath("MaxSdk/Mediation/" + adapterName + "/Editor/Dependencies.xml"); + if (!File.Exists(dependencyFilePath)) return false; + + // If version is null, we just need the adapter installed. We don't have to check for a specific version. + if (iosVersion == null) return true; + + var currentVersion = GetCurrentVersions(dependencyFilePath); + var iosVersionComparison = MaxSdkUtils.CompareVersions(currentVersion.Ios, iosVersion); + return iosVersionComparison != VersionComparisonResult.Lesser; + } + + #region Utility Methods + + /// + /// Gets the current versions for a given network's dependency file path. + /// + /// A dependency file path that from which to extract current versions. + /// Current versions of a given network's dependency file. + public static Versions GetCurrentVersions(string dependencyPath) + { + XDocument dependency; + try + { + dependency = XDocument.Load(dependencyPath); + } +#pragma warning disable 0168 + catch (IOException exception) +#pragma warning restore 0168 + { + // Couldn't find the dependencies file. The plugin is not installed. + return new Versions(); + } + + // + // + // + // + // + // + // + // + string androidVersion = null; + string iosVersion = null; + var dependenciesElement = dependency.Element("dependencies"); + if (dependenciesElement != null) + { + var androidPackages = dependenciesElement.Element("androidPackages"); + if (androidPackages != null) + { + var adapterPackage = androidPackages.Descendants().FirstOrDefault(element => element.Name.LocalName.Equals("androidPackage") + && element.FirstAttribute.Name.LocalName.Equals("spec") + && element.FirstAttribute.Value.StartsWith("com.applovin")); + if (adapterPackage != null) + { + androidVersion = adapterPackage.FirstAttribute.Value.Split(':').Last(); + // Hack alert: Some Android versions might have square brackets to force a specific version. Remove them if they are detected. + if (androidVersion.StartsWith("[")) + { + androidVersion = androidVersion.Trim('[', ']'); + } + } + } + + var iosPods = dependenciesElement.Element("iosPods"); + if (iosPods != null) + { + var adapterPod = iosPods.Descendants().FirstOrDefault(element => element.Name.LocalName.Equals("iosPod") + && element.FirstAttribute.Name.LocalName.Equals("name") + && element.FirstAttribute.Value.StartsWith("AppLovin")); + if (adapterPod != null) + { + iosVersion = adapterPod.Attributes().First(attribute => attribute.Name.LocalName.Equals("version")).Value; + } + } + } + + var currentVersions = new Versions(); + if (androidVersion != null && iosVersion != null) + { + currentVersions.Unity = string.Format("android_{0}_ios_{1}", androidVersion, iosVersion); + currentVersions.Android = androidVersion; + currentVersions.Ios = iosVersion; + } + else if (androidVersion != null) + { + currentVersions.Unity = string.Format("android_{0}", androidVersion); + currentVersions.Android = androidVersion; + } + else if (iosVersion != null) + { + currentVersions.Unity = string.Format("ios_{0}", iosVersion); + currentVersions.Ios = iosVersion; + } + + return currentVersions; + } + + /// + /// Checks whether or not the given package name is the currently importing package. + /// + /// The name of the package that needs to be checked. + /// true if the importing package matches the given package name. + private bool IsImportingNetwork(string packageName) + { + // Note: The pluginName doesn't have the '.unitypacakge' extension included in its name but the pluginFileName does. So using Contains instead of Equals. + return importingNetwork != null && GetPluginFileName(importingNetwork).Contains(packageName); + } + + /// + /// Moves the imported plugin files to the MaxSdk directory if the publisher has moved the plugin to a different directory. This is a failsafe for when some plugin files are not imported to the new location. + /// + /// True if the adapters have been moved. + public static bool MovePluginFilesIfNeeded(string pluginParentDirectory, bool isPluginOutsideAssetsDirectory) + { + var pluginDir = Path.Combine(pluginParentDirectory, "MaxSdk"); + + // Check if the user has moved the Plugin and if new assets have been imported to the default directory. + if (DefaultPluginExportPath.Equals(pluginDir) || !Directory.Exists(DefaultPluginExportPath)) return false; + + MovePluginFiles(DefaultPluginExportPath, pluginDir, isPluginOutsideAssetsDirectory); + if (!isPluginOutsideAssetsDirectory) + { + FileUtil.DeleteFileOrDirectory(DefaultPluginExportPath + ".meta"); + } + + AssetDatabase.Refresh(); + return true; + } + + /// + /// A helper function to move all the files recursively from the default plugin dir to a custom location the publisher moved the plugin to. + /// + private static void MovePluginFiles(string fromDirectory, string pluginRoot, bool isPluginOutsideAssetsDirectory) + { + var files = Directory.GetFiles(fromDirectory); + foreach (var file in files) + { + // We have to ignore some files, if the plugin is outside the Assets/ directory. + if (isPluginOutsideAssetsDirectory && PluginPathsToIgnoreMoveWhenPluginOutsideAssetsDirectory.Any(pluginPathsToIgnore => file.Contains(pluginPathsToIgnore))) continue; + + // Check if the destination folder exists and create it if it doesn't exist + var parentDirectory = Path.GetDirectoryName(file); + var destinationDirectoryPath = parentDirectory.Replace(DefaultPluginExportPath, pluginRoot); + if (!Directory.Exists(destinationDirectoryPath)) + { + Directory.CreateDirectory(destinationDirectoryPath); + } + + // If the meta file is of a folder asset and doesn't have labels (it is auto generated by Unity), just delete it. + if (IsAutoGeneratedFolderMetaFile(file)) + { + FileUtil.DeleteFileOrDirectory(file); + continue; + } + + var destinationPath = file.Replace(DefaultPluginExportPath, pluginRoot); + + // Check if the file is already present at the destination path and delete it. + if (File.Exists(destinationPath)) + { + FileUtil.DeleteFileOrDirectory(destinationPath); + } + + FileUtil.MoveFileOrDirectory(file, destinationPath); + } + + var directories = Directory.GetDirectories(fromDirectory); + foreach (var directory in directories) + { + // We might have to ignore some directories, if the plugin is outside the Assets/ directory. + if (isPluginOutsideAssetsDirectory && PluginPathsToIgnoreMoveWhenPluginOutsideAssetsDirectory.Any(pluginPathsToIgnore => directory.Contains(pluginPathsToIgnore))) continue; + + MovePluginFiles(directory, pluginRoot, isPluginOutsideAssetsDirectory); + } + + if (!isPluginOutsideAssetsDirectory) + { + FileUtil.DeleteFileOrDirectory(fromDirectory); + } + } + + private static bool IsAutoGeneratedFolderMetaFile(string assetPath) + { + // Check if it is a meta file. + if (!assetPath.EndsWith(".meta")) return false; + + var lines = File.ReadAllLines(assetPath); + var isFolderAsset = false; + var hasLabels = false; + foreach (var line in lines) + { + if (line.Contains("folderAsset: yes")) + { + isFolderAsset = true; + } + + if (line.Contains("labels:")) + { + hasLabels = true; + } + } + + // If it is a folder asset and doesn't have a label, the meta file is auto generated by + return isFolderAsset && !hasLabels; + } + + private static void CallDownloadPluginProgressCallback(string pluginName, float progress, bool isDone) + { + if (downloadPluginProgressCallback == null) return; + + downloadPluginProgressCallback(pluginName, progress, isDone); + } + + private static void CallImportPackageCompletedCallback(Network network) + { + if (importPackageCompletedCallback == null) return; + + importPackageCompletedCallback(network); + } + + private static object GetEditorUserBuildSetting(string name, object defaultValue) + { + var editorUserBuildSettingsType = typeof(EditorUserBuildSettings); + var property = editorUserBuildSettingsType.GetProperty(name); + if (property != null) + { + var value = property.GetValue(null, null); + if (value != null) return value; + } + + return defaultValue; + } + + private static string GetPluginFileName(Network network) + { + return network.Name.ToLowerInvariant() + "_" + network.LatestVersions.Unity + ".unitypackage"; + } + + #endregion + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta new file mode 100644 index 0000000..e9e3603 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: c5b874c1e65274159bcc0dc15d9458cc +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManager.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs new file mode 100644 index 0000000..904f8f9 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs @@ -0,0 +1,1131 @@ +// +// MaxIntegrationManager.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 5/27/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using System; +using System.Collections; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using VersionComparisonResult = MaxSdkUtils.VersionComparisonResult; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public class AppLovinIntegrationManagerWindow : EditorWindow + { + private const string windowTitle = "AppLovin Integration Manager"; + + private const string appLovinSdkKeyLink = "https://dash.applovin.com/o/account#keys"; + + private const string userTrackingUsageDescriptionDocsLink = "https://developer.apple.com/documentation/bundleresources/information_property_list/nsusertrackingusagedescription"; + private const string documentationTermsAndPrivacyPolicyFlow = "https://developers.applovin.com/en/unity/overview/terms-and-privacy-policy-flow"; + private const string documentationAdaptersLink = "https://developers.applovin.com/en/unity/preparing-mediated-networks"; + private const string documentationNote = "Please ensure that integration instructions (e.g. permissions, ATS settings, etc) specific to each network are implemented as well. Click the link below for more info:"; + private const string uninstallIconExportPath = "MaxSdk/Resources/Images/uninstall_icon.png"; + private const string alertIconExportPath = "MaxSdk/Resources/Images/alert_icon.png"; + private const string warningIconExportPath = "MaxSdk/Resources/Images/warning_icon.png"; + + private const string qualityServiceRequiresGradleBuildErrorMsg = "AppLovin Quality Service integration via AppLovin Integration Manager requires Custom Gradle Template enabled or Unity 2018.2 or higher.\n" + + "If you would like to continue using your existing setup, please add Quality Service Plugin to your build.gradle manually."; + + private const string customGradleVersionTooltip = "To set the version to 6.9.3, set the field to: https://services.gradle.org/distributions/gradle-6.9.3-bin.zip"; + private const string customGradleToolsVersionTooltip = "To set the version to 4.2.0, set the field to: 4.2.0"; + + private const string keyShowMicroSdkPartners = "com.applovin.show_micro_sdk_partners"; + private const string keyShowMediatedNetworks = "com.applovin.show_mediated_networks"; + private const string keyShowSdkSettings = "com.applovin.show_sdk_settings"; + private const string keyShowPrivacySettings = "com.applovin.show_privacy_settings"; + private const string keyShowOtherSettings = "com.applovin.show_other_settings"; + + private const string expandButtonText = "+"; + private const string collapseButtonText = "-"; + + private readonly string[] termsFlowPlatforms = new string[3] {"Both", "Android", "iOS"}; + private readonly string[] debugUserGeographies = new string[2] {"Not Set", "GDPR"}; + + private Vector2 scrollPosition; + private static readonly Vector2 windowMinSize = new Vector2(750, 750); + private const float actionFieldWidth = 60f; + private const float upgradeAllButtonWidth = 80f; + private const float networkFieldMinWidth = 100f; + private const float versionFieldMinWidth = 190f; + private const float privacySettingLabelWidth = 250f; + private const float networkFieldWidthPercentage = 0.22f; + private const float versionFieldWidthPercentage = 0.36f; // There are two version fields. Each take 40% of the width, network field takes the remaining 20%. + private static float previousWindowWidth = windowMinSize.x; + private static GUILayoutOption networkWidthOption = GUILayout.Width(networkFieldMinWidth); + private static GUILayoutOption versionWidthOption = GUILayout.Width(versionFieldMinWidth); + + private static GUILayoutOption privacySettingFieldWidthOption = GUILayout.Width(400); + private static readonly GUILayoutOption fieldWidth = GUILayout.Width(actionFieldWidth); + private static readonly GUILayoutOption upgradeAllButtonFieldWidth = GUILayout.Width(upgradeAllButtonWidth); + private static readonly GUILayoutOption collapseButtonWidthOption = GUILayout.Width(20f); + + private static readonly Color darkModeTextColor = new Color(0.29f, 0.6f, 0.8f); + + private GUIStyle titleLabelStyle; + private GUIStyle headerLabelStyle; + private GUIStyle environmentValueStyle; + private GUIStyle wrapTextLabelStyle; + private GUIStyle linkLabelStyle; + private GUIStyle iconStyle; + + private PluginData pluginData; + private bool pluginDataLoadFailed; + private bool isPluginMoved; + private bool shouldShowGoogleWarning; + private bool networkButtonsEnabled = true; + + private AppLovinEditorCoroutine loadDataCoroutine; + private Texture2D uninstallIcon; + private Texture2D alertIcon; + private Texture2D warningIcon; + + public static void ShowManager() + { + var manager = GetWindow(utility: true, title: windowTitle, focus: true); + manager.minSize = windowMinSize; + } + + #region Editor Window Lifecyle Methods + + private void Awake() + { + titleLabelStyle = new GUIStyle(EditorStyles.label) + { + fontSize = 14, + fontStyle = FontStyle.Bold, + fixedHeight = 20 + }; + + headerLabelStyle = new GUIStyle(EditorStyles.label) + { + fontSize = 12, + fontStyle = FontStyle.Bold, + fixedHeight = 18 + }; + + environmentValueStyle = new GUIStyle(EditorStyles.label) + { + alignment = TextAnchor.MiddleRight + }; + + linkLabelStyle = new GUIStyle(EditorStyles.label) + { + wordWrap = true, + normal = {textColor = EditorGUIUtility.isProSkin ? darkModeTextColor : Color.blue} + }; + + wrapTextLabelStyle = new GUIStyle(EditorStyles.label) + { + wordWrap = true + }; + + iconStyle = new GUIStyle(EditorStyles.miniButton) + { + fixedWidth = 18, + fixedHeight = 18, + padding = new RectOffset(1, 1, 1, 1) + }; + + // Load uninstall icon texture. + var uninstallIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(uninstallIconExportPath)); + uninstallIcon = new Texture2D(0, 0, TextureFormat.RGBA32, false); // 1. Initial size doesn't matter here, will be automatically resized once the image asset is loaded. 2. Set mipChain to false, else the texture has a weird blurry effect. + uninstallIcon.LoadImage(uninstallIconData); + + // Load alert icon texture. + var alertIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(alertIconExportPath)); + alertIcon = new Texture2D(0, 0, TextureFormat.RGBA32, false); + alertIcon.LoadImage(alertIconData); + + // Load warning icon texture. + var warningIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(warningIconExportPath)); + warningIcon = new Texture2D(0, 0, TextureFormat.RGBA32, false); + warningIcon.LoadImage(warningIconData); + + var pluginPath = Path.Combine(AppLovinIntegrationManager.PluginParentDirectory, "MaxSdk"); + isPluginMoved = !AppLovinIntegrationManager.DefaultPluginExportPath.Equals(pluginPath); + } + + private void OnEnable() + { + // Script reloads can cause AppLovinSettings.Instance to be null for one frame, + // so we load the Integration Manager on the following frame + if (AppLovinSettings.Instance == null) + { + AppLovinEditorCoroutine.StartCoroutine(WaitForNextFrameForEnable()); + } + else + { + OnWindowEnabled(); + } + } + + private IEnumerator WaitForNextFrameForEnable() + { + yield return new WaitForEndOfFrame(); + OnWindowEnabled(); + } + + private void OnWindowEnabled() + { + AppLovinIntegrationManager.downloadPluginProgressCallback = OnDownloadPluginProgress; + + // Plugin downloaded and imported. Update current versions for the imported package. + AppLovinIntegrationManager.importPackageCompletedCallback = OnImportPackageCompleted; + + // Disable old consent flow if new flow is enabled. + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) + { + AppLovinSettings.Instance.ConsentFlowEnabled = false; + AppLovinSettings.Instance.SaveAsync(); + } + + Load(); + } + + private void OnDisable() + { + if (loadDataCoroutine != null) + { + loadDataCoroutine.Stop(); + loadDataCoroutine = null; + } + + AppLovinIntegrationManager.Instance.CancelDownload(); + EditorUtility.ClearProgressBar(); + + // Saves the AppLovinSettings object if it has been changed. + AssetDatabase.SaveAssets(); + } + + private void OnGUI() + { + // OnGUI is called on each frame draw, so we don't want to do any unnecessary calculation if we can avoid it. So only calculate it when the width actually changed. + if (Math.Abs(previousWindowWidth - position.width) > 1) + { + previousWindowWidth = position.width; + CalculateFieldWidth(); + } + + using (var scrollView = new EditorGUILayout.ScrollViewScope(scrollPosition, false, false)) + { + scrollPosition = scrollView.scrollPosition; + + GUILayout.Space(5); + + // Draw AppLovin MAX plugin details + EditorGUILayout.LabelField("AppLovin MAX Plugin Details", titleLabelStyle); + + DrawPluginDetails(); + + if (pluginData != null && pluginData.PartnerMicroSdks != null) + { + DrawCollapsableSection(keyShowMicroSdkPartners, "AppLovin Micro SDK Partners", DrawPartnerMicroSdks); + } + + // Draw mediated networks); + EditorGUILayout.BeginHorizontal(); + var showDetails = DrawExpandCollapseButton(keyShowMediatedNetworks); + EditorGUILayout.LabelField("Mediated Networks", titleLabelStyle); + GUILayout.FlexibleSpace(); + DrawUpgradeAllButton(); + EditorGUILayout.EndHorizontal(); + if (showDetails) + { + DrawMediatedNetworks(); + } + + // Draw AppLovin Quality Service settings + DrawCollapsableSection(keyShowSdkSettings, "SDK Settings", DrawQualityServiceSettings); + + DrawCollapsableSection(keyShowPrivacySettings, "Privacy Settings", DrawPrivacySettings); + + DrawCollapsableSection(keyShowOtherSettings, "Other Settings", DrawOtherSettings); + + // Draw Unity environment details + EditorGUILayout.LabelField("Unity Environment Details", titleLabelStyle); + DrawUnityEnvironmentDetails(); + + // Draw documentation notes + EditorGUILayout.LabelField(new GUIContent(documentationNote), wrapTextLabelStyle); + if (GUILayout.Button(new GUIContent(documentationAdaptersLink), linkLabelStyle)) + { + Application.OpenURL(documentationAdaptersLink); + } + } + + if (GUI.changed) + { + AppLovinSettings.Instance.SaveAsync(); + AppLovinInternalSettings.Instance.Save(); + } + } + + #endregion + + #region UI Methods + + /// + /// Shows failure or loading screen based on whether or not plugin data failed to load. + /// + private void DrawEmptyPluginData() + { + GUILayout.Space(5); + + // Plugin data failed to load. Show error and retry button. + if (pluginDataLoadFailed) + { + GUILayout.Space(10); + GUILayout.BeginHorizontal(); + GUILayout.Space(5); + EditorGUILayout.LabelField("Failed to load plugin data. Please click retry or restart the integration manager.", titleLabelStyle); + if (GUILayout.Button("Retry", fieldWidth)) + { + pluginDataLoadFailed = false; + Load(); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + GUILayout.Space(10); + } + // Still loading, show loading label. + else + { + GUILayout.Space(10); + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + EditorGUILayout.LabelField("Loading data...", titleLabelStyle); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + GUILayout.Space(10); + } + + GUILayout.Space(5); + } + + /// + /// Draws AppLovin MAX plugin details. + /// + private void DrawPluginDetails() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + // Draw plugin version details + DrawHeaders("Platform", false); + + // Immediately after downloading and importing a plugin the entire IDE reloads and current versions can be null in that case. Will just show loading text in that case. + if (pluginData == null || pluginData.AppLovinMax.CurrentVersions == null) + { + DrawEmptyPluginData(); + } + else + { + var appLovinMax = pluginData.AppLovinMax; + // Check if a newer version is available to enable the upgrade button. + var upgradeButtonEnabled = appLovinMax.CurrentToLatestVersionComparisonResult == VersionComparisonResult.Lesser; + DrawPluginDetailRow("Unity 3D", appLovinMax.CurrentVersions.Unity, appLovinMax.LatestVersions.Unity); + DrawPluginDetailRow("Android", appLovinMax.CurrentVersions.Android, appLovinMax.LatestVersions.Android); + DrawPluginDetailRow("iOS", appLovinMax.CurrentVersions.Ios, appLovinMax.LatestVersions.Ios); + + // BeginHorizontal combined with FlexibleSpace makes sure that the button is centered horizontally. + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + + GUI.enabled = upgradeButtonEnabled; + if (GUILayout.Button(new GUIContent("Upgrade"), fieldWidth)) + { + AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.DownloadPlugin(appLovinMax)); + } + + GUI.enabled = true; + GUILayout.Space(5); + GUILayout.EndHorizontal(); + + GUILayout.Space(5); + } + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + /// + /// Draws the headers for a table. + /// + private void DrawHeaders(string firstColumnTitle, bool drawAction) + { + using (new EditorGUILayout.HorizontalScope()) + { + GUILayout.Space(5); + EditorGUILayout.LabelField(firstColumnTitle, headerLabelStyle, networkWidthOption); + EditorGUILayout.LabelField("Current Version", headerLabelStyle, versionWidthOption); + GUILayout.Space(3); + EditorGUILayout.LabelField("Latest Version", headerLabelStyle, versionWidthOption); + GUILayout.Space(3); + if (drawAction) + { + GUILayout.FlexibleSpace(); + GUILayout.Button("Actions", headerLabelStyle, fieldWidth); + GUILayout.Space(5); + } + } + + GUILayout.Space(4); + } + + /// + /// Draws the platform specific version details for AppLovin MAX plugin. + /// + private void DrawPluginDetailRow(string platform, string currentVersion, string latestVersion) + { + using (new EditorGUILayout.HorizontalScope()) + { + GUILayout.Space(5); + EditorGUILayout.LabelField(new GUIContent(platform), networkWidthOption); + EditorGUILayout.LabelField(new GUIContent(currentVersion), versionWidthOption); + GUILayout.Space(3); + EditorGUILayout.LabelField(new GUIContent(latestVersion), versionWidthOption); + GUILayout.Space(3); + } + + GUILayout.Space(4); + } + + /// + /// Draws mediated network details table. + /// + private void DrawMediatedNetworks() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + DrawHeaders("Network", true); + + // Immediately after downloading and importing a plugin the entire IDE reloads and current versions can be null in that case. Will just show loading text in that case. + if (pluginData == null || pluginData.AppLovinMax.CurrentVersions == null) + { + DrawEmptyPluginData(); + } + else + { + var networks = pluginData.MediatedNetworks; + foreach (var network in networks) + { + DrawNetworkDetailRow(network); + } + + GUILayout.Space(10); + } + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private void DrawPartnerMicroSdks() + { + if (pluginData == null) return; + + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + DrawHeaders("Network", true); + + var partnerMicroSdks = pluginData.PartnerMicroSdks; + foreach (var partnerMicroSdk in partnerMicroSdks) + { + DrawNetworkDetailRow(partnerMicroSdk); + } + + GUILayout.Space(10); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + /// + /// Draws the network specific details for a given network. + /// + private void DrawNetworkDetailRow(Network network) + { + string action; + var currentVersion = network.CurrentVersions != null ? network.CurrentVersions.Unity : ""; + var latestVersion = network.LatestVersions.Unity; + bool isActionEnabled; + bool isInstalled; + if (string.IsNullOrEmpty(currentVersion)) + { + action = "Install"; + currentVersion = "Not Installed"; + isActionEnabled = true; + isInstalled = false; + } + else + { + isInstalled = true; + + var comparison = network.CurrentToLatestVersionComparisonResult; + // A newer version is available + if (comparison == VersionComparisonResult.Lesser) + { + action = "Upgrade"; + isActionEnabled = true; + } + // Current installed version is newer than latest version from DB (beta version) + else if (comparison == VersionComparisonResult.Greater) + { + action = "Installed"; + isActionEnabled = false; + } + // Already on the latest version + else + { + action = "Installed"; + isActionEnabled = false; + } + } + + GUILayout.Space(4); + using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandHeight(false))) + { + GUILayout.Space(5); + EditorGUILayout.LabelField(new GUIContent(network.DisplayName), networkWidthOption); + EditorGUILayout.LabelField(new GUIContent(currentVersion), versionWidthOption); + GUILayout.Space(3); + EditorGUILayout.LabelField(new GUIContent(latestVersion), versionWidthOption); + GUILayout.Space(3); + GUILayout.FlexibleSpace(); + + if (network.RequiresUpdate) + { + GUILayout.Label(new GUIContent {image = alertIcon, tooltip = "Adapter not compatible, please update to the latest version."}, iconStyle); + } + else if ((network.Name.Equals("ADMOB_NETWORK") || network.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")) && shouldShowGoogleWarning) + { + GUILayout.Label(new GUIContent {image = warningIcon, tooltip = "You may see unexpected errors if you use different versions of the AdMob and Google Ad Manager adapter SDKs."}, iconStyle); + } + + GUI.enabled = networkButtonsEnabled && isActionEnabled; + if (GUILayout.Button(new GUIContent(action), fieldWidth)) + { + // Download the plugin. + AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.DownloadPlugin(network)); + } + + GUI.enabled = true; + GUILayout.Space(2); + + GUI.enabled = networkButtonsEnabled && isInstalled; + if (GUILayout.Button(new GUIContent {image = uninstallIcon, tooltip = "Uninstall"}, iconStyle)) + { + EditorUtility.DisplayProgressBar("Integration Manager", "Deleting " + network.Name + "...", 0.5f); + var pluginRoot = AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; + foreach (var pluginFilePath in network.PluginFilePaths) + { + var filePath = Path.Combine(pluginRoot, pluginFilePath); + FileUtil.DeleteFileOrDirectory(filePath); + FileUtil.DeleteFileOrDirectory(filePath + ".meta"); + } + + AppLovinIntegrationManager.UpdateCurrentVersions(network, pluginRoot); + + // Refresh UI + AssetDatabase.Refresh(); + EditorUtility.ClearProgressBar(); + } + + GUI.enabled = true; + GUILayout.Space(5); + } + + if (isInstalled) + { + DrawGoogleAppIdTextBoxIfNeeded(network); + } + } + + private void DrawGoogleAppIdTextBoxIfNeeded(Network network) + { + // Custom integration for AdMob where the user can enter the Android and iOS App IDs. + if (network.Name.Equals("ADMOB_NETWORK")) + { + // Show only one set of text boxes if both ADMOB and GAM are installed + if (AppLovinIntegrationManager.IsAdapterInstalled("GoogleAdManager")) return; + + DrawGoogleAppIdTextBox(); + } + + // Custom integration for GAM where the user can enter the Android and iOS App IDs. + else if (network.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")) + { + DrawGoogleAppIdTextBox(); + } + } + + /// + /// Draws the text box for GAM or ADMOB to input the App ID + /// + private void DrawGoogleAppIdTextBox() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(20); + using (new EditorGUILayout.VerticalScope("box")) + { + GUILayout.Space(2); + AppLovinSettings.Instance.AdMobAndroidAppId = DrawTextField("App ID (Android)", AppLovinSettings.Instance.AdMobAndroidAppId, networkWidthOption); + AppLovinSettings.Instance.AdMobIosAppId = DrawTextField("App ID (iOS)", AppLovinSettings.Instance.AdMobIosAppId, networkWidthOption); + } + + GUILayout.EndHorizontal(); + } + + /// + /// Draws the upgrade all button + /// + private void DrawUpgradeAllButton() + { + GUI.enabled = NetworksRequireUpgrade(); + if (GUILayout.Button(new GUIContent("Upgrade All"), upgradeAllButtonFieldWidth)) + { + AppLovinEditorCoroutine.StartCoroutine(UpgradeAllNetworks()); + } + + GUI.enabled = true; + GUILayout.Space(10); + } + + private void DrawQualityServiceSettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + GUILayout.Space(4); + if (!AppLovinIntegrationManager.CanProcessAndroidQualityServiceSettings) + { + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox(qualityServiceRequiresGradleBuildErrorMsg, MessageType.Warning); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + + GUILayout.Space(4); + } + + AppLovinSettings.Instance.SdkKey = DrawTextField("AppLovin SDK Key", AppLovinSettings.Instance.SdkKey, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + GUILayout.Button("You can find your SDK key here: ", wrapTextLabelStyle, GUILayout.Width(185)); // Setting a fixed width since Unity adds arbitrary padding at the end leaving a space between link and text. + if (GUILayout.Button(new GUIContent(appLovinSdkKeyLink), linkLabelStyle)) + { + Application.OpenURL(appLovinSdkKeyLink); + } + + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinSettings.Instance.QualityServiceEnabled = GUILayout.Toggle(AppLovinSettings.Instance.QualityServiceEnabled, " Enable MAX Ad Review"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + GUILayout.Space(4); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private string DrawTextField(string fieldTitle, string text, GUILayoutOption labelWidth, GUILayoutOption textFieldWidthOption = null, bool isTextFieldEditable = true, string tooltip = "") + { + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + var guiContent = MaxSdkUtils.IsValidString(tooltip) ? new GUIContent(fieldTitle, tooltip) : new GUIContent(fieldTitle); + EditorGUILayout.LabelField(guiContent, labelWidth); + GUILayout.Space(4); + if (isTextFieldEditable) + { + text = (textFieldWidthOption == null) ? GUILayout.TextField(text) : GUILayout.TextField(text, textFieldWidthOption); + } + else + { + if (textFieldWidthOption == null) + { + GUILayout.Label(text); + } + else + { + GUILayout.Label(text, textFieldWidthOption); + } + } + + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + return text; + } + + private void DrawPrivacySettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + if (AppLovinSettings.Instance.ConsentFlowEnabled) + { + DrawTermsFlowSettings(); + } + else + { + DrawConsentFlowSettings(); + } + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private void DrawTermsFlowSettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox("The Terms Flow has been deprecated; switch to the MAX Terms and Privacy Policy Flow instead.", MessageType.Warning); // TODO Refine + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Switch to MAX Terms and Privacy Policy Flow")) + { + AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl = AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl; + AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl = AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl; + AppLovinInternalSettings.Instance.ConsentFlowEnabled = true; + AppLovinSettings.Instance.ConsentFlowEnabled = false; + } + + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinSettings.Instance.ConsentFlowEnabled = GUILayout.Toggle(AppLovinSettings.Instance.ConsentFlowEnabled, " Enable Terms Flow"); + GUILayout.FlexibleSpace(); + GUI.enabled = AppLovinSettings.Instance.ConsentFlowEnabled; + AppLovinSettings.Instance.ConsentFlowPlatform = (Platform) EditorGUILayout.Popup((int) AppLovinSettings.Instance.ConsentFlowPlatform, termsFlowPlatforms); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl = DrawTextField("Privacy Policy URL", AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl = DrawTextField("Terms of Service URL (optional)", AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionEn = DrawTextField("User Tracking Usage Description (iOS only)", AppLovinSettings.Instance.UserTrackingUsageDescriptionEn, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinSettings.Instance.UserTrackingUsageLocalizationEnabled = GUILayout.Toggle(AppLovinSettings.Instance.UserTrackingUsageLocalizationEnabled, " Localize User Tracking Usage Description (iOS only)"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + if (AppLovinSettings.Instance.UserTrackingUsageLocalizationEnabled) + { + AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHans = DrawTextField("Chinese, Simplified (zh-Hans)", AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHans, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHant = DrawTextField("Chinese, Traditional (zh-Hant)", AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHant, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); // TODO: Remove new mark for next release. + AppLovinSettings.Instance.UserTrackingUsageDescriptionFr = DrawTextField("French (fr)", AppLovinSettings.Instance.UserTrackingUsageDescriptionFr, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionDe = DrawTextField("German (de)", AppLovinSettings.Instance.UserTrackingUsageDescriptionDe, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionJa = DrawTextField("Japanese (ja)", AppLovinSettings.Instance.UserTrackingUsageDescriptionJa, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionKo = DrawTextField("Korean (ko)", AppLovinSettings.Instance.UserTrackingUsageDescriptionKo, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinSettings.Instance.UserTrackingUsageDescriptionEs = DrawTextField("Spanish (es)", AppLovinSettings.Instance.UserTrackingUsageDescriptionEs, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox("MAX may add more localized strings to this list in the future, which will set the default value of the User Tracking Usage Description string for more locales. If you are overriding these with your own custom translations, you may want to review this list whenever you upgrade the plugin to see if there are new entries you may want to customize.", MessageType.Info); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox("If you have your own implementation of InfoPlist.strings localization implementation, please use that instead. Using both at the same time may cause conflicts.", MessageType.Info); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + } + + GUI.enabled = true; + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + GUILayout.Button("Click the link below for more information about User Tracking Usage Description: ", wrapTextLabelStyle); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + if (GUILayout.Button(new GUIContent(userTrackingUsageDescriptionDocsLink), linkLabelStyle)) + { + Application.OpenURL(userTrackingUsageDescriptionDocsLink); + } + + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + } + + private void DrawConsentFlowSettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinInternalSettings.Instance.ConsentFlowEnabled = GUILayout.Toggle(AppLovinInternalSettings.Instance.ConsentFlowEnabled, " Enable MAX Terms and Privacy Policy Flow"); + GUILayout.EndHorizontal(); + GUILayout.Space(6); + GUILayout.Space(4); + EditorGUILayout.HelpBox("This flow automatically includes Google UMP.", MessageType.Info); + + GUI.enabled = true; + + if (!AppLovinInternalSettings.Instance.ConsentFlowEnabled) return; + + GUILayout.Space(6); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.LabelField("Click the link below to access the guide on creating the GDPR form within AdMob's dashboard."); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + if (GUILayout.Button(new GUIContent(documentationTermsAndPrivacyPolicyFlow), linkLabelStyle)) + { + Application.OpenURL(documentationTermsAndPrivacyPolicyFlow); + } + + GUILayout.Space(4); + GUILayout.EndHorizontal(); + + GUILayout.Space(8); + + AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl = DrawTextField("Privacy Policy URL", AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl = DrawTextField("Terms of Service URL (optional)", AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.LabelField("iOS specific settings:", headerLabelStyle); + GUILayout.EndHorizontal(); + + var isEditableTextField = AppLovinInternalSettings.Instance.OverrideDefaultUserTrackingUsageDescriptions; + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinInternalSettings.Instance.OverrideDefaultUserTrackingUsageDescriptions = GUILayout.Toggle(AppLovinInternalSettings.Instance.OverrideDefaultUserTrackingUsageDescriptions, " Override Default User Tracking Usage Description"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + GUILayout.Space(4); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn = DrawTextField("User Tracking Usage Description", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + AppLovinInternalSettings.Instance.UserTrackingUsageLocalizationEnabled = GUILayout.Toggle(AppLovinInternalSettings.Instance.UserTrackingUsageLocalizationEnabled, " Localize User Tracking Usage Description"); + GUILayout.EndHorizontal(); + GUILayout.Space(4); + + if (AppLovinInternalSettings.Instance.UserTrackingUsageLocalizationEnabled) + { + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans = DrawTextField("Chinese, Simplified (zh-Hans)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant = DrawTextField("Chinese, Traditional (zh-Hant)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr = DrawTextField("French (fr)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe = DrawTextField("German (de)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa = DrawTextField("Japanese (ja)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo = DrawTextField("Korean (ko)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs = DrawTextField("Spanish (es)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField); + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.HelpBox("If you have your own implementation of InfoPlist.strings localization implementation, please use that instead. Using both at the same time may cause conflicts.", MessageType.Info); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + } + + GUILayout.Space(4); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + GUILayout.Button("Click the link below for more information about User Tracking Usage Description: ", wrapTextLabelStyle); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + if (GUILayout.Button(new GUIContent(userTrackingUsageDescriptionDocsLink), linkLabelStyle)) + { + Application.OpenURL(userTrackingUsageDescriptionDocsLink); + } + + GUILayout.Space(4); + GUILayout.EndHorizontal(); + GUILayout.Space(8); + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.LabelField("Testing:", headerLabelStyle); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + GUILayout.Space(4); + EditorGUILayout.LabelField("Debug User Geography"); + AppLovinInternalSettings.Instance.DebugUserGeography = (MaxSdkBase.ConsentFlowUserGeography) EditorGUILayout.Popup((int) AppLovinInternalSettings.Instance.DebugUserGeography, debugUserGeographies, privacySettingFieldWidthOption); + GUILayout.Space(4); + GUILayout.EndHorizontal(); + + EditorGUILayout.HelpBox("Debug User Geography is only enabled in debug mode", MessageType.Info); + } + + private void DrawOtherSettings() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + GUILayout.Space(5); + AppLovinSettings.Instance.SetAttributionReportEndpoint = DrawOtherSettingsToggle(AppLovinSettings.Instance.SetAttributionReportEndpoint, " Set Advertising Attribution Report Endpoint in Info.plist (iOS only)"); + GUILayout.Space(5); + AppLovinSettings.Instance.AddApsSkAdNetworkIds = DrawOtherSettingsToggle(AppLovinSettings.Instance.AddApsSkAdNetworkIds, " Add Amazon Publisher Services SKAdNetworkID's"); + GUILayout.Space(5); + var autoUpdateEnabled = DrawOtherSettingsToggle(EditorPrefs.GetBool(AppLovinAutoUpdater.KeyAutoUpdateEnabled, true), " Enable Auto Update", "Checks for AppLovin MAX plugin updates and notifies you when an update is available."); + EditorPrefs.SetBool(AppLovinAutoUpdater.KeyAutoUpdateEnabled, autoUpdateEnabled); + GUILayout.Space(5); + var verboseLoggingEnabled = DrawOtherSettingsToggle(EditorPrefs.GetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, false), " Enable Verbose Logging"); + EditorPrefs.SetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, verboseLoggingEnabled); + GUILayout.Space(5); + AppLovinSettings.Instance.CustomGradleVersionUrl = DrawTextField("Custom Gradle Version URL", AppLovinSettings.Instance.CustomGradleVersionUrl, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, tooltip: customGradleVersionTooltip); + AppLovinSettings.Instance.CustomGradleToolsVersion = DrawTextField("Custom Gradle Tools Version", AppLovinSettings.Instance.CustomGradleToolsVersion, GUILayout.Width(privacySettingLabelWidth), privacySettingFieldWidthOption, tooltip: customGradleToolsVersionTooltip); + EditorGUILayout.HelpBox("This will overwrite the gradle build tools version in your base gradle template.", MessageType.Info); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private bool DrawOtherSettingsToggle(bool value, string text, string tooltip = "") + { + using (new EditorGUILayout.HorizontalScope()) + { + GUILayout.Space(4); + var content = MaxSdkUtils.IsValidString(tooltip) ? new GUIContent(text, tooltip) : new GUIContent(text); + var toggleValue = GUILayout.Toggle(value, content); + GUILayout.Space(4); + + return toggleValue; + } + } + + private void DrawUnityEnvironmentDetails() + { + GUILayout.BeginHorizontal(); + GUILayout.Space(10); + using (new EditorGUILayout.VerticalScope("box")) + { + DrawUnityEnvironmentDetailRow("Unity Version", Application.unityVersion); + GUILayout.Space(5); + DrawUnityEnvironmentDetailRow("Platform", Application.platform.ToString()); + GUILayout.Space(5); + DrawUnityEnvironmentDetailRow("External Dependency Manager Version", AppLovinIntegrationManager.ExternalDependencyManagerVersion); + GUILayout.Space(5); + DrawUnityEnvironmentDetailRow("Gradle Template Enabled", AppLovinIntegrationManager.GradleTemplateEnabled.ToString()); + } + + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + private void DrawUnityEnvironmentDetailRow(string key, string value) + { + using (new EditorGUILayout.HorizontalScope()) + { + GUILayout.Space(5); + EditorGUILayout.LabelField(key, GUILayout.Width(250)); + GUILayout.FlexibleSpace(); + EditorGUILayout.LabelField(value, environmentValueStyle); + GUILayout.Space(5); + } + } + + private void DrawCollapsableSection(string keyShowDetails, string label, Action drawContent) + { + EditorGUILayout.BeginHorizontal(); + var showDetails = DrawExpandCollapseButton(keyShowDetails); + + EditorGUILayout.LabelField(label, titleLabelStyle); + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + if (showDetails) + { + drawContent(); + } + } + + private bool DrawExpandCollapseButton(string keyShowDetails) + { + var showDetails = EditorPrefs.GetBool(keyShowDetails, true); + var buttonText = showDetails ? collapseButtonText : expandButtonText; + if (GUILayout.Button(buttonText, collapseButtonWidthOption)) + { + EditorPrefs.SetBool(keyShowDetails, !showDetails); + } + + return showDetails; + } + + /// + /// Calculates the fields width based on the width of the window. + /// + private void CalculateFieldWidth() + { + var currentWidth = position.width; + var availableWidth = currentWidth - actionFieldWidth - 80; // NOTE: Magic number alert. This is the sum of all the spacing the fields and other UI elements. + var networkLabelWidth = Math.Max(networkFieldMinWidth, availableWidth * networkFieldWidthPercentage); + networkWidthOption = GUILayout.Width(networkLabelWidth); + + var versionLabelWidth = Math.Max(versionFieldMinWidth, availableWidth * versionFieldWidthPercentage); + versionWidthOption = GUILayout.Width(versionLabelWidth); + + const int textFieldOtherUiElementsWidth = 55; // NOTE: Magic number alert. This is the sum of all the spacing the fields and other UI elements. + var availableUserDescriptionTextFieldWidth = currentWidth - privacySettingLabelWidth - textFieldOtherUiElementsWidth; + privacySettingFieldWidthOption = GUILayout.Width(availableUserDescriptionTextFieldWidth); + } + + #endregion + + #region Utility Methods + + /// + /// Loads the plugin data to be displayed by this window. + /// + private void Load() + { + loadDataCoroutine = AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.LoadPluginData(data => + { + if (data == null) + { + pluginDataLoadFailed = true; + } + else + { + pluginData = data; + pluginDataLoadFailed = false; + + UpdateShouldShowGoogleWarningIfNeeded(); + } + + CalculateFieldWidth(); + Repaint(); + })); + } + + /// + /// Callback method that will be called with progress updates when the plugin is being downloaded. + /// + public static void OnDownloadPluginProgress(string pluginName, float progress, bool done) + { + // Download is complete. Clear progress bar. + if (done) + { + EditorUtility.ClearProgressBar(); + } + // Download is in progress, update progress bar. + else + { + if (EditorUtility.DisplayCancelableProgressBar(windowTitle, string.Format("Downloading {0} plugin...", pluginName), progress)) + { + AppLovinIntegrationManager.Instance.CancelDownload(); + EditorUtility.ClearProgressBar(); + } + } + } + + private void OnImportPackageCompleted(Network network) + { + var parentDirectory = network.Name.Equals("APPLOVIN_NETWORK") ? AppLovinIntegrationManager.PluginParentDirectory : AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; + AppLovinIntegrationManager.UpdateCurrentVersions(network, parentDirectory); + + UpdateShouldShowGoogleWarningIfNeeded(); + } + + private void UpdateShouldShowGoogleWarningIfNeeded() + { + if (pluginData == null) + { + shouldShowGoogleWarning = false; + return; + } + + var networks = pluginData.MediatedNetworks; + var googleNetwork = networks.FirstOrDefault(foundNetwork => foundNetwork.Name.Equals("ADMOB_NETWORK")); + var googleAdManagerNetwork = networks.FirstOrDefault(foundNetwork => foundNetwork.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")); + + if (googleNetwork != null && googleAdManagerNetwork != null && + !string.IsNullOrEmpty(googleNetwork.CurrentVersions.Unity) && !string.IsNullOrEmpty(googleAdManagerNetwork.CurrentVersions.Unity) && + !googleNetwork.CurrentVersions.HasEqualSdkVersions(googleAdManagerNetwork.CurrentVersions)) + { + shouldShowGoogleWarning = true; + } + else + { + shouldShowGoogleWarning = false; + } + } + + /// + /// Upgrades all outdated networks + /// + private IEnumerator UpgradeAllNetworks() + { + networkButtonsEnabled = false; + EditorApplication.LockReloadAssemblies(); + var networks = pluginData.MediatedNetworks; + foreach (var network in networks) + { + var comparison = network.CurrentToLatestVersionComparisonResult; + // A newer version is available + if (!string.IsNullOrEmpty(network.CurrentVersions.Unity) && comparison == VersionComparisonResult.Lesser) + { + yield return AppLovinIntegrationManager.Instance.DownloadPlugin(network, false); + } + } + + EditorApplication.UnlockReloadAssemblies(); + networkButtonsEnabled = true; + + // The pluginData becomes stale after the networks have been updated, and we should re-load it. + Load(); + } + + /// + /// Returns whether any network adapter needs to be upgraded + /// + private bool NetworksRequireUpgrade() + { + if (pluginData == null || pluginData.AppLovinMax.CurrentVersions == null) return false; + + var networks = pluginData.MediatedNetworks; + return networks.Any(network => !string.IsNullOrEmpty(network.CurrentVersions.Unity) && network.CurrentToLatestVersionComparisonResult == VersionComparisonResult.Lesser); + } + + #endregion + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta new file mode 100644 index 0000000..d7996fd --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 84c61b4c05e114cec91df447d1b585f8 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinIntegrationManagerWindow.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs new file mode 100644 index 0000000..41552d9 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs @@ -0,0 +1,297 @@ +// +// AppLovinInternalSettigns.cs +// AppLovin User Engagement Unity Plugin +// +// Created by Santosh Bagadi on 9/15/22. +// Copyright © 2022 AppLovin. All rights reserved. +// + +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// A representing the AppLovin internal settings that can be set in the Integration Manager Window. + /// + /// The scriptable object asset is saved under ProjectSettings as AppLovinInternalSettings.json. + /// + public class AppLovinInternalSettings : ScriptableObject + { + private static AppLovinInternalSettings instance; + + public const string DefaultUserTrackingDescriptionEn = "This uses device info for more personalized ads and content"; + public const string DefaultUserTrackingDescriptionDe = "Dies benutzt Gerätinformationen für relevantere Werbeinhalte"; + public const string DefaultUserTrackingDescriptionEs = "Esto utiliza la información del dispositivo para anuncios y contenido más personalizados"; + public const string DefaultUserTrackingDescriptionFr = "Cela permet d'utiliser les informations du téléphone pour afficher des contenus publicitaires plus pertinents."; + public const string DefaultUserTrackingDescriptionJa = "これはユーザーデータをもとに、より関連性の高い広告コンテンツをお客様に提供します"; + public const string DefaultUserTrackingDescriptionKo = "보다 개인화된 광고 및 콘텐츠를 위해 기기 정보를 사용합니다."; + public const string DefaultUserTrackingDescriptionZhHans = "我们使用设备信息来提供个性化的广告和内容。"; + public const string DefaultUserTrackingDescriptionZhHant = "我們使用設備信息來提供個性化的廣告和內容。"; + + [SerializeField] private bool consentFlowEnabled; + [SerializeField] private string consentFlowPrivacyPolicyUrl = string.Empty; + [SerializeField] private string consentFlowTermsOfServiceUrl = string.Empty; + [SerializeField] private bool overrideDefaultUserTrackingUsageDescriptions; + [SerializeField] private MaxSdkBase.ConsentFlowUserGeography debugUserGeography; + [SerializeField] private string userTrackingUsageDescriptionEn = string.Empty; + [SerializeField] private bool userTrackingUsageLocalizationEnabled; + [SerializeField] private string userTrackingUsageDescriptionDe = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionEs = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionFr = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionJa = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionKo = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionZhHans = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionZhHant = string.Empty; + + private const string SettingsFilePath = "ProjectSettings/AppLovinInternalSettings.json"; + + public static AppLovinInternalSettings Instance + { + get + { + if (instance != null) return instance; + + instance = CreateInstance(); + + var projectRootPath = Path.GetDirectoryName(Application.dataPath); + var settingsFilePath = Path.Combine(projectRootPath, SettingsFilePath); + if (!File.Exists(settingsFilePath)) + { + instance.Save(); + return instance; + } + + var settingsJson = File.ReadAllText(settingsFilePath); + if (string.IsNullOrEmpty(settingsJson)) + { + instance.Save(); + return instance; + } + + JsonUtility.FromJsonOverwrite(settingsJson, instance); + return instance; + } + } + + public void Save() + { + var settingsJson = JsonUtility.ToJson(instance); + try + { + var projectRootPath = Path.GetDirectoryName(Application.dataPath); + var settingsFilePath = Path.Combine(projectRootPath, SettingsFilePath); + File.WriteAllText(settingsFilePath, settingsJson); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to save internal settings."); + Console.WriteLine(exception); + } + } + + /// + /// Whether or not AppLovin Consent Flow is enabled. + /// + public bool ConsentFlowEnabled + { + get { return consentFlowEnabled; } + set + { + var previousValue = consentFlowEnabled; + consentFlowEnabled = value; + + if (value) + { + // If the value didn't change, we don't need to update anything. + if (previousValue) return; + + UserTrackingUsageDescriptionEn = DefaultUserTrackingDescriptionEn; + UserTrackingUsageLocalizationEnabled = true; + } + else + { + ConsentFlowPrivacyPolicyUrl = string.Empty; + ConsentFlowTermsOfServiceUrl = string.Empty; + UserTrackingUsageDescriptionEn = string.Empty; + UserTrackingUsageLocalizationEnabled = false; + OverrideDefaultUserTrackingUsageDescriptions = false; + } + } + } + + /// + /// A URL pointing to the Privacy Policy for the app to be shown when prompting the user for consent. + /// + public string ConsentFlowPrivacyPolicyUrl + { + get { return consentFlowPrivacyPolicyUrl; } + set { consentFlowPrivacyPolicyUrl = value; } + } + + /// + /// An optional URL pointing to the Terms of Service for the app to be shown when prompting the user for consent. + /// + public string ConsentFlowTermsOfServiceUrl + { + get { return consentFlowTermsOfServiceUrl; } + set { consentFlowTermsOfServiceUrl = value; } + } + + /// + /// A User Tracking Usage Description in English to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionEn + { + get { return userTrackingUsageDescriptionEn; } + set { userTrackingUsageDescriptionEn = value; } + } + + /// + /// An optional string to set debug user geography + /// + public MaxSdkBase.ConsentFlowUserGeography DebugUserGeography + { + get { return debugUserGeography; } + set { debugUserGeography = value; } + } + + public bool OverrideDefaultUserTrackingUsageDescriptions + { + get { return overrideDefaultUserTrackingUsageDescriptions; } + set + { + var previousValue = overrideDefaultUserTrackingUsageDescriptions; + overrideDefaultUserTrackingUsageDescriptions = value; + + if (!value) + { + if (!previousValue) return; + + UserTrackingUsageDescriptionEn = DefaultUserTrackingDescriptionEn; + UserTrackingUsageDescriptionDe = DefaultUserTrackingDescriptionDe; + UserTrackingUsageDescriptionEs = DefaultUserTrackingDescriptionEs; + UserTrackingUsageDescriptionFr = DefaultUserTrackingDescriptionFr; + UserTrackingUsageDescriptionJa = DefaultUserTrackingDescriptionJa; + UserTrackingUsageDescriptionKo = DefaultUserTrackingDescriptionKo; + UserTrackingUsageDescriptionZhHans = DefaultUserTrackingDescriptionZhHans; + UserTrackingUsageDescriptionZhHant = DefaultUserTrackingDescriptionZhHant; + } + } + } + + /// + /// Whether or not to localize User Tracking Usage Description. + /// For more information see Apple's documentation. + /// + public bool UserTrackingUsageLocalizationEnabled + { + get { return userTrackingUsageLocalizationEnabled; } + set + { + var previousValue = userTrackingUsageLocalizationEnabled; + userTrackingUsageLocalizationEnabled = value; + + if (value) + { + // If the value didn't change, don't do anything + if (previousValue) return; + + // Don't set the default values if they are being overriden. + if (OverrideDefaultUserTrackingUsageDescriptions) return; + + UserTrackingUsageDescriptionDe = DefaultUserTrackingDescriptionDe; + UserTrackingUsageDescriptionEs = DefaultUserTrackingDescriptionEs; + UserTrackingUsageDescriptionFr = DefaultUserTrackingDescriptionFr; + UserTrackingUsageDescriptionJa = DefaultUserTrackingDescriptionJa; + UserTrackingUsageDescriptionKo = DefaultUserTrackingDescriptionKo; + UserTrackingUsageDescriptionZhHans = DefaultUserTrackingDescriptionZhHans; + UserTrackingUsageDescriptionZhHant = DefaultUserTrackingDescriptionZhHant; + } + else + { + UserTrackingUsageDescriptionDe = string.Empty; + UserTrackingUsageDescriptionEs = string.Empty; + UserTrackingUsageDescriptionFr = string.Empty; + UserTrackingUsageDescriptionJa = string.Empty; + UserTrackingUsageDescriptionKo = string.Empty; + UserTrackingUsageDescriptionZhHans = string.Empty; + UserTrackingUsageDescriptionZhHant = string.Empty; + } + } + } + + /// + /// A User Tracking Usage Description in German to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionDe + { + get { return userTrackingUsageDescriptionDe; } + set { userTrackingUsageDescriptionDe = value; } + } + + /// + /// A User Tracking Usage Description in Spanish to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionEs + { + get { return userTrackingUsageDescriptionEs; } + set { userTrackingUsageDescriptionEs = value; } + } + + /// + /// A User Tracking Usage Description in French to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionFr + { + get { return userTrackingUsageDescriptionFr; } + set { userTrackingUsageDescriptionFr = value; } + } + + /// + /// A User Tracking Usage Description in Japanese to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionJa + { + get { return userTrackingUsageDescriptionJa; } + set { userTrackingUsageDescriptionJa = value; } + } + + /// + /// A User Tracking Usage Description in Korean to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionKo + { + get { return userTrackingUsageDescriptionKo; } + set { userTrackingUsageDescriptionKo = value; } + } + + /// + /// A User Tracking Usage Description in Chinese (Simplified) to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionZhHans + { + get { return userTrackingUsageDescriptionZhHans; } + set { userTrackingUsageDescriptionZhHans = value; } + } + + /// + /// A User Tracking Usage Description in Chinese (Traditional) to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionZhHant + { + get { return userTrackingUsageDescriptionZhHant; } + set { userTrackingUsageDescriptionZhHant = value; } + } + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta new file mode 100644 index 0000000..a863905 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 65c51e21887ae42c2839962fb9585e9f +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinInternalSettings.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs new file mode 100644 index 0000000..130b383 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs @@ -0,0 +1,60 @@ +// +// MaxMenuItems.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 5/27/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using UnityEditor; +using UnityEngine; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public class AppLovinMenuItems + { + /** + * The special characters at the end represent a shortcut for this action. + * + * % - ctrl on Windows, cmd on macOS + * # - shift + * & - alt + * + * So, (shift + cmd/ctrl + i) will launch the integration manager + */ + [MenuItem("AppLovin/Integration Manager %#i")] + private static void IntegrationManager() + { + ShowIntegrationManager(); + } + + [MenuItem("AppLovin/Documentation")] + private static void Documentation() + { + Application.OpenURL("https://developers.applovin.com/en/unity/overview/integration"); + } + + [MenuItem("AppLovin/Contact Us")] + private static void ContactUs() + { + Application.OpenURL("https://www.applovin.com/contact/"); + } + + [MenuItem("AppLovin/About")] + private static void About() + { + Application.OpenURL("https://www.applovin.com/about/"); + } + + [MenuItem("Assets/AppLovin Integration Manager")] + private static void AssetsIntegrationManager() + { + ShowIntegrationManager(); + } + + private static void ShowIntegrationManager() + { + AppLovinIntegrationManagerWindow.ShowManager(); + } + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.meta new file mode 100644 index 0000000..30fb834 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 02c2d277874f649d18a59d382420bf65 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinMenuItems.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs new file mode 100644 index 0000000..533a4f3 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs @@ -0,0 +1,550 @@ +// +// MaxPostProcessBuildAndroid.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 4/10/20. +// Copyright © 2020 AppLovin. All rights reserved. +// + +#if UNITY_ANDROID +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Xml.Linq; +using AppLovinMax.ThirdParty.MiniJson; +using UnityEditor; +using UnityEditor.Android; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// A post processor used to update the Android project once it is generated. + /// + public class AppLovinPostProcessAndroid : IPostGenerateGradleAndroidProject + { +#if UNITY_2019_3_OR_NEWER + private const string PropertyAndroidX = "android.useAndroidX"; + private const string PropertyJetifier = "android.enableJetifier"; + private const string EnableProperty = "=true"; +#endif + private const string PropertyDexingArtifactTransform = "android.enableDexingArtifactTransform"; + private const string DisableProperty = "=false"; + + private const string KeyMetaDataAppLovinVerboseLoggingOn = "applovin.sdk.verbose_logging"; + private const string KeyMetaDataGoogleApplicationId = "com.google.android.gms.ads.APPLICATION_ID"; + private const string KeyMetaDataGoogleOptimizeInitialization = "com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"; + private const string KeyMetaDataGoogleOptimizeAdLoading = "com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"; + + private const string KeyMetaDataMobileFuseAutoInit = "com.mobilefuse.sdk.disable_auto_init"; + private const string KeyMetaDataMyTargetAutoInit = "com.my.target.autoInitMode"; + + private const string KeyMetaDataAppLovinSdkKey = "applovin.sdk.key"; + + private const string AppLovinSettingsFileName = "applovin_settings.json"; + + private const string KeyTermsFlowSettings = "terms_flow_settings"; + private const string KeyTermsFlowEnabled = "terms_flow_enabled"; + private const string KeyTermsFlowTermsOfService = "terms_flow_terms_of_service"; + private const string KeyTermsFlowPrivacyPolicy = "terms_flow_privacy_policy"; + + private const string KeySdkKey = "sdk_key"; + private const string KeyConsentFlowSettings = "consent_flow_settings"; + private const string KeyConsentFlowEnabled = "consent_flow_enabled"; + private const string KeyConsentFlowTermsOfService = "consent_flow_terms_of_service"; + private const string KeyConsentFlowPrivacyPolicy = "consent_flow_privacy_policy"; + private const string KeyConsentFlowDebugUserGeography = "consent_flow_debug_user_geography"; + + private const string KeyRenderOutsideSafeArea = "render_outside_safe_area"; + +#if UNITY_2022_3_OR_NEWER + // To match "'com.android.library' version '7.3.1'" line in build.gradle + private static readonly Regex TokenGradleVersionLibrary = new Regex(".*id ['\"]com\\.android\\.library['\"] version"); + private static readonly Regex TokenGradleVersion = new Regex(".*id ['\"]com\\.android\\.application['\"] version"); +#else + // To match "classpath 'com.android.tools.build:gradle:4.0.1'" line in build.gradle + private static readonly Regex TokenGradleVersion = new Regex(".*classpath ['\"]com\\.android\\.tools\\.build:gradle:.*"); +#endif + + // To match "distributionUrl=..." in gradle-wrapper.properties file + private static readonly Regex TokenDistributionUrl = new Regex(".*distributionUrl.*"); + + private static readonly XNamespace AndroidNamespace = "http://schemas.android.com/apk/res/android"; + + private static string PluginMediationDirectory + { + get + { + var pluginParentDir = AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; + return Path.Combine(pluginParentDir, "MaxSdk/Mediation/"); + } + } + + public void OnPostGenerateGradleAndroidProject(string path) + { +#if UNITY_2019_3_OR_NEWER + var rootGradleBuildFilePath = Path.Combine(path, "../build.gradle"); + var gradlePropertiesPath = Path.Combine(path, "../gradle.properties"); + var gradleWrapperPropertiesPath = Path.Combine(path, "../gradle/wrapper/gradle-wrapper.properties"); +#else + var rootGradleBuildFilePath = Path.Combine(path, "build.gradle"); + var gradlePropertiesPath = Path.Combine(path, "gradle.properties"); + var gradleWrapperPropertiesPath = Path.Combine(path, "gradle/wrapper/gradle-wrapper.properties"); +#endif + + UpdateGradleVersionsIfNeeded(gradleWrapperPropertiesPath, rootGradleBuildFilePath); + + var gradlePropertiesUpdated = new List(); + + // If the gradle properties file already exists, make sure to add any previous properties. + if (File.Exists(gradlePropertiesPath)) + { + var lines = File.ReadAllLines(gradlePropertiesPath); + +#if UNITY_2019_3_OR_NEWER + // Add all properties except AndroidX, Jetifier, and DexingArtifactTransform since they may already exist. We will re-add them below. + gradlePropertiesUpdated.AddRange(lines.Where(line => !line.Contains(PropertyAndroidX) && !line.Contains(PropertyJetifier) && !line.Contains(PropertyDexingArtifactTransform))); +#else + // Add all properties except DexingArtifactTransform since it may already exist. We will re-add it below. + gradlePropertiesUpdated.AddRange(lines.Where(line => !line.Contains(PropertyDexingArtifactTransform))); +#endif + } + +#if UNITY_2019_3_OR_NEWER + // Enable AndroidX and Jetifier properties + gradlePropertiesUpdated.Add(PropertyAndroidX + EnableProperty); + gradlePropertiesUpdated.Add(PropertyJetifier + EnableProperty); +#endif + + // `DexingArtifactTransform` has been removed in Gradle 8+ which is the default Gradle version for Unity 6. +#if !UNITY_6000_0_OR_NEWER + // Disable dexing using artifact transform (it causes issues for ExoPlayer with Gradle plugin 3.5.0+) + gradlePropertiesUpdated.Add(PropertyDexingArtifactTransform + DisableProperty); +#endif + + try + { + File.WriteAllText(gradlePropertiesPath, string.Join("\n", gradlePropertiesUpdated.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to enable AndroidX and Jetifier. gradle.properties file write failed."); + Console.WriteLine(exception); + } + + ProcessAndroidManifest(path); + AddSdkSettings(path); + } + + public int callbackOrder + { + get { return int.MaxValue; } + } + + private static void ProcessAndroidManifest(string path) + { + var manifestPath = Path.Combine(path, "src/main/AndroidManifest.xml"); + XDocument manifest; + try + { + manifest = XDocument.Load(manifestPath); + } +#pragma warning disable 0168 + catch (IOException exception) +#pragma warning restore 0168 + { + MaxSdkLogger.UserWarning("[AppLovin MAX] AndroidManifest.xml is missing."); + return; + } + + // Get the `manifest` element. + var elementManifest = manifest.Element("manifest"); + if (elementManifest == null) + { + MaxSdkLogger.UserWarning("[AppLovin MAX] AndroidManifest.xml is invalid."); + return; + } + + var elementApplication = elementManifest.Element("application"); + if (elementApplication == null) + { + MaxSdkLogger.UserWarning("[AppLovin MAX] AndroidManifest.xml is invalid."); + return; + } + + var metaDataElements = elementApplication.Descendants().Where(element => element.Name.LocalName.Equals("meta-data")); + + EnableVerboseLoggingIfNeeded(elementApplication); + AddGoogleApplicationIdIfNeeded(elementApplication, metaDataElements); + AddGoogleOptimizationFlagsIfNeeded(elementApplication, metaDataElements); + DisableAutoInitIfNeeded(elementApplication, metaDataElements); + RemoveSdkKeyIfNeeded(metaDataElements); + + // Save the updated manifest file. + manifest.Save(manifestPath); + } + + private static void EnableVerboseLoggingIfNeeded(XElement elementApplication) + { + var enabled = EditorPrefs.GetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, false); + + var descendants = elementApplication.Descendants(); + var verboseLoggingMetaData = descendants.FirstOrDefault(descendant => descendant.FirstAttribute != null && + descendant.FirstAttribute.Name.LocalName.Equals("name") && + descendant.FirstAttribute.Value.Equals(KeyMetaDataAppLovinVerboseLoggingOn) && + descendant.LastAttribute != null && + descendant.LastAttribute.Name.LocalName.Equals("value")); + + // check if applovin.sdk.verbose_logging meta data exists. + if (verboseLoggingMetaData != null) + { + if (enabled) + { + // update applovin.sdk.verbose_logging meta data value. + verboseLoggingMetaData.LastAttribute.Value = enabled.ToString(); + } + else + { + // remove applovin.sdk.verbose_logging meta data. + verboseLoggingMetaData.Remove(); + } + } + else + { + if (enabled) + { + // add applovin.sdk.verbose_logging meta data if it does not exist. + var metaData = CreateMetaDataElement(KeyMetaDataAppLovinVerboseLoggingOn, enabled.ToString()); + elementApplication.Add(metaData); + } + } + } + + private static void AddGoogleApplicationIdIfNeeded(XElement elementApplication, IEnumerable metaDataElements) + { + if (!AppLovinIntegrationManager.IsAdapterInstalled("Google") && !AppLovinIntegrationManager.IsAdapterInstalled("GoogleAdManager")) return; + + var googleApplicationIdMetaData = GetMetaDataElement(metaDataElements, KeyMetaDataGoogleApplicationId); + var appId = AppLovinSettings.Instance.AdMobAndroidAppId; + // Log error if the App ID is not set. + if (string.IsNullOrEmpty(appId) || !appId.StartsWith("ca-app-pub-")) + { + MaxSdkLogger.UserError("Google App ID is not set. Please enter a valid app ID within the AppLovin Integration Manager window."); + return; + } + + // Check if the Google App ID meta data already exists. Update if it already exists. + if (googleApplicationIdMetaData != null) + { + googleApplicationIdMetaData.SetAttributeValue(AndroidNamespace + "value", appId); + } + // Meta data doesn't exist, add it. + else + { + elementApplication.Add(CreateMetaDataElement(KeyMetaDataGoogleApplicationId, appId)); + } + } + + private static void AddGoogleOptimizationFlagsIfNeeded(XElement elementApplication, IEnumerable metaDataElements) + { + if (!AppLovinIntegrationManager.IsAdapterInstalled("Google") && !AppLovinIntegrationManager.IsAdapterInstalled("GoogleAdManager")) return; + + var googleOptimizeInitializationMetaData = GetMetaDataElement(metaDataElements, KeyMetaDataGoogleOptimizeInitialization); + // If meta data doesn't exist, add it + if (googleOptimizeInitializationMetaData == null) + { + elementApplication.Add(CreateMetaDataElement(KeyMetaDataGoogleOptimizeInitialization, true)); + } + + var googleOptimizeAdLoadingMetaData = GetMetaDataElement(metaDataElements, KeyMetaDataGoogleOptimizeAdLoading); + // If meta data doesn't exist, add it + if (googleOptimizeAdLoadingMetaData == null) + { + elementApplication.Add(CreateMetaDataElement(KeyMetaDataGoogleOptimizeAdLoading, true)); + } + } + + private static void DisableAutoInitIfNeeded(XElement elementApplication, IEnumerable metaDataElements) + { + if (AppLovinIntegrationManager.IsAdapterInstalled("MobileFuse")) + { + var mobileFuseMetaData = GetMetaDataElement(metaDataElements, KeyMetaDataMobileFuseAutoInit); + // If MobileFuse meta data doesn't exist, add it + if (mobileFuseMetaData == null) + { + elementApplication.Add(CreateMetaDataElement(KeyMetaDataMobileFuseAutoInit, true)); + } + } + + if (AppLovinIntegrationManager.IsAdapterInstalled("MyTarget")) + { + var myTargetMetaData = GetMetaDataElement(metaDataElements, KeyMetaDataMyTargetAutoInit); + // If MyTarget meta data doesn't exist, add it + if (myTargetMetaData == null) + { + elementApplication.Add(CreateMetaDataElement(KeyMetaDataMyTargetAutoInit, 0)); + } + } + } + + private static void RemoveSdkKeyIfNeeded(IEnumerable metaDataElements) + { + var sdkKeyMetaData = GetMetaDataElement(metaDataElements, KeyMetaDataAppLovinSdkKey); + if (sdkKeyMetaData == null) return; + + sdkKeyMetaData.Remove(); + } + + private static void UpdateGradleVersionsIfNeeded(string gradleWrapperPropertiesPath, string rootGradleBuildFilePath) + { + var customGradleVersionUrl = AppLovinSettings.Instance.CustomGradleVersionUrl; + var customGradleToolsVersion = AppLovinSettings.Instance.CustomGradleToolsVersion; + + if (MaxSdkUtils.IsValidString(customGradleVersionUrl)) + { + var newDistributionUrl = string.Format("distributionUrl={0}", customGradleVersionUrl); + if (ReplaceStringInFile(gradleWrapperPropertiesPath, TokenDistributionUrl, newDistributionUrl)) + { + MaxSdkLogger.D("Distribution url set to " + newDistributionUrl); + } + else + { + MaxSdkLogger.E("Failed to set distribution URL"); + } + } + + if (MaxSdkUtils.IsValidString(customGradleToolsVersion)) + { +#if UNITY_2022_3_OR_NEWER + // Unity 2022.3+ requires Gradle Plugin version 7.1.2+. + if (MaxSdkUtils.CompareVersions(customGradleToolsVersion, "7.1.2") == MaxSdkUtils.VersionComparisonResult.Lesser) + { + MaxSdkLogger.E("Failed to set gradle plugin version. Unity 2022.3+ requires gradle plugin version 7.1.2+"); + return; + } + + var newGradleVersionLibraryLine = AppLovinProcessGradleBuildFile.GetFormattedBuildScriptLine(string.Format("id 'com.android.library' version '{0}' apply false", customGradleToolsVersion)); + if (ReplaceStringInFile(rootGradleBuildFilePath, TokenGradleVersionLibrary, newGradleVersionLibraryLine)) + { + MaxSdkLogger.D("Gradle library version set to " + newGradleVersionLibraryLine); + } + else + { + MaxSdkLogger.E("Failed to set gradle library version"); + } + + var newGradleVersionLine = AppLovinProcessGradleBuildFile.GetFormattedBuildScriptLine(string.Format("id 'com.android.application' version '{0}' apply false", customGradleToolsVersion)); +#else + var newGradleVersionLine = AppLovinProcessGradleBuildFile.GetFormattedBuildScriptLine(string.Format("classpath 'com.android.tools.build:gradle:{0}'", customGradleToolsVersion)); +#endif + if (ReplaceStringInFile(rootGradleBuildFilePath, TokenGradleVersion, newGradleVersionLine)) + { + MaxSdkLogger.D("Gradle version set to " + newGradleVersionLine); + } + else + { + MaxSdkLogger.E("Failed to set gradle plugin version"); + } + } + } + + private static void AddSdkSettings(string path) + { + var appLovinSdkSettings = new Dictionary(); + var rawResourceDirectory = Path.Combine(path, "src/main/res/raw"); + + // Add the SDK key to the SDK settings. + appLovinSdkSettings[KeySdkKey] = AppLovinSettings.Instance.SdkKey; + appLovinSdkSettings[KeyRenderOutsideSafeArea] = PlayerSettings.Android.renderOutsideSafeArea; + + // Add the Consent/Terms flow settings if needed. + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) + { + EnableConsentFlowIfNeeded(rawResourceDirectory, appLovinSdkSettings); + } + else + { + EnableTermsFlowIfNeeded(rawResourceDirectory, appLovinSdkSettings); + } + + WriteAppLovinSettings(rawResourceDirectory, appLovinSdkSettings); + } + + private static void EnableConsentFlowIfNeeded(string rawResourceDirectory, Dictionary applovinSdkSettings) + { + // Check if consent flow is enabled. No need to create the applovin_consent_flow_settings.json if consent flow is disabled. + var consentFlowEnabled = AppLovinInternalSettings.Instance.ConsentFlowEnabled; + if (!consentFlowEnabled) + { + RemoveAppLovinSettingsRawResourceFileIfNeeded(rawResourceDirectory); + return; + } + + var privacyPolicyUrl = AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl; + if (string.IsNullOrEmpty(privacyPolicyUrl)) + { + AppLovinIntegrationManager.ShowBuildFailureDialog("You cannot use the AppLovin SDK's consent flow without defining a Privacy Policy URL in the AppLovin Integration Manager."); + + // No need to update the applovin_consent_flow_settings.json here. Default consent flow state will be determined on the SDK side. + return; + } + + var consentFlowSettings = new Dictionary(); + consentFlowSettings[KeyConsentFlowEnabled] = consentFlowEnabled; + consentFlowSettings[KeyConsentFlowPrivacyPolicy] = privacyPolicyUrl; + + var termsOfServiceUrl = AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl; + if (MaxSdkUtils.IsValidString(termsOfServiceUrl)) + { + consentFlowSettings[KeyConsentFlowTermsOfService] = termsOfServiceUrl; + } + + var debugUserGeography = AppLovinInternalSettings.Instance.DebugUserGeography; + if (debugUserGeography == MaxSdkBase.ConsentFlowUserGeography.Gdpr) + { + consentFlowSettings[KeyConsentFlowDebugUserGeography] = "gdpr"; + } + + applovinSdkSettings[KeyConsentFlowSettings] = consentFlowSettings; + } + + private static void EnableTermsFlowIfNeeded(string rawResourceDirectory, Dictionary applovinSdkSettings) + { + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) return; + + // Check if terms flow is enabled for this format. No need to create the applovin_consent_flow_settings.json if consent flow is disabled. + var consentFlowEnabled = AppLovinSettings.Instance.ConsentFlowEnabled; + var consentFlowPlatform = AppLovinSettings.Instance.ConsentFlowPlatform; + if (!consentFlowEnabled || (consentFlowPlatform != Platform.All && consentFlowPlatform != Platform.Android)) + { + RemoveAppLovinSettingsRawResourceFileIfNeeded(rawResourceDirectory); + return; + } + + var privacyPolicyUrl = AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl; + if (string.IsNullOrEmpty(privacyPolicyUrl)) + { + AppLovinIntegrationManager.ShowBuildFailureDialog("You cannot use the AppLovin SDK's consent flow without defining a Privacy Policy URL in the AppLovin Integration Manager."); + + // No need to update the applovin_consent_flow_settings.json here. Default consent flow state will be determined on the SDK side. + return; + } + + var consentFlowSettings = new Dictionary(); + consentFlowSettings[KeyTermsFlowEnabled] = consentFlowEnabled; + consentFlowSettings[KeyTermsFlowPrivacyPolicy] = privacyPolicyUrl; + + var termsOfServiceUrl = AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl; + if (MaxSdkUtils.IsValidString(termsOfServiceUrl)) + { + consentFlowSettings[KeyTermsFlowTermsOfService] = termsOfServiceUrl; + } + + applovinSdkSettings[KeyTermsFlowSettings] = consentFlowSettings; + } + + private static void WriteAppLovinSettingsRawResourceFile(string applovinSdkSettingsJson, string rawResourceDirectory) + { + if (!Directory.Exists(rawResourceDirectory)) + { + Directory.CreateDirectory(rawResourceDirectory); + } + + var consentFlowSettingsFilePath = Path.Combine(rawResourceDirectory, AppLovinSettingsFileName); + try + { + File.WriteAllText(consentFlowSettingsFilePath, applovinSdkSettingsJson + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("applovin_settings.json file write failed due to: " + exception.Message); + Console.WriteLine(exception); + } + } + + /// + /// Removes the applovin_settings json file from the build if it exists. + /// + /// The raw resource directory that holds the json file + private static void RemoveAppLovinSettingsRawResourceFileIfNeeded(string rawResourceDirectory) + { + var consentFlowSettingsFilePath = Path.Combine(rawResourceDirectory, AppLovinSettingsFileName); + if (!File.Exists(consentFlowSettingsFilePath)) return; + + try + { + File.Delete(consentFlowSettingsFilePath); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Deleting applovin_settings.json failed due to: " + exception.Message); + Console.WriteLine(exception); + } + } + + private static void WriteAppLovinSettings(string rawResourceDirectory, Dictionary applovinSdkSettings) + { + var applovinSdkSettingsJson = Json.Serialize(applovinSdkSettings); + WriteAppLovinSettingsRawResourceFile(applovinSdkSettingsJson, rawResourceDirectory); + } + + /// + /// Creates and returns a meta-data element with the given name and value. + /// + private static XElement CreateMetaDataElement(string name, object value) + { + var metaData = new XElement("meta-data"); + metaData.Add(new XAttribute(AndroidNamespace + "name", name)); + metaData.Add(new XAttribute(AndroidNamespace + "value", value)); + + return metaData; + } + + /// + /// Looks through all the given meta-data elements to check if the required one exists. Returns null if it doesn't exist. + /// + private static XElement GetMetaDataElement(IEnumerable metaDataElements, string metaDataName) + { + foreach (var metaDataElement in metaDataElements) + { + var attributes = metaDataElement.Attributes(); + if (attributes.Any(attribute => attribute.Name.Namespace.Equals(AndroidNamespace) + && attribute.Name.LocalName.Equals("name") + && attribute.Value.Equals(metaDataName))) + { + return metaDataElement; + } + } + + return null; + } + + /// + /// Finds the first line that contains regexToMatch and replaces the whole line with replacement + /// + /// Path to the file you want to replace a line in + /// Regex to search for in the line you want to replace + /// String that you want as the new line + /// Returns whether the string was successfully replaced or not + private static bool ReplaceStringInFile(string path, Regex regexToMatch, string replacement) + { + if (!File.Exists(path)) return false; + + var lines = File.ReadAllLines(path); + for (var i = 0; i < lines.Length; i++) + { + if (regexToMatch.IsMatch(lines[i])) + { + lines[i] = replacement; + File.WriteAllLines(path, lines); + return true; + } + } + + return false; + } + } +} + +#endif diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs.meta new file mode 100644 index 0000000..2877140 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: c01ea79d0cb2a43c093e2fd07201df9e +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroid.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs new file mode 100644 index 0000000..e3a0d2e --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs @@ -0,0 +1,70 @@ +// +// AppLovinBuildPostProcessor.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 8/29/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_ANDROID + +using System.IO; +using UnityEditor.Android; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// Adds Quality Service plugin to the Gradle project once the project has been exported. See for more details. + /// + public class AppLovinPostProcessGradleProject : AppLovinProcessGradleBuildFile, IPostGenerateGradleAndroidProject + { + public void OnPostGenerateGradleAndroidProject(string path) + { + if (!AppLovinSettings.Instance.QualityServiceEnabled) return; + +#if UNITY_2019_3_OR_NEWER + // On Unity 2019.3+, the path returned is the path to the unityLibrary's module. + // The AppLovin Quality Service buildscript closure related lines need to be added to the root build.gradle file. + var rootGradleBuildFilePath = Path.Combine(path, "../build.gradle"); + var rootSettingsGradleFilePath = Path.Combine(path, "../settings.gradle"); + + // For 2022.2 and newer and 2021.3.41+ + var qualityServiceAdded = AddPluginToRootGradleBuildFile(rootGradleBuildFilePath); + var appLovinRepositoryAdded = AddAppLovinRepository(rootSettingsGradleFilePath); + + // For 2021.3.40 and older and 2022.0 - 2022.1.x + var buildScriptChangesAdded = AddQualityServiceBuildScriptLines(rootGradleBuildFilePath); + + var failedToAddPlugin = !buildScriptChangesAdded && !(qualityServiceAdded && appLovinRepositoryAdded); + if (failedToAddPlugin) + { + MaxSdkLogger.UserWarning("Failed to add AppLovin Quality Service plugin to the gradle project."); + return; + } + + // The plugin needs to be added to the application module (named launcher) + var applicationGradleBuildFilePath = Path.Combine(path, "../launcher/build.gradle"); +#else + // If Gradle template is enabled, we would have already updated the plugin. + if (AppLovinIntegrationManager.GradleTemplateEnabled) return; + + var applicationGradleBuildFilePath = Path.Combine(path, "build.gradle"); +#endif + + if (!File.Exists(applicationGradleBuildFilePath)) + { + MaxSdkLogger.UserWarning("Couldn't find build.gradle file. Failed to add AppLovin Quality Service plugin to the gradle project."); + return; + } + + AddAppLovinQualityServicePlugin(applicationGradleBuildFilePath); + } + + public int callbackOrder + { + get { return int.MaxValue; } + } + } +} + +#endif diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta new file mode 100644 index 0000000..c167f0c --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: f75e54e2eb78f427ca8643c97684387b +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessAndroidGradle.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs new file mode 100644 index 0000000..87ab3e7 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs @@ -0,0 +1,791 @@ +// +// MaxIntegrationManager.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 8/29/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_IOS || UNITY_IPHONE +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEditor.Callbacks; +#if UNITY_2019_3_OR_NEWER +using UnityEditor.iOS.Xcode.Extensions; +#endif +using UnityEditor.iOS.Xcode; +using UnityEngine; +using Debug = UnityEngine.Debug; +using UnityEngine.Networking; +using VersionComparisonResult = MaxSdkUtils.VersionComparisonResult; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + [Serializable] + public class SkAdNetworkData + { + [SerializeField] public string[] SkAdNetworkIds; + } + + public class AppLovinPostProcessiOS + { + private const string OutputFileName = "AppLovinQualityServiceSetup.rb"; + +#if !UNITY_2019_3_OR_NEWER + private const string UnityMainTargetName = "Unity-iPhone"; +#endif + // Use a priority of 90 to have AppLovin embed frameworks after Pods are installed (EDM finishes installing Pods at priority 60) and before Firebase Crashlytics runs their scripts (at priority 100). + private const int AppLovinEmbedFrameworksPriority = 90; + + private const string TargetUnityIphonePodfileLine = "target 'Unity-iPhone' do"; + private const string UseFrameworksPodfileLine = "use_frameworks!"; + private const string UseFrameworksDynamicPodfileLine = "use_frameworks! :linkage => :dynamic"; + private const string UseFrameworksStaticPodfileLine = "use_frameworks! :linkage => :static"; + + private const string ResourcesDirectoryName = "Resources"; + private const string AppLovinMaxResourcesDirectoryName = "AppLovinMAXResources"; + private const string AppLovinAdvertisingAttributionEndpoint = "https://postbacks-app.com"; + + private const string AppLovinSettingsPlistFileName = "AppLovin-Settings.plist"; + + private const string KeySdkKey = "SdkKey"; + + private const string AppLovinVerboseLoggingOnKey = "AppLovinVerboseLoggingOn"; + + private const string KeyConsentFlowInfo = "ConsentFlowInfo"; + private const string KeyConsentFlowEnabled = "ConsentFlowEnabled"; + private const string KeyConsentFlowTermsOfService = "ConsentFlowTermsOfService"; + private const string KeyConsentFlowPrivacyPolicy = "ConsentFlowPrivacyPolicy"; + private const string KeyConsentFlowDebugUserGeography = "ConsentFlowDebugUserGeography"; + + private const string KeyAppLovinSdkKeyToRemove = "AppLovinSdkKey"; + + private static readonly Regex PodfilePodLineRegex = new Regex("pod \'([^\']*)\'"); + + private static string PluginMediationDirectory + { + get + { + var pluginParentDir = AppLovinIntegrationManager.MediationSpecificPluginParentDirectory; + return Path.Combine(pluginParentDir, "MaxSdk/Mediation/"); + } + } + + /// + /// Adds AppLovin Quality Service to the iOS project once the project has been exported. + /// + /// 1. Downloads the Quality Service ruby script. + /// 2. Runs the script using Ruby which integrates AppLovin Quality Service to the project. + /// + [PostProcessBuild(int.MaxValue)] // We want to run Quality Service script last. + public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath) + { + if (!AppLovinSettings.Instance.QualityServiceEnabled) return; + + var sdkKey = AppLovinSettings.Instance.SdkKey; + if (string.IsNullOrEmpty(sdkKey)) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. SDK Key is empty. Please enter the AppLovin SDK Key in the Integration Manager."); + return; + } + + var outputFilePath = Path.Combine(buildPath, OutputFileName); + + // Check if Quality Service is already installed. + if (File.Exists(outputFilePath) && Directory.Exists(Path.Combine(buildPath, "AppLovinQualityService"))) + { + // TODO: Check if there is a way to validate if the SDK key matches the script. Else the pub can't use append when/if they change the SDK Key. + return; + } + + // Download the ruby script needed to install Quality Service + var downloadHandler = new DownloadHandlerFile(outputFilePath); + var postJson = string.Format("{{\"sdk_key\" : \"{0}\"}}", sdkKey); + var bodyRaw = Encoding.UTF8.GetBytes(postJson); + var uploadHandler = new UploadHandlerRaw(bodyRaw); + uploadHandler.contentType = "application/json"; + + using (var unityWebRequest = new UnityWebRequest("https://api2.safedk.com/v1/build/ios_setup2")) + { + unityWebRequest.method = UnityWebRequest.kHttpVerbPOST; + unityWebRequest.downloadHandler = downloadHandler; + unityWebRequest.uploadHandler = uploadHandler; + var operation = unityWebRequest.SendWebRequest(); + + // Wait for the download to complete or the request to timeout. + while (!operation.isDone) { } + +#if UNITY_2020_1_OR_NEWER + if (unityWebRequest.result != UnityWebRequest.Result.Success) +#else + if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) +#endif + { + MaxSdkLogger.UserError("AppLovin Quality Service installation failed. Failed to download script with error: " + unityWebRequest.error); + return; + } + + // Check if Ruby is installed + var rubyVersion = AppLovinCommandLine.Run("ruby", "--version", buildPath); + if (rubyVersion.ExitCode != 0) + { + MaxSdkLogger.UserError("AppLovin Quality Service installation requires Ruby. Please install Ruby, export it to your system PATH and re-export the project."); + return; + } + + // Ruby is installed, run `ruby AppLovinQualityServiceSetup.rb` + var result = AppLovinCommandLine.Run("ruby", OutputFileName, buildPath); + + // Check if we have an error. + if (result.ExitCode != 0) MaxSdkLogger.UserError("Failed to set up AppLovin Quality Service"); + + MaxSdkLogger.UserDebug(result.Message); + } + } + + [PostProcessBuild(AppLovinEmbedFrameworksPriority)] + public static void MaxPostProcessPbxProject(BuildTarget buildTarget, string buildPath) + { + var projectPath = PBXProject.GetPBXProjectPath(buildPath); + var project = new PBXProject(); + project.ReadFromFile(projectPath); + +#if UNITY_2019_3_OR_NEWER + var unityMainTargetGuid = project.GetUnityMainTargetGuid(); + var unityFrameworkTargetGuid = project.GetUnityFrameworkTargetGuid(); +#else + var unityMainTargetGuid = project.TargetGuidByName(UnityMainTargetName); + var unityFrameworkTargetGuid = project.TargetGuidByName(UnityMainTargetName); +#endif + EmbedDynamicLibrariesIfNeeded(buildPath, project, unityMainTargetGuid); + + var internalSettingsEnabled = AppLovinInternalSettings.Instance.ConsentFlowEnabled; + var userTrackingUsageDescriptionDe = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe : AppLovinSettings.Instance.UserTrackingUsageDescriptionDe; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionDe, "de", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionEn = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn : AppLovinSettings.Instance.UserTrackingUsageDescriptionEn; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionEn, "en", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionEs = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs : AppLovinSettings.Instance.UserTrackingUsageDescriptionEs; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionEs, "es", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionFr = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr : AppLovinSettings.Instance.UserTrackingUsageDescriptionFr; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionFr, "fr", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionJa = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa : AppLovinSettings.Instance.UserTrackingUsageDescriptionJa; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionJa, "ja", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionKo = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo : AppLovinSettings.Instance.UserTrackingUsageDescriptionKo; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionKo, "ko", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionZhHans = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans : AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHans; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionZhHans, "zh-Hans", buildPath, project, unityMainTargetGuid); + var userTrackingUsageDescriptionZhHant = internalSettingsEnabled ? AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant : AppLovinSettings.Instance.UserTrackingUsageDescriptionZhHant; + LocalizeUserTrackingDescriptionIfNeeded(userTrackingUsageDescriptionZhHant, "zh-Hant", buildPath, project, unityMainTargetGuid); + + AddSwiftSupport(buildPath, project, unityFrameworkTargetGuid, unityMainTargetGuid); + AddYandexSettingsIfNeeded(project, unityMainTargetGuid); + + project.WriteToFile(projectPath); + } + + private static void EmbedDynamicLibrariesIfNeeded(string buildPath, PBXProject project, string targetGuid) + { + // Check that the Pods directory exists (it might not if a publisher is building with Generate Podfile setting disabled in EDM). + var podsDirectory = Path.Combine(buildPath, "Pods"); + if (!Directory.Exists(podsDirectory) || !ShouldEmbedDynamicLibraries(buildPath)) return; + + var dynamicLibraryPathsToEmbed = GetDynamicLibraryPathsToEmbed(podsDirectory, buildPath); + if (dynamicLibraryPathsToEmbed == null || dynamicLibraryPathsToEmbed.Count == 0) return; + +#if UNITY_2019_3_OR_NEWER + foreach (var dynamicLibraryPath in dynamicLibraryPathsToEmbed) + { + var fileGuid = project.AddFile(dynamicLibraryPath, dynamicLibraryPath); + project.AddFileToEmbedFrameworks(targetGuid, fileGuid); + } +#else + string runpathSearchPaths; + runpathSearchPaths = project.GetBuildPropertyForAnyConfig(targetGuid, "LD_RUNPATH_SEARCH_PATHS"); + runpathSearchPaths += string.IsNullOrEmpty(runpathSearchPaths) ? "" : " "; + + // Check if runtime search paths already contains the required search paths for dynamic libraries. + if (runpathSearchPaths.Contains("@executable_path/Frameworks")) return; + + runpathSearchPaths += "@executable_path/Frameworks"; + project.SetBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", runpathSearchPaths); +#endif + } + + /// + /// |-----------------------------------------------------------------------------------------------------------------------------------------------------| + /// | embed | use_frameworks! (:linkage => :dynamic) | use_frameworks! :linkage => :static | `use_frameworks!` line not present | + /// |---------------------------|------------------------------------------|---------------------------------------|--------------------------------------| + /// | Unity-iPhone present | Do not embed dynamic libraries | Embed dynamic libraries | Do not embed dynamic libraries | + /// | Unity-iPhone not present | Embed dynamic libraries | Embed dynamic libraries | Embed dynamic libraries | + /// |-----------------------------------------------------------------------------------------------------------------------------------------------------| + /// + /// An iOS build path + /// Whether or not the dynamic libraries should be embedded. + private static bool ShouldEmbedDynamicLibraries(string buildPath) + { + var podfilePath = Path.Combine(buildPath, "Podfile"); + if (!File.Exists(podfilePath)) return false; + + // If the Podfile doesn't have a `Unity-iPhone` target, we should embed the dynamic libraries. + var lines = File.ReadAllLines(podfilePath); + var containsUnityIphoneTarget = lines.Any(line => line.Contains(TargetUnityIphonePodfileLine)); + if (!containsUnityIphoneTarget) return true; + + // If the Podfile does not have a `use_frameworks! :linkage => static` line, we should not embed the dynamic libraries. + var useFrameworksStaticLineIndex = Array.FindIndex(lines, line => line.Contains(UseFrameworksStaticPodfileLine)); + if (useFrameworksStaticLineIndex == -1) return false; + + // If more than one of the `use_frameworks!` lines are present, CocoaPods will use the last one. + var useFrameworksLineIndex = Array.FindIndex(lines, line => line.Trim() == UseFrameworksPodfileLine); // Check for exact line to avoid matching `use_frameworks! :linkage => static/dynamic` + var useFrameworksDynamicLineIndex = Array.FindIndex(lines, line => line.Contains(UseFrameworksDynamicPodfileLine)); + + // Check if `use_frameworks! :linkage => :static` is the last line of the three. If it is, we should embed the dynamic libraries. + return useFrameworksLineIndex < useFrameworksStaticLineIndex && useFrameworksDynamicLineIndex < useFrameworksStaticLineIndex; + } + + private static List GetDynamicLibraryPathsToEmbed(string podsDirectory, string buildPath) + { + var podfilePath = Path.Combine(buildPath, "Podfile"); + var dynamicLibraryFrameworksToEmbed = GetDynamicLibraryFrameworksToEmbed(podfilePath); + + return GetDynamicLibraryPathsInProjectToEmbed(podsDirectory, dynamicLibraryFrameworksToEmbed); + } + + private static List GetDynamicLibraryFrameworksToEmbed(string podfilePath) + { + var dynamicLibrariesToEmbed = GetDynamicLibrariesToEmbed(); + + var podsInUnityIphoneTarget = GetPodNamesInUnityIphoneTarget(podfilePath); + var dynamicLibrariesToIgnore = dynamicLibrariesToEmbed.Where(dynamicLibraryToEmbed => podsInUnityIphoneTarget.Contains(dynamicLibraryToEmbed.PodName)).ToList(); + + // Determine frameworks to embed based on the dynamic libraries to embed and ignore + var dynamicLibraryFrameworksToIgnore = dynamicLibrariesToIgnore.SelectMany(library => library.FrameworkNames).Distinct().ToList(); + return dynamicLibrariesToEmbed.SelectMany(library => library.FrameworkNames).Except(dynamicLibraryFrameworksToIgnore).Distinct().ToList(); + } + + private static List GetDynamicLibrariesToEmbed() + { + var pluginData = AppLovinIntegrationManager.LoadPluginDataSync(); + if (pluginData == null) + { + MaxSdkLogger.E("Failed to load plugin data. Dynamic libraries will not be embedded."); + return null; + } + + // Get the dynamic libraries to embed for each network + var librariesToAdd = pluginData.MediatedNetworks + .Where(network => network.DynamicLibrariesToEmbed != null) + .SelectMany(network => network.DynamicLibrariesToEmbed + .Where(libraryToEmbed => IsRequiredNetworkVersionInstalled(libraryToEmbed, network))) + .ToList(); + + // Get the dynamic libraries to embed for AppLovin MAX + if (pluginData.AppLovinMax.DynamicLibrariesToEmbed != null) + { + librariesToAdd.AddRange(pluginData.AppLovinMax.DynamicLibrariesToEmbed); + } + + // Get the dynamic libraries to embed for third parties + if (pluginData.ThirdPartyDynamicLibrariesToEmbed != null) + { + // TODO: Add version check for third party dynamic libraries. + librariesToAdd.AddRange(pluginData.ThirdPartyDynamicLibrariesToEmbed); + } + + return librariesToAdd; + } + + private static List GetPodNamesInUnityIphoneTarget(string podfilePath) + { + var lines = File.ReadAllLines(podfilePath); + var podNamesInUnityIphone = new List(); + + var insideUnityIphoneTarget = false; + foreach (var line in lines) + { + // Loop until we find the `target 'Unity-iPhone'` line + if (insideUnityIphoneTarget) + { + if (line.Trim() == "end") break; + + if (PodfilePodLineRegex.IsMatch(line)) + { + var podName = PodfilePodLineRegex.Match(line).Groups[1].Value; + podNamesInUnityIphone.Add(podName); + } + } + else if (line.Contains(TargetUnityIphonePodfileLine)) + { + insideUnityIphoneTarget = true; + } + } + + return podNamesInUnityIphone; + } + + private static bool IsRequiredNetworkVersionInstalled(DynamicLibraryToEmbed libraryToEmbed, Network network) + { + var currentIosVersion = network.CurrentVersions.Ios; + if (string.IsNullOrEmpty(currentIosVersion)) return false; + + var minIosVersion = libraryToEmbed.MinVersion; + var maxIosVersion = libraryToEmbed.MaxVersion; + + var greaterThanOrEqualToMinVersion = string.IsNullOrEmpty(minIosVersion) || MaxSdkUtils.CompareVersions(currentIosVersion, minIosVersion) != VersionComparisonResult.Lesser; + var lessThanOrEqualToMaxVersion = string.IsNullOrEmpty(maxIosVersion) || MaxSdkUtils.CompareVersions(currentIosVersion, maxIosVersion) != VersionComparisonResult.Greater; + + return greaterThanOrEqualToMinVersion && lessThanOrEqualToMaxVersion; + } + + private static List GetDynamicLibraryPathsInProjectToEmbed(string podsDirectory, List dynamicLibrariesToEmbed) + { + var dynamicLibraryPathsPresentInProject = new List(); + foreach (var dynamicLibraryToSearch in dynamicLibrariesToEmbed) + { + // both .framework and .xcframework are directories, not files + var directories = Directory.GetDirectories(podsDirectory, dynamicLibraryToSearch, SearchOption.AllDirectories); + if (directories.Length <= 0) continue; + + var dynamicLibraryAbsolutePath = directories[0]; + var relativePath = GetDynamicLibraryRelativePath(dynamicLibraryAbsolutePath); + dynamicLibraryPathsPresentInProject.Add(relativePath); + } + + return dynamicLibraryPathsPresentInProject; + } + + private static string GetDynamicLibraryRelativePath(string dynamicLibraryAbsolutePath) + { + var index = dynamicLibraryAbsolutePath.LastIndexOf("Pods", StringComparison.Ordinal); + return dynamicLibraryAbsolutePath.Substring(index); + } + + private static void LocalizeUserTrackingDescriptionIfNeeded(string localizedUserTrackingDescription, string localeCode, string buildPath, PBXProject project, string targetGuid) + { + var resourcesDirectoryPath = Path.Combine(buildPath, AppLovinMaxResourcesDirectoryName); + var localeSpecificDirectoryName = localeCode + ".lproj"; + var localeSpecificDirectoryPath = Path.Combine(resourcesDirectoryPath, localeSpecificDirectoryName); + var infoPlistStringsFilePath = Path.Combine(localeSpecificDirectoryPath, "InfoPlist.strings"); + + // Check if localization has been disabled between builds, and remove them as needed. + if (ShouldRemoveLocalization(localizedUserTrackingDescription)) + { + if (!File.Exists(infoPlistStringsFilePath)) return; + + File.Delete(infoPlistStringsFilePath); + return; + } + + // Log an error if we detect a localization file for this language in the `Resources` directory + var legacyResourcedDirectoryPath = Path.Combine(buildPath, ResourcesDirectoryName); + var localeSpecificLegacyDirectoryPath = Path.Combine(legacyResourcedDirectoryPath, localeSpecificDirectoryName); + if (Directory.Exists(localeSpecificLegacyDirectoryPath)) + { + MaxSdkLogger.UserError("Detected existing localization resource for \"" + localeCode + "\" locale. Skipping localization for User Tracking Usage Description. Please disable localization in AppLovin Integration manager and add the localizations to your existing resource."); + return; + } + + // Create intermediate directories as needed. + if (!Directory.Exists(resourcesDirectoryPath)) + { + Directory.CreateDirectory(resourcesDirectoryPath); + } + + if (!Directory.Exists(localeSpecificDirectoryPath)) + { + Directory.CreateDirectory(localeSpecificDirectoryPath); + } + + var localizedDescriptionLine = "\"NSUserTrackingUsageDescription\" = \"" + localizedUserTrackingDescription + "\";\n"; + // File already exists, update it in case the value changed between builds. + if (File.Exists(infoPlistStringsFilePath)) + { + var output = new List(); + var lines = File.ReadAllLines(infoPlistStringsFilePath); + var keyUpdated = false; + foreach (var line in lines) + { + if (line.Contains("NSUserTrackingUsageDescription")) + { + output.Add(localizedDescriptionLine); + keyUpdated = true; + } + else + { + output.Add(line); + } + } + + if (!keyUpdated) + { + output.Add(localizedDescriptionLine); + } + + File.WriteAllText(infoPlistStringsFilePath, string.Join("\n", output.ToArray()) + "\n"); + } + // File doesn't exist, create one. + else + { + File.WriteAllText(infoPlistStringsFilePath, "/* Localized versions of Info.plist keys - Generated by AL MAX plugin */\n" + localizedDescriptionLine); + } + + var localeSpecificDirectoryRelativePath = Path.Combine(AppLovinMaxResourcesDirectoryName, localeSpecificDirectoryName); + var guid = project.AddFolderReference(localeSpecificDirectoryRelativePath, localeSpecificDirectoryRelativePath); + project.AddFileToBuild(targetGuid, guid); + } + + private static bool ShouldRemoveLocalization(string localizedUserTrackingDescription) + { + if (string.IsNullOrEmpty(localizedUserTrackingDescription)) return true; + + var settings = AppLovinSettings.Instance; + var internalSettings = AppLovinInternalSettings.Instance; + + return (!internalSettings.ConsentFlowEnabled || !internalSettings.UserTrackingUsageLocalizationEnabled) + && (!settings.ConsentFlowEnabled || !settings.UserTrackingUsageLocalizationEnabled); + } + + private static void AddSwiftSupport(string buildPath, PBXProject project, string unityFrameworkTargetGuid, string unityMainTargetGuid) + { + var swiftFileRelativePath = "Classes/MAXSwiftSupport.swift"; + var swiftFilePath = Path.Combine(buildPath, swiftFileRelativePath); + + // Add Swift file + CreateSwiftFile(swiftFilePath); + var swiftFileGuid = project.AddFile(swiftFileRelativePath, swiftFileRelativePath); + project.AddFileToBuild(unityFrameworkTargetGuid, swiftFileGuid); + + // Add Swift version property if needed + var swiftVersion = project.GetBuildPropertyForAnyConfig(unityFrameworkTargetGuid, "SWIFT_VERSION"); + if (string.IsNullOrEmpty(swiftVersion)) + { + project.SetBuildProperty(unityFrameworkTargetGuid, "SWIFT_VERSION", "5.0"); + } + + // Enable Swift modules + project.AddBuildProperty(unityFrameworkTargetGuid, "CLANG_ENABLE_MODULES", "YES"); + project.AddBuildProperty(unityMainTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES"); + } + + private static void CreateSwiftFile(string swiftFilePath) + { + if (File.Exists(swiftFilePath)) return; + + // Create a file to write to. + using (var writer = File.CreateText(swiftFilePath)) + { + writer.WriteLine("//\n// MAXSwiftSupport.swift\n//"); + writer.WriteLine("\nimport Foundation\n"); + writer.WriteLine("// This file ensures the project includes Swift support."); + writer.WriteLine("// It is automatically generated by the MAX Unity Plugin."); + writer.Close(); + } + } + + [PostProcessBuild(int.MaxValue)] + public static void MaxPostProcessPlist(BuildTarget buildTarget, string path) + { + var plistPath = Path.Combine(path, "Info.plist"); + var plist = new PlistDocument(); + plist.ReadFromFile(plistPath); + + SetAttributionReportEndpointIfNeeded(plist); + + EnableVerboseLoggingIfNeeded(plist); + AddGoogleApplicationIdIfNeeded(plist); + + AddSdkSettings(plist, path); + EnableTermsFlowIfNeeded(plist); + AddSkAdNetworksInfoIfNeeded(plist); + RemoveSdkKeyIfNeeded(plist); + + plist.WriteToFile(plistPath); + } + + private static void SetAttributionReportEndpointIfNeeded(PlistDocument plist) + { + if (AppLovinSettings.Instance.SetAttributionReportEndpoint) + { + plist.root.SetString("NSAdvertisingAttributionReportEndpoint", AppLovinAdvertisingAttributionEndpoint); + } + else + { + PlistElement attributionReportEndPoint; + plist.root.values.TryGetValue("NSAdvertisingAttributionReportEndpoint", out attributionReportEndPoint); + + // Check if we had previously set the attribution endpoint and un-set it. + if (attributionReportEndPoint != null && AppLovinAdvertisingAttributionEndpoint.Equals(attributionReportEndPoint.AsString())) + { + plist.root.values.Remove("NSAdvertisingAttributionReportEndpoint"); + } + } + } + + private static void EnableVerboseLoggingIfNeeded(PlistDocument plist) + { + if (!EditorPrefs.HasKey(MaxSdkLogger.KeyVerboseLoggingEnabled)) return; + + var enabled = EditorPrefs.GetBool(MaxSdkLogger.KeyVerboseLoggingEnabled); + if (enabled) + { + plist.root.SetBoolean(AppLovinVerboseLoggingOnKey, true); + } + else + { + plist.root.values.Remove(AppLovinVerboseLoggingOnKey); + } + } + + private static void AddGoogleApplicationIdIfNeeded(PlistDocument plist) + { + if (!AppLovinIntegrationManager.IsAdapterInstalled("Google") && !AppLovinIntegrationManager.IsAdapterInstalled("GoogleAdManager")) return; + + const string googleApplicationIdentifier = "GADApplicationIdentifier"; + var appId = AppLovinSettings.Instance.AdMobIosAppId; + // Log error if the App ID is not set. + if (string.IsNullOrEmpty(appId) || !appId.StartsWith("ca-app-pub-")) + { + MaxSdkLogger.UserError("[AppLovin MAX] Google App ID is not set. Please enter a valid app ID within the AppLovin Integration Manager window."); + return; + } + + plist.root.SetString(googleApplicationIdentifier, appId); + } + + private static void AddYandexSettingsIfNeeded(PBXProject project, string unityMainTargetGuid) + { + if (!AppLovinIntegrationManager.IsAdapterInstalled("Yandex")) return; + + if (MaxSdkUtils.CompareVersions(PlayerSettings.iOS.targetOSVersionString, "12.0") == MaxSdkUtils.VersionComparisonResult.Lesser) + { + MaxSdkLogger.UserWarning("Your iOS target version is under the minimum required version by Yandex. Please update it to 12.0 or newer in your ProjectSettings and rebuild your project."); + return; + } + + project.SetBuildProperty(unityMainTargetGuid, "GENERATE_INFOPLIST_FILE", "NO"); + } + + private static void AddSdkSettings(PlistDocument infoPlist, string buildPath) + { + var sdkSettingsPlistPath = Path.Combine(buildPath, AppLovinSettingsPlistFileName); + var sdkSettingsPlist = new PlistDocument(); + if (File.Exists(sdkSettingsPlistPath)) + { + sdkSettingsPlist.ReadFromFile(sdkSettingsPlistPath); + } + + // Add the SDK key to the SDK settings plist. + sdkSettingsPlist.root.SetString(KeySdkKey, AppLovinSettings.Instance.SdkKey); + + // Add consent flow settings if needed. + EnableConsentFlowIfNeeded(sdkSettingsPlist, infoPlist); + + sdkSettingsPlist.WriteToFile(sdkSettingsPlistPath); + + var projectPath = PBXProject.GetPBXProjectPath(buildPath); + var project = new PBXProject(); + project.ReadFromFile(projectPath); + +#if UNITY_2019_3_OR_NEWER + var unityMainTargetGuid = project.GetUnityMainTargetGuid(); +#else + var unityMainTargetGuid = project.TargetGuidByName(UnityMainTargetName); +#endif + + var guid = project.AddFile(AppLovinSettingsPlistFileName, AppLovinSettingsPlistFileName, PBXSourceTree.Source); + project.AddFileToBuild(unityMainTargetGuid, guid); + project.WriteToFile(projectPath); + } + + private static void EnableConsentFlowIfNeeded(PlistDocument applovinSettingsPlist, PlistDocument infoPlist) + { + var consentFlowEnabled = AppLovinInternalSettings.Instance.ConsentFlowEnabled; + if (!consentFlowEnabled) return; + + var userTrackingUsageDescription = AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn; + var privacyPolicyUrl = AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl; + if (string.IsNullOrEmpty(userTrackingUsageDescription) || string.IsNullOrEmpty(privacyPolicyUrl)) + { + AppLovinIntegrationManager.ShowBuildFailureDialog("You cannot use the AppLovin SDK's consent flow without defining a Privacy Policy URL and the `User Tracking Usage Description` in the AppLovin Integration Manager. \n\n" + + "Both values must be included to enable the SDK's consent flow."); + + // No need to update the info.plist here. Default consent flow state will be determined on the SDK side. + return; + } + + var consentFlowInfoRoot = applovinSettingsPlist.root.CreateDict(KeyConsentFlowInfo); + consentFlowInfoRoot.SetBoolean(KeyConsentFlowEnabled, consentFlowEnabled); + consentFlowInfoRoot.SetString(KeyConsentFlowPrivacyPolicy, privacyPolicyUrl); + + var termsOfServiceUrl = AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl; + if (MaxSdkUtils.IsValidString(termsOfServiceUrl)) + { + consentFlowInfoRoot.SetString(KeyConsentFlowTermsOfService, termsOfServiceUrl); + } + + var debugUserGeography = AppLovinInternalSettings.Instance.DebugUserGeography; + if (debugUserGeography == MaxSdkBase.ConsentFlowUserGeography.Gdpr) + { + consentFlowInfoRoot.SetString(KeyConsentFlowDebugUserGeography, "gdpr"); + } + + infoPlist.root.SetString("NSUserTrackingUsageDescription", userTrackingUsageDescription); + } + + private static void EnableTermsFlowIfNeeded(PlistDocument plist) + { + // Check if terms flow is enabled. No need to update info.plist if consent flow is disabled. + var consentFlowEnabled = AppLovinSettings.Instance.ConsentFlowEnabled; + if (!consentFlowEnabled) return; + + // Check if terms flow is enabled for this format. + var consentFlowPlatform = AppLovinSettings.Instance.ConsentFlowPlatform; + if (consentFlowPlatform != Platform.All && consentFlowPlatform != Platform.iOS) return; + + var userTrackingUsageDescription = AppLovinSettings.Instance.UserTrackingUsageDescriptionEn; + var privacyPolicyUrl = AppLovinSettings.Instance.ConsentFlowPrivacyPolicyUrl; + if (string.IsNullOrEmpty(userTrackingUsageDescription) || string.IsNullOrEmpty(privacyPolicyUrl)) + { + AppLovinIntegrationManager.ShowBuildFailureDialog("You cannot use the AppLovin SDK's consent flow without defining a Privacy Policy URL and the `User Tracking Usage Description` in the AppLovin Integration Manager. \n\n" + + "Both values must be included to enable the SDK's consent flow."); + + // No need to update the info.plist here. Default consent flow state will be determined on the SDK side. + return; + } + + var consentFlowInfoRoot = plist.root.CreateDict("AppLovinConsentFlowInfo"); + consentFlowInfoRoot.SetBoolean("AppLovinConsentFlowEnabled", true); + consentFlowInfoRoot.SetString("AppLovinConsentFlowPrivacyPolicy", privacyPolicyUrl); + + var termsOfServiceUrl = AppLovinSettings.Instance.ConsentFlowTermsOfServiceUrl; + if (!string.IsNullOrEmpty(termsOfServiceUrl)) + { + consentFlowInfoRoot.SetString("AppLovinConsentFlowTermsOfService", termsOfServiceUrl); + } + + plist.root.SetString("NSUserTrackingUsageDescription", userTrackingUsageDescription); + } + + private static void AddSkAdNetworksInfoIfNeeded(PlistDocument plist) + { + var skAdNetworkData = GetSkAdNetworkData(); + var skAdNetworkIds = skAdNetworkData.SkAdNetworkIds; + // Check if we have a valid list of SKAdNetworkIds that need to be added. + if (skAdNetworkIds == null || skAdNetworkIds.Length < 1) return; + + // + // Add the SKAdNetworkItems to the plist. It should look like following: + // + // SKAdNetworkItems + // + // + // SKAdNetworkIdentifier + // ABC123XYZ.skadnetwork + // + // + // SKAdNetworkIdentifier + // 123QWE456.skadnetwork + // + // + // SKAdNetworkIdentifier + // 987XYZ123.skadnetwork + // + // + // + PlistElement skAdNetworkItems; + plist.root.values.TryGetValue("SKAdNetworkItems", out skAdNetworkItems); + var existingSkAdNetworkIds = new HashSet(); + // Check if SKAdNetworkItems array is already in the Plist document and collect all the IDs that are already present. + if (skAdNetworkItems != null && skAdNetworkItems.GetType() == typeof(PlistElementArray)) + { + var plistElementDictionaries = skAdNetworkItems.AsArray().values.Where(plistElement => plistElement.GetType() == typeof(PlistElementDict)); + foreach (var plistElement in plistElementDictionaries) + { + PlistElement existingId; + plistElement.AsDict().values.TryGetValue("SKAdNetworkIdentifier", out existingId); + if (existingId == null || existingId.GetType() != typeof(PlistElementString) || string.IsNullOrEmpty(existingId.AsString())) continue; + + existingSkAdNetworkIds.Add(existingId.AsString()); + } + } + // Else, create an array of SKAdNetworkItems into which we will add our IDs. + else + { + skAdNetworkItems = plist.root.CreateArray("SKAdNetworkItems"); + } + + foreach (var skAdNetworkId in skAdNetworkIds) + { + // Skip adding IDs that are already in the array. + if (existingSkAdNetworkIds.Contains(skAdNetworkId)) continue; + + var skAdNetworkItemDict = skAdNetworkItems.AsArray().AddDict(); + skAdNetworkItemDict.SetString("SKAdNetworkIdentifier", skAdNetworkId); + } + } + + private static SkAdNetworkData GetSkAdNetworkData() + { + var uriBuilder = new UriBuilder("https://unity.applovin.com/max/1.0/skadnetwork_ids"); + + // Get the list of installed ad networks to be passed up + var maxMediationDirectory = PluginMediationDirectory; + if (Directory.Exists(maxMediationDirectory)) + { + var mediationNetworkDirectories = Directory.GetDirectories(maxMediationDirectory); + var installedNetworks = mediationNetworkDirectories.Select(Path.GetFileName).ToList(); + if (AppLovinSettings.Instance.AddApsSkAdNetworkIds) + { + installedNetworks.Add("AmazonAdMarketplace"); + } + + var adNetworks = string.Join(",", installedNetworks.ToArray()); + if (!string.IsNullOrEmpty(adNetworks)) + { + uriBuilder.Query += string.Format("ad_networks={0}", adNetworks); + } + } + + using (var unityWebRequest = UnityWebRequest.Get(uriBuilder.ToString())) + { + var operation = unityWebRequest.SendWebRequest(); + // Wait for the download to complete or the request to timeout. + while (!operation.isDone) { } + +#if UNITY_2020_1_OR_NEWER + if (unityWebRequest.result != UnityWebRequest.Result.Success) +#else + if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) +#endif + { + MaxSdkLogger.UserError("Failed to retrieve SKAdNetwork IDs with error: " + unityWebRequest.error); + return new SkAdNetworkData(); + } + + try + { + return JsonUtility.FromJson(unityWebRequest.downloadHandler.text); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to parse data '" + unityWebRequest.downloadHandler.text + "' with exception: " + exception); + return new SkAdNetworkData(); + } + } + } + + private static void RemoveSdkKeyIfNeeded(PlistDocument plist) + { + if (!plist.root.values.ContainsKey(KeyAppLovinSdkKeyToRemove)) return; + + plist.root.values.Remove(KeyAppLovinSdkKeyToRemove); + } + } +} + +#endif diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta new file mode 100644 index 0000000..8182708 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: d5d209f90444f4a90830b48b5f3f3ff4 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPostProcessiOS.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs new file mode 100644 index 0000000..3f6e2b8 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs @@ -0,0 +1,105 @@ +// +// AppLovinPreProcess.cs +// AppLovin MAX Unity Plugin +// +// Created by Jonathan Liu on 10/19/2023. +// Copyright © 2023 AppLovin. All rights reserved. +// + +using System; +using System.Linq; +using System.Xml; +using System.Xml.Linq; +using UnityEngine; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public abstract class AppLovinPreProcess + { + private const string AppLovinDependenciesFileExportPath = "MaxSdk/AppLovin/Editor/Dependencies.xml"; + + private static readonly XmlWriterSettings DependenciesFileXmlWriterSettings = new XmlWriterSettings + { + Indent = true, + IndentChars = " ", + NewLineChars = "\n", + NewLineHandling = NewLineHandling.Replace + }; + + /// + /// Adds a string into AppLovin's Dependencies.xml file inside the containerElementString if it doesn't exist + /// + /// The line you want to add into the xml file + /// The root XML element under which to add the line. For example, to add a new dependency to Android, pass in "androidPackages" + protected static void TryAddStringToDependencyFile(string lineToAdd, string containerElementString) + { + try + { + var dependenciesFilePath = MaxSdkUtils.GetAssetPathForExportPath(AppLovinDependenciesFileExportPath); + var dependencies = XDocument.Load(dependenciesFilePath); + // Get the container where we are going to insert the line + var containerElement = dependencies.Descendants(containerElementString).FirstOrDefault(); + + if (containerElement == null) + { + MaxSdkLogger.E(containerElementString + " not found in Dependencies.xml file"); + return; + } + + var elementToAdd = XElement.Parse(lineToAdd); + + // Check if the xml file doesn't already contain the string. + if (containerElement.Elements().Any(element => XNode.DeepEquals(element, elementToAdd))) return; + + // Append the new element to the container element + containerElement.Add(elementToAdd); + + using (var xmlWriter = XmlWriter.Create(dependenciesFilePath, DependenciesFileXmlWriterSettings)) + { + dependencies.Save(xmlWriter); + } + } + catch (Exception exception) + { + MaxSdkLogger.UserWarning("Google CMP will not function. Unable to add string to dependency file due to exception: " + exception.Message); + } + } + + /// + /// Removes a string from AppLovin's Dependencies.xml file inside the containerElementString if it exists + /// + /// The line you want to remove from the xml file + /// The root XML element from which to remove the line. For example, to remove an Android dependency, pass in "androidPackages" + protected static void TryRemoveStringFromDependencyFile(string lineToRemove, string containerElementString) + { + try + { + var dependenciesFilePath = MaxSdkUtils.GetAssetPathForExportPath(AppLovinDependenciesFileExportPath); + var dependencies = XDocument.Load(dependenciesFilePath); + var containerElement = dependencies.Descendants(containerElementString).FirstOrDefault(); + + if (containerElement == null) + { + MaxSdkLogger.E(containerElementString + " not found in Dependencies.xml file"); + return; + } + + // Check if the dependency line exists. + var elementToFind = XElement.Parse(lineToRemove); + var existingElement = containerElement.Elements().FirstOrDefault(element => XNode.DeepEquals(element, elementToFind)); + if (existingElement == null) return; + + existingElement.Remove(); + + using (var xmlWriter = XmlWriter.Create(dependenciesFilePath, DependenciesFileXmlWriterSettings)) + { + dependencies.Save(xmlWriter); + } + } + catch (Exception exception) + { + MaxSdkLogger.UserWarning("Unable to remove string from dependency file due to exception: " + exception.Message); + } + } + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs.meta new file mode 100644 index 0000000..f5e00db --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 0e6254f24e89548b3a7644fa7bf25f9d +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcess.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs new file mode 100644 index 0000000..204a7ba --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs @@ -0,0 +1,67 @@ +// +// AppLovinBuildPreProcessor.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 8/27/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_ANDROID + +using UnityEditor.Build; +using UnityEditor.Build.Reporting; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + /// + /// Adds the AppLovin Quality Service plugin to the gradle template file. See for more details. + /// + public class AppLovinPreProcessAndroid : AppLovinProcessGradleBuildFile, IPreprocessBuildWithReport + { + private const string UmpLegacyDependencyLine = ""; + private const string UmpDependencyLine = ""; + private const string AndroidPackagesContainerElementString = "androidPackages"; + + public void OnPreprocessBuild(BuildReport report) + { + PreprocessAppLovinQualityServicePlugin(); + AddGoogleCmpDependencyIfNeeded(); + } + + private static void PreprocessAppLovinQualityServicePlugin() + { + // We can only process gradle template file here. If it is not available, we will try again in post build on Unity IDEs newer than 2018_2 (see AppLovinPostProcessGradleProject). + if (!AppLovinIntegrationManager.GradleTemplateEnabled) return; + +#if UNITY_2019_3_OR_NEWER + // The publisher could be migrating from older Unity versions to 2019_3 or newer. + // If so, we should delete the plugin from the template. The plugin will be added to the project's application module in the post processing script (AppLovinPostProcessGradleProject). + RemoveAppLovinQualityServiceOrSafeDkPlugin(AppLovinIntegrationManager.GradleTemplatePath); +#else + AddAppLovinQualityServicePlugin(AppLovinIntegrationManager.GradleTemplatePath); +#endif + } + + private static void AddGoogleCmpDependencyIfNeeded() + { + // Remove the legacy fixed UMP version if it exists, we'll add the dependency with a dynamic version below. + TryRemoveStringFromDependencyFile(UmpLegacyDependencyLine, AndroidPackagesContainerElementString); + + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) + { + TryAddStringToDependencyFile(UmpDependencyLine, AndroidPackagesContainerElementString); + } + else + { + TryRemoveStringFromDependencyFile(UmpDependencyLine, AndroidPackagesContainerElementString); + } + } + + public int callbackOrder + { + get { return int.MaxValue; } + } + } +} + +#endif diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta new file mode 100644 index 0000000..4dd79e8 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 8ccaf444d0d4f4cadb5debe7c41b20c4 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessAndroid.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs new file mode 100644 index 0000000..8537150 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs @@ -0,0 +1,49 @@ +// +// AppLovinBuildPreProcessiOS.cs +// AppLovin MAX Unity Plugin +// +// Created by Jonathan Liu on 10/17/2023. +// Copyright © 2023 AppLovin. All rights reserved. +// + +#if UNITY_IOS + +using UnityEditor.Build; +using UnityEditor.Build.Reporting; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public class AppLovinPreProcessiOS : AppLovinPreProcess, IPreprocessBuildWithReport + { + public void OnPreprocessBuild(BuildReport report) + { + AddGoogleCmpDependencyIfNeeded(); + } + + private const string UmpLegacyDependencyLine = ""; + private const string UmpDependencyLine = ""; + private const string IosPodsContainerElementString = "iosPods"; + + private static void AddGoogleCmpDependencyIfNeeded() + { + // Remove the legacy fixed UMP version if it exists, we'll add the dependency with a dynamic version below. + TryRemoveStringFromDependencyFile(UmpLegacyDependencyLine, IosPodsContainerElementString); + + if (AppLovinInternalSettings.Instance.ConsentFlowEnabled) + { + TryAddStringToDependencyFile(UmpDependencyLine, IosPodsContainerElementString); + } + else + { + TryRemoveStringFromDependencyFile(UmpDependencyLine, IosPodsContainerElementString); + } + } + + public int callbackOrder + { + get { return int.MaxValue; } + } + } +} + +#endif diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs.meta new file mode 100644 index 0000000..33bdffb --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: ee45537a5833240d7afcfac4a38df1b9 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinPreProcessiOS.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs new file mode 100644 index 0000000..166524c --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs @@ -0,0 +1,602 @@ +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 9/3/19. +// Copyright © 2019 AppLovin. All rights reserved. +// + +#if UNITY_ANDROID + +using System.Text; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.Networking; +using Debug = UnityEngine.Debug; + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + [Serializable] + public class AppLovinQualityServiceData + { + public string api_key; + } + + /// + /// Adds or updates the AppLovin Quality Service plugin to the provided build.gradle file. + /// If the gradle file already has the plugin, the API key is updated. + /// + public abstract class AppLovinProcessGradleBuildFile : AppLovinPreProcess + { + private static readonly Regex TokenBuildScriptRepositories = new Regex(".*repositories.*"); + private static readonly Regex TokenBuildScriptDependencies = new Regex(".*classpath \'com.android.tools.build:gradle.*"); + private static readonly Regex TokenApplicationPlugin = new Regex(".*apply plugin: \'com.android.application\'.*"); + private static readonly Regex TokenApiKey = new Regex(".*apiKey.*"); + private static readonly Regex TokenAppLovinPlugin = new Regex(".*apply plugin:.+?(?=applovin-quality-service).*"); + + private const string PluginsMatcher = "plugins"; + private const string PluginManagementMatcher = "pluginManagement"; + private const string QualityServicePluginRoot = " id 'com.applovin.quality' version '+' apply false // NOTE: Requires version 4.8.3+ for Gradle version 7.2+"; + + private const string BuildScriptMatcher = "buildscript"; + private const string QualityServiceMavenRepo = "maven { url 'https://artifacts.applovin.com/android'; content { includeGroupByRegex 'com.applovin.*' } }"; + private const string QualityServiceDependencyClassPath = "classpath 'com.applovin.quality:AppLovinQualityServiceGradlePlugin:+'"; + private const string QualityServiceApplyPlugin = "apply plugin: 'applovin-quality-service'"; + private const string QualityServicePlugin = "applovin {"; + private const string QualityServiceApiKey = " apiKey '{0}'"; + private const string QualityServiceBintrayMavenRepo = "https://applovin.bintray.com/Quality-Service"; + private const string QualityServiceNoRegexMavenRepo = "maven { url 'https://artifacts.applovin.com/android' }"; + + // Legacy plugin detection variables + private const string QualityServiceDependencyClassPathV3 = "classpath 'com.applovin.quality:AppLovinQualityServiceGradlePlugin:3.+'"; + private static readonly Regex TokenSafeDkLegacyApplyPlugin = new Regex(".*apply plugin:.+?(?=safedk).*"); + private const string SafeDkLegacyPlugin = "safedk {"; + private const string SafeDkLegacyMavenRepo = "http://download.safedk.com"; + private const string SafeDkLegacyDependencyClassPath = "com.safedk:SafeDKGradlePlugin:"; + + /// + /// Updates the provided Gradle script to add Quality Service plugin. + /// + /// The gradle file to update. + protected static void AddAppLovinQualityServicePlugin(string applicationGradleBuildFilePath) + { + if (!AppLovinSettings.Instance.QualityServiceEnabled) return; + + var sdkKey = AppLovinSettings.Instance.SdkKey; + if (string.IsNullOrEmpty(sdkKey)) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. SDK Key is empty. Please enter the AppLovin SDK Key in the Integration Manager."); + return; + } + + // Retrieve the API Key using the SDK Key. + var qualityServiceData = RetrieveQualityServiceData(sdkKey); + var apiKey = qualityServiceData.api_key; + if (string.IsNullOrEmpty(apiKey)) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. API Key is empty."); + return; + } + + // Generate the updated Gradle file that needs to be written. + var lines = File.ReadAllLines(applicationGradleBuildFilePath).ToList(); + var sanitizedLines = RemoveLegacySafeDkPlugin(lines); + var outputLines = GenerateUpdatedBuildFileLines( + sanitizedLines, + apiKey, +#if UNITY_2019_3_OR_NEWER + false // On Unity 2019.3+, the buildscript closure related lines will to be added to the root build.gradle file. +#else + true +#endif + ); + // outputLines can be null if we couldn't add the plugin. + if (outputLines == null) return; + + try + { + File.WriteAllText(applicationGradleBuildFilePath, string.Join("\n", outputLines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. Gradle file write failed."); + Console.WriteLine(exception); + } + } + + /// + /// Adds AppLovin Quality Service plugin DSL element to the project's root build.gradle file. + /// Sample build.gradle file after adding quality service: + /// plugins { + /// id 'com.android.application' version '7.4.2' apply false + /// id 'com.android.library' version '7.4.2' apply false + /// id 'com.applovin.quality' version '+' apply false + /// } + /// tasks.register('clean', Delete) { + /// delete rootProject.layout.buildDirectory + /// } + /// + /// + /// The path to project's root build.gradle file. + /// true when the plugin was added successfully. + protected bool AddPluginToRootGradleBuildFile(string rootGradleBuildFile) + { + var lines = File.ReadAllLines(rootGradleBuildFile).ToList(); + + // Check if the plugin is already added to the file. + var pluginAdded = lines.Any(line => line.Contains(QualityServicePluginRoot)); + if (pluginAdded) return true; + + var outputLines = new List(); + var insidePluginsClosure = false; + foreach (var line in lines) + { + if (line.Contains(PluginsMatcher)) + { + insidePluginsClosure = true; + } + + if (!pluginAdded && insidePluginsClosure && line.Contains("}")) + { + outputLines.Add(QualityServicePluginRoot); + pluginAdded = true; + insidePluginsClosure = false; + } + + outputLines.Add(line); + } + + if (!pluginAdded) return false; + + try + { + File.WriteAllText(rootGradleBuildFile, string.Join("\n", outputLines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. Root Gradle file write failed."); + Console.WriteLine(exception); + return false; + } + + return true; + } + + /// + /// Adds the AppLovin maven repository to the project's settings.gradle file. + /// Sample settings.gradle file after adding AppLovin Repository: + /// pluginManagement { + /// repositories { + /// maven { url 'https://artifacts.applovin.com/android'; content { includeGroupByRegex 'com.applovin.*' } } + /// + /// gradlePluginPortal() + /// google() + /// mavenCentral() + /// } + /// } + /// ... + /// + /// + /// The path to the project's settings.gradle file. + /// true if the repository was added successfully. + protected bool AddAppLovinRepository(string settingsGradleFile) + { + var lines = File.ReadLines(settingsGradleFile).ToList(); + var outputLines = new List(); + var mavenRepoAdded = false; + var pluginManagementClosureDepth = 0; + var insidePluginManagementClosure = false; + var pluginManagementMatched = false; + foreach (var line in lines) + { + outputLines.Add(line); + + if (!pluginManagementMatched && line.Contains(PluginManagementMatcher)) + { + pluginManagementMatched = true; + insidePluginManagementClosure = true; + } + + if (insidePluginManagementClosure) + { + if (line.Contains("{")) + { + pluginManagementClosureDepth++; + } + + if (line.Contains("}")) + { + pluginManagementClosureDepth--; + } + + if (pluginManagementClosureDepth == 0) + { + insidePluginManagementClosure = false; + } + } + + if (insidePluginManagementClosure) + { + if (!mavenRepoAdded && TokenBuildScriptRepositories.IsMatch(line)) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo)); + mavenRepoAdded = true; + } + } + } + + if (!mavenRepoAdded) return false; + + try + { + File.WriteAllText(settingsGradleFile, string.Join("\n", outputLines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. Setting Gradle file write failed."); + Console.WriteLine(exception); + return false; + } + + return true; + } + +#if UNITY_2019_3_OR_NEWER + /// + /// Adds the necessary AppLovin Quality Service dependency and maven repo lines to the provided root build.gradle file. + /// Sample build.gradle file after adding quality service: + /// allprojects { + /// buildscript { + /// repositories { + /// maven { url 'https://artifacts.applovin.com/android'; content { includeGroupByRegex 'com.applovin.*' } } + /// google() + /// jcenter() + /// } + /// + /// dependencies { + /// classpath 'com.android.tools.build:gradle:4.0.1' + /// classpath 'com.applovin.quality:AppLovinQualityServiceGradlePlugin:+' + /// } + /// ... + /// + /// + /// The root build.gradle file path + /// true if the build script lines were applied correctly. + protected bool AddQualityServiceBuildScriptLines(string rootGradleBuildFile) + { + var lines = File.ReadAllLines(rootGradleBuildFile).ToList(); + var outputLines = GenerateUpdatedBuildFileLines(lines, null, true); + + // outputLines will be null if we couldn't add the build script lines. + if (outputLines == null) return false; + + try + { + File.WriteAllText(rootGradleBuildFile, string.Join("\n", outputLines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to install AppLovin Quality Service plugin. Root Gradle file write failed."); + Console.WriteLine(exception); + return false; + } + + return true; + } + + /// + /// Removes the AppLovin Quality Service Plugin or Legacy SafeDK plugin from the given gradle template file if either of them are present. + /// + /// The gradle template file from which to remove the plugin from + protected static void RemoveAppLovinQualityServiceOrSafeDkPlugin(string gradleTemplateFile) + { + var lines = File.ReadAllLines(gradleTemplateFile).ToList(); + lines = RemoveLegacySafeDkPlugin(lines); + lines = RemoveAppLovinQualityServicePlugin(lines); + + try + { + File.WriteAllText(gradleTemplateFile, string.Join("\n", lines.ToArray()) + "\n"); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to remove AppLovin Quality Service Plugin from mainTemplate.gradle. Please remove the Quality Service plugin from the mainTemplate.gradle manually."); + Console.WriteLine(exception); + } + } +#endif + + private static AppLovinQualityServiceData RetrieveQualityServiceData(string sdkKey) + { + var postJson = string.Format("{{\"sdk_key\" : \"{0}\"}}", sdkKey); + var bodyRaw = Encoding.UTF8.GetBytes(postJson); + // Upload handler is automatically disposed when UnityWebRequest is disposed + var uploadHandler = new UploadHandlerRaw(bodyRaw); + uploadHandler.contentType = "application/json"; + + using (var unityWebRequest = new UnityWebRequest("https://api2.safedk.com/v1/build/cred")) + { + unityWebRequest.method = UnityWebRequest.kHttpVerbPOST; + unityWebRequest.uploadHandler = uploadHandler; + unityWebRequest.downloadHandler = new DownloadHandlerBuffer(); + + var operation = unityWebRequest.SendWebRequest(); + + // Wait for the download to complete or the request to timeout. + while (!operation.isDone) { } + +#if UNITY_2020_1_OR_NEWER + if (unityWebRequest.result != UnityWebRequest.Result.Success) +#else + if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) +#endif + { + MaxSdkLogger.UserError("Failed to retrieve API Key for SDK Key: " + sdkKey + "with error: " + unityWebRequest.error); + return new AppLovinQualityServiceData(); + } + + try + { + return JsonUtility.FromJson(unityWebRequest.downloadHandler.text); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Failed to parse API Key." + exception); + return new AppLovinQualityServiceData(); + } + } + } + + private static List RemoveLegacySafeDkPlugin(List lines) + { + return RemovePlugin(lines, SafeDkLegacyPlugin, SafeDkLegacyMavenRepo, SafeDkLegacyDependencyClassPath, TokenSafeDkLegacyApplyPlugin); + } + + private static List RemoveAppLovinQualityServicePlugin(List lines) + { + return RemovePlugin(lines, QualityServicePlugin, QualityServiceMavenRepo, QualityServiceDependencyClassPath, TokenAppLovinPlugin); + } + + private static List RemovePlugin(List lines, string pluginLine, string mavenRepo, string dependencyClassPath, Regex applyPluginToken) + { + var sanitizedLines = new List(); + var legacyRepoRemoved = false; + var legacyDependencyClassPathRemoved = false; + var legacyPluginRemoved = false; + var legacyPluginMatched = false; + var insideLegacySafeDkClosure = false; + foreach (var line in lines) + { + if (!legacyPluginMatched && line.Contains(pluginLine)) + { + legacyPluginMatched = true; + insideLegacySafeDkClosure = true; + } + + if (insideLegacySafeDkClosure && line.Contains("}")) + { + insideLegacySafeDkClosure = false; + continue; + } + + if (insideLegacySafeDkClosure) + { + continue; + } + + if (!legacyRepoRemoved && line.Contains(mavenRepo)) + { + legacyRepoRemoved = true; + continue; + } + + if (!legacyDependencyClassPathRemoved && line.Contains(dependencyClassPath)) + { + legacyDependencyClassPathRemoved = true; + continue; + } + + if (!legacyPluginRemoved && applyPluginToken.IsMatch(line)) + { + legacyPluginRemoved = true; + continue; + } + + sanitizedLines.Add(line); + } + + return sanitizedLines; + } + + private static List GenerateUpdatedBuildFileLines(List lines, string apiKey, bool addBuildScriptLines) + { + var addPlugin = !string.IsNullOrEmpty(apiKey); + // A sample of the template file. + // ... + // allprojects { + // repositories {**ARTIFACTORYREPOSITORY** + // google() + // jcenter() + // flatDir { + // dirs 'libs' + // } + // } + // } + // + // apply plugin: 'com.android.application' + // **APPLY_PLUGINS** + // + // dependencies { + // implementation fileTree(dir: 'libs', include: ['*.jar']) + // **DEPS**} + // ... + var outputLines = new List(); + // Check if the plugin exists, if so, update the SDK Key. + var pluginExists = lines.Any(line => TokenAppLovinPlugin.IsMatch(line)); + if (pluginExists) + { + var pluginMatched = false; + var insideAppLovinClosure = false; + var updatedApiKey = false; + var mavenRepoUpdated = false; + var dependencyClassPathUpdated = false; + foreach (var line in lines) + { + // Bintray maven repo is no longer being used. Update to s3 maven repo with regex check + if (!mavenRepoUpdated && (line.Contains(QualityServiceBintrayMavenRepo) || line.Contains(QualityServiceNoRegexMavenRepo))) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo)); + mavenRepoUpdated = true; + continue; + } + + // We no longer use version specific dependency class path. Just use + for version to always pull the latest. + if (!dependencyClassPathUpdated && line.Contains(QualityServiceDependencyClassPathV3)) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceDependencyClassPath)); + dependencyClassPathUpdated = true; + continue; + } + + if (!pluginMatched && line.Contains(QualityServicePlugin)) + { + insideAppLovinClosure = true; + pluginMatched = true; + } + + if (insideAppLovinClosure && line.Contains("}")) + { + insideAppLovinClosure = false; + } + + // Update the API key. + if (insideAppLovinClosure && !updatedApiKey && TokenApiKey.IsMatch(line)) + { + outputLines.Add(string.Format(QualityServiceApiKey, apiKey)); + updatedApiKey = true; + } + // Keep adding the line until we find and update the plugin. + else + { + outputLines.Add(line); + } + } + } + // Plugin hasn't been added yet, add it. + else + { + var buildScriptClosureDepth = 0; + var insideBuildScriptClosure = false; + var buildScriptMatched = false; + var qualityServiceRepositoryAdded = false; + var qualityServiceDependencyClassPathAdded = false; + var qualityServicePluginAdded = false; + foreach (var line in lines) + { + // Add the line to the output lines. + outputLines.Add(line); + + // Check if we need to add the build script lines and add them. + if (addBuildScriptLines) + { + if (!buildScriptMatched && line.Contains(BuildScriptMatcher)) + { + buildScriptMatched = true; + insideBuildScriptClosure = true; + } + + // Match the parenthesis to track if we are still inside the buildscript closure. + if (insideBuildScriptClosure) + { + if (line.Contains("{")) + { + buildScriptClosureDepth++; + } + + if (line.Contains("}")) + { + buildScriptClosureDepth--; + } + + if (buildScriptClosureDepth == 0) + { + insideBuildScriptClosure = false; + + // There may be multiple buildscript closures and we need to keep looking until we added both the repository and classpath. + buildScriptMatched = qualityServiceRepositoryAdded && qualityServiceDependencyClassPathAdded; + } + } + + if (insideBuildScriptClosure) + { + // Add the build script dependency repositories. + if (!qualityServiceRepositoryAdded && TokenBuildScriptRepositories.IsMatch(line)) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo)); + qualityServiceRepositoryAdded = true; + } + // Add the build script dependencies. + else if (!qualityServiceDependencyClassPathAdded && TokenBuildScriptDependencies.IsMatch(line)) + { + outputLines.Add(GetFormattedBuildScriptLine(QualityServiceDependencyClassPath)); + qualityServiceDependencyClassPathAdded = true; + } + } + } + + // Check if we need to add the plugin and add it. + if (addPlugin) + { + // Add the plugin. + if (!qualityServicePluginAdded && TokenApplicationPlugin.IsMatch(line)) + { + outputLines.Add(QualityServiceApplyPlugin); + outputLines.AddRange(GenerateAppLovinPluginClosure(apiKey)); + qualityServicePluginAdded = true; + } + } + } + + if ((addBuildScriptLines && (!qualityServiceRepositoryAdded || !qualityServiceDependencyClassPathAdded)) || (addPlugin && !qualityServicePluginAdded)) + { + return null; + } + } + + return outputLines; + } + + public static string GetFormattedBuildScriptLine(string buildScriptLine) + { +#if UNITY_2022_2_OR_NEWER + return " " +#elif UNITY_2019_3_OR_NEWER + return " " +#else + return " " +#endif + + buildScriptLine; + } + + private static IEnumerable GenerateAppLovinPluginClosure(string apiKey) + { + // applovin { + // // NOTE: DO NOT CHANGE - this is NOT your AppLovin MAX SDK key - this is a derived key. + // apiKey "456...a1b" + // } + var linesToInject = new List(5); + linesToInject.Add(""); + linesToInject.Add("applovin {"); + linesToInject.Add(" // NOTE: DO NOT CHANGE - this is NOT your AppLovin MAX SDK key - this is a derived key."); + linesToInject.Add(string.Format(QualityServiceApiKey, apiKey)); + linesToInject.Add("}"); + + return linesToInject; + } + } +} + +#endif diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta new file mode 100644 index 0000000..5e49844 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 732b7510bc9c94aafb3fd3b8c0dc5d2d +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinProcessGradleBuildFile.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs new file mode 100644 index 0000000..df88d8d --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs @@ -0,0 +1,425 @@ +// +// AppLovinSettings.cs +// AppLovin MAX Unity Plugin +// +// Created by Santosh Bagadi on 1/27/20. +// Copyright © 2019 AppLovin. All rights reserved. +// + +using AppLovinMax.Scripts.IntegrationManager.Editor; +using System.IO; +using UnityEditor; +using UnityEngine; +using UnityEngine.Serialization; + + +namespace AppLovinMax.Scripts.IntegrationManager.Editor +{ + public enum Platform + { + All, + Android, + iOS + } +} + +/// +/// A representing the AppLovin Settings that can be set in the Integration Manager Window. +/// +/// The scriptable object asset is created with the name AppLovinSettings.asset and is placed under the directory Assets/MaxSdk/Resources. +/// +/// NOTE: Not name spacing this class since it is reflected upon by the Google adapter and will break compatibility. +/// +public class AppLovinSettings : ScriptableObject +{ + public const string SettingsExportPath = "MaxSdk/Resources/AppLovinSettings.asset"; + + public const string DefaultUserTrackingDescriptionEnV0 = "Pressing \\\"Allow\\\" uses device info for more relevant ad content"; + public const string DefaultUserTrackingDescriptionEnV1 = "This only uses device info for less annoying, more relevant ads"; + public const string DefaultUserTrackingDescriptionEnV2 = "This only uses device info for more interesting and relevant ads"; + public const string DefaultUserTrackingDescriptionEnV3 = "This uses device info for more personalized ads and content"; + + public const string DefaultUserTrackingDescriptionDe = "\\\"Erlauben\\\" drücken benutzt Gerätinformationen für relevantere Werbeinhalte"; + public const string DefaultUserTrackingDescriptionEs = "Presionando \\\"Permitir\\\", se usa la información del dispositivo para obtener contenido publicitario más relevante"; + public const string DefaultUserTrackingDescriptionFr = "\\\"Autoriser\\\" permet d'utiliser les infos du téléphone pour afficher des contenus publicitaires plus pertinents"; + public const string DefaultUserTrackingDescriptionJa = "\\\"許可\\\"をクリックすることで、デバイス情報を元により最適な広告を表示することができます"; + public const string DefaultUserTrackingDescriptionKo = "\\\"허용\\\"을 누르면 더 관련성 높은 광고 콘텐츠를 제공하기 위해 기기 정보가 사용됩니다"; + public const string DefaultUserTrackingDescriptionZhHans = "点击\\\"允许\\\"以使用设备信息获得更加相关的广告内容"; + public const string DefaultUserTrackingDescriptionZhHant = "點擊\\\"允許\\\"以使用設備信息獲得更加相關的廣告內容"; + + /// + /// A placeholder constant to be replaced with the actual default localization or an empty string based on whether or not localization is enabled when when the getter is called. + /// + protected const string DefaultLocalization = "default_localization"; + + private static AppLovinSettings instance; + + [SerializeField] private bool qualityServiceEnabled = true; + [SerializeField] private string sdkKey; + + [SerializeField] private bool setAttributionReportEndpoint; + [SerializeField] private bool addApsSkAdNetworkIds; + + [SerializeField] private string customGradleVersionUrl; + [SerializeField] private string customGradleToolsVersion; + + [SerializeField] private bool consentFlowEnabled; + [SerializeField] private Platform consentFlowPlatform; + [SerializeField] private string consentFlowPrivacyPolicyUrl = string.Empty; + [SerializeField] private string consentFlowTermsOfServiceUrl = string.Empty; + [FormerlySerializedAs("userTrackingUsageDescription")] [SerializeField] private string userTrackingUsageDescriptionEn = string.Empty; + [SerializeField] private bool userTrackingUsageLocalizationEnabled; + [SerializeField] private string userTrackingUsageDescriptionDe = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionEs = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionFr = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionJa = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionKo = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionZhHans = string.Empty; + [SerializeField] private string userTrackingUsageDescriptionZhHant = DefaultLocalization; + + [SerializeField] private string adMobAndroidAppId = string.Empty; + [SerializeField] private string adMobIosAppId = string.Empty; + + [SerializeField] private bool showInternalSettingsInIntegrationManager; + + /// + /// An instance of AppLovin Setting. + /// + public static AppLovinSettings Instance + { + get + { + if (instance == null) + { + // Check for an existing AppLovinSettings somewhere in the project + var guids = AssetDatabase.FindAssets("AppLovinSettings t:ScriptableObject"); + if (guids.Length > 1) + { + MaxSdkLogger.UserWarning("Multiple AppLovinSettings found. This may cause unexpected results."); + } + + if (guids.Length != 0) + { + var path = AssetDatabase.GUIDToAssetPath(guids[0]); + instance = AssetDatabase.LoadAssetAtPath(path); + return instance; + } + + // If there is no existing AppLovinSettings asset, create one in the default location + string settingsFilePath; + // The settings file should be under the Assets/ folder so that it can be version controlled and cannot be overriden when updating. + // If the plugin is outside the Assets folder, create the settings asset at the default location. + if (AppLovinIntegrationManager.IsPluginOutsideAssetsDirectory) + { + // Note: Can't use absolute path when calling `CreateAsset`. Should use relative path to Assets/ directory. + settingsFilePath = Path.Combine("Assets", SettingsExportPath); + + var maxSdkDir = Path.Combine(Application.dataPath, "MaxSdk"); + if (!Directory.Exists(maxSdkDir)) + { + Directory.CreateDirectory(maxSdkDir); + } + } + else + { + settingsFilePath = Path.Combine(AppLovinIntegrationManager.PluginParentDirectory, SettingsExportPath); + } + + var settingsDir = Path.GetDirectoryName(settingsFilePath); + if (!Directory.Exists(settingsDir)) + { + Directory.CreateDirectory(settingsDir); + } + + // On script reload AssetDatabase.FindAssets() can fail and will overwrite AppLovinSettings without this check + if (!File.Exists(settingsFilePath)) + { + instance = CreateInstance(); + AssetDatabase.CreateAsset(instance, settingsFilePath); + MaxSdkLogger.D("Creating new AppLovinSettings asset at path: " + settingsFilePath); + } + } + + return instance; + } + } + + /// + /// Whether or not to install Quality Service plugin. + /// + public bool QualityServiceEnabled + { + get { return Instance.qualityServiceEnabled; } + set { Instance.qualityServiceEnabled = value; } + } + + /// + /// AppLovin SDK Key. + /// + public string SdkKey + { + get { return Instance.sdkKey; } + set { Instance.sdkKey = value; } + } + + /// + /// Whether or not to set `NSAdvertisingAttributionReportEndpoint` in Info.plist. + /// + public bool SetAttributionReportEndpoint + { + get { return Instance.setAttributionReportEndpoint; } + set { Instance.setAttributionReportEndpoint = value; } + } + + /// + /// Whether or not to add Amazon Publisher Services SKAdNetworkID's. + /// + public bool AddApsSkAdNetworkIds + { + get { return Instance.addApsSkAdNetworkIds; } + set { Instance.addApsSkAdNetworkIds = value; } + } + + /// + /// A URL to set the distributionUrl in the gradle-wrapper.properties file (ex: https\://services.gradle.org/distributions/gradle-6.9.3-bin.zip) + /// + public string CustomGradleVersionUrl + { + get { return Instance.customGradleVersionUrl; } + set { Instance.customGradleVersionUrl = value; } + } + + /// + /// A string to set the custom gradle tools version (ex: com.android.tools.build:gradle:4.2.0) + /// + public string CustomGradleToolsVersion + { + get { return Instance.customGradleToolsVersion; } + set { Instance.customGradleToolsVersion = value; } + } + + /// + /// Whether or not AppLovin Consent Flow is enabled. + /// + public bool ConsentFlowEnabled + { + get + { + // Update the default EN description if an old version of the description is still being used. + if (DefaultUserTrackingDescriptionEnV0.Equals(Instance.UserTrackingUsageDescriptionEn) + || DefaultUserTrackingDescriptionEnV1.Equals(Instance.UserTrackingUsageDescriptionEn) + || DefaultUserTrackingDescriptionEnV2.Equals(Instance.UserTrackingUsageDescriptionEn)) + { + Instance.UserTrackingUsageDescriptionEn = DefaultUserTrackingDescriptionEnV3; + } + + return Instance.consentFlowEnabled; + } + set + { + var previousValue = Instance.consentFlowEnabled; + Instance.consentFlowEnabled = value; + + if (value) + { + // If the value didn't change, we don't need to update anything. + if (previousValue) return; + + Instance.UserTrackingUsageDescriptionEn = DefaultUserTrackingDescriptionEnV3; + Instance.UserTrackingUsageLocalizationEnabled = true; + } + else + { + Instance.ConsentFlowPlatform = Platform.All; + Instance.ConsentFlowPrivacyPolicyUrl = string.Empty; + Instance.ConsentFlowTermsOfServiceUrl = string.Empty; + Instance.UserTrackingUsageDescriptionEn = string.Empty; + Instance.UserTrackingUsageLocalizationEnabled = false; + } + } + } + + public Platform ConsentFlowPlatform + { + get { return Instance.consentFlowEnabled ? Instance.consentFlowPlatform : Platform.All; } + set { Instance.consentFlowPlatform = value; } + } + + /// + /// A URL pointing to the Privacy Policy for the app to be shown when prompting the user for consent. + /// + public string ConsentFlowPrivacyPolicyUrl + { + get { return Instance.consentFlowPrivacyPolicyUrl; } + set { Instance.consentFlowPrivacyPolicyUrl = value; } + } + + /// + /// An optional URL pointing to the Terms of Service for the app to be shown when prompting the user for consent. + /// + public string ConsentFlowTermsOfServiceUrl + { + get { return Instance.consentFlowTermsOfServiceUrl; } + set { Instance.consentFlowTermsOfServiceUrl = value; } + } + + /// + /// A User Tracking Usage Description in English to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionEn + { + get { return Instance.userTrackingUsageDescriptionEn; } + set { Instance.userTrackingUsageDescriptionEn = value; } + } + + /// + /// Whether or not to localize User Tracking Usage Description. + /// For more information see Apple's documentation. + /// + public bool UserTrackingUsageLocalizationEnabled + { + get { return Instance.userTrackingUsageLocalizationEnabled; } + set + { + var previousValue = Instance.userTrackingUsageLocalizationEnabled; + Instance.userTrackingUsageLocalizationEnabled = value; + + if (value) + { + // If the value didn't change or the english localization text is not the default one, we don't need to update anything. + if (previousValue || !DefaultUserTrackingDescriptionEnV3.Equals(Instance.UserTrackingUsageDescriptionEn)) return; + + Instance.UserTrackingUsageDescriptionDe = DefaultUserTrackingDescriptionDe; + Instance.UserTrackingUsageDescriptionEs = DefaultUserTrackingDescriptionEs; + Instance.UserTrackingUsageDescriptionFr = DefaultUserTrackingDescriptionFr; + Instance.UserTrackingUsageDescriptionJa = DefaultUserTrackingDescriptionJa; + Instance.UserTrackingUsageDescriptionKo = DefaultUserTrackingDescriptionKo; + Instance.UserTrackingUsageDescriptionZhHans = DefaultUserTrackingDescriptionZhHans; + Instance.UserTrackingUsageDescriptionZhHant = DefaultUserTrackingDescriptionZhHant; + } + else + { + Instance.UserTrackingUsageDescriptionDe = string.Empty; + Instance.UserTrackingUsageDescriptionEs = string.Empty; + Instance.UserTrackingUsageDescriptionFr = string.Empty; + Instance.UserTrackingUsageDescriptionJa = string.Empty; + Instance.UserTrackingUsageDescriptionKo = string.Empty; + Instance.UserTrackingUsageDescriptionZhHans = string.Empty; + Instance.UserTrackingUsageDescriptionZhHant = string.Empty; + } + } + } + + /// + /// A User Tracking Usage Description in German to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionDe + { + get { return Instance.userTrackingUsageDescriptionDe; } + set { Instance.userTrackingUsageDescriptionDe = value; } + } + + /// + /// A User Tracking Usage Description in Spanish to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionEs + { + get { return Instance.userTrackingUsageDescriptionEs; } + set { Instance.userTrackingUsageDescriptionEs = value; } + } + + /// + /// A User Tracking Usage Description in French to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionFr + { + get { return Instance.userTrackingUsageDescriptionFr; } + set { Instance.userTrackingUsageDescriptionFr = value; } + } + + /// + /// A User Tracking Usage Description in Japanese to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionJa + { + get { return Instance.userTrackingUsageDescriptionJa; } + set { Instance.userTrackingUsageDescriptionJa = value; } + } + + /// + /// A User Tracking Usage Description in Korean to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionKo + { + get { return Instance.userTrackingUsageDescriptionKo; } + set { Instance.userTrackingUsageDescriptionKo = value; } + } + + /// + /// A User Tracking Usage Description in Chinese (Simplified) to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionZhHans + { + get { return Instance.userTrackingUsageDescriptionZhHans; } + set { Instance.userTrackingUsageDescriptionZhHans = value; } + } + + /// + /// A User Tracking Usage Description in Chinese (Traditional) to be shown to users when requesting permission to use data for tracking. + /// For more information see Apple's documentation. + /// + public string UserTrackingUsageDescriptionZhHant + { + get + { + // Since this localization has been added separate from the other localizations, + // we use a placeholder constant to be replaced with the actual value or an empty string based on whether or not the localization was enabled by the publisher. + if (DefaultLocalization.Equals(Instance.userTrackingUsageDescriptionZhHant)) + { + Instance.userTrackingUsageDescriptionZhHant = Instance.UserTrackingUsageLocalizationEnabled ? DefaultUserTrackingDescriptionZhHant : string.Empty; + } + + return Instance.userTrackingUsageDescriptionZhHant; + } + set { Instance.userTrackingUsageDescriptionZhHant = value; } + } + + /// + /// AdMob Android App ID. + /// + public string AdMobAndroidAppId + { + get { return Instance.adMobAndroidAppId; } + set { Instance.adMobAndroidAppId = value; } + } + + /// + /// AdMob iOS App ID. + /// + public string AdMobIosAppId + { + get { return Instance.adMobIosAppId; } + set { Instance.adMobIosAppId = value; } + } + + public bool ShowInternalSettingsInIntegrationManager + { + get { return Instance.showInternalSettingsInIntegrationManager; } + set { Instance.showInternalSettingsInIntegrationManager = value; } + } + + /// + /// Saves the instance of the settings. + /// + public void SaveAsync() + { + EditorUtility.SetDirty(instance); + } +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta new file mode 100644 index 0000000..7e40d73 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: ebc0ba1b5ef6b4a6b9dd53d7eadfea16 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/AppLovinSettings.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef new file mode 100644 index 0000000..1cc80b7 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef @@ -0,0 +1,10 @@ +{ + "name": "MaxSdk.Scripts.IntegrationManager.Editor", + "references": [ + "MaxSdk.Scripts" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [] +} diff --git a/Assets/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta new file mode 100644 index 0000000..272b872 --- /dev/null +++ b/Assets/MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef.meta @@ -0,0 +1,6 @@ +fileFormatVersion: 2 +guid: a10a05a8449c42519fd80f2b8b580de3 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/IntegrationManager/Editor/MaxSdk.IntegrationManager.Editor.asmdef +timeCreated: 1591749873 diff --git a/Assets/MaxSdk/Scripts/MaxCmpService.cs b/Assets/MaxSdk/Scripts/MaxCmpService.cs new file mode 100644 index 0000000..c142439 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxCmpService.cs @@ -0,0 +1,170 @@ +// +// MaxCmpService.cs +// AppLovin User Engagement Unity Plugin +// +// Created by Santosh Bagadi on 10/1/23. +// Copyright © 2023 AppLovin. All rights reserved. +// + +using System; +using System.Collections.Generic; + +#if UNITY_EDITOR +#elif UNITY_ANDROID +using UnityEngine; +#elif UNITY_IOS +using System.Runtime.InteropServices; +#endif + +/// +/// This class provides direct APIs for interfacing with the Google-certified CMP installed, if any. +/// +public class MaxCmpService +{ + private static readonly MaxCmpService _instance = new MaxCmpService(); + + private MaxCmpService() { } + + private static Action OnCompletedAction; + +#if UNITY_EDITOR +#elif UNITY_ANDROID + private static readonly AndroidJavaClass MaxUnityPluginClass = new AndroidJavaClass("com.applovin.mediation.unity.MaxUnityPlugin"); +#elif UNITY_IOS + [DllImport("__Internal")] + private static extern void _MaxShowCmpForExistingUser(); + + [DllImport("__Internal")] + private static extern bool _MaxHasSupportedCmp(); +#endif + + internal static MaxCmpService Instance + { + get { return _instance; } + } + + /// + /// Shows the CMP flow to an existing user. + /// Note that the user's current consent will be reset before the CMP alert is shown. + /// + /// Called when the CMP flow finishes showing. + public void ShowCmpForExistingUser(Action onCompletedAction) + { + OnCompletedAction = onCompletedAction; + +#if UNITY_EDITOR + var errorProps = new Dictionary + { + {"code", (int) MaxCmpError.ErrorCode.FormUnavailable}, + {"message", "CMP is not supported in Unity editor"} + }; + + NotifyCompletedIfNeeded(errorProps); +#elif UNITY_ANDROID + MaxUnityPluginClass.CallStatic("showCmpForExistingUser"); +#elif UNITY_IOS + _MaxShowCmpForExistingUser(); +#endif + } + + /// + /// Returns true if a supported CMP SDK is detected. + /// + public bool HasSupportedCmp + { + get + { +#if UNITY_EDITOR + return false; +#elif UNITY_ANDROID + return MaxUnityPluginClass.CallStatic("hasSupportedCmp"); +#elif UNITY_IOS + return _MaxHasSupportedCmp(); +#else + return false; +#endif + } + } + + internal static void NotifyCompletedIfNeeded(Dictionary errorProps) + { + if (OnCompletedAction == null) return; + + var error = (errorProps == null) ? null : MaxCmpError.Create(errorProps); + OnCompletedAction(error); + } +} + +public class MaxCmpError +{ + public enum ErrorCode + { + /// + /// Indicates that an unspecified error has occurred. + /// + Unspecified = -1, + + /// + /// Indicates that the CMP has not been integrated correctly. + /// + IntegrationError = 1, + + /// + /// Indicates that the CMP form is unavailable. + /// + FormUnavailable = 2, + + /// + /// Indicates that the CMP form is not required. + /// + FormNotRequired = 3 + } + + public static MaxCmpError Create(IDictionary error) + { + return new MaxCmpError() + { + Code = GetCode(MaxSdkUtils.GetIntFromDictionary(error, "code")), + Message = MaxSdkUtils.GetStringFromDictionary(error, "message"), + CmpCode = MaxSdkUtils.GetIntFromDictionary(error, "cmpCode", -1), + CmpMessage = MaxSdkUtils.GetStringFromDictionary(error, "cmpMessage") + }; + } + + private static ErrorCode GetCode(int code) + { + switch (code) + { + case 1: + return ErrorCode.IntegrationError; + case 2: + return ErrorCode.FormUnavailable; + case 3: + return ErrorCode.FormNotRequired; + default: + return ErrorCode.Unspecified; + } + } + + private MaxCmpError() { } + + /// + /// The error code for this error. + /// + public ErrorCode Code { get; private set; } + + /// + /// The error message for this error. + /// + public string Message { get; private set; } + + /// + /// The error code returned by the CMP. + /// + public int CmpCode { get; private set; } + + /// + /// The error message returned by the CMP. + /// + public string CmpMessage { get; private set; } +} diff --git a/Assets/MaxSdk/Scripts/MaxCmpService.cs.meta b/Assets/MaxSdk/Scripts/MaxCmpService.cs.meta new file mode 100644 index 0000000..598fc90 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxCmpService.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: f2e895983b04846af81b59189de0310c +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxCmpService.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxEventExecutor.cs b/Assets/MaxSdk/Scripts/MaxEventExecutor.cs new file mode 100644 index 0000000..1065e6d --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxEventExecutor.cs @@ -0,0 +1,108 @@ +// +// MaxEventExecutor.cs +// Max Unity Plugin +// +// Created by Jonathan Liu on 1/22/2024. +// Copyright © 2024 AppLovin. All rights reserved. +// + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Events; + +namespace AppLovinMax.Internal +{ + public class MaxEventExecutor : MonoBehaviour + { + private static MaxEventExecutor instance; + private static List adEventsQueue = new List(); + + private static volatile bool adEventsQueueEmpty = true; + + struct MaxAction + { + public Action action; + public string eventName; + + public MaxAction(Action actionToExecute, string nameOfEvent) + { + action = actionToExecute; + eventName = nameOfEvent; + } + } + + public static void InitializeIfNeeded() + { + if (instance != null) return; + + var executor = new GameObject("MaxEventExecutor"); + executor.hideFlags = HideFlags.HideAndDontSave; + DontDestroyOnLoad(executor); + instance = executor.AddComponent(); + } + + #region Public API + +#if UNITY_EDITOR || !(UNITY_ANDROID || UNITY_IPHONE || UNITY_IOS) + public static MaxEventExecutor Instance + { + get + { + InitializeIfNeeded(); + return instance; + } + } +#endif + + public static void ExecuteOnMainThread(Action action, string eventName) + { + lock (adEventsQueue) + { + adEventsQueue.Add(new MaxAction(action, eventName)); + adEventsQueueEmpty = false; + } + } + + public static void InvokeOnMainThread(UnityEvent unityEvent, string eventName) + { + ExecuteOnMainThread(() => unityEvent.Invoke(), eventName); + } + + #endregion + + public void Update() + { + if (adEventsQueueEmpty) return; + + var actionsToExecute = new List(); + lock (adEventsQueue) + { + actionsToExecute.AddRange(adEventsQueue); + adEventsQueue.Clear(); + adEventsQueueEmpty = true; + } + + foreach (var maxAction in actionsToExecute) + { + if (maxAction.action.Target != null) + { + try + { + maxAction.action.Invoke(); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Caught exception in publisher event: " + maxAction.eventName + ", exception: " + exception); + Debug.LogException(exception); + } + } + } + } + + public void Disable() + { + instance = null; + } + } +} diff --git a/Assets/MaxSdk/Scripts/MaxEventExecutor.cs.meta b/Assets/MaxSdk/Scripts/MaxEventExecutor.cs.meta new file mode 100644 index 0000000..18ba126 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxEventExecutor.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 4715dd62632564dc4810a4dc98243f4a +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxEventExecutor.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxEventSystemChecker.cs b/Assets/MaxSdk/Scripts/MaxEventSystemChecker.cs new file mode 100644 index 0000000..19a082f --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxEventSystemChecker.cs @@ -0,0 +1,37 @@ +// +// EventSystemChecker.cs +// AppLovin MAX Unity Plugin +// +// Created by Jonathan Liu on 10/23/2022. +// Copyright © 2022 AppLovin. All rights reserved. +// + +#if UNITY_EDITOR +using UnityEngine; +using UnityEngine.EventSystems; + +namespace AppLovinMax.Scripts +{ + /// + /// A script to check and enable event system as needed for the AppLovin MAX ad prefabs. + /// + [RequireComponent(typeof(EventSystem))] + public class MaxEventSystemChecker : MonoBehaviour + { + private void Awake() + { + // Enable the EventSystem if there is no other EventSystem in the scene + var eventSystem = GetComponent(); + var currentSystem = UnityEngine.EventSystems.EventSystem.current; + if (currentSystem == null || currentSystem == eventSystem) + { + eventSystem.enabled = true; + } + else + { + eventSystem.enabled = false; + } + } + } +} +#endif diff --git a/Assets/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta b/Assets/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta new file mode 100644 index 0000000..12874b6 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxEventSystemChecker.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: e0acf281ba86b4929a6942ecd998395b +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxEventSystemChecker.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxEvents.cs b/Assets/MaxSdk/Scripts/MaxEvents.cs new file mode 100644 index 0000000..b0a9ad6 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxEvents.cs @@ -0,0 +1,21 @@ +/** + * Class containing pre-defined constants to use with AppLovin event tracking APIs. + */ +public static class MaxEvents +{ + /** + * Nested class representing pre-defined AppLovin events to be fired with AppLovin event tracking APIs. + */ + public class AppLovin + { + public const string UserLoggedIn = "login"; + public const string UserCreatedAccount = "registration"; + public const string UserCompletedTutorial = "tutorial"; + public const string UserCompletedLevel = "level"; + public const string UserCompletedAchievement = "achievement"; + public const string UserSpentVirtualCurrency = "vcpurchase"; + public const string UserCompletedInAppPurchase = "iap"; + public const string UserSentInvitation = "invite"; + public const string UserSharedLink = "share"; + } +} \ No newline at end of file diff --git a/Assets/MaxSdk/Scripts/MaxEvents.cs.meta b/Assets/MaxSdk/Scripts/MaxEvents.cs.meta new file mode 100644 index 0000000..bfb6ad5 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxEvents.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 67ec2f620c6b0405ba16ea2c032dc9a2 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxEvents.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef b/Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef new file mode 100644 index 0000000..99e1d22 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef @@ -0,0 +1,6 @@ + { + "name": "MaxSdk.Scripts", + "references": [], + "includePlatforms": [], + "excludePlatforms": [] +} diff --git a/Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta b/Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta new file mode 100644 index 0000000..b55da72 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdk.Scripts.asmdef.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a4cfc1a18fa3a469b96d885db522f42e +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdk.Scripts.asmdef +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxSdk.cs b/Assets/MaxSdk/Scripts/MaxSdk.cs new file mode 100644 index 0000000..7909929 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdk.cs @@ -0,0 +1,30 @@ +/** + * AppLovin MAX Unity Plugin C# Wrapper + */ + +using UnityEngine; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +public class MaxSdk : +#if UNITY_EDITOR + // Check for Unity Editor first since the editor also responds to the currently selected platform. + MaxSdkUnityEditor +#elif UNITY_ANDROID + MaxSdkAndroid +#elif UNITY_IPHONE || UNITY_IOS + MaxSdkiOS +#else + MaxSdkUnityEditor +#endif +{ + private const string _version = "7.0.0"; + + /// + /// Returns the current plugin version. + /// + public static string Version + { + get { return _version; } + } +} diff --git a/Assets/MaxSdk/Scripts/MaxSdk.cs.meta b/Assets/MaxSdk/Scripts/MaxSdk.cs.meta new file mode 100644 index 0000000..c1c32f4 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdk.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 2fc7aa576843c44e68c7ab14b475bb82 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdk.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxSdkAndroid.cs b/Assets/MaxSdk/Scripts/MaxSdkAndroid.cs new file mode 100644 index 0000000..a489db2 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkAndroid.cs @@ -0,0 +1,1069 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using AppLovinMax.ThirdParty.MiniJson; + +/// +/// Android AppLovin MAX Unity Plugin implementation +/// +public class MaxSdkAndroid : MaxSdkBase +{ + private static readonly AndroidJavaClass MaxUnityPluginClass = + new AndroidJavaClass("com.applovin.mediation.unity.MaxUnityPlugin"); + + private static BackgroundCallbackProxy BackgroundCallback = new BackgroundCallbackProxy(); + + public static MaxUserServiceAndroid UserService + { + get { return MaxUserServiceAndroid.Instance; } + } + + static MaxSdkAndroid() + { + InitializeEventExecutor(); + + MaxUnityPluginClass.CallStatic("setBackgroundCallback", BackgroundCallback); + } + + #region Initialization + + /// + /// Initialize the default instance of AppLovin SDK. + /// + /// Please make sure that application's Android manifest or Info.plist includes the AppLovin SDK key. + /// + /// OPTIONAL: Set the MAX ad unit ids to be used for this instance of the SDK. 3rd-party SDKs will be initialized with the credentials configured for these ad unit ids. + /// This should only be used if you have different sets of ad unit ids / credentials for the same package name. + /// + public static void InitializeSdk(string[] adUnitIds = null) + { + var serializedAdUnitIds = (adUnitIds != null) ? string.Join(",", adUnitIds) : ""; + MaxUnityPluginClass.CallStatic("initializeSdk", serializedAdUnitIds, GenerateMetaData()); + } + + /// + /// Check if the SDK has been initialized + /// + /// True if SDK has been initialized + public static bool IsInitialized() + { + return MaxUnityPluginClass.CallStatic("isInitialized"); + } + + #endregion + + #region User Info + + /// + /// Set an identifier for the current user. This identifier will be tied to SDK events and our optional S2S postbacks. + /// + /// If you're using reward validation, you can optionally set an identifier to be included with currency validation postbacks. + /// For example, a username or email. We'll include this in the postback when we ping your currency endpoint from our server. + /// + /// + /// The user identifier to be set. Must not be null. + public static void SetUserId(string userId) + { + MaxUnityPluginClass.CallStatic("setUserId", userId); + } + + /// + /// Set the . + /// + /// The segment collection to be set. Must not be {@code null} + public static void SetSegmentCollection(MaxSegmentCollection segmentCollection) + { + MaxUnityPluginClass.CallStatic("setSegmentCollection", JsonUtility.ToJson(segmentCollection)); + } + + #endregion + + #region MAX + + /// + /// Returns the list of available mediation networks. + /// + /// Please call this method after the SDK has initialized. + /// + public static List GetAvailableMediatedNetworks() + { + var serializedNetworks = MaxUnityPluginClass.CallStatic("getAvailableMediatedNetworks"); + return MaxSdkUtils.PropsStringsToList(serializedNetworks); + } + + /// + /// Present the mediation debugger UI. + /// This debugger tool provides the status of your integration for each third-party ad network. + /// + /// Please call this method after the SDK has initialized. + /// + public static void ShowMediationDebugger() + { + MaxUnityPluginClass.CallStatic("showMediationDebugger"); + } + + /// + /// Present the creative debugger UI. + /// This debugger tool provides information for recently displayed ads. + /// + /// Please call this method after the SDK has initialized. + /// + public static void ShowCreativeDebugger() + { + MaxUnityPluginClass.CallStatic("showCreativeDebugger"); + } + + /// + /// Returns the arbitrary ad value for a given ad unit identifier with key. Returns null if no ad is loaded. + /// + /// Ad unit identifier for which to get the ad value for. Must not be null. + /// Ad value key. Must not be null. + /// Arbitrary ad value for a given key, or null if no ad is loaded. + public static string GetAdValue(string adUnitIdentifier, string key) + { + var value = MaxUnityPluginClass.CallStatic("getAdValue", adUnitIdentifier, key); + + if (string.IsNullOrEmpty(value)) return null; + + return value; + } + + #endregion + + #region Privacy + + /// + /// Get the SDK configuration for this user. + /// + /// Note: This method should be called only after SDK has been initialized. + /// + public static SdkConfiguration GetSdkConfiguration() + { + var sdkConfigurationStr = MaxUnityPluginClass.CallStatic("getSdkConfiguration"); + var sdkConfigurationDict = Json.Deserialize(sdkConfigurationStr) as Dictionary; + return SdkConfiguration.Create(sdkConfigurationDict); + } + + /// + /// Set whether or not user has provided consent for information sharing with AppLovin and other providers. + /// + /// true if the user has provided consent for information sharing with AppLovin. false by default. + public static void SetHasUserConsent(bool hasUserConsent) + { + MaxUnityPluginClass.CallStatic("setHasUserConsent", hasUserConsent); + } + + /// + /// Check if user has provided consent for information sharing with AppLovin and other providers. + /// + /// true if user has provided consent for information sharing. false if the user declined to share information or the consent value has not been set . + public static bool HasUserConsent() + { + return MaxUnityPluginClass.CallStatic("hasUserConsent"); + } + + /// + /// Check if user has set consent for information sharing. + /// + /// true if user has set a value of consent for information sharing. + public static bool IsUserConsentSet() + { + return MaxUnityPluginClass.CallStatic("isUserConsentSet"); + } + + /// + /// Set whether or not user has opted out of the sale of their personal information. + /// + /// true if the user has opted out of the sale of their personal information. + public static void SetDoNotSell(bool doNotSell) + { + MaxUnityPluginClass.CallStatic("setDoNotSell", doNotSell); + } + + /// + /// Check if the user has opted out of the sale of their personal information. + /// + /// true if the user has opted out of the sale of their personal information. false if the user opted in to the sell of their personal information or the value has not been set . + public static bool IsDoNotSell() + { + return MaxUnityPluginClass.CallStatic("isDoNotSell"); + } + + /// + /// Check if the user has set the option to sell their personal information. + /// + /// true if user has chosen an option to sell their personal information. + public static bool IsDoNotSellSet() + { + return MaxUnityPluginClass.CallStatic("isDoNotSellSet"); + } + + #endregion + + #region Banners + + /// + /// Create a new banner. + /// + /// Ad unit identifier of the banner to create. Must not be null. + /// Banner position. Must not be null. + public static void CreateBanner(string adUnitIdentifier, BannerPosition bannerPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create banner"); + MaxUnityPluginClass.CallStatic("createBanner", adUnitIdentifier, bannerPosition.ToSnakeCaseString()); + } + + /// + /// Create a new banner with a custom position. + /// + /// Ad unit identifier of the banner to create. Must not be null. + /// The X coordinate (horizontal position) of the banner relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the banner relative to the top left corner of the screen. + /// + /// The banner is placed within the safe area of the screen. You can use this to get the absolute position of the banner on screen. + /// + public static void CreateBanner(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create banner"); + MaxUnityPluginClass.CallStatic("createBanner", adUnitIdentifier, x, y); + } + + /// + /// Load a new banner ad. + /// NOTE: The method loads the first banner ad and initiates an automated banner refresh process. + /// You only need to call this method if you pause banner refresh. + /// + /// Ad unit identifier of the banner to load. Must not be null. + public static void LoadBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load banner"); + MaxUnityPluginClass.CallStatic("loadBanner", adUnitIdentifier); + } + + /// + /// Set the banner placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the banner to set the placement for. Must not be null. + /// Placement to set + public static void SetBannerPlacement(string adUnitIdentifier, string placement) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner placement"); + MaxUnityPluginClass.CallStatic("setBannerPlacement", adUnitIdentifier, placement); + } + + /// + /// Starts or resumes auto-refreshing of the banner for the given ad unit identifier. + /// + /// Ad unit identifier of the banner for which to start auto-refresh. Must not be null. + public static void StartBannerAutoRefresh(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "start banner auto-refresh"); + MaxUnityPluginClass.CallStatic("startBannerAutoRefresh", adUnitIdentifier); + } + + /// + /// Pauses auto-refreshing of the banner for the given ad unit identifier. + /// + /// Ad unit identifier of the banner for which to stop auto-refresh. Must not be null. + public static void StopBannerAutoRefresh(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "stop banner auto-refresh"); + MaxUnityPluginClass.CallStatic("stopBannerAutoRefresh", adUnitIdentifier); + } + + /// + /// Updates the position of the banner to the new position provided. + /// + /// The ad unit identifier of the banner for which to update the position. Must not be null. + /// A new position for the banner. Must not be null. + public static void UpdateBannerPosition(string adUnitIdentifier, BannerPosition bannerPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update banner position"); + MaxUnityPluginClass.CallStatic("updateBannerPosition", adUnitIdentifier, bannerPosition.ToSnakeCaseString()); + } + + /// + /// Updates the position of the banner to the new coordinates provided. + /// + /// The ad unit identifier of the banner for which to update the position. Must not be null. + /// The X coordinate (horizontal position) of the banner relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the banner relative to the top left corner of the screen. + /// + /// The banner is placed within the safe area of the screen. You can use this to get the absolute position of the banner on screen. + /// + public static void UpdateBannerPosition(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update banner position"); + MaxUnityPluginClass.CallStatic("updateBannerPosition", adUnitIdentifier, x, y); + } + + /// + /// Overrides the width of the banner in dp. + /// + /// The ad unit identifier of the banner for which to override the width for. Must not be null. + /// The desired width of the banner in dp + public static void SetBannerWidth(string adUnitIdentifier, float width) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner width"); + MaxUnityPluginClass.CallStatic("setBannerWidth", adUnitIdentifier, width); + } + + /// + /// Show banner at a position determined by the 'CreateBanner' call. + /// + /// Ad unit identifier of the banner to show. Must not be null. + public static void ShowBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show banner"); + MaxUnityPluginClass.CallStatic("showBanner", adUnitIdentifier); + } + + /// + /// Remove banner from the ad view and destroy it. + /// + /// Ad unit identifier of the banner to destroy. Must not be null. + public static void DestroyBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy banner"); + MaxUnityPluginClass.CallStatic("destroyBanner", adUnitIdentifier); + } + + /// + /// Hide banner. + /// + /// Ad unit identifier of the banner to hide. Must not be null. + public static void HideBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide banner"); + MaxUnityPluginClass.CallStatic("hideBanner", adUnitIdentifier); + } + + /// + /// Set non-transparent background color for banners to be fully functional. + /// + /// Ad unit identifier of the banner to set background color for. Must not be null. + /// A background color to set for the ad. Must not be null. + public static void SetBannerBackgroundColor(string adUnitIdentifier, Color color) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set background color"); + MaxUnityPluginClass.CallStatic("setBannerBackgroundColor", adUnitIdentifier, MaxSdkUtils.ParseColor(color)); + } + + /// + /// Set an extra parameter for the banner ad. + /// + /// Ad unit identifier of the banner to set the extra parameter for. Must not be null. + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. + public static void SetBannerExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner extra parameter"); + MaxUnityPluginClass.CallStatic("setBannerExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// Set a local extra parameter for the banner ad. + /// + /// Ad unit identifier of the banner to set the local extra parameter for. Must not be null. + /// The key for the local extra parameter. Must not be null. + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types + public static void SetBannerLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner local extra parameter"); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setBannerLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setBannerLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } + } + + /// + /// The custom data to tie the showing banner ad to, for ILRD and rewarded postbacks via the {CUSTOM_DATA} macro. Maximum size is 8KB. + /// + /// Banner ad unit identifier of the banner to set the custom data for. Must not be null. + /// The custom data to be set. + public static void SetBannerCustomData(string adUnitIdentifier, string customData) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner custom data"); + MaxUnityPluginClass.CallStatic("setBannerCustomData", adUnitIdentifier, customData); + } + + /// + /// The banner position on the screen. When setting the banner position via or , + /// the banner is placed within the safe area of the screen. This returns the absolute position of the banner on screen. + /// + /// Ad unit identifier of the banner for which to get the position on screen. Must not be null. + /// A representing the banner position on screen. + public static Rect GetBannerLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get banner layout"); + var positionRect = MaxUnityPluginClass.CallStatic("getBannerLayout", adUnitIdentifier); + return GetRectFromString(positionRect); + } + + #endregion + + #region MRECs + + /// + /// Create a new MREC. + /// + /// Ad unit identifier of the MREC to create. Must not be null. + /// MREC position. Must not be null. + public static void CreateMRec(string adUnitIdentifier, AdViewPosition mrecPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create MREC"); + MaxUnityPluginClass.CallStatic("createMRec", adUnitIdentifier, mrecPosition.ToSnakeCaseString()); + } + + /// + /// Create a new MREC with a custom position. + /// + /// Ad unit identifier of the MREC to create. Must not be null. + /// The X coordinate (horizontal position) of the MREC relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the MREC relative to the top left corner of the screen. + /// + /// The MREC is placed within the safe area of the screen. You can use this to get the absolute position Rect of the MREC on screen. + /// + public static void CreateMRec(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create MREC"); + MaxUnityPluginClass.CallStatic("createMRec", adUnitIdentifier, x, y); + } + + /// + /// Load a new MREC ad. + /// NOTE: The method loads the first MREC ad and initiates an automated MREC refresh process. + /// You only need to call this method if you pause MREC refresh. + /// + /// Ad unit identifier of the MREC to load. Must not be null. + public static void LoadMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load MREC"); + MaxUnityPluginClass.CallStatic("loadMRec", adUnitIdentifier); + } + + /// + /// Set the MREC placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the MREC to set the placement for. Must not be null. + /// Placement to set + public static void SetMRecPlacement(string adUnitIdentifier, string placement) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC placement"); + MaxUnityPluginClass.CallStatic("setMRecPlacement", adUnitIdentifier, placement); + } + + /// + /// Starts or resumes auto-refreshing of the MREC for the given ad unit identifier. + /// + /// Ad unit identifier of the MREC for which to start auto-refresh. Must not be null. + public static void StartMRecAutoRefresh(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "start MREC auto-refresh"); + MaxUnityPluginClass.CallStatic("startMRecAutoRefresh", adUnitIdentifier); + } + + /// + /// Pauses auto-refreshing of the MREC for the given ad unit identifier. + /// + /// Ad unit identifier of the MREC for which to stop auto-refresh. Must not be null. + public static void StopMRecAutoRefresh(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "stop MREC auto-refresh"); + MaxUnityPluginClass.CallStatic("stopMRecAutoRefresh", adUnitIdentifier); + } + + /// + /// Updates the position of the MREC to the new position provided. + /// + /// The ad unit identifier of the MREC for which to update the position. Must not be null. + /// A new position for the MREC. Must not be null. + public static void UpdateMRecPosition(string adUnitIdentifier, AdViewPosition mrecPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update MREC position"); + MaxUnityPluginClass.CallStatic("updateMRecPosition", adUnitIdentifier, mrecPosition.ToSnakeCaseString()); + } + + /// + /// Updates the position of the MREC to the new coordinates provided. + /// + /// The ad unit identifier of the MREC for which to update the position. Must not be null. + /// The X coordinate (horizontal position) of the MREC relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the MREC relative to the top left corner of the screen. + /// + /// The MREC is placed within the safe area of the screen. You can use this to get the absolute position Rect of the MREC on screen. + /// + public static void UpdateMRecPosition(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "update MREC position"); + MaxUnityPluginClass.CallStatic("updateMRecPosition", adUnitIdentifier, x, y); + } + + /// + /// Show MREC at a position determined by the 'CreateMRec' call. + /// + /// Ad unit identifier of the MREC to show. Must not be null. + public static void ShowMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show MREC"); + MaxUnityPluginClass.CallStatic("showMRec", adUnitIdentifier); + } + + /// + /// Remove MREC from the ad view and destroy it. + /// + /// Ad unit identifier of the MREC to destroy. Must not be null. + public static void DestroyMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy MREC"); + MaxUnityPluginClass.CallStatic("destroyMRec", adUnitIdentifier); + } + + /// + /// Hide MREC. + /// + /// Ad unit identifier of the MREC to hide. Must not be null. + public static void HideMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide MREC"); + MaxUnityPluginClass.CallStatic("hideMRec", adUnitIdentifier); + } + + /// + /// Set an extra parameter for the MREC ad. + /// + /// Ad unit identifier of the MREC to set the extra parameter for. Must not be null. + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. + public static void SetMRecExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC extra parameter"); + MaxUnityPluginClass.CallStatic("setMRecExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// Set a local extra parameter for the MREC ad. + /// + /// Ad unit identifier of the MREC to set the local extra parameter for. Must not be null. + /// The key for the local extra parameter. Must not be null. + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types + public static void SetMRecLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC local extra parameter"); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setMRecLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setMRecLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } + } + + /// + /// The custom data to tie the showing MREC ad to, for ILRD and rewarded postbacks via the {CUSTOM_DATA} macro. Maximum size is 8KB. + /// + /// MREC Ad unit identifier of the banner to set the custom data for. Must not be null. + /// The custom data to be set. + public static void SetMRecCustomData(string adUnitIdentifier, string customData) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC custom data"); + MaxUnityPluginClass.CallStatic("setMRecCustomData", adUnitIdentifier, customData); + } + + /// + /// The MREC position on the screen. When setting the banner position via or , + /// the banner is placed within the safe area of the screen. This returns the absolute position of the MREC on screen. + /// + /// Ad unit identifier of the MREC for which to get the position on screen. Must not be null. + /// A representing the banner position on screen. + public static Rect GetMRecLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get MREC layout"); + var positionRect = MaxUnityPluginClass.CallStatic("getMRecLayout", adUnitIdentifier); + return GetRectFromString(positionRect); + } + + #endregion + + #region Interstitials + + /// + /// Start loading an interstitial. + /// + /// Ad unit identifier of the interstitial to load. Must not be null. + public static void LoadInterstitial(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load interstitial"); + MaxUnityPluginClass.CallStatic("loadInterstitial", adUnitIdentifier); + } + + /// + /// Check if interstitial ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the interstitial to load. Must not be null. + /// True if the ad is ready to be displayed + public static bool IsInterstitialReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check interstitial loaded"); + return MaxUnityPluginClass.CallStatic("isInterstitialReady", adUnitIdentifier); + } + + /// + /// Present loaded interstitial for a given placement to tie ad events to. Note: if the interstitial is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the interstitial to load. Must not be null. + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowInterstitial(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show interstitial"); + + if (IsInterstitialReady(adUnitIdentifier)) + { + MaxUnityPluginClass.CallStatic("showInterstitial", adUnitIdentifier, placement, customData); + } + else + { + MaxSdkLogger.UserWarning("Not showing MAX Ads interstitial: ad not ready"); + } + } + + /// + /// Set an extra parameter for the ad. + /// + /// Ad unit identifier of the interstitial to set the extra parameter for. Must not be null. + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. + public static void SetInterstitialExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set interstitial extra parameter"); + MaxUnityPluginClass.CallStatic("setInterstitialExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// Set a local extra parameter for the ad. + /// + /// Ad unit identifier of the interstitial to set the local extra parameter for. Must not be null. + /// The key for the local extra parameter. Must not be null. + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types + public static void SetInterstitialLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set interstitial local extra parameter"); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setInterstitialLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setInterstitialLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } + } + + #endregion + + #region App Open + + /// + /// Start loading an app open ad. + /// + /// Ad unit identifier of the app open ad to load. Must not be null. + public static void LoadAppOpenAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load app open ad"); + MaxUnityPluginClass.CallStatic("loadAppOpenAd", adUnitIdentifier); + } + + /// + /// Check if app open ad ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the app open ad to load. Must not be null. + /// True if the ad is ready to be displayed + public static bool IsAppOpenAdReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check app open ad loaded"); + return MaxUnityPluginClass.CallStatic("isAppOpenAdReady", adUnitIdentifier); + } + + /// + /// Present loaded app open ad for a given placement to tie ad events to. Note: if the app open ad is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the app open ad to load. Must not be null. + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowAppOpenAd(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show app open ad"); + + if (IsAppOpenAdReady(adUnitIdentifier)) + { + MaxUnityPluginClass.CallStatic("showAppOpenAd", adUnitIdentifier, placement, customData); + } + else + { + MaxSdkLogger.UserWarning("Not showing MAX Ads app open ad: ad not ready"); + } + } + + /// + /// Set an extra parameter for the ad. + /// + /// Ad unit identifier of the app open ad to set the extra parameter for. Must not be null. + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. + public static void SetAppOpenAdExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set app open ad extra parameter"); + MaxUnityPluginClass.CallStatic("setAppOpenAdExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// Set a local extra parameter for the ad. + /// + /// Ad unit identifier of the app open ad to set the local extra parameter for. Must not be null. + /// The key for the local extra parameter. Must not be null. + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types + public static void SetAppOpenAdLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set app open ad local extra parameter"); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setAppOpenAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setAppOpenAdLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } + } + + #endregion + + #region Rewarded + + /// + /// Start loading an rewarded ad. + /// + /// Ad unit identifier of the rewarded ad to load. Must not be null. + public static void LoadRewardedAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load rewarded ad"); + MaxUnityPluginClass.CallStatic("loadRewardedAd", adUnitIdentifier); + } + + /// + /// Check if rewarded ad ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the rewarded ad to load. Must not be null. + /// True if the ad is ready to be displayed + public static bool IsRewardedAdReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check rewarded ad loaded"); + return MaxUnityPluginClass.CallStatic("isRewardedAdReady", adUnitIdentifier); + } + + /// ready to be + /// Present loaded rewarded ad for a given placement to tie ad events to. Note: if the rewarded ad is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the interstitial to load. Must not be null. + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowRewardedAd(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show rewarded ad"); + + if (IsRewardedAdReady(adUnitIdentifier)) + { + MaxUnityPluginClass.CallStatic("showRewardedAd", adUnitIdentifier, placement, customData); + } + else + { + MaxSdkLogger.UserWarning("Not showing MAX Ads rewarded ad: ad not ready"); + } + } + + /// + /// Set an extra parameter for the ad. + /// + /// Ad unit identifier of the rewarded to set the extra parameter for. Must not be null. + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. + public static void SetRewardedAdExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded ad extra parameter"); + MaxUnityPluginClass.CallStatic("setRewardedAdExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// Set a local extra parameter for the ad. + /// + /// Ad unit identifier of the rewarded to set the local extra parameter for. Must not be null. + /// The key for the local extra parameter. Must not be null. + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types + public static void SetRewardedAdLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded ad local extra parameter"); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setRewardedAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setRewardedAdLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } + } + + #endregion + + #region Rewarded Interstitial + + /// + /// Start loading an rewarded interstitial ad. + /// + /// Ad unit identifier of the rewarded interstitial ad to load. Must not be null. + public static void LoadRewardedInterstitialAd(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load rewarded interstitial ad"); + MaxUnityPluginClass.CallStatic("loadRewardedInterstitialAd", adUnitIdentifier); + } + + /// + /// Check if rewarded interstitial ad ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the rewarded interstitial ad to load. Must not be null. + /// True if the ad is ready to be displayed + public static bool IsRewardedInterstitialAdReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check rewarded interstitial ad loaded"); + return MaxUnityPluginClass.CallStatic("isRewardedInterstitialAdReady", adUnitIdentifier); + } + + /// + /// Present loaded rewarded interstitial ad for a given placement to tie ad events to. Note: if the rewarded interstitial ad is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the rewarded interstitial to show. Must not be null. + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowRewardedInterstitialAd(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show rewarded interstitial ad"); + + if (IsRewardedInterstitialAdReady(adUnitIdentifier)) + { + MaxUnityPluginClass.CallStatic("showRewardedInterstitialAd", adUnitIdentifier, placement, customData); + } + else + { + MaxSdkLogger.UserWarning("Not showing MAX Ads rewarded interstitial ad: ad not ready"); + } + } + + /// + /// Set an extra parameter for the ad. + /// + /// Ad unit identifier of the rewarded interstitial to set the extra parameter for. Must not be null. + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. + public static void SetRewardedInterstitialAdExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded interstitial ad extra parameter"); + MaxUnityPluginClass.CallStatic("setRewardedInterstitialAdExtraParameter", adUnitIdentifier, key, value); + } + + /// + /// Set a local extra parameter for the ad. + /// + /// Ad unit identifier of the rewarded interstitial to set the local extra parameter for. Must not be null. + /// The key for the local extra parameter. Must not be null. + /// The value for the extra parameter. Accepts the following types: , null, IList, IDictionary, string, primitive types + public static void SetRewardedInterstitialAdLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set rewarded interstitial ad local extra parameter"); + + if (value == null || value is AndroidJavaObject) + { + MaxUnityPluginClass.CallStatic("setRewardedInterstitialAdLocalExtraParameter", adUnitIdentifier, key, (AndroidJavaObject) value); + } + else + { + MaxUnityPluginClass.CallStatic("setRewardedInterstitialAdLocalExtraParameterJson", adUnitIdentifier, key, SerializeLocalExtraParameterValue(value)); + } + } + + #endregion + + #region Event Tracking + + /// + /// Track an event using AppLovin. + /// + /// An event from the list of pre-defined events may be found in MaxEvents.cs as part of the AppLovin SDK framework. Must not be null. + /// A dictionary containing key-value pairs further describing this event. + public static void TrackEvent(string name, IDictionary parameters = null) + { + MaxUnityPluginClass.CallStatic("trackEvent", name, Json.Serialize(parameters)); + } + + #endregion + + #region Settings + + /// + /// Set whether to begin video ads in a muted state or not. + /// + /// Please call this method after the SDK has initialized. + /// + /// true if video ads should being in muted state. + public static void SetMuted(bool muted) + { + MaxUnityPluginClass.CallStatic("setMuted", muted); + } + + /// + /// Whether video ads begin in a muted state or not. Defaults to false. + /// + /// Note: Returns false if the SDK is not initialized. + /// + /// true if video ads begin in muted state. + public static bool IsMuted() + { + return MaxUnityPluginClass.CallStatic("isMuted"); + } + + /// + /// Toggle verbose logging of AppLovin SDK. If enabled AppLovin messages will appear in standard application log accessible via logcat. All log messages will have "AppLovinSdk" tag. + /// + /// true if verbose logging should be enabled. + public static void SetVerboseLogging(bool enabled) + { + MaxUnityPluginClass.CallStatic("setVerboseLogging", enabled); + } + + /// + /// Whether or not verbose logging is enabled. + /// + /// true if verbose logging is enabled. + public static bool IsVerboseLoggingEnabled() + { + return MaxUnityPluginClass.CallStatic("isVerboseLoggingEnabled"); + } + + /// + /// Whether the creative debugger will be displayed on fullscreen ads after flipping the device screen down twice. Defaults to true. + /// + /// true if the creative debugger should be enabled. + public static void SetCreativeDebuggerEnabled(bool enabled) + { + MaxUnityPluginClass.CallStatic("setCreativeDebuggerEnabled", enabled); + } + + /// + /// Enable devices to receive test ads, by passing in the advertising identifier (IDFA/GAID) of each test device. + /// Refer to AppLovin logs for the IDFA/GAID of your current device. + /// + /// String list of advertising identifiers from devices to receive test ads. + public static void SetTestDeviceAdvertisingIdentifiers(string[] advertisingIdentifiers) + { + if (IsInitialized()) + { + MaxSdkLogger.UserError("Test Device Advertising Identifiers must be set before SDK initialization."); + return; + } + + // Wrap the string array in an object array, so the compiler does not split into multiple strings. + object[] arguments = {advertisingIdentifiers}; + MaxUnityPluginClass.CallStatic("setTestDeviceAdvertisingIds", arguments); + } + + /// + /// Whether or not the native AppLovin SDKs listen to exceptions. Defaults to true. + /// + /// true if the native AppLovin SDKs should not listen to exceptions. + public static void SetExceptionHandlerEnabled(bool enabled) + { + MaxUnityPluginClass.CallStatic("setExceptionHandlerEnabled", enabled); + } + + /// + /// Set an extra parameter to pass to the AppLovin server. + /// + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. May be null. + public static void SetExtraParameter(string key, string value) + { + MaxUnityPluginClass.CallStatic("setExtraParameter", key, value); + } + + /// + /// Get the native insets in pixels for the safe area. + /// These insets are used to position ads within the safe area of the screen. + /// + public static SafeAreaInsets GetSafeAreaInsets() + { + // Use an int array instead of json serialization for performance + var insets = MaxUnityPluginClass.CallStatic("getSafeAreaInsets"); + + // Convert from points to pixels + var screenDensity = MaxSdkUtils.GetScreenDensity(); + for (var i = 0; i < insets.Length; i++) + { + insets[i] *= (int) screenDensity; + } + + return new SafeAreaInsets(insets); + } + + #endregion + + #region Obsolete + + [Obsolete("This API has been deprecated and will be removed in a future release. Please set your SDK key in the AppLovin Integration Manager.")] + public static void SetSdkKey(string sdkKey) + { + MaxUnityPluginClass.CallStatic("setSdkKey", sdkKey); + Debug.LogWarning("MaxSdk.SetSdkKey() has been deprecated and will be removed in a future release. Please set your SDK key in the AppLovin Integration Manager."); + } + + [Obsolete("This method has been deprecated. Please use `GetSdkConfiguration().ConsentDialogState`")] + public static ConsentDialogState GetConsentDialogState() + { + if (!IsInitialized()) + { + MaxSdkLogger.UserWarning( + "MAX Ads SDK has not been initialized yet. GetConsentDialogState() may return ConsentDialogState.Unknown"); + } + + return (ConsentDialogState) MaxUnityPluginClass.CallStatic("getConsentDialogState"); + } + + [Obsolete("This method has been deprecated. The AdInfo object is returned with ad callbacks.")] + public static AdInfo GetAdInfo(string adUnitIdentifier) + { + var adInfoString = MaxUnityPluginClass.CallStatic("getAdInfo", adUnitIdentifier); + + if (string.IsNullOrEmpty(adInfoString)) return null; + + var adInfoDictionary = Json.Deserialize(adInfoString) as Dictionary; + return new AdInfo(adInfoDictionary); + } + + #endregion + + internal class BackgroundCallbackProxy : AndroidJavaProxy + { + public BackgroundCallbackProxy() : base("com.applovin.mediation.unity.MaxUnityAdManager$BackgroundCallback") { } + + public void onEvent(string propsStr) + { + HandleBackgroundCallback(propsStr); + } + } +} diff --git a/Assets/MaxSdk/Scripts/MaxSdkAndroid.cs.meta b/Assets/MaxSdk/Scripts/MaxSdkAndroid.cs.meta new file mode 100644 index 0000000..2cf5448 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkAndroid.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 10335fad6bfef47b8819a411aa591dc8 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdkAndroid.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxSdkBase.cs b/Assets/MaxSdk/Scripts/MaxSdkBase.cs new file mode 100644 index 0000000..7b83cb5 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkBase.cs @@ -0,0 +1,808 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using AppLovinMax.ThirdParty.MiniJson; +using AppLovinMax.Internal; +using UnityEngine; + +#if UNITY_IOS && !UNITY_EDITOR +using System.Runtime.InteropServices; +#endif + +public abstract class MaxSdkBase +{ + /// + /// This enum represents the user's geography used to determine the type of consent flow shown to the user. + /// + public enum ConsentFlowUserGeography + { + /// + /// User's geography is unknown. + /// + Unknown, + + /// + /// The user is in GDPR region. + /// + Gdpr, + + /// + /// The user is in a non-GDPR region. + /// + Other + } + +#if UNITY_EDITOR || UNITY_IPHONE || UNITY_IOS + /// + /// App tracking status values. Primarily used in conjunction with iOS14's AppTrackingTransparency.framework. + /// + public enum AppTrackingStatus + { + /// + /// Device is on < iOS14, AppTrackingTransparency.framework is not available. + /// + Unavailable, + + /// + /// The value returned if a user has not yet received an authorization request to authorize access to app-related data that can be used for tracking the user or the device. + /// + NotDetermined, + + /// + /// The value returned if authorization to access app-related data that can be used for tracking the user or the device is restricted. + /// + Restricted, + + /// + /// The value returned if the user denies authorization to access app-related data that can be used for tracking the user or the device. + /// + Denied, + + /// + /// The value returned if the user authorizes access to app-related data that can be used for tracking the user or the device. + /// + Authorized, + } +#endif + + public enum AdViewPosition + { + TopLeft, + TopCenter, + TopRight, + Centered, + CenterLeft, + CenterRight, + BottomLeft, + BottomCenter, + BottomRight + } + + public enum BannerPosition + { + TopLeft, + TopCenter, + TopRight, + Centered, + CenterLeft, + CenterRight, + BottomLeft, + BottomCenter, + BottomRight + } + + public class SdkConfiguration + { + /// + /// Whether or not the SDK has been initialized successfully. + /// + public bool IsSuccessfullyInitialized { get; private set; } + + /// + /// Get the country code for this user. + /// + public string CountryCode { get; private set; } + +#if UNITY_EDITOR || UNITY_IPHONE || UNITY_IOS + /// + /// App tracking status values. Primarily used in conjunction with iOS14's AppTrackingTransparency.framework. + /// + public AppTrackingStatus AppTrackingStatus { get; private set; } +#endif + + public bool IsTestModeEnabled { get; private set; } + + /// + /// Get the user's geography used to determine the type of consent flow shown to the user. + /// If no such determination could be made, will be returned. + /// + public ConsentFlowUserGeography ConsentFlowUserGeography { get; private set; } + + [Obsolete("This API has been deprecated and will be removed in a future release.")] + public ConsentDialogState ConsentDialogState { get; private set; } + +#if UNITY_EDITOR || !(UNITY_ANDROID || UNITY_IPHONE || UNITY_IOS) + public static SdkConfiguration CreateEmpty() + { + var sdkConfiguration = new SdkConfiguration(); + sdkConfiguration.IsSuccessfullyInitialized = true; +#pragma warning disable 0618 + sdkConfiguration.ConsentDialogState = ConsentDialogState.Unknown; +#pragma warning restore 0618 +#if UNITY_EDITOR + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Authorized; +#endif + var currentRegion = RegionInfo.CurrentRegion; + sdkConfiguration.CountryCode = currentRegion != null ? currentRegion.TwoLetterISORegionName : "US"; + sdkConfiguration.IsTestModeEnabled = false; + + return sdkConfiguration; + } +#endif + + public static SdkConfiguration Create(IDictionary eventProps) + { + var sdkConfiguration = new SdkConfiguration(); + + sdkConfiguration.IsSuccessfullyInitialized = MaxSdkUtils.GetBoolFromDictionary(eventProps, "isSuccessfullyInitialized"); + sdkConfiguration.CountryCode = MaxSdkUtils.GetStringFromDictionary(eventProps, "countryCode", ""); + sdkConfiguration.IsTestModeEnabled = MaxSdkUtils.GetBoolFromDictionary(eventProps, "isTestModeEnabled"); + + var consentFlowUserGeographyStr = MaxSdkUtils.GetStringFromDictionary(eventProps, "consentFlowUserGeography", ""); + if ("1".Equals(consentFlowUserGeographyStr)) + { + sdkConfiguration.ConsentFlowUserGeography = ConsentFlowUserGeography.Gdpr; + } + else if ("2".Equals(consentFlowUserGeographyStr)) + { + sdkConfiguration.ConsentFlowUserGeography = ConsentFlowUserGeography.Other; + } + else + { + sdkConfiguration.ConsentFlowUserGeography = ConsentFlowUserGeography.Unknown; + } + +#pragma warning disable 0618 + var consentDialogStateStr = MaxSdkUtils.GetStringFromDictionary(eventProps, "consentDialogState", ""); + if ("1".Equals(consentDialogStateStr)) + { + sdkConfiguration.ConsentDialogState = ConsentDialogState.Applies; + } + else if ("2".Equals(consentDialogStateStr)) + { + sdkConfiguration.ConsentDialogState = ConsentDialogState.DoesNotApply; + } + else + { + sdkConfiguration.ConsentDialogState = ConsentDialogState.Unknown; + } +#pragma warning restore 0618 + +#if UNITY_IPHONE || UNITY_IOS + var appTrackingStatusStr = MaxSdkUtils.GetStringFromDictionary(eventProps, "appTrackingStatus", "-1"); + if ("-1".Equals(appTrackingStatusStr)) + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Unavailable; + } + else if ("0".Equals(appTrackingStatusStr)) + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.NotDetermined; + } + else if ("1".Equals(appTrackingStatusStr)) + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Restricted; + } + else if ("2".Equals(appTrackingStatusStr)) + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Denied; + } + else // "3" is authorized + { + sdkConfiguration.AppTrackingStatus = AppTrackingStatus.Authorized; + } +#endif + + return sdkConfiguration; + } + } + + public struct Reward + { + public string Label; + public int Amount; + + public override string ToString() + { + return "Reward: " + Amount + " " + Label; + } + + public bool IsValid() + { + return !string.IsNullOrEmpty(Label) && Amount > 0; + } + } + + /** + * This enum contains various error codes that the SDK can return when a MAX ad fails to load or display. + */ + public enum ErrorCode + { + /// + /// This error code represents an error that could not be categorized into one of the other defined errors. See the message field in the error object for more details. + /// + Unspecified = -1, + + /// + /// This error code indicates that MAX returned no eligible ads from any mediated networks for this app/device. + /// + NoFill = 204, + + /// + /// This error code indicates that MAX returned eligible ads from mediated networks, but all ads failed to load. See the adLoadFailureInfo field in the error object for more details. + /// + AdLoadFailed = -5001, + + /// + /// This error code represents an error that was encountered when showing an ad. + /// + AdDisplayFailed = -4205, + + /// + /// This error code indicates that the ad request failed due to a generic network error. See the message field in the error object for more details. + /// + NetworkError = -1000, + + /// + /// This error code indicates that the ad request timed out due to a slow internet connection. + /// + NetworkTimeout = -1001, + + /// + /// This error code indicates that the ad request failed because the device is not connected to the internet. + /// + NoNetwork = -1009, + + /// + /// This error code indicates that you attempted to show a fullscreen ad while another fullscreen ad is still showing. + /// + FullscreenAdAlreadyShowing = -23, + + /// + /// This error code indicates you are attempting to show a fullscreen ad before the one has been loaded. + /// + FullscreenAdNotReady = -24, + +#if UNITY_IOS || UNITY_IPHONE + /// + /// This error code indicates you attempted to present a fullscreen ad from an invalid view controller. + /// + FullscreenAdInvalidViewController = -25, +#endif + + /// + /// This error code indicates you are attempting to load a fullscreen ad while another fullscreen ad is already loading. + /// + FullscreenAdAlreadyLoading = -26, + + /// + /// This error code indicates you are attempting to load a fullscreen ad while another fullscreen ad is still showing. + /// + FullscreenAdLoadWhileShowing = -27, + +#if UNITY_ANDROID + /// + /// This error code indicates that the SDK failed to display an ad because the user has the "Don't Keep Activities" developer setting enabled. + /// + DontKeepActivitiesEnabled = -5602, +#endif + + /// + /// This error code indicates that the SDK failed to load an ad because the publisher provided an invalid ad unit identifier. + /// Possible reasons for an invalid ad unit identifier: + /// 1. Ad unit identifier is malformed or does not exist + /// 2. Ad unit is disabled + /// 3. Ad unit is not associated with the current app's package name + /// 4. Ad unit was created within the last 30-60 minutes + /// + InvalidAdUnitId = -5603 + } + + /** + * This enum contains possible states of an ad in the waterfall the adapter response info could represent. + */ + public enum MaxAdLoadState + { + /// + /// The AppLovin Max SDK did not attempt to load an ad from this network in the waterfall because an ad higher + /// in the waterfall loaded successfully. + /// + AdLoadNotAttempted, + + /// + /// An ad successfully loaded from this network. + /// + AdLoaded, + + /// + /// An ad failed to load from this network. + /// + FailedToLoad + } + + public class AdInfo + { + public string AdUnitIdentifier { get; private set; } + public string AdFormat { get; private set; } + public string NetworkName { get; private set; } + public string NetworkPlacement { get; private set; } + public string Placement { get; private set; } + public string CreativeIdentifier { get; private set; } + public double Revenue { get; private set; } + public string RevenuePrecision { get; private set; } + public WaterfallInfo WaterfallInfo { get; private set; } + public long LatencyMillis { get; private set; } + public string DspName { get; private set; } + + public AdInfo(IDictionary adInfoDictionary) + { + AdUnitIdentifier = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "adUnitId"); + AdFormat = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "adFormat"); + NetworkName = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "networkName"); + NetworkPlacement = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "networkPlacement"); + CreativeIdentifier = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "creativeId"); + Placement = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "placement"); + Revenue = MaxSdkUtils.GetDoubleFromDictionary(adInfoDictionary, "revenue", -1); + RevenuePrecision = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "revenuePrecision"); + WaterfallInfo = new WaterfallInfo(MaxSdkUtils.GetDictionaryFromDictionary(adInfoDictionary, "waterfallInfo", new Dictionary())); + LatencyMillis = MaxSdkUtils.GetLongFromDictionary(adInfoDictionary, "latencyMillis"); + DspName = MaxSdkUtils.GetStringFromDictionary(adInfoDictionary, "dspName"); + } + + public override string ToString() + { + return "[AdInfo adUnitIdentifier: " + AdUnitIdentifier + + ", adFormat: " + AdFormat + + ", networkName: " + NetworkName + + ", networkPlacement: " + NetworkPlacement + + ", creativeIdentifier: " + CreativeIdentifier + + ", placement: " + Placement + + ", revenue: " + Revenue + + ", revenuePrecision: " + RevenuePrecision + + ", latency: " + LatencyMillis + + ", dspName: " + DspName + "]"; + } + } + + /// + /// Returns information about the ad response in a waterfall. + /// + public class WaterfallInfo + { + public String Name { get; private set; } + public String TestName { get; private set; } + public List NetworkResponses { get; private set; } + public long LatencyMillis { get; private set; } + + public WaterfallInfo(IDictionary waterfallInfoDict) + { + Name = MaxSdkUtils.GetStringFromDictionary(waterfallInfoDict, "name"); + TestName = MaxSdkUtils.GetStringFromDictionary(waterfallInfoDict, "testName"); + + var networkResponsesList = MaxSdkUtils.GetListFromDictionary(waterfallInfoDict, "networkResponses", new List()); + NetworkResponses = new List(); + foreach (var networkResponseObject in networkResponsesList) + { + var networkResponseDict = networkResponseObject as Dictionary; + if (networkResponseDict == null) continue; + + var networkResponse = new NetworkResponseInfo(networkResponseDict); + NetworkResponses.Add(networkResponse); + } + + LatencyMillis = MaxSdkUtils.GetLongFromDictionary(waterfallInfoDict, "latencyMillis"); + } + + public override string ToString() + { + return "[MediatedNetworkInfo: name = " + Name + + ", testName = " + TestName + + ", latency = " + LatencyMillis + + ", networkResponse = " + string.Join(", ", NetworkResponses.Select(networkResponseInfo => networkResponseInfo.ToString()).ToArray()) + "]"; + } + } + + public class NetworkResponseInfo + { + public MaxAdLoadState AdLoadState { get; private set; } + public MediatedNetworkInfo MediatedNetwork { get; private set; } + public Dictionary Credentials { get; private set; } + public bool IsBidding { get; private set; } + public long LatencyMillis { get; private set; } + public ErrorInfo Error { get; private set; } + + public NetworkResponseInfo(IDictionary networkResponseInfoDict) + { + var mediatedNetworkInfoDict = MaxSdkUtils.GetDictionaryFromDictionary(networkResponseInfoDict, "mediatedNetwork"); + MediatedNetwork = mediatedNetworkInfoDict != null ? new MediatedNetworkInfo(mediatedNetworkInfoDict) : null; + + Credentials = MaxSdkUtils.GetDictionaryFromDictionary(networkResponseInfoDict, "credentials", new Dictionary()); + IsBidding = MaxSdkUtils.GetBoolFromDictionary(networkResponseInfoDict, "isBidding"); + LatencyMillis = MaxSdkUtils.GetLongFromDictionary(networkResponseInfoDict, "latencyMillis"); + AdLoadState = (MaxAdLoadState) MaxSdkUtils.GetIntFromDictionary(networkResponseInfoDict, "adLoadState"); + + var errorInfoDict = MaxSdkUtils.GetDictionaryFromDictionary(networkResponseInfoDict, "error"); + Error = errorInfoDict != null ? new ErrorInfo(errorInfoDict) : null; + } + + public override string ToString() + { + var stringBuilder = new StringBuilder("[NetworkResponseInfo: adLoadState = ").Append(AdLoadState); + stringBuilder.Append(", mediatedNetwork = ").Append(MediatedNetwork); + stringBuilder.Append(", credentials = ").Append(string.Join(", ", Credentials.Select(keyValuePair => keyValuePair.ToString()).ToArray())); + + switch (AdLoadState) + { + case MaxAdLoadState.FailedToLoad: + stringBuilder.Append(", error = ").Append(Error); + break; + case MaxAdLoadState.AdLoaded: + stringBuilder.Append(", latency = ").Append(LatencyMillis); + break; + } + + return stringBuilder.Append("]").ToString(); + } + } + + public class MediatedNetworkInfo + { + public string Name { get; private set; } + public string AdapterClassName { get; private set; } + public string AdapterVersion { get; private set; } + public string SdkVersion { get; private set; } + + public MediatedNetworkInfo(IDictionary mediatedNetworkDictionary) + { + // NOTE: Unity Editor creates empty string + Name = MaxSdkUtils.GetStringFromDictionary(mediatedNetworkDictionary, "name", ""); + AdapterClassName = MaxSdkUtils.GetStringFromDictionary(mediatedNetworkDictionary, "adapterClassName", ""); + AdapterVersion = MaxSdkUtils.GetStringFromDictionary(mediatedNetworkDictionary, "adapterVersion", ""); + SdkVersion = MaxSdkUtils.GetStringFromDictionary(mediatedNetworkDictionary, "sdkVersion", ""); + } + + public override string ToString() + { + return "[MediatedNetworkInfo name: " + Name + + ", adapterClassName: " + AdapterClassName + + ", adapterVersion: " + AdapterVersion + + ", sdkVersion: " + SdkVersion + "]"; + } + } + + public class ErrorInfo + { + public ErrorCode Code { get; private set; } + public string Message { get; private set; } + public int MediatedNetworkErrorCode { get; private set; } + public string MediatedNetworkErrorMessage { get; private set; } + public string AdLoadFailureInfo { get; private set; } + public WaterfallInfo WaterfallInfo { get; private set; } + public long LatencyMillis { get; private set; } + + public ErrorInfo(IDictionary errorInfoDictionary) + { + Code = (ErrorCode) MaxSdkUtils.GetIntFromDictionary(errorInfoDictionary, "errorCode", -1); + Message = MaxSdkUtils.GetStringFromDictionary(errorInfoDictionary, "errorMessage", ""); + MediatedNetworkErrorCode = MaxSdkUtils.GetIntFromDictionary(errorInfoDictionary, "mediatedNetworkErrorCode", (int) ErrorCode.Unspecified); + MediatedNetworkErrorMessage = MaxSdkUtils.GetStringFromDictionary(errorInfoDictionary, "mediatedNetworkErrorMessage", ""); + AdLoadFailureInfo = MaxSdkUtils.GetStringFromDictionary(errorInfoDictionary, "adLoadFailureInfo", ""); + WaterfallInfo = new WaterfallInfo(MaxSdkUtils.GetDictionaryFromDictionary(errorInfoDictionary, "waterfallInfo", new Dictionary())); + LatencyMillis = MaxSdkUtils.GetLongFromDictionary(errorInfoDictionary, "latencyMillis"); + } + + public override string ToString() + { + var stringbuilder = new StringBuilder("[ErrorInfo code: ").Append(Code); + stringbuilder.Append(", message: ").Append(Message); + + if (Code == ErrorCode.AdDisplayFailed) + { + stringbuilder.Append(", mediatedNetworkCode: ").Append(MediatedNetworkErrorCode); + stringbuilder.Append(", mediatedNetworkMessage: ").Append(MediatedNetworkErrorMessage); + } + + stringbuilder.Append(", latency: ").Append(LatencyMillis); + return stringbuilder.Append(", adLoadFailureInfo: ").Append(AdLoadFailureInfo).Append("]").ToString(); + } + } + + /// + /// Inset values for the safe area on the screen used to render banner ads. + /// + public class SafeAreaInsets + { + public int Left { get; private set; } + public int Top { get; private set; } + public int Right { get; private set; } + public int Bottom { get; private set; } + + /// + /// Creates a new instance of . + /// + /// An integer array with insets values in the order of left, top, right, and bottom + internal SafeAreaInsets(int[] insets) + { + Left = insets[0]; + Top = insets[1]; + Right = insets[2]; + Bottom = insets[3]; + } + + public override string ToString() + { + return "[SafeAreaInsets: Left: " + Left + + ", Top: " + Top + + ", Right: " + Right + + ", Bottom: " + Bottom + "]"; + } + } + + /// + /// Determines whether ad events raised by the AppLovin's Unity plugin should be invoked on the Unity main thread. + /// + public static bool? InvokeEventsOnUnityMainThread { get; set; } + + /// + /// The CMP service, which provides direct APIs for interfacing with the Google-certified CMP installed, if any. + /// + public static MaxCmpService CmpService + { + get { return MaxCmpService.Instance; } + } + + protected static void ValidateAdUnitIdentifier(string adUnitIdentifier, string debugPurpose) + { + if (string.IsNullOrEmpty(adUnitIdentifier)) + { + MaxSdkLogger.UserError("No MAX Ads Ad Unit ID specified for: " + debugPurpose); + } + } + + // Allocate the MaxEventExecutor singleton which handles pushing callbacks from the background to the main thread. + protected static void InitializeEventExecutor() + { + MaxEventExecutor.InitializeIfNeeded(); + } + + /// + /// Generates serialized Unity meta data to be passed to the SDK. + /// + /// Serialized Unity meta data. + protected static string GenerateMetaData() + { + var metaData = new Dictionary(2); + metaData.Add("UnityVersion", Application.unityVersion); + + return Json.Serialize(metaData); + } + + /// + /// Parses the prop string provided to a . + /// + /// A prop string representing a Rect + /// A the prop string represents. + protected static Rect GetRectFromString(string rectPropString) + { + var rectDict = Json.Deserialize(rectPropString) as Dictionary; + var originX = MaxSdkUtils.GetFloatFromDictionary(rectDict, "origin_x", 0); + var originY = MaxSdkUtils.GetFloatFromDictionary(rectDict, "origin_y", 0); + var width = MaxSdkUtils.GetFloatFromDictionary(rectDict, "width", 0); + var height = MaxSdkUtils.GetFloatFromDictionary(rectDict, "height", 0); + + return new Rect(originX, originY, width, height); + } + + /// + /// Handles forwarding callbacks from native to C#. + /// + /// A prop string with the event data + protected static void HandleBackgroundCallback(string propsStr) + { + try + { + MaxSdkCallbacks.ForwardEvent(propsStr); + } + catch (Exception exception) + { + var eventProps = Json.Deserialize(propsStr) as Dictionary; + if (eventProps == null) return; + + var eventName = MaxSdkUtils.GetStringFromDictionary(eventProps, "name", ""); + MaxSdkLogger.UserError("Unable to notify ad delegate due to an error in the publisher callback '" + eventName + "' due to exception: " + exception.Message); + Debug.LogException(exception); + } + } + + protected static string SerializeLocalExtraParameterValue(object value) + { + if (!(value.GetType().IsPrimitive || value is string || value is IList || value is IDictionary)) + { + MaxSdkLogger.UserError("Local extra parameters must be an IList, IDictionary, string, or a primitive type"); + return ""; + } + + Dictionary data = new Dictionary + { + {"value", value} + }; + + return Json.Serialize(data); + } + + [Obsolete("This API has been deprecated and will be removed in a future release.")] + public enum ConsentDialogState + { + Unknown, + Applies, + DoesNotApply + } +} + +/// +/// An extension class for and enums. +/// +internal static class AdPositionExtenstion +{ + public static string ToSnakeCaseString(this MaxSdkBase.BannerPosition position) + { + if (position == MaxSdkBase.BannerPosition.TopLeft) + { + return "top_left"; + } + else if (position == MaxSdkBase.BannerPosition.TopCenter) + { + return "top_center"; + } + else if (position == MaxSdkBase.BannerPosition.TopRight) + { + return "top_right"; + } + else if (position == MaxSdkBase.BannerPosition.Centered) + { + return "centered"; + } + else if (position == MaxSdkBase.BannerPosition.CenterLeft) + { + return "center_left"; + } + else if (position == MaxSdkBase.BannerPosition.CenterRight) + { + return "center_right"; + } + else if (position == MaxSdkBase.BannerPosition.BottomLeft) + { + return "bottom_left"; + } + else if (position == MaxSdkBase.BannerPosition.BottomCenter) + { + return "bottom_center"; + } + else // position == MaxSdkBase.BannerPosition.BottomRight + { + return "bottom_right"; + } + } + + public static string ToSnakeCaseString(this MaxSdkBase.AdViewPosition position) + { + if (position == MaxSdkBase.AdViewPosition.TopLeft) + { + return "top_left"; + } + else if (position == MaxSdkBase.AdViewPosition.TopCenter) + { + return "top_center"; + } + else if (position == MaxSdkBase.AdViewPosition.TopRight) + { + return "top_right"; + } + else if (position == MaxSdkBase.AdViewPosition.Centered) + { + return "centered"; + } + else if (position == MaxSdkBase.AdViewPosition.CenterLeft) + { + return "center_left"; + } + else if (position == MaxSdkBase.AdViewPosition.CenterRight) + { + return "center_right"; + } + else if (position == MaxSdkBase.AdViewPosition.BottomLeft) + { + return "bottom_left"; + } + else if (position == MaxSdkBase.AdViewPosition.BottomCenter) + { + return "bottom_center"; + } + else // position == MaxSdkBase.AdViewPosition.BottomRight + { + return "bottom_right"; + } + } +} + +namespace AppLovinMax.Internal.API +{ + [Obsolete("This class has been deprecated and will be removed in a future SDK release.")] + public class CFError + { + public int Code { get; private set; } + + public string Message { get; private set; } + + public static CFError Create(int code = -1, string message = "") + { + return new CFError(code, message); + } + + private CFError(int code, string message) + { + Code = code; + Message = message; + } + + public override string ToString() + { + return "[CFError Code: " + Code + + ", Message: " + Message + "]"; + } + } + + [Obsolete("This enum has been deprecated. Please use `MaxSdk.GetSdkConfiguration().ConsentFlowUserGeography` instead.")] + public enum CFType + { + Unknown, + Standard, + Detailed + } + + public class CFService + { + [Obsolete("This property has been deprecated. Please use `MaxSdk.GetSdkConfiguration().ConsentFlowUserGeography` instead.")] + public static CFType CFType + { + get + { + switch (MaxSdk.GetSdkConfiguration().ConsentFlowUserGeography) + { + case MaxSdkBase.ConsentFlowUserGeography.Unknown: + return CFType.Unknown; + case MaxSdkBase.ConsentFlowUserGeography.Gdpr: + return CFType.Detailed; + case MaxSdkBase.ConsentFlowUserGeography.Other: + return CFType.Standard; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + + [Obsolete("This method has been deprecated. Please use `MaxSdk.CmpService.ShowCmpForExistingUser` instead.")] + public static void SCF(Action onFlowCompletedAction) + { + MaxSdkBase.CmpService.ShowCmpForExistingUser(error => + { + if (onFlowCompletedAction == null) return; + + var cfError = error == null ? null : CFError.Create((int) error.Code, error.Message); + onFlowCompletedAction(cfError); + }); + } + } +} diff --git a/Assets/MaxSdk/Scripts/MaxSdkBase.cs.meta b/Assets/MaxSdk/Scripts/MaxSdkBase.cs.meta new file mode 100644 index 0000000..f27f769 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkBase.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 893e4e55a7e394274957f1034f7afc45 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdkBase.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs b/Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs new file mode 100644 index 0000000..d2e3522 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs @@ -0,0 +1,1737 @@ +/** + * This is is a global Unity object that is used to forward callbacks from native iOS / Android Max code to the application. + */ + +using System; +using System.Collections.Generic; +using System.Globalization; +using UnityEngine; +using AppLovinMax.ThirdParty.MiniJson; +using AppLovinMax.Internal; + +public static class MaxSdkCallbacks +{ + // Fired when the SDK has finished initializing + private static Action _onSdkInitializedEvent; + public static event Action OnSdkInitializedEvent + { + add + { + LogSubscribedToEvent("OnSdkInitializedEvent"); + _onSdkInitializedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnSdkInitializedEvent"); + _onSdkInitializedEvent -= value; + } + } + + // Fire when the Consent Dialog has been dismissed. + private static Action _onSdkConsentDialogDismissedEvent; + public static event Action OnSdkConsentDialogDismissedEvent + { + add + { + LogSubscribedToEvent("OnSdkConsentDialogDismissedEvent"); + _onSdkConsentDialogDismissedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnSdkConsentDialogDismissedEvent"); + _onSdkConsentDialogDismissedEvent -= value; + } + } + + private static Action _onApplicationStateChangedEvent; + /// + /// Fired when the application is paused or resumed. + /// + public static event Action OnApplicationStateChangedEvent + { + add + { + LogSubscribedToEvent("OnApplicationStateChangedEvent"); + _onApplicationStateChangedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnApplicationStateChangedEvent"); + _onApplicationStateChangedEvent -= value; + } + } + + private static Action _onInterstitialAdLoadedEventV2; + private static Action _onInterstitialAdLoadFailedEventV2; + private static Action _onInterstitialAdDisplayedEventV2; + private static Action _onInterstitialAdFailedToDisplayEventV2; + private static Action _onInterstitialAdClickedEventV2; + private static Action _onInterstitialAdRevenuePaidEvent; + private static Action _onInterstitialAdReviewCreativeIdGeneratedEvent; + private static Action _onInterstitialAdHiddenEventV2; + + public class Interstitial + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdLoadedEvent"); + _onInterstitialAdLoadedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdLoadedEvent"); + _onInterstitialAdLoadedEventV2 -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdLoadFailedEvent"); + _onInterstitialAdLoadFailedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdLoadFailedEvent"); + _onInterstitialAdLoadFailedEventV2 -= value; + } + } + + /** + * Fired when an interstitial ad is displayed (may not be received by Unity until the interstitial ad closes). + */ + public static event Action OnAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdDisplayedEvent"); + _onInterstitialAdDisplayedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdDisplayedEvent"); + _onInterstitialAdDisplayedEventV2 -= value; + } + } + + public static event Action OnAdDisplayFailedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdDisplayFailedEvent"); + _onInterstitialAdFailedToDisplayEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdDisplayFailedEvent"); + _onInterstitialAdFailedToDisplayEventV2 -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdClickedEvent"); + _onInterstitialAdClickedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdClickedEvent"); + _onInterstitialAdClickedEventV2 -= value; + } + } + + /// + /// Fired when an interstitial ad impression was validated and revenue will be paid. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdRevenuePaidEvent"); + _onInterstitialAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdRevenuePaidEvent"); + _onInterstitialAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdReviewCreativeIdGeneratedEvent"); + _onInterstitialAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdReviewCreativeIdGeneratedEvent"); + _onInterstitialAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdHiddenEvent"); + _onInterstitialAdHiddenEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdHiddenEvent"); + _onInterstitialAdHiddenEventV2 -= value; + } + } + } + + private static Action _onAppOpenAdLoadedEvent; + private static Action _onAppOpenAdLoadFailedEvent; + private static Action _onAppOpenAdDisplayedEvent; + private static Action _onAppOpenAdFailedToDisplayEvent; + private static Action _onAppOpenAdClickedEvent; + private static Action _onAppOpenAdRevenuePaidEvent; + private static Action _onAppOpenAdHiddenEvent; + + public class AppOpen + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdLoadedEvent"); + _onAppOpenAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdLoadedEvent"); + _onAppOpenAdLoadedEvent -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdLoadFailedEvent"); + _onAppOpenAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdLoadFailedEvent"); + _onAppOpenAdLoadFailedEvent -= value; + } + } + + /** + * Fired when an app open ad is displayed (may not be received by Unity until the app open ad closes). + */ + public static event Action OnAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdDisplayedEvent"); + _onAppOpenAdDisplayedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdDisplayedEvent"); + _onAppOpenAdDisplayedEvent -= value; + } + } + + public static event Action OnAdDisplayFailedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdDisplayFailedEvent"); + _onAppOpenAdFailedToDisplayEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdDisplayFailedEvent"); + _onAppOpenAdFailedToDisplayEvent -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdClickedEvent"); + _onAppOpenAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdClickedEvent"); + _onAppOpenAdClickedEvent -= value; + } + } + + /// + /// Fired when an app open ad impression was validated and revenue will be paid. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdRevenuePaidEvent"); + _onAppOpenAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdRevenuePaidEvent"); + _onAppOpenAdRevenuePaidEvent -= value; + } + } + + public static event Action OnAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnAppOpenAdHiddenEvent"); + _onAppOpenAdHiddenEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnAppOpenAdHiddenEvent"); + _onAppOpenAdHiddenEvent -= value; + } + } + } + + private static Action _onRewardedAdLoadedEventV2; + private static Action _onRewardedAdLoadFailedEventV2; + private static Action _onRewardedAdDisplayedEventV2; + private static Action _onRewardedAdFailedToDisplayEventV2; + private static Action _onRewardedAdClickedEventV2; + private static Action _onRewardedAdRevenuePaidEvent; + private static Action _onRewardedAdReviewCreativeIdGeneratedEvent; + private static Action _onRewardedAdReceivedRewardEventV2; + private static Action _onRewardedAdHiddenEventV2; + + public class Rewarded + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdLoadedEvent"); + _onRewardedAdLoadedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdLoadedEvent"); + _onRewardedAdLoadedEventV2 -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdLoadFailedEvent"); + _onRewardedAdLoadFailedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdLoadFailedEvent"); + _onRewardedAdLoadFailedEventV2 -= value; + } + } + + /** + * Fired when a rewarded ad is displayed (may not be received by Unity until the rewarded ad closes). + */ + public static event Action OnAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdDisplayedEvent"); + _onRewardedAdDisplayedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdDisplayedEvent"); + _onRewardedAdDisplayedEventV2 -= value; + } + } + + public static event Action OnAdDisplayFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdDisplayFailedEvent"); + _onRewardedAdFailedToDisplayEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdDisplayFailedEvent"); + _onRewardedAdFailedToDisplayEventV2 -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdClickedEvent"); + _onRewardedAdClickedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdClickedEvent"); + _onRewardedAdClickedEventV2 -= value; + } + } + + /// + /// Fired when a rewarded ad impression was validated and revenue will be paid. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdRevenuePaidEvent"); + _onRewardedAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdRevenuePaidEvent"); + _onRewardedAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdReviewCreativeIdGeneratedEvent"); + _onRewardedAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdReviewCreativeIdGeneratedEvent"); + _onRewardedAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdReceivedRewardEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdReceivedRewardEvent"); + _onRewardedAdReceivedRewardEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdReceivedRewardEvent"); + _onRewardedAdReceivedRewardEventV2 -= value; + } + } + + public static event Action OnAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdHiddenEvent"); + _onRewardedAdHiddenEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdHiddenEvent"); + _onRewardedAdHiddenEventV2 -= value; + } + } + } + + private static Action _onRewardedInterstitialAdLoadedEvent; + private static Action _onRewardedInterstitialAdLoadFailedEvent; + private static Action _onRewardedInterstitialAdDisplayedEvent; + private static Action _onRewardedInterstitialAdFailedToDisplayEvent; + private static Action _onRewardedInterstitialAdClickedEvent; + private static Action _onRewardedInterstitialAdRevenuePaidEvent; + private static Action _onRewardedInterstitialAdReviewCreativeIdGeneratedEvent; + private static Action _onRewardedInterstitialAdReceivedRewardEvent; + private static Action _onRewardedInterstitialAdHiddenEvent; + + public class RewardedInterstitial + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdLoadedEvent"); + _onRewardedInterstitialAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdLoadedEvent"); + _onRewardedInterstitialAdLoadedEvent -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdLoadFailedEvent"); + _onRewardedInterstitialAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdLoadFailedEvent"); + _onRewardedInterstitialAdLoadFailedEvent -= value; + } + } + + /** + * Fired when a rewarded interstitial ad is displayed (may not be received by Unity until + * the rewarded interstitial ad closes). + */ + public static event Action OnAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdDisplayedEvent"); + _onRewardedInterstitialAdDisplayedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdDisplayedEvent"); + _onRewardedInterstitialAdDisplayedEvent -= value; + } + } + + public static event Action OnAdDisplayFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdDisplayFailedEvent"); + _onRewardedInterstitialAdFailedToDisplayEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdDisplayFailedEvent"); + _onRewardedInterstitialAdFailedToDisplayEvent -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdClickedEvent"); + _onRewardedInterstitialAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdClickedEvent"); + _onRewardedInterstitialAdClickedEvent -= value; + } + } + + /// + /// Fired when a rewarded interstitial ad impression was validated and revenue will be paid. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdRevenuePaidEvent"); + _onRewardedInterstitialAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdRevenuePaidEvent"); + _onRewardedInterstitialAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// Executed on a background thread to avoid any delays in execution. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdReviewCreativeIdGeneratedEvent"); + _onRewardedInterstitialAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdReviewCreativeIdGeneratedEvent"); + _onRewardedInterstitialAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdReceivedRewardEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdReceivedRewardEvent"); + _onRewardedInterstitialAdReceivedRewardEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdReceivedRewardEvent"); + _onRewardedInterstitialAdReceivedRewardEvent -= value; + } + } + + public static event Action OnAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnRewardedInterstitialAdHiddenEvent"); + _onRewardedInterstitialAdHiddenEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedInterstitialAdHiddenEvent"); + _onRewardedInterstitialAdHiddenEvent -= value; + } + } + } + + private static Action _onBannerAdLoadedEventV2; + private static Action _onBannerAdLoadFailedEventV2; + private static Action _onBannerAdClickedEventV2; + private static Action _onBannerAdRevenuePaidEvent; + private static Action _onBannerAdReviewCreativeIdGeneratedEvent; + private static Action _onBannerAdExpandedEventV2; + private static Action _onBannerAdCollapsedEventV2; + + public class Banner + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdLoadedEvent"); + _onBannerAdLoadedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdLoadedEvent"); + _onBannerAdLoadedEventV2 -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdLoadFailedEvent"); + _onBannerAdLoadFailedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdLoadFailedEvent"); + _onBannerAdLoadFailedEventV2 -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdClickedEvent"); + _onBannerAdClickedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdClickedEvent"); + _onBannerAdClickedEventV2 -= value; + } + } + + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnBannerAdRevenuePaidEvent"); + _onBannerAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdRevenuePaidEvent"); + _onBannerAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdReviewCreativeIdGeneratedEvent"); + _onBannerAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdReviewCreativeIdGeneratedEvent"); + _onBannerAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdExpandedEvent"); + _onBannerAdExpandedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdExpandedEvent"); + _onBannerAdExpandedEventV2 -= value; + } + } + + public static event Action OnAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdCollapsedEvent"); + _onBannerAdCollapsedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdCollapsedEvent"); + _onBannerAdCollapsedEventV2 -= value; + } + } + } + + private static Action _onMRecAdLoadedEventV2; + private static Action _onMRecAdLoadFailedEventV2; + private static Action _onMRecAdClickedEventV2; + private static Action _onMRecAdRevenuePaidEvent; + private static Action _onMRecAdReviewCreativeIdGeneratedEvent; + private static Action _onMRecAdExpandedEventV2; + private static Action _onMRecAdCollapsedEventV2; + + public class MRec + { + public static event Action OnAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdLoadedEvent"); + _onMRecAdLoadedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdLoadedEvent"); + _onMRecAdLoadedEventV2 -= value; + } + } + + public static event Action OnAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdLoadFailedEvent"); + _onMRecAdLoadFailedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdLoadFailedEvent"); + _onMRecAdLoadFailedEventV2 -= value; + } + } + + public static event Action OnAdClickedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdClickedEvent"); + _onMRecAdClickedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdClickedEvent"); + _onMRecAdClickedEventV2 -= value; + } + } + + public static event Action OnAdRevenuePaidEvent + { + add + { + LogSubscribedToEvent("OnMRecAdRevenuePaidEvent"); + _onMRecAdRevenuePaidEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdRevenuePaidEvent"); + _onMRecAdRevenuePaidEvent -= value; + } + } + + /// + /// Fired when an Ad Review Creative ID has been generated. + /// The parameters returned are the adUnitIdentifier, adReviewCreativeId, and adInfo in that respective order. + /// + public static event Action OnAdReviewCreativeIdGeneratedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdReviewCreativeIdGeneratedEvent"); + _onMRecAdReviewCreativeIdGeneratedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdReviewCreativeIdGeneratedEvent"); + _onMRecAdReviewCreativeIdGeneratedEvent -= value; + } + } + + public static event Action OnAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdExpandedEvent"); + _onMRecAdExpandedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdExpandedEvent"); + _onMRecAdExpandedEventV2 -= value; + } + } + + public static event Action OnAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdCollapsedEvent"); + _onMRecAdCollapsedEventV2 += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdCollapsedEvent"); + _onMRecAdCollapsedEventV2 -= value; + } + } + } + + private static Action _onBannerAdLoadedEvent; + private static Action _onBannerAdLoadFailedEvent; + private static Action _onBannerAdClickedEvent; + private static Action _onBannerAdExpandedEvent; + private static Action _onBannerAdCollapsedEvent; + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdLoadedEvent` instead.")] + public static event Action OnBannerAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdLoadedEvent"); + _onBannerAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdLoadedEvent"); + _onBannerAdLoadedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdLoadFailedEvent` instead.")] + public static event Action OnBannerAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdLoadFailedEvent"); + _onBannerAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdLoadFailedEvent"); + _onBannerAdLoadFailedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdClickedEvent` instead.")] + public static event Action OnBannerAdClickedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdClickedEvent"); + _onBannerAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdClickedEvent"); + _onBannerAdClickedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdExpandedEvent` instead.")] + public static event Action OnBannerAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdExpandedEvent"); + _onBannerAdExpandedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdExpandedEvent"); + _onBannerAdExpandedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Banner.OnAdCollapsedEvent` instead.")] + public static event Action OnBannerAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnBannerAdCollapsedEvent"); + _onBannerAdCollapsedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnBannerAdCollapsedEvent"); + _onBannerAdCollapsedEvent -= value; + } + } + + private static Action _onMRecAdLoadedEvent; + private static Action _onMRecAdLoadFailedEvent; + private static Action _onMRecAdClickedEvent; + private static Action _onMRecAdExpandedEvent; + private static Action _onMRecAdCollapsedEvent; + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdLoadedEvent` instead.")] + public static event Action OnMRecAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdLoadedEvent"); + _onMRecAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdLoadedEvent"); + _onMRecAdLoadedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdLoadFailedEvent` instead.")] + public static event Action OnMRecAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdLoadFailedEvent"); + _onMRecAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdLoadFailedEvent"); + _onMRecAdLoadFailedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdClickedEvent` instead.")] + public static event Action OnMRecAdClickedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdClickedEvent"); + _onMRecAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdClickedEvent"); + _onMRecAdClickedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdExpandedEvent` instead.")] + public static event Action OnMRecAdExpandedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdExpandedEvent"); + _onMRecAdExpandedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdExpandedEvent"); + _onMRecAdExpandedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.MRec.OnAdCollapsedEvent` instead.")] + public static event Action OnMRecAdCollapsedEvent + { + add + { + LogSubscribedToEvent("OnMRecAdCollapsedEvent"); + _onMRecAdCollapsedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnMRecAdCollapsedEvent"); + _onMRecAdCollapsedEvent -= value; + } + } + + private static Action _onInterstitialAdLoadedEvent; + private static Action _onInterstitialLoadFailedEvent; + private static Action _onInterstitialAdDisplayedEvent; + private static Action _onInterstitialAdFailedToDisplayEvent; + private static Action _onInterstitialAdClickedEvent; + private static Action _onInterstitialAdHiddenEvent; + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdLoadedEvent` instead.")] + public static event Action OnInterstitialLoadedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialLoadedEvent"); + _onInterstitialAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialLoadedEvent"); + _onInterstitialAdLoadedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent` instead.")] + public static event Action OnInterstitialLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialLoadFailedEvent"); + _onInterstitialLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialLoadFailedEvent"); + _onInterstitialLoadFailedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdHiddenEvent` instead.")] + public static event Action OnInterstitialHiddenEvent + { + add + { + LogSubscribedToEvent("OnInterstitialHiddenEvent"); + _onInterstitialAdHiddenEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialHiddenEvent"); + _onInterstitialAdHiddenEvent -= value; + } + } + + // Fired when an interstitial ad is displayed (may not be received by Unity until the interstitial closes) + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent` instead.")] + public static event Action OnInterstitialDisplayedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialDisplayedEvent"); + _onInterstitialAdDisplayedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialDisplayedEvent"); + _onInterstitialAdDisplayedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdDisplayFailedEvent` instead.")] + public static event Action OnInterstitialAdFailedToDisplayEvent + { + add + { + LogSubscribedToEvent("OnInterstitialAdFailedToDisplayEvent"); + _onInterstitialAdFailedToDisplayEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialAdFailedToDisplayEvent"); + _onInterstitialAdFailedToDisplayEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Interstitial.OnAdClickedEvent` instead.")] + public static event Action OnInterstitialClickedEvent + { + add + { + LogSubscribedToEvent("OnInterstitialClickedEvent"); + _onInterstitialAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnInterstitialClickedEvent"); + _onInterstitialAdClickedEvent -= value; + } + } + + private static Action _onRewardedAdLoadedEvent; + private static Action _onRewardedAdLoadFailedEvent; + private static Action _onRewardedAdDisplayedEvent; + private static Action _onRewardedAdFailedToDisplayEvent; + private static Action _onRewardedAdClickedEvent; + private static Action _onRewardedAdReceivedRewardEvent; + private static Action _onRewardedAdHiddenEvent; + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdLoadedEvent` instead.")] + public static event Action OnRewardedAdLoadedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdLoadedEvent"); + _onRewardedAdLoadedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdLoadedEvent"); + _onRewardedAdLoadedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent` instead.")] + public static event Action OnRewardedAdLoadFailedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdLoadFailedEvent"); + _onRewardedAdLoadFailedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdLoadFailedEvent"); + _onRewardedAdLoadFailedEvent -= value; + } + } + + // Fired when an rewarded ad is displayed (may not be received by Unity until the rewarded ad closes) + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdDisplayedEvent` instead.")] + public static event Action OnRewardedAdDisplayedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdDisplayedEvent"); + _onRewardedAdDisplayedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdDisplayedEvent"); + _onRewardedAdDisplayedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdHiddenEvent` instead.")] + public static event Action OnRewardedAdHiddenEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdHiddenEvent"); + _onRewardedAdHiddenEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdHiddenEvent"); + _onRewardedAdHiddenEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdClickedEvent` instead.")] + public static event Action OnRewardedAdClickedEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdClickedEvent"); + _onRewardedAdClickedEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdClickedEvent"); + _onRewardedAdClickedEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdDisplayFailedEvent` instead.")] + public static event Action OnRewardedAdFailedToDisplayEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdFailedToDisplayEvent"); + _onRewardedAdFailedToDisplayEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdFailedToDisplayEvent"); + _onRewardedAdFailedToDisplayEvent -= value; + } + } + + [Obsolete("This callback has been deprecated. Please use `MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent` instead.")] + public static event Action OnRewardedAdReceivedRewardEvent + { + add + { + LogSubscribedToEvent("OnRewardedAdReceivedRewardEvent"); + _onRewardedAdReceivedRewardEvent += value; + } + remove + { + LogUnsubscribedToEvent("OnRewardedAdReceivedRewardEvent"); + _onRewardedAdReceivedRewardEvent -= value; + } + } + + public static void ForwardEvent(string eventPropsStr) + { + var eventProps = Json.Deserialize(eventPropsStr) as Dictionary; + if (eventProps == null) + { + MaxSdkLogger.E("Failed to forward event due to invalid event data"); + return; + } + + var keepInBackground = MaxSdkUtils.GetBoolFromDictionary(eventProps, "keepInBackground", false); + var eventName = MaxSdkUtils.GetStringFromDictionary(eventProps, "name", ""); + if (eventName == "OnInitialCallbackEvent") + { + MaxSdkLogger.D("Initial background callback."); + } + else if (eventName == "OnSdkInitializedEvent") + { + var sdkConfiguration = MaxSdkBase.SdkConfiguration.Create(eventProps); + InvokeEvent(_onSdkInitializedEvent, sdkConfiguration, eventName, keepInBackground); + } + else if (eventName == "OnSdkConsentDialogDismissedEvent") + { + InvokeEvent(_onSdkConsentDialogDismissedEvent, eventName, keepInBackground); + } + else if (eventName == "OnCmpCompletedEvent") + { + var errorProps = MaxSdkUtils.GetDictionaryFromDictionary(eventProps, "error"); + MaxCmpService.NotifyCompletedIfNeeded(errorProps); + } + else if (eventName == "OnApplicationStateChanged") + { + var isPaused = MaxSdkUtils.GetBoolFromDictionary(eventProps, "isPaused"); + InvokeEvent(_onApplicationStateChangedEvent, isPaused, eventName, keepInBackground); + } + // Ad Events + else + { + var adInfo = new MaxSdkBase.AdInfo(eventProps); + var adUnitIdentifier = MaxSdkUtils.GetStringFromDictionary(eventProps, "adUnitId", ""); + if (eventName == "OnBannerAdLoadedEvent") + { + InvokeEvent(_onBannerAdLoadedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onBannerAdLoadedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnBannerAdLoadFailedEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onBannerAdLoadFailedEvent, adUnitIdentifier, errorCode, eventName, keepInBackground); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onBannerAdLoadFailedEventV2, adUnitIdentifier, errorInfo, eventName, keepInBackground); + } + else if (eventName == "OnBannerAdClickedEvent") + { + InvokeEvent(_onBannerAdClickedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onBannerAdClickedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnBannerAdRevenuePaidEvent") + { + InvokeEvent(_onBannerAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnBannerAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onBannerAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnBannerAdExpandedEvent") + { + InvokeEvent(_onBannerAdExpandedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onBannerAdExpandedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnBannerAdCollapsedEvent") + { + InvokeEvent(_onBannerAdCollapsedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onBannerAdCollapsedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnMRecAdLoadedEvent") + { + InvokeEvent(_onMRecAdLoadedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onMRecAdLoadedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnMRecAdLoadFailedEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onMRecAdLoadFailedEvent, adUnitIdentifier, errorCode, eventName, keepInBackground); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onMRecAdLoadFailedEventV2, adUnitIdentifier, errorInfo, eventName, keepInBackground); + } + else if (eventName == "OnMRecAdClickedEvent") + { + InvokeEvent(_onMRecAdClickedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onMRecAdClickedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnMRecAdRevenuePaidEvent") + { + InvokeEvent(_onMRecAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnMRecAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onMRecAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnMRecAdExpandedEvent") + { + InvokeEvent(_onMRecAdExpandedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onMRecAdExpandedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnMRecAdCollapsedEvent") + { + InvokeEvent(_onMRecAdCollapsedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onMRecAdCollapsedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnInterstitialLoadedEvent") + { + InvokeEvent(_onInterstitialAdLoadedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onInterstitialAdLoadedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnInterstitialLoadFailedEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onInterstitialLoadFailedEvent, adUnitIdentifier, errorCode, eventName, keepInBackground); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onInterstitialAdLoadFailedEventV2, adUnitIdentifier, errorInfo, eventName, keepInBackground); + } + else if (eventName == "OnInterstitialHiddenEvent") + { + InvokeEvent(_onInterstitialAdHiddenEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onInterstitialAdHiddenEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnInterstitialDisplayedEvent") + { + InvokeEvent(_onInterstitialAdDisplayedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onInterstitialAdDisplayedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnInterstitialAdFailedToDisplayEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onInterstitialAdFailedToDisplayEvent, adUnitIdentifier, errorCode, eventName, keepInBackground); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onInterstitialAdFailedToDisplayEventV2, adUnitIdentifier, errorInfo, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnInterstitialClickedEvent") + { + InvokeEvent(_onInterstitialAdClickedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onInterstitialAdClickedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnInterstitialAdRevenuePaidEvent") + { + InvokeEvent(_onInterstitialAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnInterstitialAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onInterstitialAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnAppOpenAdLoadedEvent") + { + InvokeEvent(_onAppOpenAdLoadedEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnAppOpenAdLoadFailedEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onAppOpenAdLoadFailedEvent, adUnitIdentifier, errorInfo, eventName, keepInBackground); + } + else if (eventName == "OnAppOpenAdHiddenEvent") + { + InvokeEvent(_onAppOpenAdHiddenEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnAppOpenAdDisplayedEvent") + { + InvokeEvent(_onAppOpenAdDisplayedEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnAppOpenAdFailedToDisplayEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onAppOpenAdFailedToDisplayEvent, adUnitIdentifier, errorInfo, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnAppOpenAdClickedEvent") + { + InvokeEvent(_onAppOpenAdClickedEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnAppOpenAdRevenuePaidEvent") + { + InvokeEvent(_onAppOpenAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdLoadedEvent") + { + InvokeEvent(_onRewardedAdLoadedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onRewardedAdLoadedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdLoadFailedEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onRewardedAdLoadFailedEvent, adUnitIdentifier, errorCode, eventName, keepInBackground); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onRewardedAdLoadFailedEventV2, adUnitIdentifier, errorInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdDisplayedEvent") + { + InvokeEvent(_onRewardedAdDisplayedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onRewardedAdDisplayedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdHiddenEvent") + { + InvokeEvent(_onRewardedAdHiddenEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onRewardedAdHiddenEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdClickedEvent") + { + InvokeEvent(_onRewardedAdClickedEvent, adUnitIdentifier, eventName, keepInBackground); + InvokeEvent(_onRewardedAdClickedEventV2, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdRevenuePaidEvent") + { + InvokeEvent(_onRewardedAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onRewardedAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdFailedToDisplayEvent") + { + var errorCode = MaxSdkUtils.GetIntFromDictionary(eventProps, "errorCode", -1); + InvokeEvent(_onRewardedAdFailedToDisplayEvent, adUnitIdentifier, errorCode, eventName, keepInBackground); + + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + InvokeEvent(_onRewardedAdFailedToDisplayEventV2, adUnitIdentifier, errorInfo, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedAdReceivedRewardEvent") + { + var reward = new MaxSdkBase.Reward + { + Label = MaxSdkUtils.GetStringFromDictionary(eventProps, "rewardLabel", ""), + Amount = MaxSdkUtils.GetIntFromDictionary(eventProps, "rewardAmount", 0) + }; + + InvokeEvent(_onRewardedAdReceivedRewardEvent, adUnitIdentifier, reward, eventName, keepInBackground); + InvokeEvent(_onRewardedAdReceivedRewardEventV2, adUnitIdentifier, reward, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdLoadedEvent") + { + InvokeEvent(_onRewardedInterstitialAdLoadedEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdLoadFailedEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + + InvokeEvent(_onRewardedInterstitialAdLoadFailedEvent, adUnitIdentifier, errorInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdDisplayedEvent") + { + InvokeEvent(_onRewardedInterstitialAdDisplayedEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdHiddenEvent") + { + InvokeEvent(_onRewardedInterstitialAdHiddenEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdClickedEvent") + { + InvokeEvent(_onRewardedInterstitialAdClickedEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdRevenuePaidEvent") + { + InvokeEvent(_onRewardedInterstitialAdRevenuePaidEvent, adUnitIdentifier, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdReviewCreativeIdGeneratedEvent") + { + var adReviewCreativeId = MaxSdkUtils.GetStringFromDictionary(eventProps, "adReviewCreativeId", ""); + InvokeEvent(_onRewardedInterstitialAdReviewCreativeIdGeneratedEvent, adUnitIdentifier, adReviewCreativeId, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdFailedToDisplayEvent") + { + var errorInfo = new MaxSdkBase.ErrorInfo(eventProps); + + InvokeEvent(_onRewardedInterstitialAdFailedToDisplayEvent, adUnitIdentifier, errorInfo, adInfo, eventName, keepInBackground); + } + else if (eventName == "OnRewardedInterstitialAdReceivedRewardEvent") + { + var reward = new MaxSdkBase.Reward + { + Label = MaxSdkUtils.GetStringFromDictionary(eventProps, "rewardLabel", ""), + Amount = MaxSdkUtils.GetIntFromDictionary(eventProps, "rewardAmount", 0) + }; + + InvokeEvent(_onRewardedInterstitialAdReceivedRewardEvent, adUnitIdentifier, reward, adInfo, eventName, keepInBackground); + } + else + { + MaxSdkLogger.UserWarning("Unknown MAX Ads event fired: " + eventName); + } + } + } + +#if UNITY_EDITOR + public static void EmitSdkInitializedEvent() + { + if (_onSdkInitializedEvent == null) return; + + _onSdkInitializedEvent(MaxSdkBase.SdkConfiguration.CreateEmpty()); + } +#endif + + private static void InvokeEvent(Action evt, string eventName, bool keepInBackground) + { + if (!CanInvokeEvent(evt)) return; + + MaxSdkLogger.UserDebug("Invoking event: " + eventName); + if (ShouldInvokeInBackground(keepInBackground)) + { + try + { + evt(); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Caught exception in publisher event: " + eventName + ", exception: " + exception); + Debug.LogException(exception); + } + } + else + { + MaxEventExecutor.ExecuteOnMainThread(evt, eventName); + } + } + + private static void InvokeEvent(Action evt, T param, string eventName, bool keepInBackground) + { + if (!CanInvokeEvent(evt)) return; + + MaxSdkLogger.UserDebug("Invoking event: " + eventName + ". Param: " + param); + if (ShouldInvokeInBackground(keepInBackground)) + { + try + { + evt(param); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Caught exception in publisher event: " + eventName + ", exception: " + exception); + Debug.LogException(exception); + } + } + else + { + MaxEventExecutor.ExecuteOnMainThread(() => evt(param), eventName); + } + } + + private static void InvokeEvent(Action evt, T1 param1, T2 param2, string eventName, bool keepInBackground) + { + if (!CanInvokeEvent(evt)) return; + + MaxSdkLogger.UserDebug("Invoking event: " + eventName + ". Params: " + param1 + ", " + param2); + if (ShouldInvokeInBackground(keepInBackground)) + { + try + { + evt(param1, param2); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Caught exception in publisher event: " + eventName + ", exception: " + exception); + Debug.LogException(exception); + } + } + else + { + MaxEventExecutor.ExecuteOnMainThread(() => evt(param1, param2), eventName); + } + } + + private static void InvokeEvent(Action evt, T1 param1, T2 param2, T3 param3, string eventName, bool keepInBackground) + { + if (!CanInvokeEvent(evt)) return; + + MaxSdkLogger.UserDebug("Invoking event: " + eventName + ". Params: " + param1 + ", " + param2 + ", " + param3); + if (ShouldInvokeInBackground(keepInBackground)) + { + try + { + evt(param1, param2, param3); + } + catch (Exception exception) + { + MaxSdkLogger.UserError("Caught exception in publisher event: " + eventName + ", exception: " + exception); + Debug.LogException(exception); + } + } + else + { + MaxEventExecutor.ExecuteOnMainThread(() => evt(param1, param2, param3), eventName); + } + } + + private static bool CanInvokeEvent(Delegate evt) + { + if (evt == null) return false; + + // Check that publisher is not over-subscribing + if (evt.GetInvocationList().Length > 5) + { + MaxSdkLogger.UserWarning("Ads Event (" + evt + ") has over 5 subscribers. Please make sure you are properly un-subscribing to actions!!!"); + } + + return true; + } + + private static bool ShouldInvokeInBackground(bool keepInBackground) + { + return MaxSdkBase.InvokeEventsOnUnityMainThread == null ? keepInBackground : !MaxSdkBase.InvokeEventsOnUnityMainThread.Value; + } + + private static void LogSubscribedToEvent(string eventName) + { + MaxSdkLogger.D("Listener has been added to callback: " + eventName); + } + + private static void LogUnsubscribedToEvent(string eventName) + { + MaxSdkLogger.D("Listener has been removed from callback: " + eventName); + } + +#if UNITY_EDITOR && UNITY_2019_2_OR_NEWER + /// + /// Resets static event handlers so they still get reset even if Domain Reloading is disabled + /// + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] + private static void ResetOnDomainReload() + { + _onSdkInitializedEvent = null; + _onSdkConsentDialogDismissedEvent = null; + + _onInterstitialAdLoadedEventV2 = null; + _onInterstitialAdLoadFailedEventV2 = null; + _onInterstitialAdDisplayedEventV2 = null; + _onInterstitialAdFailedToDisplayEventV2 = null; + _onInterstitialAdClickedEventV2 = null; + _onInterstitialAdRevenuePaidEvent = null; + _onInterstitialAdReviewCreativeIdGeneratedEvent = null; + _onInterstitialAdHiddenEventV2 = null; + + _onAppOpenAdLoadedEvent = null; + _onAppOpenAdLoadFailedEvent = null; + _onAppOpenAdDisplayedEvent = null; + _onAppOpenAdFailedToDisplayEvent = null; + _onAppOpenAdClickedEvent = null; + _onAppOpenAdRevenuePaidEvent = null; + _onAppOpenAdHiddenEvent = null; + + _onRewardedAdLoadedEventV2 = null; + _onRewardedAdLoadFailedEventV2 = null; + _onRewardedAdDisplayedEventV2 = null; + _onRewardedAdFailedToDisplayEventV2 = null; + _onRewardedAdClickedEventV2 = null; + _onRewardedAdRevenuePaidEvent = null; + _onRewardedAdReviewCreativeIdGeneratedEvent = null; + _onRewardedAdReceivedRewardEventV2 = null; + _onRewardedAdHiddenEventV2 = null; + + _onRewardedInterstitialAdLoadedEvent = null; + _onRewardedInterstitialAdLoadFailedEvent = null; + _onRewardedInterstitialAdDisplayedEvent = null; + _onRewardedInterstitialAdFailedToDisplayEvent = null; + _onRewardedInterstitialAdClickedEvent = null; + _onRewardedInterstitialAdRevenuePaidEvent = null; + _onRewardedInterstitialAdReviewCreativeIdGeneratedEvent = null; + _onRewardedInterstitialAdReceivedRewardEvent = null; + _onRewardedInterstitialAdHiddenEvent = null; + + _onBannerAdLoadedEventV2 = null; + _onBannerAdLoadFailedEventV2 = null; + _onBannerAdClickedEventV2 = null; + _onBannerAdRevenuePaidEvent = null; + _onBannerAdReviewCreativeIdGeneratedEvent = null; + _onBannerAdExpandedEventV2 = null; + _onBannerAdCollapsedEventV2 = null; + + _onMRecAdLoadedEventV2 = null; + _onMRecAdLoadFailedEventV2 = null; + _onMRecAdClickedEventV2 = null; + _onMRecAdRevenuePaidEvent = null; + _onMRecAdReviewCreativeIdGeneratedEvent = null; + _onMRecAdExpandedEventV2 = null; + _onMRecAdCollapsedEventV2 = null; + + _onBannerAdLoadedEvent = null; + _onBannerAdLoadFailedEvent = null; + _onBannerAdClickedEvent = null; + _onBannerAdExpandedEvent = null; + _onBannerAdCollapsedEvent = null; + + _onMRecAdLoadedEvent = null; + _onMRecAdLoadFailedEvent = null; + _onMRecAdClickedEvent = null; + _onMRecAdExpandedEvent = null; + _onMRecAdCollapsedEvent = null; + + _onInterstitialAdLoadedEvent = null; + _onInterstitialLoadFailedEvent = null; + _onInterstitialAdDisplayedEvent = null; + _onInterstitialAdFailedToDisplayEvent = null; + _onInterstitialAdClickedEvent = null; + _onInterstitialAdHiddenEvent = null; + + _onRewardedAdLoadedEvent = null; + _onRewardedAdLoadFailedEvent = null; + _onRewardedAdDisplayedEvent = null; + _onRewardedAdFailedToDisplayEvent = null; + _onRewardedAdClickedEvent = null; + _onRewardedAdReceivedRewardEvent = null; + _onRewardedAdHiddenEvent = null; + } +#endif +} diff --git a/Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta b/Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta new file mode 100644 index 0000000..dd08049 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkCallbacks.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 4dc129a60049645f7a492a0a658a6c22 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdkCallbacks.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxSdkLogger.cs b/Assets/MaxSdk/Scripts/MaxSdkLogger.cs new file mode 100644 index 0000000..ecdc881 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkLogger.cs @@ -0,0 +1,70 @@ +using UnityEngine; + +public class MaxSdkLogger +{ + private const string SdkTag = "AppLovin MAX"; + public const string KeyVerboseLoggingEnabled = "com.applovin.verbose_logging_enabled"; + + /// + /// Log debug messages. + /// + public static void UserDebug(string message) + { + Debug.Log("Debug [" + SdkTag + "] " + message); + } + + /// + /// Log debug messages when verbose logging is enabled. + /// + /// Verbose logging can be enabled by calling or via the Integration Manager for build time logs. + /// + public static void D(string message) + { + if (MaxSdk.IsVerboseLoggingEnabled()) + { + Debug.Log("Debug [" + SdkTag + "] " + message); + } + } + + /// + /// Log warning messages. + /// + public static void UserWarning(string message) + { + Debug.LogWarning("Warning [" + SdkTag + "] " + message); + } + + /// + /// Log warning messages when verbose logging is enabled. + /// + /// Verbose logging can be enabled by calling or via the Integration Manager for build time logs. + /// + public static void W(string message) + { + if (MaxSdk.IsVerboseLoggingEnabled()) + { + Debug.LogWarning("Warning [" + SdkTag + "] " + message); + } + } + + /// + /// Log error messages. + /// + public static void UserError(string message) + { + Debug.LogError("Error [" + SdkTag + "] " + message); + } + + /// + /// Log error messages when verbose logging is enabled. + /// + /// Verbose logging can be enabled by calling or via the Integration Manager for build time logs. + /// + public static void E(string message) + { + if (MaxSdk.IsVerboseLoggingEnabled()) + { + Debug.LogError("Error [" + SdkTag + "] " + message); + } + } +} diff --git a/Assets/MaxSdk/Scripts/MaxSdkLogger.cs.meta b/Assets/MaxSdk/Scripts/MaxSdkLogger.cs.meta new file mode 100644 index 0000000..01a3427 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkLogger.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: ff2b160afdfd4a74b731954323772a90 +labels: +- al_max +- al_max_export_path-MaxSdk/Scripts/MaxSdkLogger.cs +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MaxSdk/Scripts/MaxSdkUnityEditor.cs b/Assets/MaxSdk/Scripts/MaxSdkUnityEditor.cs new file mode 100644 index 0000000..e767fb0 --- /dev/null +++ b/Assets/MaxSdk/Scripts/MaxSdkUnityEditor.cs @@ -0,0 +1,1383 @@ +// This script is used for Unity Editor and non Android or iOS platforms. + +#if UNITY_EDITOR || !(UNITY_ANDROID || UNITY_IPHONE || UNITY_IOS) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using AppLovinMax.Internal; +using AppLovinMax.ThirdParty.MiniJson; +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; +using UnityEngine.UI; +using Object = UnityEngine.Object; + +/// +/// Unity Editor AppLovin MAX Unity Plugin implementation +/// +public class MaxSdkUnityEditor : MaxSdkBase +{ + private static bool _isInitialized; + private static bool _hasUserConsent = false; + private static bool _isUserConsentSet = false; + private static bool _doNotSell = false; + private static bool _isDoNotSellSet = false; + private static bool _showStubAds = true; + private static SafeAreaInsets _safeAreaInsets = new SafeAreaInsets(new int[] {0, 0, 0, 0}); + private static readonly HashSet RequestedAdUnits = new HashSet(); + private static readonly HashSet ReadyAdUnits = new HashSet(); + private static readonly Dictionary StubBanners = new Dictionary(); + + // Ad Placement + private static readonly Dictionary BannerPlacements = new Dictionary(); + private static readonly Dictionary MRecPlacements = new Dictionary(); + + public static MaxUserServiceUnityEditor UserService + { + get { return MaxUserServiceUnityEditor.Instance; } + } + + [RuntimeInitializeOnLoadMethod] + public static void InitializeMaxSdkUnityEditorOnLoad() + { + // Unity destroys the stub banners each time the editor exits play mode, but the StubBanners stays in memory if Enter Play Mode settings is enabled. + StubBanners.Clear(); + } + + #region Initialization + + /// + /// Initialize the default instance of AppLovin SDK. + /// + /// Please make sure that application's Android manifest or Info.plist includes the AppLovin SDK key. + /// + /// + /// OPTIONAL: Set the MAX ad unit ids to be used for this instance of the SDK. 3rd-party SDKs will be initialized with the credentials configured for these ad unit ids. + /// This should only be used if you have different sets of ad unit ids / credentials for the same package name. + /// + public static void InitializeSdk(string[] adUnitIds = null) + { + _isInitialized = true; + + // Slight delay to emulate the SDK initializing + ExecuteWithDelay(0.1f, () => + { + _isInitialized = true; + +#if UNITY_EDITOR + MaxSdkCallbacks.EmitSdkInitializedEvent(); +#endif + }); + } + + /// + /// Check if the SDK has been initialized. + /// + /// True if SDK has been initialized + public static bool IsInitialized() + { + return _isInitialized; + } + + /// + /// Prevent stub ads from showing in the Unity Editor + /// + public static void DisableStubAds() + { + _showStubAds = false; + } + + #endregion + + #region User Info + + /// + /// Set an identifier for the current user. This identifier will be tied to SDK events and our optional S2S postbacks. + /// + /// If you're using reward validation, you can optionally set an identifier to be included with currency validation postbacks. + /// For example, a username or email. We'll include this in the postback when we ping your currency endpoint from our server. + /// + /// + /// The user identifier to be set. Must not be null. + public static void SetUserId(string userId) { } + + /// + /// Set the . + /// + /// The segment collection to be set. Must not be {@code null} + public static void SetSegmentCollection(MaxSegmentCollection segmentCollection) + { + if (_isInitialized) + { + Debug.LogError("Segment collection must be set before MAX SDK is initialized "); + } + } + + #endregion + + #region MAX + + /// + /// Returns the list of available mediation networks. + /// + /// Please call this method after the SDK has initialized. + /// + public static List GetAvailableMediatedNetworks() + { + return new List(); + } + + /// + /// Present the mediation debugger UI. + /// This debugger tool provides the status of your integration for each third-party ad network. + /// + /// Please call this method after the SDK has initialized. + /// + public static void ShowMediationDebugger() + { + if (!_isInitialized) + { + MaxSdkLogger.UserWarning("The mediation debugger cannot be shown before the MAX SDK has been initialized." + + "\nCall 'MaxSdk.InitializeSdk();' and listen for 'MaxSdkCallbacks.OnSdkInitializedEvent' before showing the mediation debugger."); + } + else + { + MaxSdkLogger.UserWarning("The mediation debugger cannot be shown in the Unity Editor. Please export the project to Android or iOS first."); + } + } + + /// + /// Present the mediation debugger UI. + /// + /// Please call this method after the SDK has initialized. + /// + public static void ShowCreativeDebugger() + { + if (!_isInitialized) + { + MaxSdkLogger.UserWarning("The creative debugger cannot be shown before the MAX SDK has been initialized." + + "\nCall 'MaxSdk.InitializeSdk();' and listen for 'MaxSdkCallbacks.OnSdkInitializedEvent' before showing the mediation debugger."); + } + else + { + MaxSdkLogger.UserWarning("The creative debugger cannot be shown in the Unity Editor. Please export the project to Android or iOS first."); + } + } + + /// + /// Returns the arbitrary ad value for a given ad unit identifier with key. Returns null if no ad is loaded. + /// + /// Ad unit identifier for which to get the ad value for. Must not be null. + /// Ad value key. Must not be null. + /// Arbitrary ad value for a given key, or null if no ad is loaded. + public static string GetAdValue(string adUnitIdentifier, string key) + { + return ""; + } + + #endregion + + #region Privacy + + /// + /// Get the SDK configuration for this user. + /// + /// Note: This method should be called only after SDK has been initialized. + /// + public static SdkConfiguration GetSdkConfiguration() + { + return SdkConfiguration.CreateEmpty(); + } + + /// + /// Set whether or not user has provided consent for information sharing with AppLovin and other providers. + /// + /// true if the user has provided consent for information sharing with AppLovin. false by default. + public static void SetHasUserConsent(bool hasUserConsent) + { + _hasUserConsent = hasUserConsent; + _isUserConsentSet = true; + } + + /// + /// Check if user has provided consent for information sharing with AppLovin and other providers. + /// + /// true if user has provided consent for information sharing. false if the user declined to share information or the consent value has not been set . + public static bool HasUserConsent() + { + return _hasUserConsent; + } + + /// + /// Check if user has set consent for information sharing. + /// + /// true if user has set a value of consent for information sharing. + public static bool IsUserConsentSet() + { + return _isUserConsentSet; + } + + /// + /// Set whether or not user has opted out of the sale of their personal information. + /// + /// true if the user has opted out of the sale of their personal information. + public static void SetDoNotSell(bool doNotSell) + { + _doNotSell = doNotSell; + _isDoNotSellSet = true; + } + + /// + /// Check if the user has opted out of the sale of their personal information. + /// + /// true if the user has opted out of the sale of their personal information. false if the user opted in to the sell of their personal information or the value has not been set . + public static bool IsDoNotSell() + { + return _doNotSell; + } + + /// + /// Check if the user has set the option to sell their personal information. + /// + /// true if user has chosen an option to sell their personal information. + public static bool IsDoNotSellSet() + { + return _isDoNotSellSet; + } + + #endregion + + #region Banners + + /// + /// Create a new banner. + /// + /// Ad unit identifier of the banner to create. Must not be null. + /// Banner position. Must not be null. + public static void CreateBanner(string adUnitIdentifier, BannerPosition bannerPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create banner"); + RequestAdUnit(adUnitIdentifier); + + if (_showStubAds && !StubBanners.ContainsKey(adUnitIdentifier)) + { + CreateStubBanner(adUnitIdentifier, bannerPosition); + } + + ExecuteWithDelay(1f, () => + { + var placement = MaxSdkUtils.GetStringFromDictionary(BannerPlacements, adUnitIdentifier); + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnBannerAdLoadedEvent", adUnitIdentifier, placement)); + MaxSdkCallbacks.ForwardEvent(eventProps); + }); + } + + /// + /// Create a new banner with a custom position. + /// + /// Ad unit identifier of the banner to create. Must not be null. + /// The X coordinate (horizontal position) of the banner relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the banner relative to the top left corner of the screen. + /// + /// The banner is placed within the safe area of the screen. You can use this to get the absolute position of the banner on screen. + /// + public static void CreateBanner(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create banner"); + RequestAdUnit(adUnitIdentifier); + + // TODO: Add stub ads support + } + + private static void CreateStubBanner(string adUnitIdentifier, BannerPosition bannerPosition) + { +#if UNITY_EDITOR + // Only support BottomCenter and TopCenter for now + var bannerPrefabName = bannerPosition == BannerPosition.BottomCenter ? "BannerBottom" : "BannerTop"; + var prefabPath = MaxSdkUtils.GetAssetPathForExportPath("MaxSdk/Prefabs/" + bannerPrefabName + ".prefab"); + var bannerPrefab = AssetDatabase.LoadAssetAtPath(prefabPath); + var stubBanner = Object.Instantiate(bannerPrefab, Vector3.zero, Quaternion.identity); + stubBanner.SetActive(false); // Hidden by default + Object.DontDestroyOnLoad(stubBanner); + + var bannerText = stubBanner.GetComponentInChildren(); + bannerText.text += ":\n" + adUnitIdentifier; + + StubBanners.Add(adUnitIdentifier, stubBanner); +#endif + } + + /// + /// Load a new banner ad. + /// NOTE: The method loads the first banner ad and initiates an automated banner refresh process. + /// You only need to call this method if you pause banner refresh. + /// + /// Ad unit identifier of the banner to load. Must not be null. + public static void LoadBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load banner"); + + ExecuteWithDelay(1f, () => + { + var placement = MaxSdkUtils.GetStringFromDictionary(BannerPlacements, adUnitIdentifier); + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnBannerAdLoadedEvent", adUnitIdentifier, placement)); + MaxSdkCallbacks.ForwardEvent(eventProps); + }); + } + + /// + /// Set the banner placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the banner to set the placement for. Must not be null. + /// Placement to set + public static void SetBannerPlacement(string adUnitIdentifier, string placement) + { + BannerPlacements[adUnitIdentifier] = placement; + MaxSdkLogger.UserDebug("Setting banner placement to '" + placement + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Starts or resumes auto-refreshing of the banner for the given ad unit identifier. + /// + /// Ad unit identifier of the banner for which to start auto-refresh. Must not be null. + public static void StartBannerAutoRefresh(string adUnitIdentifier) + { + MaxSdkLogger.UserDebug("Starting banner auto refresh."); + } + + /// + /// Pauses auto-refreshing of the banner for the given ad unit identifier. + /// + /// Ad unit identifier of the banner for which to stop auto-refresh. Must not be null. + public static void StopBannerAutoRefresh(string adUnitIdentifier) + { + MaxSdkLogger.UserDebug("Stopping banner auto refresh."); + } + + /// + /// Updates the position of the banner to the new position provided. + /// + /// The ad unit identifier of the banner for which to update the position. Must not be null. + /// A new position for the banner. Must not be null. + public static void UpdateBannerPosition(string adUnitIdentifier, BannerPosition bannerPosition) + { + MaxSdkLogger.D("[AppLovin MAX] Updating banner position to '" + bannerPosition + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Updates the position of the banner to the new coordinates provided. + /// + /// The ad unit identifier of the banner for which to update the position. Must not be null. + /// The X coordinate (horizontal position) of the banner relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the banner relative to the top left corner of the screen. + /// + /// The banner is placed within the safe area of the screen. You can use this to get the absolute position of the banner on screen. + /// + public static void UpdateBannerPosition(string adUnitIdentifier, float x, float y) + { + MaxSdkLogger.UserDebug("Updating banner position to '(" + x + "," + y + ")"); + } + + /// + /// Overrides the width of the banner in points/dp. + /// + /// The ad unit identifier of the banner for which to override the width for. Must not be null. + /// The desired width of the banner in points/dp + public static void SetBannerWidth(string adUnitIdentifier, float width) + { + // NOTE: Will implement in a future release + MaxSdkLogger.D("[AppLovin MAX] Set banner width to '" + width + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Show banner at a position determined by the 'CreateBanner' call. + /// + /// Ad unit identifier of the banner to show. Must not be null. + public static void ShowBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show banner"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("Banner '" + adUnitIdentifier + "' was not created, can not show it"); + } + else + { + GameObject stubBanner; + if (StubBanners.TryGetValue(adUnitIdentifier, out stubBanner)) + { + stubBanner.SetActive(true); + } + } + } + + /// + /// Remove banner from the ad view and destroy it. + /// + /// Ad unit identifier of the banner to destroy. Must not be null. + public static void DestroyBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy banner"); + + GameObject stubBanner; + if (StubBanners.TryGetValue(adUnitIdentifier, out stubBanner)) + { + Object.Destroy(stubBanner); + StubBanners.Remove(adUnitIdentifier); + } + } + + /// + /// Hide banner. + /// + /// Ad unit identifier of the banner to hide. Must not be null. + public static void HideBanner(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide banner"); + + GameObject stubBanner; + if (StubBanners.TryGetValue(adUnitIdentifier, out stubBanner)) + { + stubBanner.SetActive(false); + } + } + + /// + /// Set non-transparent background color for banners to be fully functional. + /// + /// Ad unit identifier of the banner to set background color for. Must not be null. + /// A background color to set for the ad. Must not be null. + public static void SetBannerBackgroundColor(string adUnitIdentifier, Color color) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set background color"); + + GameObject stubBanner; + if (StubBanners.TryGetValue(adUnitIdentifier, out stubBanner)) + { + stubBanner.GetComponentInChildren().color = color; + } + } + + /// + /// Set an extra parameter for the banner ad. + /// + /// Ad unit identifier of the banner to set the extra parameter for. Must not be null. + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. + public static void SetBannerExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner extra parameter"); + } + + /// + /// Set a local extra parameter for the banner ad. + /// + /// Ad unit identifier of the banner to set the local extra parameter for. Must not be null. + /// The key for the local extra parameter. Must not be null. + /// The value for the local extra parameter. + public static void SetBannerLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner local extra parameter"); + } + + /// + /// The custom data to tie the showing banner ad to, for ILRD and rewarded postbacks via the {CUSTOM_DATA} macro. Maximum size is 8KB. + /// + /// Banner ad unit identifier of the banner to set the custom data for. Must not be null. + /// The custom data to be set. + public static void SetBannerCustomData(string adUnitIdentifier, string customData) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set banner custom data"); + } + + /// + /// The banner position on the screen. When setting the banner position via or , + /// the banner is placed within the safe area of the screen. This returns the absolute position of the banner on screen. + /// + /// Ad unit identifier of the banner for which to get the position on screen. Must not be null. + /// A representing the banner position on screen. + public static Rect GetBannerLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get banner layout"); + return Rect.zero; + } + + #endregion + + #region MRECs + + /// + /// Create a new MREC. + /// + /// Ad unit identifier of the MREC to create. Must not be null. + /// MREC position. Must not be null. + public static void CreateMRec(string adUnitIdentifier, AdViewPosition mrecPosition) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create MREC"); + RequestAdUnit(adUnitIdentifier); + + ExecuteWithDelay(1f, () => + { + var placement = MaxSdkUtils.GetStringFromDictionary(MRecPlacements, adUnitIdentifier); + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnMRecAdLoadedEvent", adUnitIdentifier, placement)); + MaxSdkCallbacks.ForwardEvent(eventProps); + }); + } + + /// + /// Create a new MREC with a custom position. + /// + /// Ad unit identifier of the MREC to create. Must not be null. + /// The X coordinate (horizontal position) of the MREC relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the MREC relative to the top left corner of the screen. + /// + /// The MREC is placed within the safe area of the screen. You can use this to get the absolute position Rect of the MREC on screen. + /// + public static void CreateMRec(string adUnitIdentifier, float x, float y) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "create MREC"); + RequestAdUnit(adUnitIdentifier); + } + + /// + /// Load a new MREC ad. + /// NOTE: The method loads the first MREC ad and initiates an automated MREC refresh process. + /// You only need to call this method if you pause MREC refresh. + /// + /// Ad unit identifier of the MREC to load. Must not be null. + public static void LoadMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load MREC"); + + ExecuteWithDelay(1f, () => + { + var placement = MaxSdkUtils.GetStringFromDictionary(MRecPlacements, adUnitIdentifier); + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnMRecAdLoadedEvent", adUnitIdentifier, placement)); + MaxSdkCallbacks.ForwardEvent(eventProps); + }); + } + + /// + /// Set the MREC placement for an ad unit identifier to tie the future ad events to. + /// + /// Ad unit identifier of the MREC to set the placement for. Must not be null. + /// Placement to set + public static void SetMRecPlacement(string adUnitIdentifier, string placement) + { + MRecPlacements[adUnitIdentifier] = placement; + MaxSdkLogger.UserDebug("Setting MREC placement to '" + placement + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Starts or resumes auto-refreshing of the MREC for the given ad unit identifier. + /// + /// Ad unit identifier of the MREC for which to start auto-refresh. Must not be null. + public static void StartMRecAutoRefresh(string adUnitIdentifier) + { + MaxSdkLogger.UserDebug("Starting banner auto refresh."); + } + + /// + /// Pauses auto-refreshing of the MREC for the given ad unit identifier. + /// + /// Ad unit identifier of the MREC for which to stop auto-refresh. Must not be null. + public static void StopMRecAutoRefresh(string adUnitIdentifier) + { + MaxSdkLogger.UserDebug("Stopping banner auto refresh."); + } + + /// + /// Updates the position of the MREC to the new position provided. + /// + /// The ad unit identifier of the MREC for which to update the position. Must not be null. + /// A new position for the MREC. Must not be null. + public static void UpdateMRecPosition(string adUnitIdentifier, AdViewPosition mrecPosition) + { + MaxSdkLogger.UserDebug("Updating MREC position to '" + mrecPosition + "' for ad unit id '" + adUnitIdentifier + "'"); + } + + /// + /// Updates the position of the MREC to the new coordinates provided. + /// + /// The ad unit identifier of the MREC for which to update the position. Must not be null. + /// The X coordinate (horizontal position) of the MREC relative to the top left corner of the screen. + /// The Y coordinate (vertical position) of the MREC relative to the top left corner of the screen. + /// + /// The MREC is placed within the safe area of the screen. You can use this to get the absolute position Rect of the MREC on screen. + /// + public static void UpdateMRecPosition(string adUnitIdentifier, float x, float y) + { + MaxSdkLogger.UserDebug("Updating MREC position to '(" + x + "," + y + ")"); + } + + /// + /// Show MREC at a position determined by the 'CreateMRec' call. + /// + /// Ad unit identifier of the MREC to show. Must not be null. + public static void ShowMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show MREC"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("MREC '" + adUnitIdentifier + "' was not created, can not show it"); + } + } + + /// + /// Remove MREC from the ad view and destroy it. + /// + /// Ad unit identifier of the MREC to destroy. Must not be null. + public static void DestroyMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "destroy MREC"); + } + + /// + /// Hide MREC. + /// + /// Ad unit identifier of the MREC to hide. Must not be null. + public static void HideMRec(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "hide MREC"); + } + + /// + /// Set an extra parameter for the MREC ad. + /// + /// Ad unit identifier of the MREC to set the extra parameter for. Must not be null. + /// The key for the extra parameter. Must not be null. + /// The value for the extra parameter. + public static void SetMRecExtraParameter(string adUnitIdentifier, string key, string value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC extra parameter"); + } + + /// + /// Set a local extra parameter for the MREC ad. + /// + /// Ad unit identifier of the MREC to set the local extra parameter for. Must not be null. + /// The key for the local extra parameter. Must not be null. + /// The value for the local extra parameter. + public static void SetMRecLocalExtraParameter(string adUnitIdentifier, string key, object value) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC local extra parameter"); + } + + /// + /// The custom data to tie the showing MREC ad to, for ILRD and rewarded postbacks via the {CUSTOM_DATA} macro. Maximum size is 8KB. + /// + /// MREC Ad unit identifier of the banner to set the custom data for. Must not be null. + /// The custom data to be set. + public static void SetMRecCustomData(string adUnitIdentifier, string customData) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "set MREC custom data"); + } + + /// + /// The MREC position on the screen. When setting the MREC position via or , + /// the MREC is placed within the safe area of the screen. This returns the absolute position of the MREC on screen. + /// + /// Ad unit identifier of the MREC for which to get the position on screen. Must not be null. + /// A representing the banner position on screen. + public static Rect GetMRecLayout(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "get MREC layout"); + return Rect.zero; + } + + #endregion + + #region Interstitials + + /// + /// Start loading an interstitial. + /// + /// Ad unit identifier of the interstitial to load + public static void LoadInterstitial(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "load interstitial"); + RequestAdUnit(adUnitIdentifier); + + ExecuteWithDelay(1f, () => + { + AddReadyAdUnit(adUnitIdentifier); + + var eventProps = Json.Serialize(CreateBaseEventPropsDictionary("OnInterstitialLoadedEvent", adUnitIdentifier)); + MaxSdkCallbacks.ForwardEvent(eventProps); + }); + } + + /// + /// Check if interstitial ad is loaded and ready to be displayed. + /// + /// Ad unit identifier of the interstitial to load + /// True if the ad is ready to be displayed + public static bool IsInterstitialReady(string adUnitIdentifier) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "check interstitial loaded"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("Interstitial '" + adUnitIdentifier + + "' was not requested, can not check if it is loaded"); + return false; + } + + return IsAdUnitReady(adUnitIdentifier); + } + + /// + /// Present loaded interstitial for a given placement to tie ad events to. Note: if the interstitial is not ready to be displayed nothing will happen. + /// + /// Ad unit identifier of the interstitial to load + /// The placement to tie the showing ad's events to + /// The custom data to tie the showing ad's events to. Maximum size is 8KB. + public static void ShowInterstitial(string adUnitIdentifier, string placement = null, string customData = null) + { + ValidateAdUnitIdentifier(adUnitIdentifier, "show interstitial"); + + if (!IsAdUnitRequested(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning( + "Interstitial '" + adUnitIdentifier + "' was not requested, can not show it"); + return; + } + + if (!IsInterstitialReady(adUnitIdentifier)) + { + MaxSdkLogger.UserWarning("Interstitial '" + adUnitIdentifier + "' is not ready, please check IsInterstitialReady() before showing."); + return; + } + + RemoveReadyAdUnit(adUnitIdentifier); + + if (_showStubAds) + { + ShowStubInterstitial(adUnitIdentifier, placement); + } + } + + private static void ShowStubInterstitial(string adUnitIdentifier, string placement) + { +#if UNITY_EDITOR + var prefabPath = MaxSdkUtils.GetAssetPathForExportPath("MaxSdk/Prefabs/Interstitial.prefab"); + var interstitialPrefab = AssetDatabase.LoadAssetAtPath(prefabPath); + var stubInterstitial = Object.Instantiate(interstitialPrefab, Vector3.zero, Quaternion.identity); + var interstitialText = GameObject.Find("MaxInterstitialTitle").GetComponent(); + var closeButton = GameObject.Find("MaxInterstitialCloseButton").GetComponent