///Creates a new animated parameter out of a member info that optionaly exists on a component in child transform of root transform.
        public bool TryAddParameter(MemberInfo member, IKeyable keyable, Transform child, Transform root)
        {
            if (animatedParameters == null)
            {
                animatedParameters = new List <AnimatedParameter>();
            }

            var newParam = new AnimatedParameter(member, keyable, child, root);

            if (!newParam.isValid)
            {
                return(false);
            }

            var found = animatedParameters.Find(p => p.CompareTo(newParam));

            if (found != null)
            {
                //handle possible changes from property to field and vice-verse
                if (found.parameterType != newParam.parameterType)
                {
                    found.ChangeMemberType(newParam.parameterType);
                }
                return(false);
            }

            animatedParameters.Add(newParam);
            return(true);
        }
 public AnimationDataCollection(IKeyable keyable, System.Type type, string[] memberPaths, string transformPath)
 {
     foreach (var memberPath in memberPaths)
     {
         TryAddParameter(keyable, type, memberPath, transformPath);
     }
 }
Exemple #3
0
 ///Validate the parameter within the context of provided keyable reference
 public void Validate(IKeyable keyable)
 {
     this.keyable = keyable;
                 #if SLATE_USE_EXPRESSIONS
     CompileExpression();
                 #endif
 }
        ///In SceneGUI, shows a position handle for target parameter of target keyable
        public static bool DoParameterPositionHandle(IKeyable keyable, AnimatedParameter animParam, TransformSpace space)
        {
            var originalPos = (Vector3)animParam.GetCurrentValueAsObject();
            var newPos      = originalPos;

            if (DoVectorPositionHandle(keyable, space, ref newPos))
            {
                if (keyable.IsRootTimeWithinClip())
                {
                    if (!Event.current.shift)
                    {
                        animParam.SetCurrentValue(newPos);
                    }
                    else
                    {
                        animParam.OffsetValue(newPos - originalPos);
                    }
                }
                else
                {
                    animParam.SetCurrentValue(newPos);
                    animParam.OffsetValue(newPos - originalPos);
                }
                EditorUtility.SetDirty(keyable as Object);
                return(true);
            }
            return(false);
        }
Exemple #5
0
 ///Try add key at time in keyable animation data
 public static void TryAddIdentityKey(this IKeyable keyable, float time)
 {
     if (keyable != null && keyable.animationData != null && keyable.animationData.isValid)
     {
         keyable.animationData.TryKeyIdentity(time);
     }
 }
        ///Creates a new animated parameter out of a member info that optionaly exists on a component in child transform of root transform.
        public bool TryAddParameter(IKeyable keyable, System.Type type, string memberPath, string transformPath)
        {
            if (animatedParameters == null)
            {
                _animatedParameters = new List <AnimatedParameter>();
            }

            var newParam = new AnimatedParameter(keyable, type, memberPath, transformPath);

            if (!newParam.isValid)
            {
                return(false);
            }

            var found = _animatedParameters.Find(p => p.CompareTo(newParam));

            if (found != null)
            {
                //handle possible changes from property to field and vice-verse
                if (found.parameterType != newParam.parameterType)
                {
                    found.ChangeMemberType(newParam.parameterType);
                }
                return(false);
            }

            _animatedParameters.Add(newParam);
            if (newParam.isExternal)
            {
                ReOrderParameters();
            }
            return(true);
        }
 public AnimationDataCollection(MemberInfo[] memberInfoParameters, IKeyable keyable, Transform child, Transform root)
 {
     foreach (var member in memberInfoParameters)
     {
         TryAddParameter(member, keyable, child, root);
     }
 }
Exemple #8
0
        ///----------------------------------------------------------------------------------------------

        ///Returns AnimationCurves of ALL (enabled and disabled) animated parameters stored in animationData of keyable.
        public static AnimationCurve[] GetCurvesAll(this IKeyable keyable)
        {
            if (keyable.animationData != null && keyable.animationData.isValid)
            {
                return(keyable.animationData.GetCurvesAll());
            }
            return(new AnimationCurve[0]);
        }
