///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); } }
///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); }
///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); } }
///---------------------------------------------------------------------------------------------- ///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]); }
//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; }
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); } } }
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); }
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); }
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); }
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); }
///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."); }
///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); }
///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(); }
///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; }
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(); } } } }
//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; }
///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); } }
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; * } */ }
///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)); }
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(); }
///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; }