fixes
This commit is contained in:
@@ -1,31 +0,0 @@
|
|||||||
using Darkmatter.Core.Contracts.Services.Ads;
|
|
||||||
using Darkmatter.Core.Data.Static.Services.Ads;
|
|
||||||
using Darkmatter.Libs.Installers;
|
|
||||||
using UnityEngine;
|
|
||||||
using VContainer;
|
|
||||||
using VContainer.Unity;
|
|
||||||
|
|
||||||
namespace Darkmatter.Services.Ads
|
|
||||||
{
|
|
||||||
public class AdServiceModule : MonoBehaviour, IModule
|
|
||||||
{
|
|
||||||
[SerializeField] private AdUnitCatalogSO adUnitCatalog;
|
|
||||||
[SerializeField] private AdMobAdService adService;
|
|
||||||
|
|
||||||
public void Register(IContainerBuilder builder)
|
|
||||||
{
|
|
||||||
if (adUnitCatalog != null)
|
|
||||||
builder.RegisterComponent(adUnitCatalog);
|
|
||||||
|
|
||||||
var resolved = adService;
|
|
||||||
if (resolved == null) resolved = GetComponent<AdMobAdService>();
|
|
||||||
if (resolved == null) resolved = GetComponentInChildren<AdMobAdService>(includeInactive: true);
|
|
||||||
if (resolved == null) resolved = FindFirstObjectByType<AdMobAdService>(FindObjectsInactive.Include);
|
|
||||||
|
|
||||||
if (resolved != null)
|
|
||||||
builder.RegisterComponent<IAdService>(resolved);
|
|
||||||
else
|
|
||||||
Debug.LogError("[AdServiceModule] No AdMobAdService component found. Assign 'adService' field or add AdMobAdService MonoBehaviour to scene.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3a17cb41935543a6b4f67be8f398d774
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Services.Ads",
|
|
||||||
"rootNamespace": "Darkmatter.Services.Ads",
|
|
||||||
"references": [
|
|
||||||
"GUID:6a0a834eb41764f12ba55c3fb04a40cb",
|
|
||||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
|
||||||
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
|
|
||||||
"GUID:c1c03c0e5b2f4412b9f2be1c20d6a9b1"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [
|
|
||||||
{
|
|
||||||
"name": "com.google.ads.mobile",
|
|
||||||
"expression": "1.0.0",
|
|
||||||
"define": "GOOGLE_MOBILE_ADS"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
||||||
@@ -1,534 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using Darkmatter.Core.Contracts.Services.Ads;
|
|
||||||
using Darkmatter.Core.Data.Dynamic.Services.Ads;
|
|
||||||
using Darkmatter.Core.Data.Static.Services.Ads;
|
|
||||||
using Darkmatter.Core.Enums.Services.Ads;
|
|
||||||
using UnityEngine;
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
using GoogleMobileAds.Api;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Darkmatter.Services.Ads
|
|
||||||
{
|
|
||||||
public class AdMobAdService : MonoBehaviour, IAdService
|
|
||||||
{
|
|
||||||
[SerializeField] private AdUnitCatalogSO catalog;
|
|
||||||
[Tooltip("Auto-reload after dismiss/failure for non-banner formats.")]
|
|
||||||
[SerializeField] private bool autoReload = true;
|
|
||||||
[Tooltip("Seconds between auto-reload retries on failure.")]
|
|
||||||
[SerializeField, Min(1f)] private float reloadDelaySeconds = 5f;
|
|
||||||
|
|
||||||
public bool IsInitialized => _initialized;
|
|
||||||
public event Action<AdFormat, AdLoadState> LoadStateChanged;
|
|
||||||
|
|
||||||
private bool _initialized;
|
|
||||||
private bool _hasUserConsent = true;
|
|
||||||
private bool _isChildDirected;
|
|
||||||
private CancellationTokenSource _lifetimeCts;
|
|
||||||
|
|
||||||
private readonly Dictionary<AdFormat, AdLoadState> _states = new();
|
|
||||||
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
private InterstitialAd _interstitial;
|
|
||||||
private RewardedAd _rewarded;
|
|
||||||
private RewardedInterstitialAd _rewardedInterstitial;
|
|
||||||
private AppOpenAd _appOpen;
|
|
||||||
private BannerView _banner;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_lifetimeCts = new CancellationTokenSource();
|
|
||||||
foreach (AdFormat fmt in Enum.GetValues(typeof(AdFormat)))
|
|
||||||
_states[fmt] = AdLoadState.Idle;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDestroy()
|
|
||||||
{
|
|
||||||
_lifetimeCts?.Cancel();
|
|
||||||
_lifetimeCts?.Dispose();
|
|
||||||
_lifetimeCts = null;
|
|
||||||
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
_interstitial?.Destroy();
|
|
||||||
_rewarded?.Destroy();
|
|
||||||
_rewardedInterstitial?.Destroy();
|
|
||||||
_appOpen?.Destroy();
|
|
||||||
_banner?.Destroy();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask InitializeAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (_initialized) return;
|
|
||||||
if (catalog == null)
|
|
||||||
{
|
|
||||||
Debug.LogError("[AdMobAdService] No AdUnitCatalogSO assigned.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
ApplyRequestConfiguration();
|
|
||||||
|
|
||||||
var tcs = new UniTaskCompletionSource<bool>();
|
|
||||||
MobileAds.Initialize(_ => tcs.TrySetResult(true));
|
|
||||||
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
{
|
|
||||||
await tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
Debug.Log("[AdMobAdService] Initialized.");
|
|
||||||
#else
|
|
||||||
await UniTask.CompletedTask;
|
|
||||||
_initialized = true;
|
|
||||||
Debug.LogWarning("[AdMobAdService] GOOGLE_MOBILE_ADS not defined. Service will no-op. Add scripting define after importing Google Mobile Ads SDK.");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask<bool> LoadAsync(AdFormat format, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (!_initialized)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("[AdMobAdService] Load called before init.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
string unitId = catalog.GetUnitId(format, Application.platform);
|
|
||||||
if (string.IsNullOrEmpty(unitId))
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[AdMobAdService] No unit ID for {format} on {Application.platform}.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetState(format, AdLoadState.Loading);
|
|
||||||
var request = new AdRequest();
|
|
||||||
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case AdFormat.Interstitial:
|
|
||||||
return await LoadInterstitialAsync(unitId, request, cancellationToken);
|
|
||||||
case AdFormat.Rewarded:
|
|
||||||
return await LoadRewardedAsync(unitId, request, cancellationToken);
|
|
||||||
case AdFormat.RewardedInterstitial:
|
|
||||||
return await LoadRewardedInterstitialAsync(unitId, request, cancellationToken);
|
|
||||||
case AdFormat.AppOpen:
|
|
||||||
return await LoadAppOpenAsync(unitId, request, cancellationToken);
|
|
||||||
case AdFormat.Banner:
|
|
||||||
Debug.LogWarning("[AdMobAdService] Use ShowBannerAsync for banners.");
|
|
||||||
SetState(format, AdLoadState.Failed);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
#else
|
|
||||||
await UniTask.CompletedTask;
|
|
||||||
SetState(format, AdLoadState.Failed);
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsReady(AdFormat format)
|
|
||||||
{
|
|
||||||
if (!_initialized) return false;
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
return format switch
|
|
||||||
{
|
|
||||||
AdFormat.Interstitial => _interstitial != null && _interstitial.CanShowAd(),
|
|
||||||
AdFormat.Rewarded => _rewarded != null && _rewarded.CanShowAd(),
|
|
||||||
AdFormat.RewardedInterstitial => _rewardedInterstitial != null && _rewardedInterstitial.CanShowAd(),
|
|
||||||
AdFormat.AppOpen => _appOpen != null && _appOpen.CanShowAd(),
|
|
||||||
_ => false
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask<AdShowResult> ShowAsync(AdFormat format, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (!_initialized) return AdShowResult.Failure("Not initialized.");
|
|
||||||
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
if (!IsReady(format))
|
|
||||||
{
|
|
||||||
bool loaded = await LoadAsync(format, cancellationToken);
|
|
||||||
if (!loaded) return AdShowResult.Failure($"{format} failed to load.");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case AdFormat.Interstitial: return await ShowInterstitialAsync(cancellationToken);
|
|
||||||
case AdFormat.Rewarded: return await ShowRewardedAsync(cancellationToken);
|
|
||||||
case AdFormat.RewardedInterstitial: return await ShowRewardedInterstitialAsync(cancellationToken);
|
|
||||||
case AdFormat.AppOpen: return await ShowAppOpenAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
return AdShowResult.Failure($"{format} not supported by ShowAsync.");
|
|
||||||
#else
|
|
||||||
await UniTask.CompletedTask;
|
|
||||||
return AdShowResult.Failure("GOOGLE_MOBILE_ADS not defined.");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask<bool> ShowBannerAsync(BannerSize size, BannerPosition position, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (!_initialized) return false;
|
|
||||||
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
string unitId = catalog.GetUnitId(AdFormat.Banner, Application.platform);
|
|
||||||
if (string.IsNullOrEmpty(unitId)) return false;
|
|
||||||
|
|
||||||
_banner?.Destroy();
|
|
||||||
_banner = new BannerView(unitId, MapBannerSize(size), MapBannerPosition(position));
|
|
||||||
|
|
||||||
var tcs = new UniTaskCompletionSource<bool>();
|
|
||||||
_banner.OnBannerAdLoaded += () => tcs.TrySetResult(true);
|
|
||||||
_banner.OnBannerAdLoadFailed += err =>
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[AdMobAdService] Banner load failed: {err}");
|
|
||||||
tcs.TrySetResult(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
SetState(AdFormat.Banner, AdLoadState.Loading);
|
|
||||||
_banner.LoadAd(new AdRequest());
|
|
||||||
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
{
|
|
||||||
bool ok = await tcs.Task;
|
|
||||||
SetState(AdFormat.Banner, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
await UniTask.CompletedTask;
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HideBanner()
|
|
||||||
{
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
_banner?.Hide();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DestroyBanner()
|
|
||||||
{
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
_banner?.Destroy();
|
|
||||||
_banner = null;
|
|
||||||
SetState(AdFormat.Banner, AdLoadState.Idle);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetConsent(bool hasUserConsent, bool isChildDirected)
|
|
||||||
{
|
|
||||||
_hasUserConsent = hasUserConsent;
|
|
||||||
_isChildDirected = isChildDirected;
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
if (_initialized) ApplyRequestConfiguration();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GOOGLE_MOBILE_ADS
|
|
||||||
private void ApplyRequestConfiguration()
|
|
||||||
{
|
|
||||||
var config = new RequestConfiguration
|
|
||||||
{
|
|
||||||
TagForChildDirectedTreatment = _isChildDirected
|
|
||||||
? TagForChildDirectedTreatment.True
|
|
||||||
: TagForChildDirectedTreatment.Unspecified,
|
|
||||||
TagForUnderAgeOfConsent = _hasUserConsent
|
|
||||||
? TagForUnderAgeOfConsent.Unspecified
|
|
||||||
: TagForUnderAgeOfConsent.True
|
|
||||||
};
|
|
||||||
|
|
||||||
if (catalog.TestDeviceIds is { Count: > 0 })
|
|
||||||
{
|
|
||||||
config.TestDeviceIds = new List<string>(catalog.TestDeviceIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
MobileAds.SetRequestConfiguration(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTask<bool> LoadInterstitialAsync(string unitId, AdRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<bool>();
|
|
||||||
InterstitialAd.Load(unitId, request, (ad, error) =>
|
|
||||||
{
|
|
||||||
if (error != null || ad == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[AdMobAdService] Interstitial load failed: {error}");
|
|
||||||
tcs.TrySetResult(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_interstitial?.Destroy();
|
|
||||||
_interstitial = ad;
|
|
||||||
WireFullScreenEvents(ad, AdFormat.Interstitial);
|
|
||||||
tcs.TrySetResult(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
{
|
|
||||||
bool ok = await tcs.Task;
|
|
||||||
SetState(AdFormat.Interstitial, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTask<bool> LoadRewardedAsync(string unitId, AdRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<bool>();
|
|
||||||
RewardedAd.Load(unitId, request, (ad, error) =>
|
|
||||||
{
|
|
||||||
if (error != null || ad == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[AdMobAdService] Rewarded load failed: {error}");
|
|
||||||
tcs.TrySetResult(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_rewarded?.Destroy();
|
|
||||||
_rewarded = ad;
|
|
||||||
WireFullScreenEvents(ad, AdFormat.Rewarded);
|
|
||||||
tcs.TrySetResult(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
{
|
|
||||||
bool ok = await tcs.Task;
|
|
||||||
SetState(AdFormat.Rewarded, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTask<bool> LoadRewardedInterstitialAsync(string unitId, AdRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<bool>();
|
|
||||||
RewardedInterstitialAd.Load(unitId, request, (ad, error) =>
|
|
||||||
{
|
|
||||||
if (error != null || ad == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[AdMobAdService] RewardedInterstitial load failed: {error}");
|
|
||||||
tcs.TrySetResult(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_rewardedInterstitial?.Destroy();
|
|
||||||
_rewardedInterstitial = ad;
|
|
||||||
WireFullScreenEvents(ad, AdFormat.RewardedInterstitial);
|
|
||||||
tcs.TrySetResult(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
{
|
|
||||||
bool ok = await tcs.Task;
|
|
||||||
SetState(AdFormat.RewardedInterstitial, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTask<bool> LoadAppOpenAsync(string unitId, AdRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<bool>();
|
|
||||||
AppOpenAd.Load(unitId, request, (ad, error) =>
|
|
||||||
{
|
|
||||||
if (error != null || ad == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[AdMobAdService] AppOpen load failed: {error}");
|
|
||||||
tcs.TrySetResult(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_appOpen?.Destroy();
|
|
||||||
_appOpen = ad;
|
|
||||||
WireFullScreenEvents(ad, AdFormat.AppOpen);
|
|
||||||
tcs.TrySetResult(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
{
|
|
||||||
bool ok = await tcs.Task;
|
|
||||||
SetState(AdFormat.AppOpen, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTask<AdShowResult> ShowInterstitialAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<AdShowResult>();
|
|
||||||
Action onClosed = () => tcs.TrySetResult(AdShowResult.Success());
|
|
||||||
Action<AdError> onFailed = err => tcs.TrySetResult(AdShowResult.Failure(err?.GetMessage()));
|
|
||||||
|
|
||||||
_interstitial.OnAdFullScreenContentClosed += onClosed;
|
|
||||||
_interstitial.OnAdFullScreenContentFailed += onFailed;
|
|
||||||
_interstitial.Show();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_interstitial != null)
|
|
||||||
{
|
|
||||||
_interstitial.OnAdFullScreenContentClosed -= onClosed;
|
|
||||||
_interstitial.OnAdFullScreenContentFailed -= onFailed;
|
|
||||||
}
|
|
||||||
ScheduleReload(AdFormat.Interstitial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTask<AdShowResult> ShowRewardedAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<AdShowResult>();
|
|
||||||
bool earned = false;
|
|
||||||
AdReward reward = default;
|
|
||||||
|
|
||||||
Action onClosed = () => tcs.TrySetResult(earned ? AdShowResult.WithReward(reward) : AdShowResult.Success());
|
|
||||||
Action<AdError> onFailed = err => tcs.TrySetResult(AdShowResult.Failure(err?.GetMessage()));
|
|
||||||
|
|
||||||
_rewarded.OnAdFullScreenContentClosed += onClosed;
|
|
||||||
_rewarded.OnAdFullScreenContentFailed += onFailed;
|
|
||||||
_rewarded.Show(r =>
|
|
||||||
{
|
|
||||||
earned = true;
|
|
||||||
reward = new AdReward(r.Type, r.Amount);
|
|
||||||
});
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_rewarded != null)
|
|
||||||
{
|
|
||||||
_rewarded.OnAdFullScreenContentClosed -= onClosed;
|
|
||||||
_rewarded.OnAdFullScreenContentFailed -= onFailed;
|
|
||||||
}
|
|
||||||
ScheduleReload(AdFormat.Rewarded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTask<AdShowResult> ShowRewardedInterstitialAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<AdShowResult>();
|
|
||||||
bool earned = false;
|
|
||||||
AdReward reward = default;
|
|
||||||
|
|
||||||
Action onClosed = () => tcs.TrySetResult(earned ? AdShowResult.WithReward(reward) : AdShowResult.Success());
|
|
||||||
Action<AdError> onFailed = err => tcs.TrySetResult(AdShowResult.Failure(err?.GetMessage()));
|
|
||||||
|
|
||||||
_rewardedInterstitial.OnAdFullScreenContentClosed += onClosed;
|
|
||||||
_rewardedInterstitial.OnAdFullScreenContentFailed += onFailed;
|
|
||||||
_rewardedInterstitial.Show(r =>
|
|
||||||
{
|
|
||||||
earned = true;
|
|
||||||
reward = new AdReward(r.Type, r.Amount);
|
|
||||||
});
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_rewardedInterstitial != null)
|
|
||||||
{
|
|
||||||
_rewardedInterstitial.OnAdFullScreenContentClosed -= onClosed;
|
|
||||||
_rewardedInterstitial.OnAdFullScreenContentFailed -= onFailed;
|
|
||||||
}
|
|
||||||
ScheduleReload(AdFormat.RewardedInterstitial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTask<AdShowResult> ShowAppOpenAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var tcs = new UniTaskCompletionSource<AdShowResult>();
|
|
||||||
Action onClosed = () => tcs.TrySetResult(AdShowResult.Success());
|
|
||||||
Action<AdError> onFailed = err => tcs.TrySetResult(AdShowResult.Failure(err?.GetMessage()));
|
|
||||||
|
|
||||||
_appOpen.OnAdFullScreenContentClosed += onClosed;
|
|
||||||
_appOpen.OnAdFullScreenContentFailed += onFailed;
|
|
||||||
_appOpen.Show();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
|
||||||
return await tcs.Task;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_appOpen != null)
|
|
||||||
{
|
|
||||||
_appOpen.OnAdFullScreenContentClosed -= onClosed;
|
|
||||||
_appOpen.OnAdFullScreenContentFailed -= onFailed;
|
|
||||||
}
|
|
||||||
ScheduleReload(AdFormat.AppOpen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WireFullScreenEvents(InterstitialAd ad, AdFormat format) =>
|
|
||||||
ad.OnAdFullScreenContentClosed += () => SetState(format, AdLoadState.Idle);
|
|
||||||
|
|
||||||
private void WireFullScreenEvents(RewardedAd ad, AdFormat format) =>
|
|
||||||
ad.OnAdFullScreenContentClosed += () => SetState(format, AdLoadState.Idle);
|
|
||||||
|
|
||||||
private void WireFullScreenEvents(RewardedInterstitialAd ad, AdFormat format) =>
|
|
||||||
ad.OnAdFullScreenContentClosed += () => SetState(format, AdLoadState.Idle);
|
|
||||||
|
|
||||||
private void WireFullScreenEvents(AppOpenAd ad, AdFormat format) =>
|
|
||||||
ad.OnAdFullScreenContentClosed += () => SetState(format, AdLoadState.Idle);
|
|
||||||
|
|
||||||
private void ScheduleReload(AdFormat format)
|
|
||||||
{
|
|
||||||
if (!autoReload || _lifetimeCts == null) return;
|
|
||||||
ReloadAfterDelayAsync(format, _lifetimeCts.Token).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async UniTaskVoid ReloadAfterDelayAsync(AdFormat format, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(reloadDelaySeconds), cancellationToken: cancellationToken);
|
|
||||||
await LoadAsync(format, cancellationToken);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AdSize MapBannerSize(BannerSize size) => size switch
|
|
||||||
{
|
|
||||||
BannerSize.Banner => AdSize.Banner,
|
|
||||||
BannerSize.LargeBanner => AdSize.LargeBanner,
|
|
||||||
BannerSize.MediumRectangle => AdSize.MediumRectangle,
|
|
||||||
BannerSize.FullBanner => AdSize.IABBanner,
|
|
||||||
BannerSize.Leaderboard => AdSize.Leaderboard,
|
|
||||||
BannerSize.SmartBanner => AdSize.SmartBanner,
|
|
||||||
BannerSize.AnchoredAdaptive => AdSize.GetCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(AdSize.FullWidth),
|
|
||||||
_ => AdSize.Banner
|
|
||||||
};
|
|
||||||
|
|
||||||
private static AdPosition MapBannerPosition(BannerPosition position) => position switch
|
|
||||||
{
|
|
||||||
BannerPosition.Top => AdPosition.Top,
|
|
||||||
BannerPosition.Bottom => AdPosition.Bottom,
|
|
||||||
BannerPosition.TopLeft => AdPosition.TopLeft,
|
|
||||||
BannerPosition.TopRight => AdPosition.TopRight,
|
|
||||||
BannerPosition.BottomLeft => AdPosition.BottomLeft,
|
|
||||||
BannerPosition.BottomRight => AdPosition.BottomRight,
|
|
||||||
BannerPosition.Center => AdPosition.Center,
|
|
||||||
_ => AdPosition.Bottom
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private void SetState(AdFormat format, AdLoadState state)
|
|
||||||
{
|
|
||||||
_states[format] = state;
|
|
||||||
LoadStateChanged?.Invoke(format, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 018ba83ad51c4d9a89a904ba3d21ead2
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -14,18 +14,19 @@ namespace Darkmatter.Services.Audio
|
|||||||
|
|
||||||
public void Register(IContainerBuilder builder)
|
public void Register(IContainerBuilder builder)
|
||||||
{
|
{
|
||||||
if (sfxCatalog != null)
|
if (sfxCatalog == null)
|
||||||
builder.RegisterComponent(sfxCatalog);
|
{
|
||||||
|
Debug.LogError("[AudioServiceModule] SfxCatalogSO not assigned.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
builder.RegisterComponent(sfxCatalog);
|
||||||
|
|
||||||
var resolved = audioService;
|
if (audioService == null)
|
||||||
if (resolved == null) resolved = GetComponent<AudioService>();
|
{
|
||||||
if (resolved == null) resolved = GetComponentInChildren<AudioService>(includeInactive: true);
|
Debug.LogError("[AudioServiceModule] AudioService not assigned. Assign the scene component to the 'audioService' field.");
|
||||||
if (resolved == null) resolved = FindFirstObjectByType<AudioService>(FindObjectsInactive.Include);
|
return;
|
||||||
|
}
|
||||||
if (resolved != null)
|
builder.RegisterComponent<IAudioService>(audioService);
|
||||||
builder.RegisterComponent<IAudioService>(resolved);
|
|
||||||
else
|
|
||||||
Debug.LogError("[AudioServiceModule] No AudioService component found. SFX/music won't play. Assign 'audioService' field or add AudioService MonoBehaviour to scene.");
|
|
||||||
|
|
||||||
builder.Register<ISfxPlayer, SfxPlayer>(Lifetime.Singleton);
|
builder.Register<ISfxPlayer, SfxPlayer>(Lifetime.Singleton);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -346,8 +346,11 @@ namespace Darkmatter.Services.Audio
|
|||||||
source.loop = request.PlayMode == AudioPlayMode.Loop;
|
source.loop = request.PlayMode == AudioPlayMode.Loop;
|
||||||
|
|
||||||
source.transform.localPosition = Vector3.zero;
|
source.transform.localPosition = Vector3.zero;
|
||||||
|
source.enabled = true;
|
||||||
|
if (!source.gameObject.activeInHierarchy) source.gameObject.SetActive(true);
|
||||||
|
|
||||||
source.Play();
|
source.Play();
|
||||||
|
Debug.Log($"[AudioService] Play clip='{(request.Clip != null ? request.Clip.name : "null")}' ch={request.Channel} vol={source.volume:F2} mixer={(source.outputAudioMixerGroup != null ? source.outputAudioMixerGroup.name : "none")} listener={(AudioListener.volume)} muted={AudioListener.pause} isPlaying={source.isPlaying}");
|
||||||
if (IsChannelPaused(request.Channel))
|
if (IsChannelPaused(request.Channel))
|
||||||
{
|
{
|
||||||
source.Pause();
|
source.Pause();
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 1272845566047700851}
|
- component: {fileID: 1272845566047700851}
|
||||||
- component: {fileID: 3476496333429146458}
|
- component: {fileID: 3476496333429146458}
|
||||||
- component: {fileID: 4136462144027782631}
|
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: AppleDrawing
|
m_Name: AppleDrawing
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -48,36 +47,6 @@ CanvasRenderer:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 6246945885353309008}
|
m_GameObject: {fileID: 6246945885353309008}
|
||||||
m_CullTransparentMesh: 1
|
m_CullTransparentMesh: 1
|
||||||
--- !u!114 &4136462144027782631
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6246945885353309008}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
m_RaycastTarget: 1
|
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
|
||||||
m_OnCullStateChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
m_Sprite: {fileID: 21300000, guid: 06c1593744b6629468f632c6b5cba376, type: 3}
|
|
||||||
m_Type: 0
|
|
||||||
m_PreserveAspect: 1
|
|
||||||
m_FillCenter: 1
|
|
||||||
m_FillMethod: 4
|
|
||||||
m_FillAmount: 1
|
|
||||||
m_FillClockwise: 1
|
|
||||||
m_FillOrigin: 0
|
|
||||||
m_UseSpriteMesh: 0
|
|
||||||
m_PixelsPerUnitMultiplier: 1
|
|
||||||
--- !u!1001 &1278753232270531628
|
--- !u!1001 &1278753232270531628
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -118,6 +87,18 @@ PrefabInstance:
|
|||||||
propertyPath: m_SizeDelta.y
|
propertyPath: m_SizeDelta.y
|
||||||
value: 381
|
value: 381
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
||||||
|
propertyPath: m_LocalScale.x
|
||||||
|
value: 0.61996
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
||||||
|
propertyPath: m_LocalScale.y
|
||||||
|
value: 0.61996
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
||||||
|
propertyPath: m_LocalScale.z
|
||||||
|
value: 0.61996
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
||||||
propertyPath: m_LocalPosition.x
|
propertyPath: m_LocalPosition.x
|
||||||
value: 0
|
value: 0
|
||||||
@@ -148,11 +129,11 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
||||||
propertyPath: m_AnchoredPosition.x
|
propertyPath: m_AnchoredPosition.x
|
||||||
value: -302
|
value: -282
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
||||||
propertyPath: m_AnchoredPosition.y
|
propertyPath: m_AnchoredPosition.y
|
||||||
value: 504
|
value: 484
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
- target: {fileID: 4772353642633016153, guid: 483b170ade7354414929ed6252fa552e, type: 3}
|
||||||
propertyPath: m_LocalEulerAnglesHint.x
|
propertyPath: m_LocalEulerAnglesHint.x
|
||||||
@@ -222,11 +203,11 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4433096382570807284, guid: 70aa2daf45f0649c2823d1930e906f59, type: 3}
|
- target: {fileID: 4433096382570807284, guid: 70aa2daf45f0649c2823d1930e906f59, type: 3}
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 666
|
value: 425.856
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4433096382570807284, guid: 70aa2daf45f0649c2823d1930e906f59, type: 3}
|
- target: {fileID: 4433096382570807284, guid: 70aa2daf45f0649c2823d1930e906f59, type: 3}
|
||||||
propertyPath: m_SizeDelta.y
|
propertyPath: m_SizeDelta.y
|
||||||
value: 381
|
value: 170.875
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4433096382570807284, guid: 70aa2daf45f0649c2823d1930e906f59, type: 3}
|
- target: {fileID: 4433096382570807284, guid: 70aa2daf45f0649c2823d1930e906f59, type: 3}
|
||||||
propertyPath: m_LocalPosition.x
|
propertyPath: m_LocalPosition.x
|
||||||
@@ -326,6 +307,18 @@ PrefabInstance:
|
|||||||
propertyPath: m_SizeDelta.y
|
propertyPath: m_SizeDelta.y
|
||||||
value: 381
|
value: 381
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3648889831887995107, guid: ed3abc5b1c6bc43938850705ab3e4d4b, type: 3}
|
||||||
|
propertyPath: m_LocalScale.x
|
||||||
|
value: 2.4848
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3648889831887995107, guid: ed3abc5b1c6bc43938850705ab3e4d4b, type: 3}
|
||||||
|
propertyPath: m_LocalScale.y
|
||||||
|
value: 2.4848
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3648889831887995107, guid: ed3abc5b1c6bc43938850705ab3e4d4b, type: 3}
|
||||||
|
propertyPath: m_LocalScale.z
|
||||||
|
value: 2.4848
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3648889831887995107, guid: ed3abc5b1c6bc43938850705ab3e4d4b, type: 3}
|
- target: {fileID: 3648889831887995107, guid: ed3abc5b1c6bc43938850705ab3e4d4b, type: 3}
|
||||||
propertyPath: m_LocalPosition.x
|
propertyPath: m_LocalPosition.x
|
||||||
value: 0
|
value: 0
|
||||||
|
|||||||
@@ -1080,7 +1080,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Darkmatter.Services.Music.Installers.MusicServiceModule
|
m_EditorClassIdentifier: Assembly-CSharp::Darkmatter.Services.Music.Installers.MusicServiceModule
|
||||||
defaultTrack: {fileID: 8300000, guid: d2ea12320736942649eb53c30ab7e4bb, type: 3}
|
defaultTrack: {fileID: 8300000, guid: d2ea12320736942649eb53c30ab7e4bb, type: 3}
|
||||||
defaultVolume: 0.6
|
defaultVolume: 0.3
|
||||||
crossFadeSeconds: 0.4
|
crossFadeSeconds: 0.4
|
||||||
mixerGroup: {fileID: 0}
|
mixerGroup: {fileID: 0}
|
||||||
--- !u!1 &445008005
|
--- !u!1 &445008005
|
||||||
@@ -1585,6 +1585,52 @@ Transform:
|
|||||||
- {fileID: 1707278033}
|
- {fileID: 1707278033}
|
||||||
m_Father: {fileID: 1798580248}
|
m_Father: {fileID: 1798580248}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!1 &1156238479
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1156238481}
|
||||||
|
- component: {fileID: 1156238482}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: AdServiceModule
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &1156238481
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1156238479}
|
||||||
|
serializedVersion: 2
|
||||||
|
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_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1156238482
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1156238479}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 018ba83ad51c4d9a89a904ba3d21ead2, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Services.Ads::Darkmatter.Services.Ads.AdMobAdService
|
||||||
|
autoReload: 1
|
||||||
|
reloadDelaySeconds: 5
|
||||||
--- !u!1 &1239449674
|
--- !u!1 &1239449674
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1959,8 +2005,8 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 3a17cb41935543a6b4f67be8f398d774, type: 3}
|
m_Script: {fileID: 11500000, guid: 3a17cb41935543a6b4f67be8f398d774, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Services.Ads::Darkmatter.Services.Ads.AdServiceModule
|
m_EditorClassIdentifier: Services.Ads::Darkmatter.Services.Ads.AdServiceModule
|
||||||
adUnitCatalog: {fileID: 0}
|
adUnitCatalog: {fileID: 11400000, guid: 6e2d0c78aa02e4411948adcca14299a5, type: 2}
|
||||||
adService: {fileID: 0}
|
adService: {fileID: 1156238482}
|
||||||
--- !u!1 &1740606684
|
--- !u!1 &1740606684
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -2347,3 +2393,4 @@ SceneRoots:
|
|||||||
- {fileID: 109717503}
|
- {fileID: 109717503}
|
||||||
- {fileID: 1424266587}
|
- {fileID: 1424266587}
|
||||||
- {fileID: 196669903}
|
- {fileID: 196669903}
|
||||||
|
- {fileID: 1156238481}
|
||||||
|
|||||||
@@ -1806,8 +1806,7 @@ RectTransform:
|
|||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children: []
|
||||||
- {fileID: 4116787378023023922}
|
|
||||||
m_Father: {fileID: 153461769}
|
m_Father: {fileID: 153461769}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
@@ -3612,112 +3611,6 @@ RectTransform:
|
|||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 0, y: 0}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0, y: 0}
|
m_Pivot: {x: 0, y: 0}
|
||||||
--- !u!224 &4116787378023023922 stripped
|
|
||||||
RectTransform:
|
|
||||||
m_CorrespondingSourceObject: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
m_PrefabInstance: {fileID: 4467542889302059353}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
--- !u!1001 &4467542889302059353
|
|
||||||
PrefabInstance:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Modification:
|
|
||||||
serializedVersion: 3
|
|
||||||
m_TransformParent: {fileID: 1143672390}
|
|
||||||
m_Modifications:
|
|
||||||
- target: {fileID: 6799536857748686187, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_Name
|
|
||||||
value: BallColoring
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 6799536857748686187, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_IsActive
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_Pivot.x
|
|
||||||
value: 0.5
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_Pivot.y
|
|
||||||
value: 0.5
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_AnchorMax.x
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_AnchorMax.y
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_AnchorMin.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_AnchorMin.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_SizeDelta.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_SizeDelta.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalPosition.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalPosition.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalPosition.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalRotation.w
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalRotation.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalRotation.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalRotation.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_AnchoredPosition.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_AnchoredPosition.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 7007843749351456914, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
m_RemovedComponents: []
|
|
||||||
m_RemovedGameObjects: []
|
|
||||||
m_AddedGameObjects: []
|
|
||||||
m_AddedComponents: []
|
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: e02814fe96e1cf84491b9545b5642307, type: 3}
|
|
||||||
--- !u!1660057539 &9223372036854775807
|
--- !u!1660057539 &9223372036854775807
|
||||||
SceneRoots:
|
SceneRoots:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 3a320ad839a14f578bb9ff149807ed84
|
guid: e3b3a9722913e4c45aaff4ccd98a108b
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: fd05451b7a0c4e04ae9521e8052ee1e2
|
guid: a7e7ae719e93e480aaaecd0460cce6ae
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
8
Assets/Plugins/Android/gradleTemplate.properties
Normal file
8
Assets/Plugins/Android/gradleTemplate.properties
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M
|
||||||
|
org.gradle.parallel=true
|
||||||
|
unityStreamingAssets=**STREAMING_ASSETS**
|
||||||
|
# Android Resolver Properties Start
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=true
|
||||||
|
# Android Resolver Properties End
|
||||||
|
**ADDITIONAL_PROPERTIES**
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 6fbb9ad075cb419095482b3d74c4311c
|
guid: 44f8f6574c2b0426185a812ff10cb76e
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
62
Assets/Plugins/Android/mainTemplate.gradle
Normal file
62
Assets/Plugins/Android/mainTemplate.gradle
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
apply from: '../shared/keepUnitySymbols.gradle'
|
||||||
|
apply from: '../shared/common.gradle'
|
||||||
|
**APPLY_PLUGINS**
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
// Android Resolver Dependencies Start
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' // Packages/com.google.ads.mobile/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:12
|
||||||
|
implementation 'androidx.lifecycle:lifecycle-process:2.6.2' // Packages/com.google.ads.mobile/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:17
|
||||||
|
implementation 'com.google.android.gms:play-services-ads:25.3.0' // Packages/com.google.ads.mobile/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:7
|
||||||
|
implementation 'com.google.android.ump:user-messaging-platform:4.0.0' // Packages/com.google.ads.mobile/GoogleMobileAds/Editor/GoogleUmpDependencies.xml:7
|
||||||
|
// Android Resolver Dependencies End
|
||||||
|
**DEPS**}
|
||||||
|
|
||||||
|
// Android Resolver Exclusions Start
|
||||||
|
android {
|
||||||
|
packaging {
|
||||||
|
exclude ('/lib/armeabi/*' + '*')
|
||||||
|
exclude ('/lib/armeabi-v7a/*' + '*')
|
||||||
|
exclude ('/lib/mips/*' + '*')
|
||||||
|
exclude ('/lib/mips64/*' + '*')
|
||||||
|
exclude ('/lib/x86/*' + '*')
|
||||||
|
exclude ('/lib/x86_64/*' + '*')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Android Resolver Exclusions End
|
||||||
|
android {
|
||||||
|
namespace "com.unity3d.player"
|
||||||
|
ndkPath "**NDKPATH**"
|
||||||
|
ndkVersion "**NDKVERSION**"
|
||||||
|
compileSdk **APIVERSION**
|
||||||
|
buildToolsVersion "**BUILDTOOLS**"
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
|
targetCompatibility JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk **MINSDK**
|
||||||
|
targetSdk **TARGETSDK**
|
||||||
|
ndk {
|
||||||
|
abiFilters **ABIFILTERS**
|
||||||
|
debugSymbolLevel **DEBUGSYMBOLLEVEL**
|
||||||
|
}
|
||||||
|
consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
|
||||||
|
**DEFAULT_CONFIG_SETUP**
|
||||||
|
}
|
||||||
|
|
||||||
|
lint {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
|
||||||
|
androidResources {
|
||||||
|
noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
|
||||||
|
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
|
||||||
|
}**PACKAGING**
|
||||||
|
}
|
||||||
|
**IL_CPP_BUILD_SETUP**
|
||||||
|
**SOURCE_BUILD_SETUP**
|
||||||
|
**EXTERNAL_SOURCES**
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 662a8e56a1724c84ad8c10211211f0d5
|
guid: d3e10adc032c64599a7e518dd8d65c66
|
||||||
AssemblyDefinitionImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
31
Assets/Plugins/Android/settingsTemplate.gradle
Normal file
31
Assets/Plugins/Android/settingsTemplate.gradle
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
**ARTIFACTORYREPOSITORY**
|
||||||
|
gradlePluginPortal()
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
include ':launcher'
|
||||||
|
include ':unityLibrary'
|
||||||
|
**INCLUDES**
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
||||||
|
repositories {
|
||||||
|
**ARTIFACTORYREPOSITORY**
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
// Android Resolver Repos Start
|
||||||
|
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
|
||||||
|
maven {
|
||||||
|
url "https://maven.google.com/" // Packages/com.google.ads.mobile/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:7, Packages/com.google.ads.mobile/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:12, Packages/com.google.ads.mobile/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:17, Packages/com.google.ads.mobile/GoogleMobileAds/Editor/GoogleUmpDependencies.xml:7
|
||||||
|
}
|
||||||
|
mavenLocal()
|
||||||
|
// Android Resolver Repos End
|
||||||
|
flatDir {
|
||||||
|
dirs "${project(':unityLibrary').projectDir}/libs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Assets/Plugins/Android/settingsTemplate.gradle.meta
Normal file
7
Assets/Plugins/Android/settingsTemplate.gradle.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4a569f41ac85440a2a22e0f5673a3356
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -60,7 +60,8 @@
|
|||||||
"com.unity.modules.video": "1.0.0",
|
"com.unity.modules.video": "1.0.0",
|
||||||
"com.unity.modules.vr": "1.0.0",
|
"com.unity.modules.vr": "1.0.0",
|
||||||
"com.unity.modules.wind": "1.0.0",
|
"com.unity.modules.wind": "1.0.0",
|
||||||
"com.unity.modules.xr": "1.0.0"
|
"com.unity.modules.xr": "1.0.0",
|
||||||
|
"com.google.ads.mobile": "11.2.0"
|
||||||
},
|
},
|
||||||
"scopedRegistries": [
|
"scopedRegistries": [
|
||||||
{
|
{
|
||||||
@@ -76,6 +77,8 @@
|
|||||||
"scopes": [
|
"scopes": [
|
||||||
"com.gilzoide.update-manager",
|
"com.gilzoide.update-manager",
|
||||||
"com.github-glitchenzo.nugetforunity",
|
"com.github-glitchenzo.nugetforunity",
|
||||||
|
"com.google.ads.mobile",
|
||||||
|
"com.google.external-dependency-manager",
|
||||||
"com.yasirkula.nativegallery",
|
"com.yasirkula.nativegallery",
|
||||||
"jp.hadashikick.vcontainer"
|
"jp.hadashikick.vcontainer"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -31,6 +31,23 @@
|
|||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"url": "https://package.openupm.com"
|
"url": "https://package.openupm.com"
|
||||||
},
|
},
|
||||||
|
"com.google.ads.mobile": {
|
||||||
|
"version": "11.2.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.google.external-dependency-manager": "1.2.187",
|
||||||
|
"com.unity.modules.androidjni": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://package.openupm.com"
|
||||||
|
},
|
||||||
|
"com.google.external-dependency-manager": {
|
||||||
|
"version": "1.2.187",
|
||||||
|
"depth": 1,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {},
|
||||||
|
"url": "https://package.openupm.com"
|
||||||
|
},
|
||||||
"com.kyrylokuzyk.primetween": {
|
"com.kyrylokuzyk.primetween": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
|
|||||||
26
ProjectSettings/AndroidResolverDependencies.xml
Normal file
26
ProjectSettings/AndroidResolverDependencies.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<dependencies>
|
||||||
|
<packages>
|
||||||
|
<package>androidx.constraintlayout:constraintlayout:2.1.4</package>
|
||||||
|
<package>androidx.lifecycle:lifecycle-process:2.6.2</package>
|
||||||
|
<package>com.google.android.gms:play-services-ads:25.3.0</package>
|
||||||
|
<package>com.google.android.ump:user-messaging-platform:4.0.0</package>
|
||||||
|
</packages>
|
||||||
|
<files />
|
||||||
|
<settings>
|
||||||
|
<setting name="androidAbis" value="arm64-v8a" />
|
||||||
|
<setting name="bundleId" value="com.Darkmatter.Colorbook" />
|
||||||
|
<setting name="explodeAars" value="True" />
|
||||||
|
<setting name="gradleBuildEnabled" value="True" />
|
||||||
|
<setting name="gradlePropertiesTemplateEnabled" value="True" />
|
||||||
|
<setting name="gradleTemplateEnabled" value="True" />
|
||||||
|
<setting name="installAndroidPackages" value="True" />
|
||||||
|
<setting name="localMavenRepoDir" value="Assets/GeneratedLocalRepo" />
|
||||||
|
<setting name="packageDir" value="Assets/Plugins/Android" />
|
||||||
|
<setting name="patchAndroidManifest" value="True" />
|
||||||
|
<setting name="patchMainTemplateGradle" value="True" />
|
||||||
|
<setting name="projectExportEnabled" value="False" />
|
||||||
|
<setting name="useFullCustomMavenRepoPathWhenExport" value="True" />
|
||||||
|
<setting name="useFullCustomMavenRepoPathWhenNotExport" value="False" />
|
||||||
|
<setting name="useJetifier" value="True" />
|
||||||
|
</settings>
|
||||||
|
</dependencies>
|
||||||
5
ProjectSettings/GvhProjectSettings.xml
Normal file
5
ProjectSettings/GvhProjectSettings.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<projectSettings>
|
||||||
|
<projectSetting name="GooglePlayServices.PromptBeforeAutoResolution" value="False" />
|
||||||
|
<projectSetting name="GooglePlayServices.UseJetifier" value="True" />
|
||||||
|
</projectSettings>
|
||||||
@@ -47,6 +47,8 @@ MonoBehaviour:
|
|||||||
m_Scopes:
|
m_Scopes:
|
||||||
- com.gilzoide.update-manager
|
- com.gilzoide.update-manager
|
||||||
- com.github-glitchenzo.nugetforunity
|
- com.github-glitchenzo.nugetforunity
|
||||||
|
- com.google.ads.mobile
|
||||||
|
- com.google.external-dependency-manager
|
||||||
- com.yasirkula.nativegallery
|
- com.yasirkula.nativegallery
|
||||||
- jp.hadashikick.vcontainer
|
- jp.hadashikick.vcontainer
|
||||||
m_IsDefault: 0
|
m_IsDefault: 0
|
||||||
|
|||||||
Reference in New Issue
Block a user