| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2020 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 11:32:55 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup spgraph | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Graph Slider Operators | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file contains a collection of operators to modify keyframes in the graph editor. | 
					
						
							|  |  |  |  * All operators are modal and use a slider that allows the user to define a percentage | 
					
						
							|  |  |  |  * to modify the operator. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | #include <float.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_listbase.h"
 | 
					
						
							|  |  |  | #include "BLI_string.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_anim_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "RNA_access.h"
 | 
					
						
							|  |  |  | #include "RNA_define.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLT_translation.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "UI_interface.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ED_anim_api.h"
 | 
					
						
							|  |  |  | #include "ED_keyframes_edit.h"
 | 
					
						
							|  |  |  | #include "ED_numinput.h"
 | 
					
						
							|  |  |  | #include "ED_screen.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-07 20:10:53 +01:00
										 |  |  | #include "ED_util.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "graph_intern.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 11:32:55 +11:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Internal Struct & Defines
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-31 11:19:40 +00:00
										 |  |  | /* Used to obtain a list of animation channels for the operators to work on. */ | 
					
						
							|  |  |  | #define OPERATOR_DATA_FILTER \
 | 
					
						
							|  |  |  |   (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | \ | 
					
						
							|  |  |  |    ANIMFILTER_NODUPLIS) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-31 11:52:24 -06:00
										 |  |  | /* This data type is only used for modal operation. */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  | typedef struct tGraphSliderOp { | 
					
						
							| 
									
										
										
										
											2021-10-31 11:52:24 -06:00
										 |  |  |   bAnimContext ac; | 
					
						
							|  |  |  |   Scene *scene; | 
					
						
							|  |  |  |   ScrArea *area; | 
					
						
							|  |  |  |   ARegion *region; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** A 0-1 value for determining how much we should decimate. */ | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   PropertyRNA *factor_prop; | 
					
						
							| 
									
										
										
										
											2021-10-31 11:52:24 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** The original bezt curve data (used for restoring fcurves). */ | 
					
						
							|  |  |  |   ListBase bezt_arr_list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct tSlider *slider; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   /* Each operator has a specific update function. */ | 
					
						
							|  |  |  |   void (*modal_update)(struct bContext *, struct wmOperator *); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-31 11:52:24 -06:00
										 |  |  |   NumInput num; | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  | } tGraphSliderOp; | 
					
						
							| 
									
										
										
										
											2021-10-31 11:52:24 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct tBeztCopyData { | 
					
						
							|  |  |  |   int tot_vert; | 
					
						
							|  |  |  |   BezTriple *bezt; | 
					
						
							|  |  |  | } tBeztCopyData; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 11:32:55 +11:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Utility Functions
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2021-10-31 11:28:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Construct a list with the original bezt arrays so we can restore them during modal operation.
 | 
					
						
							|  |  |  |  * The data is stored on the struct that is passed.*/ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  | static void store_original_bezt_arrays(tGraphSliderOp *gso) | 
					
						
							| 
									
										
										
										
											2021-10-31 11:28:10 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   ListBase anim_data = {NULL, NULL}; | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   bAnimContext *ac = &gso->ac; | 
					
						
							| 
									
										
										
										
											2021-10-31 11:28:10 +00:00
										 |  |  |   bAnimListElem *ale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Loop through filtered data and copy the curves. */ | 
					
						
							|  |  |  |   for (ale = anim_data.first; ale; ale = ale->next) { | 
					
						
							|  |  |  |     FCurve *fcu = (FCurve *)ale->key_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fcu->bezt == NULL) { | 
					
						
							|  |  |  |       /* This curve is baked, skip it. */ | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int arr_size = sizeof(BezTriple) * fcu->totvert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tBeztCopyData *copy = MEM_mallocN(sizeof(tBeztCopyData), "bezts_copy"); | 
					
						
							|  |  |  |     BezTriple *bezts_copy = MEM_mallocN(arr_size, "bezts_copy_array"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     copy->tot_vert = fcu->totvert; | 
					
						
							|  |  |  |     memcpy(bezts_copy, fcu->bezt, arr_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     copy->bezt = bezts_copy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     LinkData *link = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     link = MEM_callocN(sizeof(LinkData), "Bezt Link"); | 
					
						
							|  |  |  |     link->data = copy; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |     BLI_addtail(&gso->bezt_arr_list, link); | 
					
						
							| 
									
										
										
										
											2021-10-31 11:28:10 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ANIM_animdata_freelist(&anim_data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | /* Overwrite the current bezts arrays with the original data. */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  | static void reset_bezts(tGraphSliderOp *gso) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   ListBase anim_data = {NULL, NULL}; | 
					
						
							|  |  |  |   LinkData *link_bezt; | 
					
						
							|  |  |  |   bAnimListElem *ale; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   bAnimContext *ac = &gso->ac; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Filter data. */ | 
					
						
							| 
									
										
										
										
											2021-10-31 11:19:40 +00:00
										 |  |  |   ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Loop through filtered data and reset bezts. */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   for (ale = anim_data.first, link_bezt = gso->bezt_arr_list.first; ale; ale = ale->next) { | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |     FCurve *fcu = (FCurve *)ale->key_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fcu->bezt == NULL) { | 
					
						
							|  |  |  |       /* This curve is baked, skip it. */ | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tBeztCopyData *data = link_bezt->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int arr_size = sizeof(BezTriple) * data->tot_vert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     MEM_freeN(fcu->bezt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fcu->bezt = MEM_mallocN(arr_size, __func__); | 
					
						
							|  |  |  |     fcu->totvert = data->tot_vert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memcpy(fcu->bezt, data->bezt, arr_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     link_bezt = link_bezt->next; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ANIM_animdata_freelist(&anim_data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 11:32:55 +11:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  | /** \name Common Modal Functions
 | 
					
						
							| 
									
										
										
										
											2021-11-05 11:32:55 +11:00
										 |  |  |  * \{ */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:35:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  | static void graph_slider_exit(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   tGraphSliderOp *gso = op->customdata; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   wmWindow *win = CTX_wm_window(C); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If data exists, clear its data and exit. */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   if (gso == NULL) { | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   ScrArea *area = gso->area; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   LinkData *link; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   ED_slider_destroy(C, gso->slider); | 
					
						
							| 
									
										
										
										
											2021-09-07 20:10:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   for (link = gso->bezt_arr_list.first; link != NULL; link = link->next) { | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |     tBeztCopyData *copy = link->data; | 
					
						
							|  |  |  |     MEM_freeN(copy->bezt); | 
					
						
							|  |  |  |     MEM_freeN(link->data); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   BLI_freelistN(&gso->bezt_arr_list); | 
					
						
							|  |  |  |   MEM_freeN(gso); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Return to normal cursor and header status. */ | 
					
						
							|  |  |  |   WM_cursor_modal_restore(win); | 
					
						
							|  |  |  |   ED_area_status_text(area, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   /* cleanup */ | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   op->customdata = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  | static int graph_slider_modal(bContext *C, wmOperator *op, const wmEvent *event) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   tGraphSliderOp *gso = op->customdata; | 
					
						
							| 
									
										
										
										
											2021-09-07 20:10:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   const bool has_numinput = hasNumInput(&gso->num); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   ED_slider_modal(gso->slider, event); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   switch (event->type) { | 
					
						
							|  |  |  |     /* Confirm */ | 
					
						
							|  |  |  |     case LEFTMOUSE: | 
					
						
							|  |  |  |     case EVT_RETKEY: | 
					
						
							|  |  |  |     case EVT_PADENTER: { | 
					
						
							|  |  |  |       if (event->val == KM_PRESS) { | 
					
						
							|  |  |  |         graph_slider_exit(C, op); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |         return OPERATOR_FINISHED; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |     /* Cancel */ | 
					
						
							|  |  |  |     case EVT_ESCKEY: | 
					
						
							|  |  |  |     case RIGHTMOUSE: { | 
					
						
							|  |  |  |       if (event->val == KM_PRESS) { | 
					
						
							|  |  |  |         reset_bezts(gso); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         graph_slider_exit(C, op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* When the mouse is moved, the percentage and the keyframes update. */ | 
					
						
							|  |  |  |     case MOUSEMOVE: { | 
					
						
							|  |  |  |       if (has_numinput == false) { | 
					
						
							|  |  |  |         /* Do the update as specified by the operator. */ | 
					
						
							|  |  |  |         gso->modal_update(C, op); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: { | 
					
						
							|  |  |  |       if ((event->val == KM_PRESS) && handleNumInput(C, &gso->num, event)) { | 
					
						
							|  |  |  |         float value; | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |         float percentage = RNA_property_float_get(op->ptr, gso->factor_prop); | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /* Grab percentage from numeric input, and store this new value for redo
 | 
					
						
							|  |  |  |          * NOTE: users see ints, while internally we use a 0-1 float. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         value = percentage * 100.0f; | 
					
						
							|  |  |  |         applyNumInput(&gso->num, &value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         percentage = value / 100.0f; | 
					
						
							|  |  |  |         ED_slider_factor_set(gso->slider, percentage); | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |         RNA_property_float_set(op->ptr, gso->factor_prop, percentage); | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         gso->modal_update(C, op); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Unhandled event - maybe it was some view manip? */ | 
					
						
							|  |  |  |       /* Allow to pass through. */ | 
					
						
							|  |  |  |       return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   return OPERATOR_RUNNING_MODAL; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  | /* Allocate tGraphSliderOp and assign to op->customdata. */ | 
					
						
							|  |  |  | static int graph_slider_invoke(bContext *C, wmOperator *op, const wmEvent *event) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   tGraphSliderOp *gso; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EW_SCROLL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Init slide-op data. */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   gso = op->customdata = MEM_callocN(sizeof(tGraphSliderOp), "tGraphSliderOp"); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Get editor data. */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   if (ANIM_animdata_get_context(C, &gso->ac) == 0) { | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |     graph_slider_exit(C, op); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |     return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   gso->factor_prop = RNA_struct_find_property(op->ptr, "factor"); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   gso->scene = CTX_data_scene(C); | 
					
						
							|  |  |  |   gso->area = CTX_wm_area(C); | 
					
						
							|  |  |  |   gso->region = CTX_wm_region(C); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   store_original_bezt_arrays(gso); | 
					
						
							| 
									
										
										
										
											2021-10-31 11:28:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   gso->slider = ED_slider_create(C); | 
					
						
							|  |  |  |   ED_slider_init(gso->slider, event); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   if (gso->bezt_arr_list.first == NULL) { | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |     WM_report(RPT_WARNING, | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |               "Fcurve Slider: Can't work on baked channels. Unbake them and try again."); | 
					
						
							|  |  |  |     graph_slider_exit(C, op); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |     return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   WM_event_add_modal_handler(C, op); | 
					
						
							|  |  |  |   return OPERATOR_RUNNING_MODAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Decimate Keyframes Operator
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef enum tDecimModes { | 
					
						
							|  |  |  |   DECIM_RATIO = 1, | 
					
						
							|  |  |  |   DECIM_ERROR, | 
					
						
							|  |  |  | } tDecimModes; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  | static void decimate_graph_keys(bAnimContext *ac, float factor, float error_sq_max) | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   ListBase anim_data = {NULL, NULL}; | 
					
						
							|  |  |  |   bAnimListElem *ale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Filter data. */ | 
					
						
							|  |  |  |   ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Loop through filtered data and clean curves. */ | 
					
						
							|  |  |  |   for (ale = anim_data.first; ale; ale = ale->next) { | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |     if (!decimate_fcurve(ale, factor, error_sq_max)) { | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |       /* The selection contains unsupported keyframe types! */ | 
					
						
							|  |  |  |       WM_report(RPT_WARNING, "Decimate: Skipping non linear/bezier keyframes!"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ale->update |= ANIM_UPDATE_DEFAULT; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ANIM_animdata_update(ac, &anim_data); | 
					
						
							|  |  |  |   ANIM_animdata_freelist(&anim_data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Draw a percentage indicator in workspace footer. */ | 
					
						
							|  |  |  | static void decimate_draw_status(bContext *C, tGraphSliderOp *gso) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char status_str[UI_MAX_DRAW_STR]; | 
					
						
							|  |  |  |   char mode_str[32]; | 
					
						
							|  |  |  |   char slider_string[UI_MAX_DRAW_STR]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   strcpy(mode_str, TIP_("Decimate Keyframes")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (hasNumInput(&gso->num)) { | 
					
						
							|  |  |  |     char str_ofs[NUM_STR_REP_LEN]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     outputNumInput(&gso->num, str_ofs, &gso->scene->unit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_ofs); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, slider_string); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ED_workspace_status_text(C, status_str); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  | static void decimate_modal_update(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   /* Perform decimate updates - in response to some user action
 | 
					
						
							|  |  |  |    * (e.g. pressing a key or moving the mouse). */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   tGraphSliderOp *gso = op->customdata; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   decimate_draw_status(C, gso); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Reset keyframe data (so we get back to the original state). */ | 
					
						
							| 
									
										
										
										
											2021-11-04 21:20:26 +00:00
										 |  |  |   reset_bezts(gso); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Apply... */ | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   float factor = ED_slider_factor_get(gso->slider); | 
					
						
							|  |  |  |   RNA_property_float_set(op->ptr, gso->factor_prop, factor); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   /* We don't want to limit the decimation to a certain error margin. */ | 
					
						
							|  |  |  |   const float error_sq_max = FLT_MAX; | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   decimate_graph_keys(&gso->ac, factor, error_sq_max); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  | static int decimate_invoke(bContext *C, wmOperator *op, const wmEvent *event) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   const int invoke_result = graph_slider_invoke(C, op, event); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   if (invoke_result == OPERATOR_CANCELLED) { | 
					
						
							|  |  |  |     return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   tGraphSliderOp *gso = op->customdata; | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   gso->modal_update = decimate_modal_update; | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   ED_slider_allow_overshoot_set(gso->slider, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return invoke_result; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  | static int decimate_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   bAnimContext ac; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Get editor data. */ | 
					
						
							|  |  |  |   if (ANIM_animdata_get_context(C, &ac) == 0) { | 
					
						
							|  |  |  |     return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tDecimModes mode = RNA_enum_get(op->ptr, "mode"); | 
					
						
							|  |  |  |   /* We want to be able to work on all available keyframes. */ | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   float factor = 1.0f; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   /* We don't want to limit the decimation to a certain error margin. */ | 
					
						
							|  |  |  |   float error_sq_max = FLT_MAX; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (mode) { | 
					
						
							|  |  |  |     case DECIM_RATIO: | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |       factor = RNA_float_get(op->ptr, "factor"); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case DECIM_ERROR: | 
					
						
							|  |  |  |       error_sq_max = RNA_float_get(op->ptr, "remove_error_margin"); | 
					
						
							|  |  |  |       /* The decimate algorithm expects the error to be squared. */ | 
					
						
							|  |  |  |       error_sq_max *= error_sq_max; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   if (factor == 0.0f || error_sq_max == 0.0f) { | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |     /* Nothing to remove. */ | 
					
						
							|  |  |  |     return OPERATOR_FINISHED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   decimate_graph_keys(&ac, factor, error_sq_max); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Set notifier that keyframes have changed. */ | 
					
						
							|  |  |  |   WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  | static bool decimate_poll_property(const bContext *UNUSED(C), | 
					
						
							|  |  |  |                                    wmOperator *op, | 
					
						
							|  |  |  |                                    const PropertyRNA *prop) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   const char *prop_id = RNA_property_identifier(prop); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (STRPREFIX(prop_id, "remove")) { | 
					
						
							|  |  |  |     int mode = RNA_enum_get(op->ptr, "mode"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |     if (STREQ(prop_id, "factor") && mode != DECIM_RATIO) { | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (STREQ(prop_id, "remove_error_margin") && mode != DECIM_ERROR) { | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  | static char *decimate_desc(bContext *UNUSED(C), wmOperatorType *UNUSED(op), PointerRNA *ptr) | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (RNA_enum_get(ptr, "mode") == DECIM_ERROR) { | 
					
						
							|  |  |  |     return BLI_strdup( | 
					
						
							|  |  |  |         "Decimate F-Curves by specifying how much it can deviate from the original curve"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Use default description. */ | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const EnumPropertyItem decimate_mode_items[] = { | 
					
						
							|  |  |  |     {DECIM_RATIO, | 
					
						
							|  |  |  |      "RATIO", | 
					
						
							|  |  |  |      0, | 
					
						
							|  |  |  |      "Ratio", | 
					
						
							|  |  |  |      "Use a percentage to specify how many keyframes you want to remove"}, | 
					
						
							|  |  |  |     {DECIM_ERROR, | 
					
						
							|  |  |  |      "ERROR", | 
					
						
							|  |  |  |      0, | 
					
						
							|  |  |  |      "Error Margin", | 
					
						
							|  |  |  |      "Use an error margin to specify how much the curve is allowed to deviate from the original " | 
					
						
							|  |  |  |      "path"}, | 
					
						
							|  |  |  |     {0, NULL, 0, NULL, NULL}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GRAPH_OT_decimate(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* Identifiers */ | 
					
						
							|  |  |  |   ot->name = "Decimate Keyframes"; | 
					
						
							|  |  |  |   ot->idname = "GRAPH_OT_decimate"; | 
					
						
							|  |  |  |   ot->description = | 
					
						
							|  |  |  |       "Decimate F-Curves by removing keyframes that influence the curve shape the least"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* API callbacks */ | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   ot->poll_property = decimate_poll_property; | 
					
						
							|  |  |  |   ot->get_description = decimate_desc; | 
					
						
							|  |  |  |   ot->invoke = decimate_invoke; | 
					
						
							| 
									
										
										
										
											2021-12-03 22:24:41 +00:00
										 |  |  |   ot->modal = graph_slider_modal; | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |   ot->exec = decimate_exec; | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   ot->poll = graphop_editable_keyframes_poll; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Properties */ | 
					
						
							|  |  |  |   RNA_def_enum(ot->srna, | 
					
						
							|  |  |  |                "mode", | 
					
						
							|  |  |  |                decimate_mode_items, | 
					
						
							|  |  |  |                DECIM_RATIO, | 
					
						
							|  |  |  |                "Mode", | 
					
						
							|  |  |  |                "Which mode to use for decimation"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 11:19:54 -06:00
										 |  |  |   RNA_def_float_factor(ot->srna, | 
					
						
							| 
									
										
										
										
											2021-12-06 22:19:00 +00:00
										 |  |  |                        "factor", | 
					
						
							| 
									
										
										
										
											2021-01-27 11:19:54 -06:00
										 |  |  |                        1.0f / 3.0f, | 
					
						
							|  |  |  |                        0.0f, | 
					
						
							|  |  |  |                        1.0f, | 
					
						
							|  |  |  |                        "Remove", | 
					
						
							|  |  |  |                        "The ratio of remaining keyframes after the operation", | 
					
						
							|  |  |  |                        0.0f, | 
					
						
							|  |  |  |                        1.0f); | 
					
						
							| 
									
										
										
										
											2020-11-23 15:11:51 +01:00
										 |  |  |   RNA_def_float(ot->srna, | 
					
						
							|  |  |  |                 "remove_error_margin", | 
					
						
							|  |  |  |                 0.0f, | 
					
						
							|  |  |  |                 0.0f, | 
					
						
							|  |  |  |                 FLT_MAX, | 
					
						
							|  |  |  |                 "Max Error Margin", | 
					
						
							|  |  |  |                 "How much the new decimated curve is allowed to deviate from the original", | 
					
						
							|  |  |  |                 0.0f, | 
					
						
							|  |  |  |                 10.0f); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-05 11:32:55 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** \} */ |