镇海炼化,地块全压里罐区
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

450 lines
17 KiB

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
namespace HighlightPlus {
public delegate bool OnObjectSelectionEvent(GameObject obj);
[RequireComponent(typeof(HighlightEffect))]
[DefaultExecutionOrder(100)]
[HelpURL("https://kronnect.com/guides/highlight-plus-introduction/")]
public class HighlightManager : MonoBehaviour {
[Tooltip("Enables highlight when pointer is over this object.")]
[SerializeField]
bool _highlightOnHover = true;
public bool highlightOnHover {
get { return _highlightOnHover; }
set {
if (_highlightOnHover != value) {
_highlightOnHover = value;
if (!_highlightOnHover) {
if (currentEffect != null) {
Highlight(false);
}
}
}
}
}
public LayerMask layerMask = -1;
public Camera raycastCamera;
public RayCastSource raycastSource = RayCastSource.MousePosition;
[Tooltip("Minimum distance for target.")]
public float minDistance;
[Tooltip("Maximum distance for target. 0 = infinity")]
public float maxDistance;
[Tooltip("Blocks interaction if pointer is over an UI element")]
public bool respectUI = true;
[Tooltip("If the object will be selected by clicking with mouse or tapping on it.")]
public bool selectOnClick;
[Tooltip("Optional profile for objects selected by clicking on them")]
public HighlightProfile selectedProfile;
[Tooltip("Profile to use whtn object is selected and highlighted.")]
public HighlightProfile selectedAndHighlightedProfile;
[Tooltip("Automatically deselects other previously selected objects")]
public bool singleSelection;
[Tooltip("Toggles selection on/off when clicking object")]
public bool toggle;
[Tooltip("Keeps current selection when clicking outside of any selectable object")]
public bool keepSelection = true;
HighlightEffect baseEffect, currentEffect;
Transform currentObject;
RaycastHit2D[] hitInfo2D;
public readonly static List<HighlightEffect> selectedObjects = new List<HighlightEffect>();
public event OnObjectSelectionEvent OnObjectSelected;
public event OnObjectSelectionEvent OnObjectUnSelected;
public event OnObjectHighlightEvent OnObjectHighlightStart;
public event OnObjectHighlightEvent OnObjectHighlightEnd;
public static int lastTriggerFrame;
static HighlightManager _instance;
public static HighlightManager instance {
get {
if (_instance == null) {
_instance = Misc.FindObjectOfType<HighlightManager>();
}
return _instance;
}
}
[RuntimeInitializeOnLoadMethod]
static void DomainReloadDisabledSupport() {
selectedObjects.Clear();
lastTriggerFrame = 0;
_instance = null;
}
void OnEnable() {
currentObject = null;
currentEffect = null;
if (baseEffect == null) {
baseEffect = GetComponent<HighlightEffect> ();
if (baseEffect == null) {
baseEffect = gameObject.AddComponent<HighlightEffect> ();
}
}
raycastCamera = GetComponent<Camera> ();
if (raycastCamera == null) {
raycastCamera = GetCamera ();
if (raycastCamera == null) {
Debug.LogError ("Highlight Manager: no camera found!");
}
}
hitInfo2D = new RaycastHit2D[1];
InputProxy.Init();
}
void OnDisable () {
SwitchesObject (null);
internal_DeselectAll();
}
void Update () {
if (raycastCamera == null)
return;
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
if (respectUI) {
EventSystem es = EventSystem.current;
if (es == null) {
es = CreateEventSystem();
}
List<RaycastResult> raycastResults = new List<RaycastResult>();
PointerEventData eventData = new PointerEventData(es);
Vector3 cameraPos = raycastCamera.transform.position;
if (raycastSource == RayCastSource.MousePosition) {
eventData.position = InputProxy.mousePosition;
} else {
eventData.position = new Vector2(raycastCamera.pixelWidth * 0.5f, raycastCamera.pixelHeight * 0.5f);
}
es.RaycastAll(eventData, raycastResults);
int hitCount = raycastResults.Count;
// check UI blocker
bool blocked = false;
for (int k = 0; k < hitCount; k++) {
RaycastResult rr = raycastResults[k];
if (rr.module is UnityEngine.UI.GraphicRaycaster) {
blocked = true;
break;
}
}
if (blocked) return;
// look for our gameobject
for (int k = 0; k < hitCount; k++) {
RaycastResult rr = raycastResults[k];
float distance = Vector3.Distance(rr.worldPosition, cameraPos);
if (distance < minDistance || (maxDistance > 0 && distance > maxDistance)) continue;
GameObject theGameObject = rr.gameObject;
if ((layerMask & (1 << rr.gameObject.layer)) == 0) continue;
// is this object state controller by Highlight Trigger?
HighlightTrigger trigger = theGameObject.GetComponent<HighlightTrigger>();
if (trigger != null) return;
// Toggles selection
Transform t = theGameObject.transform;
if (InputProxy.GetMouseButtonDown(0)) {
if (selectOnClick) {
ToggleSelection(t, !toggle);
}
} else {
// Check if the object has a Highlight Effect
if (t != currentObject) {
SwitchesObject(t);
}
}
return;
}
}
// if not blocked by UI and no hit found, fallback to raycast (required if no PhysicsRaycaster is present on the camera)
#endif
Ray ray;
if (raycastSource == RayCastSource.MousePosition) {
#if !ENABLE_INPUT_SYSTEM
if (!CanInteract()) {
return;
}
#endif
ray = raycastCamera.ScreenPointToRay(InputProxy.mousePosition);
} else {
ray = new Ray(raycastCamera.transform.position, raycastCamera.transform.forward);
}
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo, maxDistance > 0 ? maxDistance : raycastCamera.farClipPlane, layerMask) && Vector3.Distance(hitInfo.point, ray.origin) >= minDistance) {
Transform t = hitInfo.collider.transform;
// is this object state controller by Highlight Trigger?
HighlightTrigger trigger = t.GetComponent<HighlightTrigger>();
if (trigger != null) return;
// Toggles selection
if (InputProxy.GetMouseButtonDown(0)) {
if (selectOnClick) {
ToggleSelection(t, !toggle);
}
} else {
// Check if the object has a Highlight Effect
if (t != currentObject) {
SwitchesObject(t);
}
}
return;
} else // check sprites
if (Physics2D.GetRayIntersectionNonAlloc(ray, hitInfo2D, maxDistance > 0 ? maxDistance : raycastCamera.farClipPlane, layerMask) > 0 && Vector3.Distance(hitInfo2D[0].point, ray.origin) >= minDistance) {
Transform t = hitInfo2D[0].collider.transform;
// is this object state controller by Highlight Trigger?
HighlightTrigger trigger = t.GetComponent<HighlightTrigger>();
if (trigger != null) return;
// Toggles selection
if (InputProxy.GetMouseButtonDown(0)) {
if (selectOnClick) {
ToggleSelection(t, !toggle);
}
} else {
// Check if the object has a Highlight Effect
if (t != currentObject) {
SwitchesObject(t);
}
}
return;
}
// no hit
if (selectOnClick && !keepSelection && InputProxy.GetMouseButtonDown(0) && lastTriggerFrame < Time.frameCount) {
internal_DeselectAll();
}
SwitchesObject (null);
}
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
EventSystem CreateEventSystem() {
GameObject eo = new GameObject("Event System created by Highlight Plus", typeof(EventSystem), typeof(UnityEngine.InputSystem.UI.InputSystemUIInputModule));
return eo.GetComponent<EventSystem>();
}
#endif
void SwitchesObject (Transform newObject) {
if (currentEffect != null) {
if (highlightOnHover) {
Highlight(false);
}
currentEffect = null;
}
currentObject = newObject;
if (newObject == null) return;
HighlightTrigger ht = newObject.GetComponent<HighlightTrigger>();
if (ht != null && ht.enabled)
return;
HighlightEffect otherEffect = newObject.GetComponent<HighlightEffect> ();
if (otherEffect == null) {
// Check if there's a parent highlight effect that includes this object
HighlightEffect parentEffect = newObject.GetComponentInParent<HighlightEffect>();
if (parentEffect != null && parentEffect.Includes(newObject)) {
currentEffect = parentEffect;
if (highlightOnHover) {
Highlight(true);
}
return;
}
}
currentEffect = otherEffect != null ? otherEffect : baseEffect;
baseEffect.enabled = currentEffect == baseEffect;
currentEffect.SetTarget(currentObject);
if (highlightOnHover) {
Highlight(true);
}
}
#if !ENABLE_INPUT_SYSTEM
bool CanInteract() {
if (!respectUI) return true;
EventSystem es = EventSystem.current;
if (es == null) return true;
if (Application.isMobilePlatform && InputProxy.touchCount > 0 && es.IsPointerOverGameObject(InputProxy.GetFingerIdFromTouch(0))) {
return false;
} else if (es.IsPointerOverGameObject(-1))
return false;
return true;
}
#endif
void ToggleSelection(Transform t, bool forceSelection) {
// We need a highlight effect on each selected object
HighlightEffect hb = t.GetComponent<HighlightEffect>();
if (hb == null) {
HighlightEffect parentEffect = t.GetComponentInParent<HighlightEffect>();
if (parentEffect != null && parentEffect.Includes(t)) {
hb = parentEffect;
if (hb.previousSettings == null) {
hb.previousSettings = ScriptableObject.CreateInstance<HighlightProfile>();
}
hb.previousSettings.Save(hb);
} else {
hb = t.gameObject.AddComponent<HighlightEffect>();
hb.previousSettings = ScriptableObject.CreateInstance<HighlightProfile>();
// copy default highlight effect settings from this manager into this highlight plus component
hb.previousSettings.Save(baseEffect);
hb.previousSettings.Load(hb);
}
}
bool currentState = hb.isSelected;
bool newState = forceSelection ? true : !currentState;
if (newState == currentState) return;
if (newState) {
if (OnObjectSelected != null && !OnObjectSelected(t.gameObject)) return;
} else {
if (OnObjectUnSelected != null && !OnObjectUnSelected(t.gameObject)) return;
}
if (singleSelection) {
internal_DeselectAll();
}
currentEffect = hb;
currentEffect.isSelected = newState;
baseEffect.enabled = false;
if (currentEffect.isSelected) {
if (currentEffect.previousSettings == null) {
currentEffect.previousSettings = ScriptableObject.CreateInstance<HighlightProfile>();
}
hb.previousSettings.Save(hb);
if (!selectedObjects.Contains(currentEffect)) {
selectedObjects.Add(currentEffect);
}
} else {
if (currentEffect.previousSettings != null) {
currentEffect.previousSettings.Load(hb);
}
if (selectedObjects.Contains(currentEffect)) {
selectedObjects.Remove(currentEffect);
}
}
Highlight(newState);
}
void Highlight(bool state) {
if (state) {
if (!currentEffect.highlighted) {
if (OnObjectHighlightStart != null && currentEffect.target != null) {
if (!OnObjectHighlightStart(currentEffect.target.gameObject)) return;
}
}
} else {
if (currentEffect.highlighted) {
if (OnObjectHighlightEnd != null && currentEffect.target != null) {
OnObjectHighlightEnd(currentEffect.target.gameObject);
}
}
}
if (selectOnClick || currentEffect.isSelected) {
if (currentEffect.isSelected) {
if (state && selectedAndHighlightedProfile != null) {
selectedAndHighlightedProfile.Load(currentEffect);
} else if (selectedProfile != null) {
selectedProfile.Load(currentEffect);
} else {
currentEffect.previousSettings.Load(currentEffect);
}
if (currentEffect.highlighted && currentEffect.fading != HighlightEffect.FadingState.FadingOut) {
currentEffect.UpdateMaterialProperties();
} else {
currentEffect.SetHighlighted(true);
}
return;
} else if (!highlightOnHover) {
currentEffect.SetHighlighted(false);
return;
}
}
currentEffect.SetHighlighted(state);
}
public static Camera GetCamera() {
Camera raycastCamera = Camera.main;
if (raycastCamera == null) {
raycastCamera = Misc.FindObjectOfType<Camera>();
}
return raycastCamera;
}
void internal_DeselectAll() {
foreach (HighlightEffect hb in selectedObjects) {
if (hb != null && hb.gameObject != null) {
if (OnObjectUnSelected != null) {
if (!OnObjectUnSelected(hb.gameObject)) continue;
}
hb.RestorePreviousHighlightEffectSettings();
hb.isSelected = false;
hb.SetHighlighted(false);
}
}
selectedObjects.Clear();
}
public static void DeselectAll() {
foreach (HighlightEffect hb in selectedObjects) {
if (hb != null && hb.gameObject != null) {
hb.isSelected = false;
if (hb.highlighted && _instance != null) {
_instance.Highlight(false);
} else {
hb.SetHighlighted(false);
}
}
}
selectedObjects.Clear();
}
/// <summary>
/// Manually causes highlight manager to select an object
/// </summary>
public void SelectObject(Transform t) {
ToggleSelection(t, true);
}
/// <summary>
/// Manually causes highlight manager to toggle selection on an object
/// </summary>
public void ToggleObject(Transform t) {
ToggleSelection(t, false);
}
/// <summary>
/// Manually causes highlight manager to unselect an object
/// </summary>
public void UnselectObject(Transform t) {
if (t == null) return;
HighlightEffect hb = t.GetComponent<HighlightEffect>();
if (hb == null) return;
if (hb.isSelected) {
ToggleSelection(t, false);
}
}
}
}