Organize custom scripts under Assets/Baba_yaga and merge Opsive folders to Assets root

This commit is contained in:
2026-07-01 20:32:28 +07:00
parent 83d4157ac6
commit befc19bf37
5901 changed files with 243 additions and 141 deletions

View File

@@ -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...");
}
}
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 656810ab70d10d7438b035944bd59d10
timeCreated: 1500577975
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4f24fc5d582beec488190d0cd2b3d23c
timeCreated: 1500577998
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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 characters 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 characters 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--;
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e72baa9831944124fb035424c5363624
timeCreated: 1500577985
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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; }
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7eb87493a412def42ab4459e90b63fad
timeCreated: 1500568651
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3d5b87c8ccab5434d8c5726aeca70ea9
timeCreated: 1500577963
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 48c74037a5499b04d88196cd50a34861
timeCreated: 1513706666
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1bf2354ad2c5a0d42bec2a6197c57687
timeCreated: 1500577998
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0043c4a2cc8f541459db43040e5a6934
timeCreated: 1500577998
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e5375adc4b7a75840ab955ac685facaf
timeCreated: 1500577998
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: