using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
public abstract class DocumentedOption<T> : FuzzyOption<T>
{
public XmlDocumentationTags documentation { get; protected set; }
public bool zoom { get; protected set; }
public bool showType { get; protected set; }
public override bool hasFooter => documentation != null;
private bool showIcon => zoom && icon != null;
public override float GetFooterHeight(float width)
{
if (showIcon)
{
width -= Styles.zoomSize + Styles.zoomSpacing;
}
var height = 0f;
width -= 2;
if (documentation.summary != null)
{
height += GetSummaryHeight(width);
}
foreach (var parameterDocumentation in documentation.parameters)
{
Type parameterType = null;
if (documentation.parameterTypes.ContainsKey(parameterDocumentation.Key))
{
parameterType = documentation.parameterTypes[parameterDocumentation.Key];
}
height += GetParameterHeight(parameterDocumentation, parameterType, width);
}
if (documentation.returns != null)
{
height += GetReturnsHeight(width);
}
if (documentation.remarks != null)
{
height += GetRemarksHeight(width);
}
if (showIcon)
{
return Mathf.Max(Styles.zoomSize + 2 * Styles.zoomSpacing, height);
}
return height;
}
public override void OnFooterGUI(Rect position)
{
if (showIcon)
{
var zoomPosition = new Rect
(
position.x + Styles.zoomSpacing,
position.y + Styles.zoomSpacing,
Styles.zoomSize,
Styles.zoomSize
);
position.x += Styles.zoomSize + Styles.zoomSpacing;
position.width -= Styles.zoomSize + Styles.zoomSpacing;
GUI.DrawTexture(zoomPosition, icon?[IconSize.Medium]);
}
var y = position.y;
if (documentation.summary != null)
{
var summaryPosition = new Rect
(
position.x,
y,
position.width,
GetSummaryHeight(position.width)
);
OnSummaryGUI(summaryPosition);
y = summaryPosition.yMax;
}
if (documentation.parameters.Count > 0)
{
var parameterPosition = new Rect
(
position.x,
y,
position.width,
0
);
foreach (var parameterDocumentation in documentation.parameters)
{
Type parameterType = null;
if (documentation.parameterTypes.ContainsKey(parameterDocumentation.Key))
{
parameterType = documentation.parameterTypes[parameterDocumentation.Key];
}
parameterPosition.height = GetParameterHeight(parameterDocumentation, parameterType, position.width);
OnParameterGUI(parameterPosition, parameterDocumentation, parameterType);
parameterPosition.y += parameterPosition.height;
y = parameterPosition.y;
}
}
if (documentation.returns != null)
{
var returnsPosition = new Rect
(
position.x,
y,
position.width,
GetReturnsHeight(position.width)
);
OnReturnsGUI(returnsPosition);
y = returnsPosition.yMax;
}
if (documentation.remarks != null)
{
var remarksPosition = new Rect
(
position.x,
y,
position.width,
GetRemarksHeight(position.width)
);
OnRemarksGUI(remarksPosition);
y = remarksPosition.yMax;
}
}
private float GetSummaryHeight(float width)
{
return Styles.summary.CalcHeight(new GUIContent(documentation.summary), width);
}
private void OnSummaryGUI(Rect summaryPosition)
{
EditorGUI.LabelField(summaryPosition, documentation.summary, Styles.summary);
}
private float GetParameterReturnsHeight(GUIContent label, float width)
{
width -= IconSize.Small + Styles.iconSpacing;
return Styles.parameterSummary.CalcHeight(label, width);
}
private void OnParameterReturnsGUI(Type type, GUIContent label, Rect position)
{
var x = position.x + Styles.parameterSummary.padding.left;
var width = position.width;
if (type != null)
{
var icon = type.Icon()?[IconSize.Small];
if (icon != null)
{
var iconPosition = new Rect
(
x,
position.y - 1,
IconSize.Small,
IconSize.Small
);
x += iconPosition.width + Styles.iconSpacing;
width -= iconPosition.width + Styles.iconSpacing;
GUI.DrawTexture(iconPosition, icon);
}
}
var labelPosition = new Rect
(
x,
position.y,
width,
position.height
);
GUI.Label(labelPosition, label, Styles.parameterSummary);
}
private float GetParameterHeight(KeyValuePair<string, string> documentation, Type type, float width)
{
return GetParameterReturnsHeight(GetParameterLabel(documentation, type), width);
}
private GUIContent GetParameterLabel(KeyValuePair<string, string> documentation, Type type)
{
var label = BoltCore.Configuration.humanNaming ? StringUtility.Prettify(documentation.Key) : documentation.Key;
if (showType && type != null)
{
return new GUIContent($"<b>{label}: </b>{documentation.Value} ({type.CSharpName(false)})");
}
else
{
return new GUIContent($"<b>{label}: </b>{documentation.Value}");
}
}
private GUIContent GetReturnsLabel()
{
if (showType && documentation.returnType != null)
{
return new GUIContent($"<b>Returns: </b>{documentation.returns} ({documentation.returnType})");
}
else
{
return new GUIContent($"<b>Returns: </b>{documentation.returns}");
}
}
private void OnParameterGUI(Rect parameterPosition, KeyValuePair<string, string> documentation, Type type)
{
OnParameterReturnsGUI(type, GetParameterLabel(documentation, type), parameterPosition);
}
private float GetReturnsHeight(float width)
{
return GetParameterReturnsHeight(GetReturnsLabel(), width);
}
private void OnReturnsGUI(Rect returnsPosition)
{
OnParameterReturnsGUI(documentation.returnType, GetReturnsLabel(), returnsPosition);
}
private float GetRemarksHeight(float width)
{
return Styles.remarks.CalcHeight(new GUIContent(documentation.remarks), width);
}
private void OnRemarksGUI(Rect remarksPosition)
{
GUI.Label(remarksPosition, documentation.remarks, Styles.remarks);
}
public static class Styles
{
static Styles()
{
summary = new GUIStyle(EditorStyles.label);
summary.padding = new RectOffset(7, 7, 7, 7);
summary.wordWrap = true;
summary.richText = true;
parameterSummary = new GUIStyle(EditorStyles.label);
parameterSummary.padding = new RectOffset(7, 7, 0, 7);
parameterSummary.wordWrap = true;
parameterSummary.richText = true;
remarks = new GUIStyle(EditorStyles.label);
remarks.padding = new RectOffset(7, 7, 7, 7);
remarks.wordWrap = true;
remarks.richText = true;
remarks.fontSize = 10;
remarks.normal.textColor = ColorPalette.unityForegroundDim;
//remarks.fontStyle = FontStyle.Italic;
}
public static readonly GUIStyle summary;
public static readonly GUIStyle parameterSummary;
public static readonly GUIStyle remarks;
public static readonly float iconSpacing = 0;
public static readonly float zoomSize = 32;
public static readonly float zoomSpacing = 8;
}
}
}