同步
This commit is contained in:
174
Packages/dev.yarnspinner.unity/Runtime/Views/OptionItem.cs
Normal file
174
Packages/dev.yarnspinner.unity/Runtime/Views/OptionItem.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using Yarn.Unity.Attributes;
|
||||
|
||||
#if USE_TMP
|
||||
using TMPro;
|
||||
#else
|
||||
using TextMeshProUGUI = Yarn.Unity.TMPShim;
|
||||
#endif
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Yarn.Unity
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct InternalAppearance
|
||||
{
|
||||
[SerializeField] internal Sprite sprite;
|
||||
[SerializeField] internal Color colour;
|
||||
}
|
||||
|
||||
public class OptionItem : UnityEngine.UI.Selectable, ISubmitHandler, IPointerClickHandler, IPointerEnterHandler
|
||||
{
|
||||
[MustNotBeNull, SerializeField] protected TextMeshProUGUI? text;
|
||||
[SerializeField] protected UnityEngine.UI.Image? selectionImage;
|
||||
|
||||
[Group("Appearance"), SerializeField] protected InternalAppearance normal;
|
||||
[Group("Appearance"), SerializeField] protected InternalAppearance selected;
|
||||
[Group("Appearance"), SerializeField] protected InternalAppearance disabled;
|
||||
|
||||
[Group("Appearance"), SerializeField] protected bool disabledStrikeThrough = true;
|
||||
|
||||
public YarnTaskCompletionSource<DialogueOption?>? OnOptionSelected;
|
||||
public System.Threading.CancellationToken completionToken;
|
||||
|
||||
protected bool hasSubmittedOptionSelection = false;
|
||||
|
||||
protected DialogueOption? _option;
|
||||
public virtual DialogueOption Option
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_option == null)
|
||||
{
|
||||
throw new System.NullReferenceException("Option has not been set on the option item");
|
||||
}
|
||||
return _option;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_option = value;
|
||||
|
||||
hasSubmittedOptionSelection = false;
|
||||
|
||||
// When we're given an Option, use its text and update our
|
||||
// interactibility.
|
||||
string line = value.Line.TextWithoutCharacterName.Text;
|
||||
if (disabledStrikeThrough && !value.IsAvailable)
|
||||
{
|
||||
line = $"<s>{value.Line.TextWithoutCharacterName.Text}</s>";
|
||||
}
|
||||
|
||||
if (text == null)
|
||||
{
|
||||
Debug.LogWarning($"The {nameof(text)} is null, is it not connected in the inspector?", this);
|
||||
return;
|
||||
}
|
||||
|
||||
text.text = line;
|
||||
interactable = value.IsAvailable;
|
||||
|
||||
// we want to apply the default styling to the option item when they are given an option
|
||||
ApplyStyle(normal);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ApplyStyle(InternalAppearance style)
|
||||
{
|
||||
Color newColour = style.colour;
|
||||
Sprite newSprite = style.sprite;
|
||||
if (!Option.IsAvailable)
|
||||
{
|
||||
newColour = disabled.colour;
|
||||
newSprite = disabled.sprite;
|
||||
}
|
||||
|
||||
if (text == null)
|
||||
{
|
||||
Debug.LogWarning($"The {nameof(text)} is null, is it not connected in the inspector?", this);
|
||||
return;
|
||||
}
|
||||
|
||||
text.color = newColour;
|
||||
|
||||
if (selectionImage != null)
|
||||
{
|
||||
selectionImage.color = newColour;
|
||||
if (newSprite != null)
|
||||
{
|
||||
selectionImage.sprite = newSprite;
|
||||
selectionImage.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionImage.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSelect(BaseEventData eventData)
|
||||
{
|
||||
base.OnSelect(eventData);
|
||||
|
||||
ApplyStyle(selected);
|
||||
}
|
||||
|
||||
public override void OnDeselect(BaseEventData eventData)
|
||||
{
|
||||
base.OnDeselect(eventData);
|
||||
|
||||
ApplyStyle(normal);
|
||||
}
|
||||
|
||||
new public bool IsHighlighted
|
||||
{
|
||||
get
|
||||
{
|
||||
return EventSystem.current.currentSelectedGameObject == this.gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
// If we receive a submit or click event, invoke our "we just selected this option" handler.
|
||||
public void OnSubmit(BaseEventData eventData)
|
||||
{
|
||||
InvokeOptionSelected();
|
||||
}
|
||||
|
||||
public void InvokeOptionSelected()
|
||||
{
|
||||
// turns out that Selectable subclasses aren't intrinsically interactive/non-interactive
|
||||
// based on their canvasgroup, you still need to check at the moment of interaction
|
||||
if (!IsInteractable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We only want to invoke this once, because it's an error to
|
||||
// submit an option when the Dialogue Runner isn't expecting it. To
|
||||
// prevent this, we'll only invoke this if the flag hasn't been cleared already.
|
||||
if (hasSubmittedOptionSelection == false && !completionToken.IsCancellationRequested)
|
||||
{
|
||||
hasSubmittedOptionSelection = true;
|
||||
OnOptionSelected?.TrySetResult(this.Option);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
InvokeOptionSelected();
|
||||
}
|
||||
|
||||
// If we mouse-over, we're telling the UI system that this element is
|
||||
// the currently 'selected' (i.e. focused) element.
|
||||
public override void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
base.Select();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user