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:
130
Assets/Editor/Dialogue/DialogueContentDrawer.cs
Normal file
130
Assets/Editor/Dialogue/DialogueContentDrawer.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Dialogue.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom property drawer for DialogueContent that displays either text or image fields based on content type
|
||||
/// </summary>
|
||||
[CustomPropertyDrawer(typeof(DialogueContent))]
|
||||
public class DialogueContentDrawer : PropertyDrawer
|
||||
{
|
||||
// Height constants
|
||||
private const float TypeSelectorHeight = 20f;
|
||||
private const float PropertySpacing = 2f;
|
||||
private const float TextFieldHeight = 40f; // Taller for multi-line text
|
||||
private const float ImageFieldHeight = 18f;
|
||||
private const float PreviewHeight = 64f;
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var contentTypeProperty = property.FindPropertyRelative("_contentType");
|
||||
var height = TypeSelectorHeight + PropertySpacing;
|
||||
|
||||
// Add height based on content type
|
||||
if (contentTypeProperty.enumValueIndex == (int)DialogueContentType.Text)
|
||||
{
|
||||
height += TextFieldHeight;
|
||||
}
|
||||
else // Image
|
||||
{
|
||||
height += ImageFieldHeight;
|
||||
|
||||
// Add preview height if an image is assigned
|
||||
var imageProperty = property.FindPropertyRelative("_image");
|
||||
if (imageProperty.objectReferenceValue != null)
|
||||
{
|
||||
height += PropertySpacing + PreviewHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
// Create a property field and indent it
|
||||
var contentRect = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
|
||||
var indent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
// Get properties
|
||||
var contentTypeProperty = property.FindPropertyRelative("_contentType");
|
||||
var textProperty = property.FindPropertyRelative("_text");
|
||||
var imageProperty = property.FindPropertyRelative("_image");
|
||||
|
||||
// Calculate rects
|
||||
var typeRect = new Rect(contentRect.x, contentRect.y, contentRect.width, TypeSelectorHeight);
|
||||
var contentFieldRect = new Rect(
|
||||
contentRect.x,
|
||||
contentRect.y + TypeSelectorHeight + PropertySpacing,
|
||||
contentRect.width,
|
||||
contentTypeProperty.enumValueIndex == (int)DialogueContentType.Text ? TextFieldHeight : ImageFieldHeight);
|
||||
|
||||
// Draw the content type dropdown
|
||||
EditorGUI.PropertyField(typeRect, contentTypeProperty, GUIContent.none);
|
||||
|
||||
// Draw the appropriate field based on content type
|
||||
if (contentTypeProperty.enumValueIndex == (int)DialogueContentType.Text)
|
||||
{
|
||||
// Create a custom style with word wrap enabled
|
||||
GUIStyle wordWrapStyle = new GUIStyle(EditorStyles.textArea);
|
||||
wordWrapStyle.wordWrap = true;
|
||||
|
||||
// Text field with word wrap for multi-line input
|
||||
textProperty.stringValue = EditorGUI.TextArea(contentFieldRect, textProperty.stringValue, wordWrapStyle);
|
||||
}
|
||||
else // Image
|
||||
{
|
||||
// Draw the image field
|
||||
EditorGUI.PropertyField(contentFieldRect, imageProperty, GUIContent.none);
|
||||
|
||||
// Draw a preview if an image is assigned
|
||||
if (imageProperty.objectReferenceValue != null)
|
||||
{
|
||||
var sprite = imageProperty.objectReferenceValue as Sprite;
|
||||
if (sprite != null)
|
||||
{
|
||||
var previewRect = new Rect(
|
||||
contentRect.x,
|
||||
contentFieldRect.y + contentFieldRect.height + PropertySpacing,
|
||||
contentRect.width,
|
||||
PreviewHeight);
|
||||
|
||||
// Draw the preview with preserved aspect ratio
|
||||
DrawSpritePreview(previewRect, sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel = indent;
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private void DrawSpritePreview(Rect position, Sprite sprite)
|
||||
{
|
||||
if (sprite == null || sprite.texture == null) return;
|
||||
|
||||
// Calculate aspect-preserved rect
|
||||
float aspectRatio = sprite.rect.width / sprite.rect.height;
|
||||
float targetWidth = Mathf.Min(position.width, position.height * aspectRatio);
|
||||
float targetHeight = targetWidth / aspectRatio;
|
||||
|
||||
// Center the preview
|
||||
Rect previewRect = new Rect(
|
||||
position.x + (position.width - targetWidth) * 0.5f,
|
||||
position.y + (position.height - targetHeight) * 0.5f,
|
||||
targetWidth,
|
||||
targetHeight
|
||||
);
|
||||
|
||||
// Draw the sprite preview
|
||||
EditorGUI.DrawPreviewTexture(previewRect, sprite.texture, null, ScaleMode.ScaleToFit);
|
||||
|
||||
// Draw a border around the preview
|
||||
GUI.Box(previewRect, GUIContent.none);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user