Exemple #9
0
        //This is basicaly used in Tracks. Shows only the parameter controls in a vertical style for space conservation.
        public static void ShowMiniParameterKeyControls(AnimatedParameter animParam, IKeyable keyable)
        {
            if (animParam == null)
            {
                return;
            }

            var rootTime      = keyable.root.currentTime;
            var keyableLength = keyable.endTime - keyable.startTime;
            var keyableTime   = Mathf.Clamp(rootTime - keyable.startTime, 0, keyableLength);
            var isRecording   = rootTime >= keyable.startTime && rootTime <= keyable.endTime && rootTime > 0;

            var hasAnyKey  = animParam.HasAnyKey();
            var hasKeyNow  = animParam.HasKey(keyableTime);
            var hasChanged = animParam.HasChanged();

            GUI.color = EditorGUIUtility.isProSkin? new Color(0, 0, 0, 0.2f) : new Color(0, 0, 0, 0.5f);
            GUILayout.BeginHorizontal(Slate.Styles.headerBoxStyle);
            GUI.color = Color.white;
            GUILayout.FlexibleSpace();

            if (GUILayout.Button(Slate.Styles.previousKeyIcon, GUIStyle.none, GUILayout.Height(18), GUILayout.Width(18)))
            {
                keyable.root.currentTime = animParam.GetKeyPrevious(keyableTime) + keyable.startTime;
            }

            GUI.color = hasKeyNow? Color.red : Color.white;
            GUI.color = hasAnyKey && hasChanged? Color.green : GUI.color;
            if (GUILayout.Button(Slate.Styles.keyIcon, GUIStyle.none, GUILayout.Height(18), GUILayout.Width(18)))
            {
                if (!hasKeyNow || hasChanged)
                {
                    animParam.SetKeyCurrent(keyableTime);
                }
                else
                {
                    animParam.RemoveKey(keyableTime);
                }
            }
            GUI.color = Color.white;

            if (GUILayout.Button(Slate.Styles.nextKeyIcon, GUIStyle.none, GUILayout.Height(18), GUILayout.Width(18)))
            {
                keyable.root.currentTime = animParam.GetKeyNext(keyableTime) + keyable.startTime;
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUI.enabled = !animParam.isExternal || isRecording;

            GUI.color = EditorGUIUtility.isProSkin? new Color(0.5f, 0.5f, 0.5f, 0.5f) : new Color(0, 0, 0, 0.3f);
            GUILayout.BeginVertical(Slate.Styles.clipBoxFooterStyle);
            GUI.color = Color.white;
            DoParameterField(null, animParam, keyableTime);
            GUILayout.EndVertical();
            GUI.enabled = true;
        }
Exemple #10
0
 public CurveRenderer(IAnimatableData animatable, IKeyable keyable, Rect posRect)
 {
     this.animatable         = animatable;
     this.keyable            = keyable;
     this.curves             = animatable.GetCurves();
     this.posRect            = posRect;
     Undo.undoRedoPerformed += () => { RefreshCurves(); };
     Init();
 }
 ///0. Validate the parameters within the context of a keyable reference
 public void Validate(IKeyable keyable)
 {
     if (animatedParameters != null)
     {
         for (var i = 0; i < animatedParameters.Count; i++)
         {
             animatedParameters[i].Validate(keyable);
         }
     }
 }
Exemple #12
0
        public static void DrawDopeSheet(IAnimatableData animatable, IKeyable keyable, Rect rect, float startTime, float length, bool highlightRange = true)
        {
            DopeSheetRenderer dopeSheet = null;

            if (!cache.TryGetValue(animatable, out dopeSheet))
            {
                cache[animatable] = dopeSheet = new DopeSheetRenderer(animatable, keyable);
            }
            dopeSheet.DrawDopeSheet(animatable, keyable, rect, startTime, length, highlightRange);
        }
Exemple #13
0
        public static void Draw3DCurve(IAnimatableData animatable, IKeyable keyable, Transform transformContext, float time, float timeSpan = 50f)
        {
            CurveEditor3DRenderer instance = null;

            if (!cache.TryGetValue(animatable, out instance))
            {
                cache[animatable] = instance = new CurveEditor3DRenderer();
            }
            instance.Draw3DCurve(animatable, keyable, transformContext, time, timeSpan);
        }
Exemple #14
0
        public static void DrawCurves(IAnimatableData animatable, IKeyable keyable, Rect posRect, Rect timeRect)
        {
            CurveRenderer instance = null;

            if (!cache.TryGetValue(animatable, out instance))
            {
                cache[animatable] = instance = new CurveRenderer(animatable, keyable, posRect);
            }
            instance.Draw(posRect, timeRect);
        }
Exemple #15
0
            public DopeSheetRenderer(IAnimatableData animatable, IKeyable keyable)
            {
                this.animatable = animatable;
                this.allCurves  = animatable.GetCurves();
                this.keyable    = keyable;
                RefreshDopeKeys(animatable);
                Undo.undoRedoPerformed += () => { ResetInteraction(); refreshDopeKeys = true; };

#if UNITY_2018_3_OR_NEWER
                UnityEditor.Experimental.SceneManagement.PrefabStage.prefabStageClosing += (stage) => { refreshDopeKeys = true; };
#endif
            }
        ///In SceneGUI, shows a rotation handle for target parameter of target keyable
        public static bool DoParameterRotationHandle(IKeyable keyable, AnimatedParameter animParam, TransformSpace space, Vector3 position)
        {
            var originalRot = (Vector3)animParam.GetCurrentValueAsObject();
            var newRot      = originalRot;

            if (DoVectorRotationHandle(keyable, space, position, ref newRot))
            {
                animParam.SetCurrentValue(newRot);
                EditorUtility.SetDirty(keyable as Object);
                return(true);
            }
            return(false);
        }
Exemple #17
0
 ///Creates a new animated parameter out of a member info that optionaly exists on a component in child transform of root transform.
 public AnimatedParameter(MemberInfo member, IKeyable keyable, Transform child, Transform root)
 {
     this.keyable = keyable;
     if (member is PropertyInfo)
     {
         ConstructWithProperty((PropertyInfo)member, child, root);
         return;
     }
     if (member is FieldInfo)
     {
         ConstructWithField((FieldInfo)member, child, root);
         return;
     }
     Debug.LogError("MemberInfo provided is neither Property nor Field");
 }
        ///Creates a new animated parameter out of a member info that optionaly exists on a component in child transform of root transform.
        public AnimatedParameter(IKeyable keyable, Type type, string memberPath, string transformPath)
        {
            this.keyable = keyable;
            var member = ReflectionTools.GetRelativeMember(type, memberPath);

            if (member is PropertyInfo)
            {
                ConstructWithProperty((PropertyInfo)member, type, memberPath, transformPath);
                return;
            }
            if (member is FieldInfo)
            {
                ConstructWithField((FieldInfo)member, type, memberPath, transformPath);
                return;
            }
            Debug.LogError("MemberInfo provided is neither Property, nor Field, or can't be found.");
        }
Exemple #19
0
        ///Try record keys
        public static bool TryAutoKey(this IKeyable keyable, float time)
        {
            if (Application.isPlaying || keyable.root.isReSampleFrame)
            {
                return(false);
            }

            if (!Prefs.autoKey || GUIUtility.hotControl != 0)
            {
                return(false);
            }

            var case1           = ReferenceEquals(CutsceneUtility.selectedObject, keyable);
            var activeTransform = UnityEditor.Selection.activeTransform;
            var actor           = keyable.actor;
            var case2           = actor != null && activeTransform != null && activeTransform.IsChildOf(actor.transform);

            if (case1 || case2)
            {
                return(keyable.animationData.TryAutoKey(time));
            }
            return(false);
        }
Exemple #20
0
        ///The gear context menu for all parameters
        public static void DoParamGearContextMenu(AnimatedParameter animParam, IKeyable keyable)
        {
            var keyableTime = keyable.RootTimeToLocalTime();
            var hasKeyNow   = animParam.HasKey(keyableTime);
            var hasAnyKey   = animParam.HasAnyKey();

            var menu = new GenericMenu();

            if (animParam.enabled)
            {
                if (hasKeyNow)
                {
                    menu.AddDisabledItem(new GUIContent("Add Key"));
                    menu.AddItem(new GUIContent("Remove Key"), false, () => { animParam.RemoveKey(keyableTime); });
                }
                else
                {
                    menu.AddItem(new GUIContent("Add Key"), false, () => { animParam.SetKeyCurrent(keyableTime); });
                    menu.AddDisabledItem(new GUIContent("Remove Key"));
                }

                if (hasAnyKey)
                {
                    menu.AddItem(new GUIContent("Pre Wrap Mode/Clamp"), false, () => { animParam.SetPreWrapMode(WrapMode.ClampForever); });
                    menu.AddItem(new GUIContent("Pre Wrap Mode/Loop"), false, () => { animParam.SetPreWrapMode(WrapMode.Loop); });
                    menu.AddItem(new GUIContent("Pre Wrap Mode/PingPong"), false, () => { animParam.SetPreWrapMode(WrapMode.PingPong); });

                    menu.AddItem(new GUIContent("Post Wrap Mode/Clamp"), false, () => { animParam.SetPostWrapMode(WrapMode.ClampForever); });
                    menu.AddItem(new GUIContent("Post Wrap Mode/Loop"), false, () => { animParam.SetPostWrapMode(WrapMode.Loop); });
                    menu.AddItem(new GUIContent("Post Wrap Mode/PingPong"), false, () => { animParam.SetPostWrapMode(WrapMode.PingPong); });
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Pre Wrap Mode"));
                    menu.AddDisabledItem(new GUIContent("Post Wrap Mode"));
                }

#if SLATE_USE_EXPRESSIONS
                if (!animParam.hasActiveExpression)
                {
                    menu.AddItem(new GUIContent("Set Expression"), false, () => { animParam.scriptExpression = "value"; });
                    menu.AddDisabledItem(new GUIContent("Remove Expression"));
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Set Expression"));
                    menu.AddItem(new GUIContent("Remove Expression"), false, () => { animParam.scriptExpression = null; });
                }
#endif
            }

            menu.AddItem(new GUIContent(animParam.enabled ? "Disable" : "Enable"), false, () => { animParam.SetEnabled(!animParam.enabled, keyableTime); });

            menu.AddSeparator("/");
            if (hasAnyKey)
            {
                menu.AddItem(new GUIContent("Remove Animation"), false, () =>
                {
                    if (EditorUtility.DisplayDialog("Reset Animation", "All animation keys will be removed for this parameter.\nAre you sure?", "Yes", "No"))
                    {
                        if (animParam.isExternal)
                        {
                            animParam.RestoreSnapshot();
                        }
                        animParam.Reset();
                        if (animParam.isExternal)
                        {
                            animParam.SetSnapshot();
                        }
                    }
                });
            }
            else
            {
                menu.AddDisabledItem(new GUIContent("Remove Animation"));
            }

            if (animParam.isExternal)
            {
                menu.AddItem(new GUIContent("Remove Parameter"), false, () =>
                {
                    if (EditorUtility.DisplayDialog("Remove Parameter", "Completely Remove Parameter.\nAre you sure?", "Yes", "No"))
                    {
                        animParam.RestoreSnapshot();
                        keyable.animationData.RemoveParameter(animParam);
                        CutsceneUtility.RefreshAllAnimationEditorsOf(keyable.animationData);
                    }
                });
            }

            menu.ShowAsContext();
            Event.current.Use();
        }
Exemple #21
0
        ///Display an AnimatedParameter GUI
        public static void ShowParameter(AnimatedParameter animParam, IKeyable keyable, SerializedProperty serializedProperty = null)
        {
            //Calling this through a PropertyDrawer (thus serialized property != null), seems to have some mambo jumbo spacing.
            //This fixes that spacing so that both field and property parameter editors looks the same.
            GUILayout.Space(serializedProperty != null ? 0 : 2);

            if (!animParam.isValid)
            {
                GUILayout.Label("Animatable Parameter is invalid");
                return;
            }

            var e                = Event.current;
            var keyableLength    = keyable.GetLength();
            var keyableTime      = keyable.RootTimeToLocalTime();
            var isRecording      = keyable.IsRootTimeWithinClip();
            var foldOut          = EditorTools.GetObjectFoldOut(animParam);
            var hasAnyKey        = animParam.HasAnyKey();
            var hasKeyNow        = animParam.HasKey(keyableTime);
            var hasChanged       = animParam.HasChanged();
            var parameterEnabled = animParam.enabled;
            var lastRect         = new Rect();

            GUI.backgroundColor = new Color(0, 0.4f, 0.4f, 0.5f);
            GUILayout.BeginVertical(Slate.Styles.headerBoxStyle);
            GUI.backgroundColor = Color.white;

            GUILayout.BeginHorizontal();

            var sFold = foldOut ? "▼" : "▶";
            var sName = animParam.ToString();

            GUILayout.Label(sFold, GUILayout.Width(13));
            lastRect    = GUILayoutUtility.GetLastRect();
            GUI.enabled = !animParam.isExternal || isRecording;

            GUI.backgroundColor = hasAnyKey && parameterEnabled ? new Color(1, 0.6f, 0.6f) : Color.white;
            GUI.backgroundColor = hasAnyKey && parameterEnabled && isRecording ? Slate.Styles.recordingColor : GUI.backgroundColor;

            DoParameterField(string.Format("<b>{0}</b>", sName), animParam, keyableTime);

            GUI.enabled         = true;
            GUI.backgroundColor = Color.white;

            EditorGUIUtility.AddCursorRect(lastRect, MouseCursor.Link);
            if (e.type == EventType.MouseDown && e.button == 0 && lastRect.Contains(e.mousePosition))
            {
                EditorTools.SetObjectFoldOut(animParam, !foldOut);
                e.Use();
            }

            GUI.enabled = hasAnyKey && parameterEnabled;
            if (GUILayout.Button(Slate.Styles.previousKeyIcon, GUIStyle.none, GUILayout.Height(20), GUILayout.Width(16)))
            {
                keyable.root.currentTime = animParam.GetKeyPrevious(keyableTime) + keyable.startTime;
            }
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);

            GUI.enabled = parameterEnabled;
            GUI.color   = hasKeyNow && parameterEnabled ? new Color(1, 0.3f, 0.3f) : Color.white;
            GUI.color   = hasAnyKey && hasChanged ? Color.green : GUI.color;
            if (GUILayout.Button(Slate.Styles.keyIcon, GUIStyle.none, GUILayout.Height(20), GUILayout.Width(16)))
            {
                if (e.alt)     //temporary solution
                {
                    animParam.scriptExpression = "value";
                    EditorTools.SetObjectFoldOut(animParam, true);
                }
                else
                {
                    if (!hasKeyNow || hasChanged)
                    {
                        animParam.SetKeyCurrent(keyableTime);
                    }
                    else
                    {
                        animParam.RemoveKey(keyableTime);
                    }
                }
            }
            GUI.color = Color.white;
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);


            GUI.enabled = hasAnyKey && parameterEnabled;
            if (GUILayout.Button(Slate.Styles.nextKeyIcon, GUIStyle.none, GUILayout.Height(20), GUILayout.Width(16)))
            {
                keyable.root.currentTime = animParam.GetKeyNext(keyableTime) + keyable.startTime;
            }
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);

            GUILayout.Space(2);

            GUI.enabled = true;
            GUI.color   = Color.white.WithAlpha(animParam.enabled ? 1 : 0.5f);
            if (GUILayout.Button(Slate.Styles.gearIcon, GUIStyle.none, GUILayout.Height(20), GUILayout.Width(16)))
            {
                DoParamGearContextMenu(animParam, keyable);
            }
            GUI.color = Color.white;
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);

            GUI.enabled = true;
            GUILayout.EndHorizontal();

            //...
            GUILayout.Space(3);
            GUILayout.EndVertical();

            // var fade = EditorTools.GetObjectFoldOutFaded(animParam);
            if (EditorTools.GetObjectFoldOut(animParam))
            {
                var hasExpression = animParam.hasActiveExpression;

                GUI.color = new Color(0.5f, 0.5f, 0.5f, 0.3f);
                GUILayout.BeginVertical(Slate.Styles.clipBoxFooterStyle);
                GUI.color = Color.white;

#if SLATE_USE_EXPRESSIONS
                GUILayout.BeginHorizontal();
                if (hasExpression)
                {
                    if (GUILayout.Button(Styles.expressionIcon, GUI.skin.label, GUILayout.Width(18)))
                    {
                        var menu = Slate.Expressions.ExpressionsMenuGenerator.GetExpressionEnvironmentMenu(animParam.GetExpressionEnvironment(), (template) => { animParam.scriptExpression = template; });
                        menu.ShowAsContext();
                    }
                    EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);
                    animParam.scriptExpression = EditorGUILayout.DelayedTextField(animParam.scriptExpression);
                }
                GUILayout.EndHorizontal();

                if (hasExpression && animParam.compileException != null)
                {
                    EditorGUILayout.HelpBox(animParam.compileException.Message, MessageType.Error);
                }
