4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2008 Blender Foundation.
21 * All rights reserved.
24 * Contributor(s): Blender Foundation, Joshua Leung
26 * ***** END GPL LICENSE BLOCK *****
29 /** \file blender/editors/animation/anim_deps.c
30 * \ingroup edanimation
36 #include "MEM_guardedalloc.h"
38 #include "DNA_anim_types.h"
39 #include "DNA_armature_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_node_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_sequence_types.h"
45 #include "BLI_blenlib.h"
46 #include "BLI_utildefines.h"
48 #include "BKE_animsys.h"
49 #include "BKE_action.h"
50 #include "BKE_context.h"
51 #include "BKE_depsgraph.h"
52 #include "BKE_global.h"
54 #include "BKE_sequencer.h"
55 #include "BKE_utildefines.h"
57 #include "RNA_access.h"
59 #include "ED_anim_api.h"
61 /* **************************** depsgraph tagging ******************************** */
63 /* tags the given anim list element for refreshes (if applicable)
64 * due to Animation Editor editing
66 void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
76 /* tag AnimData for refresh so that other views will update in realtime with these changes */
77 adt= BKE_animdata_from_id(id);
79 adt->recalc |= ADT_RECALC_ANIM;
82 fcu= (ale->datatype == ALE_FCURVE)? ale->key_data: NULL;
84 if (fcu && fcu->rna_path) {
85 /* if we have an fcurve, call the update for the property we
86 are editing, this is then expected to do the proper redraws
87 and depsgraph updates */
88 PointerRNA id_ptr, ptr;
91 RNA_id_pointer_create(id, &id_ptr);
93 if(RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop))
94 RNA_property_update_main(G.main, scene, &ptr, prop);
97 /* in other case we do standard depsgaph update, ideally
98 we'd be calling property update functions here too ... */
99 DAG_id_tag_update(id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX or do we want something more restrictive?
103 /* tags the given ID block for refreshes (if applicable) due to
104 * Animation Editor editing */
105 void ANIM_id_update(Scene *UNUSED(scene), ID *id)
108 AnimData *adt= BKE_animdata_from_id(id);
110 /* tag AnimData for refresh so that other views will update in realtime with these changes */
112 adt->recalc |= ADT_RECALC_ANIM;
114 /* set recalc flags */
115 DAG_id_tag_update(id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX or do we want something more restrictive?
119 /* **************************** animation data <-> data syncing ******************************** */
120 /* This code here is used to synchronise the
121 * - selection (to find selected data easier)
122 * - ... (insert other relevant items here later)
123 * status in relevant Blender data with the status stored in animation channels.
125 * This should be called in the refresh() callbacks for various editors in
126 * response to appropriate notifiers.
129 /* perform syncing updates for Action Groups */
130 static void animchan_sync_group (bAnimContext *UNUSED(ac), bAnimListElem *ale)
132 bActionGroup *agrp= (bActionGroup *)ale->data;
133 ID *owner_id= ale->id;
135 /* major priority is selection status
136 * so we need both a group and an owner
138 if (ELEM(NULL, agrp, owner_id))
141 /* for standard Objects, check if group is the name of some bone */
142 if (GS(owner_id->name) == ID_OB) {
143 Object *ob= (Object *)owner_id;
145 /* check if there are bones, and whether the name matches any
146 * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone
149 bPoseChannel *pchan= get_pose_channel(ob->pose, agrp->name);
151 /* if one matches, sync the selection status */
153 if (pchan->bone->flag & BONE_SELECTED)
154 agrp->flag |= AGRP_SELECTED;
156 agrp->flag &= ~AGRP_SELECTED;
162 /* perform syncing updates for F-Curves */
163 static void animchan_sync_fcurve (bAnimContext *UNUSED(ac), bAnimListElem *ale)
165 FCurve *fcu= (FCurve *)ale->data;
166 ID *owner_id= ale->id;
168 /* major priority is selection status, so refer to the checks done in anim_filter.c
169 * skip_fcurve_selected_data() for reference about what's going on here...
171 if (ELEM3(NULL, fcu, fcu->rna_path, owner_id))
174 if (GS(owner_id->name) == ID_OB) {
175 Object *ob= (Object *)owner_id;
177 /* only affect if F-Curve involves pose.bones */
178 if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
182 /* get bone-name, and check if this bone is selected */
183 bone_name= BLI_getQuotedStr(fcu->rna_path, "pose.bones[");
184 pchan= get_pose_channel(ob->pose, bone_name);
185 if (bone_name) MEM_freeN(bone_name);
187 /* F-Curve selection depends on whether the bone is selected */
188 if ((pchan) && (pchan->bone)) {
189 if (pchan->bone->flag & BONE_SELECTED)
190 fcu->flag |= FCURVE_SELECTED;
192 fcu->flag &= ~FCURVE_SELECTED;
196 else if (GS(owner_id->name) == ID_SCE) {
197 Scene *scene = (Scene *)owner_id;
199 /* only affect if F-Curve involves sequence_editor.sequences */
200 if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
201 Editing *ed= seq_give_editing(scene, FALSE);
205 /* get strip name, and check if this strip is selected */
206 seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all[");
207 seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE);
208 if (seq_name) MEM_freeN(seq_name);
210 /* can only add this F-Curve if it is selected */
212 if (seq->flag & SELECT)
213 fcu->flag |= FCURVE_SELECTED;
215 fcu->flag &= ~FCURVE_SELECTED;
219 else if (GS(owner_id->name) == ID_NT) {
220 bNodeTree *ntree = (bNodeTree *)owner_id;
222 /* check for selected nodes */
223 if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
227 /* get strip name, and check if this strip is selected */
228 node_name= BLI_getQuotedStr(fcu->rna_path, "nodes[");
229 node = nodeFindNodebyName(ntree, node_name);
230 if (node_name) MEM_freeN(node_name);
232 /* can only add this F-Curve if it is selected */
234 if (node->flag & NODE_SELECT)
235 fcu->flag |= FCURVE_SELECTED;
237 fcu->flag &= ~FCURVE_SELECTED;
243 /* ---------------- */
245 /* Main call to be exported to animation editors */
246 void ANIM_sync_animchannels_to_data (const bContext *C)
249 ListBase anim_data = {NULL, NULL};
253 /* get animation context info for filtering the channels */
254 // TODO: check on whether we need to set the area specially instead, since active area might not be ok?
255 if (ANIM_animdata_get_context(C, &ac) == 0)
259 /* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed */
260 filter= ANIMFILTER_CHANNELS;
261 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
263 /* flush settings as appropriate depending on the types of the channels */
264 for (ale= anim_data.first; ale; ale= ale->next) {
267 animchan_sync_group(&ac, ale);
270 case ANIMTYPE_FCURVE:
271 animchan_sync_fcurve(&ac, ale);
276 BLI_freelistN(&anim_data);