Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2008 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * 00022 * Contributor(s): Blender Foundation, Joshua Leung 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include <string.h> 00033 00034 #include "MEM_guardedalloc.h" 00035 00036 #include "DNA_anim_types.h" 00037 #include "DNA_armature_types.h" 00038 #include "DNA_object_types.h" 00039 #include "DNA_node_types.h" 00040 #include "DNA_scene_types.h" 00041 #include "DNA_sequence_types.h" 00042 00043 #include "BLI_blenlib.h" 00044 #include "BLI_utildefines.h" 00045 00046 #include "BKE_animsys.h" 00047 #include "BKE_action.h" 00048 #include "BKE_context.h" 00049 #include "BKE_depsgraph.h" 00050 #include "BKE_global.h" 00051 #include "BKE_node.h" 00052 #include "BKE_sequencer.h" 00053 #include "BKE_utildefines.h" 00054 00055 #include "RNA_access.h" 00056 00057 #include "ED_anim_api.h" 00058 00059 /* **************************** depsgraph tagging ******************************** */ 00060 00061 /* tags the given anim list element for refreshes (if applicable) 00062 * due to Animation Editor editing 00063 */ 00064 void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale) 00065 { 00066 ID *id; 00067 FCurve *fcu; 00068 AnimData *adt; 00069 00070 id= ale->id; 00071 if (!id) 00072 return; 00073 00074 /* tag AnimData for refresh so that other views will update in realtime with these changes */ 00075 adt= BKE_animdata_from_id(id); 00076 if (adt) 00077 adt->recalc |= ADT_RECALC_ANIM; 00078 00079 /* update data */ 00080 fcu= (ale->datatype == ALE_FCURVE)? ale->key_data: NULL; 00081 00082 if (fcu && fcu->rna_path) { 00083 /* if we have an fcurve, call the update for the property we 00084 are editing, this is then expected to do the proper redraws 00085 and depsgraph updates */ 00086 PointerRNA id_ptr, ptr; 00087 PropertyRNA *prop; 00088 00089 RNA_id_pointer_create(id, &id_ptr); 00090 00091 if(RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) 00092 RNA_property_update_main(G.main, scene, &ptr, prop); 00093 } 00094 else { 00095 /* in other case we do standard depsgaph update, ideally 00096 we'd be calling property update functions here too ... */ 00097 DAG_id_tag_update(id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX or do we want something more restrictive? 00098 } 00099 } 00100 00101 /* tags the given ID block for refreshes (if applicable) due to 00102 * Animation Editor editing */ 00103 void ANIM_id_update(Scene *UNUSED(scene), ID *id) 00104 { 00105 if (id) { 00106 AnimData *adt= BKE_animdata_from_id(id); 00107 00108 /* tag AnimData for refresh so that other views will update in realtime with these changes */ 00109 if (adt) 00110 adt->recalc |= ADT_RECALC_ANIM; 00111 00112 /* set recalc flags */ 00113 DAG_id_tag_update(id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX or do we want something more restrictive? 00114 } 00115 } 00116 00117 /* **************************** animation data <-> data syncing ******************************** */ 00118 /* This code here is used to synchronise the 00119 * - selection (to find selected data easier) 00120 * - ... (insert other relevant items here later) 00121 * status in relevant Blender data with the status stored in animation channels. 00122 * 00123 * This should be called in the refresh() callbacks for various editors in 00124 * response to appropriate notifiers. 00125 */ 00126 00127 /* perform syncing updates for Action Groups */ 00128 static void animchan_sync_group (bAnimContext *UNUSED(ac), bAnimListElem *ale) 00129 { 00130 bActionGroup *agrp= (bActionGroup *)ale->data; 00131 ID *owner_id= ale->id; 00132 00133 /* major priority is selection status 00134 * so we need both a group and an owner 00135 */ 00136 if (ELEM(NULL, agrp, owner_id)) 00137 return; 00138 00139 /* for standard Objects, check if group is the name of some bone */ 00140 if (GS(owner_id->name) == ID_OB) { 00141 Object *ob= (Object *)owner_id; 00142 00143 /* check if there are bones, and whether the name matches any 00144 * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone 00145 */ 00146 if (ob->pose) { 00147 bPoseChannel *pchan= get_pose_channel(ob->pose, agrp->name); 00148 00149 /* if one matches, sync the selection status */ 00150 if (pchan) { 00151 if (pchan->bone->flag & BONE_SELECTED) 00152 agrp->flag |= AGRP_SELECTED; 00153 else 00154 agrp->flag &= ~AGRP_SELECTED; 00155 } 00156 } 00157 } 00158 } 00159 00160 /* perform syncing updates for F-Curves */ 00161 static void animchan_sync_fcurve (bAnimContext *UNUSED(ac), bAnimListElem *ale) 00162 { 00163 FCurve *fcu= (FCurve *)ale->data; 00164 ID *owner_id= ale->id; 00165 00166 /* major priority is selection status, so refer to the checks done in anim_filter.c 00167 * skip_fcurve_selected_data() for reference about what's going on here... 00168 */ 00169 if (ELEM3(NULL, fcu, fcu->rna_path, owner_id)) 00170 return; 00171 00172 if (GS(owner_id->name) == ID_OB) { 00173 Object *ob= (Object *)owner_id; 00174 00175 /* only affect if F-Curve involves pose.bones */ 00176 if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) { 00177 bPoseChannel *pchan; 00178 char *bone_name; 00179 00180 /* get bone-name, and check if this bone is selected */ 00181 bone_name= BLI_getQuotedStr(fcu->rna_path, "pose.bones["); 00182 pchan= get_pose_channel(ob->pose, bone_name); 00183 if (bone_name) MEM_freeN(bone_name); 00184 00185 /* F-Curve selection depends on whether the bone is selected */ 00186 if ((pchan) && (pchan->bone)) { 00187 if (pchan->bone->flag & BONE_SELECTED) 00188 fcu->flag |= FCURVE_SELECTED; 00189 else 00190 fcu->flag &= ~FCURVE_SELECTED; 00191 } 00192 } 00193 } 00194 else if (GS(owner_id->name) == ID_SCE) { 00195 Scene *scene = (Scene *)owner_id; 00196 00197 /* only affect if F-Curve involves sequence_editor.sequences */ 00198 if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { 00199 Editing *ed= seq_give_editing(scene, FALSE); 00200 Sequence *seq; 00201 char *seq_name; 00202 00203 /* get strip name, and check if this strip is selected */ 00204 seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all["); 00205 seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE); 00206 if (seq_name) MEM_freeN(seq_name); 00207 00208 /* can only add this F-Curve if it is selected */ 00209 if (seq) { 00210 if (seq->flag & SELECT) 00211 fcu->flag |= FCURVE_SELECTED; 00212 else 00213 fcu->flag &= ~FCURVE_SELECTED; 00214 } 00215 } 00216 } 00217 else if (GS(owner_id->name) == ID_NT) { 00218 bNodeTree *ntree = (bNodeTree *)owner_id; 00219 00220 /* check for selected nodes */ 00221 if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) { 00222 bNode *node; 00223 char *node_name; 00224 00225 /* get strip name, and check if this strip is selected */ 00226 node_name= BLI_getQuotedStr(fcu->rna_path, "nodes["); 00227 node = nodeFindNodebyName(ntree, node_name); 00228 if (node_name) MEM_freeN(node_name); 00229 00230 /* can only add this F-Curve if it is selected */ 00231 if (node) { 00232 if (node->flag & NODE_SELECT) 00233 fcu->flag |= FCURVE_SELECTED; 00234 else 00235 fcu->flag &= ~FCURVE_SELECTED; 00236 } 00237 } 00238 } 00239 } 00240 00241 /* ---------------- */ 00242 00243 /* Main call to be exported to animation editors */ 00244 void ANIM_sync_animchannels_to_data (const bContext *C) 00245 { 00246 bAnimContext ac; 00247 ListBase anim_data = {NULL, NULL}; 00248 bAnimListElem *ale; 00249 int filter; 00250 00251 /* get animation context info for filtering the channels */ 00252 // TODO: check on whether we need to set the area specially instead, since active area might not be ok? 00253 if (ANIM_animdata_get_context(C, &ac) == 0) 00254 return; 00255 00256 /* filter data */ 00257 /* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed */ 00258 filter= ANIMFILTER_DATA_VISIBLE|ANIMFILTER_LIST_CHANNELS; 00259 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 00260 00261 /* flush settings as appropriate depending on the types of the channels */ 00262 for (ale= anim_data.first; ale; ale= ale->next) { 00263 switch (ale->type) { 00264 case ANIMTYPE_GROUP: 00265 animchan_sync_group(&ac, ale); 00266 break; 00267 00268 case ANIMTYPE_FCURVE: 00269 animchan_sync_fcurve(&ac, ale); 00270 break; 00271 } 00272 } 00273 00274 BLI_freelistN(&anim_data); 00275 }