@@ -94,6 +94,34 @@ public Selection(SerializedProperty curve, int keyframeIndex, Keyframe? keyframe
9494 this . keyframe = keyframe ;
9595 }
9696 }
97+
98+ internal struct MenuAction
99+ {
100+ internal SerializedProperty curve ;
101+ internal int index ;
102+ internal Vector3 position ;
103+
104+ internal MenuAction ( SerializedProperty curve )
105+ {
106+ this . curve = curve ;
107+ this . index = - 1 ;
108+ this . position = Vector3 . zero ;
109+ }
110+
111+ internal MenuAction ( SerializedProperty curve , int index )
112+ {
113+ this . curve = curve ;
114+ this . index = index ;
115+ this . position = Vector3 . zero ;
116+ }
117+
118+ internal MenuAction ( SerializedProperty curve , Vector3 position )
119+ {
120+ this . curve = curve ;
121+ this . index = - 1 ;
122+ this . position = position ;
123+ }
124+ }
97125 #endregion
98126
99127 #region Fields & properties
@@ -392,14 +420,34 @@ void OnCurveGUI(Rect rect, SerializedProperty curve, CurveState state)
392420 EditMoveTangent ( animCurve , keys , k , m_TangentEditMode , e . shift || ! ( alreadyBroken || e . control ) ) ;
393421 }
394422
395- // Keyframe selection
423+ // Keyframe selection & context menu
396424 if ( e . type == EventType . mouseDown && rect . Contains ( e . mousePosition ) )
397425 {
398426 if ( hitRect . Contains ( e . mousePosition ) )
399427 {
400- SelectKeyframe ( curve , k ) ;
401- m_EditMode = EditMode . Moving ;
402- e . Use ( ) ;
428+ if ( e . button == 0 )
429+ {
430+ SelectKeyframe ( curve , k ) ;
431+ m_EditMode = EditMode . Moving ;
432+ e . Use ( ) ;
433+ }
434+ else if ( e . button == 1 )
435+ {
436+ // Keyframe context menu
437+ var menu = new GenericMenu ( ) ;
438+ menu . AddItem ( new GUIContent ( "Delete Key" ) , false , ( x ) =>
439+ {
440+ var action = ( MenuAction ) x ;
441+ var curveValue = action . curve . animationCurveValue ;
442+ action . curve . serializedObject . Update ( ) ;
443+ RemoveKeyframe ( curveValue , action . index ) ;
444+ m_SelectedKeyframeIndex = - 1 ;
445+ SaveCurve ( action . curve , curveValue ) ;
446+ action . curve . serializedObject . ApplyModifiedProperties ( ) ;
447+ } , new MenuAction ( curve , k ) ) ;
448+ menu . ShowAsContext ( ) ;
449+ e . Use ( ) ;
450+ }
403451 }
404452 }
405453
@@ -455,6 +503,7 @@ void OnGeneralUI(Rect rect)
455503 GUI . FocusControl ( null ) ;
456504 m_SelectedCurve = null ;
457505 m_SelectedKeyframeIndex = - 1 ;
506+ bool used = false ;
458507
459508 var hit = CanvasToCurve ( e . mousePosition ) ;
460509 float curvePickValue = CurveToCanvas ( hit ) . y ;
@@ -478,18 +527,35 @@ void OnGeneralUI(Rect rect)
478527 {
479528 m_SelectedCurve = prop ;
480529
481- // Create a keyframe on double-click on this curve
482- if ( e . clickCount == 2 )
530+ if ( e . clickCount == 2 && e . button == 0 )
483531 {
532+ // Create a keyframe on double-click on this curve
484533 EditCreateKeyframe ( animCurve , hit , true , state . zeroKeyConstantValue ) ;
485534 SaveCurve ( prop , animCurve ) ;
486535 }
536+ else if ( e . button == 1 )
537+ {
538+ // Curve context menu
539+ var menu = new GenericMenu ( ) ;
540+ menu . AddItem ( new GUIContent ( "Add Key" ) , false , ( x ) =>
541+ {
542+ var action = ( MenuAction ) x ;
543+ var curveValue = action . curve . animationCurveValue ;
544+ action . curve . serializedObject . Update ( ) ;
545+ EditCreateKeyframe ( curveValue , hit , true , 0f ) ;
546+ SaveCurve ( action . curve , curveValue ) ;
547+ action . curve . serializedObject . ApplyModifiedProperties ( ) ;
548+ } , new MenuAction ( prop , hit ) ) ;
549+ menu . ShowAsContext ( ) ;
550+ e . Use ( ) ;
551+ used = true ;
552+ }
487553 }
488554 }
489555
490- // Create a keyframe on every curve on double-click
491- if ( e . clickCount == 2 && m_SelectedCurve == null )
556+ if ( e . clickCount == 2 && e . button == 0 && m_SelectedCurve == null )
492557 {
558+ // Create a keyframe on every curve on double-click
493559 foreach ( var curve in m_Curves )
494560 {
495561 if ( ! curve . Value . editable || ! curve . Value . visible )
@@ -502,6 +568,14 @@ void OnGeneralUI(Rect rect)
502568 SaveCurve ( prop , animCurve ) ;
503569 }
504570 }
571+ else if ( ! used && e . button == 1 )
572+ {
573+ // Global context menu
574+ var menu = new GenericMenu ( ) ;
575+ menu . AddItem ( new GUIContent ( "Add Key At Position" ) , false , ( ) => ContextMenuAddKey ( hit , false ) ) ;
576+ menu . AddItem ( new GUIContent ( "Add Key On Curves" ) , false , ( ) => ContextMenuAddKey ( hit , true ) ) ;
577+ menu . ShowAsContext ( ) ;
578+ }
505579
506580 e . Use ( ) ;
507581 }
@@ -547,6 +621,33 @@ void SelectKeyframe(SerializedProperty curve, int keyframeIndex)
547621 Invalidate ( ) ;
548622 }
549623
624+ void ContextMenuAddKey ( Vector3 hit , bool createOnCurve )
625+ {
626+ SerializedObject serializedObject = null ;
627+
628+ foreach ( var curve in m_Curves )
629+ {
630+ if ( ! curve . Value . editable || ! curve . Value . visible )
631+ continue ;
632+
633+ var prop = curve . Key ;
634+ var state = curve . Value ;
635+
636+ if ( serializedObject == null )
637+ {
638+ serializedObject = prop . serializedObject ;
639+ serializedObject . Update ( ) ;
640+ }
641+
642+ var animCurve = prop . animationCurveValue ;
643+ EditCreateKeyframe ( animCurve , hit , createOnCurve , state . zeroKeyConstantValue ) ;
644+ SaveCurve ( prop , animCurve ) ;
645+ }
646+
647+ if ( serializedObject != null )
648+ serializedObject . ApplyModifiedProperties ( ) ;
649+ }
650+
550651 void EditCreateKeyframe ( AnimationCurve curve , Vector3 position , bool createOnCurve , float zeroKeyConstantValue )
551652 {
552653 float tangent = EvaluateTangent ( curve , position . x ) ;
0 commit comments