#endif

                string info = null;
                if (!parameterEnabled)
                {
                    info = "Parameter is disabled or overriden.";
                }

                if (info == null && !hasAnyKey && !hasExpression)
                {
                    info = "Parameter is not yet animated. You can make it so by creating the first key.";
                }

                if (info == null && keyableLength == 0 && hasAnyKey)
                {
                    info = "Length of Clip is zero. Can not display Curve Editor.";
                }

                if (info == null && animParam.isExternal && !isRecording)
                {
                    info = "This Parameter can only be edited when time is within the clip range.";
                }

                if (info != null)
                {
                    GUILayout.Label(info);
                }
                else
                {
                    DoCurveBox(animParam, keyable, isRecording);
                }

                GUILayout.EndVertical();
                GUILayout.Space(5);
            }
            else
            {
#if SLATE_USE_EXPRESSIONS
                if (animParam.hasActiveExpression)
                {
                    GUI.color = new Color(0.5f, 0.5f, 0.5f, 0.3f);
                    GUILayout.BeginHorizontal(Styles.clipBoxFooterStyle);
                    GUI.color = Color.white;
                    GUILayout.Space(10);
                    GUILayout.Label(string.Format("<b>= </b><size=9>{0}</size>", animParam.scriptExpression));
                    GUILayout.EndHorizontal();
                }
#endif
            }

            // EditorGUILayout.EndFadeGroup();
        }
        /// <summary>
        ///     Builds the current key.
        /// </summary>
        private void BuildCurrentKey()
        {
            var conceptKeys = new List<IKeyValue>();
            foreach (var key in this._dataSetConcepts)
            {
                IKeyValue keyValue = new KeyValueImpl(key.Value, key.Key);
                conceptKeys.Add(keyValue);
            }

            foreach (var key in this._groupConcepts)
            {
                IKeyValue keyValue = new KeyValueImpl(key.Value, key.Key);
                conceptKeys.Add(keyValue);
            }

            foreach (var key in this._sectionConcepts)
            {
                IKeyValue keyValue = new KeyValueImpl(key.Value, key.Key);
                conceptKeys.Add(keyValue);
            }

            foreach (var key in this._observationConcepts)
            {
                IKeyValue keyValue = new KeyValueImpl(key.Value, key.Key);
                conceptKeys.Add(keyValue);
            }

            var attributeKeys = new List<IKeyValue>();
            foreach (var key in this._dataSetAttributes)
            {
                IKeyValue keyValue = new KeyValueImpl(key.Value, key.Key);
                attributeKeys.Add(keyValue);
            }

            foreach (var key in this._groupAttributes)
            {
                IKeyValue keyValue = new KeyValueImpl(key.Value, key.Key);
                attributeKeys.Add(keyValue);
            }

            foreach (var key in this._sectionAttributes)
            {
                IKeyValue keyValue = new KeyValueImpl(key.Value, key.Key);
                attributeKeys.Add(keyValue);
            }

            if (!string.IsNullOrWhiteSpace(this._timeDimensionId) && !string.IsNullOrWhiteSpace(this._obsTime))
            {
                TimeFormat timeFormat = DateUtil.GetTimeFormatOfDate(this._obsTime);
                this._currentKey = new KeyableImpl(this._dataflow, this._currentDsd, conceptKeys, attributeKeys, timeFormat, this._timeDimensionId, this._obsTime);
            }
            else
            {
                this._currentKey = new KeyableImpl(this._dataflow, this._currentDsd, conceptKeys, attributeKeys, string.Empty);
            }
        }
 /// <summary>
 ///     Moves the read position back to the start of the Data Set (<see cref="IDataReaderEngine.KeyablePosition" /> moved
 ///     back to -1)
 /// </summary>
 public void Reset()
 {
     this._currentlyProcessingReaderIndex = -1;
     this._ediDataReader = null;
     this._currentObsPos = -1;
     this._keyablePosition = -1;
     this._currentKey = null;
     this._currentObs = null;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="ObservationImpl"/> class.
        /// </summary>
        /// <param name="obsTime">
        /// The obs time 0. 
        /// </param>
        /// <param name="obsValue">
        /// The obs value 1. 
        /// </param>
        /// <param name="attributes">
        /// The attributes 2. 
        /// </param>
        public ObservationImpl(IKeyable seriesKey, string obsTime, string obsValue, IList<IKeyValue> attributes
            ,params IAnnotation[] annotations)
        {
            this.obsValue = obsValue;
            this._seriesKey = seriesKey;

            if (seriesKey == null)
            {
                throw new ArgumentException("Series Key can not be null");
            }
            if (!ObjectUtil.ValidString(obsTime))
            {
                if (seriesKey.TimeSeries)
                {
                    throw new ArgumentException(
                        "Observation for Key '" + seriesKey + "' does not specify the observation time");
                }
                throw new ArgumentException(
                    "Observation for Key '" + seriesKey + "' does not specify the observation concept: "
                    + seriesKey.CrossSectionConcept);
            }
       
            this.obsTime = obsTime;
            if (attributes != null)
            {
                this.attributes = new List<IKeyValue>(attributes);
                foreach (IKeyValue currentKv in attributes)
                {
                    this.attributeMap.Add(currentKv.Concept, currentKv);
                }
            }

            if(annotations != null)
            {
			  foreach(IAnnotation currentAnnotation in annotations) 
              {
				 this.annotations.Add(currentAnnotation);
			  }
	 	    }
            this.isCrossSection = false;
        }
Exemple #25
0
            public void DrawDopeSheet(IAnimatableData animatable, IKeyable keyable, Rect rect, float startTime, float length, bool highlightRange)
            {
                this.length     = length;
                this.rect       = rect;
                this.width      = rect.width;
                this.startTime  = startTime;
                this.animatable = animatable;
                this.allCurves  = animatable.GetCurves();
                this.keyable    = keyable;
                var e = Event.current;

                //no curves?
                if (allCurves == null || allCurves.Length == 0)
                {
                    GUI.Label(new Rect(rect.x, rect.y, rect.width, rect.height), "---");
                    return;
                }

                //if flag is true refresh all dopesheets of the same IKeyable
                if (refreshDopeKeys)
                {
                    refreshDopeKeys = false;
                    DopeSheetEditor.RefreshDopeKeysOf(animatable);
                }

                //range graphics
                if (highlightRange && currentTimes.Count > 0)
                {
                    var firstKeyPos = TimeToPos(currentTimes.FirstOrDefault());
                    var lastKeyPos  = TimeToPos(currentTimes.LastOrDefault());

                    if (Mathf.Abs(firstKeyPos - lastKeyPos) > 0)
                    {
                        var rangeRect = Rect.MinMaxRect(firstKeyPos - 8, rect.yMin, lastKeyPos + 8, rect.yMax);
                        rangeRect.xMin = Mathf.Max(rangeRect.xMin, rect.xMin);
                        rangeRect.xMax = Mathf.Min(rangeRect.xMax, rect.xMax);
                        if (rangeRect.width > 5)
                        {
                            GUI.color = EditorGUIUtility.isProSkin ? new Color(0f, 0.5f, 0.5f, 0.4f) : new Color(1, 1, 1, 0.5f);
                            GUI.Box(rangeRect, string.Empty, Slate.Styles.clipBoxStyle);
                            GUI.color = Color.white;
                        }

                        if (preWrapMode != WrapMode.ClampForever)
                        {
                            var r = Rect.MinMaxRect(rect.xMin, rect.yMin, firstKeyPos, rect.yMax);
                            if (r.width > 16)
                            {
                                GUI.color = new Color(1, 1, 1, 0.5f);
                                var r2 = new Rect(0, 0, 16, 16);
                                r2.center = r.center;
                                Texture2D icon = null;
                                if (preWrapMode == WrapMode.Loop)
                                {
                                    icon = Styles.loopIcon;
                                }
                                if (preWrapMode == WrapMode.PingPong)
                                {
                                    icon = Styles.pingPongIcon;
                                }
                                if (icon != null)
                                {
                                    GUI.Box(r2, icon, GUIStyle.none);
                                }
                                GUI.color = Color.white;
                            }
                        }

                        if (postWrapMode != WrapMode.ClampForever)
                        {
                            var r = Rect.MinMaxRect(lastKeyPos, rect.yMin, rect.xMax, rect.yMax);
                            if (r.width > 16)
                            {
                                GUI.color = new Color(1, 1, 1, 0.25f);
                                var r2 = new Rect(0, 0, 16, 16);
                                r2.center = r.center;
                                Texture2D icon = null;
                                if (postWrapMode == WrapMode.Loop)
                                {
                                    icon = Styles.loopIcon;
                                }
                                if (postWrapMode == WrapMode.PingPong)
                                {
                                    icon = Styles.pingPongIcon;
                                }
                                if (icon != null)
                                {
                                    GUI.Box(r2, icon, GUIStyle.none);
                                }
                                GUI.color = Color.white;
                            }
                        }
                    }
                }

                //bg graphics (just a horizontal line)
                GUI.color = new Color(0, 0, 0, 0.1f);
                var center   = rect.y + (rect.height / 2);
                var lineRect = Rect.MinMaxRect(rect.x, center - 1, rect.xMax, center + 1);

                GUI.DrawTexture(lineRect, Slate.Styles.whiteTexture);
                GUI.color = Color.white;

                //selection rect graphics
                if (timeSelectionRect != null)
                {
                    GUI.Box(pixelSelectionRect, string.Empty);
                    GUI.color = new Color(0.5f, 0.5f, 1, 0.25f);
                    GUI.DrawTexture(pixelSelectionRect, Slate.Styles.whiteTexture);
                    GUI.color = Color.white;
                }


                //draw the dopekeys
                var tangentMode = TangentMode.Editable;

                for (var t = 0; t < currentTimes.Count; t++)
                {
                    var time = currentTimes[t];
                    //ignore if out of view range (+- some extra offset)
                    if (time < startTime - 0.1f || time > startTime + length + 0.1f)
                    {
                        continue;
                    }

                    //DopeKey graphics/icon
                    var icon = Slate.Styles.dopeKey;
                    if (Prefs.keyframesStyle == Prefs.KeyframesStyle.PerTangentMode)
                    {
                        tangentMode = tangentModes[t];
                        if (tangentMode != TangentMode.Editable)
                        {
                            if (tangentMode == TangentMode.Smooth)
                            {
                                icon = Slate.Styles.dopeKeySmooth;
                            }
                            if (tangentMode == TangentMode.Constant)
                            {
                                icon = Slate.Styles.dopeKeyConstant;
                            }
                            if (tangentMode == TangentMode.Linear)
                            {
                                icon = Slate.Styles.dopeKeyLinear;
                            }
                        }
                    }

                    var dopeKeyRect = new Rect(0, 0, icon.width, icon.height);
                    dopeKeyRect.center = new Vector2(TimeToPos(time), rect.center.y);
                    var isSelected = t == pickIndex || (rectSelectedIndeces != null && rectSelectedIndeces.Contains(t));
                    GUI.color = isSelected ? new Color(0.6f, 0.6f, 1) : Color.white;
                    GUI.DrawTexture(dopeKeyRect, icon);
                    GUI.color = Color.white;


                    //key value label
                    if (Prefs.showDopesheetKeyValues)
                    {
                        var nextPos        = t < currentTimes.Count - 1 ? TimeToPos(currentTimes[t + 1]) : TimeToPos(length);
                        var valueLabelRect = Rect.MinMaxRect(dopeKeyRect.xMax, rect.yMin - 3, nextPos - dopeKeyRect.width / 2, rect.yMax);
                        if (valueLabelRect.width > 20)
                        {
                            GUI.Label(valueLabelRect, keyLabels[t], Slate.Styles.leftLabel);
                        }
                    }


                    //do the following only if we dont have a rect selection
                    if (timeSelectionRect == null)
                    {
                        //pick the key
                        if (e.type == EventType.MouseDown && dopeKeyRect.Contains(e.mousePosition))
                        {
                            prePickTimes = new List <float>(currentTimes);
                            pickIndex    = t;
                            if (e.clickCount == 2)
                            {
                                keyable.root.currentTime       = time + keyable.startTime;
                                CutsceneUtility.selectedObject = keyable;
                            }
                            e.Use();
                        }

                        //single key context menu
                        if (e.type == EventType.MouseUp && e.button == 1 && dopeKeyRect.Contains(e.mousePosition))
                        {
                            DoSingleKeyContextMenu(e, time, tangentMode);
                            e.Use();
                        }
                    }
                }


                //drag the picked key if any. Shift drags all next to it as well
                if (pickIndex != -1)
                {
                    var controlID = GUIUtility.GetControlID(FocusType.Passive);
                    var eventType = e.GetTypeForControl(controlID);
                    if (eventType == EventType.MouseDrag && e.button == 0)
                    {
                        GUIUtility.hotControl = controlID;
                        var lastTime = currentTimes[pickIndex];
                        var newTime  = PosToTime(e.mousePosition.x);
                        newTime = Mathf.Round(newTime / Prefs.snapInterval) * Prefs.snapInterval;
                        newTime = Mathf.Clamp(newTime, startTime, startTime + length);
                        if (e.shift)
                        {
                            var max = pickIndex > 0 ? currentTimes[pickIndex - 1] + Prefs.snapInterval : startTime;
                            newTime = Mathf.Max(newTime, max);
                            foreach (var time in currentTimes.Where(k => k > lastTime))
                            {
                                var index = currentTimes.IndexOf(time);
                                currentTimes[index] += newTime - lastTime;
                            }
                        }
                        currentTimes[pickIndex] = newTime;
                    }

                    //apply the changes when mouse up and deselect key
                    if (eventType == EventType.MouseUp)
                    {
                        GUIUtility.hotControl = 0;
                        pickIndex             = -1;
                        Apply();
                        e.Use();
                    }
                }



                //Multikey selection, dragging and retiming
                if (pickIndex == -1)
                {
                    var retimeInRect  = Rect.MinMaxRect(pixelSelectionRect.xMin, pixelSelectionRect.yMin, pixelSelectionRect.xMin + 4, pixelSelectionRect.yMax);
                    var retimeOutRect = Rect.MinMaxRect(pixelSelectionRect.xMax - 4, pixelSelectionRect.yMin, pixelSelectionRect.xMax, pixelSelectionRect.yMax);

                    var controlID = GUIUtility.GetControlID(FocusType.Passive);
                    var eventType = e.GetTypeForControl(controlID);

                    if (e.rawType == EventType.MouseDown && !rect.Contains(e.mousePosition))
                    {
                        ResetInteraction();
                    }

                    if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition))
                    {
                        //if no rect selection, start one.
                        if (timeSelectionRect == null)
                        {
                            if (e.button == 0)
                            {
                                selectionStartPos = e.mousePosition.x;
                                e.Use();
                            }
                        }
                        else
                        {
                            //if we have a rect and mouse contains it, initialize original values and keys.
                            if (pixelSelectionRect.Contains(e.mousePosition))
                            {
                                prePickTimes          = new List <float>(currentTimes);
                                startDragTime         = (float)PosToTime(e.mousePosition.x);
                                preScaleSelectionRect = timeSelectionRect.Value;
                                rectSelectedIndeces   = new List <int>();
                                var temp = timeSelectionRect.Value;
                                for (var i = 0; i < currentTimes.Count; i++)
                                {
                                    if (currentTimes[i] >= temp.xMin && currentTimes[i] <= temp.xMax)
                                    {
                                        rectSelectedIndeces.Add(i);
                                    }
                                }

                                isRetiming = e.button == 0 && retimeInRect.Contains(e.mousePosition) || retimeOutRect.Contains(e.mousePosition);
                                e.Use();

                                //if we have a rect, but mouse is outside, clear all and reset values.
                            }
                            else
                            {
                                ResetInteraction();
                                e.Use();
                            }
                        }
                    }


                    //create the selection rect
                    if (eventType == EventType.MouseDrag && selectionStartPos != null)
                    {
                        GUIUtility.hotControl = controlID;
                        var a    = PosToTime(selectionStartPos.Value);
                        var b    = PosToTime(e.mousePosition.x);
                        var xMin = Mathf.Min(a, b);
                        var xMax = Mathf.Max(a, b);
                        xMin = Mathf.Max(xMin, startTime);
                        xMax = Mathf.Min(xMax, startTime + length);
                        timeSelectionRect = Mathf.Abs(a - b) >= 0.001f ? Rect.MinMaxRect(xMin, rect.yMin, xMax, rect.yMax) : (Rect?)null;
                    }

                    //draw the selection rect
                    if (timeSelectionRect != null)
                    {
                        EditorGUIUtility.AddCursorRect(retimeInRect, MouseCursor.ResizeHorizontal);
                        EditorGUIUtility.AddCursorRect(retimeOutRect, MouseCursor.ResizeHorizontal);
                        EditorGUIUtility.AddCursorRect(pixelSelectionRect, MouseCursor.Link);
                        GUI.Box(retimeInRect, string.Empty);
                        GUI.Box(retimeOutRect, string.Empty);
                    }

                    //move/retime the selection rect
                    if (eventType == EventType.MouseDrag && timeSelectionRect != null && e.button == 0 && (startDragTime != null || isRetiming))
                    {
                        GUIUtility.hotControl = controlID;
                        var temp        = timeSelectionRect.Value;
                        var pointerTime = PosToTime(e.mousePosition.x);

                        //retime
                        if (isRetiming)
                        {
                            var retimeIn = Mathf.Abs(pointerTime - temp.x) < Mathf.Abs(pointerTime - temp.xMax);
                            if (retimeIn)
                            {
                                temp.xMin = Mathf.Max(pointerTime, 0);
                            }
                            else
                            {
                                temp.xMax = pointerTime;
                            }

                            foreach (var index in rectSelectedIndeces)
                            {
                                var preTime = prePickTimes[index];
                                var norm    = Mathf.InverseLerp(preScaleSelectionRect.xMin, preScaleSelectionRect.xMax, preTime);
                                currentTimes[index] = Mathf.Lerp(temp.xMin, temp.xMax, norm);
                            }

                            //move
                        }
                        else
                        {
                            if (startDragTime != null)
                            {
                                var delta = pointerTime - (float)startDragTime;
                                if (temp.x + delta >= 0)
                                {
                                    foreach (var index in rectSelectedIndeces)
                                    {
                                        currentTimes[index] += delta;
                                    }
                                    temp.x       += delta;
                                    startDragTime = (float)pointerTime;
                                }
                            }
                        }

                        timeSelectionRect = temp;
                    }

                    //Apply all changes and reset values on MouseUp within or outside the rect
                    if (eventType == EventType.MouseUp)
                    {
                        //mouse up when making a selection
                        if (selectionStartPos != null)
                        {
                            GUIUtility.hotControl = 0;
                            selectionStartPos     = null;
                        }

                        //mouse up when dragging or retiming the existing selection
                        if (timeSelectionRect != null && (startDragTime != null || isRetiming))
                        {
                            GUIUtility.hotControl = 0;
                            Apply();
                            isRetiming    = false;
                            startDragTime = null;
                            if (e.button == 0)
                            {
                                rectSelectedIndeces = null;
                            }
                        }
                    }

                    //Context click
                    if (eventType == EventType.ContextClick && rect.Contains(e.mousePosition))
                    {
                        if (pixelSelectionRect.Contains(e.mousePosition))
                        {
                            DoMultiKeyContextMenu(e);
                            e.Use();
                        }
                        else
                        {
                            DoVoidContextMenu(e);
                            e.Use();
                        }
                    }
                }
            }
