overmelted/Assets/ConjureOS/Scripts/MetadataWindow/ConjureArcadeMetadataWindow.cs

301 lines
12 KiB
C#

#if UNITY_EDITOR
using System;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using ConjureOS.CustomWindow;
namespace ConjureOS.MetadataWindow
{
public class ConjureArcadeMetadataWindow : EditorWindow
{
private const string WindowName = "Arcade Game Metadata Editor";
// Game Metadata
private static ConjureArcadeMetadata metadata;
private ConjureArcadeMetadataValidator metadataValidator;
private SerializedObject serializedObject;
// Metadata Properties
private SerializedProperty gameTitleProperty;
private SerializedProperty versionProperty;
private SerializedProperty descriptionProperty;
private SerializedProperty minNumPlayerProperty;
private SerializedProperty maxNumPlayerProperty;
private SerializedProperty useLeaderboardProperty;
private SerializedProperty thumbnailProperty;
private SerializedProperty gameplayImageProperty;
private SerializedProperty developersProperty;
private SerializedProperty genresProperty;
private ReorderableList developersList;
private ReorderableList genresList;
// UI Properties
private Vector2 scrollPos = Vector2.zero;
private void OnEnable()
{
metadataValidator = new ConjureArcadeMetadataValidator();
titleContent = new GUIContent(WindowName);
if (!metadata)
{
OnLoad();
}
serializedObject = new SerializedObject(metadata);
SetUpProperties(serializedObject);
}
[InitializeOnLoadMethod]
private static void OnLoad()
{
if (!metadata)
{
metadata = AssetDatabase.LoadAssetAtPath<ConjureArcadeMetadata>(ConjureArcadeMetadata.MetadataAssetPath);
// Data exists
if (metadata)
{
return;
}
metadata = CreateInstance<ConjureArcadeMetadata>();
AssetDatabase.CreateAsset(metadata, ConjureArcadeMetadata.MetadataAssetPath);
AssetDatabase.Refresh();
}
}
private void OnGUI()
{
serializedObject.Update();
// Add padding to the window
int globalSpace = 2;
int uniformPadding = ConjureArcadeGUI.Style.UniformPadding;
RectOffset padding = new RectOffset(uniformPadding, uniformPadding, 0, 0);
Rect area = new Rect(
padding.right,
padding.top,
position.width - (padding.left),
position.height - (padding.top + padding.bottom));
// Generate input fields
GUILayout.BeginArea(area);
// Scrollbar
RectOffset vertScrollbarPadding = new RectOffset(uniformPadding, 0, 0, 0);
GUIStyle vertScrollbarSkin = new GUIStyle(GUI.skin.verticalScrollbar);
vertScrollbarSkin.margin = vertScrollbarPadding;
scrollPos = GUILayout.BeginScrollView(scrollPos, false, true, new GUIStyle(GUI.skin.horizontalScrollbar), vertScrollbarSkin);
GUILayout.Space(uniformPadding);
GUILayout.Label("GAME METADATA", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(gameTitleProperty, new GUIContent("Game Title"));
ShowErrorMessage(metadataValidator.GameTitleErrorMessage);
GUILayout.Space(globalSpace);
EditorGUILayout.PropertyField(versionProperty, new GUIContent("Version"));
ShowErrorMessage(metadataValidator.VersionErrorMessage);
GUILayout.Space(globalSpace);
EditorGUILayout.PropertyField(descriptionProperty, new GUIContent("Description"), GUILayout.Height(150));
ShowErrorMessage(metadataValidator.DescriptionErrorMessage);
GUILayout.Space(globalSpace);
EditorGUILayout.PropertyField(minNumPlayerProperty, new GUIContent("Min Number of Players"));
ShowErrorMessage(metadataValidator.MinNumPlayerErrorMessage);
GUILayout.Space(globalSpace);
EditorGUILayout.PropertyField(maxNumPlayerProperty, new GUIContent("Max Number of Players"));
ShowErrorMessage(metadataValidator.MaxNumPlayerErrorMessage);
GUILayout.Space(globalSpace);
EditorGUILayout.PropertyField(useLeaderboardProperty, new GUIContent("Use Leaderboard"));
GUILayout.Space(globalSpace);
EditorGUILayout.PropertyField(thumbnailProperty, new GUIContent("Thumbnail"));
ShowErrorMessage(metadataValidator.ThumbnailErrorMessage);
GUILayout.Space(globalSpace);
EditorGUILayout.PropertyField(gameplayImageProperty, new GUIContent("Gameplay Image"));
ShowErrorMessage(metadataValidator.GameplayImageErrorMessage);
GUILayout.Space(globalSpace);
GUILayout.Space(10);
developersList.DoLayoutList();
ShowErrorMessage(metadataValidator.DevelopersErrorMessage);
GUILayout.Space(10);
UpdateReorderableListInteractions(genresList, ConjureArcadeMetadata.MaxSelectedGenres);
genresList.DoLayoutList();
ShowErrorMessage(metadataValidator.GenresErrorMessage);
GUILayout.Space(10);
// Show release date and last change date ONLY if a date has been set
if (metadata.ReleaseDate != DateTime.MinValue)
{
GUILayout.Label("Release Date: " + metadata.ReleaseDate.ToString());
}
if (metadata.LastGameUpdate != DateTime.MinValue)
{
GUILayout.Label("Last Change: " + metadata.LastGameUpdate.ToString());
}
// Validate properties and save data
serializedObject.ApplyModifiedProperties();
GUILayout.Space(30);
if (GUILayout.Button("Execute Validation", GUILayout.Width(150)))
{
metadataValidator.ValidateMetadata(metadata);
}
GUILayout.Space(globalSpace);
ShowValidationResultMessage();
GUILayout.Space(uniformPadding);
GUILayout.EndScrollView();
GUILayout.EndArea();
}
private void ShowErrorMessage(string errorMessage)
{
if (errorMessage != string.Empty)
{
GUILayout.Label(errorMessage, ConjureArcadeGUI.Style.ErrorStyle);
GUILayout.Space(3);
}
}
private void ShowValidationResultMessage()
{
MetadataValidationStateType validationState = metadataValidator.GetValidationStateType();
switch (validationState)
{
case MetadataValidationStateType.NotVerified:
// No message is displayed
return;
case MetadataValidationStateType.Validated:
// No error, means it's a success
GUILayout.Label(ConjureArcadeGUI.Message.MetadataConfirmedMessage, ConjureArcadeGUI.Style.SuccessStyle);
GUILayout.Space(3);
break;
case MetadataValidationStateType.Failed:
// Errors were detected
string plural = (metadataValidator.ErrorCount > 1) ? "s" : "";
string formatedMessage = string.Format(ConjureArcadeGUI.Message.MetadataFailedMessage, metadataValidator.ErrorCount, plural);
ShowErrorMessage(formatedMessage);
break;
}
}
private void SetUpProperties(SerializedObject serializedObject)
{
// Get data
gameTitleProperty = serializedObject.FindProperty("gameTitle");
versionProperty = serializedObject.FindProperty("version");
descriptionProperty = serializedObject.FindProperty("description");
minNumPlayerProperty = serializedObject.FindProperty("minNumPlayer");
maxNumPlayerProperty = serializedObject.FindProperty("maxNumPlayer");
useLeaderboardProperty = serializedObject.FindProperty("useLeaderboard");
thumbnailProperty = serializedObject.FindProperty("thumbnail");
gameplayImageProperty = serializedObject.FindProperty("gameplayImage");
// Get developers data and prepare list
developersProperty = serializedObject.FindProperty("developers");
developersList = new ReorderableList(serializedObject, developersProperty, true, true, true, true);
developersList.drawElementCallback = DrawDevelopersListItems;
developersList.drawHeaderCallback = DrawDevelopersListHeader;
developersList.onReorderCallback = OnDevelopersReorder;
// Get genres data and prepare list
genresProperty = serializedObject.FindProperty("genres");
genresList = new ReorderableList(serializedObject, genresProperty, true, true, true, true);
genresList.drawElementCallback = DrawGenresListItems;
genresList.drawHeaderCallback = DrawGenresListHeader;
}
private void UpdateReorderableListInteractions(ReorderableList list, int countLimit)
{
// Hide or show the "Add" button only if the count limit has not been reached
if (genresList.count >= countLimit)
{
list.displayAdd = false;
}
else
{
list.displayAdd = true;
}
}
// ReorderableList Callbacks =====
private void DrawGenresListItems(Rect rect, int index, bool isActive, bool isFocused)
{
// Get the selected genre of the current item
var element = genresProperty.GetArrayElementAtIndex(index);
var selectedGenre = element.FindPropertyRelative(nameof(GameGenre.selectedGenre));
var popupHeight = EditorGUI.GetPropertyHeight(selectedGenre);
// Create popup
selectedGenre.intValue = EditorGUI.Popup(new Rect(rect.x, rect.y, rect.width, popupHeight), selectedGenre.intValue, ConjureArcadeMetadata.GenreOptions);
}
private void DrawDevelopersListItems(Rect rect, int index, bool isActive, bool isFocused)
{
// Get the selected genre of the current item
var element = developersProperty.GetArrayElementAtIndex(index);
// Create popup
GUIStyle fieldErrorIndicatorStyle = new GUIStyle(EditorStyles.textField);
fieldErrorIndicatorStyle.normal.textColor = ConjureArcadeGUI.Style.ColorError;
for (int i = 0; i < metadataValidator.DevelopersErrorIndex.Count; i++)
{
if (index == metadataValidator.DevelopersErrorIndex[i])
{
element.stringValue = EditorGUI.TextField(new Rect(rect.x, rect.y, rect.width, rect.height), element.stringValue, fieldErrorIndicatorStyle);
return;
}
}
element.stringValue = EditorGUI.TextField(new Rect(rect.x, rect.y, rect.width, rect.height), element.stringValue);
}
private void DrawGenresListHeader(Rect rect)
{
DrawListHeader(rect, "Genres");
}
private void DrawDevelopersListHeader(Rect rect)
{
DrawListHeader(rect, "Developers");
}
private void DrawListHeader(Rect rect, string name)
{
EditorGUI.LabelField(rect, name);
}
private void OnDevelopersReorder(ReorderableList reList)
{
// On reorder of the developers list, data are revalidated because of the new order
serializedObject.ApplyModifiedProperties();
metadataValidator.ValidateDevelopersList(metadata.Developers);
}
}
}
#endif