Organize custom scripts under Assets/Baba_yaga and merge Opsive folders to Assets root
This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Editor.Inspectors.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the inspector for an add-on that has been installed.
|
||||
/// </summary>
|
||||
public abstract class AddOnInspector
|
||||
{
|
||||
protected MainManagerWindow m_MainManagerWindow;
|
||||
public MainManagerWindow MainManagerWindow { set { m_MainManagerWindow = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Draws the add-on inspector.
|
||||
/// </summary>
|
||||
public abstract void DrawInspector();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a list of all of the available add-ons.
|
||||
/// </summary>
|
||||
[OrderedEditorItem("Add-Ons", 11)]
|
||||
public class AddOnsManager : Manager
|
||||
{
|
||||
private string[] m_ToolbarStrings = { "Installed Add-Ons", "Available Add-Ons" };
|
||||
[SerializeField] private bool m_DrawInstalledAddOns;
|
||||
[SerializeField] private bool m_Initialized;
|
||||
|
||||
private AddOnInspector[] m_AddOnInspectors;
|
||||
private string[] m_AddOnNames;
|
||||
|
||||
private static GUIStyle s_AddOnTitle;
|
||||
private static GUIStyle AddOnTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_AddOnTitle == null) {
|
||||
s_AddOnTitle = new GUIStyle(InspectorStyles.CenterBoldLabel);
|
||||
s_AddOnTitle.fontSize = 14;
|
||||
s_AddOnTitle.alignment = TextAnchor.MiddleLeft;
|
||||
}
|
||||
return s_AddOnTitle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the information about the add-on.
|
||||
/// </summary>
|
||||
private class AvailableAddOn
|
||||
{
|
||||
private const int c_IconSize = 78;
|
||||
|
||||
private int m_ID;
|
||||
private string m_Name;
|
||||
private string m_AddOnURL;
|
||||
private string m_Description;
|
||||
private bool m_Installed;
|
||||
private Texture2D m_Icon;
|
||||
private MainManagerWindow m_MainManagerWindow;
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
private UnityEngine.Networking.UnityWebRequest m_IconRequest;
|
||||
private UnityEngine.Networking.DownloadHandlerTexture m_TextureDownloadHandler;
|
||||
#else
|
||||
private WWW m_IconRequest;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the AvailableAddOn class.
|
||||
/// </summary>
|
||||
public AvailableAddOn(int id, string name, string iconURL, string addOnURL, string description, string type, MainManagerWindow mainManagerWindow)
|
||||
{
|
||||
m_ID = id;
|
||||
m_Name = name;
|
||||
m_AddOnURL = addOnURL;
|
||||
m_Description = description;
|
||||
// The add-on is installed if the type exists.
|
||||
m_Installed = !string.IsNullOrEmpty(type) && UltimateCharacterController.Utility.UnityEngineUtility.GetType(type) != null;
|
||||
m_MainManagerWindow = mainManagerWindow;
|
||||
|
||||
// Start loading the icon as soon as the url is retrieved.
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
m_TextureDownloadHandler = new UnityEngine.Networking.DownloadHandlerTexture();
|
||||
m_IconRequest = UnityEngine.Networking.UnityWebRequest.Get(iconURL);
|
||||
m_IconRequest.downloadHandler = m_TextureDownloadHandler;
|
||||
m_IconRequest.SendWebRequest();
|
||||
#else
|
||||
m_IconRequest = new WWW(iconURL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the inspector for the available add-on.
|
||||
/// </summary>
|
||||
public void DrawAddOn()
|
||||
{
|
||||
if (m_IconRequest != null) {
|
||||
if (m_IconRequest.isDone) {
|
||||
if (string.IsNullOrEmpty(m_IconRequest.error)) {
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
m_Icon = m_TextureDownloadHandler.texture;
|
||||
#else
|
||||
m_Icon = m_IconRequest.texture;
|
||||
#endif
|
||||
}
|
||||
m_IconRequest = null;
|
||||
} else {
|
||||
m_MainManagerWindow.Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the add-on details.
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (m_Icon != null) {
|
||||
GUILayout.Label(m_Icon);
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginVertical();
|
||||
var name = m_Name;
|
||||
if (m_Installed) {
|
||||
name += " (INSTALLED)";
|
||||
}
|
||||
EditorGUILayout.LabelField(name, InspectorStyles.BoldLabel, GUILayout.Height(20));
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (!string.IsNullOrEmpty(m_AddOnURL) && GUILayout.Button("Overview", GUILayout.MaxWidth(150))) {
|
||||
Application.OpenURL(m_AddOnURL);
|
||||
}
|
||||
if (m_ID > 0 && GUILayout.Button("Asset Store", GUILayout.MaxWidth(150))) {
|
||||
Application.OpenURL("https://opsive.com/asset/UltimateCharacterController/AssetRedirect.php?asset=" + m_ID);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
GUILayout.Space(5);
|
||||
EditorGUILayout.LabelField(m_Description, InspectorStyles.WordWrapLabel);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 m_InstalledScrollPosition;
|
||||
private Vector2 m_AvailableScrollPosition;
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
private UnityEngine.Networking.UnityWebRequest m_AddOnsReqest;
|
||||
#else
|
||||
private WWW m_AddOnsReqest;
|
||||
#endif
|
||||
private AvailableAddOn[] m_AvailableAddOns;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the manager after deserialization.
|
||||
/// </summary>
|
||||
public override void Initialize(MainManagerWindow mainManagerWindow)
|
||||
{
|
||||
base.Initialize(mainManagerWindow);
|
||||
|
||||
BuildInstalledAddOns();
|
||||
|
||||
if (!m_Initialized) {
|
||||
m_DrawInstalledAddOns = m_AvailableAddOns != null && m_AvailableAddOns.Length > 0;
|
||||
m_Initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds and create an instance of the inspectors for all of the installed add-ons.
|
||||
/// </summary>
|
||||
private void BuildInstalledAddOns()
|
||||
{
|
||||
var addOnInspectors = new List<Type>();
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
var addOnIndexes = new List<int>();
|
||||
for (int i = 0; i < assemblies.Length; ++i) {
|
||||
var assemblyTypes = assemblies[i].GetTypes();
|
||||
for (int j = 0; j < assemblyTypes.Length; ++j) {
|
||||
// Must implement AddOnInspector.
|
||||
if (!typeof(AddOnInspector).IsAssignableFrom(assemblyTypes[j])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore abstract classes.
|
||||
if (assemblyTypes[j].IsAbstract) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// A valid inspector class.
|
||||
addOnInspectors.Add(assemblyTypes[j]);
|
||||
var index = addOnIndexes.Count;
|
||||
if (assemblyTypes[j].GetCustomAttributes(typeof(OrderedEditorItem), true).Length > 0) {
|
||||
var item = assemblyTypes[j].GetCustomAttributes(typeof(OrderedEditorItem), true)[0] as OrderedEditorItem;
|
||||
index = item.Index;
|
||||
}
|
||||
addOnIndexes.Add(index);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not reinitialize the inspectors if they are already initialized and there aren't any changes.
|
||||
if (m_AddOnInspectors != null && m_AddOnInspectors.Length == addOnInspectors.Count) {
|
||||
return;
|
||||
}
|
||||
|
||||
// All of the manager types have been found. Sort by the index.
|
||||
var inspectorTypes = addOnInspectors.ToArray();
|
||||
Array.Sort(addOnIndexes.ToArray(), inspectorTypes);
|
||||
|
||||
m_AddOnInspectors = new AddOnInspector[addOnInspectors.Count];
|
||||
m_AddOnNames = new string[addOnInspectors.Count];
|
||||
|
||||
// The inspector types have been found and sorted. Add them to the list.
|
||||
for (int i = 0; i < inspectorTypes.Length; ++i) {
|
||||
m_AddOnInspectors[i] = Activator.CreateInstance(inspectorTypes[i]) as AddOnInspector;
|
||||
m_AddOnInspectors[i].MainManagerWindow = m_MainManagerWindow;
|
||||
|
||||
var name = InspectorUtility.SplitCamelCase(inspectorTypes[i].Name);
|
||||
if (addOnInspectors[i].GetCustomAttributes(typeof(OrderedEditorItem), true).Length > 0) {
|
||||
var item = inspectorTypes[i].GetCustomAttributes(typeof(OrderedEditorItem), true)[0] as OrderedEditorItem;
|
||||
name = item.Name;
|
||||
}
|
||||
m_AddOnNames[i] = name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the Manager.
|
||||
/// </summary>
|
||||
public override void OnGUI()
|
||||
{
|
||||
var toolbarSelection = GUILayout.Toolbar(m_DrawInstalledAddOns ? 0 : 1, m_ToolbarStrings, EditorStyles.toolbarButton);
|
||||
m_DrawInstalledAddOns = toolbarSelection == 0;
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (m_DrawInstalledAddOns) {
|
||||
DrawInstalledAddOns();
|
||||
} else {
|
||||
DrawAvailableAddOns();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the inspector for all installed add-ons.
|
||||
/// </summary>
|
||||
private void DrawInstalledAddOns()
|
||||
{
|
||||
if (m_AddOnInspectors == null || m_AddOnInspectors.Length == 0) {
|
||||
GUILayout.Label("No add-ons are currently installed.\n\nSelect the \"Available Add-Ons\" tab to see a list of all of the available add-ons.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_InstalledScrollPosition = EditorGUILayout.BeginScrollView(m_InstalledScrollPosition);
|
||||
for (int i = 0; i < m_AddOnInspectors.Length; ++i) {
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(m_AddOnNames[i], InspectorStyles.LargeBoldLabel);
|
||||
GUILayout.Space(4);
|
||||
m_AddOnInspectors[i].DrawInspector();
|
||||
EditorGUILayout.EndVertical();
|
||||
if (i != m_AddOnInspectors.Length - 1) {
|
||||
GUILayout.Space(20);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws all of the add-ons that are currently available.
|
||||
/// </summary>
|
||||
private void DrawAvailableAddOns()
|
||||
{
|
||||
if (m_AvailableAddOns == null && m_AddOnsReqest == null) {
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
m_AddOnsReqest = UnityEngine.Networking.UnityWebRequest.Get("https://opsive.com/asset/UltimateCharacterController/AddOnsList.txt");
|
||||
m_AddOnsReqest.SendWebRequest();
|
||||
#else
|
||||
m_AddOnsReqest = new WWW("https://opsive.com/asset/UltimateCharacterController/AddOnsList.txt");
|
||||
#endif
|
||||
} else if (m_AvailableAddOns == null && m_AddOnsReqest.isDone && string.IsNullOrEmpty(m_AddOnsReqest.error) && Event.current.type == EventType.Layout) {
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
var splitAddOns = m_AddOnsReqest.downloadHandler.text.Split('\n');
|
||||
#else
|
||||
var splitAddOns = m_AddOnsReqest.text.Split('\n');
|
||||
#endif
|
||||
m_AvailableAddOns = new AvailableAddOn[splitAddOns.Length];
|
||||
var count = 0;
|
||||
for (int i = 0; i < splitAddOns.Length; ++i) {
|
||||
if (string.IsNullOrEmpty(splitAddOns[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The data must contain info on the add-on name, id, icon, add-on url, description, and type.
|
||||
var addOnData = splitAddOns[i].Split(',');
|
||||
if (addOnData.Length < 6) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_AvailableAddOns[count] = new AvailableAddOn(int.Parse(addOnData[0].Trim()), addOnData[1].Trim(), addOnData[2].Trim(), addOnData[3].Trim(), addOnData[4].Trim(), addOnData[5].Trim(), m_MainManagerWindow);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count != m_AvailableAddOns.Length) {
|
||||
Array.Resize(ref m_AvailableAddOns, count);
|
||||
}
|
||||
m_AddOnsReqest = null;
|
||||
} else if (m_AddOnsReqest != null) {
|
||||
m_MainManagerWindow.Repaint();
|
||||
}
|
||||
|
||||
// Draw the add-ons once they are loaded.
|
||||
if (m_AvailableAddOns != null && m_AvailableAddOns.Length > 0) {
|
||||
m_AvailableScrollPosition = EditorGUILayout.BeginScrollView(m_AvailableScrollPosition);
|
||||
// Draw each add-on.
|
||||
for (int i = 0; i < m_AvailableAddOns.Length; ++i) {
|
||||
m_AvailableAddOns[i].DrawAddOn();
|
||||
if (i != m_AvailableAddOns.Length - 1) {
|
||||
GUILayout.Space(20);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndScrollView();
|
||||
} else {
|
||||
if (m_AddOnsReqest != null && m_AddOnsReqest.isDone && !string.IsNullOrEmpty(m_AddOnsReqest.error)) {
|
||||
EditorGUILayout.LabelField("Error: Unable to retrieve add-ons.");
|
||||
} else {
|
||||
EditorGUILayout.LabelField("Retrieveing the list of current add-ons...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03e4d0a3100a1e6498436b3a670df678
|
||||
timeCreated: 1500577998
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 656810ab70d10d7438b035944bd59d10
|
||||
timeCreated: 1500577975
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,355 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Editor.Inspectors.Utility;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the inspector for an integrations that has been installed.
|
||||
/// </summary>
|
||||
public abstract class IntegrationInspector
|
||||
{
|
||||
protected MainManagerWindow m_MainManagerWindow;
|
||||
public MainManagerWindow MainManagerWindow { set { m_MainManagerWindow = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Draws the integration inspector.
|
||||
/// </summary>
|
||||
public abstract void DrawInspector();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a list of all of the available integrations.
|
||||
/// </summary>
|
||||
[OrderedEditorItem("Integrations", 10)]
|
||||
public class IntegrationsManager : Manager
|
||||
{
|
||||
private const int c_IntegrationCellWidth = 270;
|
||||
private const int c_IntegrationCellHeight = 100;
|
||||
private const int c_IntegrationCellSpacing = 5;
|
||||
|
||||
private string[] m_ToolbarStrings = { "Integration Inspectors", "Available Integrations" };
|
||||
[SerializeField] private bool m_DrawIntegrationInspectors;
|
||||
[SerializeField] private bool m_Initialized;
|
||||
|
||||
private IntegrationInspector[] m_IntegrationInspectors;
|
||||
private string[] m_IntegrationNames;
|
||||
|
||||
private Vector2 m_InstalledScrollPosition;
|
||||
private Vector2 m_AvailableScrollPosition;
|
||||
|
||||
private static GUIStyle s_IntegrationAssetTitle;
|
||||
private static GUIStyle IntegrationAssetTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_IntegrationAssetTitle == null) {
|
||||
s_IntegrationAssetTitle = new GUIStyle(InspectorStyles.CenterBoldLabel);
|
||||
s_IntegrationAssetTitle.fontSize = 14;
|
||||
s_IntegrationAssetTitle.alignment = TextAnchor.MiddleLeft;
|
||||
}
|
||||
return s_IntegrationAssetTitle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the information about the integration asset.
|
||||
/// </summary>
|
||||
private class AssetIntegration
|
||||
{
|
||||
private const int c_IconSize = 78;
|
||||
|
||||
private int m_ID;
|
||||
private string m_Name;
|
||||
private string m_IntegrationURL;
|
||||
private Texture2D m_Icon;
|
||||
private MainManagerWindow m_MainManagerWindow;
|
||||
|
||||
private UnityEngine.Networking.UnityWebRequest m_IconRequest;
|
||||
private UnityEngine.Networking.DownloadHandlerTexture m_TextureDownloadHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the AssetIntegration class.
|
||||
/// </summary>
|
||||
public AssetIntegration(int id, string name, string iconURL, string integrationURL, MainManagerWindow mainManagerWindow)
|
||||
{
|
||||
m_ID = id;
|
||||
m_Name = name;
|
||||
m_IntegrationURL = integrationURL;
|
||||
m_MainManagerWindow = mainManagerWindow;
|
||||
|
||||
// Start loading the icon as soon as the url is retrieved.
|
||||
m_TextureDownloadHandler = new UnityEngine.Networking.DownloadHandlerTexture();
|
||||
m_IconRequest = UnityEngine.Networking.UnityWebRequest.Get(iconURL);
|
||||
m_IconRequest.downloadHandler = m_TextureDownloadHandler;
|
||||
m_IconRequest.SendWebRequest();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the integration details at the specified position.
|
||||
/// </summary>
|
||||
public void DrawIntegration(Vector2 position)
|
||||
{
|
||||
if (m_IconRequest != null) {
|
||||
if (m_IconRequest.isDone) {
|
||||
if (string.IsNullOrEmpty(m_IconRequest.error)) {
|
||||
m_Icon = m_TextureDownloadHandler.texture;
|
||||
}
|
||||
m_IconRequest = null;
|
||||
} else {
|
||||
m_MainManagerWindow.Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the icon, name, and integration/Asset Store link.
|
||||
if (m_Icon != null) {
|
||||
GUI.DrawTexture(new Rect(position.x, position.y, c_IconSize, c_IconSize), m_Icon);
|
||||
}
|
||||
|
||||
var rect = new Rect(position.x + c_IconSize + 10, position.y + 3, 250, 18);
|
||||
EditorGUI.LabelField(rect, m_Name, IntegrationAssetTitle);
|
||||
|
||||
if (!string.IsNullOrEmpty(m_IntegrationURL) && GUI.Button(new Rect(rect.x, rect.y + 23, 80, 18), "Integration")) {
|
||||
Application.OpenURL(m_IntegrationURL);
|
||||
}
|
||||
|
||||
if (m_ID > 0 && GUI.Button(new Rect(rect.x, rect.y + (string.IsNullOrEmpty(m_IntegrationURL) ? 23 : 47), 80, 18), "Asset Store")) {
|
||||
Application.OpenURL("https://opsive.com/asset/UltimateCharacterController/AssetRedirect.php?asset=" + m_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 m_ScrollPosition;
|
||||
private UnityEngine.Networking.UnityWebRequest m_IntegrationsReqest;
|
||||
private AssetIntegration[] m_Integrations;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the manager after deserialization.
|
||||
/// </summary>
|
||||
public override void Initialize(MainManagerWindow mainManagerWindow)
|
||||
{
|
||||
base.Initialize(mainManagerWindow);
|
||||
|
||||
BuildInstalledIntegrations();
|
||||
|
||||
if (!m_Initialized) {
|
||||
m_DrawIntegrationInspectors = m_IntegrationInspectors != null && m_IntegrationInspectors.Length > 0;
|
||||
m_Initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds and create an instance of the inspectors for all of the installed integrations.
|
||||
/// </summary>
|
||||
private void BuildInstalledIntegrations()
|
||||
{
|
||||
var integrationInspectors = new List<Type>();
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
var integrationIndexes = new List<int>();
|
||||
for (int i = 0; i < assemblies.Length; ++i) {
|
||||
var assemblyTypes = assemblies[i].GetTypes();
|
||||
for (int j = 0; j < assemblyTypes.Length; ++j) {
|
||||
// Must implement IntegrationInspector.
|
||||
if (!typeof(IntegrationInspector).IsAssignableFrom(assemblyTypes[j])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore abstract classes.
|
||||
if (assemblyTypes[j].IsAbstract) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// A valid inspector class.
|
||||
integrationInspectors.Add(assemblyTypes[j]);
|
||||
var index = integrationIndexes.Count;
|
||||
if (assemblyTypes[j].GetCustomAttributes(typeof(OrderedEditorItem), true).Length > 0) {
|
||||
var item = assemblyTypes[j].GetCustomAttributes(typeof(OrderedEditorItem), true)[0] as OrderedEditorItem;
|
||||
index = item.Index;
|
||||
}
|
||||
integrationIndexes.Add(index);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not reinitialize the inspectors if they are already initialized and there aren't any changes.
|
||||
if (m_IntegrationInspectors != null && m_IntegrationInspectors.Length == integrationInspectors.Count) {
|
||||
return;
|
||||
}
|
||||
|
||||
// All of the manager types have been found. Sort by the index.
|
||||
var inspectorTypes = integrationInspectors.ToArray();
|
||||
Array.Sort(integrationIndexes.ToArray(), inspectorTypes);
|
||||
|
||||
m_IntegrationInspectors = new IntegrationInspector[integrationInspectors.Count];
|
||||
m_IntegrationNames = new string[integrationInspectors.Count];
|
||||
|
||||
// The inspector types have been found and sorted. Add them to the list.
|
||||
for (int i = 0; i < inspectorTypes.Length; ++i) {
|
||||
m_IntegrationInspectors[i] = Activator.CreateInstance(inspectorTypes[i]) as IntegrationInspector;
|
||||
m_IntegrationInspectors[i].MainManagerWindow = m_MainManagerWindow;
|
||||
|
||||
var name = InspectorUtility.SplitCamelCase(inspectorTypes[i].Name);
|
||||
if (integrationInspectors[i].GetCustomAttributes(typeof(OrderedEditorItem), true).Length > 0) {
|
||||
var item = inspectorTypes[i].GetCustomAttributes(typeof(OrderedEditorItem), true)[0] as OrderedEditorItem;
|
||||
name = item.Name;
|
||||
}
|
||||
m_IntegrationNames[i] = name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the Manager.
|
||||
/// </summary>
|
||||
public override void OnGUI()
|
||||
{
|
||||
var toolbarSelection = GUILayout.Toolbar(m_DrawIntegrationInspectors ? 0 : 1, m_ToolbarStrings, EditorStyles.toolbarButton);
|
||||
m_DrawIntegrationInspectors = toolbarSelection == 0;
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (m_DrawIntegrationInspectors) {
|
||||
DrawIntegrationInspectors();
|
||||
} else {
|
||||
DrawAvailableIntegrations();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the inspector for all installed integrations.
|
||||
/// </summary>
|
||||
private void DrawIntegrationInspectors()
|
||||
{
|
||||
if (m_IntegrationInspectors == null || m_IntegrationInspectors.Length == 0) {
|
||||
GUILayout.Label("No integrations installed use a custom inspector.\n\nSelect the \"Available Integrations\" tab to see a list of all of the available integrations.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_InstalledScrollPosition = EditorGUILayout.BeginScrollView(m_InstalledScrollPosition);
|
||||
for (int i = 0; i < m_IntegrationInspectors.Length; ++i) {
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(m_IntegrationNames[i], InspectorStyles.LargeBoldLabel);
|
||||
GUILayout.Space(4);
|
||||
m_IntegrationInspectors[i].DrawInspector();
|
||||
EditorGUILayout.EndVertical();
|
||||
if (i != m_IntegrationInspectors.Length - 1) {
|
||||
GUILayout.Space(20);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws all of the integrations that are currently available.
|
||||
/// </summary>
|
||||
private void DrawAvailableIntegrations()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Integrations can also be found on the");
|
||||
GUILayout.Space(-3);
|
||||
if (GUILayout.Button("integrations page.", InspectorStyles.LinkStyle, GUILayout.Width(106))) {
|
||||
Application.OpenURL(GetIntegrationLink());
|
||||
}
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (m_Integrations == null && m_IntegrationsReqest == null) {
|
||||
m_IntegrationsReqest = UnityEngine.Networking.UnityWebRequest.Get("https://opsive.com/asset/UltimateCharacterController/IntegrationsList.txt");
|
||||
m_IntegrationsReqest.SendWebRequest();
|
||||
} else if (m_Integrations == null && m_IntegrationsReqest.isDone && string.IsNullOrEmpty(m_IntegrationsReqest.error)) {
|
||||
var splitIntegrations = m_IntegrationsReqest.downloadHandler.text.Split('\n');
|
||||
m_Integrations = new AssetIntegration[splitIntegrations.Length];
|
||||
var count = 0;
|
||||
for (int i = 0; i < splitIntegrations.Length; ++i) {
|
||||
if (string.IsNullOrEmpty(splitIntegrations[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The data must contain info on the integration name, id, icon, and integraiton url.
|
||||
var integrationData = splitIntegrations[i].Split(',');
|
||||
if (integrationData.Length < 4) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_Integrations[count] = new AssetIntegration(int.Parse(integrationData[0].Trim()), integrationData[1].Trim(), integrationData[2].Trim(), integrationData[3].Trim(), m_MainManagerWindow);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count != m_Integrations.Length) {
|
||||
System.Array.Resize(ref m_Integrations, count);
|
||||
}
|
||||
m_IntegrationsReqest = null;
|
||||
} else if (m_IntegrationsReqest != null) {
|
||||
m_MainManagerWindow.Repaint();
|
||||
}
|
||||
|
||||
// Draw the integrations once they are loaded.
|
||||
if (m_Integrations != null && m_Integrations.Length > 0) {
|
||||
var lastRect = GUILayoutUtility.GetLastRect();
|
||||
// Multiple integrations can be drawn on a single row depending on the width of the window.
|
||||
var cellsPerRow = (int)(Screen.width - m_MainManagerWindow.MenuWidth - 2) / (c_IntegrationCellWidth + c_IntegrationCellSpacing);
|
||||
m_ScrollPosition = GUI.BeginScrollView(new Rect(0, lastRect.y, Screen.width - m_MainManagerWindow.MenuWidth - 2, Screen.height - 96), m_ScrollPosition,
|
||||
new Rect(0, 0, Screen.width - m_MainManagerWindow.MenuWidth - 25,
|
||||
((m_Integrations.Length / cellsPerRow) + (m_Integrations.Length % 2 == 0 ? 0 : 1)) * (c_IntegrationCellHeight + c_IntegrationCellSpacing)));
|
||||
var position = new Vector2(0, 20);
|
||||
// Draw each integration.
|
||||
for (int i = 0; i < m_Integrations.Length; ++i) {
|
||||
position.x = (i % cellsPerRow) * c_IntegrationCellWidth;
|
||||
m_Integrations[i].DrawIntegration(position + (new Vector2(0, c_IntegrationCellHeight + c_IntegrationCellSpacing) * (i / cellsPerRow)));
|
||||
}
|
||||
GUI.EndScrollView();
|
||||
} else {
|
||||
if (m_IntegrationsReqest == null) {
|
||||
if (Event.current.type == EventType.Repaint) {
|
||||
m_IntegrationsReqest = UnityEngine.Networking.UnityWebRequest.Get("https://opsive.com/asset/UltimateCharacterController/IntegrationsList.txt");
|
||||
m_IntegrationsReqest.SendWebRequest();
|
||||
}
|
||||
} else {
|
||||
if (m_IntegrationsReqest != null && m_IntegrationsReqest.isDone && !string.IsNullOrEmpty(m_IntegrationsReqest.error)) {
|
||||
EditorGUILayout.LabelField("Error: Unable to retrieve integrations.");
|
||||
} else {
|
||||
EditorGUILayout.LabelField("Retrieveing the list of current integrations...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the integration link for the current asset.
|
||||
/// </summary>
|
||||
/// <returns>The integration link for the current asset.</returns>
|
||||
public static string GetIntegrationLink()
|
||||
{
|
||||
#pragma warning disable 0162
|
||||
#if FIRST_PERSON_CONTROLLER && THIRD_PERSON_CONTROLLER && ULTIMATE_CHARACTER_CONTROLLER_SHOOTER && ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
return "https://opsive.com/downloads/?pid=923";
|
||||
#endif
|
||||
#if FIRST_PERSON_CONTROLLER && ULTIMATE_CHARACTER_CONTROLLER_SHOOTER && ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
return "https://opsive.com/downloads?pid=807";
|
||||
#endif
|
||||
#if THIRD_PERSON_CONTROLLER && ULTIMATE_CHARACTER_CONTROLLER_SHOOTER && ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
return "https://opsive.com/downloads?pid=926";
|
||||
#endif
|
||||
#if FIRST_PERSON_CONTROLLER && ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
|
||||
return "https://opsive.com/downloads?pid=185";
|
||||
#endif
|
||||
#if FIRST_PERSON_CONTROLLER && ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
return "https://opsive.com/downloads?pid=1106";
|
||||
#endif
|
||||
#if THIRD_PERSON_CONTROLLER && ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
|
||||
return "https://opsive.com/downloads?pid=1107";
|
||||
#endif
|
||||
#if THIRD_PERSON_CONTROLLER && ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
return "https://opsive.com/downloads?pid=1108";
|
||||
#endif
|
||||
return string.Empty;
|
||||
#pragma warning restore 0162
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f24fc5d582beec488190d0cd2b3d23c
|
||||
timeCreated: 1500577998
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,931 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
using Opsive.Shared.Inventory;
|
||||
using Opsive.UltimateCharacterController.Editor.Inspectors.Utility;
|
||||
using Opsive.UltimateCharacterController.Editor.Utility;
|
||||
using Opsive.UltimateCharacterController.Inventory;
|
||||
using Opsive.UltimateCharacterController.Items;
|
||||
using Opsive.UltimateCharacterController.Items.Actions;
|
||||
using Opsive.UltimateCharacterController.StateSystem;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using Opsive.UltimateCharacterController.Utility.Builders;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The ItemManager will draw any item properties
|
||||
/// </summary>
|
||||
[OrderedEditorItem("Item", 4)]
|
||||
public class ItemManager : Manager
|
||||
{
|
||||
private string[] m_ToolbarStrings = { "New Item", "Existing Item" };
|
||||
private enum ThirdPersonHumanoidParentHand { Left, Right }
|
||||
|
||||
[SerializeField] private bool m_DrawNewItems = true;
|
||||
|
||||
// New Item.
|
||||
[SerializeField] private string m_Name;
|
||||
[SerializeField] private ItemDefinitionBase m_ItemDefinition;
|
||||
[SerializeField] private int m_AnimatorItemID;
|
||||
[SerializeField] private GameObject m_Character;
|
||||
[SerializeField] private int m_SlotID;
|
||||
[SerializeField] private bool m_AddFirstPersonPerspective = true;
|
||||
[SerializeField] private GameObject m_FirstPersonObject;
|
||||
[SerializeField] private RuntimeAnimatorController m_FirstPersonObjectAnimatorController = null;
|
||||
[SerializeField] private GameObject m_FirstPersonVisibleItem;
|
||||
[SerializeField] private RuntimeAnimatorController m_FirstPersonVisibleItemAnimatorController = null;
|
||||
[SerializeField] private GameObject m_FirstPersonParent;
|
||||
[SerializeField] private bool m_AddThirdPersonPerspective = true;
|
||||
[SerializeField] private GameObject m_ThirdPersonObject;
|
||||
[SerializeField] private RuntimeAnimatorController m_ThirdPersonObjectAnimatorController;
|
||||
[SerializeField] private ThirdPersonHumanoidParentHand m_ThirdHumanoidParentHand = ThirdPersonHumanoidParentHand.Right;
|
||||
[SerializeField] private GameObject m_ThirdPersonParent;
|
||||
[SerializeField] private ItemBuilder.ActionType m_ActionType;
|
||||
[SerializeField] private ItemDefinitionBase m_ActionItemDefinition;
|
||||
[SerializeField] private bool m_AddToDefaultLoadout = true;
|
||||
[SerializeField] private StateConfiguration m_AddStateConfiguration;
|
||||
[SerializeField] private int m_AddProfileIndex;
|
||||
[SerializeField] private string m_AddProfileName;
|
||||
|
||||
// Existing Item.
|
||||
[SerializeField] private Item m_Item;
|
||||
[SerializeField] private ItemBuilder.ActionType m_AddActionType;
|
||||
[SerializeField] private ItemDefinitionBase m_ExistingAddActionItemDefinition;
|
||||
[SerializeField] private int m_RemoveActionTypeIndex;
|
||||
[SerializeField] private GameObject m_ExistingFirstPersonObject;
|
||||
[SerializeField] private RuntimeAnimatorController m_ExistingFirstPersonObjectAnimatorController;
|
||||
[SerializeField] private GameObject m_ExistingFirstPersonVisibleItem;
|
||||
[SerializeField] private GameObject m_ExistingFirstPersonParent;
|
||||
[SerializeField] private RuntimeAnimatorController m_ExistingFirstPersonVisibleItemAnimatorController;
|
||||
[SerializeField] private GameObject m_ExistingThirdPersonObject;
|
||||
[SerializeField] private RuntimeAnimatorController m_ExistingThirdPersonObjectAnimatorController;
|
||||
[SerializeField] private ThirdPersonHumanoidParentHand m_ExistingThirdHumanoidParentHand = ThirdPersonHumanoidParentHand.Right;
|
||||
[SerializeField] private GameObject m_ExistingThirdPersonParent;
|
||||
[SerializeField] private StateConfiguration m_ExistingStateConfiguration;
|
||||
[SerializeField] private int m_ExistingProfileIndex;
|
||||
|
||||
private ItemSlot m_FirstPersonItemSlot = null;
|
||||
private ItemSlot m_ThirdPersonItemSlot = null;
|
||||
private ItemSlot m_ExistingFirstPersonItemSlot = null;
|
||||
private ItemSlot m_ExistingThirdPersonItemSlot = null;
|
||||
|
||||
private Material m_InvisibleShadowCaster;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the manager after deserialization.
|
||||
/// </summary>
|
||||
public override void Initialize(MainManagerWindow mainManagerWindow)
|
||||
{
|
||||
base.Initialize(mainManagerWindow);
|
||||
|
||||
// Find the state configuration.
|
||||
var stateConfiguration = ManagerUtility.FindStateConfiguration(m_MainManagerWindow);
|
||||
if (stateConfiguration != null) {
|
||||
if (m_AddStateConfiguration == null) {
|
||||
m_AddStateConfiguration = stateConfiguration;
|
||||
}
|
||||
if (m_ExistingStateConfiguration == null) {
|
||||
m_ExistingStateConfiguration = stateConfiguration;
|
||||
}
|
||||
}
|
||||
|
||||
m_InvisibleShadowCaster = ManagerUtility.FindInvisibleShadowCaster(m_MainManagerWindow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the ItemManager.
|
||||
/// </summary>
|
||||
public override void OnGUI()
|
||||
{
|
||||
var toolbarSelection = GUILayout.Toolbar(m_DrawNewItems ? 0 : 1, m_ToolbarStrings, EditorStyles.toolbarButton);
|
||||
m_DrawNewItems = toolbarSelection == 0;
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (m_DrawNewItems) {
|
||||
GUILayout.Label("New Item", InspectorStyles.CenterBoldLabel);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("See");
|
||||
GUILayout.Space(-3);
|
||||
if (GUILayout.Button("this page", InspectorStyles.LinkStyle, GUILayout.Width(55))) {
|
||||
Application.OpenURL("https://opsive.com/support/documentation/ultimate-character-controller/getting-started/setup/item-creation/");
|
||||
}
|
||||
GUILayout.Space(-1);
|
||||
GUILayout.Label("for the steps on setting up various item configurations.");
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(10);
|
||||
DrawNewItem();
|
||||
} else {
|
||||
GUILayout.Label("Existing Item", InspectorStyles.CenterBoldLabel);
|
||||
DrawExistingItem();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the UI for new item.
|
||||
/// </summary>
|
||||
private void DrawNewItem()
|
||||
{
|
||||
var canBuild = true;
|
||||
m_Name = EditorGUILayout.TextField(new GUIContent("Name", "Specifies the name of the item. It is recommended that this be a unique name though it is not required."), m_Name);
|
||||
if (string.IsNullOrEmpty(m_Name)) {
|
||||
canBuild = false;
|
||||
EditorGUILayout.HelpBox("The item must have a name.", MessageType.Error);
|
||||
}
|
||||
m_ItemDefinition = EditorGUILayout.ObjectField(new GUIContent("Item Definition", "The Item Definition that the Item should use. The Item Definition works with the Inventory to determine the properties for that item."),
|
||||
m_ItemDefinition, typeof(ItemDefinitionBase), false) as ItemDefinitionBase;
|
||||
if (canBuild && m_ItemDefinition == null) {
|
||||
canBuild = false;
|
||||
EditorGUILayout.HelpBox("The item must specify an Item Definition.", MessageType.Error);
|
||||
} else {
|
||||
// Ensure the Item Definition exists within the collection set by the Item Set Manager.
|
||||
ItemSetManager itemSetManager;
|
||||
if (m_ItemDefinition != null && m_Character != null && (itemSetManager = m_Character.GetComponent<ItemSetManager>()) != null && itemSetManager.ItemCollection != null) {
|
||||
if (AssetDatabase.GetAssetPath(m_ItemDefinition) != AssetDatabase.GetAssetPath(itemSetManager.ItemCollection)) {
|
||||
EditorGUILayout.HelpBox("The Item Definition must exist within the Item Collection specified on the character's Item Set Manager.", MessageType.Error);
|
||||
canBuild = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var character = EditorGUILayout.ObjectField(new GUIContent("Character", "Specifies the character that the Item should be added to. This field should be empty if the item will be added at runtime."),
|
||||
m_Character, typeof(GameObject), true) as GameObject;
|
||||
var characterUpdate = false;
|
||||
if (character != m_Character) {
|
||||
m_Character = character;
|
||||
characterUpdate = true;
|
||||
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
// Try to assign the first person objects if they exist.
|
||||
if (m_Character != null) {
|
||||
var firstPersonObjects = m_Character.GetComponentInChildren<FirstPersonController.Character.FirstPersonObjects>();
|
||||
if (firstPersonObjects != null) {
|
||||
var firstPersonBaseObject = firstPersonObjects.GetComponentInChildren<FirstPersonController.Character.Identifiers.FirstPersonBaseObject>();
|
||||
if (firstPersonBaseObject != null) {
|
||||
m_FirstPersonObject = firstPersonBaseObject.gameObject;
|
||||
}
|
||||
}
|
||||
m_AddThirdPersonPerspective = m_Character.GetComponent<Animator>() != null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (m_Character == null) {
|
||||
m_SlotID = EditorGUILayout.IntField(new GUIContent("Slot ID", "The ID of the slot that the Item should occupy. " +
|
||||
"The Item will be parented to the Item Slot component for the corresponding perspective. " +
|
||||
"The Slot ID must match for both first and third person perspective."), m_SlotID);
|
||||
} else {
|
||||
if (EditorUtility.IsPersistent(m_Character)) {
|
||||
if (canBuild) {
|
||||
EditorGUILayout.HelpBox("The character must be located within the scene.", MessageType.Error);
|
||||
canBuild = false;
|
||||
}
|
||||
} else {
|
||||
// The attach to object must be a character already created.
|
||||
if (m_Character.GetComponentInChildren<ItemPlacement>() == null) {
|
||||
if (canBuild) {
|
||||
EditorGUILayout.HelpBox("The character must be an already created character.", MessageType.Error);
|
||||
canBuild = false;
|
||||
}
|
||||
} else {
|
||||
if (m_ItemDefinition != null & m_Character.GetComponent<Inventory>() != null) {
|
||||
// The item can automatically be added to the default loadout if the inventory component exists.
|
||||
EditorGUI.indentLevel++;
|
||||
m_AddToDefaultLoadout = EditorGUILayout.Toggle(new GUIContent("Add to Default Loadout", "If a character is specified the Item Definition can automatically be added to the Inventory's Default Loadout."),
|
||||
m_AddToDefaultLoadout);
|
||||
EditorGUI.indentLevel--;
|
||||
} else {
|
||||
m_AddToDefaultLoadout = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_AnimatorItemID = EditorGUILayout.IntField(new GUIContent("Animator Item ID",
|
||||
"The ID of the Item within the Animator Controller. " +
|
||||
"This ID is used by the SlotXItemID parameter within the Animator Controller and it must be unique for each item."),
|
||||
m_AnimatorItemID);
|
||||
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
GUILayout.Space(5);
|
||||
GUILayout.Label("First Person", InspectorStyles.BoldLabel);
|
||||
GUI.enabled = m_FirstPersonObject == null && m_FirstPersonVisibleItem == null;
|
||||
m_AddFirstPersonPerspective = EditorGUILayout.Toggle(new GUIContent("Add First Person Item", "Should the first person item perspective be added?"), m_AddFirstPersonPerspective);
|
||||
GUI.enabled = m_AddFirstPersonPerspective;
|
||||
var firstPersonSuccess = DrawFirstPersonObject(m_Character, ref m_FirstPersonObject, ref m_FirstPersonObjectAnimatorController, ref m_FirstPersonVisibleItem,
|
||||
ref m_FirstPersonParent, ref m_FirstPersonItemSlot, ref m_FirstPersonVisibleItemAnimatorController,
|
||||
m_ThirdPersonItemSlot != null ? m_ThirdPersonItemSlot.ID : 0, characterUpdate, canBuild && m_AddFirstPersonPerspective);
|
||||
GUI.enabled = true;
|
||||
if (m_AddFirstPersonPerspective) {
|
||||
if (!firstPersonSuccess) {
|
||||
canBuild = false;
|
||||
} else if (m_ActionType == ItemBuilder.ActionType.MagicItem && (m_FirstPersonObject == null || m_FirstPersonVisibleItem == null)) {
|
||||
canBuild = false;
|
||||
EditorGUILayout.HelpBox("Magic items require an item GameObject (can be empty).", MessageType.Error);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (m_Character == null || (m_Character != null && m_Character.GetComponent<Animator>() != null)) {
|
||||
GUILayout.Space(10);
|
||||
GUILayout.Label("Third Person (including AI and multiplayer)", InspectorStyles.BoldLabel);
|
||||
GUI.enabled = m_ThirdPersonObject == null;
|
||||
m_AddThirdPersonPerspective = EditorGUILayout.Toggle(new GUIContent("Add Third Person Item", "Should the third person item perspective be added?"), m_AddThirdPersonPerspective);
|
||||
GUI.enabled = m_AddThirdPersonPerspective;
|
||||
var thirdPersonSuccess = DrawThirdPersonObject(m_Character, ref m_ThirdPersonObject, ref m_ThirdHumanoidParentHand, ref m_ThirdPersonParent, ref m_ThirdPersonItemSlot,
|
||||
ref m_ThirdPersonObjectAnimatorController, m_FirstPersonItemSlot != null ? m_FirstPersonItemSlot.ID : 0, characterUpdate, canBuild && m_AddThirdPersonPerspective);
|
||||
GUI.enabled = true;
|
||||
if (canBuild && m_AddThirdPersonPerspective) {
|
||||
if (!thirdPersonSuccess) {
|
||||
canBuild = false;
|
||||
} else if (m_ActionType == ItemBuilder.ActionType.MagicItem && m_ThirdPersonObject == null) {
|
||||
canBuild = false;
|
||||
EditorGUILayout.HelpBox("Magic items require an item GameObject (can be empty).", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_AddFirstPersonPerspective && !m_AddThirdPersonPerspective) {
|
||||
if (canBuild) {
|
||||
EditorGUILayout.HelpBox("At least one perspective must be added.", MessageType.Error);
|
||||
canBuild = false;
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(15);
|
||||
m_ActionType = (ItemBuilder.ActionType)EditorGUILayout.EnumPopup(new GUIContent("Action Type",
|
||||
"A drop down field which allows you to specify which Item Action should be added. More Item Actions can be added to the Item through the Existing Item tab."),
|
||||
m_ActionType);
|
||||
|
||||
#if !ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
|
||||
if (m_ActionType == ItemBuilder.ActionType.ShootableWeapon && canBuild) {
|
||||
EditorGUILayout.HelpBox("The shooter controller is necessary in order to create shootable weapons.", MessageType.Error);
|
||||
canBuild = false;
|
||||
}
|
||||
#endif
|
||||
#if !ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
if (m_ActionType == ItemBuilder.ActionType.MeleeWeapon && canBuild) {
|
||||
EditorGUILayout.HelpBox("The melee controller is necessary in order to create melee weapons.", MessageType.Error);
|
||||
canBuild = false;
|
||||
}
|
||||
#endif
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
// The slot IDs must match.
|
||||
if (m_FirstPersonItemSlot != null && m_ThirdPersonItemSlot != null && m_FirstPersonItemSlot.ID != m_ThirdPersonItemSlot.ID && canBuild) {
|
||||
canBuild = false;
|
||||
EditorGUILayout.HelpBox("The first and third person ItemSlots must use the same ID.", MessageType.Error);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_ActionType == ItemBuilder.ActionType.ShootableWeapon) {
|
||||
EditorGUI.indentLevel++;
|
||||
m_ActionItemDefinition = EditorGUILayout.ObjectField("Consumable Item Definition", m_ActionItemDefinition, typeof(ItemDefinitionBase), false) as ItemDefinitionBase;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
// Setup profiles.
|
||||
GUILayout.Space(5);
|
||||
var updatedStateConfiguration = EditorGUILayout.ObjectField(new GUIContent("State Configuration", "Allows for the item to be preconfigured with already defined values. " +
|
||||
"This is useful if you have a specific type of item that has already been created and you'd like to apply the same values to the new item."),
|
||||
m_AddStateConfiguration, typeof(StateConfiguration), false) as StateConfiguration;
|
||||
if (updatedStateConfiguration != m_AddStateConfiguration) {
|
||||
if (updatedStateConfiguration != null) {
|
||||
EditorPrefs.SetString(ManagerUtility.LastStateConfigurationGUIDString, AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(updatedStateConfiguration)));
|
||||
} else {
|
||||
EditorPrefs.SetString(ManagerUtility.LastStateConfigurationGUIDString, string.Empty);
|
||||
}
|
||||
m_AddStateConfiguration = updatedStateConfiguration;
|
||||
}
|
||||
|
||||
if (m_AddStateConfiguration != null) {
|
||||
EditorGUI.indentLevel++;
|
||||
var profiles = m_AddStateConfiguration.GetProfilesForGameObject(null, StateConfiguration.Profile.ProfileType.Item);
|
||||
if (profiles.Count > 0) {
|
||||
// The item can be added without any profiles.
|
||||
profiles.Insert(0, "(None)");
|
||||
m_AddProfileIndex = EditorGUILayout.Popup("Profile", m_AddProfileIndex, profiles.ToArray());
|
||||
m_AddProfileName = profiles[m_AddProfileIndex];
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
GUILayout.Space(5);
|
||||
GUI.enabled = canBuild;
|
||||
if (GUILayout.Button("Build Item")) {
|
||||
var item = ItemBuilder.BuildItem(m_Name, m_ItemDefinition, m_AnimatorItemID, m_Character, m_SlotID, m_AddToDefaultLoadout, m_AddFirstPersonPerspective, m_FirstPersonObject, m_FirstPersonObjectAnimatorController,
|
||||
m_FirstPersonVisibleItem, m_FirstPersonItemSlot, m_FirstPersonVisibleItemAnimatorController, m_AddThirdPersonPerspective, m_ThirdPersonObject, m_ThirdPersonItemSlot, m_ThirdPersonObjectAnimatorController,
|
||||
m_InvisibleShadowCaster, m_ActionType, m_ActionItemDefinition);
|
||||
// Setup any profiles on the item.
|
||||
if (m_AddStateConfiguration != null && m_AddProfileIndex > 0) {
|
||||
m_AddStateConfiguration.AddStatesToGameObject(m_AddProfileName, item.gameObject);
|
||||
InspectorUtility.SetDirty(item.gameObject);
|
||||
} else if (m_AddFirstPersonPerspective && !m_AddThirdPersonPerspective) {
|
||||
// First person items should not use animation events for equip/unequip.
|
||||
var createdItem = item.GetComponent<Item>();
|
||||
createdItem.EquipEvent = new AnimationEventTrigger(false, 0);
|
||||
createdItem.EquipCompleteEvent = new AnimationEventTrigger(false, 0.3f);
|
||||
createdItem.UnequipEvent = new AnimationEventTrigger(false, 0.3f);
|
||||
InspectorUtility.SetDirty(createdItem);
|
||||
} else if (m_AddFirstPersonPerspective && m_AddThirdPersonPerspective) {
|
||||
// A first and third person item is being created. Add a new state which has the correct first person properties.
|
||||
var preset = Shared.Editor.Utility.InspectorUtility.LoadAsset<PersistablePreset>("50a5f74ba80091b47954d1f678ac7823");
|
||||
if (preset != null) {
|
||||
var createdItem = item.GetComponent<Item>();
|
||||
var states = createdItem.States;
|
||||
System.Array.Resize(ref states, states.Length + 1);
|
||||
// Default must always be at the end.
|
||||
states[states.Length - 1] = states[0];
|
||||
states[0] = new State("FirstPerson", preset, null);
|
||||
createdItem.States = states;
|
||||
InspectorUtility.SetDirty(createdItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the animators have the required parameters.
|
||||
if (m_FirstPersonObjectAnimatorController != null) {
|
||||
AnimatorBuilder.AddParameters((UnityEditor.Animations.AnimatorController)m_FirstPersonObjectAnimatorController);
|
||||
}
|
||||
if (m_FirstPersonVisibleItemAnimatorController != null) {
|
||||
AnimatorBuilder.AddParameters((UnityEditor.Animations.AnimatorController)m_FirstPersonVisibleItemAnimatorController);
|
||||
}
|
||||
if (m_ThirdPersonObjectAnimatorController != null) {
|
||||
AnimatorBuilder.AddParameters((UnityEditor.Animations.AnimatorController)m_ThirdPersonObjectAnimatorController);
|
||||
}
|
||||
|
||||
// If the character is null then a prefab will be created.
|
||||
if (m_Character == null) {
|
||||
var path = EditorUtility.SaveFilePanel("Save Item", "Assets", m_Name + ".prefab", "prefab");
|
||||
if (path.Length != 0 && Application.dataPath.Length < path.Length) {
|
||||
var relativePath = path.Replace(Application.dataPath, "");
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
PrefabUtility.SaveAsPrefabAsset(item, "Assets" + relativePath);
|
||||
#else
|
||||
PrefabUtility.CreatePrefab("Assets" + relativePath, item);
|
||||
#endif
|
||||
Object.DestroyImmediate(item, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the original objects if they are in the scene - this will prevent duplicate objects from existing.
|
||||
if (m_FirstPersonVisibleItem != null && !EditorUtility.IsPersistent(m_FirstPersonVisibleItem) &&
|
||||
(m_Character == null || !m_FirstPersonVisibleItem.transform.IsChildOf(m_Character.transform))) {
|
||||
Object.DestroyImmediate(m_FirstPersonVisibleItem, true);
|
||||
m_FirstPersonVisibleItem = null;
|
||||
}
|
||||
if (m_FirstPersonObject != null && !EditorUtility.IsPersistent(m_FirstPersonObject) &&
|
||||
(m_Character == null || !m_FirstPersonObject.transform.IsChildOf(m_Character.transform))) {
|
||||
Object.DestroyImmediate(m_FirstPersonObject, true);
|
||||
m_FirstPersonObject = null;
|
||||
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
// The base object should be updated to the new instance.
|
||||
if (m_Character != null) {
|
||||
var firstPersonObjects = m_Character.GetComponentInChildren<FirstPersonController.Character.FirstPersonObjects>();
|
||||
if (firstPersonObjects != null) {
|
||||
var firstPersonBaseObject = firstPersonObjects.GetComponentInChildren<FirstPersonController.Character.Identifiers.FirstPersonBaseObject>();
|
||||
if (firstPersonBaseObject != null) {
|
||||
m_FirstPersonObject = firstPersonBaseObject.gameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (m_ThirdPersonObject != null && !EditorUtility.IsPersistent(m_ThirdPersonObject) &&
|
||||
(m_Character == null || !m_ThirdPersonObject.transform.IsChildOf(m_Character.transform))) {
|
||||
Object.DestroyImmediate(m_ThirdPersonObject, true);
|
||||
m_ThirdPersonObject = null;
|
||||
}
|
||||
|
||||
// Select the newly added item.
|
||||
Selection.activeGameObject = item.gameObject;
|
||||
}
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
/// <summary>
|
||||
/// Draws the controls for the first person object fields.
|
||||
/// </summary>
|
||||
/// <param name="character">The character that has the item (can be null).</param>
|
||||
/// <param name="firstPersonObject">A reference to the first person object.</param>
|
||||
/// <param name="firstPersonObjectAnimatorController">A reference to the animator controller added to the first person object. Can be null.</param>
|
||||
/// <param name="firstPersonVisibleItem">A reference to the first person visible item.</param>
|
||||
/// <param name="firstPersonParent">A reference to the first person parent.</param>
|
||||
/// <param name="firstPersonItemSlot">The ItemSlot on the parent GameObject.</param>
|
||||
/// <param name="firstPersonVisibleItemAnimatorController">A reference to the animator controller added to the first person visible item. Can be null.</param>
|
||||
/// <param name="defaultItemSlotIndex">The index of the default item slot.</param>
|
||||
/// <param name="characterUpdate">Was the character field updated?</param>
|
||||
/// <param name="showError">Should the error be shown (if any)?</param>
|
||||
/// <returns>Was the objects drawn successfully?</returns>
|
||||
private bool DrawFirstPersonObject(GameObject character, ref GameObject firstPersonObject, ref RuntimeAnimatorController firstPersonObjectAnimatorController, ref GameObject firstPersonVisibleItem,
|
||||
ref GameObject firstPersonParent, ref ItemSlot firstPersonItemSlot, ref RuntimeAnimatorController firstPersonVisibleItemAnimatorController,
|
||||
int defaultItemSlotIndex, bool characterUpdate, bool showError)
|
||||
{
|
||||
var success = true;
|
||||
firstPersonObject = EditorGUILayout.ObjectField(new GUIContent("First Person Base", "A reference to the base object that should be used by the first person item. This will usually be the character’s separated arms. " +
|
||||
"A single object can be used for multiple Items. If a First Person Visible Item is specified this object should be within the scene so the Item Slot can be specified."),
|
||||
firstPersonObject, typeof(GameObject), true) as GameObject;
|
||||
if (character != null && firstPersonObject == null) {
|
||||
success = false;
|
||||
if (showError) {
|
||||
EditorGUILayout.HelpBox("A first person base object is required.", MessageType.Error);
|
||||
}
|
||||
} else if (firstPersonObject != null) {
|
||||
if (EditorUtility.IsPersistent(firstPersonObject)) {
|
||||
success = false;
|
||||
if (showError) {
|
||||
EditorGUILayout.HelpBox("Please drag your first person base object into the scene. The Item Manager cannot add components to prefabs.", MessageType.Error);
|
||||
}
|
||||
} else {
|
||||
if (firstPersonObject.GetComponent<Character.UltimateCharacterLocomotion>() != null) {
|
||||
if (showError) {
|
||||
EditorGUILayout.HelpBox("The First Person Base object cannot be a created character.", MessageType.Error);
|
||||
}
|
||||
success = false;
|
||||
} else {
|
||||
Animator animator;
|
||||
if ((animator = firstPersonObject.GetComponent<Animator>()) == null || animator.runtimeAnimatorController == null) {
|
||||
EditorGUI.indentLevel++;
|
||||
firstPersonObjectAnimatorController = EditorGUILayout.ObjectField(new GUIContent("Animator Controller",
|
||||
"A reference to the Animator Controller used by the First Person Base field. " +
|
||||
"This Animator Controller will only be active when the Item is equipped."),
|
||||
firstPersonObjectAnimatorController, typeof(RuntimeAnimatorController), false) as RuntimeAnimatorController;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var visibleItem = EditorGUILayout.ObjectField(new GUIContent("First Person Visible Item", "Specifies the Item object that is actually visible and rendered to the screen, such as the assault rifle or sword. " +
|
||||
"This field should be left blank if you are adding an item that is part of the character’s body such as a fist for punching."),
|
||||
firstPersonVisibleItem, typeof(GameObject), true) as GameObject;
|
||||
// The visible item should not have the Item component.
|
||||
if (visibleItem != null && visibleItem.GetComponent<Item>()) {
|
||||
success = false;
|
||||
if (showError) {
|
||||
EditorGUILayout.HelpBox("The visible item should not be an already created item. The visible item should be a model representing the item.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
// Preselect the parent if the first person object is not null.
|
||||
if ((visibleItem != firstPersonVisibleItem || characterUpdate) && visibleItem != null && firstPersonObject != null) {
|
||||
var itemSlots = firstPersonObject.GetComponentsInChildren<ItemSlot>();
|
||||
if (itemSlots.Length > 0) {
|
||||
var itemSlot = itemSlots[0];
|
||||
for (int i = 1; i < itemSlots.Length; ++i) {
|
||||
if (itemSlots[i].ID == defaultItemSlotIndex) {
|
||||
itemSlot = itemSlots[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
firstPersonParent = itemSlot.gameObject;
|
||||
}
|
||||
}
|
||||
firstPersonVisibleItem = visibleItem;
|
||||
if ((character != null && (firstPersonObject == null && firstPersonVisibleItem != null)) ||
|
||||
(firstPersonObject != null && firstPersonVisibleItem != null && !firstPersonVisibleItem.transform.IsChildOf(firstPersonObject.transform))) {
|
||||
EditorGUI.indentLevel++;
|
||||
var invalidItemSlot = false;
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
firstPersonParent = EditorGUILayout.ObjectField(new GUIContent("Item Parent", "Specifies the object that the First Person Visible Item should be parented to. This GameObject must have the ItemSlot component."),
|
||||
firstPersonParent, typeof(GameObject), true) as GameObject;
|
||||
if (firstPersonParent == null) {
|
||||
invalidItemSlot = true;
|
||||
} else {
|
||||
// The First Person Parent should be a child of the FirstPersonObjects component.
|
||||
if ((firstPersonObject == null && firstPersonParent.GetComponentInParent<UltimateCharacterController.FirstPersonController.Character.FirstPersonObjects>() == null) ||
|
||||
firstPersonObject != null && !firstPersonParent.transform.IsChildOf(firstPersonObject.transform)) {
|
||||
invalidItemSlot = true;
|
||||
} else if ((firstPersonItemSlot = firstPersonParent.GetComponent<ItemSlot>()) == null) {
|
||||
// Allow for some leeway if there is only one child ItemSlot component.
|
||||
var itemSlots = firstPersonParent.GetComponentsInChildren<ItemSlot>();
|
||||
if (itemSlots.Length == 1) {
|
||||
firstPersonParent = itemSlots[0].gameObject;
|
||||
} else {
|
||||
invalidItemSlot = true;
|
||||
// Allow the ItemSlot to be added.
|
||||
if (GUILayout.Button("Add ItemSlot", GUILayout.Width(150))) {
|
||||
firstPersonParent = AddItemSlot(character != null ? character : firstPersonObject, firstPersonParent.transform, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (invalidItemSlot) {
|
||||
success = false;
|
||||
if (showError) {
|
||||
EditorGUILayout.HelpBox("The first person Item Parent field does not specify a valid ItemSlot GameObject.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
if (firstPersonVisibleItem != null) {
|
||||
EditorGUI.indentLevel++;
|
||||
firstPersonVisibleItemAnimatorController = EditorGUILayout.ObjectField(new GUIContent("Animator Controller", "Specifies the Animator Controller that should be used by the First Person Visible Item."),
|
||||
firstPersonVisibleItemAnimatorController, typeof(RuntimeAnimatorController), false) as RuntimeAnimatorController;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Draws the controls for the third person object fields.
|
||||
/// </summary>
|
||||
/// <param name="character">The character that has the item (can be null).</param>
|
||||
/// <param name="thirdPersonObject">A reference to the third person object.</param>
|
||||
/// <param name="parentHand">A reference to the third person hand.</param>
|
||||
/// <param name="thirdPersonParent">A reference to the third person parent.</param>
|
||||
/// <param name="thirdPersonItemSlot">The ItemSlot on the parent GameObject.</param>
|
||||
/// <param name="defaultItemSlotIndex">The index of the default item slot.</param>
|
||||
/// <param name="characterUpdate">Was the character field updated?</param>
|
||||
/// <param name="showError">Should the error be shown (if any)?</param>
|
||||
/// <returns>Was the objects drawn successfully?</returns>
|
||||
private bool DrawThirdPersonObject(GameObject character, ref GameObject thirdPersonObject, ref ThirdPersonHumanoidParentHand parentHand, ref GameObject thirdPersonParent,
|
||||
ref ItemSlot thirdPersonItemSlot, ref RuntimeAnimatorController thirdPersonObjectAnimatorController,
|
||||
int defaultItemSlotIndex, bool characterUpdate, bool showError)
|
||||
{
|
||||
var success = true;
|
||||
var prevThirdPersonObject = thirdPersonObject;
|
||||
thirdPersonObject = EditorGUILayout.ObjectField(new GUIContent("Third Person Visible Item", "Specifies the third person item object. " +
|
||||
"This is the object that will be visible and rendered to the screen, such as the assault rifle or sword."),
|
||||
thirdPersonObject, typeof(GameObject), true) as GameObject;
|
||||
if (thirdPersonObject != null && thirdPersonObject.GetComponent<Item>()) {
|
||||
success = false;
|
||||
if (showError) {
|
||||
EditorGUILayout.HelpBox("The visible item should not be an already created item. The visible item should be a model representing the item.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
if (thirdPersonObject != null && character != null) {
|
||||
EditorGUI.indentLevel++;
|
||||
var invalidItemSlot = false;
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
var animator = character.GetComponent<Animator>();
|
||||
|
||||
// Setup the default ItemSlot to be the same ID as the first person perspective.
|
||||
if (prevThirdPersonObject != thirdPersonObject || characterUpdate) {
|
||||
var itemSlots = character.GetComponentsInChildren<ItemSlot>();
|
||||
for (int i = 0; i < itemSlots.Length; ++i) {
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
if (itemSlots[i].GetComponentInParent<UltimateCharacterController.FirstPersonController.Character.Identifiers.FirstPersonBaseObject>() != null) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (itemSlots[i].ID == defaultItemSlotIndex) {
|
||||
thirdPersonItemSlot = itemSlots[i];
|
||||
thirdPersonParent = thirdPersonItemSlot.gameObject;
|
||||
|
||||
if (animator != null && animator.GetBoneTransform(HumanBodyBones.Head) != null) {
|
||||
if (thirdPersonParent.transform.IsChildOf(animator.GetBoneTransform(HumanBodyBones.RightHand))) {
|
||||
parentHand = ThirdPersonHumanoidParentHand.Right;
|
||||
} else {
|
||||
parentHand = ThirdPersonHumanoidParentHand.Left;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show a dropdown for the humanoid characters.
|
||||
if (animator != null && animator.GetBoneTransform(HumanBodyBones.Head) != null) {
|
||||
var hand = (ThirdPersonHumanoidParentHand)EditorGUILayout.EnumPopup("Hand", parentHand);
|
||||
if (thirdPersonParent == null || hand != parentHand) {
|
||||
parentHand = hand;
|
||||
var handTransform = animator.GetBoneTransform(hand == ThirdPersonHumanoidParentHand.Right ? HumanBodyBones.RightHand : HumanBodyBones.LeftHand);
|
||||
var itemSlot = handTransform.GetComponentInChildren<ItemSlot>();
|
||||
if (itemSlot != null) {
|
||||
thirdPersonParent = itemSlot.gameObject;
|
||||
} else {
|
||||
thirdPersonParent = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
thirdPersonParent = EditorGUILayout.ObjectField(new GUIContent("Item Parent", "Specifies the object that the Third Person Visible Item should be parented to. This GameObject must have the ItemSlot component."),
|
||||
thirdPersonParent, typeof(GameObject), true) as GameObject;
|
||||
}
|
||||
if (thirdPersonParent == null) {
|
||||
invalidItemSlot = true;
|
||||
} else {
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
// The Third Person Parent should not be a child of the FirstPersonObjects component.
|
||||
if (thirdPersonParent.GetComponentInParent<UltimateCharacterController.FirstPersonController.Character.FirstPersonObjects>() != null) {
|
||||
invalidItemSlot = true;
|
||||
} else {
|
||||
#endif
|
||||
if ((thirdPersonItemSlot = thirdPersonParent.GetComponent<ItemSlot>()) == null) {
|
||||
// Allow for some leeway if there is only one child ItemSlot component.
|
||||
var itemSlots = thirdPersonParent.GetComponentsInChildren<ItemSlot>();
|
||||
if (itemSlots.Length == 1) {
|
||||
thirdPersonParent = itemSlots[0].gameObject;
|
||||
} else {
|
||||
success = false;
|
||||
// Allow the ItemSlot to be added.
|
||||
if (GUILayout.Button("Add ItemSlot", GUILayout.Width(150))) {
|
||||
thirdPersonParent = AddItemSlot(character, thirdPersonParent.transform, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
}
|
||||
#endif
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (invalidItemSlot) {
|
||||
success = false;
|
||||
if (showError) {
|
||||
EditorGUILayout.HelpBox("The third person Item Parent field does not specify a valid ItemSlot GameObject.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
if (thirdPersonObject != null) {
|
||||
EditorGUI.indentLevel++;
|
||||
thirdPersonObjectAnimatorController = EditorGUILayout.ObjectField(new GUIContent("Animator Controller", "Specifies the Animator Controller that should be used by the Third Person Visible Item."),
|
||||
thirdPersonObjectAnimatorController, typeof(RuntimeAnimatorController), false) as RuntimeAnimatorController;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an ItemSlot child GameObject to the specified parent.
|
||||
/// </summary>
|
||||
/// <param name="baseParent">The object that is adding the item slot.</param>
|
||||
/// <param name="itemParent">The object to add the ItemSlot to.</param>
|
||||
/// <param name="firstPerson">Should a first person ItemSlot be added?</param>
|
||||
/// <returns>The added the ItemSlot GameObject (can be null).</returns>
|
||||
private GameObject AddItemSlot(GameObject baseParent, Transform itemParent, bool firstPerson)
|
||||
{
|
||||
// The new ItemSlot's ID should be unique.
|
||||
var allItemSlots = baseParent.GetComponentsInChildren<ItemSlot>();
|
||||
var maxID = -1;
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
var firstPersonObjects = baseParent.GetComponentInChildren<UltimateCharacterController.FirstPersonController.Character.FirstPersonObjects>();
|
||||
#endif
|
||||
for (int i = 0; i < allItemSlots.Length; ++i) {
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
// The ItemSlot must match the perspective.
|
||||
if (firstPersonObjects != null && (allItemSlots[i].transform.IsChildOf(firstPersonObjects.transform) != firstPerson)){
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (allItemSlots[i].ID > maxID) {
|
||||
maxID = allItemSlots[i].ID;
|
||||
}
|
||||
}
|
||||
// Setup the new ItemSlot.
|
||||
var itemSlotGameObject = new GameObject("Items", new System.Type[] { typeof(ItemSlot) });
|
||||
itemSlotGameObject.transform.SetParentOrigin(itemParent);
|
||||
var itemSlot = itemSlotGameObject.GetComponent<ItemSlot>();
|
||||
// The new ID should be one greater than the previous max ID.
|
||||
itemSlot.ID = maxID + 1;
|
||||
return itemSlotGameObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the UI for existing item.
|
||||
/// </summary>
|
||||
private void DrawExistingItem()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
m_Item = EditorGUILayout.ObjectField("Item", m_Item, typeof(Item), true) as Item;
|
||||
GUI.enabled = m_Item != null;
|
||||
if (GUILayout.Button("Remove", GUILayout.Width(80))) {
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
var firstPersonVisibleItemObject = m_Item.GetComponent<UltimateCharacterController.FirstPersonController.Items.FirstPersonPerspectiveItem>();
|
||||
if (firstPersonVisibleItemObject != null) {
|
||||
ItemBuilder.RemoveFirstPersonObject(firstPersonVisibleItemObject);
|
||||
}
|
||||
#endif
|
||||
var thirdPersonVisibleItemObject = m_Item.GetComponent<UltimateCharacterController.ThirdPersonController.Items.ThirdPersonPerspectiveItem>();
|
||||
if (thirdPersonVisibleItemObject != null) {
|
||||
ItemBuilder.RemoveThirdPersonObject(thirdPersonVisibleItemObject);
|
||||
}
|
||||
// The ItemDefinition should also be removed from the Inventory/ItemSetManager.
|
||||
var inventory = m_Item.GetComponentInParent<Inventory>();
|
||||
if (inventory != null) {
|
||||
var defaultLoadout = new System.Collections.Generic.List<ItemDefinitionAmount>(inventory.DefaultLoadout);
|
||||
for (int i = defaultLoadout.Count - 1; i > -1; --i) {
|
||||
if (defaultLoadout[i].ItemDefinition == m_Item.ItemDefinition) {
|
||||
defaultLoadout.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
inventory.DefaultLoadout = defaultLoadout.ToArray();
|
||||
EditorUtility.SetDirty(inventory);
|
||||
}
|
||||
|
||||
var itemSetManager = inventory.GetComponent<ItemSetManager>();
|
||||
if (itemSetManager != null) {
|
||||
for (int i = 0; i < itemSetManager.CategoryItemSets.Length; ++i) {
|
||||
var category = itemSetManager.CategoryItemSets[i];
|
||||
for (int j = category.ItemSetList.Count - 1; j > -1; --j) {
|
||||
if (category.ItemSetList[j].Slots[m_Item.SlotID] == m_Item.ItemDefinition) {
|
||||
category.ItemSetList.RemoveAt(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
EditorUtility.SetDirty(itemSetManager);
|
||||
}
|
||||
|
||||
Undo.DestroyObjectImmediate(m_Item.gameObject);
|
||||
m_Item = null;
|
||||
}
|
||||
GUI.enabled = m_Item != null;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// Actions can be removed.
|
||||
if (m_Item != null) {
|
||||
var actions = m_Item.GetComponents<ItemAction>();
|
||||
if (actions.Length > 0) {
|
||||
var actionStrings = new string[actions.Length];
|
||||
for (int i = 0; i < actions.Length; ++i) {
|
||||
actionStrings[i] = InspectorUtility.DisplayTypeName(actions[i].GetType(), false);
|
||||
if (actions.Length > 1) {
|
||||
actionStrings[i] += " (ID " + actions[i].ID + ")";
|
||||
}
|
||||
}
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
m_RemoveActionTypeIndex = EditorGUILayout.Popup("Remove Action", m_RemoveActionTypeIndex, actionStrings);
|
||||
if (GUILayout.Button("Remove", GUILayout.Width(80))) {
|
||||
ItemBuilder.RemoveAction(actions[m_RemoveActionTypeIndex]);
|
||||
m_RemoveActionTypeIndex = 0;
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
// Actions can be added.
|
||||
GUILayout.Space(5);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
m_AddActionType = (ItemBuilder.ActionType)EditorGUILayout.EnumPopup("Add Action", m_AddActionType);
|
||||
var canBuild = true;
|
||||
|
||||
#if !ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
|
||||
if (m_AddActionType == ItemBuilder.ActionType.ShootableWeapon) {
|
||||
EditorGUILayout.HelpBox("The shooter controller is necessary in order to create melee weapons.", MessageType.Error);
|
||||
canBuild = false;
|
||||
}
|
||||
#endif
|
||||
#if !ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
if (m_AddActionType == ItemBuilder.ActionType.MeleeWeapon) {
|
||||
EditorGUILayout.HelpBox("The melee controller is necessary in order to create melee weapons.", MessageType.Error);
|
||||
canBuild = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_AddActionType == ItemBuilder.ActionType.ShootableWeapon) {
|
||||
EditorGUI.indentLevel++;
|
||||
m_ExistingAddActionItemDefinition = EditorGUILayout.ObjectField("Consumable Item Definition", m_ExistingAddActionItemDefinition, typeof(ItemDefinitionBase), false) as ItemDefinitionBase;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Add", GUILayout.Width(80))) {
|
||||
ItemBuilder.AddAction(m_Item.gameObject, m_AddActionType, m_ExistingAddActionItemDefinition);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
GUI.enabled = m_Item != null && canBuild;
|
||||
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
GUILayout.Space(5);
|
||||
// The first person objects can be added or removed.
|
||||
EditorGUILayout.LabelField("First Person", InspectorStyles.BoldLabel);
|
||||
EditorGUI.indentLevel++;
|
||||
FirstPersonController.Items.FirstPersonPerspectiveItem firstPersonVisibleItem = null;
|
||||
if (m_Item != null) {
|
||||
firstPersonVisibleItem = m_Item.GetComponent<FirstPersonController.Items.FirstPersonPerspectiveItem>();
|
||||
GUI.enabled = firstPersonVisibleItem == null;
|
||||
if (firstPersonVisibleItem != null) {
|
||||
m_ExistingFirstPersonObject = firstPersonVisibleItem.Object;
|
||||
m_ExistingFirstPersonVisibleItem = firstPersonVisibleItem.VisibleItem;
|
||||
if (m_ExistingFirstPersonVisibleItem != null) {
|
||||
var firstPersonVisibleItemAnimator = firstPersonVisibleItem.VisibleItem.GetComponent<Animator>();
|
||||
if (firstPersonVisibleItemAnimator != null) {
|
||||
m_ExistingFirstPersonVisibleItemAnimatorController = firstPersonVisibleItemAnimator.runtimeAnimatorController;
|
||||
} else {
|
||||
m_ExistingFirstPersonVisibleItemAnimatorController = null;
|
||||
}
|
||||
} else {
|
||||
m_ExistingFirstPersonVisibleItemAnimatorController = null;
|
||||
}
|
||||
}
|
||||
var character = m_Item.GetComponentInParent<Character.UltimateCharacterLocomotion>();
|
||||
DrawFirstPersonObject(character != null ? character.gameObject : null, ref m_ExistingFirstPersonObject, ref m_ExistingFirstPersonObjectAnimatorController,
|
||||
ref m_ExistingFirstPersonVisibleItem, ref m_ExistingFirstPersonParent, ref m_ExistingFirstPersonItemSlot,
|
||||
ref m_ExistingFirstPersonVisibleItemAnimatorController,
|
||||
m_ExistingThirdPersonItemSlot != null ? m_ExistingThirdPersonItemSlot.ID : 0, false, true);
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(InspectorUtility.IndentWidth);
|
||||
GUI.enabled = m_Item != null && firstPersonVisibleItem == null;
|
||||
if (GUILayout.Button("Add")) {
|
||||
var character = m_Item.GetComponentInParent<Character.UltimateCharacterLocomotion>();
|
||||
ItemBuilder.AddFirstPersonObject(character.gameObject, m_Item.name, m_Item.gameObject, ref m_ExistingFirstPersonObject, m_ExistingFirstPersonObjectAnimatorController,
|
||||
ref m_ExistingFirstPersonVisibleItem, m_ExistingFirstPersonItemSlot, m_ExistingFirstPersonVisibleItemAnimatorController);
|
||||
|
||||
// Ensure the animators have the required parameters.
|
||||
if (m_ExistingFirstPersonObjectAnimatorController != null) {
|
||||
AnimatorBuilder.AddParameters((UnityEditor.Animations.AnimatorController)m_ExistingFirstPersonObjectAnimatorController);
|
||||
}
|
||||
if (m_ExistingFirstPersonVisibleItemAnimatorController != null) {
|
||||
AnimatorBuilder.AddParameters((UnityEditor.Animations.AnimatorController)m_ExistingFirstPersonVisibleItemAnimatorController);
|
||||
}
|
||||
}
|
||||
|
||||
GUI.enabled = m_Item != null && firstPersonVisibleItem != null;
|
||||
if (GUILayout.Button("Remove")) {
|
||||
ItemBuilder.RemoveFirstPersonObject(firstPersonVisibleItem);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUI.indentLevel--;
|
||||
#endif
|
||||
|
||||
// The third person objects can be added or removed.
|
||||
GUI.enabled = m_Item != null;
|
||||
GUILayout.Space(5);
|
||||
EditorGUILayout.LabelField("Third Person", InspectorStyles.BoldLabel);
|
||||
EditorGUI.indentLevel++;
|
||||
ThirdPersonController.Items.ThirdPersonPerspectiveItem thirdPersonVisibleItem = null;
|
||||
if (m_Item != null) {
|
||||
thirdPersonVisibleItem = m_Item.GetComponent<ThirdPersonController.Items.ThirdPersonPerspectiveItem>();
|
||||
GUI.enabled = thirdPersonVisibleItem == null;
|
||||
if (thirdPersonVisibleItem != null) {
|
||||
m_ExistingThirdPersonObject = thirdPersonVisibleItem.Object;
|
||||
if (m_ExistingThirdPersonObject != null) {
|
||||
var thirdPersonAnimator = thirdPersonVisibleItem.Object.GetComponent<Animator>();
|
||||
if (thirdPersonAnimator != null) {
|
||||
m_ExistingThirdPersonObjectAnimatorController = thirdPersonAnimator.runtimeAnimatorController;
|
||||
} else {
|
||||
m_ExistingThirdPersonObjectAnimatorController = null;
|
||||
}
|
||||
} else {
|
||||
m_ExistingThirdPersonObjectAnimatorController = null;
|
||||
}
|
||||
}
|
||||
var character = m_Item.GetComponentInParent<Character.UltimateCharacterLocomotion>();
|
||||
if (character == null || (character != null && character.GetComponent<Animator>() != null)) {
|
||||
DrawThirdPersonObject(character != null ? character.gameObject : null, ref m_ExistingThirdPersonObject, ref m_ExistingThirdHumanoidParentHand, ref m_ExistingThirdPersonParent,
|
||||
ref m_ExistingThirdPersonItemSlot, ref m_ExistingThirdPersonObjectAnimatorController,
|
||||
m_ExistingFirstPersonItemSlot != null ? m_ExistingFirstPersonItemSlot.ID : 0, false, true);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(InspectorUtility.IndentWidth);
|
||||
GUI.enabled = m_Item != null && thirdPersonVisibleItem == null;
|
||||
if (GUILayout.Button("Add")) {
|
||||
var character = m_Item.GetComponentInParent<Character.UltimateCharacterLocomotion>();
|
||||
ItemBuilder.AddThirdPersonObject(character.gameObject, m_Item.name, m_Item.gameObject, ref m_ExistingThirdPersonObject, m_ExistingThirdPersonItemSlot, m_ExistingThirdPersonObjectAnimatorController, m_InvisibleShadowCaster, false);
|
||||
// Ensure the animators have the required parameters.
|
||||
if (m_ExistingThirdPersonObjectAnimatorController != null) {
|
||||
AnimatorBuilder.AddParameters((UnityEditor.Animations.AnimatorController)m_ExistingThirdPersonObjectAnimatorController);
|
||||
}
|
||||
}
|
||||
GUI.enabled = m_Item != null && thirdPersonVisibleItem != null;
|
||||
if (GUILayout.Button("Remove")) {
|
||||
ItemBuilder.RemoveThirdPersonObject(thirdPersonVisibleItem);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
GUI.enabled = m_Item != null;
|
||||
|
||||
// Setup profiles.
|
||||
GUILayout.Space(5);
|
||||
EditorGUILayout.LabelField("State Profile", InspectorStyles.BoldLabel);
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
var updatedStateConfiguration = EditorGUILayout.ObjectField("State Configuration", m_ExistingStateConfiguration, typeof(StateConfiguration), false) as StateConfiguration;
|
||||
if (updatedStateConfiguration != m_ExistingStateConfiguration) {
|
||||
if (updatedStateConfiguration != null) {
|
||||
EditorPrefs.SetString(ManagerUtility.LastStateConfigurationGUIDString, AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(updatedStateConfiguration)));
|
||||
} else {
|
||||
EditorPrefs.SetString(ManagerUtility.LastStateConfigurationGUIDString, string.Empty);
|
||||
}
|
||||
m_ExistingStateConfiguration = updatedStateConfiguration;
|
||||
}
|
||||
if (m_ExistingStateConfiguration != null) {
|
||||
var profiles = m_ExistingStateConfiguration.GetProfilesForGameObject(m_Item == null ? null : m_Item.gameObject, StateConfiguration.Profile.ProfileType.Item);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
var canSetup = true;
|
||||
if (profiles.Count == 0) {
|
||||
canSetup = false;
|
||||
profiles.Add("(None)");
|
||||
}
|
||||
m_ExistingProfileIndex = EditorGUILayout.Popup("Profile", m_ExistingProfileIndex, profiles.ToArray());
|
||||
GUI.enabled = m_Item != null && canSetup;
|
||||
if (GUILayout.Button("Apply")) {
|
||||
m_ExistingStateConfiguration.AddStatesToGameObject(profiles[m_ExistingProfileIndex], m_Item.gameObject);
|
||||
InspectorUtility.SetDirty(m_Item.gameObject);
|
||||
}
|
||||
GUI.enabled = m_Item != null;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62cba94d259a7ab4a85cc88e859b52ae
|
||||
timeCreated: 1500577998
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e72baa9831944124fb035424c5363624
|
||||
timeCreated: 1500577985
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,485 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
using Opsive.Shared.Utility;
|
||||
using Opsive.UltimateCharacterController.Editor.Inspectors.Utility;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The MainManagerWindow is an editor window which contains all of the sub managers. This window draws the high level menu options and draws
|
||||
/// the selected sub manager.
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public class MainManagerWindow : EditorWindow
|
||||
{
|
||||
private float c_MenuWidth = 120;
|
||||
|
||||
public float MenuWidth { get { return c_MenuWidth; } }
|
||||
|
||||
private Manager[] m_Managers;
|
||||
private string[] m_ManagerNames;
|
||||
private Vector2 m_MenuScrollPosition;
|
||||
private int m_MenuSelection;
|
||||
|
||||
// Unity's serialization doesn't support abstract classes so serialize the data separately.
|
||||
private Serialization[] m_ManagerData;
|
||||
|
||||
private UnityEngine.Networking.UnityWebRequest m_UpdateCheckRequest;
|
||||
private DateTime m_LastUpdateCheck = DateTime.MinValue;
|
||||
|
||||
public string LatestVersion
|
||||
{
|
||||
get { return EditorPrefs.GetString("Opsive.UltimateCharacterController.Editor.LatestVersion", AssetInfo.Version); }
|
||||
set { EditorPrefs.SetString("Opsive.UltimateCharacterController.Editor.LatestVersion", value); }
|
||||
}
|
||||
private DateTime LastUpdateCheck
|
||||
{
|
||||
get
|
||||
{
|
||||
try {
|
||||
// Don't read from editor prefs if it isn't necessary.
|
||||
if (m_LastUpdateCheck != DateTime.MinValue) {
|
||||
return m_LastUpdateCheck;
|
||||
}
|
||||
|
||||
m_LastUpdateCheck = DateTime.Parse(EditorPrefs.GetString("Opsive.UltimateCharacterController.Editor.LastUpdateCheck", "1/1/1971 00:00:01"), System.Globalization.CultureInfo.InvariantCulture);
|
||||
} catch (Exception /*e*/) {
|
||||
m_LastUpdateCheck = DateTime.UtcNow;
|
||||
}
|
||||
return m_LastUpdateCheck;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_LastUpdateCheck = value;
|
||||
EditorPrefs.SetString("Opsive.UltimateCharacterController.Editor.LastUpdateCheck", m_LastUpdateCheck.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
|
||||
private GUIStyle m_MenuBackground;
|
||||
private GUIStyle MenuBackground {
|
||||
get {
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
if (m_MenuBackground == null) {
|
||||
m_MenuBackground = new GUIStyle(EditorStyles.label);
|
||||
// The left, top, and bottom background border should extend to prevent it from being seen.
|
||||
var overflow = m_MenuBackground.overflow;
|
||||
overflow.left = overflow.top = overflow.bottom = 3;
|
||||
m_MenuBackground.overflow = overflow;
|
||||
var border = m_MenuBackground.border;
|
||||
border.left = border.right = 10;
|
||||
m_MenuBackground.border = border;
|
||||
}
|
||||
#else
|
||||
if (m_MenuBackground == null) {
|
||||
m_MenuBackground = new GUIStyle(EditorStyles.textArea);
|
||||
// The left, top, and bottom background border should extend to prevent it from being seen.
|
||||
var overflow = m_MenuBackground.overflow;
|
||||
overflow.left = overflow.top = overflow.bottom = 3;
|
||||
m_MenuBackground.overflow = overflow;
|
||||
}
|
||||
#endif
|
||||
return m_MenuBackground;
|
||||
}
|
||||
}
|
||||
|
||||
private GUIStyle m_MenuButton;
|
||||
private GUIStyle MenuButton {
|
||||
get {
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
if (m_MenuButton == null) {
|
||||
m_MenuButton = new GUIStyle(EditorStyles.label);
|
||||
m_MenuButton.fontSize = 13;
|
||||
m_MenuButton.alignment = TextAnchor.MiddleRight;
|
||||
}
|
||||
#else
|
||||
if (m_MenuButton == null) {
|
||||
m_MenuButton = new GUIStyle(EditorStyles.toolbarButton);
|
||||
m_MenuButton.active.background = m_MenuButton.normal.background = null;
|
||||
m_MenuButton.fontSize = 13;
|
||||
m_MenuButton.alignment = TextAnchor.MiddleRight;
|
||||
var padding = m_MenuBackground.padding;
|
||||
padding.left = 0;
|
||||
padding.right = 2;
|
||||
m_MenuBackground.padding = padding;
|
||||
}
|
||||
#endif
|
||||
return m_MenuButton;
|
||||
}
|
||||
}
|
||||
private GUIStyle m_SelectedMenuButton;
|
||||
private GUIStyle SelectedMenuButton {
|
||||
get {
|
||||
if (m_SelectedMenuButton == null) {
|
||||
m_SelectedMenuButton = new GUIStyle(MenuButton);
|
||||
#if !UNITY_2019_3_OR_NEWER
|
||||
var overflow = m_SelectedMenuButton.overflow;
|
||||
overflow.top = overflow.bottom = 4;
|
||||
#endif
|
||||
}
|
||||
if (m_SelectedMenuButton.active.background == null) {
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
var background = new Texture2D(1, 1, TextureFormat.RGBA32, false);
|
||||
#else
|
||||
var background = new Texture2D(1, 1, TextureFormat.RGBA32, false, true);
|
||||
#endif
|
||||
background.SetPixel(0, 0, EditorGUIUtility.isProSkin ? new Color(0.243f, 0.373f, 0.588f) : new Color(0.247f, 0.494f, 0.871f));
|
||||
background.Apply();
|
||||
m_SelectedMenuButton.active.background = m_SelectedMenuButton.normal.background = background;
|
||||
}
|
||||
return m_SelectedMenuButton;
|
||||
}
|
||||
}
|
||||
private GUIStyle m_ManagerTitle;
|
||||
private GUIStyle ManagerTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_ManagerTitle == null) {
|
||||
m_ManagerTitle = new GUIStyle(InspectorStyles.CenterBoldLabel);
|
||||
m_ManagerTitle.fontSize = 16;
|
||||
m_ManagerTitle.alignment = TextAnchor.MiddleLeft;
|
||||
}
|
||||
return m_ManagerTitle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform editor checks as soon as the scripts are done compiling.
|
||||
/// </summary>
|
||||
static MainManagerWindow()
|
||||
{
|
||||
EditorApplication.update += EditorStartup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Main Manager.
|
||||
/// </summary>
|
||||
[MenuItem("Tools/Opsive/Ultimate Character Controller/Main Manager", false, 1)]
|
||||
public static MainManagerWindow ShowWindow()
|
||||
{
|
||||
var window = EditorWindow.GetWindow<MainManagerWindow>(false, "Character Manager");
|
||||
window.minSize = new Vector2(680, 550);
|
||||
return window;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the project settings dialogues.
|
||||
/// </summary>
|
||||
private static void UpdateProjectSettings()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Update Input Manager?", "Do you want to update the Input Manager?\n\n" +
|
||||
"If you have already updated the Input Manager or are using custom inputs you can select No.", "Yes", "No")) {
|
||||
Utility.UnityInputBuilder.UpdateInputManager();
|
||||
}
|
||||
if (EditorUtility.DisplayDialog("Update Layers?", "Do you want to update the project layers?\n\n" +
|
||||
"If you have already updated the layers or are using custom layers you can select No.", "Yes", "No")) {
|
||||
SetupManager.UpdateLayers();
|
||||
}
|
||||
EditorPrefs.SetBool("Opsive.UltimateCharacterController.Editor.UpdateProject", false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Main Manager and shows the Character Manager.
|
||||
/// </summary>
|
||||
[MenuItem("Tools/Opsive/Ultimate Character Controller/Character Manager", false, 11)]
|
||||
public static void ShowCharacterManagerWindow()
|
||||
{
|
||||
var window = ShowWindow();
|
||||
window.Open(typeof(CharacterManager));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Main Manager and shows the Item Type Manager.
|
||||
/// </summary>
|
||||
[MenuItem("Tools/Opsive/Ultimate Character Controller/Item Type Manager", false, 12)]
|
||||
public static void ShowItemTypeManagerWindow()
|
||||
{
|
||||
var window = ShowWindow();
|
||||
window.Open(typeof(ItemTypeManager));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Main Manager and shows the Item Manager.
|
||||
/// </summary>
|
||||
[MenuItem("Tools/Opsive/Ultimate Character Controller/Item Manager", false, 13)]
|
||||
public static void ShowItemManagerWindow()
|
||||
{
|
||||
var window = ShowWindow();
|
||||
window.Open(typeof(ItemManager));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Main Manager and shows the Item Manager.
|
||||
/// </summary>
|
||||
[MenuItem("Tools/Opsive/Ultimate Character Controller/Object Manager", false, 14)]
|
||||
public static void ShowObjectManagerWindow()
|
||||
{
|
||||
var window = ShowWindow();
|
||||
window.Open(typeof(ObjectManager));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Main Manager and shows the Integrations Manager.
|
||||
/// </summary>
|
||||
[MenuItem("Tools/Opsive/Ultimate Character Controller/Integrations Manager", false, 25)]
|
||||
public static void ShowIntegrationsManagerWindow()
|
||||
{
|
||||
var window = ShowWindow();
|
||||
window.Open(typeof(IntegrationsManager));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Main Manager and shows the Add-Ons Manager.
|
||||
/// </summary>
|
||||
[MenuItem("Tools/Opsive/Ultimate Character Controller/Add-Ons Manager", false, 26)]
|
||||
public static void ShowAddOnsManagerWindow()
|
||||
{
|
||||
var window = ShowWindow();
|
||||
window.Open(typeof(AddOnsManager));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the editor window if it hasn't been shown before and also setup.
|
||||
/// </summary>
|
||||
private static void EditorStartup()
|
||||
{
|
||||
if (EditorApplication.isCompiling) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EditorPrefs.GetBool("Opsive.UltimateCharacterController.Editor.MainManagerShown", false)) {
|
||||
EditorPrefs.SetBool("Opsive.UltimateCharacterController.Editor.MainManagerShown", true);
|
||||
ShowWindow();
|
||||
}
|
||||
|
||||
if (!EditorPrefs.HasKey("Opsive.UltimateCharacterController.Editor.UpdateProject") || EditorPrefs.GetBool("Opsive.UltimateCharacterController.Editor.UpdateProject", true)) {
|
||||
EditorUtility.DisplayDialog("Project Settings Setup", "Thank you for purchasing the " + AssetInfo.Name +".\n\n" +
|
||||
"This wizard will ask two questions related to updating your project.", "OK");
|
||||
UpdateProjectSettings();
|
||||
}
|
||||
|
||||
EditorApplication.update -= EditorStartup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the inspector.
|
||||
/// </summary>
|
||||
private void OnInspectorUpdate()
|
||||
{
|
||||
UpdateCheck();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is an update available?
|
||||
/// </summary>
|
||||
/// <returns>True if an update is available.</returns>
|
||||
private bool UpdateCheck()
|
||||
{
|
||||
if (m_UpdateCheckRequest != null && m_UpdateCheckRequest.isDone) {
|
||||
if (string.IsNullOrEmpty(m_UpdateCheckRequest.error)) {
|
||||
LatestVersion = m_UpdateCheckRequest.downloadHandler.text;
|
||||
}
|
||||
m_UpdateCheckRequest = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_UpdateCheckRequest == null && DateTime.Compare(LastUpdateCheck.AddDays(1), DateTime.UtcNow) < 0) {
|
||||
var url = string.Format("https://opsive.com/asset/UpdateCheck.php?asset=UltimateCharacterController&type={0}&version={1}&unityversion={2}&devplatform={3}&targetplatform={4}",
|
||||
AssetInfo.Name.Replace(" ", ""), AssetInfo.Version, Application.unityVersion, Application.platform, EditorUserBuildSettings.activeBuildTarget);
|
||||
m_UpdateCheckRequest = UnityEngine.Networking.UnityWebRequest.Get(url);
|
||||
m_UpdateCheckRequest.SendWebRequest();
|
||||
LastUpdateCheck = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
return m_UpdateCheckRequest != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The window has been enabled.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
DeserializeManagers();
|
||||
BuildManagerItems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the Main Manager.
|
||||
/// </summary>
|
||||
private void OnGUI()
|
||||
{
|
||||
// Draw the menu.
|
||||
OnMenuGUI();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
// Draw the manager.
|
||||
OnManagerGUI();
|
||||
|
||||
// Use a custom serialization for any changes since Unity's serialization doesn't support abstract inheritance.
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
SerializeManagers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the menu UI.
|
||||
/// </summary>
|
||||
private void OnMenuGUI()
|
||||
{
|
||||
GUILayout.BeginArea(new Rect(0, 0, c_MenuWidth, position.height), MenuBackground);
|
||||
m_MenuScrollPosition = GUILayout.BeginScrollView(m_MenuScrollPosition);
|
||||
GUILayout.BeginVertical();
|
||||
GUILayout.Space(32);
|
||||
for (int i = 0; i < m_Managers.Length; ++i) {
|
||||
if (GUILayout.Button(m_ManagerNames[i], (i == m_MenuSelection ? SelectedMenuButton : MenuButton), GUILayout.Height(32))) {
|
||||
m_MenuSelection = i;
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
GUILayout.EndScrollView();
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the array which contains all of the IManager objects.
|
||||
/// </summary>
|
||||
private void BuildManagerItems()
|
||||
{
|
||||
var managers = new List<Type>();
|
||||
var managerIndexes = new List<int>();
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
for (int i = 0; i < assemblies.Length; ++i) {
|
||||
var assemblyTypes = assemblies[i].GetTypes();
|
||||
for (int j = 0; j < assemblyTypes.Length; ++j) {
|
||||
// Must implement Manager.
|
||||
if (!typeof(Manager).IsAssignableFrom(assemblyTypes[j])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore abstract classes.
|
||||
if (assemblyTypes[j].IsAbstract) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// A valid manager class.
|
||||
managers.Add(assemblyTypes[j]);
|
||||
var index = managerIndexes.Count;
|
||||
if (assemblyTypes[j].GetCustomAttributes(typeof(OrderedEditorItem), true).Length > 0) {
|
||||
var item = assemblyTypes[j].GetCustomAttributes(typeof(OrderedEditorItem), true)[0] as OrderedEditorItem;
|
||||
index = item.Index;
|
||||
}
|
||||
managerIndexes.Add(index);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not reinitialize the managers if they are already initialized and there aren't any changes.
|
||||
if (m_Managers != null && m_Managers.Length == managers.Count) {
|
||||
return;
|
||||
}
|
||||
|
||||
// All of the manager types have been found. Sort by the index.
|
||||
var managerTypes = managers.ToArray();
|
||||
Array.Sort(managerIndexes.ToArray(), managerTypes);
|
||||
|
||||
m_Managers = new Manager[managers.Count];
|
||||
m_ManagerNames = new string[managers.Count];
|
||||
|
||||
// The manager types have been found and sorted. Add them to the list.
|
||||
for (int i = 0; i < managerTypes.Length; ++i) {
|
||||
m_Managers[i] = Activator.CreateInstance(managerTypes[i]) as Manager;
|
||||
m_Managers[i].Initialize(this);
|
||||
|
||||
var name = InspectorUtility.SplitCamelCase(managerTypes[i].Name);
|
||||
if (managers[i].GetCustomAttributes(typeof(OrderedEditorItem), true).Length > 0) {
|
||||
var item = managerTypes[i].GetCustomAttributes(typeof(OrderedEditorItem), true)[0] as OrderedEditorItem;
|
||||
name = item.Name;
|
||||
}
|
||||
m_ManagerNames[i] = name;
|
||||
}
|
||||
|
||||
SerializeManagers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the manager UI.
|
||||
/// </summary>
|
||||
private void OnManagerGUI()
|
||||
{
|
||||
GUILayout.BeginArea(new Rect(c_MenuWidth + 2, 0, position.width - c_MenuWidth, position.height));
|
||||
GUILayout.Space(4);
|
||||
GUILayout.Label(m_ManagerNames[m_MenuSelection], ManagerTitle);
|
||||
GUILayout.Space(2);
|
||||
m_Managers[m_MenuSelection].OnGUI();
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified manager.
|
||||
/// </summary>
|
||||
/// <param name="managerType">The type of manager to open.</param>
|
||||
public void Open(Type managerType)
|
||||
{
|
||||
for (int i = 0; i < m_Managers.Length; ++i) {
|
||||
if (m_Managers[i].GetType() == managerType) {
|
||||
m_MenuSelection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the data for each manager.
|
||||
/// </summary>
|
||||
private void SerializeManagers()
|
||||
{
|
||||
m_ManagerData = new Serialization[m_Managers.Length];
|
||||
for (int i = 0; i < m_Managers.Length; ++i) {
|
||||
var serializedValue = new Serialization();
|
||||
serializedValue.Serialize(m_Managers[i], true, MemberVisibility.Public);
|
||||
m_ManagerData[i] = serializedValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the data for each manager.
|
||||
/// </summary>
|
||||
private void DeserializeManagers()
|
||||
{
|
||||
if (m_ManagerData != null) {
|
||||
m_Managers = new Manager[m_ManagerData.Length];
|
||||
for (int i = 0; i < m_ManagerData.Length; ++i) {
|
||||
m_Managers[i] = m_ManagerData[i].DeserializeFields(MemberVisibility.Public) as Manager;
|
||||
// The object will be null if the class doesn't exist anymore.
|
||||
if (m_Managers[i] == null) {
|
||||
continue;
|
||||
}
|
||||
m_Managers[i].Initialize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute which specifies the name and ordering of the editor items.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public class OrderedEditorItem : Attribute
|
||||
{
|
||||
private string m_Name;
|
||||
private int m_Index;
|
||||
public string Name { get { return m_Name; } }
|
||||
public int Index { get { return m_Index; } }
|
||||
public OrderedEditorItem(string name, int index) { m_Name = name; m_Index = index; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7eb87493a412def42ab4459e90b63fad
|
||||
timeCreated: 1500568651
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
/// <summary>
|
||||
/// The Manager is an abstract class which allows for various categories to the drawn to the MainManagerWindow pane.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public abstract class Manager
|
||||
{
|
||||
protected MainManagerWindow m_MainManagerWindow;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the manager after deserialization.
|
||||
/// </summary>
|
||||
public virtual void Initialize(MainManagerWindow mainManagerWindow) { m_MainManagerWindow = mainManagerWindow; }
|
||||
|
||||
/// <summary>
|
||||
/// Draws the Manager.
|
||||
/// </summary>
|
||||
public abstract void OnGUI();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d5b87c8ccab5434d8c5726aeca70ea9
|
||||
timeCreated: 1500577963
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,214 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Editor.Inspectors.Utility;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Utility functions for the manager classes.
|
||||
/// </summary>
|
||||
public static class ManagerUtility
|
||||
{
|
||||
private static string[] s_AnimatorControllerGUIDs = new string[] { "00734c75e5484e24697dddaf47e8c152", "1c65957c39679034fb94019d52d6a984", "79f4dab00da40824fbd3697b6c773522",
|
||||
"2d9ab56181c2ca34abcc6645243cf341", "e567772a993c11f448f9b69023c6cef6", "e58cef58c651b36498088253ec70c3ba",
|
||||
"7d702f1c77d91684ab1774d5ce14a714"};
|
||||
private const string c_ItemCollectionGUID = "5481010ef14c32f4cb7b6661b0c59fb4";
|
||||
private const string c_InvisibleShadowCasterGUID = "0a580a5ea04fdab47941095489aa23b7";
|
||||
private static string[] s_StateConfigurationGUIDs = new string[] { "9d35e75efc940dd4184470a31d744f39", "c7627c1aa2c6b264d87709008477a69e", "da4073e1f8f631445b1aea02f03f4760",
|
||||
"95e1719ba13cc9446b2b61a5993d5e43", "8481381869bbb8b4d8b4d1386e322d67", "bf3920a4d30a0744f9d4139fd46498ca",
|
||||
"e64c674322ee9dd47a9cf94762d7ff73"};
|
||||
|
||||
private const string c_LastItemCollectionGUIDString = "LastItemCollectionGUID";
|
||||
private const string c_LastStateConfigurationGUIDString = "LastStateConfigurationGUID";
|
||||
|
||||
public static string StateConfigurationGUID { get { return s_StateConfigurationGUIDs[0]; } }
|
||||
public static string LastItemCollectionGUIDString { get { return c_LastItemCollectionGUIDString; } }
|
||||
public static string LastStateConfigurationGUIDString { get { return c_LastStateConfigurationGUIDString; } }
|
||||
|
||||
/// <summary>
|
||||
/// Draws a control box which allows for an action when the button is pressed.
|
||||
/// </summary>
|
||||
/// <param name="title">The title of the control box.</param>
|
||||
/// <param name="additionalControls">Any additional controls that should appear before the message.</param>
|
||||
/// <param name="message">The message within the box.</param>
|
||||
/// <param name="enableButton">Is the button enabled?</param>
|
||||
/// <param name="button">The name of the button.</param>
|
||||
/// <param name="action">The action that is performed when the button is pressed.</param>
|
||||
/// <param name="successLog">The message to output to the log upon success.</param>
|
||||
public static void DrawControlBox(string title, System.Action additionalControls, string message, bool enableButton, string button, System.Action action, string successLog)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(title, InspectorStyles.BoldLabel);
|
||||
GUILayout.Space(4);
|
||||
GUILayout.Label(message, InspectorStyles.WordWrapLabel);
|
||||
if (additionalControls != null) {
|
||||
additionalControls();
|
||||
}
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
GUI.enabled = enableButton;
|
||||
if (!string.IsNullOrEmpty(button) && GUILayout.Button(button, GUILayout.Width(130))) {
|
||||
action();
|
||||
if (!string.IsNullOrEmpty(successLog)) {
|
||||
Debug.Log(successLog);
|
||||
}
|
||||
}
|
||||
GUI.enabled = true;
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(4);
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for the default animator controller.
|
||||
/// </summary>
|
||||
public static RuntimeAnimatorController FindAnimatorController(ScriptableObject editorWindow)
|
||||
{
|
||||
// The GUID should remain consistant.
|
||||
string animatorControllerPath;
|
||||
for (int i = 0; i < s_AnimatorControllerGUIDs.Length; ++i) {
|
||||
animatorControllerPath = AssetDatabase.GUIDToAssetPath(s_AnimatorControllerGUIDs[i]);
|
||||
if (!string.IsNullOrEmpty(animatorControllerPath)) {
|
||||
var animatorController = AssetDatabase.LoadAssetAtPath(animatorControllerPath, typeof(RuntimeAnimatorController)) as RuntimeAnimatorController;
|
||||
if (animatorController != null) {
|
||||
return animatorController;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The animator controller doesn't have the expected guid. Try to find the asset based on the path.
|
||||
animatorControllerPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(editorWindow))).Replace("\\", "/").Replace("Editor/Managers", "Demo/Animator/Characters/Demo.controller");
|
||||
if (System.IO.File.Exists(Application.dataPath + "/" + animatorControllerPath.Substring(7))) {
|
||||
return AssetDatabase.LoadAssetAtPath(animatorControllerPath, typeof(RuntimeAnimatorController)) as RuntimeAnimatorController;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for the default item collection.
|
||||
/// </summary>
|
||||
public static Inventory.ItemCollection FindItemCollection(ScriptableObject editorWindow)
|
||||
{
|
||||
// If an ItemCollection asset exists within the scene then use that.
|
||||
var itemSetManager = Object.FindObjectOfType<Inventory.ItemSetManager>();
|
||||
if (itemSetManager != null) {
|
||||
if (itemSetManager.ItemCollection != null) {
|
||||
return itemSetManager.ItemCollection;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the last used ItemCollection.
|
||||
var lastItemCollectionGUID = EditorPrefs.GetString(LastItemCollectionGUIDString, string.Empty);
|
||||
if (!string.IsNullOrEmpty(lastItemCollectionGUID)) {
|
||||
var lastItemCollectionPath = AssetDatabase.GUIDToAssetPath(lastItemCollectionGUID);
|
||||
if (!string.IsNullOrEmpty(lastItemCollectionPath)) {
|
||||
var itemCollection = AssetDatabase.LoadAssetAtPath(lastItemCollectionPath, typeof(Inventory.ItemCollection)) as Inventory.ItemCollection;
|
||||
if (itemCollection != null) {
|
||||
return itemCollection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The GUID should remain consistant.
|
||||
var itemCollectionPath = AssetDatabase.GUIDToAssetPath(c_ItemCollectionGUID);
|
||||
if (!string.IsNullOrEmpty(itemCollectionPath)) {
|
||||
var itemCollection = AssetDatabase.LoadAssetAtPath(itemCollectionPath, typeof(Inventory.ItemCollection)) as Inventory.ItemCollection;
|
||||
if (itemCollection != null) {
|
||||
return itemCollection;
|
||||
}
|
||||
}
|
||||
|
||||
// The item collection doesn't have the expected guid. Try to find the asset based on the path.
|
||||
itemCollectionPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(editorWindow))).Replace("\\", "/").Replace("Editor/Managers", "Demo/Inventory/DemoItemCollection.asset");
|
||||
if (System.IO.File.Exists(Application.dataPath + "/" + itemCollectionPath.Substring(7))) {
|
||||
return AssetDatabase.LoadAssetAtPath(itemCollectionPath, typeof(Inventory.ItemCollection)) as Inventory.ItemCollection;
|
||||
}
|
||||
|
||||
// Last chance: use resources to try to find the ItemCollection.
|
||||
var itemCollections = Resources.FindObjectsOfTypeAll<Inventory.ItemCollection>();
|
||||
if (itemCollections != null && itemCollections.Length > 0) {
|
||||
return itemCollections[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for the invisible shadow caster material.
|
||||
/// </summary>
|
||||
public static Material FindInvisibleShadowCaster(ScriptableObject editorWindow)
|
||||
{
|
||||
// The GUID should remain consistant.
|
||||
var shadowCasterPath = AssetDatabase.GUIDToAssetPath(c_InvisibleShadowCasterGUID);
|
||||
if (!string.IsNullOrEmpty(shadowCasterPath)) {
|
||||
var invisibleShadowCaster = AssetDatabase.LoadAssetAtPath(shadowCasterPath, typeof(Material)) as Material;
|
||||
if (invisibleShadowCaster != null) {
|
||||
return invisibleShadowCaster;
|
||||
}
|
||||
}
|
||||
|
||||
if (editorWindow != null) {
|
||||
// The invisible shadow caster doesn't have the expected guid. Try to find the material based on the path.
|
||||
shadowCasterPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(editorWindow))).Replace("\\", "/").Replace("Editor/Managers", "FirstPersonController/Materials/InvisibleShadowCaster.mat");
|
||||
if (System.IO.File.Exists(Application.dataPath + "/" + shadowCasterPath.Substring(7))) {
|
||||
return AssetDatabase.LoadAssetAtPath(shadowCasterPath, typeof(Material)) as Material;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for the default state configuration.
|
||||
/// </summary>
|
||||
public static StateSystem.StateConfiguration FindStateConfiguration(ScriptableObject editorWindow)
|
||||
{
|
||||
// Retrieve the last used StateConfiguration.
|
||||
var lastStateConfigurationGUID = EditorPrefs.GetString(LastStateConfigurationGUIDString, string.Empty);
|
||||
if (!string.IsNullOrEmpty(lastStateConfigurationGUID)) {
|
||||
var lastStateConfigurationPath = AssetDatabase.GUIDToAssetPath(lastStateConfigurationGUID);
|
||||
if (!string.IsNullOrEmpty(lastStateConfigurationPath)) {
|
||||
var stateConfiguration = AssetDatabase.LoadAssetAtPath(lastStateConfigurationPath, typeof(StateSystem.StateConfiguration)) as StateSystem.StateConfiguration;
|
||||
if (stateConfiguration != null) {
|
||||
return stateConfiguration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The GUID should remain consistant.
|
||||
string stateConfigurationPath;
|
||||
|
||||
for (int i = 0; i < s_StateConfigurationGUIDs.Length; ++i) {
|
||||
stateConfigurationPath = AssetDatabase.GUIDToAssetPath(s_StateConfigurationGUIDs[i]);
|
||||
if (!string.IsNullOrEmpty(stateConfigurationPath)) {
|
||||
var stateConfiguration = AssetDatabase.LoadAssetAtPath(stateConfigurationPath, typeof(StateSystem.StateConfiguration)) as StateSystem.StateConfiguration;
|
||||
if (stateConfiguration != null) {
|
||||
return stateConfiguration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The state configuration doesn't have the expected guid. Try to find the asset based on the path.
|
||||
stateConfigurationPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(editorWindow))).Replace("\\", "/").Replace("Editor/Managers", "Demo/Presets/DemoStateConfiguration.asset");
|
||||
if (System.IO.File.Exists(Application.dataPath + "/" + stateConfigurationPath.Substring(7))) {
|
||||
return AssetDatabase.LoadAssetAtPath(stateConfigurationPath, typeof(StateSystem.StateConfiguration)) as StateSystem.StateConfiguration;
|
||||
}
|
||||
|
||||
// Last chance: use resources to try to find the StateConfiguration.
|
||||
var stateConfigurations = Resources.FindObjectsOfTypeAll<StateSystem.StateConfiguration>();
|
||||
if (stateConfigurations != null && stateConfigurations.Length > 0) {
|
||||
return stateConfigurations[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48c74037a5499b04d88196cd50a34861
|
||||
timeCreated: 1513706666
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,227 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Game;
|
||||
using Opsive.UltimateCharacterController.Objects;
|
||||
using Opsive.UltimateCharacterController.Objects.CharacterAssist;
|
||||
using Opsive.UltimateCharacterController.Objects.ItemAssist;
|
||||
using Opsive.UltimateCharacterController.Traits;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The ObjectManager will draw any item properties
|
||||
/// </summary>
|
||||
[OrderedEditorItem("Object", 5)]
|
||||
public class ObjectManager : Manager
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of object to build.
|
||||
/// </summary>
|
||||
private enum ObjectType
|
||||
{
|
||||
ItemPickup, // Builds an ItemPickup with a Respawner component.
|
||||
DroppedItem, // Builds an ItemPickup that can be dropped from the character with the TrajectoryObject.
|
||||
HealthPickup, // Builds a HealthPickup with a Respawner component.
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
|
||||
Projectile, // Builds a Projectile that can be fired.
|
||||
MuzzleFlash, // Builds an object with the MuzzleFlash component.
|
||||
Shell, // Builds an object with the Shell component.
|
||||
Smoke, // Builds an object with the Smoke component.
|
||||
#endif
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
MeleeTrail, // Builds an object with the Trail component.
|
||||
#endif
|
||||
Grenade, // Builds a Grenade TrajectoryObject.
|
||||
Explosion, // Builds an object with the Explosion and ParticleSystem components.
|
||||
MagicProjectile, // Builds an object with the MagicProjectile and ParticleSystem components.
|
||||
Particle, // Builds an object with the ParticlePooler and ParticleSystem components
|
||||
}
|
||||
|
||||
[SerializeField] private string m_Name;
|
||||
[SerializeField] private ObjectType m_ObjectType;
|
||||
[SerializeField] private GameObject m_Object;
|
||||
[SerializeField] private bool m_MagicParticleCollisions;
|
||||
|
||||
private bool m_CanBuild;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the ObjectManager.
|
||||
/// </summary>
|
||||
public override void OnGUI()
|
||||
{
|
||||
ManagerUtility.DrawControlBox("Object Builder", DrawObjectTypes, "Builds a new object with the specified type.",
|
||||
m_Name != null && (m_Object != null || !RequiresGameObject()) && m_CanBuild,
|
||||
"Build Object", BuildObject, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the object type popup.
|
||||
/// </summary>
|
||||
private void DrawObjectTypes()
|
||||
{
|
||||
m_CanBuild = true;
|
||||
m_Name = EditorGUILayout.TextField("Name", m_Name);
|
||||
m_ObjectType = (ObjectType)EditorGUILayout.EnumPopup("Object Type", m_ObjectType);
|
||||
if (RequiresGameObject()) {
|
||||
m_Object = EditorGUILayout.ObjectField("GameObject", m_Object, typeof(GameObject), true) as GameObject;
|
||||
if (m_Object != null && m_ObjectType == ObjectType.ItemPickup) {
|
||||
if (m_Object.GetComponent<Items.Item>() != null) {
|
||||
EditorGUILayout.HelpBox("The Item Pickup should not reference an already created item. This GameObject should reference the item model.", MessageType.Error);
|
||||
m_CanBuild = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_Object = null;
|
||||
}
|
||||
if (m_ObjectType == ObjectType.MagicProjectile || m_ObjectType == ObjectType.Particle) {
|
||||
m_MagicParticleCollisions = EditorGUILayout.Toggle(new GUIContent("Magic Particle Collisions", "Should the particles respond to magic collision events?"),
|
||||
m_MagicParticleCollisions);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the object type require the GameObject field?
|
||||
/// </summary>
|
||||
/// <returns>True if the object type requires the GameObject field.</returns>
|
||||
private bool RequiresGameObject()
|
||||
{
|
||||
return m_ObjectType != ObjectType.Explosion
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
&& m_ObjectType != ObjectType.MeleeTrail
|
||||
#endif
|
||||
&& m_ObjectType != ObjectType.MagicProjectile && m_ObjectType != ObjectType.Particle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the object.
|
||||
/// </summary>
|
||||
private void BuildObject()
|
||||
{
|
||||
var path = EditorUtility.SaveFilePanel("Save Object", "Assets", m_Name + ".prefab", "prefab");
|
||||
if (path.Length == 0 || Application.dataPath.Length > path.Length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var createdObject = m_Object;
|
||||
if (createdObject == null) {
|
||||
createdObject = new GameObject();
|
||||
} else if (EditorUtility.IsPersistent(createdObject)) {
|
||||
var name = createdObject.name;
|
||||
createdObject = GameObject.Instantiate(createdObject) as GameObject;
|
||||
}
|
||||
createdObject.name = m_Name;
|
||||
|
||||
SphereCollider sphereCollider;
|
||||
switch (m_ObjectType) {
|
||||
case ObjectType.ItemPickup:
|
||||
createdObject.layer = LayerManager.VisualEffect;
|
||||
AddComponentIfNotAdded<BoxCollider>(createdObject);
|
||||
sphereCollider = AddComponentIfNotAdded<SphereCollider>(createdObject);
|
||||
sphereCollider.isTrigger = true;
|
||||
AddComponentIfNotAdded<ItemPickup>(createdObject);
|
||||
AddComponentIfNotAdded<Respawner>(createdObject);
|
||||
break;
|
||||
case ObjectType.DroppedItem:
|
||||
createdObject.layer = LayerManager.VisualEffect;
|
||||
AddComponentIfNotAdded<BoxCollider>(createdObject);
|
||||
sphereCollider = AddComponentIfNotAdded<SphereCollider>(createdObject);
|
||||
sphereCollider.isTrigger = true;
|
||||
AddComponentIfNotAdded<ItemPickup>(createdObject);
|
||||
var trajectoryObject = AddComponentIfNotAdded<TrajectoryObject>(createdObject);
|
||||
trajectoryObject.ImpactLayers = ~(1 << LayerManager.IgnoreRaycast | 1 << LayerManager.Water | 1 << LayerManager.SubCharacter | 1 << LayerManager.Overlay |
|
||||
1 << LayerManager.VisualEffect | 1 << LayerManager.SubCharacter | 1 << LayerManager.Character);
|
||||
break;
|
||||
case ObjectType.HealthPickup:
|
||||
AddComponentIfNotAdded<SphereCollider>(createdObject);
|
||||
AddComponentIfNotAdded<HealthPickup>(createdObject);
|
||||
AddComponentIfNotAdded<Respawner>(createdObject);
|
||||
break;
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
|
||||
case ObjectType.Projectile:
|
||||
AddComponentIfNotAdded<Rigidbody>(createdObject);
|
||||
AddComponentIfNotAdded<CapsuleCollider>(createdObject);
|
||||
AddComponentIfNotAdded<Projectile>(createdObject);
|
||||
break;
|
||||
case ObjectType.MuzzleFlash:
|
||||
AddComponentIfNotAdded<MuzzleFlash>(createdObject);
|
||||
break;
|
||||
case ObjectType.Shell:
|
||||
AddComponentIfNotAdded<Rigidbody>(createdObject);
|
||||
AddComponentIfNotAdded<CapsuleCollider>(createdObject);
|
||||
AddComponentIfNotAdded<Shell>(createdObject);
|
||||
var audioSource = AddComponentIfNotAdded<AudioSource>(createdObject);
|
||||
audioSource.spatialBlend = 1;
|
||||
audioSource.maxDistance = 10;
|
||||
break;
|
||||
case ObjectType.Smoke:
|
||||
AddComponentIfNotAdded<ParticleSystem>(createdObject);
|
||||
AddComponentIfNotAdded<Smoke>(createdObject);
|
||||
break;
|
||||
#endif
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
case ObjectType.MeleeTrail:
|
||||
AddComponentIfNotAdded<MeshFilter>(createdObject);
|
||||
AddComponentIfNotAdded<MeshRenderer>(createdObject);
|
||||
AddComponentIfNotAdded<Trail>(createdObject);
|
||||
break;
|
||||
#endif
|
||||
case ObjectType.Grenade:
|
||||
AddComponentIfNotAdded<Rigidbody>(createdObject);
|
||||
AddComponentIfNotAdded<CapsuleCollider>(createdObject);
|
||||
var grenade = AddComponentIfNotAdded<Grenade>(createdObject);
|
||||
grenade.DestroyOnCollision = false;
|
||||
break;
|
||||
case ObjectType.Explosion:
|
||||
AddComponentIfNotAdded<ParticleSystem>(createdObject);
|
||||
AddComponentIfNotAdded<Explosion>(createdObject);
|
||||
break;
|
||||
case ObjectType.MagicProjectile:
|
||||
AddComponentIfNotAdded<Rigidbody>(createdObject);
|
||||
AddComponentIfNotAdded<ParticleSystem>(createdObject);
|
||||
var magicParticle = AddComponentIfNotAdded<MagicProjectile>(createdObject);
|
||||
magicParticle.Collision = TrajectoryObject.CollisionMode.Ignore;
|
||||
if (m_MagicParticleCollisions) {
|
||||
AddComponentIfNotAdded<MagicParticle>(createdObject);
|
||||
}
|
||||
break;
|
||||
case ObjectType.Particle:
|
||||
var particleSystem = AddComponentIfNotAdded<ParticleSystem>(createdObject);
|
||||
AddComponentIfNotAdded<ParticlePooler>(createdObject);
|
||||
if (m_MagicParticleCollisions) {
|
||||
AddComponentIfNotAdded<MagicParticle>(createdObject);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var relativePath = path.Replace(Application.dataPath, "");
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
PrefabUtility.SaveAsPrefabAsset(createdObject, "Assets" + relativePath);
|
||||
#else
|
||||
PrefabUtility.CreatePrefab("Assets" + relativePath, createdObject);
|
||||
#endif
|
||||
Selection.activeGameObject = AssetDatabase.LoadAssetAtPath("Assets" + relativePath, typeof(GameObject)) as GameObject;
|
||||
Object.DestroyImmediate(createdObject, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the component to the specified GameObject if it isn't already added.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of component to add.</typeparam>
|
||||
/// <param name="obj">The GameObject to add the component to.</param>
|
||||
/// <returns>The component of type T.</returns>
|
||||
private T AddComponentIfNotAdded<T>(GameObject obj) where T : Component
|
||||
{
|
||||
T component;
|
||||
if ((component = obj.GetComponent<T>()) == null) {
|
||||
component = obj.AddComponent<T>();
|
||||
}
|
||||
return component;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1bf2354ad2c5a0d42bec2a6197c57687
|
||||
timeCreated: 1500577998
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,477 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
using Opsive.Shared.Game;
|
||||
using Opsive.UltimateCharacterController.Camera;
|
||||
using Opsive.UltimateCharacterController.Editor.Inspectors.Utility;
|
||||
using Opsive.UltimateCharacterController.Game;
|
||||
using Opsive.UltimateCharacterController.StateSystem;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using Opsive.UltimateCharacterController.Utility.Builders;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The SetupManager shows any project or scene related setup options.
|
||||
/// </summary>
|
||||
[OrderedEditorItem("Setup", 1)]
|
||||
public class SetupManager : Manager
|
||||
{
|
||||
private const string c_MonitorsPrefabGUID = "b5bf2e4077598914b83fc5e4ca20f2f4";
|
||||
private const string c_VirtualControlsPrefabGUID = "33d3d57ba5fc7484c8d09150e45066a4";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the perspective that the ViewType can change into.
|
||||
/// </summary>
|
||||
private enum Perspective
|
||||
{
|
||||
First, // The ViewType can only be in first person perspective.
|
||||
Third, // The ViewType can only be in third person perspective.
|
||||
Both, // The ViewType can be in first or third person perspective.
|
||||
None // Default value.
|
||||
}
|
||||
|
||||
private string[] m_ToolbarStrings = { "Scene", "Project" };
|
||||
[SerializeField] private bool m_DrawSceneSetup = true;
|
||||
|
||||
[SerializeField] private bool m_CanCreateCamera = true;
|
||||
[SerializeField] private Perspective m_Perspective = Perspective.None;
|
||||
[SerializeField] private string m_FirstPersonViewType;
|
||||
[SerializeField] private string m_ThirdPersonViewType;
|
||||
[SerializeField] private bool m_StartFirstPersonPerspective;
|
||||
[SerializeField] private StateConfiguration m_StateConfiguration;
|
||||
[SerializeField] private int m_ProfileIndex;
|
||||
[SerializeField] private string m_ProfileName;
|
||||
|
||||
private List<Type> m_FirstPersonViewTypes = new List<Type>();
|
||||
private string[] m_FirstPersonViewTypeStrings;
|
||||
private List<Type> m_ThirdPersonViewTypes = new List<Type>();
|
||||
private string[] m_ThirdPersonViewTypeStrings;
|
||||
private string[] m_PerspectiveNames = { "First", "Third", "Both" };
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the manager after deserialization.
|
||||
/// </summary>
|
||||
public override void Initialize(MainManagerWindow mainManagerWindow)
|
||||
{
|
||||
base.Initialize(mainManagerWindow);
|
||||
|
||||
// Set the default perspective based on what asset is installed.
|
||||
if (m_Perspective == Perspective.None) {
|
||||
#if FIRST_PERSON_CONTROLLER
|
||||
m_Perspective = Perspective.First;
|
||||
#elif THIRD_PERSON_CONTROLLER
|
||||
m_Perspective = Perspective.Third;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get a list of the available view types.
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
for (int i = 0; i < assemblies.Length; ++i) {
|
||||
var assemblyTypes = assemblies[i].GetTypes();
|
||||
for (int j = 0; j < assemblyTypes.Length; ++j) {
|
||||
// Must derive from ViewType.
|
||||
if (!typeof(UltimateCharacterController.Camera.ViewTypes.ViewType).IsAssignableFrom(assemblyTypes[j])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore abstract classes.
|
||||
if (assemblyTypes[j].IsAbstract) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (assemblyTypes[j].FullName.Contains("FirstPersonController")) {
|
||||
m_FirstPersonViewTypes.Add(assemblyTypes[j]);
|
||||
} else if (assemblyTypes[j].FullName.Contains("ThirdPersonController")) {
|
||||
m_ThirdPersonViewTypes.Add(assemblyTypes[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create an array of display names for the popup.
|
||||
if (m_FirstPersonViewTypes.Count > 0) {
|
||||
m_FirstPersonViewTypeStrings = new string[m_FirstPersonViewTypes.Count];
|
||||
for (int i = 0; i < m_FirstPersonViewTypes.Count; ++i) {
|
||||
m_FirstPersonViewTypeStrings[i] = InspectorUtility.DisplayTypeName(m_FirstPersonViewTypes[i], true);
|
||||
}
|
||||
}
|
||||
if (m_ThirdPersonViewTypes.Count > 0) {
|
||||
m_ThirdPersonViewTypeStrings = new string[m_ThirdPersonViewTypes.Count];
|
||||
for (int i = 0; i < m_ThirdPersonViewTypes.Count; ++i) {
|
||||
m_ThirdPersonViewTypeStrings[i] = InspectorUtility.DisplayTypeName(m_ThirdPersonViewTypes[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the state configuration.
|
||||
var stateConfiguration = ManagerUtility.FindStateConfiguration(m_MainManagerWindow);
|
||||
if (stateConfiguration != null) {
|
||||
if (m_StateConfiguration == null) {
|
||||
m_StateConfiguration = stateConfiguration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the Manager.
|
||||
/// </summary>
|
||||
public override void OnGUI()
|
||||
{
|
||||
var toolbarSelection = GUILayout.Toolbar(m_DrawSceneSetup ? 0 : 1, m_ToolbarStrings, EditorStyles.toolbarButton);
|
||||
m_DrawSceneSetup = toolbarSelection == 0;
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (m_DrawSceneSetup) {
|
||||
DrawSceneSetup();
|
||||
} else {
|
||||
DrawProjectSetup();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the controls for setting up the scene.
|
||||
/// </summary>
|
||||
private void DrawSceneSetup()
|
||||
{
|
||||
ManagerUtility.DrawControlBox("Manager Setup", null, "Adds the scene-level manager components to the scene.", true, "Add Managers", AddManagers, string.Empty);
|
||||
ManagerUtility.DrawControlBox("Camera Setup", DrawCameraViewTypes, "Sets up the camera within the scene to use the Ultimate Character Controller Camera Controller component.",
|
||||
m_CanCreateCamera, "Setup Camera", SetupCamera, string.Empty);
|
||||
ManagerUtility.DrawControlBox("UI Setup", null, "Adds the UI monitors to the scene.", true, "Add UI", AddUI, string.Empty);
|
||||
ManagerUtility.DrawControlBox("Virtual Controls Setup", null, "Adds the virtual controls to the scene.", true, "Add Virtual Controls", AddVirtualControls, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the popup for the camera view types.
|
||||
/// </summary>
|
||||
private void DrawCameraViewTypes()
|
||||
{
|
||||
// Draw the perspective.
|
||||
var selectedPerspective = (Perspective)EditorGUILayout.Popup("Perspective", (int)m_Perspective, m_PerspectiveNames);
|
||||
var isSupported = true;
|
||||
// Determine if the selected perspective is supported.
|
||||
#if !FIRST_PERSON_CONTROLLER
|
||||
if (selectedPerspective == Perspective.First || selectedPerspective == Perspective.Both) {
|
||||
EditorGUILayout.HelpBox("Unable to select the First Person Controller perspective. If you'd like to use a first person perspective ensure the " +
|
||||
"First Person Controller is imported.", MessageType.Error);
|
||||
isSupported = false;
|
||||
}
|
||||
#endif
|
||||
#if !THIRD_PERSON_CONTROLLER
|
||||
if (selectedPerspective == Perspective.Third || selectedPerspective == Perspective.Both) {
|
||||
EditorGUILayout.HelpBox("Unable to select the Third Person Controller perspective. If you'd like to use a third person perspective ensure the " +
|
||||
"Third Person Controller is imported.", MessageType.Error);
|
||||
isSupported = false;
|
||||
}
|
||||
#endif
|
||||
if (selectedPerspective != m_Perspective) {
|
||||
m_Perspective = selectedPerspective;
|
||||
}
|
||||
|
||||
m_CanCreateCamera = isSupported;
|
||||
if (!isSupported) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show the available first person ViewTypes.
|
||||
if (m_Perspective == Perspective.First || m_Perspective == Perspective.Both) {
|
||||
var selectedViewType = -1;
|
||||
for (int i = 0; i < m_FirstPersonViewTypes.Count; ++i) {
|
||||
if (m_FirstPersonViewTypes[i].FullName == m_FirstPersonViewType) {
|
||||
selectedViewType = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var viewType = selectedViewType == -1 ? 0 : selectedViewType;
|
||||
selectedViewType = EditorGUILayout.Popup("First Person View Type", viewType, m_FirstPersonViewTypeStrings);
|
||||
if (viewType != selectedViewType || string.IsNullOrEmpty(m_FirstPersonViewType)) {
|
||||
m_FirstPersonViewType = m_FirstPersonViewTypes[selectedViewType].FullName;
|
||||
}
|
||||
if (m_Perspective != Perspective.Both) {
|
||||
m_ThirdPersonViewType = string.Empty;
|
||||
}
|
||||
}
|
||||
// Show the available third person ViewTypes.
|
||||
if (m_Perspective == Perspective.Third || m_Perspective == Perspective.Both) {
|
||||
var selectedViewType = -1;
|
||||
for (int i = 0; i < m_ThirdPersonViewTypes.Count; ++i) {
|
||||
if (m_ThirdPersonViewTypes[i].FullName == m_ThirdPersonViewType) {
|
||||
selectedViewType = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var viewType = selectedViewType == -1 ? 0 : selectedViewType;
|
||||
selectedViewType = EditorGUILayout.Popup("Third Person View Type", viewType, m_ThirdPersonViewTypeStrings);
|
||||
if (viewType != selectedViewType || string.IsNullOrEmpty(m_ThirdPersonViewType)) {
|
||||
m_ThirdPersonViewType = m_ThirdPersonViewTypes[selectedViewType].FullName;
|
||||
}
|
||||
if (m_Perspective != Perspective.Both) {
|
||||
m_FirstPersonViewType = string.Empty;
|
||||
}
|
||||
}
|
||||
if (m_Perspective == Perspective.Both) {
|
||||
m_StartFirstPersonPerspective = EditorGUILayout.Popup("Start Perspective", m_StartFirstPersonPerspective ? 0 : 1, new string[] { "First Person", "Third Person" }) == 0;
|
||||
} else {
|
||||
m_StartFirstPersonPerspective = (m_Perspective == Perspective.First);
|
||||
}
|
||||
// Show the possible base configurations.
|
||||
var updatedStateConfiguration = EditorGUILayout.ObjectField("State Configuration", m_StateConfiguration, typeof(StateConfiguration), false) as StateConfiguration;
|
||||
if (updatedStateConfiguration != m_StateConfiguration) {
|
||||
if (updatedStateConfiguration != null) {
|
||||
EditorPrefs.SetString(ManagerUtility.LastStateConfigurationGUIDString, AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(updatedStateConfiguration)));
|
||||
} else {
|
||||
EditorPrefs.SetString(ManagerUtility.LastStateConfigurationGUIDString, string.Empty);
|
||||
}
|
||||
m_StateConfiguration = updatedStateConfiguration;
|
||||
}
|
||||
EditorGUI.indentLevel++;
|
||||
if (m_StateConfiguration != null) {
|
||||
var profiles = m_StateConfiguration.GetProfilesForGameObject(null, StateConfiguration.Profile.ProfileType.Camera);
|
||||
// The character can be added without any profiles.
|
||||
profiles.Insert(0, "(None)");
|
||||
m_ProfileIndex = EditorGUILayout.Popup("Profile", m_ProfileIndex, profiles.ToArray());
|
||||
m_ProfileName = profiles[m_ProfileIndex];
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
GUILayout.Space(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the camera if it hasn't already been setup.
|
||||
/// </summary>
|
||||
private void SetupCamera()
|
||||
{
|
||||
// Setup the camera.
|
||||
GameObject cameraGameObject;
|
||||
var addedCameraController = false;
|
||||
var camera = UnityEngine.Camera.main;
|
||||
if (camera == null) {
|
||||
// If the main camera can't be found then use the first available camera.
|
||||
var cameras = UnityEngine.Camera.allCameras;
|
||||
if (cameras != null && cameras.Length > 0) {
|
||||
// Prefer cameras that are at the root level.
|
||||
for (int i = 0; i < cameras.Length; ++i) {
|
||||
if (cameras[i].transform.parent == null) {
|
||||
camera = cameras[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// No cameras are at the root level. Set the first available camera.
|
||||
if (camera == null) {
|
||||
camera = cameras[0];
|
||||
}
|
||||
}
|
||||
|
||||
// A new camera should be created if there isn't a valid camera.
|
||||
if (camera == null) {
|
||||
cameraGameObject = new GameObject("Camera");
|
||||
cameraGameObject.tag = "MainCamera";
|
||||
camera = cameraGameObject.AddComponent<UnityEngine.Camera>();
|
||||
cameraGameObject.AddComponent<AudioListener>();
|
||||
}
|
||||
}
|
||||
|
||||
// The near clip plane should adjusted for viewing close objects.
|
||||
camera.nearClipPlane = 0.01f;
|
||||
|
||||
// Add the CameraController if it isn't already added.
|
||||
cameraGameObject = camera.gameObject;
|
||||
if (cameraGameObject.GetComponent<CameraController>() == null) {
|
||||
var cameraController = cameraGameObject.AddComponent<CameraController>();
|
||||
if (m_Perspective == Perspective.Both) {
|
||||
ViewTypeBuilder.AddViewType(cameraController, typeof(UltimateCharacterController.Camera.ViewTypes.Transition));
|
||||
}
|
||||
if (m_StartFirstPersonPerspective) {
|
||||
if (!string.IsNullOrEmpty(m_ThirdPersonViewType)) {
|
||||
ViewTypeBuilder.AddViewType(cameraController, UnityEngineUtility.GetType(m_ThirdPersonViewType));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(m_FirstPersonViewType)) {
|
||||
ViewTypeBuilder.AddViewType(cameraController, UnityEngineUtility.GetType(m_FirstPersonViewType));
|
||||
}
|
||||
} else {
|
||||
if (!string.IsNullOrEmpty(m_FirstPersonViewType)) {
|
||||
ViewTypeBuilder.AddViewType(cameraController, UnityEngineUtility.GetType(m_FirstPersonViewType));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(m_ThirdPersonViewType)) {
|
||||
ViewTypeBuilder.AddViewType(cameraController, UnityEngineUtility.GetType(m_ThirdPersonViewType));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Detect if a character exists in the scene. Automatically add the character if it does.
|
||||
var characters = GameObject.FindObjectsOfType<UltimateCharacterController.Character.CharacterLocomotion>();
|
||||
if (characters != null && characters.Length == 1) {
|
||||
cameraController.InitCharacterOnAwake = true;
|
||||
cameraController.Character = characters[0].gameObject;
|
||||
}
|
||||
|
||||
// Setup the components which help the Camera Controller.
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<CameraControllerHandler>(cameraGameObject);
|
||||
#if THIRD_PERSON_CONTROLLER
|
||||
if (m_Perspective != Perspective.First) {
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<ThirdPersonController.Camera.ObjectFader>(cameraGameObject);
|
||||
}
|
||||
#endif
|
||||
addedCameraController = true;
|
||||
|
||||
if (m_StateConfiguration != null) {
|
||||
if (m_ProfileIndex > 0) {
|
||||
m_StateConfiguration.AddStatesToGameObject(m_ProfileName, cameraGameObject);
|
||||
InspectorUtility.SetDirty(cameraGameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (addedCameraController) {
|
||||
Debug.Log("The Camera Controller has been added.");
|
||||
} else {
|
||||
Debug.LogWarning("Warning: No action was performed, the Camera Controller component has already been added.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the singleton manager components.
|
||||
/// </summary>
|
||||
private void AddManagers()
|
||||
{
|
||||
// Create the "Game" components if it doesn't already exists.
|
||||
Scheduler scheduler;
|
||||
GameObject gameGameObject;
|
||||
if ((scheduler = GameObject.FindObjectOfType<Scheduler>()) == null) {
|
||||
gameGameObject = new GameObject("Game");
|
||||
} else {
|
||||
gameGameObject = scheduler.gameObject;
|
||||
}
|
||||
|
||||
// Add the Singletons.
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<SurfaceSystem.SurfaceManager>(gameGameObject);
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<SurfaceSystem.DecalManager>(gameGameObject);
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<KinematicObjectManager>(gameGameObject);
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<ObjectPool>(gameGameObject);
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<Scheduler>(gameGameObject);
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<Audio.AudioManager>(gameGameObject);
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<SpawnPointManager>(gameGameObject);
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<StateManager>(gameGameObject);
|
||||
Shared.Editor.Utility.InspectorUtility.AddComponent<LayerManager>(gameGameObject);
|
||||
Debug.Log("The managers have been added.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the UI to the scene.
|
||||
/// </summary>
|
||||
private void AddUI()
|
||||
{
|
||||
var canvas = GameObject.FindObjectOfType<Canvas>();
|
||||
if (canvas == null) {
|
||||
EditorApplication.ExecuteMenuItem("GameObject/UI/Canvas");
|
||||
canvas = GameObject.FindObjectOfType<Canvas>();
|
||||
}
|
||||
|
||||
// Look up based on guid.
|
||||
GameObject uiPrefab = null;
|
||||
var monitorsPath = AssetDatabase.GUIDToAssetPath(c_MonitorsPrefabGUID);
|
||||
if (!string.IsNullOrEmpty(monitorsPath)) {
|
||||
uiPrefab = AssetDatabase.LoadAssetAtPath(monitorsPath, typeof(GameObject)) as GameObject;
|
||||
}
|
||||
|
||||
// If the guid wasn't found try the path.
|
||||
if (uiPrefab == null) {
|
||||
var baseDirectory = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(m_MainManagerWindow))).Replace("\\", "/").Replace("Editor/Managers", "");
|
||||
uiPrefab = AssetDatabase.LoadAssetAtPath(baseDirectory + "Demo/Prefabs/UI/Monitors.prefab", typeof(GameObject)) as GameObject;
|
||||
}
|
||||
|
||||
if (uiPrefab == null) {
|
||||
Debug.LogError("Error: Unable to find the UI Monitors prefab.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Instantiate the Monitors prefab.
|
||||
var uiGameObject = PrefabUtility.InstantiatePrefab(uiPrefab) as GameObject;
|
||||
uiGameObject.name = "Monitors";
|
||||
uiGameObject.GetComponent<RectTransform>().SetParent(canvas.transform, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the UI to the scene.
|
||||
/// </summary>
|
||||
private void AddVirtualControls()
|
||||
{
|
||||
var canvas = GameObject.FindObjectOfType<Canvas>();
|
||||
if (canvas == null) {
|
||||
EditorApplication.ExecuteMenuItem("GameObject/UI/Canvas");
|
||||
canvas = GameObject.FindObjectOfType<Canvas>();
|
||||
}
|
||||
|
||||
// Look up based on guid.
|
||||
GameObject virtualControlsPrefab = null;
|
||||
var virtualControlsPath = AssetDatabase.GUIDToAssetPath(c_VirtualControlsPrefabGUID);
|
||||
if (!string.IsNullOrEmpty(virtualControlsPath)) {
|
||||
virtualControlsPrefab = AssetDatabase.LoadAssetAtPath(virtualControlsPath, typeof(GameObject)) as GameObject;
|
||||
}
|
||||
|
||||
// If the guid wasn't found try the path.
|
||||
if (virtualControlsPrefab == null) {
|
||||
var baseDirectory = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(m_MainManagerWindow))).Replace("\\", "/").Replace("Editor/Managers", "");
|
||||
virtualControlsPrefab = AssetDatabase.LoadAssetAtPath(baseDirectory + "Demo/Prefabs/UI/VirtualControls.prefab", typeof(GameObject)) as GameObject;
|
||||
}
|
||||
|
||||
if (virtualControlsPrefab == null) {
|
||||
Debug.LogError("Error: Unable to find the UI Virtual Controls prefab.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Instantiate the Virtual Controls prefab.
|
||||
var virtualControls = PrefabUtility.InstantiatePrefab(virtualControlsPrefab) as GameObject;
|
||||
virtualControls.name = "VirtualControls";
|
||||
virtualControls.GetComponent<RectTransform>().SetParent(canvas.transform, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the controls for button and input setup.
|
||||
/// </summary>
|
||||
private void DrawProjectSetup()
|
||||
{
|
||||
ManagerUtility.DrawControlBox("Button Mappings", null, "This option will add the default button mappings to the Unity Input Manager. If you are using a custom button mapping or " +
|
||||
"an input integration then you do not neeed to update the Unity button mappings.", true, "Update Buttons",
|
||||
Utility.UnityInputBuilder.UpdateInputManager, "The button mappings were successfully updated.");
|
||||
GUILayout.Space(10);
|
||||
ManagerUtility.DrawControlBox("Layers", null, "This option will update the project layers to the default character controller layers. The layers do not need to be updated " +
|
||||
"if you have already setup a custom set of layers.", true, "Update Layers", UpdateLayers, "The layers were successfully updated.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates all of the layers to the Ultimate Character Controller defaults.
|
||||
/// </summary>
|
||||
public static void UpdateLayers()
|
||||
{
|
||||
var tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
|
||||
var layersProperty = tagManager.FindProperty("layers");
|
||||
|
||||
// Add the layers.
|
||||
AddLayer(layersProperty, LayerManager.Enemy, "Enemy");
|
||||
AddLayer(layersProperty, LayerManager.MovingPlatform, "MovingPlatform");
|
||||
AddLayer(layersProperty, LayerManager.VisualEffect, "VisualEffect");
|
||||
AddLayer(layersProperty, LayerManager.Overlay, "Overlay");
|
||||
AddLayer(layersProperty, LayerManager.SubCharacter, "SubCharacter");
|
||||
AddLayer(layersProperty, LayerManager.Character, "Character");
|
||||
|
||||
tagManager.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the layer index to the specified name if the string value is empty.
|
||||
/// </summary>
|
||||
private static void AddLayer(SerializedProperty layersProperty, int index, string name)
|
||||
{
|
||||
var layerElement = layersProperty.GetArrayElementAtIndex(index);
|
||||
if (string.IsNullOrEmpty(layerElement.stringValue)) {
|
||||
layerElement.stringValue = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0043c4a2cc8f541459db43040e5a6934
|
||||
timeCreated: 1500577998
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,185 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Editor.Managers
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Editor.Inspectors.Utility;
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Shows a starting window with useful links.
|
||||
/// </summary>
|
||||
[OrderedEditorItem("Welcome", 0)]
|
||||
public class WelcomeScreenManager : Manager
|
||||
{
|
||||
private const string c_DocumentationTextureGUID = "58591f58da2eed6429f27c500d2f5a98";
|
||||
private const string c_VideosTextureGUID = "fa530e1c250a12c4d88412795b5d8fa2";
|
||||
private const string c_IntegrationsTextureGUID = "ecac100d11bb3dc40a93d7b1e30c015a";
|
||||
private const string c_ForumTextureGUID = "630622cb32bb7e64da8e2c1abbfdb1a3";
|
||||
private const string c_DiscordTextureGUID = "b847fb48acf99c6478bfdc892f0276fc";
|
||||
private const string c_ReviewTextureGUID = "32f45dfc0d71947458758e055696a118";
|
||||
private const string c_ShowcaseTextureGUID = "997f4ee10d474ab44ab9d9a030110117";
|
||||
|
||||
Texture2D m_DocumentationTexture;
|
||||
Texture2D m_VideosTexture;
|
||||
Texture2D m_IntegrationsTexture;
|
||||
Texture2D m_ForumTexture;
|
||||
Texture2D m_DiscordTexture;
|
||||
Texture2D m_ReviewTexture;
|
||||
Texture2D m_ShowcaseTexture;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the manager after deserialization.
|
||||
/// </summary>
|
||||
public override void Initialize(MainManagerWindow mainManagerWindow)
|
||||
{
|
||||
base.Initialize(mainManagerWindow);
|
||||
|
||||
m_DocumentationTexture = FindTexture(c_DocumentationTextureGUID);
|
||||
m_VideosTexture = FindTexture(c_VideosTextureGUID);
|
||||
m_IntegrationsTexture = FindTexture(c_IntegrationsTextureGUID);
|
||||
m_ForumTexture = FindTexture(c_ForumTextureGUID);
|
||||
m_DiscordTexture = FindTexture(c_DiscordTextureGUID);
|
||||
m_ReviewTexture = FindTexture(c_ReviewTextureGUID);
|
||||
m_ShowcaseTexture = FindTexture(c_ShowcaseTextureGUID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the Manager.
|
||||
/// </summary>
|
||||
public override void OnGUI()
|
||||
{
|
||||
EditorGUILayout.LabelField(string.Format("Thank you for purchasing the {0}.\nThe resources below will help you get the most out of the controller.",
|
||||
UltimateCharacterController.Utility.AssetInfo.Name), InspectorStyles.WordWrapLabelCenter);
|
||||
// Draw the header image.
|
||||
GUILayout.BeginHorizontal();
|
||||
var width = m_MainManagerWindow.position.width - m_MainManagerWindow.MenuWidth - m_DocumentationTexture.width;
|
||||
GUILayout.Space(width / 2);
|
||||
GUILayout.Label(m_DocumentationTexture, InspectorStyles.CenterLabel, GUILayout.Width(m_DocumentationTexture.width), GUILayout.Height(m_DocumentationTexture.height));
|
||||
var lastRect = GUILayoutUtility.GetLastRect();
|
||||
if (Event.current.type == EventType.MouseUp && lastRect.Contains(Event.current.mousePosition)) {
|
||||
Application.OpenURL("https://opsive.com/support/documentation/ultimate-character-controller/");
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(3);
|
||||
|
||||
// The remaining images should be drawn in a grid.
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(width / 2 + 2);
|
||||
var selected = GUILayout.SelectionGrid(-1,
|
||||
new Texture2D[] { m_VideosTexture, m_IntegrationsTexture, m_ForumTexture, m_DiscordTexture, m_ReviewTexture, m_ShowcaseTexture },
|
||||
2,
|
||||
InspectorStyles.CenterLabel, GUILayout.Width(m_IntegrationsTexture.width * 2));
|
||||
if (selected != -1) {
|
||||
switch(selected) {
|
||||
case 0:
|
||||
Application.OpenURL(GetVideosURL());
|
||||
break;
|
||||
case 1:
|
||||
Application.OpenURL(IntegrationsManager.GetIntegrationLink());
|
||||
break;
|
||||
case 2:
|
||||
Application.OpenURL("https://opsive.com/forum/");
|
||||
break;
|
||||
case 3:
|
||||
Application.OpenURL("https://discord.gg/QX6VFgc");
|
||||
break;
|
||||
case 4:
|
||||
Application.OpenURL(GetAssetURL());
|
||||
break;
|
||||
case 5:
|
||||
Application.OpenURL("https://opsive.com/showcase/");
|
||||
break;
|
||||
}
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
// Draw the version at the bottom of the window.
|
||||
lastRect = GUILayoutUtility.GetLastRect();
|
||||
var offset = 455;
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
offset += 5;
|
||||
#endif
|
||||
GUILayout.Space(m_MainManagerWindow.position.height - lastRect.yMax - offset);
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(string.Format("{0} version {1}", UltimateCharacterController.Utility.AssetInfo.Name, UltimateCharacterController.Utility.AssetInfo.Version));
|
||||
try {
|
||||
var version = new Version(UltimateCharacterController.Utility.AssetInfo.Version);
|
||||
if (!string.IsNullOrEmpty(m_MainManagerWindow.LatestVersion) && version.CompareTo(new Version(m_MainManagerWindow.LatestVersion)) < 0) {
|
||||
EditorGUILayout.LabelField(string.Format(" New version available: {0}", m_MainManagerWindow.LatestVersion));
|
||||
}
|
||||
} catch (Exception /*e*/) { }
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the texture based on the GUID.
|
||||
/// </summary>
|
||||
/// <param name="guid">The GUID to find the texture with.</param>
|
||||
/// <returns>The texture with the specified GUID.</returns>
|
||||
private Texture2D FindTexture(string guid)
|
||||
{
|
||||
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (!string.IsNullOrEmpty(assetPath)) {
|
||||
return AssetDatabase.LoadAssetAtPath(assetPath, typeof(Texture2D)) as Texture2D;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the URL for the videos page.
|
||||
/// </summary>
|
||||
/// <returns>The URL for the videos page.</returns>
|
||||
private string GetVideosURL()
|
||||
{
|
||||
switch (UltimateCharacterController.Utility.AssetInfo.Name) {
|
||||
case "Ultimate Character Controller":
|
||||
return "https://opsive.com/videos/?pid=923";
|
||||
case "First Person Controller":
|
||||
return "https://opsive.com/videos/?pid=807";
|
||||
case "Third Person Controller":
|
||||
return "https://opsive.com/videos/?pid=926";
|
||||
case "Ultimate First Person Shooter":
|
||||
return "https://opsive.com/videos/?pid=185";
|
||||
case "Ultimate First Person Melee":
|
||||
return "https://opsive.com/videos/?pid=1106";
|
||||
case "Ultimate Third Person Shooter":
|
||||
return "https://opsive.com/videos/?pid=1107";
|
||||
case "Ultimate Third Person Melee":
|
||||
return "https://opsive.com/videos/?pid=1108";
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the URL for the asset page.
|
||||
/// </summary>
|
||||
/// <returns>The URL for the asset page.</returns>
|
||||
private string GetAssetURL()
|
||||
{
|
||||
switch (UltimateCharacterController.Utility.AssetInfo.Name) {
|
||||
case "Ultimate Character Controller":
|
||||
return "https://assetstore.unity.com/packages/slug/99962";
|
||||
case "First Person Controller":
|
||||
return "https://assetstore.unity.com/packages/slug/92082";
|
||||
case "Third Person Controller":
|
||||
return "https://assetstore.unity.com/packages/slug/126347";
|
||||
case "Ultimate First Person Shooter":
|
||||
return "https://assetstore.unity.com/packages/slug/106748";
|
||||
case "Ultimate First Person Melee":
|
||||
return "https://assetstore.unity.com/packages/slug/99036";
|
||||
case "Ultimate Third Person Shooter":
|
||||
return "https://assetstore.unity.com/packages/slug/99035";
|
||||
case "Ultimate Third Person Melee":
|
||||
return "https://assetstore.unity.com/packages/slug/99037";
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5375adc4b7a75840ab955ac685facaf
|
||||
timeCreated: 1500577998
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user