// 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--;
            }
        }
Beispiel #2
0
        // 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();
        }
Beispiel #3
0
        // 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);
            }
        }