// Layout entity override protected override void LayoutPropertyField(FieldInfo subfield, SerializedProperty subfieldProperty, GUIContent labelContent, bool canEdit) { // Handle all the same except entities if (canEdit || !string.Equals(subfield.Name, "entities")) { base.LayoutPropertyField(subfield, subfieldProperty, labelContent, canEdit); return; } // Entity foldout subfieldProperty.isExpanded = WitEditorUI.LayoutFoldout(labelContent, subfieldProperty.isExpanded); if (subfieldProperty.isExpanded) { EditorGUI.indentLevel++; if (subfieldProperty.arraySize == 0) { WitEditorUI.LayoutErrorLabel(WitTexts.Texts.ConfigurationEntitiesMissingLabel); } else { for (int i = 0; i < subfieldProperty.arraySize; i++) { SerializedProperty entityProp = subfieldProperty.GetArrayElementAtIndex(i); string entityPropName = entityProp.FindPropertyRelative("name").stringValue; WitEditorUI.LayoutLabel(entityPropName); } } EditorGUI.indentLevel--; } }
// Handles gui layout public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // Return error if (property.serializedObject == null) { string missingText = GetLocalizedText(property, LocalizedMissingKey); WitEditorUI.LayoutErrorLabel(missingText); return; } // Show foldout if desired string titleText = GetLocalizedText(property, LocalizedTitleKey); if (FoldoutEnabled) { property.isExpanded = WitEditorUI.LayoutFoldout(new GUIContent(titleText), property.isExpanded); if (!property.isExpanded) { return; } } // Show title only else { WitEditorUI.LayoutLabel(titleText); } // Indent GUILayout.BeginVertical(); EditorGUI.indentLevel++; // Pre fields OnGUIPreFields(position, property, label); // Iterate all subfields WitPropertyEditType editType = EditType; const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; Type fieldType = fieldInfo.FieldType; if (fieldType.IsArray) { fieldType = fieldType.GetElementType(); } FieldInfo[] subfields = fieldType.GetFields(flags); for (int s = 0; s < subfields.Length; s++) { FieldInfo subfield = subfields[s]; if (ShouldLayoutField(property, subfield)) { LayoutField(s, property, subfield, editType); } } // Post fields OnGUIPostFields(position, property, label); // Undent EditorGUI.indentLevel--; GUILayout.EndVertical(); }
// Layout property field protected virtual void LayoutPropertyField(FieldInfo subfield, SerializedProperty subfieldProperty, GUIContent labelContent, bool canEdit) { // If can edit or not array default layout if (canEdit || !subfield.FieldType.IsArray || subfieldProperty.arraySize <= 0) { EditorGUILayout.PropertyField(subfieldProperty, labelContent); return; } // If cannot edit, handle here subfieldProperty.isExpanded = WitEditorUI.LayoutFoldout(labelContent, subfieldProperty.isExpanded); if (subfieldProperty.isExpanded) { EditorGUI.indentLevel++; for (int i = 0; i < subfieldProperty.arraySize; i++) { SerializedProperty p = subfieldProperty.GetArrayElementAtIndex(i); EditorGUILayout.PropertyField(p); } EditorGUI.indentLevel--; } }
// GUI public override void OnInspectorGUI() { // Display default ui base.OnInspectorGUI(); // Get service if (_service == null) { _service = target as TTSService; } // Add additional gui onAdditionalGUI?.Invoke(_service); // Ignore if in editor if (!Application.isPlaying) { return; } // Add spaces EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.LabelField("Runtime Clip Cache", EditorStyles.boldLabel); // No clips TTSClipData[] clips = _service.GetAllRuntimeCachedClips(); if (clips == null || clips.Length == 0) { WitEditorUI.LayoutErrorLabel("No clips found"); return; } // Has clips _clipFoldout = WitEditorUI.LayoutFoldout(new GUIContent($"Clips: {clips.Length}"), _clipFoldout); if (_clipFoldout) { EditorGUI.indentLevel++; // Iterate clips foreach (TTSClipData clip in clips) { // Get display name string displayName = clip.textToSpeak; // Crop if too long if (displayName.Length > MAX_DISPLAY_TEXT) { displayName = displayName.Substring(0, MAX_DISPLAY_TEXT); } // Add voice setting id if (clip.voiceSettings != null) { displayName = $"{clip.voiceSettings.settingsID} - {displayName}"; } // Foldout if desired bool foldout = WitEditorUI.LayoutFoldout(new GUIContent(displayName), clip); if (foldout) { EditorGUI.indentLevel++; OnClipGUI(clip); EditorGUI.indentLevel--; } } EditorGUI.indentLevel--; } }
// Layout phrase data private bool LayoutPhraseData(TTSPreloadVoiceData voiceData, int phraseIndex, ref bool updated) { // Begin Phrase EditorGUI.indentLevel++; // Get data TTSPreloadPhraseData phraseData = voiceData.phrases[phraseIndex]; string title = $"{(phraseIndex+1)} - {phraseData.textToSpeak}"; // Foldout GUILayout.BeginHorizontal(); bool show = WitEditorUI.LayoutFoldout(new GUIContent(title), phraseData); if (!show) { GUILayout.EndHorizontal(); EditorGUI.indentLevel--; return(true); } // Delete if (WitEditorUI.LayoutTextButton("Delete Phrase")) { voiceData.phrases = DeleteArrayItem <TTSPreloadPhraseData>(voiceData.phrases, phraseIndex); GUILayout.EndHorizontal(); EditorGUI.indentLevel--; updated = true; return(false); } // Begin phrase Data GUILayout.EndHorizontal(); EditorGUI.indentLevel++; // Phrase bool phraseChange = false; WitEditorUI.LayoutTextField(new GUIContent("Phrase"), ref phraseData.textToSpeak, ref phraseChange); if (phraseChange) { TTSPreloadUtility.RefreshPhraseData(TtsService, new TTSDiskCacheSettings() { DiskCacheLocation = TTSDiskCacheLocation.Preload }, TtsService?.GetPresetVoiceSettings(voiceData.presetVoiceID), phraseData); updated = true; } // Clip string clipID = phraseData.clipID; WitEditorUI.LayoutTextField(new GUIContent("Clip ID"), ref clipID, ref phraseChange); // State Color col = GUI.color; Color stateColor = Color.green; string stateValue = "Downloaded"; if (!phraseData.downloaded) { if (phraseData.downloadProgress <= 0f) { stateColor = Color.red; stateValue = "Missing"; } else { stateColor = Color.yellow; stateValue = $"Downloading {(phraseData.downloadProgress * 100f):00.0}%"; } } GUI.color = stateColor; WitEditorUI.LayoutKeyLabel("State", stateValue); GUI.color = col; // End Phrase EditorGUILayout.Space(); EditorGUI.indentLevel--; EditorGUI.indentLevel--; return(true); }
// Layout private bool LayoutVoiceData(TTSPreloadData preloadData, int voiceIndex, ref bool updated) { // Indent EditorGUI.indentLevel++; // Get data TTSPreloadVoiceData voiceData = preloadData.voices[voiceIndex]; string voiceID = voiceData.presetVoiceID; if (string.IsNullOrEmpty(voiceID)) { voiceID = "No Voice Selected"; } voiceID = $"{(voiceIndex+1)} - {voiceID}"; // Foldout GUILayout.BeginHorizontal(); bool show = WitEditorUI.LayoutFoldout(new GUIContent(voiceID), voiceData); if (!show) { GUILayout.EndHorizontal(); EditorGUI.indentLevel--; return(true); } // Delete if (WitEditorUI.LayoutTextButton("Delete Voice")) { DeleteVoice(voiceIndex); GUILayout.EndHorizontal(); EditorGUI.indentLevel--; updated = true; return(false); } // Begin Voice Data GUILayout.EndHorizontal(); EditorGUI.indentLevel++; // Voice Text Field if (TtsService == null || _ttsVoiceIDs == null || _ttsVoiceIDs.Count == 0) { WitEditorUI.LayoutTextField(new GUIContent("Voice ID"), ref voiceData.presetVoiceID, ref updated); } // Voice Preset Select else { int presetIndex = _ttsVoiceIDs.IndexOf(voiceData.presetVoiceID); bool presetUpdated = false; WitEditorUI.LayoutPopup("Voice ID", _ttsVoiceIDs.ToArray(), ref presetIndex, ref presetUpdated); if (presetUpdated) { voiceData.presetVoiceID = _ttsVoiceIDs[presetIndex]; string l = string.Empty; TTSPreloadUtility.RefreshVoiceData(TtsService, voiceData, null, ref l); updated = true; } } // Ensure phrases exist if (voiceData.phrases == null) { voiceData.phrases = new TTSPreloadPhraseData[] { }; } // Phrase Foldout EditorGUILayout.BeginHorizontal(); bool isLayout = WitEditorUI.LayoutFoldout(new GUIContent($"Phrases ({voiceData.phrases.Length})"), voiceData.phrases); if (WitEditorUI.LayoutTextButton("Add Phrase")) { TTSPreloadPhraseData lastPhrase = voiceData.phrases.Length == 0 ? null : voiceData.phrases[voiceData.phrases.Length - 1]; voiceData.phrases = AddArrayItem <TTSPreloadPhraseData>(voiceData.phrases, new TTSPreloadPhraseData() { textToSpeak = lastPhrase?.textToSpeak, clipID = lastPhrase?.clipID }); GUILayout.EndHorizontal(); EditorGUI.indentLevel--; updated = true; return(false); } EditorGUILayout.EndHorizontal(); if (isLayout) { for (int p = 0; p < voiceData.phrases.Length; p++) { if (!LayoutPhraseData(voiceData, p, ref updated)) { break; } } } // End Voice Data EditorGUILayout.Space(); EditorGUI.indentLevel--; EditorGUI.indentLevel--; return(true); }
protected virtual void LayoutContent() { // Begin vertical box GUILayout.BeginVertical(EditorStyles.helpBox); // Check for app name/id update ReloadAppData(); // Title Foldout GUILayout.BeginHorizontal(); string foldoutText = WitTexts.Texts.ConfigurationHeaderLabel; if (!string.IsNullOrEmpty(_appName)) { foldoutText = foldoutText + " - " + _appName; } _foldout = WitEditorUI.LayoutFoldout(new GUIContent(foldoutText), _foldout); // Refresh button if (CanConfigurationRefresh(configuration)) { if (string.IsNullOrEmpty(_appName)) { bool isValid = WitConfigurationUtility.IsServerTokenValid(_serverToken); GUI.enabled = isValid; if (WitEditorUI.LayoutTextButton(WitTexts.Texts.ConfigurationRefreshButtonLabel)) { ApplyServerToken(_serverToken); } } else { bool isRefreshing = configuration.IsRefreshingData(); GUI.enabled = !isRefreshing; if (WitEditorUI.LayoutTextButton(isRefreshing ? WitTexts.Texts.ConfigurationRefreshingButtonLabel : WitTexts.Texts.ConfigurationRefreshButtonLabel)) { SafeRefresh(); } } } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.Space(WitStyles.ButtonMargin); // Show configuration app data if (_foldout) { // Indent EditorGUI.indentLevel++; // Server access token bool updated = false; WitEditorUI.LayoutPasswordField(WitTexts.ConfigurationServerTokenContent, ref _serverToken, ref updated); if (updated) { ApplyServerToken(_serverToken); } // Additional data if (configuration) { LayoutConfigurationData(); } // Undent EditorGUI.indentLevel--; } // End vertical box layout GUILayout.EndVertical(); GUILayout.BeginVertical(EditorStyles.helpBox); LayoutConduitContent(); GUILayout.EndVertical(); // Layout configuration request tabs LayoutConfigurationRequestTabs(); // Additional open wit button GUILayout.FlexibleSpace(); if (GUILayout.Button(OpenButtonLabel, WitStyles.TextButton)) { Application.OpenURL(HeaderUrl); } }