#if !CINEMACHINE_NO_CM2_SUPPORT
//#define DEBUG_HELPERS
#pragma warning disable CS0618 // obsolete warnings
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Splines;
using Object = UnityEngine.Object;
namespace Unity.Cinemachine.Editor
{
partial class UpgradeObjectToCm3
{
///
/// In-place upgrade a GameObject. Obsolete components are disabled (not deleted),
/// and replacement components are added. GameObject structure may be re-organized
/// (hidden objects deleted, components moved).
///
/// In a second pass, call DeleteObsoleteComponents().
///
/// The GameObject to upgrade
/// If the GameObject is not fully upgradable, a clone of the original will be returned.
/// A null return value means success.
public GameObject UpgradeComponents(GameObject go)
{
GameObject notUpgradable = null;
// Is it a DollyCart?
if (ReplaceComponent(go))
{
var obsoleteDolly = go.GetComponent();
var splineCart = go.GetComponent();
obsoleteDolly.UpgradeToCm3(splineCart);
}
// Is it a path?
if (go.TryGetComponent(out CinemachinePathBase path))
UpgradePath(path);
else if (!go.TryGetComponent(out _))
{
// It's some kind of vcam. Check for FreeLook first because it has
// hidden child VirtualCameras and we need to remove them
if (go.TryGetComponent(out var freelook))
{
notUpgradable = UpgradeFreelook(freelook);
var manager = freelook.ParentCamera as CinemachineCameraManagerBase;
if (manager != null)
manager.InvalidateCameraCache();
}
else if (go.TryGetComponent(out var vcam))
{
notUpgradable = UpgradeVcam(vcam);
var manager = vcam.ParentCamera as CinemachineCameraManagerBase;
if (manager != null)
manager.InvalidateCameraCache();
}
// Upgrade the pipeline components (there will be more of these...)
if (ReplaceComponent(go))
go.GetComponent().UpgradeToCm3(go.GetComponent());
if (ReplaceComponent(go))
{
var gc = go.GetComponent();
gc.UpgradeToCm3(go.GetComponent());
if (!go.TryGetComponent(out var _))
{
var framer = Undo.AddComponent(go);
go.GetComponent().AddExtension(framer);
gc.UpgradeToCm3(framer);
}
}
if (ReplaceComponent(go))
go.GetComponent().UpgradeToCm3(go.GetComponent());
if (ReplaceComponent(go))
{
var ft = go.GetComponent();
ft.UpgradeToCm3(go.GetComponent());
if (ft.FollowTargetAsGroup != null && ft.FollowTargetAsGroup.IsValid
&& ft.m_GroupFramingMode != CinemachineFramingTransposer.FramingMode.None
&& !go.TryGetComponent(out var _))
{
var framer = Undo.AddComponent(go);
go.GetComponent().AddExtension(framer);
ft.UpgradeToCm3(framer);
}
}
if (ReplaceComponent(go))
{
var pov = go.GetComponent();
pov.UpgradeToCm3(go.GetComponent());
ConvertInputAxis(go, "Look X (Pan)", ref pov.m_HorizontalAxis);
ConvertInputAxis(go, "Look Y (Tilt)", ref pov.m_VerticalAxis);
}
if (ReplaceComponent(go))
{
var orbital = go.GetComponent();
orbital.UpgradeToCm3(go.GetComponent());
ConvertInputAxis(go, "Look Orbit X", ref orbital.m_XAxis);
}
if (ReplaceComponent(go))
go.GetComponent().UpgradeToCm3(go.GetComponent());
if (ReplaceComponent(go))
go.GetComponent().UpgradeToCm3(go.GetComponent());
if (ReplaceComponent(go))
go.GetComponent().UpgradeToCm3(go.GetComponent());
#if CINEMACHINE_PHYSICS
if (ReplaceComponent(go))
go.GetComponent().UpgradeToCm3(go.GetComponent());
#endif
#if CINEMACHINE_PHYSICS || CINEMACHINE_PHYSICS_2D
if (go.TryGetComponent(out var confiner))
{
#if CINEMACHINE_PHYSICS
if (confiner.UpgradeToCm3_GetTargetType() == typeof(CinemachineConfiner3D))
{
ReplaceComponent(go);
confiner.UpgradeToCm3(go.GetComponent());
}
#endif
#if CINEMACHINE_PHYSICS_2D
if (confiner.UpgradeToCm3_GetTargetType() == typeof(CinemachineConfiner2D))
{
ReplaceComponent(go);
confiner.UpgradeToCm3(go.GetComponent());
}
#endif
}
#endif
}
return notUpgradable;
}
public static Type GetBehaviorReferenceUpgradeType(MonoBehaviour b)
{
#if CINEMACHINE_PHYSICS || CINEMACHINE_PHYSICS_2D
// Hack for Confiner upgrade: 2D or 3D?
if (b is CinemachineConfiner c)
return c.UpgradeToCm3_GetTargetType();
#endif
var oldType = b.GetType();
return ClassUpgradeMap.ContainsKey(oldType) ? ClassUpgradeMap[oldType] : oldType;
}
///
/// Handles animation clip reference updates for the input animation clip.
/// Does not support Undo!
///
public void ProcessAnimationClip(AnimationClip animationClip, Animator trackAnimator)
{
if (animationClip == null || trackAnimator == null)
return;
var existingEditorBindings = AnimationUtility.GetCurveBindings(animationClip);
foreach (var previousBinding in existingEditorBindings)
{
// if type is not in class upgrade map, then we won't change binding
if (!ClassUpgradeMap.ContainsKey(previousBinding.type))
continue;
var newBinding = previousBinding;
// upgrade type based on mapping
newBinding.type = ClassUpgradeMap[previousBinding.type];
// clean path pointing to old structure where vcam components lived on a hidden child gameObject
if (previousBinding.path.EndsWith("cm"))
{
var path = previousBinding.path;
//path is either cm only, or someParent/someOtherParent/.../cm. In the second case, we need to remove /cm, thus -1
var index = Mathf.Max(0, path.IndexOf("cm") - 1);
newBinding.path = path.Substring(0, index);
}
if (previousBinding.path.EndsWith("Rig"))
{
var path = newBinding.path;
//path is either xRig only, or someParent/someOtherParent/.../xRig. In the second case, we need to remove /xRig, thus -1
newBinding.path = path.Substring(0, Mathf.Max(0, FindRig(path) - 1));
static int FindRig(string path)
{
var rigs = CinemachineFreeLook.RigNames;
var index = 0;
foreach (var rig in rigs)
index = Mathf.Max(index, path.IndexOf(rig));
return index;
}
}
// clean old convention
if (previousBinding.propertyName.StartsWith("m_"))
{
var propertyName = previousBinding.propertyName;
newBinding.propertyName = propertyName.Replace("m_", string.Empty);
}
// Check if previousBinding.type needs an API change
if (m_APIUpgradeMaps.ContainsKey(previousBinding.type) &&
m_APIUpgradeMaps[previousBinding.type].ContainsKey(newBinding.propertyName))
{
var mapping = m_APIUpgradeMaps[previousBinding.type][newBinding.propertyName];
newBinding.propertyName = mapping.Item1;
// type can differ from previously set type, because some components became several separate ones
newBinding.type = mapping.Item2;
// special handling for references
if (mapping.Item1.Contains("managedReferences"))
{
// find property name of the reference
var propertyName = mapping.Item1;
var start = propertyName.IndexOf("[") + 1;
var end = propertyName.IndexOf("]");
propertyName = propertyName[start..end];
// find animated target component
var target = trackAnimator.transform.gameObject.GetComponent(mapping.Item2);
// find reference id of the property that's being animated
var so = new SerializedObject(target);
var prop = so.FindProperty(propertyName);
var newPropertyName = newBinding.propertyName;
newBinding.propertyName = newPropertyName[..start] + prop.managedReferenceId + newPropertyName[end..];
}
}
#if DEBUG_HELPERS
Debug.Log(previousBinding.path + "." + previousBinding.type.Name + "." + previousBinding.propertyName
+ " -> " + newBinding.path + "." + newBinding.type.Name + "." + newBinding.propertyName);
#endif
var curve = AnimationUtility.GetEditorCurve(animationClip, previousBinding); //keep existing curves
AnimationUtility.SetEditorCurve(animationClip, previousBinding, null); //remove previous binding
AnimationUtility.SetEditorCurve(animationClip, newBinding, curve); //set new binding
}
}
///
/// After a GameObject object has been in-place upgraded, call this to delete the
/// obsolete components that have been disabled.
///
/// The GameObject being upgraded
public void DeleteObsoleteComponents(GameObject go)
{
if (go == null)
return;
foreach (var t in ObsoleteComponentTypesToDelete)
{
var components = go.GetComponentsInChildren(t);
foreach (var c in components)
Undo.DestroyObjectImmediate(c);
}
if (PrefabUtility.IsPartOfAnyPrefab(go))
PrefabUtility.RecordPrefabInstancePropertyModifications(go);
}
/// Disable an obsolete component and add a replacement
static bool ReplaceComponent(GameObject go)
where TOld : MonoBehaviour
where TNew : MonoBehaviour
{
if (go.TryGetComponent(out var cOld) && cOld.GetType() == typeof(TOld))
{
Undo.RecordObject(cOld, "Upgrader: disable obsolete");
cOld.enabled = false;
if (!go.TryGetComponent(out var _))
Undo.AddComponent(go);
return true;
}
return false;
}
// Copy all serializable values
static void CopyValues(T from, T to)
{
var json = JsonUtility.ToJson(from);
JsonUtility.FromJsonOverwrite(json, to);
}
static CinemachineCamera UpgradeVcamBaseToCmCamera(CinemachineVirtualCameraBase vcam)
{
var go = vcam.gameObject;
if (!go.TryGetComponent(out CinemachineCamera cmCamera)) // Check if RequireComponent already added CinemachineCamera
{
// First disable the old vcamBase, or new one will be rejected
Undo.RecordObject(vcam, "Upgrader: disable obsolete");
vcam.enabled = false;
cmCamera = Undo.AddComponent(go);
CopyValues(vcam, cmCamera);
// Register the extensions with the cmCamera
foreach (var extension in vcam.gameObject.GetComponents())
cmCamera.AddExtension(extension);
}
else if (vcam.enabled) // RequireComponent added CinemachineCamera, it should be enabled iff vcam was enabled
{
Undo.RecordObject(vcam, "Upgrader: disable obsolete");
vcam.enabled = false;
Undo.RecordObject(cmCamera, "Upgrader: enable upgraded");
cmCamera.enabled = true;
}
return cmCamera;
}
static GameObject UpgradeVcam(CinemachineVirtualCamera vcam)
{
var go = vcam.gameObject;
var cmCamera = UpgradeVcamBaseToCmCamera(vcam);
cmCamera.Follow = vcam.m_Follow;
cmCamera.LookAt = vcam.m_LookAt;
cmCamera.Target.CustomLookAtTarget = vcam.m_Follow != vcam.m_LookAt;
cmCamera.Lens = vcam.m_Lens.ToLensSettings();
cmCamera.BlendHint = vcam.BlendHint;
if (vcam.m_OnCameraLiveEvent.GetPersistentEventCount() > 0)
{
var evts = Undo.AddComponent(go);
evts.OnCameraLive = vcam.m_OnCameraLiveEvent;
}
// Transfer the component pipeline
var pipeline = vcam.GetComponentPipeline();
if (pipeline != null)
foreach (var c in pipeline)
if (c != null)
CopyValues(c, Undo.AddComponent(go, c.GetType()) as CinemachineComponentBase);
// Destroy the hidden child object
var owner = vcam.GetComponentOwner();
if (owner != null && owner.gameObject != go)
UnparentAndDestroy(owner);
return null;
}
static void UnparentAndDestroy(Transform child)
{
if (child != null)
{
Undo.SetTransformParent(child, null, "Upgrader: destroy hidden child");
Undo.DestroyObjectImmediate(child.gameObject);
}
}
static void ConvertInputAxis(GameObject go, string name, ref AxisState axis)
{
if (!go.TryGetComponent(out var iac))
iac = Undo.AddComponent(go);
// Force creation of missing input controllers
iac.SynchronizeControllers();
#if CINEMACHINE_UNITY_INPUTSYSTEM
var provider = go.GetComponent();
if (provider != null)
{
provider.enabled = false;
iac.AutoEnableInputs = provider.AutoEnableInputs;
}
#endif
for (var i = 0; i < iac.Controllers.Count; ++i)
{
var c = iac.Controllers[i];
if (c.Name == name)
{
#if ENABLE_LEGACY_INPUT_MANAGER
c.Input.LegacyInput = axis.m_InputAxisName;
c.Input.LegacyGain = axis.m_MaxSpeed;
#endif
#if CINEMACHINE_UNITY_INPUTSYSTEM
if (provider != null)
c.Input.InputAction = provider.XYAxis;
c.Input.Gain = axis.m_MaxSpeed;
if (axis.m_SpeedMode == AxisState.SpeedMode.MaxSpeed)
c.Input.Gain /= 100; // very approx
#endif
c.Driver.AccelTime = axis.m_AccelTime;
c.Driver.DecelTime = axis.m_DecelTime;
break;
}
}
}
static GameObject UpgradeFreelook(CinemachineFreeLook freelook)
{
GameObject notUpgradable = null;
var topRig = freelook.GetRig(0);
var middleRig = freelook.GetRig(1);
var bottomRig = freelook.GetRig(2);
if (topRig == null || middleRig == null || bottomRig == null)
return null; // invalid Freelook, nothing to do
var go = freelook.gameObject;
if (!IsFreelookUpgradable(freelook))
{
notUpgradable = Object.Instantiate(go);
notUpgradable.SetActive(false);
Undo.AddComponent(notUpgradable);
Undo.RegisterCreatedObjectUndo(notUpgradable, "Upgrader: clone of non upgradable");
}
var cmCamera = UpgradeVcamBaseToCmCamera(freelook);
cmCamera.Follow = freelook.m_Follow;
cmCamera.LookAt = freelook.m_LookAt;
cmCamera.Target.CustomLookAtTarget = freelook.m_Follow != freelook.m_LookAt;
cmCamera.BlendHint = freelook.BlendHint;
if (freelook.m_OnCameraLiveEvent.GetPersistentEventCount() > 0)
{
var evts = Undo.AddComponent(go);
evts.OnCameraLive = freelook.m_OnCameraLiveEvent;
}
var freeLookModifier = Undo.AddComponent(go);
ConvertFreelookLens(freelook, cmCamera, freeLookModifier);
ConvertFreelookBody(freelook, go, freeLookModifier);
ConvertFreelookAim(freelook, go, freeLookModifier);
ConvertFreelookNoise(freelook, go, freeLookModifier);
ConvertInputAxis(go, "Look Orbit X", ref freelook.m_XAxis);
ConvertInputAxis(go, "Look Orbit Y", ref freelook.m_YAxis);
// Destroy the hidden child objects
UnparentAndDestroy(topRig.GetComponentOwner());
UnparentAndDestroy(topRig.transform);
UnparentAndDestroy(middleRig.GetComponentOwner());
UnparentAndDestroy(middleRig.transform);
UnparentAndDestroy(bottomRig.GetComponentOwner());
UnparentAndDestroy(bottomRig.transform);
return notUpgradable;
}
///
/// Differences in these fields will be ignored because the FreeLookModifier
/// will take care of them
///
static string[] s_FreelookIgnoreFieldsList = {
"m_ScreenX", "m_ScreenY", "m_DeadZoneWidth", "m_DeadZoneHeight",
"m_SoftZoneWidth", "m_SoftZoneHeight", "m_BiasX", "m_BiasY",
"m_AmplitudeGain", "m_FrequencyGain", };
static bool IsFreelookUpgradable(CinemachineFreeLook freelook)
{
// Freelook is not upgradable if it has:
// - look at override (parent lookat != child lookat)
// - different noise profiles on top, mid, bottom ||
// - different aim component types ||
// - same aim component types and with different parameters
var topRig = freelook.GetRig(0);
var middleRig = freelook.GetRig(1);
var bottomRig = freelook.GetRig(2);
var parentLookAt = freelook.LookAt;
var topNoise = topRig.GetCinemachineComponent();
var middleNoise = middleRig.GetCinemachineComponent();
var bottomNoise = bottomRig.GetCinemachineComponent();
var midAim = middleRig.GetCinemachineComponent(CinemachineCore.Stage.Aim);
return
parentLookAt == topRig.LookAt && parentLookAt == middleRig.LookAt && parentLookAt == bottomRig.LookAt
&& IsCompatibleNoise(topNoise, middleNoise)
&& IsCompatibleNoise(middleNoise, bottomNoise)
&& PublicFieldsEqual(topRig.GetCinemachineComponent(CinemachineCore.Stage.Aim), midAim, s_FreelookIgnoreFieldsList)
&& PublicFieldsEqual(bottomRig.GetCinemachineComponent(CinemachineCore.Stage.Aim), midAim, s_FreelookIgnoreFieldsList);
static bool IsCompatibleNoise(CinemachineBasicMultiChannelPerlin a, CinemachineBasicMultiChannelPerlin b)
{
// This check is conceived with the understanding that if a rig has empty
// noise then any specific settings differences can be accounted for in
// the FreeLookModifier by setting amplitude to 0
return a == null || b == null ||
((a.NoiseProfile == null || b.NoiseProfile == null || a.NoiseProfile == b.NoiseProfile)
&& a.PivotOffset == b.PivotOffset);
}
static bool PublicFieldsEqual(CinemachineComponentBase a, CinemachineComponentBase b, params string[] ignoreList)
{
if (a == null && b == null)
return true;
if (a == null || b == null)
return false;
var aType = a.GetType();
if (aType != b.GetType())
return false;
var publicFields = aType.GetFields();
foreach (var pi in publicFields)
{
var name = pi.Name;
if (ignoreList.Contains(name))
continue; // ignore
var field = aType.GetField(name);
if (!field.GetValue(a).Equals(field.GetValue(b)))
{
#if DEBUG_HELPERS
Debug.Log("Rig values differ: " + name);
#endif
return false;
}
}
return true;
}
}
static void ConvertFreelookLens(
CinemachineFreeLook freelook,
CinemachineCamera cmCamera, CinemachineFreeLookModifier freeLookModifier)
{
if (freelook.m_CommonLens)
cmCamera.Lens = freelook.m_Lens.ToLensSettings();
else
{
cmCamera.Lens = freelook.GetRig(1).m_Lens.ToLensSettings();
var lens0 = freelook.GetRig(0).m_Lens.ToLensSettings();
var lens2 = freelook.GetRig(2).m_Lens.ToLensSettings();
if (!LensSettings.AreEqual(ref cmCamera.Lens, ref lens0)
|| !LensSettings.AreEqual(ref cmCamera.Lens, ref lens2))
{
freeLookModifier.Modifiers.Add(new CinemachineFreeLookModifier.LensModifier
{
Top = lens0,
Bottom = lens2
});
}
}
}
static void ConvertFreelookBody(
CinemachineFreeLook freelook,
GameObject go, CinemachineFreeLookModifier freeLookModifier)
{
var top = freelook.GetRig(0).GetCinemachineComponent();
var middle = freelook.GetRig(1).GetCinemachineComponent();
var bottom = freelook.GetRig(2).GetCinemachineComponent();
if (top == null || middle == null || bottom == null)
return;
// Use middle rig as template
var orbital = Undo.AddComponent(go);
middle.UpgradeToCm3(orbital);
orbital.HorizontalAxis.Recentering = new ()
{
Enabled = freelook.m_RecenterToTargetHeading.m_enabled,
Time = freelook.m_RecenterToTargetHeading.m_RecenteringTime,
Wait = freelook.m_RecenterToTargetHeading.m_WaitTime
};
orbital.OrbitStyle = CinemachineOrbitalFollow.OrbitStyles.ThreeRing;
orbital.Orbits = new Cinemachine3OrbitRig.Settings
{
Top = new Cinemachine3OrbitRig.Orbit
{
Height = freelook.m_Orbits[0].m_Height,
Radius = Mathf.Max(freelook.m_Orbits[0].m_Radius, 0.01f),
},
Center = new Cinemachine3OrbitRig.Orbit
{
Height = freelook.m_Orbits[1].m_Height,
Radius = Mathf.Max(freelook.m_Orbits[1].m_Radius, 0.01f),
},
Bottom = new Cinemachine3OrbitRig.Orbit
{
Height = freelook.m_Orbits[2].m_Height,
Radius = Mathf.Max(freelook.m_Orbits[2].m_Radius, 0.01f),
},
SplineCurvature = freelook.m_SplineCurvature,
};
// Preserve the 0...1 range for Y axis, in case some script is depending on it
orbital.VerticalAxis.Range = new Vector2(0, 1);
orbital.VerticalAxis.Center = 0.5f;
orbital.VerticalAxis.Wrap = false;
orbital.VerticalAxis.Value = freelook.m_YAxis.Value;
orbital.VerticalAxis.Recentering = new ()
{
Enabled = freelook.m_YAxisRecentering.m_enabled,
Time = freelook.m_YAxisRecentering.m_RecenteringTime,
Wait = freelook.m_YAxisRecentering.m_WaitTime
};
// Do we need a modifier?
var topDamping = new Vector3(top.m_XDamping, top.m_YDamping, top.m_ZDamping);
var bottomDamping = new Vector3(bottom.m_XDamping, bottom.m_YDamping, bottom.m_ZDamping);
if (!(orbital.TrackerSettings.PositionDamping - topDamping).AlmostZero()
|| !(orbital.TrackerSettings.PositionDamping - bottomDamping).AlmostZero())
{
freeLookModifier.Modifiers.Add(new CinemachineFreeLookModifier.PositionDampingModifier
{
Damping = new CinemachineFreeLookModifier.TopBottomRigs
{
Top = topDamping,
Bottom = bottomDamping,
}
});
}
}
static void ConvertFreelookAim(
CinemachineFreeLook freelook,
GameObject go, CinemachineFreeLookModifier freeLookModifier)
{
// We assume that the middle aim is a suitable template
var template = freelook.GetRig(1).GetCinemachineComponent(CinemachineCore.Stage.Aim);
if (template == null)
return;
var newAim = (CinemachineComponentBase)Undo.AddComponent(go, template.GetType());
CopyValues(template, newAim);
// Add modifier if it is a composer
var middle = newAim as CinemachineComposer;
var top = freelook.GetRig(0).GetComponentInChildren();
var bottom = freelook.GetRig(2).GetComponentInChildren();
if (middle != null && top != null && bottom != null)
{
var topComposition = top.Composition;
var middleComposition = middle.Composition;
var bottomComposition = bottom.Composition;
if (!ScreenComposerSettings.Approximately(middleComposition, topComposition)
|| !ScreenComposerSettings.Approximately(middleComposition, bottomComposition))
{
freeLookModifier.Modifiers.Add(new CinemachineFreeLookModifier.CompositionModifier
{
Composition = new CinemachineFreeLookModifier.TopBottomRigs
{
Top = topComposition,
Bottom = bottomComposition
}
});
}
}
}
static void ConvertFreelookNoise(
CinemachineFreeLook freelook,
GameObject go, CinemachineFreeLookModifier freeLookModifier)
{
// Noise can be on any subset of the rigs
var top = freelook.GetRig(0).GetCinemachineComponent();
var middle = freelook.GetRig(1).GetCinemachineComponent();
var bottom = freelook.GetRig(2).GetCinemachineComponent();
var template = middle != null && middle.NoiseProfile != null
? middle : (top != null && top.NoiseProfile != null? top : bottom);
if (template == null || template.NoiseProfile == null)
return;
var middleNoise = Undo.AddComponent(go);
CopyValues(template, middleNoise);
var middleSettings = GetNoiseSettings(middle);
middleNoise.AmplitudeGain = middleSettings.Amplitude;
middleNoise.FrequencyGain = middleSettings.Frequency;
var topSettings = GetNoiseSettings(top);
var bottomSettings = GetNoiseSettings(bottom);
if (!Mathf.Approximately(topSettings.Amplitude, middleSettings.Amplitude)
|| !Mathf.Approximately(topSettings.Frequency, middleSettings.Frequency)
|| !Mathf.Approximately(bottomSettings.Amplitude, middleSettings.Amplitude)
|| !Mathf.Approximately(bottomSettings.Frequency, middleSettings.Frequency))
{
freeLookModifier.Modifiers.Add(new CinemachineFreeLookModifier.NoiseModifier
{
Noise = new CinemachineFreeLookModifier.TopBottomRigs
{
Top = topSettings,
Bottom = bottomSettings
}
});
}
CinemachineFreeLookModifier.NoiseModifier.NoiseSettings GetNoiseSettings(CinemachineBasicMultiChannelPerlin noise)
{
var settings = new CinemachineFreeLookModifier.NoiseModifier.NoiseSettings();
if (noise != null)
{
settings.Amplitude = noise.AmplitudeGain;
settings.Frequency = noise.FrequencyGain;
}
return settings;
}
}
static void UpgradePath(CinemachinePathBase pathBase)
{
var go = pathBase.gameObject;
if (go.TryGetComponent(out SplineContainer spline))
return; // already converted
spline = Undo.AddComponent(go);
var splineRoll = Undo.AddComponent(go);
splineRoll.Roll = new SplineData();
Undo.RecordObject(pathBase, "Upgrader: disable obsolete");
pathBase.enabled = false;
switch (pathBase)
{
case CinemachinePath path:
{
var waypoints = path.m_Waypoints;
spline.Spline = new Spline(waypoints.Length, path.Looped);
for (var i = 0; i < waypoints.Length; i++)
{
spline.Spline.Add(new BezierKnot
{
Position = waypoints[i].position,
Rotation = Quaternion.identity,
TangentIn = -waypoints[i].tangent,
TangentOut = waypoints[i].tangent,
});
splineRoll.Roll.Add(new DataPoint(i, waypoints[i].roll));
}
break;
}
case CinemachineSmoothPath smoothPath:
{
var waypoints = smoothPath.m_Waypoints;
spline.Spline = new Spline(waypoints.Length, smoothPath.Looped);
for (var i = 0; i < waypoints.Length; i++)
{
var tangent = smoothPath.EvaluateLocalTangent(i);
tangent /= 3f; // divide by magic number to match spline tangent scale correctly
spline.Spline.Add(new BezierKnot
{
Position = waypoints[i].position,
Rotation = Quaternion.identity,
TangentIn = -tangent,
TangentOut = tangent,
});
splineRoll.Roll.Add(new DataPoint(i, waypoints[i].roll));
}
break;
}
default:
{
// GML todo: handle this message properly
Undo.AddComponent(pathBase.gameObject);
Debug.LogError($"{go.name}: Path type {pathBase.GetType().Name} is not handled by the upgrader");
break;
}
}
}
}
}
#pragma warning restore CS0618
#endif