//---------------------------------------------------------------------------------------------------------------------- public override void OnInspectorGUI() { if (m_scPlayableAsset.IsNullRef()) return; SerializedObject so = serializedObject; EditorGUILayout.PropertyField(so.FindProperty("m_sceneCachePlayerRef"), SCENE_CACHE_PLAYER); { // Curve Operations GUILayout.BeginVertical("Box"); EditorGUILayout.LabelField("Curves", EditorStyles.boldLabel); const float BUTTON_X = 30; const float BUTTON_WIDTH = 160f; if (DrawGUIButton(BUTTON_X, BUTTON_WIDTH,"To Linear")) { SceneCacheClipData clipData = m_scPlayableAsset.GetBoundClipData(); clipData.SetCurveToLinear(); } if (DrawGUIButton(BUTTON_X, BUTTON_WIDTH,"Apply Original")) { SceneCacheClipData clipData = m_scPlayableAsset.GetBoundClipData(); clipData.ApplyOriginalSceneCacheCurve(); } GUILayout.EndVertical(); } so.ApplyModifiedProperties(); }
//---------------------------------------------------------------------------------------------------------------------- //Called when a clip is changed by the Editor. (TrimStart, TrimEnd, etc) public override void OnClipChanged(TimelineClip clip) { base.OnClipChanged(clip); SceneCachePlayableAsset playableAsset = clip.asset as SceneCachePlayableAsset; if (null == playableAsset) { Debug.LogWarning("[MeshSync] Clip Internal Error: Asset is not SceneCache"); return; } //Check if the curves is null, which may happen if the clip is created using code ? if (null == clip.curves) { CreateClipCurve(clip); } SceneCacheClipData clipData = playableAsset.GetBoundClipData() as SceneCacheClipData; if (null == clipData) { //The clip is not ready. Not deserialized yet return; } //Always apply clipCurves to clipData AnimationCurve curve = AnimationUtility.GetEditorCurve(clip.curves, SceneCachePlayableAsset.GetTimeCurveBinding()); clipData.SetAnimationCurve(curve); }
//---------------------------------------------------------------------------------------------------------------------- /// <inheritdoc/> public override ClipDrawOptions GetClipOptions(TimelineClip clip) { ClipDrawOptions clipOptions = base.GetClipOptions(clip); SceneCachePlayableAsset asset = clip.asset as SceneCachePlayableAsset; if (null == asset) { Debug.LogError("Asset is not a SceneCachePlayableAsset: " + clip.asset); return clipOptions; } SceneCacheClipData clipData = asset.GetBoundClipData(); if (null == clipData) return clipOptions; SceneCachePlayer scPlayer = asset.GetSceneCachePlayer(); if (null == scPlayer) { clipOptions.errorText = NO_SCENE_CACHE_ASSIGNED_ERROR; return clipOptions; } LimitedAnimationController overrideLimitedAnimationController =asset.GetOverrideLimitedAnimationController(); if (!scPlayer.IsLimitedAnimationOverrideable() && overrideLimitedAnimationController.IsEnabled()) { clipOptions.errorText = UNABLE_TO_OVERRIDE_LIMITED_ANIMATION_ERROR; return clipOptions; } clipOptions.tooltip = scPlayer.GetSceneCacheFilePath(); return clipOptions; }
public IEnumerator CreatePlayableAsset() { EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); //Add director GameObject directorGo = new GameObject("Director"); PlayableDirector director = directorGo.AddComponent <PlayableDirector>(); //Setup scene cache GameObject sceneCacheGo = new GameObject(); SceneCachePlayer sceneCachePlayer = sceneCacheGo.AddComponent <SceneCachePlayer>(); Assert.IsFalse(sceneCachePlayer.IsSceneCacheOpened()); SceneCachePlayerEditorUtility.ChangeSceneCacheFile(sceneCachePlayer, Path.GetFullPath(MeshSyncTestEditorConstants.CUBE_TEST_DATA_PATH)); //Create timeline asset TimelineAsset asset = ScriptableObject.CreateInstance <TimelineAsset>(); director.playableAsset = asset; //Create PlayableAsset/Track/ etc SceneCachePlayableAsset playableAsset = ScriptableObject.CreateInstance <SceneCachePlayableAsset>(); SceneCacheTrack sceneCacheTrack = asset.CreateTrack <SceneCacheTrack>(null, "TestSceneCacheTrack"); TimelineClip clip = sceneCacheTrack.CreateDefaultClip(); clip.asset = playableAsset; director.SetReferenceValue(playableAsset.GetSceneCachePlayerRef().exposedName, sceneCachePlayer); //Select gameObject and open Timeline Window. This will trigger the TimelineWindow's update etc. EditorApplication.ExecuteMenuItem("Window/Sequencing/Timeline"); Selection.activeTransform = directorGo.transform; yield return(null); director.time = 0; yield return(null); Assert.AreEqual(0, sceneCachePlayer.GetRequestedNormalizedTime()); double timePerFrame = 1.0f / sceneCacheTrack.timelineAsset.editorSettings.fps; double directorTime = clip.start + clip.duration - timePerFrame; SetDirectorTime(director, directorTime); yield return(null); //Check clipData and curve SceneCacheClipData clipData = playableAsset.GetBoundClipData(); Assert.IsNotNull(clipData); AnimationCurve curve = clipData.GetAnimationCurve(); Assert.IsNotNull(curve); float normalizedTime = curve.Evaluate((float)directorTime); Assert.AreEqual(normalizedTime, sceneCachePlayer.GetRequestedNormalizedTime()); }
//---------------------------------------------------------------------------------------------------------------------- /// <inheritdoc/> public override void DrawBackground(TimelineClip clip, ClipBackgroundRegion region) { base.DrawBackground(clip, region); SceneCachePlayableAsset asset = clip.asset as SceneCachePlayableAsset; if (null == asset) { Debug.LogError("Asset is not a SceneCachePlayableAsset: " + clip.asset); return; } SceneCacheClipData clipData = asset.GetBoundClipData(); if (null == clipData) return; LimitedAnimationController limitedAnimationController = asset.GetOverrideLimitedAnimationController(); if (!limitedAnimationController.IsEnabled()) { return; } int numFrames = limitedAnimationController.GetNumFramesToHold(); int offset = limitedAnimationController.GetFrameOffset(); GUIStyle style = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.LowerRight, normal = { textColor = new Color(0.3f,0.9f,0.3f), } }; GUIContent laContent = new GUIContent($"Limited: {numFrames}, {offset}"); Vector2 laContentSize = style.CalcSize(laContent); Rect rect = region.position; if (rect.width <= laContentSize.x * 2) //2: arbitrary return; EditorGUI.LabelField(rect, laContent, style); }
//---------------------------------------------------------------------------------------------------------------------- public override void OnInspectorGUI() { if (m_scPlayableAsset.IsNullRef()) return; SerializedObject so = serializedObject; EditorGUILayout.PropertyField(so.FindProperty("m_sceneCachePlayerRef"), SCENE_CACHE_PLAYER); EditorGUIDrawerUtility.DrawUndoableGUI(m_scPlayableAsset, "SceneCache: Snap", guiFunc: () => { SnapToFrame snap = m_scPlayableAsset.GetSnapToFrame(); return (SnapToFrame)EditorGUILayout.EnumPopup(Contents.SnapToFrame, snap); }, updateFunc: (SnapToFrame snap) => { m_scPlayableAsset.SetSnapToFrame(snap); }); { // Curve Operations GUILayout.BeginVertical("Box"); EditorGUILayout.LabelField("Curves", EditorStyles.boldLabel); const float BUTTON_X = 30; const float BUTTON_WIDTH = 160f; if (DrawGUIButton(BUTTON_X, BUTTON_WIDTH,"To Linear")) { SceneCacheClipData clipData = m_scPlayableAsset.GetBoundClipData(); clipData?.SetCurveToLinear(); } if (DrawGUIButton(BUTTON_X, BUTTON_WIDTH,"Apply Original")) { SceneCacheClipData clipData = m_scPlayableAsset.GetBoundClipData(); clipData?.ApplyOriginalSceneCacheCurve(); } GUILayout.EndVertical(); } so.ApplyModifiedProperties(); }