Exemple #26
0
//show selected clip animated parameters list info
protected void DoParamsInfoGUI(Event e, Rect trackRect, IKeyable keyable, bool showAddPropertyButton)
{
    //bg graphic
    var expansionRect = Rect.MinMaxRect(5, defaultHeight, trackRect.width - 3, finalHeight - 3);

    GUI.color = UnityEditor.EditorGUIUtility.isProSkin? new Color(0.22f, 0.22f, 0.22f) : new Color(0.7f, 0.7f, 0.7f);
    GUI.DrawTexture(expansionRect, Styles.whiteTexture);
    GUI.color = new Color(0, 0, 0, 0.05f);
    GUI.Box(expansionRect, string.Empty, Styles.shadowBorderStyle);
    GUI.color = Color.white;


    //allow resize height
    if (inspectedParameterIndex >= 0)
    {
        var resizeRect = Rect.MinMaxRect(0, finalHeight - 4, trackRect.width, finalHeight);
        UnityEditor.EditorGUIUtility.AddCursorRect(resizeRect, UnityEditor.MouseCursor.ResizeVertical);
        GUI.color = Color.grey;
        GUI.DrawTexture(resizeRect, Styles.whiteTexture);
        GUI.color = Color.white;
        if (e.type == EventType.MouseDown && e.button == 0 && resizeRect.Contains(e.mousePosition))
        {
            isResizingHeight = true; e.Use();
        }
        if (e.type == EventType.MouseDrag && isResizingHeight)
        {
            customHeight += e.delta.y;
        }
        if (e.rawType == EventType.MouseUp)
        {
            isResizingHeight = false;
        }
    }

    proposedHeight = 0f;

    if (((keyable == null) || !ReferenceEquals(keyable.parent, this)) && !ReferenceEquals(keyable, this))
    {
        GUI.Label(expansionRect, "No Clip Selected", Styles.centerLabel);
        inspectedParameterIndex = -1;
        return;
    }

    if (!showAddPropertyButton)
    {
        if (keyable is ActionClip && !(keyable as ActionClip).isValid)
        {
            GUI.Label(expansionRect, "Clip Is Invalid", Styles.centerLabel);
            return;
        }

        if (keyable.animationData == null || !keyable.animationData.isValid)
        {
            if (keyable is ActionClip)
            {
                GUI.Label(expansionRect, "Clip Has No Animatable Parameters", Styles.centerLabel);
                return;
            }
        }
    }

    proposedHeight = defaultHeight + PARAMS_TOP_MARGIN;
    if (keyable.animationData != null && keyable.animationData.animatedParameters != null)
    {
        if (inspectedParameterIndex >= keyable.animationData.animatedParameters.Count)
        {
            inspectedParameterIndex = -1;
        }

        var paramsCount = keyable.animationData.animatedParameters.Count;
        for (var i = 0; i < paramsCount; i++)
        {
            var animParam = keyable.animationData.animatedParameters[i];
            var paramRect = new Rect(expansionRect.xMin + 4, proposedHeight, expansionRect.width - 8, PARAMS_LINE_HEIGHT);
            proposedHeight += PARAMS_LINE_HEIGHT + PARAMS_LINE_MARGIN;

            GUI.color = inspectedParameterIndex == i? new Color(0.5f, 0.5f, 1f, 0.4f) : new Color(0, 0.5f, 0.5f, 0.5f);
            GUI.Box(paramRect, string.Empty, Styles.headerBoxStyle);
            GUI.color = Color.white;

            var paramName = string.Format(" <size=10><color=#252525>{0}</color></size>", animParam.ToString());
            paramName = inspectedParameterIndex == i?string.Format("<b>{0}</b>", paramName) : paramName;

            GUI.Label(paramRect, paramName, Styles.leftLabel);

            var gearRect = new Rect(paramRect.xMax - 16 - 4, paramRect.y, 16, 16);
            gearRect.center = new Vector2(gearRect.center.x, paramRect.y + (paramRect.height / 2) - 1);
            GUI.enabled     = animParam.enabled;
            if (GUI.Button(gearRect, Styles.gearIcon, GUIStyle.none))
            {
                AnimatableParameterEditor.DoParamGearContextMenu(animParam, keyable);
            }
            if (GUI.Button(paramRect, string.Empty, GUIStyle.none))
            {
                inspectedParameterIndex = inspectedParameterIndex == i? -1 : i;
                CurveEditor.FrameAllCurvesOf(animParam);
            }
            GUI.enabled = true;
        }

        proposedHeight += PARAMS_TOP_MARGIN;

        if (inspectedParameterIndex >= 0)
        {
            var controlRect = Rect.MinMaxRect(expansionRect.x + 6, proposedHeight + 5, expansionRect.xMax - 6, proposedHeight + 50);
            var animParam   = keyable.animationData.animatedParameters[inspectedParameterIndex];
            GUILayout.BeginArea(controlRect);
            AnimatableParameterEditor.ShowMiniParameterKeyControls(animParam, keyable);
            GUILayout.EndArea();
            proposedHeight = controlRect.yMax + 10;
        }
    }

    if (showAddPropertyButton && inspectedParameterIndex == -1)
    {
        var buttonRect = Rect.MinMaxRect(expansionRect.x + 6, proposedHeight + 5, expansionRect.xMax - 6, proposedHeight + 25);
        var go         = keyable.animatedParametersTarget as GameObject;
        GUI.enabled = go != null && root.currentTime <= 0;
        if (GUI.Button(buttonRect, "Add Property"))
        {
            EditorTools.ShowAnimatedPropertySelectionMenu(go, AnimatedParameter.supportedTypes, (prop, comp) => {
                        keyable.animationData.TryAddParameter(prop, keyable, comp.transform, go.transform);
                    });
        }
        GUI.enabled    = true;
        proposedHeight = buttonRect.yMax + 10;
    }

    //consume event
    if (e.type == EventType.MouseDown && expansionRect.Contains(e.mousePosition))
    {
        e.Use();
    }
}
        /// <summary>
        ///     Processes the attribute segment
        /// </summary>
        /// <returns>
        ///     true if the attribute was not a dataset attribute.  If the attribute was a dataset attribute, then it can be
        ///     retrieved from the getDatasetAttribute method
        /// </returns>
        private bool ProcessEDIAttributeSegment()
        {
            // TODO Process FNS+ - current line, does this need any processing?

            // Move to the attribute scope line
            if (EDIUtil.AssertPrefix(this._ediDataReader, EdiPrefix.DatasetAttributeScope, false))
            {
                int scope = int.Parse(this._ediDataReader.CurrentLine, CultureInfo.InvariantCulture);

                // 1 = dataset, 4=mix of dimensions, 5=observation
                if (scope == 1)
                {
                    // This is a Dataset attribute which we want to ignore because this reader is passed all the dataset attribtues up front.  
                    // Move to the next line and return false to ensure this is not processed
                    this._ediDataReader.MoveNext();
                    EDIUtil.AssertPrefix(this._ediDataReader, EdiPrefix.DatasetDataAttribute, true);
                    return false;
                }
            }
            else
            {
                this._ediDataReader.MoveBackLine();
            }

            // Move to the dimension/key pointer line
            this.AssertMoveNext();
            EDIUtil.AssertPrefix(this._ediDataReader, EdiPrefix.DatasetDataAttribute, true);
            string currentLine = this._ediDataReader.CurrentLine;
            string[] posKeySplit = EDIUtil.SplitOnPlus(currentLine);

            if (posKeySplit.Length != 2)
            {
                // TODO Exception should be caught and full line + line position put on
                throw new SdmxSyntaxException("Can not parse current line '" + currentLine + "' expecting integer+key example 5+A:B:C:D");
            }

            // TODO These two attributes gives the key of the attribute attachment, if the key is not a full key then it is a group key and the group muse be 
            // determined
            // string lastDimensionPosition = posKeySplit[0];  //TODO What does this mean?  
            string key = posKeySplit[1];

            string[] keySplit = EDIUtil.SplitOnColon(key);
            IList<IKeyValue> keyableKey = new List<IKeyValue>();
            if (keySplit.Length < this._dimensions.Length)
            {
                throw new SdmxSemmanticException("Reported attributes '" + key + "' are less then key length '" + this._dimensions.Length + "' ");
            }

            bool isGroup = false;
            for (int i = 0; i < this._dimensions.Length; i++)
            {
                string val = keySplit[i];
                if (val.Length == 0)
                {
                    isGroup = true;
                }
                else
                {
                    keyableKey.Add(new KeyValueImpl(val, this._dimensions[i]));
                }
            }

            IList<IKeyValue> attributes = this.ProcessAttributeValues();
            this._currentObs = null;

            var obsDateAsSdmxString = this.BuildObsDateAsSdmxString(keySplit, key, isGroup);

            if (isGroup)
            {
                if (obsDateAsSdmxString != null)
                {
                    this._currentKey = new KeyableImpl(this._dataflowObject, this._dataStructureObject, keyableKey, null, this._siblingGroup);
                }
                else
                {
                    this._currentKey = new KeyableImpl(this._dataflowObject, this._dataStructureObject, keyableKey, attributes, this._siblingGroup);
                }
            }
            else
            {
                if (obsDateAsSdmxString != null)
                {
                    // TODO It is not 100% sure what ctor is used in Java. There is a warning there also.
                    this._currentKey = new KeyableImpl(this._dataflowObject, this._dataStructureObject, keyableKey, null);
                    this._currentObs = new ObservationImpl(this._currentKey, obsDateAsSdmxString, null, attributes);
                }
                else
                {
                    // TODO It is not 100% sure what ctor is used in Java. There is a warning there also.
                    this._currentKey = new KeyableImpl(this._dataflowObject, this._dataStructureObject, keyableKey, attributes);
                }
            }

            return true;
        }
        /// <summary>
        ///     Gets a value indicating whether the there are any more datasets in the data source
        /// </summary>
        /// <returns>
        ///     The <see cref="bool" /> .
        /// </returns>
        public bool MoveNextDataset()
        {
            this._currentKey = null;
            this._hasNextObs = true;
            this._obsIndex = -1;
            this._keyableIndex = -1;

            bool moveSuccessful = this.MoveNextDatasetInternal();
            if (moveSuccessful)
            {
                this._datasetIndex++;
                this.DetermineCurrentDataStructure();
            }

            return moveSuccessful;
        }
        /// <summary>
        ///     Gets a value indicating whether the there are any more keys in the dataset
        /// </summary>
        /// <returns>
        ///     The <see cref="bool" /> .
        /// </returns>
        public bool MoveNextKeyable()
        {
            // If the dataset has not been read, then read it!
            if (this._datasetIndex == -1)
            {
                this.MoveNextDataset();
            }

            this._currentKey = null; // Set the current key to null, this is so when the user reads the observation it can generate it on demand 

            // If there is no more information left at all, then we return false
            if (!this._hasNext)
            {
                return false;
            }

            this._hasNextObs = true;
            this._obsIndex = -1;
            this._keyableIndex++;
            return this.MoveNextKeyableInternal();
        }
        /// <summary>
        ///     If this reader is in a series, this will return true if the series has any more observation values.
        /// </summary>
        /// <returns> true if series has more observation values </returns>
        public bool MoveNextObservation()
        {
            this._currentObs = null;

            // If we are at the end of the file, or the observations for the key, then return false, there is no point in processing anything
            if (!this._hasNext && !this._hasNextObs)
            {
                return false;
            }

            this._obsIndex++;

            if (this._currentKey == null)
            {
                this._currentKey = this.CurrentKey;
            }

            this._hasNextObs = this.MoveNextObservationInternal();
            return this._hasNextObs;
        }
 /// <summary>
 ///     Moves the read position back to the start of the Data Set (<see cref="IDataReaderEngine.KeyablePosition" /> moved
 ///     back to -1)
 /// </summary>
 public virtual void Reset()
 {
     this._hasNext = true;
     this._keyableIndex = -1;
     this._datasetIndex = -1;
     this._obsIndex = -1;
     this._currentObs = null;
     this._currentKey = null;
 }
