using System.Collections.Generic; using Articy.Unity; using Articy.Unity.Interfaces; using Articy.Unity.Utils; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; [RequireComponent(typeof(ArticyFlowPlayer))] public class ArticyDebugFlowPlayer : MonoBehaviour, IArticyFlowPlayerCallbacks { [Header("UI")] // a prefab used to instantiate a branch public GameObject branchPrefab; // the display name label, used to show the name of the current paused on node public Text displayNameLabel; // the main text label, used to show the text of the current paused on node public Text textLabel; // our 3 info labels in the middle of the panel, displaying basic information about the current pause. public Text typeLabel; public Text technicalNameLabel; public Text idLabel; // the ui target for our vertical list of branch buttons public RectTransform branchLayoutPanel; // the preview image ui element. A simple 64x64 image that will show the articy preview image or speaker, depending on the current pause. public Image previewImagePanel; [Header("Options")] // you can set this to true to see false branches in red, very helpful for debugging. public bool showFalseBranches = false; // the flow player component found on this game object private ArticyFlowPlayer flowPlayer; // Used to initializes our debug flow player handler. void Start() { // you could assign this via the inspector but this works equally well for our purpose. flowPlayer = GetComponent(); Debug.Assert(flowPlayer != null, "ArticyDebugFlowPlayer needs the ArticyFlowPlayer component!."); // by clearing at start we can safely have a prefab instantiated in the editor for our convenience and automatically get rid of it when we play. ClearAllBranches(); // just a little reminder text to actually set a start on object, otherwise the Flowplayer won't do anything and just idles. if (flowPlayer != null && flowPlayer.StartOn == null) textLabel.text = "No object selected in the flow player. Navigate to the ArticyflowPlayer and choose a StartOn node."; } // This is called everytime the flow player reaches and object of interest. public void OnFlowPlayerPaused(IFlowObject aObject) { if(aObject != null) { typeLabel.text = aObject.GetType().Name; // reset, just in case we don't have any idLabel.text = string.Empty; technicalNameLabel.text = string.Empty; var articyObj = aObject as IArticyObject; if(articyObj != null) { idLabel.text = articyObj.Id.ToHex(); technicalNameLabel.text = articyObj.TechnicalName; } } // To show the displayname in the ui of the current node var modelWithDisplayName = aObject as IObjectWithDisplayName; if (modelWithDisplayName != null) displayNameLabel.text = modelWithDisplayName.DisplayName; else displayNameLabel.text = string.Empty; // To show text in the ui of the current node // we just check if it has a text property by using the object property interfaces, if it has the property we use it to show the text in our main text label. var modelWithText = aObject as IObjectWithText; if (modelWithText != null) textLabel.text = modelWithText.Text; else textLabel.text = string.Empty; // this will make sure that we find a proper preview image to show in our ui. ExtractCurrentPausePreviewImage(aObject); } // called everytime the flow player encounteres multiple branches, or paused on a node and want to tell us how to continue. public void OnBranchesUpdated(IList aBranches) { // we clear all old branch buttons ClearAllBranches(); // for every branch provided by the flow player, we will create a button in our vertical list foreach (var branch in aBranches) { // if the branch is invalid, because a script evaluated to false, we don't create a button, unless we want to see false branches. if (!branch.IsValid && !showFalseBranches) continue; // we create a our button prefab and parent it to our vertical list var btn = Instantiate(branchPrefab); var rect = btn.GetComponent(); rect.SetParent(branchLayoutPanel, false); // here we make sure to get the Branch component from our button, either by referencing an already existing one, or by adding it. var branchBtn = btn.GetComponent(); if(branchBtn == null) branchBtn = btn.AddComponent(); // this will assign the flowplayer and branch and will create a proper label for the button. branchBtn.AssignBranch(flowPlayer, branch); } } // convenience method to clear everything underneath our branch layout panel, this should only be our dynamically created branch buttons. private void ClearAllBranches() { foreach (Transform child in branchLayoutPanel) Destroy(child.gameObject); } // method to find a preview image to show in the ui. private void ExtractCurrentPausePreviewImage(IFlowObject aObject) { IAsset articyAsset = null; previewImagePanel.sprite = null; // to figure out which asset we could show in our preview, we first try to see if it is an object with a speaker var dlgSpeaker = aObject as IObjectWithSpeaker; if (dlgSpeaker != null) { // if we have a speaker, we extract it, because now we have to check if it has a preview image. ArticyObject speaker = dlgSpeaker.Speaker; if (speaker != null) { var speakerWithPreviewImage = speaker as IObjectWithPreviewImage; if (speakerWithPreviewImage != null) { // our speaker has the property for preview image and we assign it to our asset. articyAsset = speakerWithPreviewImage.PreviewImage.Asset; } } } // if we have no asset until now, we could try to check if the target itself has a preview image. if (articyAsset == null) { var objectWithPreviewImage = aObject as IObjectWithPreviewImage; if (objectWithPreviewImage != null) { articyAsset = objectWithPreviewImage.PreviewImage.Asset; } } // and if we have an asset at this point, we load it as a sprite and show it in our ui image. if (articyAsset != null) { previewImagePanel.sprite = articyAsset.LoadAssetAsSprite(); } } public void CopyTargetLabel(BaseEventData aData) { var pointerData = aData as PointerEventData; if (pointerData != null) GUIUtility.systemCopyBuffer = pointerData.pointerPress.GetComponent().text; Debug.LogFormat("Copied text \"{0}\" into clipboard!", GUIUtility.systemCopyBuffer); } }