// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Standard Library
using System.Collections.Generic;
// Unity
using UnityEditor;
using UnityEngine;
// GameKit
using AWS.GameKit.Common.Models;
using AWS.GameKit.Editor.FileStructure;
using AWS.GameKit.Editor.GUILayoutExtensions;
using AWS.GameKit.Editor.Models;
using AWS.GameKit.Editor.Utils;
using AWS.GameKit.Editor.Windows.Settings;
using AWS.GameKit.Runtime.Models;
namespace AWS.GameKit.Editor.Windows.QuickAccess
{
///
/// Displays the Quick Access window and receives its UI events.
///
public class QuickAccessWindow : EditorWindow
{
private const string WINDOW_TITLE = "AWS GameKit";
private enum InitializationLevel
{
// Initialize() has not been called. The GUI is empty.
Uninitialized,
// Initialize() has been called. The GUI is drawn.
Initialized
}
// Controllers
private SettingsController _settingsWindowController;
private SettingsDependencyContainer _dependencies;
// State
private InitializationLevel _initLevel = InitializationLevel.Uninitialized;
// Fields marked with [SerializeField] are persisted & restored whenever Unity is restarted, Play Mode is entered, or the assembly is rebuilt.
// However, they are cleared when the window is closed. Unlike the SettingsWindow, we don't want to persist these when the window is closed.
[SerializeField] private Vector2 _scrollbarPositions;
// Events
public static event OnWindowEnabled Enabled;
public delegate void OnWindowEnabled(QuickAccessWindow enabledQuickAccessWindow);
private void OnEnable()
{
// Set title
string windowTitle = WINDOW_TITLE;
Texture windowIcon = EditorResources.Textures.WindowIcon.Get();
titleContent = new GUIContent(windowTitle, windowIcon);
// Set minimum size
minSize = new Vector2(QuickAccessGUIStyles.Window.MinWidth, QuickAccessGUIStyles.Window.MinHeight);
// Publish event
Enabled?.Invoke(this);
}
///
/// Initialize this window so it can start drawing the GUI. This is effectively the window's constructor.
///
public void Initialize(SettingsController settingsWindowController, SettingsDependencyContainer dependencies)
{
_settingsWindowController = settingsWindowController;
_dependencies = dependencies;
_initLevel = InitializationLevel.Initialized;
}
private void OnGUI()
{
if (_initLevel == InitializationLevel.Uninitialized)
{
GUILayout.Space(0f);
return;
}
EditorWindowHelper.SetBackgroundColor(this, QuickAccessGUIStyles.Window.BackgroundColor);
_scrollbarPositions = EditorGUILayout.BeginScrollView(_scrollbarPositions);
DrawEnvironmentAndCredentials();
DrawFeatureRows();
EditorGUILayout.EndScrollView();
RefreshButtonColors();
}
private void DrawEnvironmentAndCredentials()
{
}
private void DrawFeatureRows()
{
Dictionary featuresStatus = new Dictionary();
foreach (FeatureSettingsTab featureSettingsTab in FeatureSettingsTab.FeatureSettingsTabsInstances)
{
featuresStatus.Add(featureSettingsTab.FeatureType, featureSettingsTab.GetFeatureStatus());
}
foreach (FeatureType featureType in FeatureTypeEditorData.FeaturesToDisplay)
{
GUILayout.Space(QuickAccessGUIStyles.Window.SpaceBetweenFeatureRows);
FeatureStatus status;
if (!featuresStatus.TryGetValue(featureType, out status))
{
status = _dependencies.FeatureDeploymentOrchestrator.GetFeatureStatus(featureType);
}
DrawFeatureRow(new FeatureRowData(featureType), status);
}
}
private void DrawFeatureRow(FeatureRowData featureRowData, FeatureStatus deploymentStatus)
{
using (EditorGUILayout.HorizontalScope horizontalScope = new EditorGUILayout.HorizontalScope(QuickAccessGUIStyles.FeatureRow.HorizontalLayout, QuickAccessGUIStyles.FeatureRow.HorizontalLayoutOptions))
{
Rect featureRowRect = horizontalScope.rect;
// Background Button
Texture buttonTexture = EditorResources.Textures.Colors.Transparent.Get();
GUIStyle buttonStyle = QuickAccessGUIStyles.FeatureRow.Button;
if (GUI.Button(featureRowRect, buttonTexture, buttonStyle))
{
SettingsWindow.OpenPage(featureRowData.PageType);
}
// Change mouse cursor to a "pointer" when hovering over the button
EditorGUIUtility.AddCursorRect(featureRowRect, MouseCursor.Link);
// Icon
GUILayout.Box(featureRowData.Icon, QuickAccessGUIStyles.FeatureRow.Icon);
GUILayout.Space(3.4f);
// Name & Description
using (new EditorGUILayout.VerticalScope())
{
EditorGUILayout.LabelField(featureRowData.Name, QuickAccessGUIStyles.FeatureRow.Name);
GUILayout.Space(1f);
EditorGUILayout.LabelField(featureRowData.Description, QuickAccessGUIStyles.FeatureRow.Description);
}
GUILayout.FlexibleSpace();
GUILayout.Space(10f);
// Deployment Status
using (new EditorGUILayout.VerticalScope())
{
GUILayout.FlexibleSpace();
EditorGUILayoutElements.DeploymentStatusIcon(deploymentStatus);
GUILayout.FlexibleSpace();
}
using (new EditorGUILayout.VerticalScope())
{
GUILayout.FlexibleSpace();
GUILayout.Label(deploymentStatus.GetDisplayName());
GUILayout.FlexibleSpace();
}
}
}
///
/// Repaint the canvas to make the buttons instantly change their color when the mouse is hovering over them.
///
/// This is a workaround for strange behavior by GUI.Button():
/// - An un-styled GUI.Button() is instantly responsive. It changes color the instant the mouse moves on top or off of the button.
/// - A styled GUI.Button() is very slow to respond (on the order of 1-2 seconds).
///
/// Without this method, it's not possible to have a responsive button with custom colors.
///
private void RefreshButtonColors()
{
wantsMouseMove = true;
if (Event.current.type == EventType.MouseMove)
{
// It is taxing on the GPU to repaint the GUI every frame.
// So we only repaint when the mouse is on the window and it moved during the last frame.
// This limits the increased GPU usage so it only occurs while the user is interacting with the Quick Access window.
Repaint();
}
}
}
}