Blender  V2.93
graph_utils.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <float.h>
25 #include <math.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "DNA_anim_types.h"
30 #include "DNA_screen_types.h"
31 #include "DNA_space_types.h"
32 
33 #include "MEM_guardedalloc.h"
34 
35 #include "BLI_blenlib.h"
36 
37 #include "BKE_context.h"
38 #include "BKE_fcurve.h"
39 #include "BKE_screen.h"
40 
41 #include "ED_anim_api.h"
42 #include "ED_screen.h"
43 #include "UI_interface.h"
44 
45 #include "RNA_access.h"
46 
47 #include "graph_intern.h" /* own include */
48 
49 /* ************************************************************** */
50 /* Set Up Drivers Editor */
51 
52 /* Set up UI configuration for Drivers Editor */
53 /* NOTE: Currently called from window-manager
54  * (new drivers editor window) and RNA (mode switching) */
56 {
57  SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first;
58 
59  /* Set mode */
60  sipo->mode = SIPO_MODE_DRIVERS;
61 
62  /* Show Properties Region (or else the settings can't be edited) */
64  if (region_props) {
65  UI_panel_category_active_set(region_props, "Drivers");
66 
67  region_props->flag &= ~RGN_FLAG_HIDDEN;
68  /* XXX: Adjust width of this too? */
69 
71  }
72  else {
73  printf("%s: Couldn't find properties region for Drivers Editor - %p\n", __func__, area);
74  }
75 
76  /* Adjust framing in graph region */
77  /* TODO: Have a way of not resetting this every time?
78  * (e.g. So that switching back and forth between editors doesn't keep jumping?)
79  */
81  if (region_main) {
82  /* XXX: Ideally we recenter based on the range instead... */
83  region_main->v2d.tot.xmin = -2.0f;
84  region_main->v2d.tot.ymin = -2.0f;
85  region_main->v2d.tot.xmax = 2.0f;
86  region_main->v2d.tot.ymax = 2.0f;
87 
88  region_main->v2d.cur = region_main->v2d.tot;
89  }
90 }
91 
92 /* ************************************************************** */
93 /* Active F-Curve */
94 
105 {
106  ListBase anim_data = {NULL, NULL};
108  size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
109 
110  /* We take the first F-Curve only, since some other ones may have had 'active' flag set
111  * if they were from linked data.
112  */
113  if (items) {
114  bAnimListElem *ale = (bAnimListElem *)anim_data.first;
115 
116  /* remove first item from list, then free the rest of the list and return the stored one */
117  BLI_remlink(&anim_data, ale);
118  ANIM_animdata_freelist(&anim_data);
119 
120  return ale;
121  }
122 
123  /* no active F-Curve */
124  return NULL;
125 }
126 
127 /* ************************************************************** */
128 /* Operator Polling Callbacks */
129 
130 /* Check if there are any visible keyframes (for selection tools) */
132 {
133  bAnimContext ac;
134  bAnimListElem *ale;
135  ListBase anim_data = {NULL, NULL};
137  size_t items;
138  int filter;
139  bool found = false;
140 
141  /* firstly, check if in Graph Editor */
142  /* TODO: also check for region? */
143  if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
144  return found;
145  }
146 
147  /* try to init Anim-Context stuff ourselves and check */
148  if (ANIM_animdata_get_context(C, &ac) == 0) {
149  return found;
150  }
151 
152  /* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable
153  * stopping on the first successful match
154  */
156  items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
157  if (items == 0) {
158  return found;
159  }
160 
161  for (ale = anim_data.first; ale; ale = ale->next) {
162  FCurve *fcu = (FCurve *)ale->data;
163 
164  /* visible curves for selection must fulfill the following criteria:
165  * - it has bezier keyframes
166  * - F-Curve modifiers do not interfere with the result too much
167  * (i.e. the modifier-control drawing check returns false)
168  */
169  if (fcu->bezt == NULL) {
170  continue;
171  }
173  found = true;
174  break;
175  }
176  }
177 
178  /* cleanup and return findings */
179  ANIM_animdata_freelist(&anim_data);
180  return found;
181 }
182 
183 /* Check if there are any visible + editable keyframes (for editing tools) */
185 {
186  bAnimContext ac;
187  bAnimListElem *ale;
188  ListBase anim_data = {NULL, NULL};
190  size_t items;
191  int filter;
192  bool found = false;
193 
194  /* firstly, check if in Graph Editor */
195  /* TODO: also check for region? */
196  if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
197  return found;
198  }
199 
200  /* try to init Anim-Context stuff ourselves and check */
201  if (ANIM_animdata_get_context(C, &ac) == 0) {
202  return found;
203  }
204 
205  /* loop over the editable F-Curves, and see if they're suitable
206  * stopping on the first successful match
207  */
209  items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
210  if (items == 0) {
211  return found;
212  }
213 
214  for (ale = anim_data.first; ale; ale = ale->next) {
215  FCurve *fcu = (FCurve *)ale->data;
216 
217  /* editable curves must fulfill the following criteria:
218  * - it has bezier keyframes
219  * - it must not be protected from editing (this is already checked for with the edit flag
220  * - F-Curve modifiers do not interfere with the result too much
221  * (i.e. the modifier-control drawing check returns false)
222  */
223  if (fcu->bezt == NULL && fcu->fpt != NULL) {
224  /* This is a baked curve, it is never editable. */
225  continue;
226  }
227  if (BKE_fcurve_is_keyframable(fcu)) {
228  found = true;
229  break;
230  }
231  }
232 
233  /* cleanup and return findings */
234  ANIM_animdata_freelist(&anim_data);
235  return found;
236 }
237 
238 /* has active F-Curve that's editable */
240 {
241  bAnimContext ac;
242  bAnimListElem *ale;
244  bool has_fcurve = false;
245 
246  /* firstly, check if in Graph Editor */
247  /* TODO: also check for region? */
248  if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
249  return has_fcurve;
250  }
251 
252  /* try to init Anim-Context stuff ourselves and check */
253  if (ANIM_animdata_get_context(C, &ac) == 0) {
254  return has_fcurve;
255  }
256 
257  /* try to get the Active F-Curve */
258  ale = get_active_fcurve_channel(&ac);
259  if (ale == NULL) {
260  return has_fcurve;
261  }
262 
263  /* Do we have a suitable F-Curves?
264  * - For most cases, NLA Control Curves are sufficiently similar to NLA
265  * curves to serve this role too. Under the hood, they are F-Curves too.
266  * The only problems which will arise here are if these need to be
267  * in an Action too (but drivers would then also be affected!)
268  */
269  has_fcurve = ((ale->data) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE));
270  if (has_fcurve) {
271  FCurve *fcu = (FCurve *)ale->data;
272  has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0;
273  }
274 
275  /* free temp data... */
276  MEM_freeN(ale);
277 
278  /* return success */
279  return has_fcurve;
280 }
281 
282 /* has active F-Curve in the context that's editable */
284 {
285  PointerRNA ptr = CTX_data_pointer_get_type(C, "active_editable_fcurve", &RNA_FCurve);
286 
287  return ptr.data != NULL;
288 }
289 
290 /* has selected F-Curve that's editable */
292 {
293  bAnimContext ac;
294  ListBase anim_data = {NULL, NULL};
296  size_t items;
297  int filter;
298 
299  /* firstly, check if in Graph Editor */
300  /* TODO: also check for region? */
301  if ((area == NULL) || (area->spacetype != SPACE_GRAPH)) {
302  return false;
303  }
304 
305  /* try to init Anim-Context stuff ourselves and check */
306  if (ANIM_animdata_get_context(C, &ac) == 0) {
307  return false;
308  }
309 
310  /* Get the editable + selected F-Curves, and as long as we got some, we can return.
311  * NOTE: curve-visible flag isn't included,
312  * otherwise selecting a curve via list to edit is too cumbersome. */
314  items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
315  if (items == 0) {
316  return false;
317  }
318 
319  /* cleanup and return findings */
320  ANIM_animdata_freelist(&anim_data);
321  return true;
322 }
323 
324 /* ************************************************************** */
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:456
bool BKE_fcurve_are_keyframes_usable(struct FCurve *fcu)
Definition: fcurve.c:963
bool BKE_fcurve_is_keyframable(struct FCurve *fcu)
Definition: fcurve.c:1031
struct ARegion * BKE_area_find_region_type(const struct ScrArea *area, int type)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
#define ELEM(...)
@ FCURVE_VISIBLE
@ RGN_FLAG_HIDDEN
@ RGN_TYPE_UI
@ RGN_TYPE_WINDOW
@ SPACE_GRAPH
@ SIPO_MODE_DRIVERS
@ ANIMTYPE_NLACURVE
Definition: ED_anim_api.h:210
@ ANIMTYPE_FCURVE
Definition: ED_anim_api.h:207
@ ANIMFILTER_ACTIVE
Definition: ED_anim_api.h:306
@ ANIMFILTER_FOREDIT
Definition: ED_anim_api.h:315
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_CURVE_VISIBLE
Definition: ED_anim_api.h:300
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:311
void ED_region_visibility_change_update(struct bContext *C, struct ScrArea *area, struct ARegion *region)
Definition: area.c:2032
Read Guarded memory(de)allocation.
StructRNA RNA_FCurve
#define C
Definition: RandGen.cpp:39
void UI_panel_category_active_set(struct ARegion *region, const char *idname)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:425
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:405
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3442
bool graphop_visible_keyframes_poll(bContext *C)
Definition: graph_utils.c:131
bool graphop_active_editable_fcurve_ctx_poll(bContext *C)
Definition: graph_utils.c:283
bAnimListElem * get_active_fcurve_channel(bAnimContext *ac)
Definition: graph_utils.c:104
bool graphop_editable_keyframes_poll(bContext *C)
Definition: graph_utils.c:184
bool graphop_active_fcurve_poll(bContext *C)
Definition: graph_utils.c:239
bool graphop_selected_fcurve_poll(bContext *C)
Definition: graph_utils.c:291
void ED_drivers_editor_init(bContext *C, ScrArea *area)
Definition: graph_utils.c:55
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static void area(int d1, int d2, int e1, int e2, float weights[2])
FPoint * fpt
BezTriple * bezt
short flag
void * first
Definition: DNA_listBase.h:47
void * data
Definition: RNA_types.h:52
short datatype
Definition: ED_anim_api.h:75
void * data
Definition: ED_anim_api.h:73
struct bAnimListElem * next
Definition: ED_anim_api.h:135
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
PointerRNA * ptr
Definition: wm_files.c:3157