Add support for images in dialogue windows (#19)
- Extend editor nodes with custom DialogueContent data type that holds either image or text - Extend the dialogue importer to correctly process the new content into updated RuntimeDialogue content - Update SpeechBubble to be able to display either text or image - Add a custom property drawer for the DialogueContent to allow easy switching in graph authoring Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: #19
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Dialogue
|
||||
{
|
||||
@@ -18,6 +19,7 @@ namespace Dialogue
|
||||
public class SpeechBubble : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TextMeshProUGUI textDisplay;
|
||||
[SerializeField] private Image imageDisplay; // New field for displaying images
|
||||
[SerializeField] private TextDisplayMode displayMode = TextDisplayMode.Typewriter;
|
||||
[SerializeField] private float typewriterSpeed = 0.05f; // Time between characters in seconds
|
||||
[SerializeField] private AudioSource typingSoundSource;
|
||||
@@ -29,11 +31,18 @@ namespace Dialogue
|
||||
private Coroutine typewriterCoroutine;
|
||||
private Coroutine promptUpdateCoroutine;
|
||||
private string currentFullText = string.Empty;
|
||||
private Sprite currentImage = null;
|
||||
private bool isVisible = false;
|
||||
private DialogueContentType currentContentType = DialogueContentType.Text;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
|
||||
// Ensure we have both components
|
||||
if (textDisplay == null)
|
||||
Debug.LogError("SpeechBubble: TextMeshProUGUI component is not assigned!");
|
||||
|
||||
if (imageDisplay == null)
|
||||
Debug.LogError("SpeechBubble: Image component is not assigned!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -92,6 +101,7 @@ namespace Dialogue
|
||||
}
|
||||
|
||||
currentFullText = text;
|
||||
currentContentType = DialogueContentType.Text;
|
||||
|
||||
// Stop any existing typewriter effect
|
||||
if (typewriterCoroutine != null)
|
||||
@@ -100,6 +110,13 @@ namespace Dialogue
|
||||
typewriterCoroutine = null;
|
||||
}
|
||||
|
||||
// Activate text display, deactivate image display
|
||||
textDisplay.gameObject.SetActive(true);
|
||||
if (imageDisplay != null)
|
||||
{
|
||||
imageDisplay.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// Display text based on the selected mode
|
||||
if (displayMode == TextDisplayMode.Instant)
|
||||
{
|
||||
@@ -259,5 +276,117 @@ namespace Dialogue
|
||||
|
||||
typewriterCoroutine = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the image to display in the speech bubble
|
||||
/// </summary>
|
||||
/// <param name="sprite">Sprite to display</param>
|
||||
public void SetImage(Sprite sprite)
|
||||
{
|
||||
if (imageDisplay == null)
|
||||
{
|
||||
Debug.LogError("SpeechBubble: Image component is not assigned!");
|
||||
return;
|
||||
}
|
||||
|
||||
currentImage = sprite;
|
||||
currentContentType = DialogueContentType.Image;
|
||||
|
||||
// Activate image display, set the sprite
|
||||
imageDisplay.gameObject.SetActive(true);
|
||||
imageDisplay.sprite = sprite;
|
||||
|
||||
// Deactivate text display
|
||||
if (textDisplay != null)
|
||||
{
|
||||
textDisplay.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// Make sure the bubble is visible when setting image
|
||||
if (!isVisible)
|
||||
Show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the displayed image
|
||||
/// </summary>
|
||||
public void ClearImage()
|
||||
{
|
||||
SetImage(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the content of the speech bubble (text or image)
|
||||
/// </summary>
|
||||
/// <param name="text">Text content</param>
|
||||
/// <param name="image">Image content</param>
|
||||
public void SetContent(string text, Sprite image)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
currentContentType = DialogueContentType.Text;
|
||||
SetText(text);
|
||||
}
|
||||
else if (image != null)
|
||||
{
|
||||
currentContentType = DialogueContentType.Image;
|
||||
SetImage(image);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current content type of the speech bubble
|
||||
/// </summary>
|
||||
/// <returns>Current content type</returns>
|
||||
public DialogueContentType GetCurrentContentType()
|
||||
{
|
||||
return currentContentType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display dialogue content (text or image)
|
||||
/// </summary>
|
||||
/// <param name="content">The dialogue content to display</param>
|
||||
/// <param name="hasMoreDialogue">Whether there are more dialogue content items available</param>
|
||||
public void DisplayDialogueContent(DialogueContent content, bool hasMoreDialogue)
|
||||
{
|
||||
// Cancel any existing prompt update
|
||||
if (promptUpdateCoroutine != null)
|
||||
{
|
||||
StopCoroutine(promptUpdateCoroutine);
|
||||
promptUpdateCoroutine = null;
|
||||
}
|
||||
|
||||
if (content == null)
|
||||
{
|
||||
UpdatePromptVisibility(hasMoreDialogue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Display the content based on its type
|
||||
currentContentType = content.ContentType;
|
||||
|
||||
if (content.ContentType == DialogueContentType.Text)
|
||||
{
|
||||
// Show text display, hide image display
|
||||
textDisplay.gameObject.SetActive(true);
|
||||
if (imageDisplay != null) imageDisplay.gameObject.SetActive(false);
|
||||
|
||||
// Display the text
|
||||
DisplayDialogueLine(content.Text, hasMoreDialogue);
|
||||
}
|
||||
else // Image content
|
||||
{
|
||||
// Hide text display, show image display
|
||||
textDisplay.gameObject.SetActive(false);
|
||||
if (imageDisplay != null) imageDisplay.gameObject.SetActive(true);
|
||||
|
||||
// Set the image
|
||||
SetImage(content.Image);
|
||||
|
||||
// After a delay, update the prompt visibility
|
||||
promptUpdateCoroutine = StartCoroutine(UpdatePromptAfterDelay(hasMoreDialogue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user