CapersProject/Assets/Plugins/Pixel Crushers/Dialogue System/Scripts/MVC/View/View/ConversationView.cs

687 lines
31 KiB
C#

// Copyright (c) Pixel Crushers. All rights reserved.
using UnityEngine;
using System;
namespace PixelCrushers.DialogueSystem
{
public delegate void DialogueEntrySpokenDelegate(Subtitle subtitle);
public delegate float GetDefaultSubtitleDurationDelegate(string text);
/// <summary>
/// Handles the user interaction part of a conversation. The ConversationController
/// provides the content. ConversationView processes UI events and hands control to
/// ConversationController.
/// </summary>
public class ConversationView : MonoBehaviour
{
/// <summary>
/// You can assign a function here to override the method used to
/// determine the default subtitle duration -- that is, the value of {{end}}.
/// </summary>
public static GetDefaultSubtitleDurationDelegate overrideGetDefaultSubtitleDuration = null;
/// <summary>
/// Called when a subtitle is finished displaying (including text delay and cutscene
/// sequence).
/// </summary>
public event EventHandler FinishedSubtitleHandler = null;
/// <summary>
/// Called when the player selects a response.
/// </summary>
public event EventHandler<SelectedResponseEventArgs> SelectedResponseHandler = null;
private delegate bool IsCancelKeyDownDelegate();
private IDialogueUI ui = null;
private Sequencer m_sequencer = null;
private DisplaySettings settings = null;
private Subtitle lastNPCSubtitle = null;
private Subtitle lastPCSubtitle = null;
private Subtitle lastSubtitle = null;
private IsCancelKeyDownDelegate IsCancelKeyDown = null;
private Action CancelledHandler = null;
private DialogueEntrySpokenDelegate dialogueEntrySpokenHandler = null;
private bool waitForContinue = false;
private bool notifyOnFinishSubtitle = false;
private bool isPlayingResponseMenuSequence = false;
private int initialFrameCount;
public DisplaySettings displaySettings { get { return settings; } }
public bool isWaitingForContinue { get { return waitForContinue; } }
public Sequencer sequencer { get { return m_sequencer; } }
public IDialogueUI dialogueUI
{
get
{
return ui;
}
set
{
if (ui != value)
{
ui.SelectedResponseHandler -= OnSelectedResponse;
ui.Close();
ui = value;
ui.Open();
ui.SelectedResponseHandler += OnSelectedResponse;
}
}
}
/// <summary>
/// Initialize a UI and sequencer with displaySettings.
/// </summary>
/// <param name='ui'>
/// Dialogue UI.
/// </param>
/// <param name='sequencer'>
/// Sequencer.
/// </param>
/// <param name='displaySettings'>
/// Display settings to initiate the UI and sequencer with.
/// </param>
public void Initialize(IDialogueUI ui, Sequencer sequencer, DisplaySettings displaySettings, DialogueEntrySpokenDelegate dialogueEntrySpokenHandler)
{
this.ui = ui;
this.m_sequencer = sequencer;
this.settings = DialogueManager.allowSimultaneousConversations ? new DisplaySettings(displaySettings) : displaySettings;
this.dialogueEntrySpokenHandler = dialogueEntrySpokenHandler;
this.initialFrameCount = Time.frameCount;
ui.Open();
sequencer.Open();
ui.SelectedResponseHandler += OnSelectedResponse;
sequencer.FinishedSequenceHandler += OnFinishedSubtitle;
}
/// <summary>
/// Close the conversation view.
/// </summary>
public void Close()
{
ui.SelectedResponseHandler -= OnSelectedResponse;
m_sequencer.FinishedSequenceHandler -= OnFinishedSubtitle;
ui.Close();
m_sequencer.Close();
Destroy(this);
}
/// <summary>
/// Checks if the player has cancelled the conversation.
/// </summary>
public void Update()
{
if (Cancelled() && (CancelledHandler != null)) CancelledHandler();
}
private bool Cancelled()
{
return (IsCancelKeyDown == null) ? false : IsCancelKeyDown();
}
private bool IsSubtitleCancelKeyDown()
{
return settings.GetCancelSubtitleInput().isDown;
}
private bool IsConversationCancelKeyDown()
{
return settings.GetCancelConversationInput().isDown;
}
/// <summary>
/// Starts displaying a subtitle.
/// </summary>
/// <param name='subtitle'>
/// Subtitle to display.
/// </param>
/// <param name='isPCResponseNext'>
/// Indicates whether the next stage is the player or NPC.
/// </param>
/// <param name='isPCAutoResponseNext'>
/// Indicates whether the next stage is a player auto-response.
/// </param>
public void StartSubtitle(Subtitle subtitle, bool isPCResponseMenuNext, bool isPCAutoResponseNext)
{
notifyOnFinishSubtitle = true;
if (subtitle != null)
{
if (DialogueDebug.logInfo) Debug.Log(string.Format("{0}: {1} says '{2}'", new System.Object[] { DialogueDebug.Prefix, Tools.GetGameObjectName(subtitle.speakerInfo.transform), subtitle.formattedText.text }));
if (DialogueManager.instance.allowSimultaneousConversations)
{
DialogueManager.instance.displaySettings = settings;
}
NotifyParticipantsOnConversationLine(subtitle);
m_sequencer.SetParticipants(subtitle.speakerInfo.transform, subtitle.listenerInfo.transform);
m_sequencer.entrytag = subtitle.entrytag;
m_sequencer.subtitleEndTime = GetDefaultSubtitleDuration(subtitle.formattedText.text);
if (!string.IsNullOrEmpty(subtitle.sequence) && subtitle.sequence.Contains("{{default}}"))
{
subtitle.sequence = subtitle.sequence.Replace("{{default}}", GetDefaultSequence(subtitle));
}
subtitle.sequence = string.IsNullOrEmpty(subtitle.sequence) ? GetDefaultSequence(subtitle) : PreprocessSequence(subtitle);
if (ShouldShowSubtitle(subtitle))
{
ui.ShowSubtitle(subtitle);
// Save this info in case SetContinueMode() sequencer command forces reevaluation:
_subtitle = subtitle;
_isPCResponseMenuNext = isPCResponseMenuNext;
_isPCAutoResponseNext = isPCAutoResponseNext;
SetupContinueButton(subtitle, isPCResponseMenuNext, isPCAutoResponseNext);
}
else
{
waitForContinue = false;
}
if (subtitle.speakerInfo.isNPC)
{
lastNPCSubtitle = subtitle;
}
else
{
lastPCSubtitle = subtitle;
}
lastSubtitle = subtitle;
if (dialogueEntrySpokenHandler != null) dialogueEntrySpokenHandler(subtitle);
m_sequencer.PlaySequence(subtitle.sequence, settings.subtitleSettings.informSequenceStartAndEnd, false);
}
else
{
FinishSubtitle();
}
IsCancelKeyDown = IsSubtitleCancelKeyDown;
CancelledHandler = OnCancelSubtitle;
if (!string.IsNullOrEmpty(subtitle.formattedText.text)) _lastModeWasResponseMenu = false;
}
private Subtitle _subtitle = null;
private bool _isPCResponseMenuNext = false;
private bool _isPCAutoResponseNext = false;
private bool _lastModeWasResponseMenu = false;
/// <summary>
/// Determines whether the continue button should be shown, and shows or hides it.
/// Call this if you've manually changed the continue button mode while the
/// conversation is displaying a line. In most cases you won't ever need to call this
/// manually.
/// </summary>
public void SetupContinueButton()
{
SetupContinueButton(_subtitle, _isPCResponseMenuNext, _isPCAutoResponseNext);
}
private void SetupContinueButton(Subtitle subtitle, bool isPCResponseMenuNext, bool isPCAutoResponseNext)
{
if (subtitle == null) return;
var isPCLine = subtitle.speakerInfo.characterType == CharacterType.PC;
waitForContinue = ShouldWaitForContinueButton(isPCLine, isPCResponseMenuNext, isPCAutoResponseNext);
var showContinueButton = ShouldShowContinueButton(isPCLine, isPCResponseMenuNext, isPCAutoResponseNext);
if (waitForContinue)
{
if (string.IsNullOrEmpty(subtitle.formattedText.text) && (subtitle.dialogueEntry.id == 0))
{
waitForContinue = false;
}
}
var abstractDialogueUI = ui as AbstractDialogueUI;
if (abstractDialogueUI != null)
{
if (showContinueButton)
{
abstractDialogueUI.ShowContinueButton(subtitle);
}
else
{
abstractDialogueUI.HideContinueButton(subtitle);
}
}
}
private bool ShouldWaitForContinueButton(bool isPCLine, bool isPCResponseMenuNext, bool isPCAutoResponseNext)
{
switch (settings.GetContinueButtonMode())
{
case DisplaySettings.SubtitleSettings.ContinueButtonMode.Always:
return true;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.Never:
return false;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.Optional:
return false;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalBeforeResponseMenu:
return !isPCResponseMenuNext;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotBeforeResponseMenu:
return !isPCResponseMenuNext;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalBeforePCAutoresponseOrMenu:
return !(isPCResponseMenuNext || isPCAutoResponseNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotBeforePCAutoresponseOrMenu:
return !(isPCResponseMenuNext || isPCAutoResponseNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalForPC:
return !isPCLine;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotForPC:
return !isPCLine;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalForPCOrBeforeResponseMenu:
return !(isPCLine || isPCResponseMenuNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotForPCOrBeforeResponseMenu:
return !(isPCLine || isPCResponseMenuNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalForPCOrBeforePCAutoresponseOrMenu:
return !(isPCLine || isPCResponseMenuNext || isPCAutoResponseNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotForPCOrBeforePCAutoresponseOrMenu:
return !(isPCLine || isPCResponseMenuNext || isPCAutoResponseNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OnlyForPC:
return isPCLine;
default:
return false;
}
}
private bool ShouldShowContinueButton(bool isPCLine, bool isPCResponseMenuNext, bool isPCAutoResponseNext)
{
// If we require continue button on last line, we have to grab the current conversation state to check it:
if (settings.subtitleSettings.requireContinueOnLastLine && !DialogueManager.instance.currentConversationState.hasAnyResponses)
{
// Note: side effect - set waitForContinue true
waitForContinue = true;
return true;
}
// Should we show the continue button? (Even if optional and not waiting for it)
switch (settings.GetContinueButtonMode())
{
case DisplaySettings.SubtitleSettings.ContinueButtonMode.Always:
return true;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.Never:
return false;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.Optional:
return true;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalBeforeResponseMenu:
return true;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotBeforeResponseMenu:
return !isPCResponseMenuNext;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalBeforePCAutoresponseOrMenu:
return true;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotBeforePCAutoresponseOrMenu:
return !(isPCResponseMenuNext || isPCAutoResponseNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalForPC:
return true;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotForPC:
return !isPCLine;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalForPCOrBeforeResponseMenu:
return true;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotForPCOrBeforeResponseMenu:
return !(isPCLine || isPCResponseMenuNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OptionalForPCOrBeforePCAutoresponseOrMenu:
return true;
case DisplaySettings.SubtitleSettings.ContinueButtonMode.NotForPCOrBeforePCAutoresponseOrMenu:
return !(isPCLine || isPCResponseMenuNext || isPCAutoResponseNext);
case DisplaySettings.SubtitleSettings.ContinueButtonMode.OnlyForPC:
return isPCLine;
default:
return false;
}
}
/// <summary>
/// Shows the most recently displayed subtitle.
/// </summary>
public void ShowLastNPCSubtitle()
{
if (ShouldShowLastNPCSubtitle()) ui.ShowSubtitle(lastNPCSubtitle);
FinishSubtitle();
}
private bool ShouldShowLastNPCSubtitle()
{
return (settings != null) && settings.GetShowNPCSubtitlesWithResponses() &&
(lastNPCSubtitle != null) && (lastNPCSubtitle.speakerInfo.characterType == CharacterType.NPC);
}
private bool ShouldShowLastPCSubtitle()
{
return (settings != null) && settings.GetShowNPCSubtitlesWithResponses() &&
settings.subtitleSettings.allowPCSubtitleReminders &&
(lastPCSubtitle != null) && (lastSubtitle == lastPCSubtitle) &&
(lastPCSubtitle.speakerInfo.characterType == CharacterType.PC);
}
private bool ShouldShowSubtitle(Subtitle subtitle)
{
if ((subtitle != null) && (settings != null) && (settings.subtitleSettings != null))
{
if (subtitle.formattedText.noSubtitle ||
string.Equals(subtitle.sequence, "None()") ||
string.Equals(subtitle.sequence, "None();") ||
(!settings.cameraSettings.showSubtitleOnEmptyContinue &&
(string.Equals(subtitle.sequence, "Continue()") ||
string.Equals(subtitle.sequence, "Continue();"))))
{
return false;
}
if ((subtitle.speakerInfo.characterType == CharacterType.NPC) && settings.GetShowNPCSubtitlesDuringLine())
{
return true;
}
if ((subtitle.speakerInfo.characterType == CharacterType.PC) && settings.GetShowPCSubtitlesDuringLine())
{
return !(_lastModeWasResponseMenu && settings.GetSkipPCSubtitleAfterResponseMenu());
}
}
return false;
}
/// <summary>
/// Continues this conversation if the dialogue UI matches.
/// </summary>
/// <param name="dialogueUI"></param>
public void OnConversationContinue(IDialogueUI dialogueUI)
{
if (dialogueUI == this.ui)
{
HandleContinueButtonClick();
}
}
/// <summary>
/// Continues all conversations.
/// </summary>
public void OnConversationContinueAll()
{
HandleContinueButtonClick();
}
public void HandleContinueButtonClick()
{
// If we just started and another conversation just ended, ignore the continue:
if (Time.frameCount == initialFrameCount && initialFrameCount == ConversationController.frameLastConversationEnded) return;
waitForContinue = false;
FinishSubtitle();
}
private void OnCancelSubtitle()
{
if (lastSubtitle == null) // Need to create a dummy subtitle to OnConversationLineCancelled's signature.
{
var dummySubtitle = new Subtitle(null, null, null, string.Empty, string.Empty, null);
BroadcastMessage(DialogueSystemMessages.OnConversationLineCancelled, dummySubtitle, SendMessageOptions.DontRequireReceiver);
}
else
{
BroadcastMessage(DialogueSystemMessages.OnConversationLineCancelled, lastSubtitle, SendMessageOptions.DontRequireReceiver);
}
waitForContinue = false;
FinishSubtitle();
}
private void FinishSubtitle()
{
if (!waitForContinue)
{
if (m_sequencer != null) m_sequencer.Stop();
ui.HideSubtitle(lastSubtitle);
if (notifyOnFinishSubtitle)
{
notifyOnFinishSubtitle = false;
if (lastSubtitle != null) NotifyParticipantsOnConversationLineEnd(lastSubtitle);
if (FinishedSubtitleHandler != null) FinishedSubtitleHandler(this, EventArgs.Empty);
}
}
}
private void OnFinishedSubtitle()
{
FinishSubtitle();
}
/// <summary>
/// Displays the player response menu.
/// </summary>
/// <param name='subtitle'>
/// Last subtitle, to display as a reminder of what the player is responding to.
/// </param>
/// <param name='responses'>
/// Responses.
/// </param>
public void StartResponses(Subtitle subtitle, Response[] responses)
{
PlayResponseMenuSequence(subtitle.responseMenuSequence);
Subtitle lastSubtitle = ShouldShowLastPCSubtitle()
? lastPCSubtitle
: ShouldShowLastNPCSubtitle()
? lastNPCSubtitle
: null;
NotifyOnResponseMenu(responses);
ui.ShowResponses(lastSubtitle, responses, settings.GetResponseTimeout());
IsCancelKeyDown = IsConversationCancelKeyDown;
CancelledHandler = OnCancelResponseMenu;
_lastModeWasResponseMenu = true;
}
private void PlayResponseMenuSequence(string responseMenuSequence)
{
if (string.IsNullOrEmpty(responseMenuSequence) && !string.IsNullOrEmpty(settings.GetDefaultResponseMenuSequence()))
{
responseMenuSequence = settings.GetDefaultResponseMenuSequence();
}
if (!string.IsNullOrEmpty(responseMenuSequence))
{
m_sequencer.FinishedSequenceHandler -= OnFinishedSubtitle;
m_sequencer.Stop();
m_sequencer.PlaySequence(responseMenuSequence);
isPlayingResponseMenuSequence = true;
}
}
private void StopResponseMenuSequence()
{
if (isPlayingResponseMenuSequence)
{
isPlayingResponseMenuSequence = false;
m_sequencer.Stop();
m_sequencer.StopAllCoroutines();
m_sequencer.FinishedSequenceHandler += OnFinishedSubtitle;
}
}
private void OnCancelResponseMenu()
{
NotifyParticipantsOnConversationCancelled();
//---Was: BroadcastMessage(DialogueSystemMessages.OnConversationCancelled, sequencer.speaker, SendMessageOptions.DontRequireReceiver);
SelectResponse(new SelectedResponseEventArgs(null));
}
private void OnSelectedResponse(object sender, SelectedResponseEventArgs e)
{
SelectResponse(e);
}
public void SelectResponse(SelectedResponseEventArgs e)
{
StopResponseMenuSequence();
ui.HideResponses();
if (SelectedResponseHandler != null) SelectedResponseHandler(this, e);
}
/// <summary>
/// Gets the default sequence for a subtitle.
/// </summary>
/// <returns>
/// The default sequence.
/// </returns>
/// <param name='subtitle'>
/// Subtitle.
/// </param>
public string GetDefaultSequence(Subtitle subtitle)
{
float duration = m_sequencer.subtitleEndTime;
var isPlayerLine = (subtitle.speakerInfo.characterType == CharacterType.PC);
if (isPlayerLine && (!settings.GetShowPCSubtitlesDuringLine() || (_lastModeWasResponseMenu && settings.GetSkipPCSubtitleAfterResponseMenu())))
{
var playerSequence = settings.GetDefaultPlayerSequence();
return Sequencer.ReplaceShortcuts(playerSequence).Replace(SequencerKeywords.End, duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
}
else
{
var line = settings.GetDefaultSequence();
if (isPlayerLine && !string.IsNullOrEmpty(settings.GetDefaultPlayerSequence()))
{
line = settings.GetDefaultPlayerSequence();
}
if (string.IsNullOrEmpty(line))
{
return string.Format(System.Globalization.CultureInfo.InvariantCulture, "Delay({0})", new System.Object[] { duration });
}
else
{
return Sequencer.ReplaceShortcuts(line).Replace(SequencerKeywords.End, duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
}
}
}
/// <returns>
/// A duration based on the text length and the Dialogue Manager's
/// Subtitle Settings > Min Subtitle Seconds and Subtitle Chars Per Second.
/// Also factors in time for RPGMaker-style pause codes.
/// </returns>
public float GetDefaultSubtitleDuration(string text)
{
return GetDefaultSubtitleDurationInSeconds(text, settings);
//if (overrideGetDefaultSubtitleDuration != null) return overrideGetDefaultSubtitleDuration(text);
//int numCharacters = string.IsNullOrEmpty(text) ? 0 : Tools.StripRichTextCodes(text).Length;
//float numRPGMakerPauses = 0;
//if (text.Contains("\\"))
//{
// var numFullPauses = (text.Length - text.Replace("\\.", string.Empty).Length) / 2;
// var numQuarterPauses = (text.Length - text.Replace("\\,", string.Empty).Length) / 2;
// numRPGMakerPauses = (1.0f * numFullPauses) + (0.25f * numQuarterPauses);
//}
//return Mathf.Max(settings.GetMinSubtitleSeconds(), numRPGMakerPauses + (numCharacters / Mathf.Max(1, settings.GetSubtitleCharsPerSecond())));
}
/// <summary>
/// A duration based on the text length and the Dialogue Manager's
/// Subtitle Settings > Min Subtitle Seconds and Subtitle Chars Per Second.
/// Also factors in time for RPGMaker-style pause codes.
/// </summary>
/// <param name="text">Text.</param>
/// <param name="displaySettings">If null, uses Dialogue Manager's Display Settings.</param>
public static float GetDefaultSubtitleDurationInSeconds(string text, DisplaySettings displaySettings = null)
{
if (overrideGetDefaultSubtitleDuration != null) return overrideGetDefaultSubtitleDuration(text);
var settings = displaySettings ?? DialogueManager.displaySettings;
int numCharacters = string.IsNullOrEmpty(text) ? 0 : Tools.StripRichTextCodes(text).Length;
float numRPGMakerPauses = 0;
if (text.Contains("\\"))
{
var numFullPauses = (text.Length - text.Replace("\\.", string.Empty).Length) / 2;
var numQuarterPauses = (text.Length - text.Replace("\\,", string.Empty).Length) / 2;
numRPGMakerPauses = (1.0f * numFullPauses) + (0.25f * numQuarterPauses);
}
return Mathf.Max(settings.GetMinSubtitleSeconds(), numRPGMakerPauses + (numCharacters / Mathf.Max(1, settings.GetSubtitleCharsPerSecond())));
}
private string PreprocessSequence(Subtitle subtitle)
{
if ((subtitle == null) || (string.IsNullOrEmpty(subtitle.sequence))) return string.Empty;
subtitle.sequence = Sequencer.ReplaceShortcuts(subtitle.sequence);
if (!subtitle.sequence.Contains(SequencerKeywords.End)) return subtitle.sequence;
float duration = m_sequencer.subtitleEndTime;
return subtitle.sequence.Replace(SequencerKeywords.End, duration.ToString(System.Globalization.CultureInfo.InvariantCulture));
}
private void NotifyParticipantsOnConversationLine(Subtitle subtitle)
{
NotifyParticipants(DialogueSystemMessages.OnConversationLine, subtitle);
}
private void NotifyParticipantsOnConversationLineEnd(Subtitle subtitle)
{
NotifyParticipants(DialogueSystemMessages.OnConversationLineEnd, subtitle);
}
private void NotifyParticipants(string message, Subtitle subtitle)
{
if (subtitle != null)
{
bool validSpeakerTransform = CharacterInfoHasValidTransform(subtitle.speakerInfo);
bool validListenerTransform = CharacterInfoHasValidTransform(subtitle.listenerInfo);
bool speakerIsListener = validSpeakerTransform && validListenerTransform && (subtitle.speakerInfo.transform == subtitle.listenerInfo.transform);
if (validSpeakerTransform) subtitle.speakerInfo.transform.BroadcastMessage(message, subtitle, SendMessageOptions.DontRequireReceiver);
if (validListenerTransform && !speakerIsListener) subtitle.listenerInfo.transform.BroadcastMessage(message, subtitle, SendMessageOptions.DontRequireReceiver);
DialogueManager.instance.BroadcastMessage(message, subtitle, SendMessageOptions.DontRequireReceiver);
}
}
private void NotifyOnResponseMenu(Response[] responses)
{
if (responses != null)
{
if (lastSubtitle != null)
{
bool validSpeakerTransform = CharacterInfoHasValidTransform(lastSubtitle.speakerInfo);
bool validListenerTransform = CharacterInfoHasValidTransform(lastSubtitle.listenerInfo);
bool speakerIsListener = validSpeakerTransform && validListenerTransform && (lastSubtitle.speakerInfo.transform == lastSubtitle.listenerInfo.transform);
if (validSpeakerTransform) lastSubtitle.speakerInfo.transform.BroadcastMessage(DialogueSystemMessages.OnConversationResponseMenu, responses, SendMessageOptions.DontRequireReceiver);
if (validListenerTransform && !speakerIsListener) lastSubtitle.listenerInfo.transform.BroadcastMessage(DialogueSystemMessages.OnConversationResponseMenu, responses, SendMessageOptions.DontRequireReceiver);
}
DialogueManager.instance.BroadcastMessage(DialogueSystemMessages.OnConversationResponseMenu, responses, SendMessageOptions.DontRequireReceiver);
}
}
private void NotifyParticipantsOnConversationCancelled()
{
if (lastSubtitle != null)
{
bool validSpeakerTransform = CharacterInfoHasValidTransform(lastSubtitle.speakerInfo);
bool validListenerTransform = CharacterInfoHasValidTransform(lastSubtitle.listenerInfo);
bool speakerIsListener = validSpeakerTransform && validListenerTransform && (lastSubtitle.speakerInfo.transform == lastSubtitle.listenerInfo.transform);
if (validSpeakerTransform) lastSubtitle.speakerInfo.transform.BroadcastMessage(DialogueSystemMessages.OnConversationCancelled, m_sequencer.listener ?? transform, SendMessageOptions.DontRequireReceiver);
if (validListenerTransform && !speakerIsListener) lastSubtitle.listenerInfo.transform.BroadcastMessage(DialogueSystemMessages.OnConversationCancelled, m_sequencer.speaker ?? transform, SendMessageOptions.DontRequireReceiver);
}
DialogueManager.instance.BroadcastMessage(DialogueSystemMessages.OnConversationCancelled, m_sequencer.speaker ?? transform, SendMessageOptions.DontRequireReceiver);
}
private bool CharacterInfoHasValidTransform(CharacterInfo characterInfo)
{
return (characterInfo != null) && (characterInfo.transform != null);
}
/// <summary>
/// Sets the PC portrait to use for the response menu.
/// </summary>
/// <param name="pcSprite">PC sprite.</param>
/// <param name="pcName">PC name.</param>
public void SetPCPortrait(Sprite pcSprite, string pcName)
{
var ui = DialogueManager.dialogueUI as AbstractDialogueUI;
if (ui == null) return;
ui.SetPCPortrait(pcSprite, pcName);
}
/// <summary>
/// Sets the portrait sprite to use in the UI for an actor.
/// This is used when the SetPortrait() sequencer command changes an actor's image.
/// </summary>
/// <param name="actorName">Actor name.</param>
/// <param name="sprite">Portrait sprite.</param>
public void SetActorPortraitSprite(string actorName, Sprite sprite)
{
var ui = DialogueManager.dialogueUI as AbstractDialogueUI;
if (ui == null) return;
ui.SetActorPortraitSprite(actorName, sprite);
}
}
}