Exemple #32
0
        ///Inline curve editor box
        static void DoCurveBox(AnimatedParameter animParam, IKeyable keyable, bool isRecording)
        {
            var e             = Event.current;
            var keyableLength = keyable.GetLength();
            var keyableTime   = keyable.RootTimeToLocalTime();

            GUILayout.Label("INVISIBLE TEXT", GUILayout.Height(0));
            var lastRect = GUILayoutUtility.GetLastRect();

            GUILayout.Space(250);

            var timeRect = new Rect(0, 0, keyableLength, 0);
            var posRect  = new Rect();

            if (e.type == EventType.Repaint || !fixedCurveRects.TryGetValue(animParam, out posRect))
            {
                posRect = new Rect(lastRect.x, lastRect.yMax + 5, lastRect.width, 240);
                fixedCurveRects[animParam] = posRect;
            }

            GUI.color = EditorGUIUtility.isProSkin ? new Color(0, 0, 0, 0.5f) : new Color(0, 0, 0, 0.3f);
            GUI.Box(posRect, "", (GUIStyle)"textfield");
            GUI.color = Color.white;

            var dragTimeRect = new Rect(posRect.x, posRect.y + 1, posRect.width, 10);

            GUI.Box(dragTimeRect, "");
            if (dragTimeRect.Contains(e.mousePosition))
            {
                EditorGUIUtility.AddCursorRect(dragTimeRect, MouseCursor.SplitResizeLeftRight);
                if (e.type == EventType.MouseDown && e.button == 0)
                {
                    isDraggingTime = true;
                    e.Use();
                }
            }

            if (isDraggingTime)
            {
                var iLerp = Mathf.InverseLerp(posRect.x, posRect.xMax, e.mousePosition.x);
                keyable.root.currentTime = Mathf.Lerp(keyable.startTime, keyable.endTime, iLerp);
            }

            if (e.rawType == EventType.MouseUp)
            {
                isDraggingTime = false;
            }

            if (e.type == EventType.KeyDown && posRect.Contains(e.mousePosition))
            {
                if (e.keyCode == KeyCode.Comma)
                {
                    GUIUtility.keyboardControl = 0;
                    keyable.root.currentTime   = animParam.GetKeyPrevious(keyableTime) + keyable.startTime;
                    e.Use();
                }

                if (e.keyCode == KeyCode.Period)
                {
                    GUIUtility.keyboardControl = 0;
                    keyable.root.currentTime   = animParam.GetKeyNext(keyableTime) + keyable.startTime;
                    Event.current.Use();
                }
            }

            var dopeRect = new Rect(posRect.x, dragTimeRect.yMax + 1, posRect.width, 16);

            Handles.color = Color.black.WithAlpha(0.2f);
            Handles.DrawLine(new Vector2(dopeRect.xMin, dopeRect.yMin), new Vector2(dopeRect.xMax, dopeRect.yMin));
            Handles.DrawLine(new Vector2(dopeRect.xMin, dopeRect.yMax), new Vector2(dopeRect.xMax, dopeRect.yMax));
            Handles.color = Color.white;

            DopeSheetEditor.DrawDopeSheet(animParam, keyable, dopeRect, 0, keyableLength);

            var curvesRect = new Rect(posRect.x, dopeRect.yMax, posRect.width, posRect.height - dopeRect.height - dragTimeRect.height);

            CurveEditor.DrawCurves(animParam, keyable, curvesRect, timeRect);

            if (isRecording)
            {
                var iLerp = Mathf.InverseLerp(keyable.startTime, keyable.endTime, keyable.root.currentTime);
                var lerp  = Mathf.Lerp(posRect.x, posRect.xMax, iLerp);
                var a     = new Vector3(lerp, posRect.y, 0);
                var b     = new Vector3(lerp, posRect.yMax, 0);
                Handles.color = EditorGUIUtility.isProSkin ? Slate.Styles.recordingColor : Color.red;
                Handles.DrawAAPolyLine(a, b);
                Handles.color = Color.white;
            }
        }
        /// <summary>
        ///     Processes the EDI data line.
        /// </summary>
        /// <exception cref="SdmxSemmanticException">
        ///     Reported key ' <c> firstDataLine </c> ' is less then key length '
        ///     <c> dimensions.Length </c> '
        /// </exception>
        private void ProcessEdiDataLine()
        {
            this._currentObsPos = -1;

            // Observations becomes all of the observations for the series, unfortunately the first item in the array is the key & observation value
            // So we need to extract the first value and process it, and then replace the first value with the observation minus the key
            this._observations = EDIUtil.SplitOnPlus(this._ediDataReader.CurrentLine);
            string firstDataLine = this._observations[0];

            string[] dataLineSplit = EDIUtil.SplitOnColon(firstDataLine);

            // Get the series key from the ARR segment. 
            // Note: if this is a partial key, then it is assumed to be the deletion of the sibling group, as per the EDI Specification:
            // 2520 Deletion of a group of sibling series;
            // 2521 Rule: dates/periods/time ranges cannot be present in segment;
            // 2522 e.g. if :BE:XXX:YYY is the key of the sibling group (second position: frequency wildcarded: for
            // 2523 any frequency), then the segment
            // 2524 ARR++:BE:XXX:YYY'
            // 2525 implies the deletion of all series of the group (e.g. Q:BE:XXX:YYY and M:BE:XXX:YYY) and all
            // 2526 their attribute values at all
            var seriesKey = new List<IKeyValue>();
            if (dataLineSplit.Length < this._dimensions.Length)
            {
                throw new SdmxSemmanticException("Reported key '" + firstDataLine + "' is less then key length '" + this._dimensions.Length + "' ");
            }

            bool isGroup = false;
            for (int i = 0; i < this._dimensions.Length; i++)
            {
                string val = dataLineSplit[i];
                if (val.Length == 0)
                {
                    isGroup = true;
                }
                else
                {
                    seriesKey.Add(new KeyValueImpl(val, this._dimensions[i]));
                }
            }

            // observations[0] contained both the series key (or partial key) and the first observation, we want to extract from this ONLY the observation (not the series Key)
            // and store the in the first observation location observations[0] 
            this._observations[0] = null;
            string firstObservation = string.Empty;
            for (int i = this._dimensions.Length + 2; i < dataLineSplit.Length; i++)
            {
                firstObservation += dataLineSplit[i];
                if (dataLineSplit.Length > (i + 1))
                {
                    firstObservation += ":";
                }
            }

            if (ObjectUtil.ValidString(firstObservation))
            {
                this._observations[0] = firstObservation;
            }
            else
            {
                this._observations = null;
            }

            // At this point the observations array will have been populated. Validate it.
            this.ValidateObservation(this._observations);

            this.ProcessObservations(dataLineSplit);

            TimeFormat timeFormat = this._ediTimeFormat == EdiTimeFormat.None ? null : this._ediTimeFormat.GetSdmxTimeFormat();
            if (isGroup)
            {
                this._currentKey = new KeyableImpl(this._dataflowObject, this._dataStructureObject, seriesKey, null, this._siblingGroup);
            }
            else
            {
                this._currentKey = new KeyableImpl(this._dataflowObject, this._dataStructureObject, seriesKey, null, timeFormat);
            }
        }
