public override Playable CreatePlayable(PlayableGraph graph, GameObject owner) { var playable = ScriptPlayable <CinematicCameraPlayableBehaviour> .Create(graph, new CinematicCameraPlayableBehaviour()); CinematicCameraPlayableBehaviour clone = playable.GetBehaviour(); clone._clipAsset = this; clone._cameraShot = _cameraShot.Resolve(graph.GetResolver()); return(playable); }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { _trackBinding = playerData as CinematicCamera; if (_trackBinding == null) { return; } if (!_firstFrameHappened) { _defaultState = _trackBinding.GetState(); _firstFrameHappened = true; } int numInputs = playable.GetInputCount(); float[] inputWeights = new float[numInputs]; float totalWeights = 0.0f; CinematicCameraState[] states = new CinematicCameraState[numInputs]; for (int i = 0; i < numInputs; i++) { ScriptPlayable <CinematicCameraPlayableBehaviour> scriptPlayable = (ScriptPlayable <CinematicCameraPlayableBehaviour>)playable.GetInput(i); CinematicCameraPlayableBehaviour inputBehaviour = scriptPlayable.GetBehaviour(); if (inputBehaviour != null && (inputBehaviour._cameraShot != null || inputBehaviour._path != null)) { float inputWeight = playable.GetInputWeight(i); if (inputWeight > 0.0f) { TimelineClip clip = _trackAsset.GetClip(inputBehaviour._clipAsset); if (clip != null) { double clipStart = clip.hasPreExtrapolation ? clip.extrapolatedStart : clip.start; double clipDuration = clip.hasPreExtrapolation || clip.hasPostExtrapolation ? clip.extrapolatedDuration : clip.duration; if (_director.time >= clipStart && _director.time <= clipStart + clipDuration) { inputWeights[i] = inputWeight; Extrapolation extrapolation = Extrapolation.Hold; if (clip.hasPreExtrapolation && _director.time < clip.start) { extrapolation = GetExtrapolation(clip.preExtrapolationMode); } else if (clip.hasPostExtrapolation && _director.time > clip.start + clip.duration) { extrapolation = GetExtrapolation(clip.postExtrapolationMode); } float timeInClip = (float)(_director.time - clip.start); //Single shot if (inputBehaviour._cameraShot != null) { states[i] = inputBehaviour._cameraShot.GetState(timeInClip, (float)clip.duration); } //Camera path else if (inputBehaviour._path != null) { float clipPosition = CinematicCameraMixer.GetClipPosition(extrapolation, timeInClip, (float)clip.duration); float pathT = (float)MathUtils.Interpolate(inputBehaviour._pathInterpolation, 0d, 1f, clipPosition); //Work out path position PathPosition pos = inputBehaviour._path.GetPoint(pathT); //Work out a lerp between to path nodes inputBehaviour._path.GetNodeSection(pathT, out int startNode, out int endNode, out float sectionT); //Lerp camera shot state based on the relevant section of the path GetPathNodeStateInfo(timeInClip, (float)clip.duration, inputBehaviour._path, startNode, out CinematicCameraState startNodeState, out Quaternion startNodeFromTo, out Vector3 startNodeCamFor, out Vector3 startNodeCamUp); GetPathNodeStateInfo(timeInClip, (float)clip.duration, inputBehaviour._path, endNode, out CinematicCameraState endNodeState, out Quaternion endNodeFromTo, out Vector3 endNodeCamFor, out Vector3 endNodeCamUp); Vector3 cameraForward; Vector3 cameraUp; if (sectionT <= 0f) { states[i] = startNodeState; //cameraForward = startNodeFromTo * pos._pathForward; cameraForward = startNodeCamFor; cameraUp = startNodeCamUp; } else if (sectionT >= 1f) { states[i] = endNodeState; //cameraForward = endNodeFromTo * pos._pathForward; cameraForward = endNodeCamFor; cameraUp = endNodeCamUp; } else { states[i] = CinematicCameraState.Interpolate(_trackBinding, startNodeState, endNodeState, InterpolationType.Linear, sectionT); //Work out rotation based on Quaternion cameraRotation = Quaternion.Slerp(startNodeFromTo, endNodeFromTo, sectionT); cameraForward = cameraRotation * pos._pathForward; cameraForward = Vector3.Lerp(startNodeCamFor, endNodeCamFor, sectionT); cameraUp = Vector3.Lerp(startNodeCamUp, endNodeCamUp, sectionT); } //Set camera position from path pos states[i]._position = pos._pathPosition; states[i]._rotation = Quaternion.LookRotation(cameraForward, cameraUp); } totalWeights += inputWeights[i]; } } } } } if (totalWeights > 0.0f) { CinematicCameraState blendedState = _defaultState; float weightAdjust = 1.0f / totalWeights; bool firstBlend = true; for (int i = 0; i < numInputs; i++) { if (inputWeights[i] > 0.0f) { if (firstBlend) { blendedState = states[i]; firstBlend = false; } else { blendedState = CinematicCameraState.Interpolate(_trackBinding, blendedState, states[i], InterpolationType.Linear, inputWeights[i] * weightAdjust); } } } _trackBinding.SetState(blendedState); } else { _trackBinding.SetState(_defaultState); } }