using EasyTalk.Character;
using EasyTalk.Nodes.Core;
using EasyTalk.Nodes.Utility;
using EasyTalk.Settings;
using System.Collections.Generic;
namespace EasyTalk.Display
{
///
/// This is a utilty class for handling specific display functions, such as show/hide node functionality.
///
public class DisplayUtils
{
///
/// The currently active node.
///
private static AsyncNode activeNode;
///
/// A List of panels which are to be shown.
///
private static List panelsToShow = new List();
///
/// The number of panels shown.
///
private static int numPanelsShown = 0;
///
/// The target number of panels to show.
///
private static int numPanelsToShow = 0;
///
/// A List of panels which are to be hidden.
///
private static List panelsToHide = new List();
///
/// The number of panels hidden.
///
private static int numPanelsHidden = 0;
///
/// The target number of panels to hide.
///
private static int numPanelsToHide = 0;
///
/// Processes ths provided Show node, showing each panel/character configured for the node.
///
/// The Show node to process.
/// A mapping of Display IDs to Dialogue Panels.
/// The dialogue settings to use.
public static void HandleShowNode(AsyncNode node, Dictionary displayMap, EasyTalkDialogueSettings dialogueSettings)
{
//Find the display for each target in the Show node, set animatable sprites as appropriate, and display the display for each before continuing.
activeNode = node;
ShowNode showNode = (ShowNode)node;
foreach (ShowNodeItem item in showNode.Items)
{
if (item.ShowMode == ShowMode.CHARACTER)
{
CharacterDefinition charDef = dialogueSettings.DialogueRegistry.CharacterLibrary.GetCharacterDefinition(item.CharacterName);
AnimatableDisplayImage img = charDef.GetPortrayalSprite(item.ImageID);
string targetDisplay = img.TargetID;
if(item.DisplayID != null && item.DisplayID.Length > 0)
{
targetDisplay = item.DisplayID;
}
if (displayMap.ContainsKey(targetDisplay)) //Find the sub-display
{
DialoguePanel panel = displayMap[targetDisplay];
//If the panel isn't active, we need to activate it to make sure it's initial visibility state (isHidden) is set correctly.
//This is necessary because if the developer decides to disable the panel or its parent, the panel will cease to operate propertly when told to show itself.
if(!panel.isActiveAndEnabled)
{
panel.Activate();
}
if (panel.IsHidden && panel is CharacterSpritePanel)
{
panelsToShow.Add(panel);
panel.onShowComplete.AddListener(PanelShown);
((CharacterSpritePanel)panel).SetImageOnPanel(item.CharacterName, item.ImageID);
numPanelsToShow++;
panel.Show();
}
}
}
else if (item.ShowMode == ShowMode.DISPLAY)
{
//Find the sub-display
if (displayMap.ContainsKey(item.DisplayID))
{
DialoguePanel panel = displayMap[item.DisplayID];
if (panel.IsHidden)
{
panelsToShow.Add(panel);
panel.onShowComplete.AddListener(PanelShown);
numPanelsToShow++;
panel.Show();
}
}
}
}
if(numPanelsToShow == 0)
{
PanelShown();
}
}
///
/// Called when a panel has finished being shown. After the target counter is reached, ExecutionCompleted() is called on the active Show node.
///
private static void PanelShown()
{
numPanelsShown++;
if (numPanelsToShow <= numPanelsShown)
{
//Remove listener from panels.
foreach (DialoguePanel panel in panelsToShow)
{
panel.onShowComplete.RemoveListener(PanelShown);
}
panelsToShow.Clear();
numPanelsToShow = 0;
numPanelsShown = 0;
if (activeNode != null)
{
activeNode.ExecutionCompleted();
activeNode = null;
}
}
}
///
/// Processes the provided Hide node, hiding each panel/character configured for the node.
///
/// The Hide node to process.
/// A mapping of Display IDs to Dialogue Panels.
/// The dialogue settings to use.
public static void HandleHideNode(AsyncNode node, Dictionary displayMap, EasyTalkDialogueSettings dialogueSettings)
{
//Find the display for each target in the Hide node, and hide the display for each before continuing.
activeNode = node;
HideNode hideNode = (HideNode)node;
foreach (HideNodeItem item in hideNode.Items)
{
if (item.HideMode == HideMode.CHARACTER)
{
//Search through all character sprite displays to see if they are displaying the character targeted by the hide node, and if they are, hide them.
foreach(DialoguePanel panel in displayMap.Values)
{
//If the panel isn't active, we need to activate it to make sure it's initial visibility state (isHidden) is set correctly.
//This is necessary because if the developer decides to disable the panel or its parent, the panel will cease to operate propertly when told to hide itself.
if (!panel.isActiveAndEnabled)
{
panel.Activate();
}
if (!panel.IsHidden && panel is CharacterSpritePanel)
{
CharacterSpritePanel spritePanel = panel as CharacterSpritePanel;
if(spritePanel.CurrentCharacterName != null && spritePanel.CurrentCharacterName.Equals(item.CharacterName))
{
panelsToHide.Add(spritePanel);
panel.onHideComplete.AddListener(PanelHidden);
numPanelsToHide++;
panel.Hide();
}
}
}
}
else if (item.HideMode == HideMode.DISPLAY)
{
//Find the sub-display
if (displayMap.ContainsKey(item.DisplayID))
{
DialoguePanel panel = displayMap[item.DisplayID];
if (!panel.IsHidden)
{
panelsToHide.Add(panel);
panel.onHideComplete.AddListener(PanelHidden);
numPanelsToHide++;
panel.Hide();
}
}
}
}
if(numPanelsToHide == 0)
{
PanelHidden();
}
}
///
/// Called when a panel has finished being hidden. After the target counter is reached, ExecutionCompleted() is called on the active Hide node.
///
private static void PanelHidden()
{
numPanelsHidden++;
if (numPanelsToHide <= numPanelsHidden)
{
//Remove listener from panels.
foreach (DialoguePanel panel in panelsToShow)
{
panel.onHideComplete.RemoveListener(PanelHidden);
}
panelsToHide.Clear();
numPanelsToHide = 0;
numPanelsHidden = 0;
if (activeNode != null)
{
activeNode.ExecutionCompleted();
activeNode = null;
}
}
}
}
}