Beispiel #1
0
        /// <summary>
        /// Creates a menu containing items for each available language,
        /// and for adding new languages.
        /// </summary>
        /// <returns>The prepared menu.</returns>
        private GenericMenu CreateLanguageMenu()
        {
            var menu = new GenericMenu();

            // Build the list of locales that are present in the currently
            // selected LocalizationDatabase(s).
            var locales = new List <string>();

            foreach (SerializedProperty localization in localizationsProperty)
            {
                if (localization.objectReferenceValue == null)
                {
                    continue;
                }
                var localeCode = (localization.objectReferenceValue as Localization).LocaleCode;

                locales.Add(localeCode);
            }

            foreach (var languageName in ProjectSettings.TextProjectLanguages)
            {
                var culture = Cultures.GetCulture(languageName);

                // A GUIContent for showing the display name of the culture
                GUIContent languageDisplayNameContent = new GUIContent(culture.DisplayName);

                // Does this language already exist in the selected
                // database(s)?
                if (locales.Contains(languageName))
                {
                    // Then add a disabled menu item to represent the fact
                    // that it's a valid language, but can't be added again
                    menu.AddDisabledItem(languageDisplayNameContent);
                }
                else
                {
                    menu.AddItem(
                        languageDisplayNameContent,
                        false,
                        CreateLocalizationWithLanguage,
                        languageName);
                }
            }

            // If there were zero languages available to add, include a
            // note in this menu
            if (menu.GetItemCount() == 0)
            {
                menu.AddDisabledItem(new GUIContent("No languages available"));
            }

            // Finally, add a quick way to get to the screen that lets us
            // add new languages
            menu.AddSeparator("");
            menu.AddItem(new GUIContent("Add More Languages..."), false, ShowYarnSpinnerProjectSettings);

            return(menu);
        }
