镇海炼化,地块全压里罐区
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.

441 lines
17 KiB

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
namespace HighlightPlus {
public enum TriggerMode {
ColliderEventsOnlyOnThisObject = 0,
RaycastOnThisObjectAndChildren = 1,
Volume = 2
}
public enum RayCastSource {
MousePosition = 0,
CameraDirection = 1
}
[RequireComponent(typeof(HighlightEffect))]
[ExecuteInEditMode]
[HelpURL("https://kronnect.com/guides/highlight-plus-introduction/")]
public class HighlightTrigger : MonoBehaviour {
[Tooltip("Enables highlight when pointer is over this object.")]
public bool highlightOnHover = true;
[Tooltip("Used to trigger automatic highlighting including children objects.")]
#if ENABLE_INPUT_SYSTEM
public TriggerMode triggerMode = TriggerMode.RaycastOnThisObjectAndChildren;
#else
public TriggerMode triggerMode = TriggerMode.ColliderEventsOnlyOnThisObject;
#endif
public Camera raycastCamera;
public RayCastSource raycastSource = RayCastSource.MousePosition;
public LayerMask raycastLayerMask = -1;
[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;
public LayerMask volumeLayerMask;
const int MAX_RAYCAST_HITS = 100;
[Tooltip("If the object will be selected by clicking with mouse or tapping on it.")]
public bool selectOnClick;
[Tooltip("Profile to use when object is selected by clicking on it.")]
public HighlightProfile selectedProfile;
[Tooltip("Profile to use whtn object is selected and highlighted.")]
public HighlightProfile selectedAndHighlightedProfile;
[Tooltip("Automatically deselects any other selected object prior selecting this one")]
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;
[NonSerialized] public Collider[] colliders;
[NonSerialized] public Collider2D[] colliders2D;
public bool hasColliders => (colliders != null && colliders.Length > 0);
public bool hasColliders2D => (colliders2D != null && colliders2D.Length > 0);
UnityEngine.Object currentCollider;
static RaycastHit[] hits;
static RaycastHit2D[] hits2D;
HighlightEffect hb;
public HighlightEffect highlightEffect { get { return hb; } }
public event OnObjectSelectionEvent OnObjectSelected;
public event OnObjectSelectionEvent OnObjectUnSelected;
public event OnObjectHighlightEvent OnObjectHighlightStart;
public event OnObjectHighlightEvent OnObjectHighlightEnd;
TriggerMode currentTriggerMode;
[RuntimeInitializeOnLoadMethod]
static void DomainReloadDisabledSupport() {
HighlightManager.selectedObjects.Clear();
}
void OnEnable() {
Init();
}
private void OnValidate() {
if (currentTriggerMode != triggerMode) {
UpdateTriggers();
}
}
void UpdateTriggers() {
currentTriggerMode = triggerMode;
if (currentTriggerMode == TriggerMode.RaycastOnThisObjectAndChildren) {
colliders = GetComponentsInChildren<Collider>();
colliders2D = GetComponentsInChildren<Collider2D>();
if (hits == null || hits.Length != MAX_RAYCAST_HITS) {
hits = new RaycastHit[MAX_RAYCAST_HITS];
}
if (hits2D == null || hits2D.Length != MAX_RAYCAST_HITS) {
hits2D = new RaycastHit2D[MAX_RAYCAST_HITS];
}
if (Application.isPlaying) {
StopAllCoroutines();
if (gameObject.activeInHierarchy) {
StartCoroutine(DoRayCast());
}
}
}
}
public void Init() {
if (raycastCamera == null) {
raycastCamera = HighlightManager.GetCamera();
}
UpdateTriggers();
if (hb == null) {
hb = GetComponent<HighlightEffect>();
}
InputProxy.Init();
}
void Start() {
UpdateTriggers();
if (triggerMode == TriggerMode.RaycastOnThisObjectAndChildren) {
if (raycastCamera == null) {
raycastCamera = HighlightManager.GetCamera();
if (raycastCamera == null) {
Debug.LogError("Highlight Trigger on " + gameObject.name + ": no camera found!");
}
}
} else {
Collider collider = GetComponent<Collider>();
if (collider == null) {
if (GetComponent<MeshFilter>() != null) {
gameObject.AddComponent<MeshCollider>();
}
}
}
}
IEnumerator DoRayCast() {
yield return null;
WaitForEndOfFrame w = new WaitForEndOfFrame();
while (triggerMode == TriggerMode.RaycastOnThisObjectAndChildren) {
if (raycastCamera == null) {
yield return null;
continue;
}
int hitCount;
bool hit = false;
#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);
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) {
yield return null;
continue;
}
// 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;
for (int c = 0; c < colliders.Length; c++) {
if (colliders[c].gameObject == theGameObject) {
Collider theCollider = colliders[c];
hit = true;
if (selectOnClick && InputProxy.GetMouseButtonDown(0)) {
ToggleSelection();
break;
} else if (theCollider != currentCollider) {
SwitchCollider(theCollider);
k = hitCount;
break;
}
}
}
}
}
// 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()) {
yield return null;
continue;
}
#endif
ray = raycastCamera.ScreenPointToRay(InputProxy.mousePosition);
} else {
ray = new Ray(raycastCamera.transform.position, raycastCamera.transform.forward);
}
bool isMouseButonDown = InputProxy.GetMouseButtonDown(0);
if (hasColliders2D) {
if (maxDistance > 0) {
hitCount = Physics2D.GetRayIntersectionNonAlloc(ray, hits2D, maxDistance, raycastLayerMask);
} else {
hitCount = Physics2D.GetRayIntersectionNonAlloc(ray, hits2D, float.MaxValue, raycastLayerMask);
}
for (int k = 0; k < hitCount; k++) {
if (Vector3.Distance(hits2D[k].point, ray.origin) < minDistance) continue;
Collider2D theCollider = hits2D[k].collider;
int colliders2DCount = colliders2D.Length;
for (int c = 0; c < colliders2DCount; c++) {
if (colliders2D[c] == theCollider) {
hit = true;
if (selectOnClick && isMouseButonDown) {
ToggleSelection();
break;
} else if (theCollider != currentCollider) {
SwitchCollider(theCollider);
k = hitCount;
break;
}
}
}
}
}
if (hasColliders) {
if (maxDistance > 0) {
hitCount = Physics.RaycastNonAlloc(ray, hits, maxDistance, raycastLayerMask);
} else {
hitCount = Physics.RaycastNonAlloc(ray, hits, float.MaxValue, raycastLayerMask);
}
for (int k = 0; k < hitCount; k++) {
if (Vector3.Distance(hits[k].point, ray.origin) < minDistance) continue;
Collider theCollider = hits[k].collider;
int collidersCount = colliders.Length;
for (int c = 0; c < collidersCount; c++) {
if (colliders[c] == theCollider) {
hit = true;
if (selectOnClick && isMouseButonDown) {
ToggleSelection();
break;
} else if (theCollider != currentCollider) {
SwitchCollider(theCollider);
k = hitCount;
break;
}
}
}
}
}
if (!hit && currentCollider != null) {
SwitchCollider(null);
}
if (selectOnClick && isMouseButonDown && !keepSelection && !hit) {
yield return w; // wait for other potential triggers to act
if (HighlightManager.lastTriggerFrame < Time.frameCount) {
HighlightManager.DeselectAll();
}
}
yield return 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 SwitchCollider(UnityEngine.Object newCollider) {
if (!highlightOnHover && !hb.isSelected) return;
currentCollider = newCollider;
if (currentCollider != null) {
Highlight(true);
} else {
Highlight(false);
}
}
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;
}
void OnMouseDown() {
if (isActiveAndEnabled && triggerMode == TriggerMode.ColliderEventsOnlyOnThisObject) {
if (!CanInteract()) return;
if (selectOnClick && InputProxy.GetMouseButtonDown(0)) {
ToggleSelection();
return;
}
Highlight(true);
}
}
void OnMouseEnter() {
if (isActiveAndEnabled && triggerMode == TriggerMode.ColliderEventsOnlyOnThisObject) {
if (!CanInteract()) return;
Highlight(true);
}
}
void OnMouseExit() {
if (isActiveAndEnabled && triggerMode == TriggerMode.ColliderEventsOnlyOnThisObject) {
if (!CanInteract()) return;
Highlight(false);
}
}
void Highlight(bool state) {
if (state) {
if (!hb.highlighted) {
if (OnObjectHighlightStart != null && hb.target != null) {
if (!OnObjectHighlightStart(hb.target.gameObject)) return;
}
}
} else {
if (hb.highlighted) {
if (OnObjectHighlightEnd != null && hb.target != null) {
OnObjectHighlightEnd(hb.target.gameObject);
}
}
}
if (selectOnClick || hb.isSelected) {
if (hb.isSelected) {
if (state && selectedAndHighlightedProfile != null) {
selectedAndHighlightedProfile.Load(hb);
} else if (selectedProfile != null) {
selectedProfile.Load(hb);
} else {
hb.previousSettings.Load(hb);
}
if (hb.highlighted) {
hb.UpdateMaterialProperties();
} else {
hb.SetHighlighted(true);
}
return;
} else if (!highlightOnHover) {
hb.SetHighlighted(false);
return;
}
}
hb.SetHighlighted(state);
}
void ToggleSelection() {
HighlightManager.lastTriggerFrame = Time.frameCount;
bool newState = toggle ? !hb.isSelected : true;
if (newState) {
if (OnObjectSelected != null && !OnObjectSelected(gameObject)) return;
} else {
if (OnObjectUnSelected != null && !OnObjectUnSelected(gameObject)) return;
}
if (singleSelection && newState) {
HighlightManager.DeselectAll();
}
hb.isSelected = newState;
if (newState && !HighlightManager.selectedObjects.Contains(hb)) {
HighlightManager.selectedObjects.Add(hb);
} else if (!newState && HighlightManager.selectedObjects.Contains(hb)) {
HighlightManager.selectedObjects.Remove(hb);
}
if (hb.isSelected) {
if (hb.previousSettings == null) {
hb.previousSettings = ScriptableObject.CreateInstance<HighlightProfile>();
}
hb.previousSettings.Save(hb);
} else {
hb.RestorePreviousHighlightEffectSettings();
}
Highlight(true);
}
public void OnTriggerEnter(Collider other) {
if (triggerMode == TriggerMode.Volume) {
if ((volumeLayerMask & (1 << other.gameObject.layer)) != 0) {
Highlight(true);
}
}
}
public void OnTriggerExit(Collider other) {
if (triggerMode == TriggerMode.Volume) {
if ((volumeLayerMask & (1 << other.gameObject.layer)) != 0) {
Highlight(false);
}
}
}
}
}