Firstborn/Assets/RPG Creation Kit/Scripts/Quest System/Editor/Quest Window/QuestWindow.cs

706 lines
30 KiB
C#
Raw Normal View History

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using RPGCreationKit;
using System.IO;
using System.Reflection;
using System.Linq;
namespace RPGCreationKit
{
public class QuestWindow : EditorWindow
{
public bool isReady = false;
public SerializedObject questObj;
// Navigation
public enum CurrentWindow { Quest, QuestStages, NPCs, Dialogues };
CurrentWindow m_Window;
// Buttons scroll
Vector2 buttonsScrollPos;
Vector2 indexesScrollView;
GUIStyle guiLayoutDarkColor = new GUIStyle();
GUIStyle guiLayoutLightColor = new GUIStyle();
// Quest Conditions
Vector2 questConditionsScrollView = Vector2.zero;
int selectedQuestConditionIndex = -1;
// Quest Stage Conditions
Vector2 questStageConditionsScrollView = Vector2.zero;
int selectedQuestStageConditionIndex = -1;
bool isCreatingNewStage = false;
bool hasSelectedStage = false;
int selectedStage = 0;
MonoScript[] allQuestScripts;
MonoScript[] allQuestStagesScripts;
void Callback(object obj)
{
ScriptElementData questScriptData = (ScriptElementData)obj;
questScriptData.property.stringValue = questScriptData.value;
}
public void Init(SerializedObject _quest)
{
// Windows is created from 'Configure' button of the Inspector of the Quest
// Set Title
Texture icon = AssetDatabase.LoadAssetAtPath<Texture>(EditorIconsPath.QuestWindowIcon);
GUIContent titleContent = new GUIContent("Quest Window", icon);
this.titleContent = titleContent;
// We copy the Item SerializedObject to not lose reference.
SerializedObject itemcopy = new SerializedObject(_quest.targetObject);
questObj = itemcopy;
guiLayoutDarkColor.normal.background = MakeTex(600, 1, new Color(5.0f, 5.0f, 5.0f, .1f));
guiLayoutLightColor.normal.background = MakeTex(600, 1, new Color(37.0f, 79.0f, 133.0f, .4f));
allQuestScripts = NodesHelper.GetAllResultScripts<QuestScript>();
allQuestStagesScripts = NodesHelper.GetAllResultScripts<QuestStageScript>();
isReady = true;
this.Show();
}
private Texture2D MakeTex(int width, int height, Color col)
{
Color[] pix = new Color[width * height];
for (int i = 0; i < pix.Length; i++)
pix[i] = col;
Texture2D result = new Texture2D(width, height);
result.SetPixels(pix);
result.Apply();
return result;
}
public void OnGUI()
{
if (!questObj.targetObject)
{
Debug.LogWarning("ItemObj: NullReferenceException");
return;
}
GUIStyle ButtonStyle = new GUIStyle(GUI.skin.button) { alignment = TextAnchor.MiddleCenter };
ButtonStyle.border = new RectOffset(2,2,2,2);
ButtonStyle.fontSize = 16;
ButtonStyle.font = (Font)AssetDatabase.LoadAssetAtPath<Font>("Assets/RPG Creation Kit/Fonts/monofonto.ttf");
GUIStyle HeaderStyle = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleLeft };
HeaderStyle.fontSize = 14;
HeaderStyle.font = (Font)AssetDatabase.LoadAssetAtPath<Font>("Assets/RPG Creation Kit/Fonts/monofonto.ttf");
EditorGUILayout.BeginHorizontal("box");
EditorGUILayout.LabelField("Configuring: " + questObj.targetObject.name, EditorStyles.boldLabel);
EditorGUILayout.EndHorizontal();
// Scroll View Of Buttons:
buttonsScrollPos =
EditorGUILayout.BeginScrollView(buttonsScrollPos, GUILayout.Width(position.width), GUILayout.Height(75));
GUILayout.BeginHorizontal();
GUILayout.Space(212);
GUILayout.BeginHorizontal("box");
#region NavigationMenu
// Buttons for navigation
var defaultColor = GUI.color;
if (m_Window == CurrentWindow.Quest)
GUI.color = Color.green;
else
GUI.color = defaultColor;
if (GUILayout.Button("Quests", GUILayout.Width(125), GUILayout.Height(20)))
{
m_Window = CurrentWindow.Quest;
}
if (m_Window == CurrentWindow.QuestStages)
GUI.color = Color.green;
else
GUI.color = defaultColor;
if (GUILayout.Button("Quest Stages", GUILayout.Width(125), GUILayout.Height(20)))
{
m_Window = CurrentWindow.QuestStages;
}
if (m_Window == CurrentWindow.NPCs)
GUI.color = Color.green;
else
GUI.color = defaultColor;
if (GUILayout.Button("NPCs", GUILayout.Width(125), GUILayout.Height(20)))
{
m_Window = CurrentWindow.NPCs;
}
if (m_Window == CurrentWindow.Dialogues)
GUI.color = Color.green;
else
GUI.color = defaultColor;
if (GUILayout.Button("Dialogues", GUILayout.Width(125), GUILayout.Height(20)))
{
m_Window = CurrentWindow.Dialogues;
}
GUILayout.EndHorizontal();
GUI.color = defaultColor;
EditorGUILayout.EndScrollView();
GUILayout.EndHorizontal();
#endregion
switch (m_Window)
{
case CurrentWindow.Quest:
#region code
EditorGUILayout.BeginVertical("Box");
EditorGUILayout.LabelField("QUEST SETTINGS:", HeaderStyle);
EditorGUILayout.PropertyField(questObj.FindProperty("questName"));
EditorGUILayout.PropertyField(questObj.FindProperty("questID"));
EditorGUILayout.Space();
EditorGUILayout.PropertyField(questObj.FindProperty("questDescription"));
EditorGUILayout.Space();
EditorGUILayout.PropertyField(questObj.FindProperty("questPriority"));
//EditorGUILayout.PropertyField(questObj.FindProperty("questScript"));
// display the GenericMenu when pressing a button
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Quest Script:");
string menuDisplayValue = string.IsNullOrEmpty(questObj.FindProperty("questScript").stringValue) ? "-None-" : questObj.FindProperty("questScript").stringValue;
if (GUILayout.Button(menuDisplayValue))
{
// create the menu and add items to it
GenericMenu menu = new GenericMenu();
menu.AddDisabledItem(new GUIContent("Quest Scripts"));
menu.AddSeparator("");
menu.AddItem(new GUIContent("None"), false, Callback, new ScriptElementData(questObj.FindProperty("questScript"), ""));
for (int i = 0; i < allQuestScripts.Length; i++)
{
menu.AddItem(new GUIContent(allQuestScripts[i].name), false, Callback, new ScriptElementData(questObj.FindProperty("questScript"), allQuestScripts[i].GetClass().Namespace+"."+allQuestScripts[i].name));
}
menu.ShowAsContext();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(questObj.FindProperty("firstStageIsDefaultStage"));
EditorGUILayout.PropertyField(questObj.FindProperty("allowRepeatedStages"));
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical("Box");
Event current = Event.current;
EditorGUILayout.LabelField("QUEST CONDITIONS:", HeaderStyle);
questConditionsScrollView =
EditorGUILayout.BeginScrollView(questConditionsScrollView, true, true, GUILayout.Width(position.width), GUILayout.Height(360));
Rect questConditionRectArea = new Rect(questConditionsScrollView.x, questConditionsScrollView.y, position.width, 360);
for (int i = 0; i < questObj.FindProperty("questConditions").arraySize; i++)
{
Rect currentConditionArea = EditorGUILayout.BeginHorizontal((selectedQuestConditionIndex == i) ? guiLayoutLightColor : guiLayoutDarkColor);
EditorGUILayout.PropertyField(questObj.FindProperty("questConditions").GetArrayElementAtIndex(i), GUILayout.Width(1500));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(10);
if (currentConditionArea.Contains(current.mousePosition) && Event.current.type == EventType.MouseDown && Event.current.button == 0)
{
selectedQuestConditionIndex = i;
Repaint();
}
}
// DROPDOWN TO CREATE NEW CONDITIONS
if (questConditionRectArea.Contains(current.mousePosition) && current.type == EventType.ContextClick)
{
GenericMenu menu = new GenericMenu();
menu.AddDisabledItem(new GUIContent("Quests Conditions"));
menu.AddItem(new GUIContent("New"), false, CreateNewQuestCondition);
menu.AddItem(new GUIContent("Delete Selected"), false, DeleteSelectedQuestCondition);
menu.ShowAsContext();
current.Use();
}
void CreateNewQuestCondition()
{
questObj.FindProperty("questConditions").InsertArrayElementAtIndex(questObj.FindProperty("questConditions").arraySize);
selectedQuestConditionIndex = questObj.FindProperty("questConditions").arraySize - 1;
Repaint();
}
void DeleteSelectedQuestCondition()
{
if (selectedQuestConditionIndex != -1)
{
questObj.FindProperty("questConditions").DeleteArrayElementAtIndex(selectedQuestConditionIndex);
selectedQuestConditionIndex = -1;
Repaint();
}
}
EditorGUILayout.EndScrollView();
EditorGUILayout.BeginHorizontal("box", GUILayout.MaxWidth(150));
GUI.enabled = (selectedQuestConditionIndex != -1) ? true : false;
GUI.enabled = (selectedQuestConditionIndex != -1 && selectedQuestConditionIndex != 0);
if(GUILayout.Button("↑"))
{
GUI.FocusControl(null);
questObj.FindProperty("questConditions").MoveArrayElement(selectedQuestConditionIndex, selectedQuestConditionIndex - 1);
selectedQuestConditionIndex = selectedQuestConditionIndex - 1;
Repaint();
}
GUI.enabled = (selectedQuestConditionIndex != -1 && selectedQuestConditionIndex != questObj.FindProperty("questConditions").arraySize - 1);
if (GUILayout.Button("↓"))
{
GUI.FocusControl(null);
questObj.FindProperty("questConditions").MoveArrayElement(selectedQuestConditionIndex, selectedQuestConditionIndex + 1);
selectedQuestConditionIndex = selectedQuestConditionIndex + 1;
Repaint();
}
GUI.enabled = true;
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
GUILayout.FlexibleSpace();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("SAVE", ButtonStyle))
{
questObj.ApplyModifiedProperties();
// Refresh database
var AllQuestDatabaseFiles = GetAllInstances<QuestsDatabaseFile>();
foreach (QuestsDatabaseFile file in AllQuestDatabaseFiles)
file.fill();
this.Close();
}
if (GUILayout.Button("CANCEL", ButtonStyle))
{
this.Close();
}
EditorGUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
#endregion
break;
case CurrentWindow.QuestStages:
#region code
EditorGUILayout.LabelField(" [QUEST STAGES]", HeaderStyle, GUILayout.MaxWidth(200.0f));
EditorGUILayout.BeginHorizontal();
// --- LEFT PANEL
indexesScrollView = EditorGUILayout.BeginScrollView(indexesScrollView, GUILayout.Width(210.0f), GUILayout.Height(550.0f));
Rect clickArea = EditorGUILayout.BeginVertical(guiLayoutDarkColor, GUILayout.Width(200.0f), GUILayout.Height(550.0f));
current = Event.current;
GUI.enabled = !isCreatingNewStage;
// Display all current quest stages
EditorGUILayout.BeginVertical();
for (int i = 0; i < questObj.FindProperty("questStages").arraySize; i++)
{
if (selectedStage == i && hasSelectedStage)
GUI.color = Color.green;
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Stage " + questObj.FindProperty("questStages").GetArrayElementAtIndex(i).FindPropertyRelative("index").intValue.ToString(), GUILayout.Width(150.0f)))
{
GUI.FocusControl(null);
selectedStage = i;
selectedQuestStageConditionIndex = -1;
hasSelectedStage = true;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUI.color = defaultColor;
}
GUI.enabled = true;
if (!isCreatingNewStage)
{
// DROPDOWN TO CREATE NEW STAGES
if (clickArea.Contains(current.mousePosition) && current.type == EventType.ContextClick)
{
GenericMenu menu = new GenericMenu();
menu.AddDisabledItem(new GUIContent("Quest Stages"));
menu.AddSeparator("");
menu.AddItem(new GUIContent("New"), false, CreateNew);
menu.AddItem(new GUIContent("Delete Selected"), false, DeleteSelected);
menu.ShowAsContext();
current.Use();
}
} else
{
int newStageIndex = 0;
EditorGUI.BeginChangeCheck();
GUI.SetNextControlName("NewStageField");
newStageIndex = EditorGUILayout.DelayedIntField(newStageIndex);
GUI.FocusControl("NewStageField");
Event e = Event.current;
switch (e.type)
{
case EventType.KeyDown:
if (current.keyCode == KeyCode.Escape)
{
isCreatingNewStage = false;
Repaint();
}
break;
}
// IF CREATE NEW ELEMENT
if (EditorGUI.EndChangeCheck())
{
//check if the selected stage index doesn't already exist
bool newStageAlreadyExist = false;
for(int i = 0; i < questObj.FindProperty("questStages").arraySize; i++)
{
if (questObj.FindProperty("questStages").GetArrayElementAtIndex(i).FindPropertyRelative("index").intValue == newStageIndex)
{
newStageAlreadyExist = true;
break;
}
}
// If the new stage already exist set it to a non-used stage (the last one +1)
if (newStageAlreadyExist)
newStageIndex = questObj.FindProperty("questStages").GetArrayElementAtIndex(questObj.FindProperty("questStages").arraySize - 1).FindPropertyRelative("index").intValue +1;
questObj.FindProperty("questStages").InsertArrayElementAtIndex(questObj.FindProperty("questStages").arraySize);
questObj.FindProperty("questStages").GetArrayElementAtIndex(questObj.FindProperty("questStages").arraySize - 1).FindPropertyRelative("index").intValue = newStageIndex;
// Order Array
bool triggered = false; // for selecting the corrent stage
for(int i = 0; i < questObj.FindProperty("questStages").arraySize; i++)
{
if(questObj.FindProperty("questStages").GetArrayElementAtIndex(questObj.FindProperty("questStages").arraySize - 1).FindPropertyRelative("index").intValue <
questObj.FindProperty("questStages").GetArrayElementAtIndex(i).FindPropertyRelative("index").intValue)
{
questObj.FindProperty("questStages").MoveArrayElement(questObj.FindProperty("questStages").arraySize - 1, i);
selectedStage = i;
triggered = true;
}
else if(!triggered)
selectedStage = questObj.FindProperty("questStages").arraySize - 1;
}
isCreatingNewStage = false;
}
}
void CreateNew()
{
isCreatingNewStage = true;
selectedQuestStageConditionIndex = -1;
}
void DeleteSelected()
{
if (hasSelectedStage)
{
questObj.FindProperty("questStages").DeleteArrayElementAtIndex(selectedStage);
hasSelectedStage = false;
}
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
EditorGUILayout.EndVertical();
EditorGUILayout.BeginHorizontal();
if (hasSelectedStage)
{
EditorGUILayout.BeginVertical("box", GUILayout.MaxHeight(360));
EditorGUILayout.BeginVertical(guiLayoutDarkColor);
EditorGUILayout.LabelField("[QUEST STAGE : " + questObj.FindProperty("questStages").GetArrayElementAtIndex(selectedStage).FindPropertyRelative("index").intValue + "]", HeaderStyle, GUILayout.MaxWidth(400.0f));
EditorGUILayout.PropertyField(questObj.FindProperty("questStages").GetArrayElementAtIndex(selectedStage).FindPropertyRelative("description"));
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 100;
EditorGUILayout.PropertyField(questObj.FindProperty("questStages").GetArrayElementAtIndex(selectedStage).FindPropertyRelative("completeQuest"));
EditorGUIUtility.labelWidth = 60;
EditorGUILayout.PropertyField(questObj.FindProperty("questStages").GetArrayElementAtIndex(selectedStage).FindPropertyRelative("failQuest"));
EditorGUIUtility.labelWidth = 110;
EditorGUILayout.PropertyField(questObj.FindProperty("questStages").GetArrayElementAtIndex(selectedStage).FindPropertyRelative("displayLogEntry"));
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
GUILayout.Space(15);
var curResultScript = questObj.FindProperty("questStages").GetArrayElementAtIndex(selectedStage).FindPropertyRelative("resultScript");
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Stage Script:");
string resultScriptMenuValue = string.IsNullOrEmpty(curResultScript.stringValue) ? "-None-" : curResultScript.stringValue;
if (GUILayout.Button(resultScriptMenuValue))
{
// create the menu and add items to it
GenericMenu menu = new GenericMenu();
menu.AddDisabledItem(new GUIContent("Quest Stages Scripts"));
menu.AddSeparator("");
menu.AddItem(new GUIContent("None"), false, Callback, new ScriptElementData(curResultScript, ""));
for (int i = 0; i < allQuestStagesScripts.Length; i++)
{
menu.AddItem(new GUIContent(allQuestStagesScripts[i].name), false, Callback, new ScriptElementData(curResultScript, allQuestStagesScripts[i].GetClass().Namespace + "." + allQuestStagesScripts[i].name));
}
menu.ShowAsContext();
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(15);
EditorGUILayout.BeginVertical(guiLayoutDarkColor);
current = Event.current;
EditorGUILayout.LabelField("QUEST STAGE CONDITIONS:", HeaderStyle);
questStageConditionsScrollView =
EditorGUILayout.BeginScrollView(questStageConditionsScrollView, true, true, GUILayout.Width(position.width - 230), GUILayout.Height(360));
Rect questStageConditionRectArea = new Rect(questStageConditionsScrollView.x, questStageConditionsScrollView.y, position.width, 400);
var questStages = questObj.FindProperty("questStages").GetArrayElementAtIndex(selectedStage);
for (int i = 0; i < questStages.FindPropertyRelative("stageConditions").arraySize; i++)
{
Rect currentConditionArea = EditorGUILayout.BeginHorizontal((selectedQuestStageConditionIndex == i) ? guiLayoutLightColor : guiLayoutDarkColor);
EditorGUILayout.PropertyField(questStages.FindPropertyRelative("stageConditions").GetArrayElementAtIndex(i), GUILayout.Width(1500));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(10);
if (currentConditionArea.Contains(current.mousePosition) && Event.current.type == EventType.MouseDown && Event.current.button == 0)
{
selectedQuestStageConditionIndex = i;
Repaint();
}
}
// DROPDOWN TO CREATE NEW CONDITIONS
if (questStageConditionRectArea.Contains(current.mousePosition) && current.type == EventType.ContextClick)
{
GenericMenu menu = new GenericMenu();
menu.AddDisabledItem(new GUIContent("Quest Stage Conditions"));
menu.AddItem(new GUIContent("New"), false, CreateNewQuestStageCondition);
menu.AddItem(new GUIContent("Delete Selected"), false, DeleteSelectedQuestStageCondition);
menu.ShowAsContext();
current.Use();
}
void CreateNewQuestStageCondition()
{
questStages.FindPropertyRelative("stageConditions").InsertArrayElementAtIndex(questStages.FindPropertyRelative("stageConditions").arraySize);
selectedQuestStageConditionIndex = questStages.FindPropertyRelative("stageConditions").arraySize - 1;
Repaint();
}
void DeleteSelectedQuestStageCondition()
{
if (selectedQuestStageConditionIndex != -1)
{
questStages.FindPropertyRelative("stageConditions").DeleteArrayElementAtIndex(selectedQuestStageConditionIndex);
selectedQuestStageConditionIndex = -1;
Repaint();
}
}
EditorGUILayout.EndScrollView();
EditorGUILayout.BeginHorizontal("box", GUILayout.MaxWidth(150));
GUI.enabled = (selectedQuestStageConditionIndex != -1) ? true : false;
GUI.enabled = (selectedQuestStageConditionIndex != -1 && selectedQuestStageConditionIndex != 0);
if (GUILayout.Button("↑"))
{
GUI.FocusControl(null);
questStages.FindPropertyRelative("stageConditions").MoveArrayElement(selectedQuestStageConditionIndex, selectedQuestStageConditionIndex - 1);
selectedQuestStageConditionIndex = selectedQuestStageConditionIndex - 1;
Repaint();
}
GUI.enabled = (selectedQuestStageConditionIndex != -1 && selectedQuestStageConditionIndex != questStages.FindPropertyRelative("stageConditions").arraySize - 1);
if (GUILayout.Button("↓"))
{
GUI.FocusControl(null);
questStages.FindPropertyRelative("stageConditions").MoveArrayElement(selectedQuestStageConditionIndex, selectedQuestStageConditionIndex + 1);
selectedQuestStageConditionIndex = selectedQuestStageConditionIndex + 1;
Repaint();
}
GUI.enabled = true;
EditorGUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
EditorGUILayout.EndVertical();
EditorGUILayout.EndVertical();
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndHorizontal();
GUILayout.Space(30);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("SAVE", ButtonStyle))
{
questObj.ApplyModifiedProperties();
// Refresh database
var AllQuestDatabaseFiles = GetAllInstances<QuestsDatabaseFile>();
foreach (QuestsDatabaseFile file in AllQuestDatabaseFiles)
file.fill();
this.Close();
}
if (GUILayout.Button("CANCEL", ButtonStyle))
{
this.Close();
}
EditorGUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
#endregion
break;
case CurrentWindow.NPCs:
break;
case CurrentWindow.Dialogues:
break;
default:
break;
}
}
public static MonoScript[] GetScriptAssetsOfType<T>()
{
MonoScript[] scripts = (MonoScript[])FindObjectsOfTypeIncludingAssets(typeof(MonoScript));
List<MonoScript> result = new List<MonoScript>();
foreach (MonoScript m in scripts)
{
if (m.GetClass() != null && m.GetClass().IsSubclassOf(typeof(T)) && m.GetType() != typeof(Shader))
{
result.Add(m);
}
}
return result.ToArray();
}
public static List<T> GetAllInstances<T>() where T : QuestsDatabaseFile
{
string[] guids = AssetDatabase.FindAssets("t:" + typeof(T).Name);
List<T> a = new List<T>(guids.Length);
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
a.Add(AssetDatabase.LoadAssetAtPath<T>(path));
}
return a;
}
}
}