void InitializeCoppaManager(VisualElement rootVisualElement) { rootVisualElement.AddStyleSheetPath(k_CoppaCommonStyleSheetPath); rootVisualElement.AddStyleSheetPath(EditorGUIUtility.isProSkin ? k_CoppaDarkStyleSheetPath : k_CoppaLightStyleSheetPath); var coppaTemplate = EditorGUIUtility.Load(k_CoppaTemplatePath) as VisualTreeAsset; rootVisualElement.Add(coppaTemplate.CloneTree().contentContainer); m_CoppaContainer = rootVisualElement.Q(coppaContainerName); var persistContainer = m_CoppaContainer.Q(k_PersistContainerName); var coppaField = BuildPopupField(m_CoppaContainer, k_CoppaFieldName); //Setup dashboard link var learnMoreClickable = new Clickable(() => { Application.OpenURL(k_CoppaLearnMoreUrl); }); m_CoppaContainer.Q(k_CoppaLearnLinkBtnName).AddManipulator(learnMoreClickable); var originalCoppaValue = UnityConnect.instance.GetProjectInfo().COPPA; var coppaChoicesList = new List <String>() { L10n.Tr(k_No), L10n.Tr(k_Yes) }; if (originalCoppaValue == COPPACompliance.COPPAUndefined) { coppaChoicesList.Insert(0, L10n.Tr(k_Undefined)); } coppaField.choices = coppaChoicesList; SetCoppaFieldValue(originalCoppaValue, coppaField); persistContainer.Q <Button>(k_SaveBtnName).clicked += () => { try { ServicesConfiguration.instance.RequestCurrentProjectCoppaApiUrl(projectCoppaApiUrl => { var payload = $"{{\"coppa\":\"{GetCompliancyJsonValueFromFieldValue(coppaField)}\"}}"; var uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(payload)); var currentSaveRequest = new UnityWebRequest(projectCoppaApiUrl, UnityWebRequest.kHttpVerbPUT) { uploadHandler = uploadHandler }; currentSaveRequest.suppressErrorsToConsole = true; currentSaveRequest.SetRequestHeader("AUTHORIZATION", $"Bearer {UnityConnect.instance.GetUserInfo().accessToken}"); currentSaveRequest.SetRequestHeader("Content-Type", "application/json;charset=UTF-8"); var operation = currentSaveRequest.SendWebRequest(); SetEnabledCoppaControls(coppaContainer, false); operation.completed += asyncOperation => { try { if (currentSaveRequest.responseCode == k_HttpStatusNoContent) { try { var newCompliancyValue = GetCompliancyForFieldValue(coppaField); if (!UnityConnect.instance.SetCOPPACompliance(newCompliancyValue)) { EditorAnalytics.SendCoppaComplianceEvent(new CoppaState() { isCompliant = newCompliancyValue == COPPACompliance.COPPACompliant }); SetCoppaFieldValue(originalCoppaValue, coppaField); SetPersistContainerVisibility(originalCoppaValue, persistContainer, coppaField); exceptionCallback?.Invoke(originalCoppaValue, new CoppaComplianceEditorConfigurationException(k_CoppaComplianceEditorConfigurationExceptionMessage)); } else { originalCoppaValue = newCompliancyValue; SetCoppaFieldValue(originalCoppaValue, coppaField); SetPersistContainerVisibility(originalCoppaValue, persistContainer, coppaField); NotificationManager.instance.Publish(Notification.Topic.CoppaCompliance, Notification.Severity.Info, L10n.Tr(CoppaComplianceChangedMessage)); saveButtonCallback?.Invoke(originalCoppaValue); } } catch (Exception ex) { SetCoppaFieldValue(originalCoppaValue, coppaField); SetPersistContainerVisibility(originalCoppaValue, persistContainer, coppaField); exceptionCallback?.Invoke(originalCoppaValue, new CoppaComplianceEditorConfigurationException(k_CoppaComplianceEditorConfigurationExceptionMessage, ex)); } finally { currentSaveRequest.Dispose(); currentSaveRequest = null; } } else { try { SetCoppaFieldValue(originalCoppaValue, coppaField); SetPersistContainerVisibility(originalCoppaValue, persistContainer, coppaField); exceptionCallback?.Invoke(originalCoppaValue, new CoppaComplianceWebConfigurationException(L10n.Tr(k_CoppaUnexpectedSaveRequestBehaviorMessage)) { error = currentSaveRequest.error, method = currentSaveRequest.method, timeout = currentSaveRequest.timeout, url = currentSaveRequest.url, responseHeaders = currentSaveRequest.GetResponseHeaders(), responseCode = currentSaveRequest.responseCode, isHttpError = (currentSaveRequest.result == UnityWebRequest.Result.ProtocolError), isNetworkError = (currentSaveRequest.result == UnityWebRequest.Result.ConnectionError), }); } finally { currentSaveRequest.Dispose(); currentSaveRequest = null; } } } finally { SetEnabledCoppaControls(coppaContainer, true); } }; }); } catch (Exception ex) { SetCoppaFieldValue(originalCoppaValue, coppaField); SetPersistContainerVisibility(originalCoppaValue, persistContainer, coppaField); exceptionCallback?.Invoke(originalCoppaValue, ex); } }; persistContainer.Q <Button>(k_CancelBtnName).clicked += () => { SetCoppaFieldValue(originalCoppaValue, coppaField); SetPersistContainerVisibility(originalCoppaValue, persistContainer, coppaField); cancelButtonCallback?.Invoke(originalCoppaValue); }; persistContainer.style.display = DisplayStyle.None; coppaField.RegisterValueChangedCallback(evt => { SetPersistContainerVisibility(originalCoppaValue, persistContainer, coppaField); }); }