Beispiel #2
0
        public override void OnInspectorGUI()
        {
            // If true, at least one of the Localizations in the selected
            // LocalizationDatabases are null references; in this case, the
            // Add New Localization button will be disabled (it will be
            // re-enabled when the empty field is filled)
            bool anyLocalizationsAreNull = false;

            if (localizationsProperty.arraySize == 0)
            {
                EditorGUILayout.HelpBox($"This {ObjectNames.NicifyVariableName(nameof(LocalizationDatabase)).ToLowerInvariant()} has no {ObjectNames.NicifyVariableName(nameof(Localization)).ToLowerInvariant()}s. Create a new one, or add an existing one.", MessageType.Info);
            }

            foreach (SerializedProperty property in localizationsProperty)
            {
                // The locale code for this localization ("en-AU")
                string localeCode = null;

                // The human-friendly code for this localization ("English
                // (Australia)")
                string localeCodeDisplayName = null;

                // If true, a localization asset is present in this
                // property
                bool localizationPresent = false;

                // If true, the locale code for this localization asset
                // exists inside the Cultures class's list
                bool cultureIsValid = false;

                if (property.objectReferenceValue != null)
                {
                    localeCode          = (property.objectReferenceValue as Localization).LocaleCode;
                    localizationPresent = true;

                    cultureIsValid = Cultures.HasCulture(localeCode);

                    if (cultureIsValid)
                    {
                        localeCodeDisplayName = Cultures.GetCulture(localeCode).DisplayName;
                    }
                    else
                    {
                        localeCodeDisplayName = "Invalid";
                    }
                }
                else
                {
                    // This property is empty. We'll end up drawing an
                    // empty object field here; record this so that we know
                    // to disable the 'Add Existing' button later.
                    anyLocalizationsAreNull = true;
                }

                using (new EditorGUILayout.HorizontalScope())
                {
                    // If a localization is present, show the display name
                    // and locale code; otherwise, show null (which will
                    // make the corresponding empty field take up the whole
                    // width)
                    string labelContents;
                    if (localizationPresent)
                    {
                        labelContents = localeCodeDisplayName + $" ({localeCode})";
                    }
                    else
                    {
                        labelContents = "";
                    }

                    // Show the property field for this element in the
                    // array
                    EditorGUILayout.PropertyField(property, new GUIContent(labelContents));

                    // Show a button that removes this element
                    if (GUILayout.Button("-", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
                    {
                        // Remove the element from the slot in the array...
                        property.DeleteCommand();
                        // ... and remove the empty slot from the array.
                        property.DeleteCommand();
                    }
                }

                // Is a locale code set that's invalid?
                if (localeCode == null)
                {
                    EditorGUILayout.HelpBox($"Drag and drop a {nameof(Localization)} to this field to add it to this localization database.", MessageType.Info);
                }
                else
                {
                    if (cultureIsValid == false)
                    {
                        // A locale code was set, but this locale code
                        // isn't valid. Show a warning.
                        EditorGUILayout.HelpBox($"'{localeCode}' is not a valid locale. This localization's contents won't be available in the game.", MessageType.Warning);
                    }
                    else if (ProjectSettings.TextProjectLanguages.Contains(localeCode) == false)
                    {
                        // The locale is valid, but the project settings
                        // don't include this language. Show a warning (the
                        // user won't be able to select this localization)
                        const string fixButtonLabel = "Add to Language List";

                        EditorGUILayout.HelpBox($"{localeCodeDisplayName} is not in this project's language list. This localization's contents won't be available in the game.\n\nClick {fixButtonLabel} to fix this issue.", MessageType.Warning);

                        if (GUILayout.Button(fixButtonLabel))
                        {
                            ProjectSettings.AddNewTextLanguage(localeCode);

                            // This will resolve the error, so we'll
                            // immediately repaint
                            Repaint();
                        }

                        // Nice little space to visually associate the
                        // 'add' button with the field and reduce confusion
                        EditorGUILayout.Space();
                    }
                }
            }

            // Show the buttons for adding and creating localizations only
            // if we're not editing multiple databases.
            if (serializedObject.isEditingMultipleObjects == false)
            {
                // Disable the 'add existing' button if there's already an
                // empty field. (Clicking this button adds a new empty field,
                // so we don't want to end up creating multiples.)
                using (new EditorGUI.DisabledScope(anyLocalizationsAreNull))
                {
                    // Show the 'add existing' button, which adds a new
                    // empty field for the user to drop an existing
                    // Localization asset into.
                    if (GUILayout.Button("Add Existing Localisation"))
                    {
                        localizationsProperty.InsertArrayElementAtIndex(localizationsProperty.arraySize);
                        localizationsProperty.GetArrayElementAtIndex(localizationsProperty.arraySize - 1).objectReferenceValue = null;
                    }
                }

                // Show the 'create new' button, which displays the menu of
                // available languages; selecting a language causes a new
                // localization asset to be created with that language, and
                // adds it to this database.
                if (GUILayout.Button("Create New Localization"))
                {
                    var languageMenu = CreateLanguageMenu();

                    languageMenu.ShowAsContext();
                }
            }

            GUILayout.Space(EditorGUIUtility.singleLineHeight);

            // Show information about the scripts we're pulling data from,
            // and offer to update the database now
            if (trackedProgramsProperty.arraySize == 0)
            {
                EditorGUILayout.HelpBox("No Yarn scripts currently use this database.\n\nTo make a Yarn script use this database, select one, and set its Localization Database to this file.", MessageType.Info);
            }
            else
            {
                if (serializedObject.isEditingMultipleObjects == false)
                {
                    EditorGUILayout.LabelField("Uses lines from:");

                    EditorGUI.indentLevel += 1;

                    // List every tracked program, but disable it (we don't
                    // change them here, they're changed in the inspector for
                    // the Yarn script.)
                    using (new EditorGUI.DisabledScope(true))
                    {
                        foreach (SerializedProperty trackedProgramProperty in trackedProgramsProperty)
                        {
                            EditorGUILayout.PropertyField(trackedProgramProperty, new GUIContent());
                        }
                    }

                    EditorGUI.indentLevel -= 1;

                    EditorGUILayout.Space();

                    EditorGUILayout.HelpBox("This database will automatically update when the contents of these scripts change. If you modify the .csv files for other translations, modify any locale-specific assets, or if you need to manually update the database, click Update Database.", MessageType.Info);
                }

                if (GUILayout.Button("Update Database"))
                {
                    foreach (LocalizationDatabase target in serializedObject.targetObjects)
                    {
                        LocalizationDatabaseUtility.UpdateContents(target);
                    }
                }

#if ADDRESSABLES
                // Give a helpful note if addressables are availalbe, but
                // haven't been set up. (In this circumstance,
                // Localizations won't be able to store references to the
                // assets they find.)
                if (AddressableAssetSettingsDefaultObject.SettingsExists == false)
                {
                    EditorGUILayout.HelpBox("The Addressable Assets package has been added, but it hasn't been set up yet. Assets associated with lines won't be included in this database.\n\nTo set up Addressable Assets, choose Window > Asset Management > Addressables > Groups.", MessageType.Info);
                }
#endif
            }

            serializedObject.ApplyModifiedProperties();
        }
        /// <summary>
        /// Draws a language selection popup.
        /// Returns the corresponding SerializedProperty of the drawn language selection popup which be used after ApplyModifiedProperties() to detect changes to the settings.
        /// </summary>
        /// <param name="languagePreference">Determines wheter to draw the Text Language preference or the Audio Language preference.</param>
        private SerializedProperty DrawLanguagePreference(LanguagePreference languagePreference)
        {
            // Declare and set variables depending on the type of language preference to draw
            List <string>      languages              = default;
            SerializedProperty preferencesProperty    = default;
            string             defaultProjectLanguage = default;
            string             infoMessageOnEmptyProjectLanguageList = default;
            string             languagePopupLabel = default;

            switch (languagePreference)
            {
            case LanguagePreference.TextLanguage:
                languages              = _textLanguages;
                preferencesProperty    = _preferences.FindProperty("_textLanguage");
                defaultProjectLanguage = ProjectSettings.TextProjectLanguageDefault;
                infoMessageOnEmptyProjectLanguageList = _emptyTextLanguageMessage;
                languagePopupLabel     = "Text Language";
                _textLanguageLastFrame = preferencesProperty.stringValue;
                break;

            case LanguagePreference.AudioLanguage:
                languages              = _audioLanguage;
                preferencesProperty    = _preferences.FindProperty("_audioLanguage");
                defaultProjectLanguage = ProjectSettings.AudioProjectLanguageDefault;
                infoMessageOnEmptyProjectLanguageList = _emptyAudioLanguageMessage;
                languagePopupLabel      = "Audio Language";
                _audioLanguageLastFrame = preferencesProperty.stringValue;
                break;
            }

            // Get currently available languages and determine which the selected language should be
            int selectedLanguageIndex = -1;

            string[] languagesNamesAvailableForSelection = languages.Count > 0 ? languages.ToArray() : System.Array.Empty <string>();
            var      selectedLanguage = languagesNamesAvailableForSelection
                                        .Select((name, index) => new { name, index })
                                        .FirstOrDefault(element => element.name == preferencesProperty.stringValue);

            if (selectedLanguage != null)
            {
                selectedLanguageIndex = selectedLanguage.index;
            }
            else if (!string.IsNullOrEmpty(defaultProjectLanguage))
            {
                // Assign default language in case the currently selected language has become invalid
                selectedLanguageIndex = 0;
            }
            string[] languagesDisplayNamesAvailableForSelection = languagesNamesAvailableForSelection.Select(name => Cultures.GetCulture(name).DisplayName).ToArray();
            // Disable popup and show message box in case the project languages have been defined yet
            if (languagesNamesAvailableForSelection.Length == 0)
            {
                GUI.enabled = false;
                EditorGUILayout.HelpBox(infoMessageOnEmptyProjectLanguageList, MessageType.Info);
            }
            // Draw the actual language popup
            selectedLanguageIndex = EditorGUILayout.Popup(languagePopupLabel, selectedLanguageIndex, languagesDisplayNamesAvailableForSelection);
            // Change/set the language ID
            if (selectedLanguageIndex != -1)
            {
                preferencesProperty.stringValue = languagesNamesAvailableForSelection[selectedLanguageIndex];
            }
            else
            {
                // null the language ID since the index is invalid
                preferencesProperty.stringValue = string.Empty;
            }
            GUI.enabled = true;

            return(preferencesProperty);
        }