Exemple #34
0
protected void DoClipCurves(Event e, Rect posRect, Rect timeRect, System.Func <float, float> TimeToPos, IKeyable keyable)
{
    //track expanded bg
    GUI.color = new Color(0, 0, 0, 0.08f);
    GUI.Box(posRect, string.Empty, Styles.timeBoxStyle);
    GUI.color = Color.white;

    if (((keyable == null) || !ReferenceEquals(keyable.parent, this)) && !ReferenceEquals(keyable, this))
    {
        GUI.color = new Color(1, 1, 1, 0.3f);
        GUI.Label(posRect, "Select a Clip of this Track to view it's Animated Parameters here", Styles.centerLabel);
        GUI.color = Color.white;
        return;
    }

    var finalPosRect  = posRect;
    var finalTimeRect = timeRect;

    //adjust rects
    if (keyable is ActionClip)
    {
        finalPosRect.xMin  = Mathf.Max(posRect.xMin, TimeToPos(keyable.startTime));
        finalPosRect.xMax  = Mathf.Min(posRect.xMax, TimeToPos(keyable.endTime));
        finalTimeRect.xMin = Mathf.Max(timeRect.xMin, keyable.startTime) - keyable.startTime;
        finalTimeRect.xMax = Mathf.Min(timeRect.xMax, keyable.endTime) - keyable.startTime;
    }

    //add some top/bottom margins
    finalPosRect.yMin += 1;
    finalPosRect.yMax -= 3;
    finalPosRect.width = Mathf.Max(finalPosRect.width, 5);

    //dark bg
    GUI.color = new Color(0.1f, 0.1f, 0.1f, 0.5f);
    GUI.DrawTexture(posRect, Styles.whiteTexture);
    GUI.color = Color.white;


    //out of view range
    if (keyable is ActionClip)
    {
        if (keyable.startTime > timeRect.xMax || keyable.endTime < timeRect.xMin)
        {
            return;
        }
    }


    //keyable bg
    GUI.color = UnityEditor.EditorGUIUtility.isProSkin? new Color(0.25f, 0.25f, 0.25f, 0.9f) : new Color(0.7f, 0.7f, 0.7f, 0.9f);
    GUI.Box(finalPosRect, string.Empty, Styles.clipBoxFooterStyle);
    GUI.color = Color.white;

    //if too small do nothing more
    if (finalPosRect.width <= 5)
    {
        return;
    }

    if (keyable is ActionClip && !(keyable as ActionClip).isValid)
    {
        GUI.Label(finalPosRect, "Clip Is Invalid", Styles.centerLabel);
        return;
    }

    if (keyable.animationData == null || !keyable.animationData.isValid)
    {
        if (keyable is ActionClip)
        {
            GUI.Label(finalPosRect, "Clip has no Animatable Parameters", Styles.centerLabel);
        }
        else
        {
            GUI.Label(finalPosRect, "Track has no Animated Properties. You can add some on the left side", Styles.centerLabel);
        }
        return;
    }

    if (inspectedParameterIndex >= keyable.animationData.animatedParameters.Count)
    {
        inspectedParameterIndex = -1;
    }


    //vertical guides from params to dopesheet
    if (inspectedParameterIndex == -1)
    {
        var yPos = PARAMS_TOP_MARGIN;
        for (var i = 0; i < keyable.animationData.animatedParameters.Count; i++)
        {
            // var animParam = keyable.animationData.animatedParameters[i];
            var paramRect = new Rect(0, posRect.yMin + yPos, finalPosRect.xMin - 2, PARAMS_LINE_HEIGHT);
            yPos           += PARAMS_LINE_HEIGHT + PARAMS_LINE_MARGIN;
            paramRect.yMin += 1f;
            paramRect.yMax -= 1f;
            GUI.color       = new Color(0, 0.5f, 0.5f, 0.1f);
            GUI.DrawTexture(paramRect, Styles.whiteTexture);
            GUI.color = Color.white;
        }
    }


    //begin in group and neutralize rect
    GUI.BeginGroup(finalPosRect);
    finalPosRect = new Rect(0, 0, finalPosRect.width, finalPosRect.height);

    if (inspectedParameterIndex == -1)
    {
        var yPos = PARAMS_TOP_MARGIN;
        for (var i = 0; i < keyable.animationData.animatedParameters.Count; i++)
        {
            var animParam = keyable.animationData.animatedParameters[i];
            var paramRect = new Rect(finalPosRect.xMin, finalPosRect.yMin + yPos, finalPosRect.width, PARAMS_LINE_HEIGHT);
            yPos           += PARAMS_LINE_HEIGHT + PARAMS_LINE_MARGIN;
            paramRect.yMin += 1f;
            paramRect.yMax -= 1f;
            GUI.color       = new Color(1, 1, 1, 0.3f);
            GUI.Box(paramRect, string.Empty);
            GUI.color = Color.white;

            if (animParam.enabled)
            {
                DopeSheetEditor.DrawDopeSheet(animParam, keyable, paramRect, finalTimeRect.x, finalTimeRect.width, true);
            }
            else
            {
                GUI.color = new Color(0, 0, 0, 0.2f);
                GUI.DrawTextureWithTexCoords(paramRect, Styles.stripes, new Rect(0, 0, paramRect.width / 7, paramRect.height / 7));
                GUI.color = Color.white;
            }
        }
    }

    if (inspectedParameterIndex >= 0)
    {
        var animParam = keyable.animationData.animatedParameters[inspectedParameterIndex];
        var dopeRect  = finalPosRect;
        dopeRect.y     += 4f;
        dopeRect.height = 16f;
        GUI.color       = new Color(1, 1, 1, 0.3f);
        GUI.Box(dopeRect, string.Empty);
        GUI.color = Color.white;
        DopeSheetEditor.DrawDopeSheet(animParam, keyable, dopeRect, finalTimeRect.x, finalTimeRect.width, true);
        var curveRect = finalPosRect;
        curveRect.yMin = dopeRect.yMax + 4;
        CurveEditor.DrawCurves(animParam, keyable, curveRect, finalTimeRect);
    }

    //consume event
    if (e.type == EventType.MouseDown && finalPosRect.Contains(e.mousePosition))
    {
        e.Use();
    }

    GUI.EndGroup();

/*
 *                      //darken out of clip range time
 *                      //will use if I make curve editing full-width
 *                      if (Prefs.fullWidthCurveEditing){
 *                              var darkBefore = Rect.MinMaxRect( posRect.xMin, posRect.yMin, Mathf.Max(posRect.xMin, TimeToPos(keyable.startTime)), posRect.yMax );
 *                              var darkAfter = Rect.MinMaxRect( Mathf.Min(posRect.xMax, TimeToPos(keyable.endTime)), posRect.yMin, posRect.xMax, posRect.yMax );
 *                              GUI.color = new Color(0.1f,0.1f,0.1f,0.6f);
 *                              GUI.DrawTexture(darkBefore, Styles.whiteTexture);
 *                              GUI.DrawTexture(darkAfter, Styles.whiteTexture);
 *                              GUI.color = Color.white;
 *                      }
 */
}
Exemple #35
0
 ///Try add parameter in animation data of keyable
 public static bool TryAddParameter(this IKeyable keyable, Type type, string memberPath, string transformPath)
 {
     return(keyable.animationData.TryAddParameter(keyable, type, memberPath, transformPath));
 }
