|
|
|
|
|
using System;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
namespace Pegasus
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Spawn a bunch of special objects in a scene, and the flythrough manager will find and visit them
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
///
|
|
|
|
|
|
public class PegasusManager : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The target game object we will be driving - or main scene camera if nothing selected
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public GameObject m_target;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Default flythrough type
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public PegasusConstants.FlythroughType m_flythroughType = PegasusConstants.FlythroughType.Looped;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// What to do when we fet to the end - only relevant on Once through flythroughs
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public PegasusConstants.FlythroughEndAction m_flythroughEndAction = PegasusConstants.FlythroughEndAction.StopFlythrough;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Select the targetted frame rate for the fly through
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public PegasusConstants.TargetFrameRate m_targetFramerateType = PegasusConstants.TargetFrameRate.LeaveAlone;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The algorithm the system uses to check minimum heights against
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public PegasusConstants.HeightCheckType m_heightCheckType = PegasusConstants.HeightCheckType.Terrain;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Autostart the manager at runtime
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool m_autoStartAtRuntime = true;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The POI list
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public List<PegasusPoi> m_poiList = new List<PegasusPoi>();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The minimum height above the terrain
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public float m_minHeightAboveTerrain = PegasusConstants.FlybyOffsetDefaultHeight;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Display debug messages
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool m_displayDebug = false; //Set to true if we want debug messages
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Always show gizmos
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool m_alwaysShowGizmos = true;
|
|
|
|
|
|
|
|
|
|
|
|
public PegasusConstants.FlythroughState m_currentState = PegasusConstants.FlythroughState.Stopped;
|
|
|
|
|
|
public int m_currentSegmentIdx;
|
|
|
|
|
|
public PegasusPoi m_currentSegment;
|
|
|
|
|
|
public float m_currentSegmentDistanceTravelled = 0f;
|
|
|
|
|
|
public float m_totalDistanceTravelled = 0f;
|
|
|
|
|
|
public float m_totalDistanceTravelledPct = 0f;
|
|
|
|
|
|
public float m_totalDistance = 0f;
|
|
|
|
|
|
public TimeSpan m_totalDuration = TimeSpan.Zero;
|
|
|
|
|
|
public float m_currentVelocity = 0f;
|
|
|
|
|
|
public Vector3 m_currentPosition = Vector3.zero;
|
|
|
|
|
|
public Quaternion m_currentRotation = Quaternion.identity;
|
|
|
|
|
|
|
|
|
|
|
|
public bool m_canUpdateNow = false; //Used to trigger when the camera and targetLocation can be updated
|
|
|
|
|
|
public DateTime m_lastUpdateTime = DateTime.MinValue;
|
|
|
|
|
|
public float m_frameUpdateTime = 1f / 60f;
|
|
|
|
|
|
public float m_frameUpdateDistance = 0f;
|
|
|
|
|
|
public float m_rotationDamping = 0.75f;
|
|
|
|
|
|
public float m_positionDamping = 0.3f;
|
|
|
|
|
|
|
|
|
|
|
|
public PegasusManager m_nextPegasus = null; //Used when single shot is assigned and end action is play next pegasus
|
|
|
|
|
|
|
|
|
|
|
|
//Editor related
|
|
|
|
|
|
public bool m_alwaysShowPath = false;
|
|
|
|
|
|
public bool m_showScrubber = false;
|
|
|
|
|
|
public bool m_showPOIHelpers = false;
|
|
|
|
|
|
public float m_poiGizmoSize = 0.75f;
|
|
|
|
|
|
public bool m_showAdvanced = false;
|
|
|
|
|
|
public float m_collisionHeightOffset = 1000f; //How far above a location to check for collisions
|
|
|
|
|
|
public float m_managerSpeed = PegasusConstants.SpeedMedium;
|
|
|
|
|
|
|
|
|
|
|
|
//Defaults
|
|
|
|
|
|
public PegasusDefaults m_defaults = null;
|
|
|
|
|
|
|
|
|
|
|
|
//Autobank settings
|
|
|
|
|
|
public float m_autoRollMaxSpeed = PegasusConstants.SpeedFast;
|
|
|
|
|
|
public float m_autoRollMaxAngle = 15f;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Scene playback and initialisation
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void Start()
|
|
|
|
|
|
{
|
|
|
|
|
|
//Make sure we are stopped
|
|
|
|
|
|
m_currentState = PegasusConstants.FlythroughState.Stopped;
|
|
|
|
|
|
|
|
|
|
|
|
//Grab the main camera if nothing defined
|
|
|
|
|
|
if (m_target == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Camera.main == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("Can not start Pegasus - no target has been assigned.");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_displayDebug == true)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("Assigning main camera to target : " + Camera.main.name);
|
|
|
|
|
|
}
|
|
|
|
|
|
m_target = Camera.main.gameObject;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Grab the defaults if none have been defined
|
|
|
|
|
|
if (m_defaults == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetDefaults();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Set the applications target framerate
|
|
|
|
|
|
ChangeFramerate(m_targetFramerateType);
|
|
|
|
|
|
|
|
|
|
|
|
//Initialise the flythrough - does all the expensive calcs in one hit
|
|
|
|
|
|
InitialiseFlythrough();
|
|
|
|
|
|
|
|
|
|
|
|
//Auto start at runtime if necessary
|
|
|
|
|
|
if (m_autoStartAtRuntime == true)
|
|
|
|
|
|
{
|
|
|
|
|
|
StartFlythrough();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get or create the pegasus defaults - allows people to override keys
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public void SetDefaults()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_defaults = null;
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
|
string[] guids = AssetDatabase.FindAssets("PegasusDefaults");
|
|
|
|
|
|
for (int idx = 0; idx < guids.Length; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[idx]);
|
|
|
|
|
|
if (path.Contains("PegasusDefaults.asset"))
|
|
|
|
|
|
{
|
|
|
|
|
|
m_defaults = AssetDatabase.LoadAssetAtPath<PegasusDefaults>(path);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (m_defaults == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_defaults = ScriptableObject.CreateInstance<PegasusDefaults>();
|
|
|
|
|
|
AssetDatabase.CreateAsset(m_defaults, "Assets/PegasusDefaults.asset");
|
|
|
|
|
|
AssetDatabase.SaveAssets();
|
|
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
|
|
m_defaults = ScriptableObject.CreateInstance<PegasusDefaults>();
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region Setup and control routines
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Initialise a flythrough - setup all the segments
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void InitialiseFlythrough()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_displayDebug)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("Initialising flythrough...");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_currentState = PegasusConstants.FlythroughState.Initialising;
|
|
|
|
|
|
|
|
|
|
|
|
//Rebuild the POI list based on order of poi children
|
|
|
|
|
|
m_poiList.Clear();
|
|
|
|
|
|
int idx;
|
|
|
|
|
|
for (idx = 0; idx < transform.childCount; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList.Add(transform.GetChild(idx).GetComponent<PegasusPoi>());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Iterate thru the list and set first, last, prev next on the poi
|
|
|
|
|
|
PegasusPoi poi = null;
|
|
|
|
|
|
for (idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi = m_poiList[idx];
|
|
|
|
|
|
|
|
|
|
|
|
//Update the index
|
|
|
|
|
|
poi.m_segmentIndex = idx;
|
|
|
|
|
|
|
|
|
|
|
|
//Set first / last flags
|
|
|
|
|
|
if (idx == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_isFirstPOI = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_isFirstPOI = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (idx == m_poiList.Count - 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_isLastPOI = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_isLastPOI = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Set prev / next pointers
|
|
|
|
|
|
if (m_flythroughType == PegasusConstants.FlythroughType.SingleShot)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Previous
|
|
|
|
|
|
if (poi.m_isFirstPOI)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_poiList.Count > 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_prevPoi = m_poiList[1];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_prevPoi = poi;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_prevPoi = m_poiList[idx - 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
//Next
|
|
|
|
|
|
if (poi.m_isLastPOI)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_poiList.Count > 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_nextPoi = m_poiList[idx - 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_nextPoi = poi;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_nextPoi = m_poiList[idx + 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
//Previous
|
|
|
|
|
|
if (idx == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_prevPoi = m_poiList[m_poiList.Count - 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_prevPoi = m_poiList[idx - 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
//Next
|
|
|
|
|
|
if (idx == m_poiList.Count - 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_nextPoi = m_poiList[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_nextPoi = m_poiList[idx + 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
poi.m_alwaysShowGizmos = m_alwaysShowGizmos;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Get the poi to initialise themselves - run twice as some settings depend on the next in the sequence which may not yet be initialised
|
|
|
|
|
|
for (idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList[idx].Initialise(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Next time thru grab the total distance and duration
|
|
|
|
|
|
m_totalDuration = TimeSpan.Zero;
|
|
|
|
|
|
m_totalDistanceTravelledPct = 0f;
|
|
|
|
|
|
m_totalDistanceTravelled = 0f;
|
|
|
|
|
|
m_totalDistance = 0f;
|
|
|
|
|
|
for (idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList[idx].Initialise(true);
|
|
|
|
|
|
m_poiList[idx].m_segmentStartTime = new TimeSpan(m_totalDuration.Ticks);
|
|
|
|
|
|
m_totalDistance += m_poiList[idx].m_segmentDistance;
|
|
|
|
|
|
m_totalDuration += m_poiList[idx].m_segmentDuration;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Set up the initial state
|
|
|
|
|
|
m_currentSegmentIdx = 0;
|
|
|
|
|
|
if (m_poiList.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_currentSegment = m_poiList[m_currentSegmentIdx];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_currentSegment = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_currentSegmentDistanceTravelled = 0f;
|
|
|
|
|
|
|
|
|
|
|
|
//Current time
|
|
|
|
|
|
m_lastUpdateTime = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
|
|
//Signal that we can update
|
|
|
|
|
|
m_canUpdateNow = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Restart the flythrough
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void RestartFlythrough()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_displayDebug)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("Restarting flythrough...");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_currentState = PegasusConstants.FlythroughState.Initialising;
|
|
|
|
|
|
m_totalDistanceTravelledPct = 0f;
|
|
|
|
|
|
m_totalDistanceTravelled = 0f;
|
|
|
|
|
|
|
|
|
|
|
|
//Set up the initial state
|
|
|
|
|
|
m_currentSegmentIdx = 0;
|
|
|
|
|
|
if (m_poiList.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_currentSegment = m_poiList[m_currentSegmentIdx];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_currentSegment = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_currentSegmentDistanceTravelled = 0f;
|
|
|
|
|
|
|
|
|
|
|
|
//Current time
|
|
|
|
|
|
m_lastUpdateTime = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
|
|
//Signal that we can update
|
|
|
|
|
|
m_canUpdateNow = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Update the meta data influenced by the connectivity of the flythrough - distance and duration.
|
|
|
|
|
|
/// Assumes that the segments have previously been initialised so that distance and durations are correct.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void UpdateFlythroughMetaData()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_totalDuration = TimeSpan.Zero;
|
|
|
|
|
|
m_totalDistance = 0f;
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList[idx].m_segmentStartTime = new TimeSpan(m_totalDuration.Ticks);
|
|
|
|
|
|
m_totalDuration += m_poiList[idx].m_segmentDuration;
|
|
|
|
|
|
m_totalDistance += m_poiList[idx].m_segmentDistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Update the dependencies that will change when changes are made to an individual segment as
|
|
|
|
|
|
/// they flow back 2, and forward 1 segments due to the underlying spline system.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="segment"></param>
|
|
|
|
|
|
public void UpdateSegmentWithDependencies(PegasusPoi segment)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (segment == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("Attempting to update null segment!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (m_flythroughType == PegasusConstants.FlythroughType.SingleShot)
|
|
|
|
|
|
{
|
|
|
|
|
|
int idx = segment.m_segmentIndex;
|
|
|
|
|
|
SafeInitialise(idx - 2, false, true);
|
|
|
|
|
|
SafeInitialise(idx - 1, false, true);
|
|
|
|
|
|
SafeInitialise(idx, false, true);
|
|
|
|
|
|
SafeInitialise(idx + 1, false, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
int idx = segment.m_segmentIndex;
|
|
|
|
|
|
SafeInitialise(idx - 2, true, true);
|
|
|
|
|
|
SafeInitialise(idx - 1, true, true);
|
|
|
|
|
|
SafeInitialise(idx, true, true);
|
|
|
|
|
|
SafeInitialise(idx + 1, true, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Then do a full flythrough metadata update
|
|
|
|
|
|
UpdateFlythroughMetaData();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Run a safe initialise - bury out of range and handle wrapping
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="idx"></param>
|
|
|
|
|
|
/// <param name="wrap"></param>
|
|
|
|
|
|
/// <param name="updateSegments"></param>
|
|
|
|
|
|
private void SafeInitialise(int idx, bool wrap, bool updateSegments)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!wrap)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (idx >= 0 && idx < m_poiList.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList[idx].Initialise(updateSegments);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
idx = idx % m_poiList.Count;
|
|
|
|
|
|
if (idx < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
idx += m_poiList.Count;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_poiList[idx].Initialise(updateSegments);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Public API routines
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Start a flythrough from scratch
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void StartFlythrough(bool fullInitialise = false)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Enable the application to be able to run in the background
|
|
|
|
|
|
Application.runInBackground = true;
|
|
|
|
|
|
|
|
|
|
|
|
//Initialise it
|
|
|
|
|
|
if (fullInitialise == true)
|
|
|
|
|
|
{
|
|
|
|
|
|
InitialiseFlythrough();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
RestartFlythrough();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Now start the flythough
|
|
|
|
|
|
if (m_displayDebug)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("Starting flythrough..");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Move target to its initial position and location
|
|
|
|
|
|
if (m_target != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_currentSegment.CalculateProgress(0, out m_currentVelocity, out m_currentPosition, out m_currentRotation);
|
|
|
|
|
|
m_target.transform.rotation = m_currentRotation;
|
|
|
|
|
|
m_target.transform.position = m_currentPosition;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("Cannot start Pegasus - no target has been assigned!");
|
|
|
|
|
|
m_currentState = PegasusConstants.FlythroughState.Stopped;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Kick off triggers
|
|
|
|
|
|
m_currentSegment.OnStartTriggers();
|
|
|
|
|
|
|
|
|
|
|
|
//Mark as started
|
|
|
|
|
|
m_currentState = PegasusConstants.FlythroughState.Started;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Resume a flythrough
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void ResumeFlythrough()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_displayDebug)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("Resuming flythrough");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_currentState != PegasusConstants.FlythroughState.Paused)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("Can not resume flythrough - it was not paused.");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Mark as started
|
|
|
|
|
|
m_currentState = PegasusConstants.FlythroughState.Started;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Pause a flythrough - can be resumed
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void PauseFlythrough()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_displayDebug)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("Pausing flythrough");
|
|
|
|
|
|
}
|
|
|
|
|
|
m_currentState = PegasusConstants.FlythroughState.Paused;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Stop a flythrough - cant be resumed - can be restarted
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void StopFlythrough()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_displayDebug)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("Stopping flythrough");
|
|
|
|
|
|
}
|
|
|
|
|
|
m_currentState = PegasusConstants.FlythroughState.Stopped;
|
|
|
|
|
|
m_canUpdateNow = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Change the frame rate and apply it immediately
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="newRate">New framerate</param>
|
|
|
|
|
|
public void ChangeFramerate(PegasusConstants.TargetFrameRate newRate)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_targetFramerateType = newRate;
|
|
|
|
|
|
|
|
|
|
|
|
if (m_targetFramerateType == PegasusConstants.TargetFrameRate.LeaveAlone)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Apply the target framerate only if we are playing
|
|
|
|
|
|
if (Application.isPlaying)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (m_targetFramerateType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case PegasusConstants.TargetFrameRate.NineFps:
|
|
|
|
|
|
Application.targetFrameRate = 9;
|
|
|
|
|
|
#if HELIOS3D
|
|
|
|
|
|
Time.captureFramerate = 9;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
m_frameUpdateTime = 1f / 9f;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case PegasusConstants.TargetFrameRate.FifteenFps:
|
|
|
|
|
|
Application.targetFrameRate = 15;
|
|
|
|
|
|
#if HELIOS3D
|
|
|
|
|
|
Time.captureFramerate = 15;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
m_frameUpdateTime = 1f / 15f;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case PegasusConstants.TargetFrameRate.TwentyFourFps:
|
|
|
|
|
|
Application.targetFrameRate = 24;
|
|
|
|
|
|
#if HELIOS3D
|
|
|
|
|
|
Time.captureFramerate = 24;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
m_frameUpdateTime = 1f / 24f;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case PegasusConstants.TargetFrameRate.TwentyFiveFps:
|
|
|
|
|
|
Application.targetFrameRate = 25;
|
|
|
|
|
|
#if HELIOS3D
|
|
|
|
|
|
Time.captureFramerate = 25;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
m_frameUpdateTime = 1f / 25f;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case PegasusConstants.TargetFrameRate.ThirtyFps:
|
|
|
|
|
|
Application.targetFrameRate = 30;
|
|
|
|
|
|
#if HELIOS3D
|
|
|
|
|
|
Time.captureFramerate = 30;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
m_frameUpdateTime = 1f / 30f;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case PegasusConstants.TargetFrameRate.SixtyFps:
|
|
|
|
|
|
Application.targetFrameRate = 60;
|
|
|
|
|
|
#if HELIOS3D
|
|
|
|
|
|
Time.captureFramerate = 60;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
m_frameUpdateTime = 1f / 60f;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case PegasusConstants.TargetFrameRate.NinetyFps:
|
|
|
|
|
|
Application.targetFrameRate = 90;
|
|
|
|
|
|
#if HELIOS3D
|
|
|
|
|
|
Time.captureFramerate = 90;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
m_frameUpdateTime = 1f / 90f;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case PegasusConstants.TargetFrameRate.MaxFps:
|
|
|
|
|
|
Application.targetFrameRate = -1;
|
|
|
|
|
|
#if HELIOS3D
|
|
|
|
|
|
Time.captureFramerate = 60;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
m_frameUpdateTime = 0f;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Set the speed of the fly through for every node
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="speed"></param>
|
|
|
|
|
|
public void SetSpeed(float speed)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList[idx].m_startSpeed = speed;
|
|
|
|
|
|
m_poiList[idx].m_startSpeedType = PegasusConstants.SpeedType.Custom;
|
|
|
|
|
|
}
|
|
|
|
|
|
InitialiseFlythrough();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Update state of auto roll on all POI
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="autoRoll"></param>
|
|
|
|
|
|
public void SetAutoRoll(bool autoRoll)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList[idx].m_autoRollOn = autoRoll;
|
|
|
|
|
|
if (!autoRoll)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList[idx].transform.localEulerAngles = Vector3.zero;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
InitialiseFlythrough();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Editor specific routines - use at own peril
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Select the POI - influences gizmo rendering
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="poi"></param>
|
|
|
|
|
|
public void SelectPoi(PegasusPoi poi)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_poiList[idx].m_isSelected = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (poi != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_isSelected = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Do a validated poi movement
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="poi">Point of interest to move</param>
|
|
|
|
|
|
/// <param name="movement">Amount of movement</param>
|
|
|
|
|
|
public void MovePoi(PegasusPoi poi, Vector3 movement)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.transform.position = GetValidatedPoiPosition(poi.transform.position + movement, poi.m_heightCheckType);
|
|
|
|
|
|
poi.GetRelativeOffsets(poi.transform.position, poi.m_lookatLocation, out poi.m_lookAtDistance, out poi.m_lookAtHeight, out poi.m_lookAtAngle);
|
|
|
|
|
|
UpdateSegmentWithDependencies(poi);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Do a validated poi lookat movement - including setting it into target mode
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="movement"></param>
|
|
|
|
|
|
public void MovePoiLookat(PegasusPoi poi, Vector3 movement)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_lookatType = PegasusConstants.LookatType.Target;
|
|
|
|
|
|
Vector3 lookAtLocation = GetValidatedLookatPosition(poi.m_lookatLocation + movement, poi.m_heightCheckType);
|
|
|
|
|
|
if (lookAtLocation != poi.m_lookatLocation)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi.m_lookatLocation = lookAtLocation;
|
|
|
|
|
|
poi.m_lookatType = PegasusConstants.LookatType.Target;
|
|
|
|
|
|
poi.GetRelativeOffsets(poi.transform.position, poi.m_lookatLocation, out poi.m_lookAtDistance, out poi.m_lookAtHeight, out poi.m_lookAtAngle);
|
|
|
|
|
|
UpdateSegmentWithDependencies(poi);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Move target to current location
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void MoveTargetNow()
|
|
|
|
|
|
{
|
|
|
|
|
|
MoveTargetTo(m_totalDistanceTravelled / m_totalDistance);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Move the target if one has been set to the point in the sequence selected - designed to be an editor only method
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="percent">Value betrween 0..1 which represents completion</param>
|
|
|
|
|
|
public void MoveTargetTo(float percent)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_target == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("Can not move target as none has been set");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PegasusPoi poi;
|
|
|
|
|
|
float targetPoint = percent * m_totalDistance;
|
|
|
|
|
|
float segmentStart = 0f;
|
|
|
|
|
|
float segmentEnd = 0f;
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi = m_poiList[idx];
|
|
|
|
|
|
segmentEnd = segmentStart + poi.m_segmentDistance;
|
|
|
|
|
|
if (targetPoint >= segmentStart && targetPoint <= segmentEnd)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_totalDistanceTravelled = targetPoint;
|
|
|
|
|
|
m_totalDistanceTravelledPct = m_totalDistanceTravelled / m_totalDistance;
|
|
|
|
|
|
m_currentPosition = poi.CalculatePositionLinear((targetPoint - segmentStart) / poi.m_segmentDistance);
|
|
|
|
|
|
m_currentRotation = poi.CalculateRotation((targetPoint - segmentStart) / poi.m_segmentDistance);
|
|
|
|
|
|
m_currentVelocity = poi.CalculateVelocity((targetPoint - segmentStart) / poi.m_segmentDistance);
|
|
|
|
|
|
m_target.transform.position = m_currentPosition;
|
|
|
|
|
|
m_target.transform.rotation = m_currentRotation;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
segmentStart += poi.m_segmentDistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Calculate target data based on distance through the flythrough
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="distance">Distance through flythrough</param>
|
|
|
|
|
|
/// <param name="position">Calculated position</param>
|
|
|
|
|
|
/// <param name="rotation">Calculated rotation</param>
|
|
|
|
|
|
/// <param name="velocity">Calculated velocity</param>
|
|
|
|
|
|
public void CalculateTargetAtDistance(float distance, out Vector3 position, out Quaternion rotation, out float velocity)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_target == null || m_poiList.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
position = Vector3.zero;
|
|
|
|
|
|
rotation = Quaternion.identity;
|
|
|
|
|
|
velocity = 0f;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PegasusPoi poi;
|
|
|
|
|
|
float targetPoint = distance;
|
|
|
|
|
|
|
|
|
|
|
|
if (m_flythroughType == PegasusConstants.FlythroughType.SingleShot)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Correct for invalid distances
|
|
|
|
|
|
targetPoint = Mathf.Clamp(distance, 0f, m_totalDistance);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
//Correct for looping
|
|
|
|
|
|
targetPoint = targetPoint % m_totalDistance;
|
|
|
|
|
|
if (targetPoint < 0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
targetPoint += m_totalDistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
float segmentStart = 0f;
|
|
|
|
|
|
float segmentEnd = 0f;
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi = m_poiList[idx];
|
|
|
|
|
|
segmentEnd = segmentStart + poi.m_segmentDistance;
|
|
|
|
|
|
if (targetPoint >= segmentStart && targetPoint <= segmentEnd)
|
|
|
|
|
|
{
|
|
|
|
|
|
position = poi.CalculatePositionLinear((targetPoint - segmentStart) / poi.m_segmentDistance);
|
|
|
|
|
|
rotation = poi.CalculateRotation((targetPoint - segmentStart) / poi.m_segmentDistance);
|
|
|
|
|
|
velocity = poi.CalculateVelocity((targetPoint - segmentStart) / poi.m_segmentDistance);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
segmentStart += poi.m_segmentDistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
position = m_poiList[m_poiList.Count - 1].transform.position;
|
|
|
|
|
|
rotation = m_poiList[m_poiList.Count - 1].transform.localRotation;
|
|
|
|
|
|
velocity = m_poiList[m_poiList.Count - 1].m_startSpeed;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Calculate target data based at the percentage movement through the flythrough
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="percent"></param>
|
|
|
|
|
|
/// <param name="position"></param>
|
|
|
|
|
|
/// <param name="rotation"></param>
|
|
|
|
|
|
/// <param name="velocity"></param>
|
|
|
|
|
|
public void CalculateTargetAtPercent(float percent, out Vector3 position, out Quaternion rotation, out float velocity)
|
|
|
|
|
|
{
|
|
|
|
|
|
float targetPoint = Mathf.Clamp(percent, 0f, 100f) * m_totalDistance;
|
|
|
|
|
|
CalculateTargetAtDistance(targetPoint, out position, out rotation, out velocity);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Move target to the given poi
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="targetPoi">Poi to move target to</param>
|
|
|
|
|
|
public void MoveTargetToPoi(PegasusPoi targetPoi)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_target == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("Can not move target as none has been set");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_totalDistanceTravelled = 0f;
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_poiList[idx].GetInstanceID() == targetPoi.GetInstanceID())
|
|
|
|
|
|
{
|
|
|
|
|
|
m_totalDistanceTravelledPct = m_totalDistanceTravelled / m_totalDistance;
|
|
|
|
|
|
m_currentPosition = targetPoi.CalculatePositionLinear(0f);
|
|
|
|
|
|
m_currentRotation = targetPoi.CalculateRotation(0f);
|
|
|
|
|
|
m_currentVelocity = targetPoi.CalculateVelocity(0f);
|
|
|
|
|
|
m_target.transform.position = m_currentPosition;
|
|
|
|
|
|
m_target.transform.rotation = m_currentRotation;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_totalDistanceTravelled += m_poiList[idx].m_segmentDistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Step the target 1m backward - only called by editor / /scrubber functions
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void StepTargetBackward(float distMeters)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_totalDistanceTravelled -= distMeters;
|
|
|
|
|
|
if (m_totalDistanceTravelled < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_totalDistanceTravelled = 0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
MoveTargetTo(m_totalDistanceTravelled / m_totalDistance);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Step the target 1m forward - only called by editor / /scrubber functions
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void StepTargetForward(float distMeters)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_totalDistanceTravelled += distMeters;
|
|
|
|
|
|
if (m_totalDistanceTravelled > m_totalDistance)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_totalDistanceTravelled = m_totalDistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
MoveTargetTo(m_totalDistanceTravelled / m_totalDistance);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Create debug objects for visualisation
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void CreateDebugObjects()
|
|
|
|
|
|
{
|
|
|
|
|
|
PegasusPoi poi;
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi = m_poiList[idx];
|
|
|
|
|
|
if (poi.transform.childCount == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject newCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
|
|
|
|
DestroyImmediate(newCube.GetComponent<BoxCollider>());
|
|
|
|
|
|
newCube.transform.position = poi.transform.position;
|
|
|
|
|
|
newCube.transform.localScale = new Vector3(0.05f, 10f, 0.05f);
|
|
|
|
|
|
newCube.transform.parent = poi.transform;
|
|
|
|
|
|
newCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
|
|
|
|
DestroyImmediate(newCube.GetComponent<BoxCollider>());
|
|
|
|
|
|
newCube.transform.position = poi.transform.position;
|
|
|
|
|
|
newCube.transform.localScale = new Vector3(0.05f, 0.05f, 5f);
|
|
|
|
|
|
newCube.transform.parent = poi.transform;
|
|
|
|
|
|
newCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
|
|
|
|
DestroyImmediate(newCube.GetComponent<BoxCollider>());
|
|
|
|
|
|
newCube.transform.position = poi.transform.position;
|
|
|
|
|
|
newCube.transform.localScale = new Vector3(5f, 0.05f, 0.05f);
|
|
|
|
|
|
newCube.transform.parent = poi.transform;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Delete visualisation debug objects
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void DeleteDebugObjects()
|
|
|
|
|
|
{
|
|
|
|
|
|
PegasusPoi poi;
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi = m_poiList[idx];
|
|
|
|
|
|
while (poi.transform.childCount > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
DestroyImmediate(poi.transform.GetChild(0).gameObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Return a validated / corrected poi position
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="source">Source location being checked</param>
|
|
|
|
|
|
/// <param name="heightCheckOverride">A height check overide</param>
|
|
|
|
|
|
/// <returns>Updated position taking into account minimum height</returns>
|
|
|
|
|
|
public Vector3 GetValidatedPoiPosition(Vector3 source, PegasusConstants.PoiHeightCheckType heightCheckOverride = PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Update if there is an override
|
|
|
|
|
|
PegasusConstants.HeightCheckType heightCheckType = m_heightCheckType;
|
|
|
|
|
|
if (heightCheckOverride != PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (heightCheckOverride == PegasusConstants.PoiHeightCheckType.Collision)
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.Collision;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (heightCheckOverride == PegasusConstants.PoiHeightCheckType.Terrain)
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.Terrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.None;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Peform the height check
|
|
|
|
|
|
if (heightCheckType == PegasusConstants.HeightCheckType.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (heightCheckType == PegasusConstants.HeightCheckType.Collision)
|
|
|
|
|
|
{
|
|
|
|
|
|
RaycastHit hit;
|
|
|
|
|
|
if (Physics.Raycast(new Vector3(source.x, source.y + m_collisionHeightOffset, source.z), Vector3.down, out hit, 10000f))
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((hit.point.y + m_minHeightAboveTerrain) > source.y)
|
|
|
|
|
|
{
|
|
|
|
|
|
source.y = hit.point.y + m_minHeightAboveTerrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Terrain t = GetTerrain(source);
|
|
|
|
|
|
if (t != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
float height = t.SampleHeight(source);
|
|
|
|
|
|
if ((height + m_minHeightAboveTerrain) > source.y)
|
|
|
|
|
|
{
|
|
|
|
|
|
source.y = height + m_minHeightAboveTerrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Return a validated / poi position at the minimum height
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="source">Source location being checked</param>
|
|
|
|
|
|
/// <param name="heightCheckOverride">A height check overide</param>
|
|
|
|
|
|
/// <returns>Updated position taking into account minimum height</returns>
|
|
|
|
|
|
public Vector3 GetLowestPoiPosition(Vector3 source, PegasusConstants.PoiHeightCheckType heightCheckOverride = PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Update if there is an override
|
|
|
|
|
|
PegasusConstants.HeightCheckType heightCheckType = m_heightCheckType;
|
|
|
|
|
|
if (heightCheckOverride != PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (heightCheckOverride == PegasusConstants.PoiHeightCheckType.Collision)
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.Collision;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (heightCheckOverride == PegasusConstants.PoiHeightCheckType.Terrain)
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.Terrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.None;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Peform the height check
|
|
|
|
|
|
if (heightCheckType == PegasusConstants.HeightCheckType.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (heightCheckType == PegasusConstants.HeightCheckType.Collision)
|
|
|
|
|
|
{
|
|
|
|
|
|
RaycastHit hit;
|
|
|
|
|
|
if (Physics.Raycast(new Vector3(source.x, source.y + m_collisionHeightOffset, source.z), Vector3.down, out hit, 10000f))
|
|
|
|
|
|
{
|
|
|
|
|
|
source.y = hit.point.y + m_minHeightAboveTerrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Terrain t = GetTerrain(source);
|
|
|
|
|
|
if (t != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
source.y = t.SampleHeight(source) + m_minHeightAboveTerrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Return a validated / corrected lookat position
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="source">Source location</param>
|
|
|
|
|
|
/// <returns>Updated position taking into account minimum height</returns>
|
|
|
|
|
|
public Vector3 GetValidatedLookatPosition(Vector3 source, PegasusConstants.PoiHeightCheckType heightCheckOverride = PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Update if there is an override
|
|
|
|
|
|
PegasusConstants.HeightCheckType heightCheckType = m_heightCheckType;
|
|
|
|
|
|
if (heightCheckOverride != PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (heightCheckOverride == PegasusConstants.PoiHeightCheckType.Collision)
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.Collision;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (heightCheckOverride == PegasusConstants.PoiHeightCheckType.Terrain)
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.Terrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.None;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Perform the height check
|
|
|
|
|
|
if (heightCheckType == PegasusConstants.HeightCheckType.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (heightCheckType == PegasusConstants.HeightCheckType.Collision)
|
|
|
|
|
|
{
|
|
|
|
|
|
RaycastHit hit;
|
|
|
|
|
|
if (Physics.Raycast(new Vector3(source.x, source.y + m_collisionHeightOffset, source.z), Vector3.down, out hit, 2000f))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (hit.point.y > source.y)
|
|
|
|
|
|
{
|
|
|
|
|
|
source.y = hit.point.y;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Terrain t = GetTerrain(source);
|
|
|
|
|
|
if (t != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
float height = t.SampleHeight(source);
|
|
|
|
|
|
if (height > source.y)
|
|
|
|
|
|
{
|
|
|
|
|
|
source.y = height;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Return a validated lookat position at the minimum height
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="source">Source location being checked</param>
|
|
|
|
|
|
/// <param name="heightCheckOverride">A height check overide</param>
|
|
|
|
|
|
/// <returns>Updated position taking into account minimum height</returns>
|
|
|
|
|
|
public Vector3 GetLowestLookatPosition(Vector3 source, PegasusConstants.PoiHeightCheckType heightCheckOverride = PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Update if there is an override
|
|
|
|
|
|
PegasusConstants.HeightCheckType heightCheckType = m_heightCheckType;
|
|
|
|
|
|
if (heightCheckOverride != PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (heightCheckOverride == PegasusConstants.PoiHeightCheckType.Collision)
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.Collision;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (heightCheckOverride == PegasusConstants.PoiHeightCheckType.Terrain)
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.Terrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
heightCheckType = PegasusConstants.HeightCheckType.None;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Peform the height check
|
|
|
|
|
|
if (heightCheckType == PegasusConstants.HeightCheckType.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (heightCheckType == PegasusConstants.HeightCheckType.Collision)
|
|
|
|
|
|
{
|
|
|
|
|
|
RaycastHit hit;
|
|
|
|
|
|
if (Physics.Raycast(new Vector3(source.x, source.y + m_collisionHeightOffset, source.z), Vector3.down, out hit, 2000f))
|
|
|
|
|
|
{
|
|
|
|
|
|
source.y = hit.point.y;
|
|
|
|
|
|
}
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Terrain t = GetTerrain(source);
|
|
|
|
|
|
if (t != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
source.y = t.SampleHeight(source);
|
|
|
|
|
|
}
|
|
|
|
|
|
return source;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Return a validated / corrected lookat position
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="source">Source location</param>
|
|
|
|
|
|
/// <returns>Updated position taking into account minimum height</returns>
|
|
|
|
|
|
public float GetValidatedLookatHeightRelativeToMinimum(Vector3 source, PegasusConstants.PoiHeightCheckType heightCheckOverride = PegasusConstants.PoiHeightCheckType.ManagerSettings)
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector3 minPosition = GetLowestLookatPosition(source, heightCheckOverride);
|
|
|
|
|
|
return source.y - minPosition.y;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get the terrain in this location, otherwise return null
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="location">Location to check in world units</param>
|
|
|
|
|
|
/// <returns>Terrain here or null</returns>
|
|
|
|
|
|
public Terrain GetTerrain(Vector3 location)
|
|
|
|
|
|
{
|
|
|
|
|
|
Terrain terrain;
|
|
|
|
|
|
Vector3 terrainMin = new Vector3();
|
|
|
|
|
|
Vector3 terrainMax = new Vector3();
|
|
|
|
|
|
|
|
|
|
|
|
//First check active terrain - most likely already selected
|
|
|
|
|
|
terrain = Terrain.activeTerrain;
|
|
|
|
|
|
if (terrain != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
terrainMin = terrain.GetPosition();
|
|
|
|
|
|
terrainMax = terrainMin + terrain.terrainData.size;
|
|
|
|
|
|
if (location.x >= terrainMin.x && location.x <= terrainMax.x)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (location.z >= terrainMin.z && location.z <= terrainMax.z)
|
|
|
|
|
|
{
|
|
|
|
|
|
return terrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Then check rest of terrains
|
|
|
|
|
|
for (int idx = 0; idx < Terrain.activeTerrains.Length; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
terrain = Terrain.activeTerrains[idx];
|
|
|
|
|
|
terrainMin = terrain.GetPosition();
|
|
|
|
|
|
terrainMax = terrainMin + terrain.terrainData.size;
|
|
|
|
|
|
if (location.x >= terrainMin.x && location.x <= terrainMax.x)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (location.z >= terrainMin.z && location.z <= terrainMax.z)
|
|
|
|
|
|
{
|
|
|
|
|
|
return terrain;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Update processing
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Both drive (if not coroutine based) and apply the flythrough into the scene
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void LateUpdate()
|
|
|
|
|
|
{
|
|
|
|
|
|
//Keep updating current time if paused to stop big resume time delta issue **** THis may no longer be valit
|
|
|
|
|
|
if (m_currentState == PegasusConstants.FlythroughState.Paused)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_lastUpdateTime = DateTime.Now;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Exit if we are not in running mode
|
|
|
|
|
|
if (m_currentState != PegasusConstants.FlythroughState.Started)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Calculate the update
|
|
|
|
|
|
CalculateFlythroughUpdates();
|
|
|
|
|
|
|
|
|
|
|
|
//Apply the update into the scene
|
|
|
|
|
|
if (m_canUpdateNow && m_target != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
//Apply the rotation smoothly
|
|
|
|
|
|
if (m_rotationDamping > 0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_target.transform.rotation = Quaternion.Slerp(m_target.transform.rotation, m_currentRotation, Time.deltaTime * (1f / m_rotationDamping));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_target.transform.rotation = m_currentRotation;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Apply the position update smoothly
|
|
|
|
|
|
if (m_positionDamping > 0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_target.transform.position = Vector3.Slerp(m_target.transform.position, m_currentPosition, Time.deltaTime * (1f / m_positionDamping));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_target.transform.position = m_currentPosition;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_canUpdateNow = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Perform the calculations required for the next update - will trigger an update in the LateUpdate method to apply it to the scene
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void CalculateFlythroughUpdates()
|
|
|
|
|
|
{
|
|
|
|
|
|
//Make sure we are on a segment
|
|
|
|
|
|
if (m_currentSegment != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Calculate progress and update velocity, position and rotation variables (will be physically applied in late update)
|
|
|
|
|
|
m_currentSegment.CalculateProgress(m_currentSegmentDistanceTravelled / m_currentSegment.m_segmentDistance, out m_currentVelocity, out m_currentPosition, out m_currentRotation);
|
|
|
|
|
|
|
|
|
|
|
|
//Update the rotation to allow for the rotation offset
|
|
|
|
|
|
//m_currentRotation = Quaternion.FromToRotation(Vector3.up, m_targetRotationCorrection) * m_currentRotation;
|
|
|
|
|
|
|
|
|
|
|
|
//Update distance travelled for next iteration through
|
|
|
|
|
|
if (m_targetFramerateType == PegasusConstants.TargetFrameRate.MaxFps || m_targetFramerateType == PegasusConstants.TargetFrameRate.LeaveAlone)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_frameUpdateTime = (float)((DateTime.Now - m_lastUpdateTime).Milliseconds) / 1000f;
|
|
|
|
|
|
m_lastUpdateTime = DateTime.Now;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_frameUpdateDistance = m_frameUpdateTime * m_currentVelocity;
|
|
|
|
|
|
m_currentSegmentDistanceTravelled += m_frameUpdateDistance;
|
|
|
|
|
|
m_totalDistanceTravelled += m_frameUpdateDistance;
|
|
|
|
|
|
m_totalDistanceTravelledPct = m_totalDistanceTravelled / m_totalDistance;
|
|
|
|
|
|
|
|
|
|
|
|
//Handle segment changes
|
|
|
|
|
|
if (m_currentSegmentDistanceTravelled >= m_currentSegment.m_segmentDistance)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Call any end state triggers
|
|
|
|
|
|
m_currentSegment.OnEndTriggers();
|
|
|
|
|
|
|
|
|
|
|
|
//Increment to next segment
|
|
|
|
|
|
m_currentSegmentIdx++;
|
|
|
|
|
|
if (m_currentSegmentIdx >= m_poiList.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Detect if we are at end game
|
|
|
|
|
|
if (m_flythroughType == PegasusConstants.FlythroughType.Looped)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_currentSegmentIdx = 0;
|
|
|
|
|
|
m_currentSegmentDistanceTravelled -= m_currentSegment.m_segmentDistance;
|
|
|
|
|
|
m_totalDistanceTravelled = m_currentSegmentDistanceTravelled;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_currentSegmentIdx--;
|
|
|
|
|
|
m_currentSegmentDistanceTravelled = m_currentSegment.m_segmentDistance;
|
|
|
|
|
|
m_totalDistanceTravelled = m_totalDistance;
|
|
|
|
|
|
m_totalDistanceTravelledPct = 1f;
|
|
|
|
|
|
|
|
|
|
|
|
if (m_flythroughEndAction == PegasusConstants.FlythroughEndAction.StopFlythrough)
|
|
|
|
|
|
{
|
|
|
|
|
|
StopFlythrough();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_flythroughEndAction == PegasusConstants.FlythroughEndAction.QuitApplication)
|
|
|
|
|
|
{
|
|
|
|
|
|
StopFlythrough();
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
|
UnityEditor.EditorApplication.isPlaying = false;
|
|
|
|
|
|
#else
|
|
|
|
|
|
Application.Quit();
|
|
|
|
|
|
#endif
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
StopFlythrough();
|
|
|
|
|
|
if (m_nextPegasus != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_nextPegasus.StartFlythrough();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("Next Pegasus has not been configured. Can not start.");
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_currentSegmentDistanceTravelled -= m_currentSegment.m_segmentDistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_totalDistanceTravelledPct = m_totalDistanceTravelled / m_totalDistance;
|
|
|
|
|
|
m_currentSegment = m_poiList[m_currentSegmentIdx];
|
|
|
|
|
|
m_currentSegment.OnStartTriggers();
|
|
|
|
|
|
if (m_currentState != PegasusConstants.FlythroughState.Started)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_canUpdateNow = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Override lookat for path travellers
|
|
|
|
|
|
// if (m_currentSegment.m_lookatType == PegasusConstants.LookatType.Path && m_currentSegment.m_nextPoi.m_lookatType == PegasusConstants.LookatType.Path)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// //This is inherently jittery - needs more investigation
|
|
|
|
|
|
// Vector3 forward = m_currentPosition - m_target.transform.position;
|
|
|
|
|
|
//
|
|
|
|
|
|
// //And then apply if non zero
|
|
|
|
|
|
// if (forward != Vector3.zero)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// m_currentRotation = Quaternion.LookRotation(forward);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
//Call the update for the current segment
|
|
|
|
|
|
m_currentSegment.OnUpdateTriggers(m_currentSegmentDistanceTravelled / m_currentSegment.m_segmentDistance);
|
|
|
|
|
|
|
|
|
|
|
|
//Flag that we can do an update now
|
|
|
|
|
|
m_canUpdateNow = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region POI routines
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Add a new POI at the targetLocation given
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="targetLocation">Location to add the POI at</param>
|
|
|
|
|
|
public void AddPOI(Vector3 targetLocation, Vector3 lookatLocation)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject newPoiGo = new GameObject("POI " + m_poiList.Count);
|
|
|
|
|
|
newPoiGo.transform.parent = this.transform;
|
|
|
|
|
|
newPoiGo.transform.position = targetLocation;
|
|
|
|
|
|
|
|
|
|
|
|
PegasusPoi newPoi = newPoiGo.AddComponent<PegasusPoi>();
|
|
|
|
|
|
newPoi.m_manager = this;
|
|
|
|
|
|
newPoi.m_lookatLocation = lookatLocation;
|
|
|
|
|
|
|
|
|
|
|
|
if (targetLocation != lookatLocation)
|
|
|
|
|
|
{
|
|
|
|
|
|
newPoi.m_lookatType = PegasusConstants.LookatType.Target;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
newPoi.m_startSpeedType = m_defaults.m_flyThroughSpeed;
|
|
|
|
|
|
|
|
|
|
|
|
m_poiList.Add(newPoi);
|
|
|
|
|
|
|
|
|
|
|
|
InitialiseFlythrough();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Add a new POI halfway between this POI and the next POI, taking traversal into account
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="currentPoi"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public PegasusPoi AddPoiAfter(PegasusPoi currentPoi)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject newPoiGo = new GameObject("POI " + m_poiList.Count);
|
|
|
|
|
|
|
|
|
|
|
|
PegasusPoi newPoi = newPoiGo.AddComponent<PegasusPoi>();
|
|
|
|
|
|
newPoi.m_manager = this;
|
|
|
|
|
|
newPoi.m_startSpeedType = m_defaults.m_flyThroughSpeed;
|
|
|
|
|
|
|
|
|
|
|
|
m_poiList.Insert(m_poiList.IndexOf(currentPoi) + 1, newPoi);
|
|
|
|
|
|
Vector3 newPoiLocation = GetValidatedPoiPosition(currentPoi.CalculatePositionLinear(0.5f), newPoi.m_heightCheckType);
|
|
|
|
|
|
newPoiGo.transform.position = newPoiLocation;
|
|
|
|
|
|
newPoiGo.transform.parent = this.transform;
|
|
|
|
|
|
newPoiGo.transform.SetSiblingIndex(currentPoi.m_segmentIndex + 1);
|
|
|
|
|
|
|
|
|
|
|
|
InitialiseFlythrough();
|
|
|
|
|
|
|
|
|
|
|
|
return newPoi;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Add a new POI halfway between this POI and the previous POI, taking traversal into account
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="currentPoi"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public PegasusPoi AddPoiBefore(PegasusPoi currentPoi)
|
|
|
|
|
|
{
|
|
|
|
|
|
return AddPoiAfter(GetPrevPOI(currentPoi));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get the first poi
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>First POI or null if no data</returns>
|
|
|
|
|
|
public PegasusPoi GetFirstPOI()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_poiList.Count < 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
return m_poiList[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get the poi from POI index
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="poiIndex">POI to get</param>
|
|
|
|
|
|
/// <returns>POI or null if no data or invalid index</returns>
|
|
|
|
|
|
public PegasusPoi GetPOI(int poiIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_poiList.Count == 0 || poiIndex < 0 || poiIndex >= m_poiList.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
return m_poiList[poiIndex];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get the prev poi from POI passed in
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="currentPoi">POI to start from</param>
|
|
|
|
|
|
/// <param name="wrap">Whether or not to wrap around</param>
|
|
|
|
|
|
/// <returns>Prev POI or null if no data, invalid params or wrap boundary hit</returns>
|
|
|
|
|
|
public PegasusPoi GetPrevPOI(PegasusPoi currentPoi, bool wrap = true)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (currentPoi != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (currentPoi.m_segmentIndex > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_poiList[currentPoi.m_segmentIndex - 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (wrap)
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_poiList[m_poiList.Count - 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get the next poi on from poi passed in
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="currentPoi">POI to start from</param>
|
|
|
|
|
|
/// <param name="wrap">Whether or not to wrap around</param>
|
|
|
|
|
|
/// <returns>Next POI or null if no data, invalid params or wrap boundary hit</returns>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public PegasusPoi GetNextPOI(PegasusPoi currentPoi, bool wrap = true)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (currentPoi != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (currentPoi.m_segmentIndex < m_poiList.Count - 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_poiList[currentPoi.m_segmentIndex + 1];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (wrap)
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_poiList[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Go and update all POI heights to min height of the manager
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void SetPoiToMinHeight()
|
|
|
|
|
|
{
|
|
|
|
|
|
PegasusPoi poi;
|
|
|
|
|
|
for (int idx = 0; idx < m_poiList.Count; idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
poi = m_poiList[idx];
|
|
|
|
|
|
poi.transform.position = poi.m_manager.GetLowestPoiPosition(poi.transform.position, poi.m_heightCheckType);
|
|
|
|
|
|
}
|
|
|
|
|
|
InitialiseFlythrough();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|