using HutongGames.Editor; namespace HutongGames.PlayMakerEditor { /// /// Guided Tour of the various PlayMaker editor windows and UI. /// NOTE: You can extend BaseGuidedTourWindow to make your own Guided Tour windows! /// public class PlayMakerGuidedTour : BaseGuidedTourWindow { private static PlayMakerGuidedTour instance; /// /// Open as Utility Window /// public static void Open() { FsmEditorWindow.OpenWindow(); // make sure main editor is open if (instance == null) { var window = CreateInstance(); window.ShowUtility(); // stays on top in OSX } else { GetWindow(); } } protected override void OnEnable() { base.OnEnable(); instance = this; } protected override void OnDisable() { base.OnDisable(); instance = null; } public override void Initialize() { base.Initialize(); needsMainEditor = true; SetTitle("PlayMaker"); BuildGuide(); } public override void DoGUI() { FsmEditorStyles.Init(); FsmEditorGUILayout.ToolWindowLargeTitle(this, "Guided Tour"); FsmEditorGUILayout.LabelWidth(200); //EditorGUILayout.HelpBox("NOTE: This is a BETA feature, please give feedback on the Playmaker Forums. Thanks!", MessageType.Info); DoGuidedTourGUI(); } public void OnFocus() { // Repaint all to make sure highlight ids are refreshed FsmEditor.RepaintAll(); Repaint(); } private void BuildGuide() { guidedTour.Reset(); BuildMainEditorGuide(); BuildActionBrowserGuide(); BuildGlobalVariablesGuide(); BuildFsmBrowserGuide(); BuildStateBrowserGuide(); BuildTemplatesBrowserGuide(); BuildEventBrowserGuide(); BuildFsmTimelineGuide(); BuildFsmLogGuide(); } private void BuildMainEditorGuide() { var root = AddWindow(typeof(FsmEditorWindow), "Main Editor", "The main PlayMaker Editor used to make FSMs.", "PlayMaker also uses various tool windows found in " + "Main Menu > PlayMaker > Editor Windows. " + "\n\nTool windows need the main PlayMaker Editor to be open.\n\n" + "NOTE: You can arrange PlayMaker windows and save custom layouts. " + "See: Customizing Your Workspace.", "Window", GetUrl(WikiPages.MainEditorWindow)); var selectionToolbar = AddTopic(root, "Selection Toolbar", "The Selection Toolbar lets you quickly select FSMs in the scene.", "", "", GetUrl(WikiPages.SelectionToolbar)); AddTopic(selectionToolbar, "Back", "Move Back in the selection history.", "TIP: Use this to quickly go back to a parent FSM after selecting a sub FSM."); AddTopic(selectionToolbar, "Forward", "Move forward in the selection history."); AddTopic(selectionToolbar, "History", "Recently selected FSMs.", "The popup menu shows recent FSMs, letting you quickly reselect one."); AddTopic(selectionToolbar, "Selected GameObject", "Select GameObjects that have FSMs", "The button shows the currently selected GameObject. The dropdown menu lets you select other GameObjects that have FSMs."); AddTopic(selectionToolbar, "Selected FSM", "Select an FSM on the GameObject.", "NOTE: A GameObject can have multiple FSMs."); AddTopic(selectionToolbar, "Lock Selection", "Lock the current selection.", "Keeps the FSM selected so it doesn't switch as you select other GameObjects." + "\n\nTIP: Use Lock to drag and drop components from other GameObjects into the selected FSM."); AddTopic(selectionToolbar, "Select Owner", "Select the GameObject that owns this FSM."); AddTopic(selectionToolbar, "Minimap Toggle", "Toggle the MiniMap on/off.", "The MiniMap shows an overview of the selected FSM." + "\n\nSee Graph View for more info."); AddTopic(root, "Graph View", "The canvas where you build FSMs.", "The Graph View shows a zoom-able canvas where you can add States and connect them with Transitions. " + "This defines the overall structure of an FSM. Most editing is done with right-click context menus." + "\n\nSelect a State to edit it further in the Inspector Panel", "", GetUrl(WikiPages.GraphView)); var inspector = AddTopic(root, "Inspector Panel", "Context editing of properties.", "FSM Inspector\nEdit the high level behaviour of the FSM.\n\n" + "State Inspector\nEdit the Actions run by the selected State.\n\n" + "Events Manager\nManage the Events used by the FSM.\n\n" + "Variables Manager\nManage the Variables used by the FSM.\n\n", "", GetUrl(WikiPages.InspectorPanel)); var fsmInspector = AddTopic(inspector, "FSM Inspector", "Edit the high level behaviour of the FSM.", "See also: FSM Inspector", "", GetUrl(WikiPages.FsmInspector)); fsmInspector.OnClick = () => FsmEditor.Inspector.SetMode(InspectorMode.FsmInspector); fsmInspector.Validate = () => FsmEditor.Inspector.Mode == InspectorMode.FsmInspector; var stateInspector = AddTopic(inspector, "State Inspector", "Edit the Actions run by the selected State.", "See also: State Inspector", "", GetUrl(WikiPages.StateInspector)); stateInspector.OnClick = () => FsmEditor.Inspector.SetMode(InspectorMode.StateInspector); stateInspector.Validate = () => FsmEditor.Inspector.Mode == InspectorMode.StateInspector; AddTopic(stateInspector, "Settings Menu"); var eventManager = AddTopic(inspector, "Event Manager", "Manage the Events used by the FSM.", "See also: Events Manager", "", GetUrl(WikiPages.EventManager)); eventManager.OnClick = () => FsmEditor.Inspector.SetMode(InspectorMode.EventManager); eventManager.Validate = () => FsmEditor.Inspector.Mode == InspectorMode.EventManager; var variablesManager = AddTopic(inspector, "Variable Manager", "Manage the Variables used by the FSM.", "See also: Variables Manager", "", GetUrl(WikiPages.VariableManager)); variablesManager.OnClick = () => FsmEditor.Inspector.SetMode(InspectorMode.VariableManager); variablesManager.Validate = () => FsmEditor.Inspector.Mode == InspectorMode.VariableManager; var debugToolbar = AddTopic(root, "Debug Toolbar", "The Debug Toolbar collects tools for debugging FSMs in the editor.", "", "", GetUrl(WikiPages.DebuggingToolbar)); AddTopic(debugToolbar, "Error Count", "Shows any errors in the project.", "Click to open the Error Check Window\n\n" + "NOTE: Realtime error checking is controlled in Preferences > Error Checking"); AddTopic(debugToolbar, "Debug Menu", "Opens the Debug Menu", "See Debug Menu."); AddTopic(debugToolbar, "Play Controls", "Play, Pause, and Step.", "You can see the behaviour of PlayMaker FSMs as the game runs in the Editor. " + "This 'visual debugging' of behaviours is one of the most powerful features of PlayMaker.\n\n" + "NOTE: Step behaviour is controlled in the Debug Menu."); var preferences = AddTopic(root, "Preferences", "", "Preferences allow you to customize how PlayMaker behaves.", "Preferences Toolbar", GetUrl(WikiPages.Preferences)); preferences.OnClick = () => FsmEditor.Inspector.SetMode(InspectorMode.Preferences); preferences.Validate = () => FsmEditor.Inspector.Mode == InspectorMode.Preferences; AddTopic(preferences, "Toggle Hints (F1)", "Quickly toggle all Hints off/on.", "Hints are in-line help boxes in PlayMaker editor windows. " + "They are useful while learning PlayMaker, " + "but you can save some space by turning them off.", "Hints"); AddTopic(preferences, "Open Preferences", "Opens Preferences in the Inspector Panel."); AddTopic(preferences, "Preferences Category", "Preferences are grouped into categories.", "See Online Help for more info."); } private void BuildActionBrowserGuide() { var root = AddWindow(typeof(FsmActionWindow), "Action Browser", "Browse for actions to add to a state.", "Actions run while a state is active. For an overview of how actions work, " + "check out Core Concepts > Actions in the online manual.", "Window", GetUrl(WikiPages.ActionBrowser)); AddTopic(root, "Settings Menu", "Settings for this window.", "Show Preview\nToggle the Preview of the selected action.\n\n" + "Hide Obsolete Actions\nHide actions that have been marked as Obsolete.\n\n" + "Close Window After Adding Action\nTreat the window like a popup dialog.\n\n" + "Auto Refresh Action Usage\nTrack action usage as you edit. In larger projects this might effect performance.\n\n" + "" ); AddTopic(root, "Search", "Search for actions.", "Filters the Action List as you type. Use the Search Mode dropdown to control the search.\n\n" + "NOTE: The Action List is also filtered by the Settings Menu."); AddTopic(root, "Search Mode", "Controls how to search for actions.", "Name\nSearch action names only.\n\n" + "Description\nSearch action description also.\n"); AddTopic(root, "Action List", "A list of all actions available in the project.", "NOTE: The list can be filtered by Search and the Settings Menu."); AddTopic(root, "Action Description", "A brief description of how the action works.", "A more detailed description can be found in the online help."); AddTopic(root, "Action Online Help", "Get more info on this action.", "Opens the relevant page in the online Action Reference.", "Online Help"); AddTopic(root, "Action Preview", "Preview the GUI for the selected action."); AddTopic(root, "Preview Toggle", "Toggle the preview of the selected action."); AddTopic(root, "Add Action To State", "Add selected action to the selected state.", "NOTE: You can also double click the action; Or drag and drop actions from the Action Browser into the State Inspector or Graph View.", "Add Action"); } private void BuildGlobalVariablesGuide() { var root = AddWindow(typeof(FsmGlobalsWindow), "Global Variables", "Manage the global variables used in the project.", "NOTE: Global variables are stored in:" + "\n" + "Assets/PlayMaker/Resources/PlayMakerGlobals.asset\n\n" + "DO NOT DELETE OR OVERWRITE THIS ASSET!\n\n" + "Use PlayMaker/Tools/Export Globals and Import Globals to transfer and merge globals between projects.", "Window", GetUrl(WikiPages.GlobalVariablesBrowser)); AddTopic(root, "Settings Menu", "Settings for this window."); AddTopic(root, "Search", "Interactively search as you type."); AddTopic(root, "Search Mode", "Controls how to perform the search."); AddTopic(root, "Variables List", "A list of all global variables used in the project.", "Add or select a global variable to edit.\n\nClick column headers to sort the list."); AddTopic(root, "Variable Editor", "Add/Edit a variable."); AddTopic(root, "Refresh Used Count", "Update the used count for this scene."); } private void BuildFsmBrowserGuide() { var root = AddWindow(typeof(FsmSelectorWindow), "FSM Browser", "Shows all loaded FSMs.", "Use this window to:\n\n" + "- Quickly select FSMs in your project.\n" + "- Track state of FSMs when the game is running.\n" + "- Quickly enable/disable FSMs as you test.\n" + "- Edit an FSM\'s description and help link.\n", "Window", GetUrl(WikiPages.FsmBrowser)); AddTopic(root, "Settings Menu", "Settings for this window.", "Show Full FSM Path\n" + "Show the GameObject and full path to the FSM.\n\n" + "Show Disabled FSMs\n" + "It can be useful at runtime to filter out disabled FSMs.\n\n" + "Show FSMs in Prefabs\n" + "Show FSMs used in Prefabs. Uncheck to see only FSMs in the scene.\n\n" + "Hide Prefabs when Playing\n" + "Most of the time you don't want to see prefabs when playing, just the running FSMs.\n"); AddTopic(root, "FSM Filter", "Filters the FSMs shown in the list.", "All\nShow all loaded FSMs.\n\n" + "On Selected Object\nOnly show FSMs on the selected GameObject/s.\n\n" + "Recently Selected\nOrders FSMs by their selection history, most recently selected at the top.\n\n" + "With Errors\nOnly show FSMs that have errors.\n"); AddTopic(root, "FSM List", "", "For each FSM shows: Enabled, Name, Current State.\n\n" + "Click an FSM to select it in the Main Editor and edit its properties.\n"); AddTopic(root, "Description", "A user defined description of what the FSM does.", "Use this field to help document your project."); AddTopic(root, "Help Url", "User defined link to online help.", "Use this field to help document your project. You can make a web page that explains how the FSM works in more detail.\n\n" + "HINT: You can right click in the Graph View and Save Screenshot to upload it to a web page.\n"); } private void BuildStateBrowserGuide() { var root = AddWindow(typeof(FsmStateWindow), "State Browser", "Shows all States in the selected FSM", "", "Window", GetUrl(WikiPages.StateBrowser)); AddTopic(root, "FSM Selection", "The selected FSM.", "The dropdown lets you select another FSM.\n" + "The selection is synced across editor windows."); AddTopic(root, "State List", "States in the selected FSM.", "Click a State to select it in the Main Editor."); } private void BuildTemplatesBrowserGuide() { var root = AddWindow(typeof(FsmTemplateWindow), "Templates Browser", "Shows all saved FSM Templates.", "Templates are re-usable FSMs. You can paste a Template as a new FSM, paste it into an existing FSM, " + "run it in a State using the Run FSM Action etc.\n\n" + "This window lets you manage the Templates in your project.", "Window", GetUrl(WikiPages.TemplatesBrowser)); AddTopic(root, "Settings Menu", "Settings for this window."); AddTopic(root, "Search", "Interactively search as you type."); AddTopic(root, "Search Mode", "Controls how to perform the search.", "Name\nSearch template names only.\n\n" + "Description\nSearch template description also.\n"); AddTopic(root, "Templates List", "", "Shows all the Templates in your project sorted by the categories you've defined."); AddTopic(root, "Category", "User defined category", "Use this field to edit the Template's Category. You can make as many Categories as you need for a project."); AddTopic(root, "Description", "User defined description of what the Template does.", "Use this to document your project. Since Templates can be re-used a good description is important."); AddTopic(root, "New Template", "Save a new Template asset", "NOTE: Template assets must be saved under the projects Assets folder. " + "To transfer templates to another project export it in a unitypackage."); AddTopic(root, "Load Add Templates", "Refresh the list of Templates."); } private void BuildEventBrowserGuide() { var root = AddWindow(typeof(FsmEventsWindow), "Events Browser", "Shows Events used by FSMs", "", "Window", GetUrl(WikiPages.EventBrowser)); AddTopic(root, "Settings Menu", "Settings for this window."); AddTopic(root, "Search", "Interactively search as you type."); AddTopic(root, "Search Mode", "Controls how to perform the search."); AddTopic(root, "Event List", "Events used by FSMs.", "The first column is the Global flag. Global Events can be sent between FSMs.\n" + "The Used column shows how many loaded FSMs use the event.\n" + "HINT: Right click on an event to see the FSMs that use it.\n\n" + "NOTE: Events are created in the Events tab in the Main Editor."); } private void BuildFsmTimelineGuide() { var root = AddWindow(typeof(FsmTimelineWindow), "Timeline Log", "A visual log of FSM state changes.", "NOTE: This is not connected to the new Unity Timeline feature!", "Window", GetUrl(WikiPages.FsmTimeline)); AddTopic(root, "FSM Filter", "Filters the FSMs to show.", "All FSMs\nShows all FSMs.\n\n" + "FSMs in Scene:\nShows only the FSMs in the current scene.\n\n" + "On Selected Objects:\nShows only the FSMs on the currently selected GameObject/s.\n\n" + "Recently Selected:\nOrders FSMs by their selection history, most recently selected at the top.\n"); AddTopic(root, "Timeline", "Time bar for the visual log.", "Panning and zooming works in a similar way to the Unity Animation Window.\n\n" + "Click the bar to pause the game and scrub time. Time scrubbing is synchronized across all Log Windows. " + "HINT: If Debug Flow is enabled the Main Editor will show variable values at that time.\n"); AddTopic(root, "Visual Log", "Visual log of FSM states.", "Bars represent the State of each FSM over time. The bars use the State's color to help visually organize state changes."); AddTopic(root, "Refresh", "Refresh FSM List", "Sometimes GameObjects are added/removed while playing. Use Refresh to update the FSM list."); } private void BuildFsmLogGuide() { var root = AddWindow(typeof(FsmLogWindow), "FSM Log", "A log of all FSM Events", "The log lets you examine events and state changes in an FSM. " + "You can see how long an FSM was in a state, the event that triggered the state change, etc.\n\n" + "HINT: Click SentBy to jump to the GameObject/FSM that sent an event.", "Window", GetUrl(WikiPages.FsmLog)); AddTopic(root, "Settings Menu", "Settings for this window.", "Show TimeCode\nDisplay a time code next to each log event. " + "Time codes can make it easier to figure out what else is happening on other FSMs at the same time.\n\n" + "Show Sent By\nShow the FSM that sent an event. Click on the sender to select it.\n\n" + "Show State Exit\nShow state Exit events in log. Hiding Exit events can make the log more concise; " + "the Exit is implied in the Entry to the next state."); AddTopic(root, "FSM Selection", "The selected FSM.", "The dropdown lets you select another FSM.\n" + "The selection is synced across editor windows."); AddTopic(root, "Log Entries", "Log entries for the selected FSM", "Entries follow these conventions:\n\n" + "START - Logged when the FSM is enabled.\n" + "EVENT [EventName] - Logged when the FSM receives an event.\n" + "EXIT [StateName] - Logged when a state is exited.\n" + "ENTER [StateName] - Logged when a state is entered.\n" + "STOP - Logged when the FSM is disabled.\n\n" + "Additionally, Actions and scripts can log 3 types of entries:\n\n" + "INFO Plain text log.\n" + "WARNING Warning icon and message.\n" + "ERROR Error icon and message. Also pauses execution.\n\n" + "HINT: Click SentBy to jump to the GameObject/FSM that sent an event.\n\n" + "See Online Docs for more info.\n"); AddTopic(root, "Clear", "Delete all log entries."); } /* You can cleanup here protected override void OnDisable() { base.OnDisable(); }*/ } }