Exemple #36
0
        public static void ShowParameter(AnimatedParameter animParam, IKeyable keyable, SerializedProperty serializedProperty = null)
        {
            if (!animParam.isValid)
            {
                GUILayout.Label("Animatable Parameter is invalid");
                return;
            }

            var e                = Event.current;
            var keyableLength    = keyable.endTime - keyable.startTime;
            var rootTime         = keyable.root.currentTime;
            var localTime        = Mathf.Clamp(rootTime - keyable.startTime, 0, keyableLength);
            var isRecording      = rootTime >= keyable.startTime && rootTime <= keyable.endTime && rootTime > 0;
            var foldOut          = EditorTools.GetObjectFoldOut(animParam);
            var hasAnyKey        = animParam.HasAnyKey();
            var hasKeyNow        = animParam.HasKey(localTime);
            var hasChanged       = animParam.HasChanged();
            var parameterEnabled = animParam.enabled;
            var lastRect         = new Rect();

            GUI.backgroundColor = new Color(0, 0.4f, 0.4f, 0.5f);
            GUILayout.BeginVertical(Slate.Styles.headerBoxStyle);
            GUI.backgroundColor = Color.white;

            GUILayout.BeginHorizontal();


            var sFold = foldOut? "▼" : "▶";
            var sName = animParam.ToString();


            GUI.backgroundColor = hasAnyKey && parameterEnabled? new Color(1, 0.6f, 0.6f) : Color.white;
            GUI.backgroundColor = hasAnyKey && parameterEnabled && isRecording? Slate.Styles.recordingColor : GUI.backgroundColor;
            GUILayout.Label(sFold, GUILayout.Width(13));
            lastRect    = GUILayoutUtility.GetLastRect();
            GUI.enabled = !animParam.isExternal || isRecording;

            DoParameterField(string.Format("<b>{0}</b>", sName), animParam, localTime);

            GUI.enabled         = true;
            GUI.backgroundColor = Color.white;


            EditorGUIUtility.AddCursorRect(lastRect, MouseCursor.Link);
            if (e.type == EventType.MouseDown && e.button == 0 && lastRect.Contains(e.mousePosition))
            {
                EditorTools.SetObjectFoldOut(animParam, !foldOut);
                e.Use();
            }



            GUI.enabled = hasAnyKey && parameterEnabled;
            if (GUILayout.Button(Slate.Styles.previousKeyIcon, GUIStyle.none, GUILayout.Height(20), GUILayout.Width(16)))
            {
                keyable.root.currentTime = animParam.GetKeyPrevious(localTime) + keyable.startTime;
            }
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);


            GUI.enabled = parameterEnabled;
            GUI.color   = hasKeyNow && parameterEnabled? new Color(1, 0.3f, 0.3f) : Color.white;
            GUI.color   = hasAnyKey && hasChanged? Color.green : GUI.color;
            if (GUILayout.Button(Slate.Styles.keyIcon, GUIStyle.none, GUILayout.Height(20), GUILayout.Width(16)))
            {
                if (e.alt)                  //temporary solution
                {
                    animParam.scriptExpression = "value";
                    EditorTools.SetObjectFoldOut(animParam, true);
                }
                else
                {
                    if (!hasKeyNow || hasChanged)
                    {
                        animParam.SetKeyCurrent(localTime);
                    }
                    else
                    {
                        animParam.RemoveKey(localTime);
                    }
                }
            }
            GUI.color = Color.white;
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);


            GUI.enabled = hasAnyKey && parameterEnabled;
            if (GUILayout.Button(Slate.Styles.nextKeyIcon, GUIStyle.none, GUILayout.Height(20), GUILayout.Width(16)))
            {
                keyable.root.currentTime = animParam.GetKeyNext(localTime) + keyable.startTime;
            }
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);

            GUILayout.Space(2);

            // GUI.enabled = (hasAnyKey && parameterEnabled) || animParam.isExternal;
            GUI.enabled = parameterEnabled;
            if (GUILayout.Button(Slate.Styles.gearIcon, GUIStyle.none, GUILayout.Height(20), GUILayout.Width(16)))
            {
                DoParamGearContextMenu(animParam, keyable);
            }
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);

            GUI.enabled = true;
            GUILayout.EndHorizontal();

            //...
            GUILayout.EndVertical();

            if (EditorGUILayout.BeginFadeGroup(EditorTools.GetObjectFoldOutFaded(animParam)))
            {
                GUI.color = new Color(0.5f, 0.5f, 0.5f, 0.3f);
                GUILayout.BeginVertical(Slate.Styles.clipBoxFooterStyle);
                GUI.color = Color.white;

#if SLATE_USE_EXPRESSIONS
                GUILayout.BeginHorizontal();
                var exp = animParam.scriptExpression;
                if (!string.IsNullOrEmpty(exp))
                {
                    exp = EditorGUILayout.TextArea(exp);
                    animParam.scriptExpression = exp;
                }
                if (GUILayout.Button("f", GUILayout.Width(20)))
                {
                    var menu = GetExpressionEnvirontmentMenu(animParam.GetExpressionEnvironment(), (template) => { animParam.scriptExpression = template; });
                    menu.ShowAsContext();
                }
                GUILayout.EndHorizontal();

                if (animParam.compileException != null)
                {
                    EditorGUILayout.HelpBox(animParam.compileException.Message, MessageType.Error);
                }
#endif

                string info = null;
                if (!parameterEnabled)
                {
                    info = "Parameter is disabled or overriden.";
                }

                if (info == null && !hasAnyKey)
                {
                    info = "Parameter is not yet animated. You can make it so by creating the first key.";
                }

                if (info == null && keyableLength == 0 && hasAnyKey)
                {
                    info = "Length of Clip is zero. Can not display Curve Editor.";
                }

                if (info == null && animParam.isExternal && !isRecording)
                {
                    info = "This Parameter can only be edited when time is within the clip range.";
                }

                if (info != null)
                {
                    GUILayout.Label(info);
                }
                else
                {
                    DoCurveBox(animParam, keyable, isRecording);
                }

                GUILayout.EndVertical();
                GUILayout.Space(5);
            }
            else
            {
#if SLATE_USE_EXPRESSIONS
                if (!string.IsNullOrEmpty(animParam.scriptExpression))
                {
                    GUI.color = new Color(0.5f, 0.5f, 0.5f, 0.3f);
                    GUILayout.BeginHorizontal(Styles.clipBoxFooterStyle);
                    GUI.color = Color.white;
                    GUILayout.Space(10);
                    // GUILayout.Box(Styles.expressionIcon, GUIStyle.none, GUILayout.Width(16), GUILayout.Height(16));
                    GUILayout.Label(string.Format("<b>= </b><size=9>{0}</size>", animParam.scriptExpression));
                    GUILayout.EndHorizontal();
                }
#endif
            }

            EditorGUILayout.EndFadeGroup();
        }
