using System; using System.Collections.Generic; using System.IO; using AnyThinkAds.Api; using Runtime.ADAggregator; using UnityEngine; using UnityEngine.EventSystems; public sealed class IAAAdDebugSampleGui : MonoBehaviour { private const float ReferenceWidth = 1080f; private const float ReferenceHeight = 2340f; private const int MaxLogEntries = 120; private const float StatusRefreshInterval = 1f; public ADConfig adConfig; public string userId = "debug_user_001"; public string rewardedScenario = "reward_debug"; public string interstitialScenario = "interstitial_debug"; public bool autoInitialize = true; public bool forcePortrait = true; public bool captureUnityLogs = true; public bool showVerboseState = true; public bool openDebugUiOnButton = true; public bool autoWriteLogsToFile = true; private readonly List _logs = new List(MaxLogEntries); private Vector2 _pageScroll; private Vector2 _logScroll; private Vector2 _rewardedStatusScroll; private Vector2 _interstitialStatusScroll; private bool _initInvoked; private bool _initCallbackReceived; private bool _stylesInitialized; private GUIStyle _titleStyle; private GUIStyle _sectionStyle; private GUIStyle _textStyle; private GUIStyle _buttonStyle; private GUIStyle _textFieldStyle; private GUIStyle _logStyle; private bool _rewardedReadyCache; private bool _interstitialReadyCache; private bool _maskOpen; private string _lastEventLog = ""; private string _rewardedStatusCache = "Not refreshed yet."; private string _interstitialStatusCache = "Not refreshed yet."; private float _nextStatusRefreshTime; private string _sessionLogFilePath; private string _sessionLogDirectory; private void Awake() { Application.targetFrameRate = 60; Screen.sleepTimeout = SleepTimeout.NeverSleep; if (forcePortrait) { Screen.orientation = ScreenOrientation.Portrait; } if (captureUnityLogs) { Application.logMessageReceived += OnLogMessageReceived; } ADManager.Instance.GLOBAL_ShowAwardVideoBefore += OnRewardedBefore; ADManager.Instance.GLOBAL_ShowAwardVideoComplete += OnRewardedComplete; InitializeLogFile(); AppendLog("IAA Ad Debug Sample is ready."); } private void Start() { if (autoInitialize) { TryInitialize(); } RefreshStatusCaches(true); } private void OnDestroy() { if (captureUnityLogs) { Application.logMessageReceived -= OnLogMessageReceived; } ADManager.Instance.GLOBAL_ShowAwardVideoBefore -= OnRewardedBefore; ADManager.Instance.GLOBAL_ShowAwardVideoComplete -= OnRewardedComplete; } private void OnGUI() { EnsureStyles(); var safeArea = Screen.safeArea; var scaleX = safeArea.width / ReferenceWidth; var scaleY = safeArea.height / ReferenceHeight; var previousMatrix = GUI.matrix; GUI.matrix = Matrix4x4.TRS( new Vector3(safeArea.x, safeArea.y, 0f), Quaternion.identity, new Vector3(scaleX, scaleY, 1f)); GUILayout.BeginArea(new Rect(24f, 24f, ReferenceWidth - 48f, ReferenceHeight - 48f), GUI.skin.box); _pageScroll = GUILayout.BeginScrollView(_pageScroll, false, true); DrawHeader(); DrawSetupSection(); DrawStatusSection(); DrawControlSection(); DrawLogSection(); GUILayout.EndScrollView(); GUILayout.EndArea(); GUI.matrix = previousMatrix; } private void DrawHeader() { GUILayout.Label("IAA Ad Debug Sample", _titleStyle); GUILayout.Label( $"Screen: {Screen.width} x {Screen.height} | SafeArea: {Screen.safeArea.width:0} x {Screen.safeArea.height:0}", _textStyle); GUILayout.Label( $"Reference Layout: {ReferenceWidth:0} x {ReferenceHeight:0} | Orientation: {Screen.orientation}", _textStyle); GUILayout.Space(10f); } private void DrawSetupSection() { GUILayout.Label("Setup", _sectionStyle); GUILayout.Label( $"ADConfig Asset: {(adConfig != null ? adConfig.name : "Missing")} | Init Invoked: {_initInvoked} | Init Callback: {_initCallbackReceived}", _textStyle); userId = DrawLabeledTextField("User ID", userId); rewardedScenario = DrawLabeledTextField("Rewarded Scenario", rewardedScenario); interstitialScenario = DrawLabeledTextField("Interstitial Scenario", interstitialScenario); var rewardedPlacement = adConfig?.BaseAwardAdKeyValue?.value ?? string.Empty; var interstitialPlacement = adConfig?.BaseInteractionAdKeyValue?.value ?? string.Empty; GUILayout.Label($"Rewarded Placement: {DisplayValue(rewardedPlacement)}", _textStyle); GUILayout.Label($"Interstitial Placement: {DisplayValue(interstitialPlacement)}", _textStyle); GUILayout.Space(6f); GUILayout.BeginHorizontal(); if (GUILayout.Button("Initialize ADManager", _buttonStyle, GUILayout.Height(78f))) { TryInitialize(); } if (GUILayout.Button("Open DebugUI", _buttonStyle, GUILayout.Height(78f))) { if (EnsureInitialized("Open DebugUI")) { OpenDebugUi(); } } GUILayout.EndHorizontal(); GUILayout.Space(10f); } private void DrawStatusSection() { GUILayout.Label("Runtime Status", _sectionStyle); if (_initInvoked) { RefreshStatusCaches(); GUILayout.Label($"Rewarded Ready: {_rewardedReadyCache}", _textStyle); GUILayout.Label($"Interstitial Ready: {_interstitialReadyCache}", _textStyle); GUILayout.Label($"Mask Open: {_maskOpen}", _textStyle); GUILayout.Label($"Last EventLog: {_lastEventLog}", _textStyle); } else { GUILayout.Label("Rewarded Ready: not initialized", _textStyle); GUILayout.Label("Interstitial Ready: not initialized", _textStyle); } var options = ToponAdController.CurrentOptions; if (options != null) { GUILayout.Label( $"Rewarded Auto/Prewarm/Retry: {options.RewardedAutoLoad}/{options.RewardedPrewarmOnInit}/{options.RewardedMaxLoadAttempts}@{options.RewardedLoadRetryDelayMs}ms", _textStyle); GUILayout.Label( $"Interstitial Auto/Prewarm/Retry: {options.InterstitialAutoLoad}/{options.InterstitialPrewarmOnInit}/{options.InterstitialMaxLoadAttempts}@{options.InterstitialLoadRetryDelayMs}ms", _textStyle); GUILayout.Label( $"Local Strategy Asset: {DisplayValue(options.LocalStrategyAssetPath)}", _textStyle); } if (showVerboseState && _initInvoked) { RefreshStatusCaches(); GUILayout.Space(6f); if (GUILayout.Button("Refresh Status Snapshot", _buttonStyle, GUILayout.Height(64f))) { RefreshStatusCaches(true); AppendLog("Manual status snapshot refreshed."); } GUILayout.Label("Rewarded Status", _sectionStyle); _rewardedStatusScroll = GUILayout.BeginScrollView(_rewardedStatusScroll, GUILayout.Height(240f)); GUILayout.Label(_rewardedStatusCache, _logStyle); GUILayout.EndScrollView(); GUILayout.Label("Interstitial Status", _sectionStyle); _interstitialStatusScroll = GUILayout.BeginScrollView(_interstitialStatusScroll, GUILayout.Height(220f)); GUILayout.Label(_interstitialStatusCache, _logStyle); GUILayout.EndScrollView(); } GUILayout.Space(10f); } private void DrawControlSection() { GUILayout.Label("Ad Actions", _sectionStyle); GUILayout.BeginHorizontal(); if (GUILayout.Button("Enter Rewarded Scene", _buttonStyle, GUILayout.Height(84f))) { if (EnsureInitialized("Enter Rewarded Scene")) { ADManager.Instance.EnterAdScenario(AD_Type.AwardVideo, rewardedScenario); AppendLog($"Enter rewarded scene requested. scenario={rewardedScenario}"); } } if (GUILayout.Button("Enter Interstitial Scene", _buttonStyle, GUILayout.Height(84f))) { if (EnsureInitialized("Enter Interstitial Scene")) { ADManager.Instance.EnterAdScenario(AD_Type.Interaction, interstitialScenario); AppendLog($"Enter interstitial scene requested. scenario={interstitialScenario}"); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Load Rewarded", _buttonStyle, GUILayout.Height(84f))) { if (EnsureInitialized("Load Rewarded")) { ADManager.Instance.LoadAD(AD_Type.AwardVideo); AppendLog("Manual rewarded load requested."); } } if (GUILayout.Button("Async Play Rewarded", _buttonStyle, GUILayout.Height(84f))) { if (EnsureInitialized("Play Rewarded")) { ADManager.Instance.AsyncPlayAD(AD_Type.AwardVideo, rewardedScenario, result => { AppendLog($"Rewarded callback: {result}"); }); AppendLog($"AsyncPlayAD rewarded requested. scenario={rewardedScenario}"); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Load Interstitial", _buttonStyle, GUILayout.Height(84f))) { if (EnsureInitialized("Load Interstitial")) { ADManager.Instance.LoadAD(AD_Type.Interaction); AppendLog("Manual interstitial load requested."); } } if (GUILayout.Button("Async Play Interstitial", _buttonStyle, GUILayout.Height(84f))) { if (EnsureInitialized("Play Interstitial")) { ADManager.Instance.AsyncPlayAD(AD_Type.Interaction, interstitialScenario, result => { AppendLog($"Interstitial callback: {result}"); }); AppendLog($"AsyncPlayAD interstitial requested. scenario={interstitialScenario}"); } } GUILayout.EndHorizontal(); GUILayout.Space(10f); } private void DrawLogSection() { GUILayout.Label("Diagnostics", _sectionStyle); GUILayout.BeginHorizontal(); if (GUILayout.Button("Clear Logs", _buttonStyle, GUILayout.Height(70f))) { _logs.Clear(); AppendLog("Logs cleared."); } if (GUILayout.Button("Copy All Logs", _buttonStyle, GUILayout.Height(70f))) { GUIUtility.systemCopyBuffer = string.Join("\n", _logs); AppendLog($"Copied {_logs.Count} log lines to clipboard."); } if (GUILayout.Button("Log Current Strategy", _buttonStyle, GUILayout.Height(70f))) { var options = ToponAdController.CurrentOptions; if (options == null) { AppendLog("Current strategy unavailable: controller not initialized."); } else { AppendLog( $"Strategy => RewardedAuto={options.RewardedAutoLoad}, RewardedPrewarm={options.RewardedPrewarmOnInit}, InterAuto={options.InterstitialAutoLoad}, InterPrewarm={options.InterstitialPrewarmOnInit}"); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Export Logs To File", _buttonStyle, GUILayout.Height(70f))) { ExportVisibleLogsToFile(); } if (GUILayout.Button("Copy Log File Path", _buttonStyle, GUILayout.Height(70f))) { if (string.IsNullOrWhiteSpace(_sessionLogFilePath)) { AppendLog("Log file path unavailable."); } else { GUIUtility.systemCopyBuffer = _sessionLogFilePath; AppendLog($"Copied log file path: {_sessionLogFilePath}"); } } GUILayout.EndHorizontal(); GUILayout.Label($"Log File: {DisplayValue(_sessionLogFilePath)}", _textStyle); _logScroll = GUILayout.BeginScrollView(_logScroll, GUILayout.Height(520f)); foreach (var line in _logs) { GUILayout.Label(line, _logStyle); } GUILayout.EndScrollView(); } private string DrawLabeledTextField(string label, string value) { GUILayout.BeginHorizontal(); GUILayout.Label(label, _textStyle, GUILayout.Width(260f)); value = GUILayout.TextField(value ?? string.Empty, _textFieldStyle, GUILayout.Height(64f)); GUILayout.EndHorizontal(); return value; } private bool TryInitialize() { if (_initInvoked) { AppendLog("Initialize skipped: ADManager already initialized by sample."); return true; } if (adConfig == null) { AppendLog("Initialize failed: sample ADConfig asset is missing."); return false; } if (string.IsNullOrWhiteSpace(adConfig.Id) || string.IsNullOrWhiteSpace(adConfig.Key)) { AppendLog("Initialize warning: Taku AppId/AppKey is empty. Please fill the sample ADConfig asset."); } _initInvoked = true; var controller = new SampleToponAdController( onMaskChanged: isOpen => { _maskOpen = isOpen; AppendLog($"Mask changed => open={isOpen}"); }, onEventLog: (eventTable, eventValue, eventMessage) => { _lastEventLog = $"{eventTable}:{eventValue}:{eventMessage}"; AppendLog($"EventLog => table={eventTable}, value={eventValue}, message={eventMessage}"); }); ADManager.Instance.Init(() => { _initCallbackReceived = true; AppendLog("ADManager.Init callback received."); }, userId, adConfig, controller); AppendLog($"ADManager.Init invoked with userId={userId}"); AppendLog($"Rewarded placement={adConfig.BaseAwardAdKeyValue?.value}, interstitial placement={adConfig.BaseInteractionAdKeyValue?.value}"); return true; } private bool EnsureInitialized(string actionName) { if (TryInitialize()) { return true; } AppendLog($"{actionName} cancelled: initialization failed."); return false; } private void RefreshStatusCaches(bool force = false) { if (!force && Time.unscaledTime < _nextStatusRefreshTime) { return; } _nextStatusRefreshTime = Time.unscaledTime + StatusRefreshInterval; _rewardedReadyCache = _initInvoked && ADManager.Instance.IsRealy(AD_Type.AwardVideo); _interstitialReadyCache = _initInvoked && ADManager.Instance.IsRealy(AD_Type.Interaction); _rewardedStatusCache = GetRewardedStatusText(); _interstitialStatusCache = GetInterstitialStatusText(); } private string GetRewardedStatusText() { var placement = adConfig?.BaseAwardAdKeyValue?.value; if (string.IsNullOrWhiteSpace(placement)) { return "No rewarded placement configured."; } var options = ToponAdController.CurrentOptions; if (options?.RewardedAutoLoad ?? true) { return ATRewardedAutoVideo.Instance.checkAutoAdStatus(placement); } return ATRewardedVideo.Instance.checkAdStatus(placement); } private string GetInterstitialStatusText() { var placement = adConfig?.BaseInteractionAdKeyValue?.value; if (string.IsNullOrWhiteSpace(placement)) { return "No interstitial placement configured."; } var options = ToponAdController.CurrentOptions; if (options?.InterstitialAutoLoad ?? true) { return ATInterstitialAutoAd.Instance.checkAutoAdStatus(placement); } return ATInterstitialAd.Instance.checkAdStatus(placement); } private void OnRewardedBefore(string placementId, string scenario) { AppendLog($"Rewarded before show => placement={placementId}, scenario={scenario}"); } private void OnRewardedComplete(bool completed) { AppendLog($"Rewarded global complete => reward={completed}"); } private void OnLogMessageReceived(string condition, string stackTrace, LogType type) { if (type != LogType.Error && type != LogType.Exception && type != LogType.Warning) { if (!condition.Contains("[Topon]") && !condition.Contains("ATSDK") && !condition.Contains("Rewarded") && !condition.Contains("Interstitial") && !condition.Contains("Taku")) { return; } } AppendLog($"[{type}] {condition}"); } private void OpenDebugUi() { var options = ToponAdController.CurrentOptions; if (!openDebugUiOnButton) { AppendLog("DebugUI launch disabled by sample toggle."); return; } if (options != null && !string.IsNullOrWhiteSpace(options.DebuggerKey)) { ATSDKAPI.showDebuggerUI(options.DebuggerKey); AppendLog($"Open DebugUI with debugger key={options.DebuggerKey}"); return; } ATSDKAPI.showDebuggerUI(); AppendLog("Open DebugUI with current SDK configuration."); } private void AppendLog(string message) { var line = $"{DateTime.Now:HH:mm:ss} {message}"; if (_logs.Count >= MaxLogEntries) { _logs.RemoveAt(0); } _logs.Add(line); TryAppendLineToFile(line); _logScroll.y = float.MaxValue; } private void InitializeLogFile() { try { _sessionLogDirectory = Path.Combine(Application.persistentDataPath, "IAAAdDebugLogs"); Directory.CreateDirectory(_sessionLogDirectory); var fileName = $"iaa-ad-debug-{DateTime.Now:yyyyMMdd-HHmmss}.log"; _sessionLogFilePath = Path.Combine(_sessionLogDirectory, fileName); File.WriteAllText(_sessionLogFilePath, $"IAA Ad Debug Sample Log{Environment.NewLine}" + $"Created: {DateTime.Now:yyyy-MM-dd HH:mm:ss}{Environment.NewLine}" + $"persistentDataPath: {Application.persistentDataPath}{Environment.NewLine}" + $"----------------------------------------{Environment.NewLine}"); } catch (Exception exception) { _sessionLogFilePath = null; Debug.LogWarning($"[IAA Sample] Failed to initialize log file: {exception.Message}"); } } private void TryAppendLineToFile(string line) { if (!autoWriteLogsToFile || string.IsNullOrWhiteSpace(_sessionLogFilePath)) { return; } try { File.AppendAllText(_sessionLogFilePath, line + Environment.NewLine); } catch (Exception exception) { Debug.LogWarning($"[IAA Sample] Failed to append log file: {exception.Message}"); } } private void ExportVisibleLogsToFile() { try { if (string.IsNullOrWhiteSpace(_sessionLogDirectory)) { InitializeLogFile(); } var exportPath = Path.Combine( _sessionLogDirectory ?? Application.persistentDataPath, $"iaa-ad-debug-export-{DateTime.Now:yyyyMMdd-HHmmss}.log"); File.WriteAllLines(exportPath, _logs); AppendLog($"Exported {_logs.Count} visible log lines to file: {exportPath}"); } catch (Exception exception) { AppendLog($"Export log file failed: {exception.Message}"); } } private static string DisplayValue(string value) { return string.IsNullOrWhiteSpace(value) ? "" : value; } private void EnsureStyles() { if (_stylesInitialized) { return; } _stylesInitialized = true; _titleStyle = new GUIStyle(GUI.skin.label) { fontSize = 54, fontStyle = FontStyle.Bold, alignment = TextAnchor.MiddleCenter, wordWrap = true }; _sectionStyle = new GUIStyle(GUI.skin.label) { fontSize = 34, fontStyle = FontStyle.Bold, wordWrap = true }; _textStyle = new GUIStyle(GUI.skin.label) { fontSize = 28, wordWrap = true }; _buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 28, wordWrap = true }; _textFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 28 }; _logStyle = new GUIStyle(GUI.skin.label) { fontSize = 24, wordWrap = true, richText = false }; } private sealed class SampleToponAdController : IAdController { private readonly ToponAdController _inner = new ToponAdController(); private readonly Action _onMaskChanged; private readonly Action _onEventLog; public SampleToponAdController(Action onMaskChanged, Action onEventLog) { _onMaskChanged = onMaskChanged; _onEventLog = onEventLog; } public void Init(ADConfig adConfig, object[] args) { _inner.Init(adConfig, args); } public ADPlayer CreateAdPlayer(AD_Type type) { return _inner.CreateAdPlayer(type); } public void EventLog(string eventTable, string eventValue, string eventMessage = null) { _onEventLog?.Invoke(eventTable, eventValue, eventMessage); _inner.EventLog(eventTable, eventValue, eventMessage); } public void SetMask(bool isOpen) { _onMaskChanged?.Invoke(isOpen); _inner.SetMask(isOpen); } } }