#if (UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0)
#define UNITY_PRE_5_1
#endif
using System;
using UnityEngine;
using UnityEditor;
using HutongGames.Editor;
namespace HutongGames.PlayMakerEditor
{
///
///
/// Base class for a Guided Tour Window
/// Uses GuidedTour to organize topics
/// Uses HtmlText for help text with links etc.
/// TODO: Remove some dependencies and move to HutongGames.Editor so we can use in other projects
///
public abstract class BaseGuidedTourWindow : BaseEditorWindow
{
protected GuidedTour guidedTour = new GuidedTour();
// Main scroll view
protected Vector2 scrollPosition;
private float scrollViewHeight;
private Rect selectedRect;
private bool autoScroll;
// Help panel
private Vector2 helpScrollPosition;
private GUIStyle helpStyle;
// Splitter between topics and help panel
private Rect splitterRect = new Rect();
private const float minHelpHeight = 50f;
private const float minTopicHeight = 100f;
private float helpHeight = 100f;
private bool draggingSplitter;
public override void Initialize()
{
// First time?
if (position.height < 300)
{
position = new Rect(position.x, position.y, position.width, 600);
}
minSize = new Vector2(200, 300);
// Refresh highlights created in repaint
FsmEditor.RepaintAll();
wantsMouseMove = true;
guidedTour.OnSelectionChanged = RepaintAll;
}
private void RepaintAll()
{
Repaint();
FsmEditor.RepaintAll();
}
private void InitStyles()
{
if (helpStyle == null)
{
helpStyle = new GUIStyle(EditorStyles.label)
{
richText = true,
wordWrap = true
};
}
}
public GuidedTour.Topic AddWindow(Type window,
string label,
string tooltip = "",
string helpText = "",
string highlightID = "",
string helpUrl = "")
{
return guidedTour.AddWindow(window, label, tooltip, helpText, highlightID, helpUrl);
}
public GuidedTour.Topic AddTopic(GuidedTour.Topic parent,
string label,
string tooltip = "",
string helpText = "",
string highlightID = "",
string helpUrl = "")
{
return guidedTour.AddTopic(parent, label, tooltip, helpText, highlightID, helpUrl);
}
///
/// Render the guidedTour
///
protected void DoGuidedTourGUI()
{
InitStyles();
HandleKeyboardInput();
DoSplitter();
// Hints
if (FsmEditorSettings.ShowHints)
{
GUILayout.Box("Click Topics to highlight UI and show more info.\nClick Help Button to open online help.", FsmEditorStyles.HintBox);
}
DoTopicsList();
GUILayout.FlexibleSpace();
DoBottomPanel();
// mouse event not used by other UI
// so must have clicked on empty area
if (Event.current.type == EventType.MouseDown &&
Event.current.mousePosition.y < position.height - helpHeight)
{
ClearHighlight();
}
}
private void DoTopicsList()
{
GUILayout.Space(5f);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
if (Event.current.type == EventType.Layout)
{
guidedTour.UpdateTopicTree();
}
var windows = guidedTour.GetWindows();
foreach (var window in windows)
{
FsmEditorGUILayout.LightDivider();
var topics = guidedTour.GetTopics(window);
foreach (var topic in topics)
{
DoTopicGUI(topic);
}
}
FsmEditorGUILayout.LightDivider();
EditorGUILayout.EndScrollView();
DoAutoScroll();
}
// Help panel for selected topic
private void DoBottomPanel()
{
GUILayout.BeginVertical(FsmEditorStyles.BottomBarBG);
FsmEditorGUILayout.Divider();
GUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins, GUILayout.Height(helpHeight));
helpScrollPosition = EditorGUILayout.BeginScrollView(helpScrollPosition);
if (guidedTour.SelectedTopic != null)
{
var topic = guidedTour.SelectedTopic;
GUILayout.BeginHorizontal();
GUILayout.Label(topic.Label.text, EditorStyles.boldLabel);
GUILayout.FlexibleSpace();
if (!string.IsNullOrEmpty(topic.HelpUrl))
{
if (FsmEditorGUILayout.HelpButton())
{
Application.OpenURL(topic.HelpUrl);
}
}
GUILayout.EndHorizontal();
if (!string.IsNullOrEmpty(topic.Label.tooltip))
{
EditorGUILayout.Space();
GUILayout.Label(topic.Label.tooltip, helpStyle);
}
EditorGUILayout.Space();
topic.HelpText.DoGUILayout(position.width);
}
EditorGUILayout.EndScrollView();
GUILayout.Space(5);
GUILayout.EndVertical();
GUILayout.EndVertical();
}
protected void HandleKeyboardInput()
{
switch (Event.current.keyCode)
{
case KeyCode.Escape:
ClearHighlight();
break;
}
}
protected void DoTopicGUI(GuidedTour.Topic topic)
{
if (!guidedTour.IsVisible(topic))
{
return;
}
// setup selected styles
var isSelected = guidedTour.IsHighlighted(topic);
var rowStyle = isSelected ? FsmEditorStyles.ActionItemSelected : FsmEditorStyles.ActionItem;
var labelStyle = isSelected ? FsmEditorStyles.ActionLabelSelected : FsmEditorStyles.ActionLabel;
GUILayout.BeginHorizontal(rowStyle);
GUILayout.Space(topic.Indent * 10f);
if (!string.IsNullOrEmpty(topic.HelpUrl))
{
if (FsmEditorGUILayout.HelpButton())
{
Application.OpenURL(topic.HelpUrl);
}
}
else
{
GUILayout.Space(18f);
}
if (GUILayout.Button(topic.Label, labelStyle))
{
autoScroll = true;
guidedTour.HighlightTopic(topic);
FsmEditor.RepaintAll();
GUIUtility.ExitGUI();
}
GUILayout.Space(20); // reserve space for scrollbar
GUILayout.EndHorizontal();
// Store selectedRect for auto scroll
if (isSelected && Event.current.type == EventType.Repaint)
{
selectedRect = GUILayoutUtility.GetLastRect();
selectedRect.y -= scrollPosition.y + 20;
selectedRect.height += 20; // pad to scroll a little further
}
}
private void DoAutoScroll()
{
// Auto scroll the main panel to show the selectedRect
// Should be called right after GUILayout.EndScrollView();
// Set autoScroll = true
if (Event.current.type == EventType.Repaint)
{
//Debug.Log("AutoScroll");
scrollViewHeight = GUILayoutUtility.GetLastRect().height;
if (autoScroll)
{
if (selectedRect.y < 0)
{
scrollPosition.y += selectedRect.y;
Repaint();
}
else if ((selectedRect.y + selectedRect.height) > scrollViewHeight)
{
scrollPosition.y += (selectedRect.y + selectedRect.height) - scrollViewHeight;
Repaint();
}
autoScroll = false;
}
}
}
private void DoSplitter()
{
if (draggingSplitter)
{
// set to size of window so it stays selected no matter how fast you drag
splitterRect.Set(0, 0, position.width, position.height);
}
else
{
splitterRect.Set(0, position.height - helpHeight - 4, position.width, 8);
}
EditorGUIUtility.AddCursorRect(splitterRect, MouseCursor.ResizeVertical);
if (splitterRect.Contains(currentEvent.mousePosition) && eventType == EventType.MouseDown)
{
draggingSplitter = true;
currentEvent.Use();
}
if (draggingSplitter)
{
if (eventType == EventType.MouseDrag)
{
helpHeight -= currentEvent.delta.y;
helpHeight = Mathf.Clamp(helpHeight, minHelpHeight, position.height - minTopicHeight);
currentEvent.Use();
}
if (currentEvent.rawType == EventType.MouseUp)
{
draggingSplitter = false;
}
Repaint();
}
}
public void ClearHighlight()
{
guidedTour.ClearHighlight();
Repaint();
}
///
/// Shorter command for convenience (used a lot)
///
protected string GetUrl(WikiPages page)
{
return DocHelpers.GetWikiPageUrl(page);
}
protected virtual void OnDisable()
{
ClearHighlight();
}
}
}