using System;
using UnityEngine;
using UnityEngine.EventSystems;
using Framework.Selection;
using Framework.Services;
namespace Framework.Actors.Shooter {
/// Highlights objects in the camera's center
public class LookHighlighter : ScriptComponent {
/// Tracker into which the selected objects are entered
public SelectionTracker SelectionTracker;
/// Maximum distance at which objects can be highlighted
public float MaxDistance = 10.0f;
/// Layers that will prevent highlighting from happening
public LayerMask BlockingLayerMask = 0;
/// Layers that can contain highlightable objects
///
/// This should be any solid in-game object. Usually you'd exclude glass, water,
/// user interface elements and such.
///
public LayerMask HighlightableLayerMask = Physics.DefaultRaycastLayers;
/// Called once per visual frame
protected void Update() {
// If the user is looking at a UI element, do not highlight things behind it!
EventSystem currentEventSystem = EventSystem.current;
if (currentEventSystem != null) {
var lookInputModule = currentEventSystem.currentInputModule as LookInputModule;
if (lookInputModule != null) {
if (lookInputModule.ActivePointee != null) {
setHighlightedObject(null);
return;
}
}
}
// Good, user seems to be looking at the scene, so lets see if he's looking
// at something that is selectable or highlightable
Selectable target = RaycastSelectable();
if(target != null) {
if(target.CanBeHighlighted) {
setHighlightedObject(target);
} else {
setHighlightedObject(null);
}
} else {
setHighlightedObject(null);
}
}
/// Called when the component is removed from a game object
protected void OnDestroy() {
if(this.currentlyHighlighted != null) {
setHighlightedObject(null);
}
}
/// Called when the highlighter component gets disabled
protected virtual void OnDisable() {
if(this.currentlyHighlighted != null) {
setHighlightedObject(null);
}
}
/// Does a raycast to determine the currently highlighted game object
/// The highlightable game object in the center of the view
protected Selectable RaycastSelectable() {
Selectable selectable;
// Determine if the highlighter is pointing at a game object with a collider
RaycastHit hitInfo;
bool hitSomething = Physics.Raycast(
transform.position, transform.forward, out hitInfo,
this.MaxDistance, this.BlockingLayerMask | this.HighlightableLayerMask
);
if (hitSomething) {
// Check if the game object is on a layer that we should highlight
{
int gameObjectLayerMask = (1 << hitInfo.transform.gameObject.layer);
hitSomething &= ((gameObjectLayerMask & this.HighlightableLayerMask) != 0);
}
if (hitSomething) {
selectable = hitInfo.collider.GetComponentInParent();
} else {
selectable = null;
}
#if UNITY_EDITOR
Debug.DrawLine(
transform.position, hitInfo.point, (selectable != null) ? Color.green : Color.red
);
#endif //UNITY_EDITOR
} else {
selectable = null;
}
return selectable;
}
/// Updates the highlighted game object
/// IHighlightable component of the highlighted object
private void setHighlightedObject(Selectable highlighted) {
//Debug.Log("Now highlighting " + ((highlighted == null) ? "" : ((Component)highlighted).name));
if(!ReferenceEquals(highlighted, this.currentlyHighlighted)) {
if(this.currentlyHighlighted != null) {
this.SelectionTracker.HighlightedObjects.Remove(this.currentlyHighlighted);
}
this.currentlyHighlighted = highlighted;
if(highlighted != null) {
this.SelectionTracker.HighlightedObjects.Add(highlighted);
}
}
}
/// IHighlightable component of the currently highlighted game object
private Selectable currentlyHighlighted;
}
} // namespace Framework.Actors.Shooter