Blender  V2.93
interface_anim.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 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "MEM_guardedalloc.h"
26 
27 #include "DNA_anim_types.h"
28 #include "DNA_scene_types.h"
29 #include "DNA_screen_types.h"
30 
31 #include "BLI_listbase.h"
32 #include "BLI_string.h"
33 #include "BLI_string_utf8.h"
34 #include "BLI_utildefines.h"
35 
36 #include "BKE_animsys.h"
37 #include "BKE_context.h"
38 #include "BKE_fcurve.h"
39 #include "BKE_fcurve_driver.h"
40 #include "BKE_global.h"
41 #include "BKE_main.h"
42 #include "BKE_nla.h"
43 
44 #include "DEG_depsgraph.h"
45 #include "DEG_depsgraph_build.h"
46 
47 #include "ED_keyframing.h"
48 
49 #include "UI_interface.h"
50 
51 #include "RNA_access.h"
52 
53 #include "WM_api.h"
54 #include "WM_types.h"
55 
56 #include "interface_intern.h"
57 
59  uiBut *but, AnimData **adt, bAction **action, bool *r_driven, bool *r_special)
60 {
61  /* for entire array buttons we check the first component, it's not perfect
62  * but works well enough in typical cases */
63  const int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex;
64 
66  but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special);
67 }
68 
69 void ui_but_anim_flag(uiBut *but, const AnimationEvalContext *anim_eval_context)
70 {
71  AnimData *adt;
72  bAction *act;
73  FCurve *fcu;
74  bool driven;
75  bool special;
76 
79 
80  /* NOTE: "special" is reserved for special F-Curves stored on the animation data
81  * itself (which are used to animate properties of the animation data).
82  * We count those as "animated" too for now
83  */
84  fcu = ui_but_get_fcurve(but, &adt, &act, &driven, &special);
85 
86  if (fcu) {
87  if (!driven) {
88  /* Empty curves are ignored by the animation evaluation system. */
89  if (BKE_fcurve_is_empty(fcu)) {
90  return;
91  }
92 
93  but->flag |= UI_BUT_ANIMATED;
94 
95  /* T41525 - When the active action is a NLA strip being edited,
96  * we need to correct the frame number to "look inside" the
97  * remapped action
98  */
99  float cfra = anim_eval_context->eval_time;
100  if (adt) {
102  }
103 
104  if (fcurve_frame_has_keyframe(fcu, cfra, 0)) {
105  but->flag |= UI_BUT_ANIMATED_KEY;
106  }
107 
108  /* XXX: this feature is totally broken and useless with NLA */
109  if (adt == NULL || adt->nla_tracks.first == NULL) {
111  anim_eval_context, cfra);
112  if (fcurve_is_changed(but->rnapoin, but->rnaprop, fcu, &remapped_context)) {
114  }
115  }
116  }
117  else {
118  but->flag |= UI_BUT_DRIVEN;
119  }
120  }
121 }
122 
124 {
125  uiBut *but_iter = NULL;
126 
127  BLI_assert(UI_but_is_decorator(&but_decorate->but));
128  BLI_assert(but_decorate->rnapoin.data && but_decorate->rnaprop);
129 
131  &but_decorate->but.block->buttons, but_iter, but_decorate->but.prev) {
132  if (but_iter != (uiBut *)but_decorate &&
134  but_iter, &but_decorate->rnapoin, but_decorate->rnaprop, but_decorate->rnaindex)) {
135  return but_iter;
136  }
137  }
139  &but_decorate->but.block->buttons, but_iter, but_decorate->but.prev);
140 
141  return NULL;
142 }
143 
145 {
146  if (!decorator_but->rnapoin.data || !decorator_but->rnaprop) {
147  /* Nothing to do. */
148  return;
149  }
150 
151  const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(decorator_but);
152  uiBut *but = &decorator_but->but;
153 
154  if (!but_anim) {
155  printf("Could not find button with matching property to decorate (%s.%s)\n",
156  RNA_struct_identifier(decorator_but->rnapoin.type),
157  RNA_property_identifier(decorator_but->rnaprop));
158  return;
159  }
160 
161  const int flag = but_anim->flag;
162 
163  if (flag & UI_BUT_DRIVEN) {
164  but->icon = ICON_DECORATE_DRIVER;
165  }
166  else if (flag & UI_BUT_ANIMATED_KEY) {
167  but->icon = ICON_DECORATE_KEYFRAME;
168  }
169  else if (flag & UI_BUT_ANIMATED) {
170  but->icon = ICON_DECORATE_ANIMATE;
171  }
172  else if (flag & UI_BUT_OVERRIDDEN) {
173  but->icon = ICON_DECORATE_OVERRIDE;
174  }
175  else {
176  but->icon = ICON_DECORATE;
177  }
178 
179  const int flag_copy = (UI_BUT_DISABLED | UI_BUT_INACTIVE);
180  but->flag = (but->flag & ~flag_copy) | (flag & flag_copy);
181 }
182 
187 bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
188 {
189  FCurve *fcu;
190  ChannelDriver *driver;
191  bool driven, special;
192 
193  fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
194 
195  if (fcu && driven) {
196  driver = fcu->driver;
197 
198  if (driver && driver->type == DRIVER_TYPE_PYTHON) {
199  if (str) {
200  BLI_strncpy(str, driver->expression, maxlen);
201  }
202  return true;
203  }
204  }
205 
206  return false;
207 }
208 
209 bool ui_but_anim_expression_set(uiBut *but, const char *str)
210 {
211  FCurve *fcu;
212  ChannelDriver *driver;
213  bool driven, special;
214 
215  fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special);
216 
217  if (fcu && driven) {
218  driver = fcu->driver;
219 
220  if (driver && (driver->type == DRIVER_TYPE_PYTHON)) {
221  bContext *C = but->block->evil_C;
222 
223  BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
224 
225  /* tag driver as needing to be recompiled */
226  BKE_driver_invalidate_expression(driver, true, false);
227 
228  /* clear invalid flags which may prevent this from working */
229  driver->flag &= ~DRIVER_FLAG_INVALID;
230  fcu->flag &= ~FCURVE_DISABLED;
231 
232  /* this notifier should update the Graph Editor and trigger depsgraph refresh? */
234 
236 
237  return true;
238  }
239  }
240 
241  return false;
242 }
243 
244 /* create new expression for button (i.e. a "scripted driver"), if it can be created... */
245 bool ui_but_anim_expression_create(uiBut *but, const char *str)
246 {
247  bContext *C = but->block->evil_C;
248  ID *id;
249  FCurve *fcu;
250  char *path;
251  bool ok = false;
252 
253  /* button must have RNA-pointer to a numeric-capable property */
254  if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
255  if (G.debug & G_DEBUG) {
256  printf("ERROR: create expression failed - button has no RNA info attached\n");
257  }
258  return false;
259  }
260 
261  if (RNA_property_array_check(but->rnaprop) != 0) {
262  if (but->rnaindex == -1) {
263  if (G.debug & G_DEBUG) {
264  printf("ERROR: create expression failed - can't create expression for entire array\n");
265  }
266  return false;
267  }
268  }
269 
270  /* make sure we have animdata for this */
271  /* FIXME: until materials can be handled by depsgraph,
272  * don't allow drivers to be created for them */
273  id = but->rnapoin.owner_id;
274  if ((id == NULL) || (GS(id->name) == ID_MA) || (GS(id->name) == ID_TE)) {
275  if (G.debug & G_DEBUG) {
276  printf("ERROR: create expression failed - invalid data-block for adding drivers (%p)\n", id);
277  }
278  return false;
279  }
280 
281  /* get path */
282  path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
283  if (path == NULL) {
284  return false;
285  }
286 
287  /* create driver */
289  if (fcu) {
290  ChannelDriver *driver = fcu->driver;
291 
292  if (driver) {
293  /* set type of driver */
294  driver->type = DRIVER_TYPE_PYTHON;
295 
296  /* set the expression */
297  /* TODO: need some way of identifying variables used */
298  BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
299 
300  /* updates */
301  BKE_driver_invalidate_expression(driver, true, false);
304  ok = true;
305  }
306  }
307 
308  MEM_freeN(path);
309 
310  return ok;
311 }
312 
313 void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
314 {
315  ED_autokeyframe_property(C, scene, &but->rnapoin, but->rnaprop, but->rnaindex, cfra);
316 }
317 
319 {
320  /* this operator calls UI_context_active_but_prop_get */
321  WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
322 }
323 
325 {
326  /* this operator calls UI_context_active_but_prop_get */
327  WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
328 }
329 
330 void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
331 {
333  uiButDecorator *but_decorate = arg_but;
334  uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but_decorate);
335 
336  if (!but_anim) {
337  return;
338  }
339 
340  /* FIXME(campbell), swapping active pointer is weak. */
341  SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->but.active);
342  wm->op_undo_depth++;
343 
344  if (but_anim->flag & UI_BUT_DRIVEN) {
345  /* pass */
346  /* TODO: report? */
347  }
348  else if (but_anim->flag & UI_BUT_ANIMATED_KEY) {
349  PointerRNA props_ptr;
350  wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false);
352  RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
354  WM_operator_properties_free(&props_ptr);
355  }
356  else {
357  PointerRNA props_ptr;
358  wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false);
360  RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
362  WM_operator_properties_free(&props_ptr);
363  }
364 
365  SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->but.active);
366  wm->op_undo_depth--;
367 }
AnimationEvalContext BKE_animsys_eval_context_construct_at(const AnimationEvalContext *anim_eval_context, float eval_time)
Definition: anim_sys.c:647
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
bool BKE_fcurve_is_empty(struct FCurve *fcu)
Definition: fcurve.c:2250
struct FCurve * BKE_fcurve_find_by_rna_context_ui(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, struct AnimData **r_animdata, struct bAction **r_action, bool *r_driven, bool *r_special)
Definition: fcurve.c:390
void BKE_driver_invalidate_expression(struct ChannelDriver *driver, bool expr_changed, bool varname_changed)
@ G_DEBUG
Definition: BKE_global.h:133
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:153
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode)
Definition: nla.c:582
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init)
Definition: BLI_listbase.h:161
#define LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init)
Definition: BLI_listbase.h:165
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string_utf8.c:258
#define SWAP(type, a, b)
#define UNUSED(x)
#define ELEM(...)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_TE
Definition: DNA_ID_enums.h:64
@ ID_MA
Definition: DNA_ID_enums.h:63
@ DRIVER_TYPE_PYTHON
@ DRIVER_FLAG_INVALID
@ FCURVE_DISABLED
@ DRIVER_FCURVE_KEYFRAMES
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
@ UI_BUT_ANIMATED_CHANGED
Definition: UI_interface.h:301
@ UI_BUT_ANIMATED
Definition: UI_interface.h:201
@ UI_BUT_DISABLED
Definition: UI_interface.h:199
@ UI_BUT_INACTIVE
Definition: UI_interface.h:206
@ UI_BUT_OVERRIDDEN
Definition: UI_interface.h:234
@ UI_BUT_DRIVEN
Definition: UI_interface.h:203
@ UI_BUT_ANIMATED_KEY
Definition: UI_interface.h:202
#define UI_but_is_decorator(but)
Definition: UI_interface.h:543
#define NC_ANIMATION
Definition: WM_types.h:289
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:197
#define ND_KEYFRAME
Definition: WM_types.h:394
Scene scene
FCurve * verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, eDriverFCurveCreationMode creation_mode)
Definition: drivers.c:67
#define str(s)
bool ui_but_rna_equals_ex(const uiBut *but, const PointerRNA *ptr, const PropertyRNA *prop, int index)
Definition: interface.c:677
static FCurve * ui_but_get_fcurve(uiBut *but, AnimData **adt, bAction **action, bool *r_driven, bool *r_special)
bool ui_but_anim_expression_create(uiBut *but, const char *str)
void ui_but_anim_flag(uiBut *but, const AnimationEvalContext *anim_eval_context)
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
static uiBut * ui_but_anim_decorate_find_attached_button(uiButDecorator *but_decorate)
bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
void ui_but_anim_copy_driver(bContext *C)
void ui_but_anim_paste_driver(bContext *C)
void ui_but_anim_decorate_update_from_flag(uiButDecorator *decorator_but)
bool ui_but_anim_expression_set(uiBut *but, const char *str)
#define GS(x)
Definition: iris.c:241
bool fcurve_is_changed(PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, const AnimationEvalContext *anim_eval_context)
Definition: keyframing.c:2840
bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
Definition: keyframing.c:2813
bool ED_autokeyframe_property(bContext *C, Scene *scene, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, float cfra)
Definition: keyframing.c:3047
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
const char * RNA_struct_identifier(const StructRNA *type)
Definition: rna_access.c:723
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1223
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1145
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:6272
char * RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:6027
ListBase nla_tracks
char expression[256]
ChannelDriver * driver
short flag
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
void * first
Definition: DNA_listBase.h:47
struct StructRNA * type
Definition: RNA_types.h:51
void * data
Definition: RNA_types.h:52
struct ID * owner_id
Definition: RNA_types.h:50
ListBase buttons
void * evil_C
struct PropertyRNA * rnaprop
struct PointerRNA rnapoin
struct uiBut * prev
struct uiHandleButtonData * active
uiBlock * block
BIFIconID icon
struct PropertyRNA * rnaprop
struct PointerRNA rnapoin
#define G(x, y, z)
int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, short context, PointerRNA *properties)
wmOperatorType * ot
Definition: wm_files.c:3156
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:584
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:711