2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2008 Blender Foundation.
19 * All rights reserved.
22 * Contributor(s): Blender Foundation, Joshua Leung
24 * ***** END GPL LICENSE BLOCK *****
27 /** \file blender/editors/animation/anim_deps.c
28 * \ingroup edanimation
34 #include "MEM_guardedalloc.h"
36 #include "DNA_anim_types.h"
37 #include "DNA_armature_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_node_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_sequence_types.h"
43 #include "BLI_blenlib.h"
44 #include "BLI_utildefines.h"
46 #include "BKE_animsys.h"
47 #include "BKE_action.h"
48 #include "BKE_context.h"
49 #include "BKE_depsgraph.h"
50 #include "BKE_global.h"
52 #include "BKE_sequencer.h"
53 #include "BKE_utildefines.h"
55 #include "RNA_access.h"
57 #include "ED_anim_api.h"
59 /* **************************** depsgraph tagging ******************************** */
61 /* tags the given anim list element for refreshes (if applicable)
62 * due to Animation Editor editing
64 void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
74 /* tag AnimData for refresh so that other views will update in realtime with these changes */
75 adt= BKE_animdata_from_id(id);
77 adt->recalc |= ADT_RECALC_ANIM;
80 fcu= (ale->datatype == ALE_FCURVE)? ale->key_data: NULL;
82 if (fcu && fcu->rna_path) {
83 /* if we have an fcurve, call the update for the property we
84 are editing, this is then expected to do the proper redraws
85 and depsgraph updates */
86 PointerRNA id_ptr, ptr;
89 RNA_id_pointer_create(id, &id_ptr);
91 if(RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop))
92 RNA_property_update_main(G.main, scene, &ptr, prop);
95 /* in other case we do standard depsgaph update, ideally
96 we'd be calling property update functions here too ... */
97 DAG_id_tag_update(id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX or do we want something more restrictive?
101 /* tags the given ID block for refreshes (if applicable) due to
102 * Animation Editor editing */
103 void ANIM_id_update(Scene *UNUSED(scene), ID *id)
106 AnimData *adt= BKE_animdata_from_id(id);
108 /* tag AnimData for refresh so that other views will update in realtime with these changes */
110 adt->recalc |= ADT_RECALC_ANIM;
112 /* set recalc flags */
113 DAG_id_tag_update(id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX or do we want something more restrictive?
117 /* **************************** animation data <-> data syncing ******************************** */
118 /* This code here is used to synchronise the
119 * - selection (to find selected data easier)
120 * - ... (insert other relevant items here later)
121 * status in relevant Blender data with the status stored in animation channels.
123 * This should be called in the refresh() callbacks for various editors in
124 * response to appropriate notifiers.
127 /* perform syncing updates for Action Groups */
128 static void animchan_sync_group (bAnimContext *UNUSED(ac), bAnimListElem *ale)
130 bActionGroup *agrp= (bActionGroup *)ale->data;
131 ID *owner_id= ale->id;
133 /* major priority is selection status
134 * so we need both a group and an owner
136 if (ELEM(NULL, agrp, owner_id))
139 /* for standard Objects, check if group is the name of some bone */
140 if (GS(owner_id->name) == ID_OB) {
141 Object *ob= (Object *)owner_id;
143 /* check if there are bones, and whether the name matches any
144 * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone
147 bPoseChannel *pchan= get_pose_channel(ob->pose, agrp->name);
149 /* if one matches, sync the selection status */
151 if (pchan->bone->flag & BONE_SELECTED)
152 agrp->flag |= AGRP_SELECTED;
154 agrp->flag &= ~AGRP_SELECTED;
160 /* perform syncing updates for F-Curves */
161 static void animchan_sync_fcurve (bAnimContext *UNUSED(ac), bAnimListElem *ale)
163 FCurve *fcu= (FCurve *)ale->data;
164 ID *owner_id= ale->id;
166 /* major priority is selection status, so refer to the checks done in anim_filter.c
167 * skip_fcurve_selected_data() for reference about what's going on here...
169 if (ELEM3(NULL, fcu, fcu->rna_path, owner_id))
172 if (GS(owner_id->name) == ID_OB) {
173 Object *ob= (Object *)owner_id;
175 /* only affect if F-Curve involves pose.bones */
176 if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) {
180 /* get bone-name, and check if this bone is selected */
181 bone_name= BLI_getQuotedStr(fcu->rna_path, "pose.bones[");
182 pchan= get_pose_channel(ob->pose, bone_name);
183 if (bone_name) MEM_freeN(bone_name);
185 /* F-Curve selection depends on whether the bone is selected */
186 if ((pchan) && (pchan->bone)) {
187 if (pchan->bone->flag & BONE_SELECTED)
188 fcu->flag |= FCURVE_SELECTED;
190 fcu->flag &= ~FCURVE_SELECTED;
194 else if (GS(owner_id->name) == ID_SCE) {
195 Scene *scene = (Scene *)owner_id;
197 /* only affect if F-Curve involves sequence_editor.sequences */
198 if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
199 Editing *ed= seq_give_editing(scene, FALSE);
203 /* get strip name, and check if this strip is selected */
204 seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all[");
205 seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE);
206 if (seq_name) MEM_freeN(seq_name);
208 /* can only add this F-Curve if it is selected */
210 if (seq->flag & SELECT)
211 fcu->flag |= FCURVE_SELECTED;
213 fcu->flag &= ~FCURVE_SELECTED;
217 else if (GS(owner_id->name) == ID_NT) {
218 bNodeTree *ntree = (bNodeTree *)owner_id;
220 /* check for selected nodes */
221 if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) {
225 /* get strip name, and check if this strip is selected */
226 node_name= BLI_getQuotedStr(fcu->rna_path, "nodes[");
227 node = nodeFindNodebyName(ntree, node_name);
228 if (node_name) MEM_freeN(node_name);
230 /* can only add this F-Curve if it is selected */
232 if (node->flag & NODE_SELECT)
233 fcu->flag |= FCURVE_SELECTED;
235 fcu->flag &= ~FCURVE_SELECTED;
241 /* ---------------- */
243 /* Main call to be exported to animation editors */
244 void ANIM_sync_animchannels_to_data (const bContext *C)
247 ListBase anim_data = {NULL, NULL};
251 /* get animation context info for filtering the channels */
252 // TODO: check on whether we need to set the area specially instead, since active area might not be ok?
253 if (ANIM_animdata_get_context(C, &ac) == 0)
257 /* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed */
258 filter= ANIMFILTER_DATA_VISIBLE|ANIMFILTER_LIST_CHANNELS;
259 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
261 /* flush settings as appropriate depending on the types of the channels */
262 for (ale= anim_data.first; ale; ale= ale->next) {
265 animchan_sync_group(&ac, ale);
268 case ANIMTYPE_FCURVE:
269 animchan_sync_fcurve(&ac, ale);
274 BLI_freelistN(&anim_data);