Exemple #37
0
            ///Display curves that belong to serializeContext and transformContext parent, at time and with timeSpan.
            public void Draw3DCurve(IAnimatableData animatable, IKeyable keyable, Transform transformContext, float time, float timeSpan = 50f)
            {
                this.animatable = animatable;
                // this.keyable = keyable;

                var curves = animatable.GetCurves();

                if (curves == null || curves.Length != 3)
                {
                    return;
                }

                var curveX = curves[0];
                var curveY = curves[1];
                var curveZ = curves[2];

                if (curveX.length < 2 || curveY.length < 2 || curveZ.length < 2)
                {
                    return;
                }

                if (curveX.length != curveY.length || curveY.length != curveZ.length)
                {
                    return;
                }


                var serializeContext = keyable as Object;
                var e = Event.current;

                var start = (float)Mathf.FloorToInt(time - (timeSpan / 2));
                var end   = (float)Mathf.CeilToInt(time + (timeSpan / 2));

                start = Mathf.Max(start, Mathf.Min(curveX[0].time, curveY[0].time, curveZ[0].time));
                end   = Mathf.Min(end, Mathf.Max(curveX[curveX.length - 1].time, curveY[curveY.length - 1].time, curveZ[curveZ.length - 1].time));

                if (curveX.length != lastCurveLength)
                {
                    lastCurveLength = curveX.length;
                    kIndex          = -1;
                }

                //1. Keyframes.
                for (var k = 0; k < curveX.length; k++)
                {
                    EditorGUI.BeginChangeCheck();
                    var forceChanged = false;

                    var keyX = curveX[k];
                    var keyY = curveY[k];
                    var keyZ = curveZ[k];

                    if (keyX.time < start)
                    {
                        continue;
                    }
                    if (keyX.time > end)
                    {
                        break;
                    }

                    var tangentModeX     = CurveUtility.GetKeyTangentMode(keyX);
                    var tangentModeY     = CurveUtility.GetKeyTangentMode(keyY);
                    var tangentModeZ     = CurveUtility.GetKeyTangentMode(keyZ);
                    var haveSameTangents = tangentModeX == tangentModeY && tangentModeY == tangentModeZ;
                    var tangentMode      = haveSameTangents ? tangentModeX : TangentMode.Editable;
                    var isBroken         = CurveUtility.GetKeyBroken(keyX) && CurveUtility.GetKeyBroken(keyY) && CurveUtility.GetKeyBroken(keyZ);

                    var pos = new Vector3(keyX.value, keyY.value, keyZ.value);

                    if (transformContext != null)
                    {
                        pos = transformContext.TransformPoint(pos);
                    }

                    Handles.Label(pos, keyX.time.ToString("0.00"));

                    ///MOUSE EVENTS
                    var screenPos = HandleUtility.WorldToGUIPoint(pos);
                    if (((Vector2)screenPos - e.mousePosition).magnitude < 10)
                    {
                        if (e.type == EventType.MouseDown)
                        {
                            if (e.button == 0 && kIndex != k)
                            {
                                kIndex = k;
                                GUIUtility.hotControl = 0;
                                SceneView.RepaintAll();
                                e.Use();
                            }

                            if (e.button == 1 && kIndex == k)
                            {
                                var menu = new GenericMenu();
                                menu.AddItem(new GUIContent("Jump Time Here"), false, () => { keyable.root.currentTime = curveX[kIndex].time + keyable.startTime; });
                                menu.AddItem(new GUIContent("Smooth"), tangentMode == TangentMode.Smooth, () => { contextAction = ContextAction.SetTangentMode; contextTangentMode = TangentMode.Smooth; });
                                menu.AddItem(new GUIContent("Linear"), tangentMode == TangentMode.Linear, () => { contextAction = ContextAction.SetTangentMode; contextTangentMode = TangentMode.Linear; });
                                menu.AddItem(new GUIContent("Constant"), tangentMode == TangentMode.Constant, () => { contextAction = ContextAction.SetTangentMode; contextTangentMode = TangentMode.Constant; });
                                menu.AddItem(new GUIContent("Editable"), tangentMode == TangentMode.Editable, () => { contextAction = ContextAction.SetTangentMode; contextTangentMode = TangentMode.Editable; });
                                if (tangentMode == TangentMode.Editable)
                                {
                                    menu.AddItem(new GUIContent("Tangents/Connected"), !isBroken, () => { contextAction = ContextAction.SetBrokenMode; contextBrokenMode = false; });
                                    menu.AddItem(new GUIContent("Tangents/Broken"), isBroken, () => { contextAction = ContextAction.SetBrokenMode; contextBrokenMode = true; });
                                }
                                menu.AddSeparator("/");
                                menu.AddItem(new GUIContent("Delete"), false, () => { contextAction = ContextAction.Delete; });
                                menu.ShowAsContext();
                                e.Use();
                            }
                        }
                    }

                    ///APPLY CONTEXT ACTIONS
                    if (contextAction != ContextAction.None && k == kIndex)
                    {
                        var _contextAction = contextAction;
                        contextAction = ContextAction.None;
                        forceChanged  = true;
                        if (_contextAction == ContextAction.SetBrokenMode)
                        {
                            Undo.RecordObject(serializeContext, "Animation Curve Change");
                            curveX.SetKeyBroken(kIndex, contextBrokenMode);
                            curveY.SetKeyBroken(kIndex, contextBrokenMode);
                            curveZ.SetKeyBroken(kIndex, contextBrokenMode);

                            NotifyChange();
                            return;
                        }

                        if (_contextAction == ContextAction.SetTangentMode)
                        {
                            Undo.RecordObject(serializeContext, "Animation Curve Change");
                            curveX.SetKeyTangentMode(kIndex, contextTangentMode);
                            curveY.SetKeyTangentMode(kIndex, contextTangentMode);
                            curveZ.SetKeyTangentMode(kIndex, contextTangentMode);

                            NotifyChange();
                            return;
                        }

                        if (_contextAction == ContextAction.Delete)
                        {
                            Undo.RecordObject(serializeContext, "Animation Curve Change");
                            curveX.RemoveKey(k);
                            curveY.RemoveKey(k);
                            curveZ.RemoveKey(k);
                            kIndex = -1;

                            NotifyChange();
                            return;
                        }
                    }


                    ///POSITION
                    var pointSize = HandleUtility.GetHandleSize(pos) * 0.05f;
                    var newValue  = pos;
                    if (kIndex == k)
                    {
                        if (Tools.current == Tool.Move)
                        {
                            newValue = Handles.PositionHandle(pos, Quaternion.identity);
                        }
                        else
                        {
                            newValue = Handles.FreeMoveHandle(pos, Quaternion.identity, pointSize, Vector3.zero, Handles.RectangleCap);
                        }
                    }
                    var cam = SceneView.lastActiveSceneView.camera;
                    Handles.RectangleCap(0, pos, cam.transform.rotation, pointSize);

                    if (transformContext != null)
                    {
                        newValue = transformContext.InverseTransformPoint(newValue);
                    }

                    keyX.value = newValue.x;
                    keyY.value = newValue.y;
                    keyZ.value = newValue.z;


                    ///TANGENTS
                    if (haveSameTangents && tangentMode == TangentMode.Editable)
                    {
                        if (kIndex == k)
                        {
                            if (k != 0)
                            {
                                var inHandle = new Vector3(-keyX.inTangent, -keyY.inTangent, -keyZ.inTangent);
                                inHandle /= HANDLE_DISTANCE_COMPENSATION;
                                inHandle  = newValue + inHandle;
                                if (transformContext != null)
                                {
                                    inHandle = transformContext.TransformPoint(inHandle);
                                }
                                var handleSize  = HandleUtility.GetHandleSize(inHandle) * 0.05f;
                                var newInHandle = Handles.FreeMoveHandle(inHandle, Quaternion.identity, handleSize, Vector3.zero, Handles.CircleCap);
                                Handles.DrawLine(pos, newInHandle);
                                if (transformContext != null)
                                {
                                    newInHandle = transformContext.InverseTransformPoint(newInHandle);
                                }

                                newInHandle   -= newValue;
                                newInHandle   *= HANDLE_DISTANCE_COMPENSATION;
                                keyX.inTangent = -newInHandle.x;
                                keyY.inTangent = -newInHandle.y;
                                keyZ.inTangent = -newInHandle.z;
                                if (!isBroken)
                                {
                                    keyX.outTangent = keyX.inTangent;
                                    keyY.outTangent = keyY.inTangent;
                                    keyZ.outTangent = keyZ.inTangent;
                                }
                            }

                            if (k < curveX.length - 1)
                            {
                                var outHandle = new Vector3(keyX.outTangent, keyY.outTangent, keyZ.outTangent);
                                outHandle /= HANDLE_DISTANCE_COMPENSATION;
                                outHandle  = newValue + outHandle;
                                if (transformContext != null)
                                {
                                    outHandle = transformContext.TransformPoint(outHandle);
                                }
                                var handleSize   = HandleUtility.GetHandleSize(outHandle) * 0.05f;
                                var newOutHandle = Handles.FreeMoveHandle(outHandle, Quaternion.identity, handleSize, Vector3.zero, Handles.CircleCap);
                                Handles.DrawLine(pos, newOutHandle);
                                if (transformContext != null)
                                {
                                    newOutHandle = transformContext.InverseTransformPoint(newOutHandle);
                                }
                                newOutHandle   -= newValue;
                                newOutHandle   *= HANDLE_DISTANCE_COMPENSATION;
                                keyX.outTangent = newOutHandle.x;
                                keyY.outTangent = newOutHandle.y;
                                keyZ.outTangent = newOutHandle.z;
                                if (!isBroken)
                                {
                                    keyX.inTangent = keyX.outTangent;
                                    keyY.inTangent = keyY.outTangent;
                                    keyZ.inTangent = keyZ.outTangent;
                                }
                            }
                        }
                    }

                    ///APPLY
                    if (EditorGUI.EndChangeCheck() || forceChanged)
                    {
                        Undo.RecordObject(serializeContext, "Animation Curve Change");
                        curveX.MoveKey(k, keyX);
                        curveY.MoveKey(k, keyY);
                        curveZ.MoveKey(k, keyZ);
                        EditorUtility.SetDirty(serializeContext);
                        NotifyChange();
                    }
                }


                ///2. Motion Path
                Handles.color = Prefs.motionPathsColor;
                var lastDrawnPos = Vector3.zero;

                for (var t = start; t <= end; t += DRAW_RESOLUTION)
                {
                    var pos     = new Vector3(curveX.Evaluate(t), curveY.Evaluate(t), curveZ.Evaluate(t));
                    var nextPos = new Vector3(curveX.Evaluate(t + DRAW_RESOLUTION), curveY.Evaluate(t + DRAW_RESOLUTION), curveZ.Evaluate(t + DRAW_RESOLUTION));

                    if (transformContext != null)
                    {
                        pos     = transformContext.TransformPoint(pos);
                        nextPos = transformContext.TransformPoint(nextPos);
                    }

                    if ((pos - lastDrawnPos).magnitude > DRAW_THRESHOLD)
                    {
                        lastDrawnPos = pos;
                        Handles.SphereCap(0, pos, Quaternion.identity, 0.02f);
                        Handles.DrawLine(pos, nextPos);
                    }
                }
                Handles.color = Color.white;


                ///3. GUI
                if (kIndex >= 0)
                {
                    var guiRect = new Rect(Screen.width - 300, Screen.height - 170, 280, 130);
                    var kx      = curveX[kIndex];
                    var ky      = curveY[kIndex];
                    var kz      = curveZ[kIndex];
                    EditorGUI.BeginChangeCheck();
                    {
                        Handles.BeginGUI();
                        GUILayout.BeginArea(guiRect);
                        EditorTools.BeginBody("Keyframe Parameters");
                        kx.value = EditorGUILayout.FloatField("X", kx.value);
                        ky.value = EditorGUILayout.FloatField("Y", ky.value);
                        kz.value = EditorGUILayout.FloatField("Z", kz.value);

                        GUI.enabled = CurveUtility.GetKeyTangentMode(kx) == TangentMode.Editable;
                        var inTangent = new Vector3(kx.inTangent, ky.inTangent, kz.inTangent);
                        inTangent    = EditorGUILayout.Vector3Field("", inTangent);
                        kx.inTangent = inTangent.x;
                        ky.inTangent = inTangent.y;
                        kz.inTangent = inTangent.z;

                        GUI.enabled = CurveUtility.GetKeyBroken(kx);
                        var outTangent = new Vector3(kx.outTangent, ky.outTangent, kz.outTangent);
                        outTangent    = EditorGUILayout.Vector3Field("", outTangent);
                        kx.outTangent = outTangent.x;
                        ky.outTangent = outTangent.y;
                        kz.outTangent = outTangent.z;

                        GUI.enabled = true;

                        EditorTools.EndBody();
                        GUILayout.EndArea();
                        Handles.EndGUI();
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        Undo.RecordObject(serializeContext, "Animation Curve Change");
                        curveX.MoveKey(kIndex, kx);
                        curveY.MoveKey(kIndex, ky);
                        curveZ.MoveKey(kIndex, kz);
                        EditorUtility.SetDirty(serializeContext);
                        NotifyChange();
                    }
                }


                /*
                 *              for (var k = 0; k < curveX.length - 1; k++){
                 *                  var keyX = curveX[k];
                 *                  var keyY = curveY[k];
                 *                  var keyZ = curveZ[k];
                 *                  var nextKeyX = curveX[k+1];
                 *                  var nextKeyY = curveY[k+1];
                 *                  var nextKeyZ = curveZ[k+1];
                 *
                 *                  var t = new Vector3(keyX.time, keyY.time, keyZ.time);
                 *                  var nextT = new Vector3(nextKeyX.time, nextKeyY.time, nextKeyZ.time);
                 *
                 *                  var tangent = new Vector3( keyX.outTangent, keyY.outTangent, keyZ.outTangent );
                 *                  var nextTangent = new Vector3( nextKeyX.inTangent, nextKeyY.inTangent, nextKeyZ.inTangent );
                 *
                 *                  var pos = new Vector3( keyX.value, keyY.value, keyZ.value );
                 *                  var nextPos = new Vector3( nextKeyX.value, nextKeyY.value, nextKeyZ.value );
                 *
                 *                  if (transformContext != null){
                 *                      pos = transformContext.TransformPoint(pos);
                 *                      nextPos = transformContext.TransformPoint(nextPos);
                 *                  }
                 *
                 *                  var num = (nextT - t) * 0.333333f;
                 *                  var tangentPos = new Vector3( pos.x + num.x * tangent.x, pos.y + num.y * tangent.y, pos.z + num.z * tangent.z );
                 *                  var nextTangentPos = new Vector3( nextPos.x - num.x * nextTangent.x, nextPos.y - num.y * nextTangent.y, nextPos.z - num.z * nextTangent.z );
                 *
                 *                  Handles.DrawBezier(pos, nextPos, tangentPos, nextTangentPos, Prefs.motionPathsColor, null, 1.5f);
                 *              }
                 */
            }
        /// <summary>
        /// Initializes a new instance of the <see cref="ObservationImpl"/> class.
        /// </summary>
        /// <param name="obsTime">
        /// The obs time 0. 
        /// </param>
        /// <param name="obsValue">
        /// The obs value 1. 
        /// </param>
        /// <param name="attributes">
        /// The attributes 2. 
        /// </param>
        /// <param name="crossSectionValue">
        /// The cross section value 3. 
        /// </param>
        /// <param name="annotations">
        /// The cross section value 3. 
        /// </param>
        public ObservationImpl(IKeyable seriesKey,
            string obsTime, string obsValue, IList<IKeyValue> attributes, IKeyValue crossSectionValue, 
            params IAnnotation[] annotations)
        {
            this._seriesKey = seriesKey;
            this.obsValue = obsValue;
            this.obsTime = obsTime;

            if (seriesKey == null)
                throw new ArgumentException("Series Key can not be null");

            if (attributes != null)
            {
                this.attributes = new List<IKeyValue>(attributes);

                foreach (IKeyValue currentKv in attributes)
                {
                    this.attributeMap.Add(currentKv.Concept, currentKv);
                }
            }

            if(annotations != null) 
            {
			   foreach(IAnnotation currentAnnotation in annotations)
               {
				  this.annotations.Add(currentAnnotation);
			   }
		    }

            this.crossSectionValue = crossSectionValue;
            this.isCrossSection = crossSectionValue != null;
        }