169 lines
7.5 KiB
C#
169 lines
7.5 KiB
C#
// Copyright (c) Pixel Crushers. All rights reserved.
|
|
|
|
using PixelCrushers.DialogueSystem.UnityGUI;
|
|
using UnityEngine;
|
|
|
|
namespace PixelCrushers.DialogueSystem
|
|
{
|
|
|
|
/// <summary>
|
|
/// This component modifies the behavior of a Selector or ProximitySelector to
|
|
/// draw the heading and reticle on top of the selection instead an absolute
|
|
/// screen position.
|
|
///
|
|
/// If you're using this with Standard UI, size the Main Graphic appropriately so
|
|
/// this script can determine its size.
|
|
/// </summary>
|
|
[AddComponentMenu("")] // Use wrapper.
|
|
public class SelectorFollowTarget : MonoBehaviour
|
|
{
|
|
|
|
public Vector3 offset = Vector3.zero;
|
|
|
|
private Selector selector = null;
|
|
private ProximitySelector proximitySelector = null;
|
|
private bool previousUseDefaultGUI = false;
|
|
|
|
private Usable lastUsable = null;
|
|
private string heading = string.Empty;
|
|
private string useMessage = string.Empty;
|
|
|
|
private GameObject lastSelectionDrawn = null;
|
|
private float selectionHeight = 0;
|
|
private Vector2 selectionHeadingSize = Vector2.zero;
|
|
private Vector2 selectionUseMessageSize = Vector2.zero;
|
|
|
|
private SelectorUseStandardUIElements selectorUseStandardUIElements = null;
|
|
|
|
void Awake()
|
|
{
|
|
selector = GetComponent<Selector>();
|
|
proximitySelector = GetComponent<ProximitySelector>();
|
|
selectorUseStandardUIElements = GetComponent<SelectorUseStandardUIElements>();
|
|
|
|
}
|
|
|
|
void OnEnable()
|
|
{
|
|
if (selector != null)
|
|
{
|
|
previousUseDefaultGUI = selector.useDefaultGUI;
|
|
selector.useDefaultGUI = false;
|
|
}
|
|
if (proximitySelector != null)
|
|
{
|
|
previousUseDefaultGUI = proximitySelector.useDefaultGUI;
|
|
proximitySelector.useDefaultGUI = false;
|
|
}
|
|
}
|
|
|
|
void OnDisable()
|
|
{
|
|
if (selector != null)
|
|
{
|
|
selector.useDefaultGUI = previousUseDefaultGUI;
|
|
}
|
|
if (proximitySelector != null)
|
|
{
|
|
proximitySelector.useDefaultGUI = previousUseDefaultGUI;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If using Standard UI, positions the UI elements on top of the usable target.
|
|
/// </summary>
|
|
public virtual void Update()
|
|
{
|
|
if (selectorUseStandardUIElements == null || !selectorUseStandardUIElements.enabled || StandardUISelectorElements.instance == null) return;
|
|
Usable usable = null;
|
|
if (selector != null && selector.enabled)
|
|
{
|
|
usable = selector.CurrentUsable;
|
|
}
|
|
else if (proximitySelector != null && proximitySelector.enabled)
|
|
{
|
|
usable = proximitySelector.CurrentUsable;
|
|
}
|
|
if (usable == null) return;
|
|
var mainGraphic = selectorUseStandardUIElements.elements.mainGraphic;
|
|
var selection = usable.gameObject;
|
|
var screenPos = UnityEngine.Camera.main.WorldToScreenPoint(selection.transform.position + (Vector3.up * selectionHeight));
|
|
screenPos += offset;
|
|
screenPos += new Vector3(-mainGraphic.rectTransform.sizeDelta.x / 2, mainGraphic.rectTransform.sizeDelta.y / 2, 0);
|
|
if (screenPos.z < 0) return;
|
|
mainGraphic.rectTransform.position = screenPos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// If using legacy Unity GUI, draws the selection UI on top of the selection target.
|
|
/// </summary>
|
|
public virtual void OnGUI()
|
|
{
|
|
// Use using Standard UI elements, don't draw legacy Unity GUI:
|
|
if (selectorUseStandardUIElements != null && selectorUseStandardUIElements.enabled) return;
|
|
|
|
// Otherwise draw it at usable's position:
|
|
if (selector != null && selector.useDefaultGUI)
|
|
{
|
|
DrawOnSelection(selector.CurrentUsable, selector.CurrentDistance, selector.reticle, selector.GuiStyle, selector.defaultUseMessage, selector.inRangeColor, selector.outOfRangeColor, selector.textStyle, selector.textStyleColor);
|
|
}
|
|
else if (proximitySelector != null && proximitySelector.useDefaultGUI)
|
|
{
|
|
DrawOnSelection(proximitySelector.CurrentUsable, 0, null, proximitySelector.GuiStyle, proximitySelector.defaultUseMessage, proximitySelector.color, proximitySelector.color, proximitySelector.textStyle, proximitySelector.textStyleColor);
|
|
}
|
|
}
|
|
|
|
protected void DrawOnSelection(Usable usable, float distance, Selector.Reticle reticle, GUIStyle guiStyle, string defaultUseMessage,
|
|
Color inRangeColor, Color outOfRangeColor, TextStyle textStyle, Color textStyleColor)
|
|
{
|
|
if (usable == null) return;
|
|
if ((usable != lastUsable) || string.IsNullOrEmpty(heading))
|
|
{
|
|
lastUsable = usable;
|
|
heading = usable.GetName();
|
|
useMessage = string.IsNullOrEmpty(usable.overrideUseMessage) ? defaultUseMessage : usable.overrideUseMessage;
|
|
}
|
|
GameObject selection = usable.gameObject;
|
|
if (selection != lastSelectionDrawn)
|
|
{
|
|
selectionHeight = Tools.GetGameObjectHeight(selection);
|
|
selectionHeadingSize = guiStyle.CalcSize(new GUIContent(heading));
|
|
selectionUseMessageSize = guiStyle.CalcSize(new GUIContent(useMessage));
|
|
}
|
|
|
|
// Set text color based on distance:
|
|
bool inUseRange = (distance <= usable.maxUseDistance);
|
|
guiStyle.normal.textColor = inUseRange ? inRangeColor : outOfRangeColor;
|
|
|
|
// Draw heading:
|
|
Vector3 screenPos = UnityEngine.Camera.main.WorldToScreenPoint(selection.transform.position + (Vector3.up * selectionHeight));
|
|
screenPos += offset;
|
|
screenPos = new Vector3(screenPos.x, screenPos.y + selectionUseMessageSize.y + selectionHeadingSize.y, screenPos.z);
|
|
if (screenPos.z < 0) return;
|
|
Rect rect = new Rect(screenPos.x - (selectionHeadingSize.x / 2), (Screen.height - screenPos.y) - (selectionHeadingSize.y / 2), selectionHeadingSize.x, selectionHeadingSize.y);
|
|
UnityGUITools.DrawText(rect, heading, guiStyle, textStyle, textStyleColor);
|
|
|
|
// Draw use message:
|
|
screenPos = UnityEngine.Camera.main.WorldToScreenPoint(selection.transform.position + (Vector3.up * (selectionHeight)));
|
|
screenPos += offset;
|
|
screenPos = new Vector3(screenPos.x, screenPos.y + selectionUseMessageSize.y, screenPos.z);
|
|
rect = new Rect(screenPos.x - (selectionUseMessageSize.x / 2), (Screen.height - screenPos.y) - (selectionUseMessageSize.y / 2), selectionUseMessageSize.x, selectionUseMessageSize.y);
|
|
UnityGUITools.DrawText(rect, useMessage, guiStyle, textStyle, textStyleColor);
|
|
|
|
// Draw reticle:
|
|
if (reticle != null)
|
|
{
|
|
Texture2D reticleTexture = inUseRange ? reticle.inRange : reticle.outOfRange;
|
|
if (reticleTexture != null)
|
|
{
|
|
screenPos = UnityEngine.Camera.main.WorldToScreenPoint(selection.transform.position + (Vector3.up * 0.5f * selectionHeight));
|
|
rect = new Rect(screenPos.x - (reticle.width / 2), (Screen.height - screenPos.y) - (reticle.height / 2), reticle.width, reticle.height);
|
|
GUI.Label(rect, reticleTexture);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|