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) 2009 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 #include <stdio.h> 00034 #include <math.h> 00035 #include <float.h> 00036 00037 #include "DNA_anim_types.h" 00038 #include "DNA_object_types.h" 00039 #include "DNA_scene_types.h" 00040 00041 #include "MEM_guardedalloc.h" 00042 00043 #include "BLI_math.h" 00044 #include "BLI_blenlib.h" 00045 #include "BLI_editVert.h" 00046 #include "BLI_rand.h" 00047 #include "BLI_utildefines.h" 00048 00049 #include "BLF_translation.h" 00050 00051 #include "BKE_context.h" 00052 #include "BKE_depsgraph.h" 00053 #include "BKE_fcurve.h" 00054 #include "BKE_main.h" 00055 #include "BKE_screen.h" 00056 #include "BKE_unit.h" 00057 00058 00059 #include "WM_api.h" 00060 #include "WM_types.h" 00061 00062 #include "RNA_access.h" 00063 00064 #include "ED_anim_api.h" 00065 #include "ED_keyframing.h" 00066 #include "ED_screen.h" 00067 00068 #include "UI_interface.h" 00069 #include "UI_resources.h" 00070 00071 #include "graph_intern.h" // own include 00072 00073 /* XXX */ 00074 00075 /* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */ 00076 #define UI_FLT_MAX 10000.0f 00077 00078 00079 /* ******************* graph editor space & buttons ************** */ 00080 00081 #define B_REDR 1 00082 00083 /* -------------- */ 00084 00085 static void do_graph_region_buttons(bContext *UNUSED(C), void *UNUSED(arg), int event) 00086 { 00087 //Scene *scene= CTX_data_scene(C); 00088 00089 switch(event) { 00090 00091 } 00092 00093 /* default for now */ 00094 //WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); 00095 } 00096 00097 /* -------------- */ 00098 00099 static int graph_panel_context(const bContext *C, bAnimListElem **ale, FCurve **fcu) 00100 { 00101 bAnimContext ac; 00102 bAnimListElem *elem= NULL; 00103 00104 /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools) 00105 * to work correctly is able to be correctly retrieved. There's no point showing empty panels? 00106 */ 00107 if (ANIM_animdata_get_context(C, &ac) == 0) 00108 return 0; 00109 00110 /* try to find 'active' F-Curve */ 00111 elem= get_active_fcurve_channel(&ac); 00112 if(elem == NULL) 00113 return 0; 00114 00115 if(fcu) 00116 *fcu= (FCurve*)elem->data; 00117 if(ale) 00118 *ale= elem; 00119 else 00120 MEM_freeN(elem); 00121 00122 return 1; 00123 } 00124 00125 static int graph_panel_poll(const bContext *C, PanelType *UNUSED(pt)) 00126 { 00127 return graph_panel_context(C, NULL, NULL); 00128 } 00129 00130 /* -------------- */ 00131 00132 /* Graph Editor View Settings */ 00133 static void graph_panel_view(const bContext *C, Panel *pa) 00134 { 00135 bScreen *sc= CTX_wm_screen(C); 00136 SpaceIpo *sipo= CTX_wm_space_graph(C); 00137 Scene *scene= CTX_data_scene(C); 00138 PointerRNA spaceptr, sceneptr; 00139 uiLayout *col, *sub, *row; 00140 00141 /* get RNA pointers for use when creating the UI elements */ 00142 RNA_id_pointer_create(&scene->id, &sceneptr); 00143 RNA_pointer_create(&sc->id, &RNA_SpaceGraphEditor, sipo, &spaceptr); 00144 00145 /* 2D-Cursor */ 00146 col= uiLayoutColumn(pa->layout, 0); 00147 uiItemR(col, &spaceptr, "show_cursor", 0, NULL, ICON_NONE); 00148 00149 sub= uiLayoutColumn(col, 1); 00150 uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor")); 00151 uiItemO(sub, "Cursor from Selection", ICON_NONE, "GRAPH_OT_frame_jump"); 00152 00153 sub= uiLayoutColumn(col, 1); 00154 uiLayoutSetActive(sub, RNA_boolean_get(&spaceptr, "show_cursor")); 00155 row= uiLayoutSplit(sub, 0.7, 1); 00156 uiItemR(row, &sceneptr, "frame_current", 0, "Cursor X", ICON_NONE); 00157 uiItemEnumO(row, "GRAPH_OT_snap", "To Keys", 0, "type", GRAPHKEYS_SNAP_CFRA); 00158 row= uiLayoutSplit(sub, 0.7, 1); 00159 uiItemR(row, &spaceptr, "cursor_position_y", 0, "Cursor Y", ICON_NONE); 00160 uiItemEnumO(row, "GRAPH_OT_snap", "To Keys", 0, "type", GRAPHKEYS_SNAP_VALUE); 00161 } 00162 00163 /* ******************* active F-Curve ************** */ 00164 00165 static void graph_panel_properties(const bContext *C, Panel *pa) 00166 { 00167 bAnimListElem *ale; 00168 FCurve *fcu; 00169 PointerRNA fcu_ptr; 00170 uiLayout *layout = pa->layout; 00171 uiLayout *col, *row, *sub; 00172 uiBlock *block; 00173 char name[256]; 00174 int icon = 0; 00175 00176 if (!graph_panel_context(C, &ale, &fcu)) 00177 return; 00178 00179 block= uiLayoutGetBlock(layout); 00180 uiBlockSetHandleFunc(block, do_graph_region_buttons, NULL); 00181 00182 /* F-Curve pointer */ 00183 RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr); 00184 00185 /* user-friendly 'name' for F-Curve */ 00186 // TODO: only show the path if this is invalid? 00187 col= uiLayoutColumn(layout, 0); 00188 icon= getname_anim_fcurve(name, ale->id, fcu); 00189 uiItemL(col, name, icon); 00190 00191 /* RNA-Path Editing - only really should be enabled when things aren't working */ 00192 col= uiLayoutColumn(layout, 1); 00193 uiLayoutSetEnabled(col, (fcu->flag & FCURVE_DISABLED)!=0); 00194 uiItemR(col, &fcu_ptr, "data_path", 0, "", ICON_RNA); 00195 uiItemR(col, &fcu_ptr, "array_index", 0, NULL, ICON_NONE); 00196 00197 /* color settings */ 00198 col= uiLayoutColumn(layout, 1); 00199 uiItemL(col, "Display Color:", ICON_NONE); 00200 00201 row= uiLayoutRow(col, 1); 00202 uiItemR(row, &fcu_ptr, "color_mode", 0, "", ICON_NONE); 00203 00204 sub= uiLayoutRow(row, 1); 00205 uiLayoutSetEnabled(sub, (fcu->color_mode==FCURVE_COLOR_CUSTOM)); 00206 uiItemR(sub, &fcu_ptr, "color", 0, "", ICON_NONE); 00207 00208 MEM_freeN(ale); 00209 } 00210 00211 /* ******************* active Keyframe ************** */ 00212 00213 /* get 'active' keyframe for panel editing */ 00214 static short get_active_fcurve_keyframe_edit(FCurve *fcu, BezTriple **bezt, BezTriple **prevbezt) 00215 { 00216 BezTriple *b; 00217 int i; 00218 00219 /* zero the pointers */ 00220 *bezt = *prevbezt = NULL; 00221 00222 /* sanity checks */ 00223 if ((fcu->bezt == NULL) || (fcu->totvert == 0)) 00224 return 0; 00225 00226 /* find first selected keyframe for now, and call it the active one 00227 * - this is a reasonable assumption, given that whenever anyone 00228 * wants to edit numerically, there is likely to only be 1 vert selected 00229 */ 00230 for (i=0, b=fcu->bezt; i < fcu->totvert; i++, b++) { 00231 if (BEZSELECTED(b)) { 00232 /* found 00233 * - 'previous' is either the one before, of the keyframe itself (which is still fine) 00234 * XXX: we can just make this null instead if needed 00235 */ 00236 *prevbezt = (i > 0) ? b-1 : b; 00237 *bezt = b; 00238 00239 return 1; 00240 } 00241 } 00242 00243 /* not found */ 00244 return 0; 00245 } 00246 00247 /* update callback for active keyframe properties - base updates stuff */ 00248 static void graphedit_activekey_update_cb(bContext *C, void *fcu_ptr, void *UNUSED(bezt_ptr)) 00249 { 00250 SpaceIpo *sipo= CTX_wm_space_graph(C); 00251 const short use_handle = !(sipo->flag & SIPO_NOHANDLES); 00252 FCurve *fcu = (FCurve *)fcu_ptr; 00253 00254 /* make sure F-Curve and its handles are still valid after this editing */ 00255 sort_time_fcurve(fcu); 00256 testhandles_fcurve(fcu, use_handle); 00257 } 00258 00259 /* update callback for active keyframe properties - handle-editing wrapper */ 00260 static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bezt_ptr) 00261 { 00262 BezTriple *bezt = (BezTriple *)bezt_ptr; 00263 00264 /* since editing the handles, make sure they're set to types which are receptive to editing 00265 * see transform_conversions.c :: createTransGraphEditData(), last step in second loop 00266 */ 00267 if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { 00268 /* by changing to aligned handles, these can now be moved... */ 00269 bezt->h1= HD_ALIGN; 00270 bezt->h2= HD_ALIGN; 00271 } 00272 00273 /* now call standard updates */ 00274 graphedit_activekey_update_cb(C, fcu_ptr, bezt_ptr); 00275 } 00276 00277 static void graph_panel_key_properties(const bContext *C, Panel *pa) 00278 { 00279 bAnimListElem *ale; 00280 FCurve *fcu; 00281 BezTriple *bezt, *prevbezt; 00282 00283 uiLayout *layout = pa->layout; 00284 uiLayout *col; 00285 uiBlock *block; 00286 00287 if (!graph_panel_context(C, &ale, &fcu)) 00288 return; 00289 00290 block = uiLayoutGetBlock(layout); 00291 uiBlockSetHandleFunc(block, do_graph_region_buttons, NULL); 00292 00293 /* only show this info if there are keyframes to edit */ 00294 if (get_active_fcurve_keyframe_edit(fcu, &bezt, &prevbezt)) { 00295 PointerRNA bezt_ptr, id_ptr, fcu_prop_ptr; 00296 PropertyRNA *fcu_prop = NULL; 00297 uiBut *but; 00298 int unit = B_UNIT_NONE; 00299 00300 /* RNA pointer to keyframe, to allow editing */ 00301 RNA_pointer_create(ale->id, &RNA_Keyframe, bezt, &bezt_ptr); 00302 00303 /* get property that F-Curve affects, for some unit-conversion magic */ 00304 RNA_id_pointer_create(ale->id, &id_ptr); 00305 if (RNA_path_resolve(&id_ptr, fcu->rna_path, &fcu_prop_ptr, &fcu_prop) && fcu_prop) { 00306 /* determine the unit for this property */ 00307 unit = RNA_SUBTYPE_UNIT(RNA_property_subtype(fcu_prop)); 00308 } 00309 00310 /* interpolation */ 00311 col= uiLayoutColumn(layout, 0); 00312 uiItemR(col, &bezt_ptr, "interpolation", 0, NULL, ICON_NONE); 00313 00314 /* numerical coordinate editing 00315 * - we use the button-versions of the calls so that we can attach special update handlers 00316 * and unit conversion magic that cannot be achieved using a purely RNA-approach 00317 */ 00318 // XXX: 00319 col= uiLayoutColumn(layout, 1); 00320 /* keyframe itself */ 00321 { 00322 uiItemL(col, "Key:", ICON_NONE); 00323 00324 but = uiDefButR(block, NUM, B_REDR, "Frame", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "co", 0, 0, 0, -1, -1, NULL); 00325 uiButSetFunc(but, graphedit_activekey_update_cb, fcu, bezt); 00326 00327 but = uiDefButR(block, NUM, B_REDR, "Value", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "co", 1, 0, 0, -1, -1, NULL); 00328 uiButSetFunc(but, graphedit_activekey_update_cb, fcu, bezt); 00329 uiButSetUnitType(but, unit); 00330 } 00331 00332 /* previous handle - only if previous was Bezier interpolation */ 00333 if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) { 00334 uiItemL(col, "Left Handle:", ICON_NONE); 00335 00336 but = uiDefButR(block, NUM, B_REDR, "X", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_left", 0, 0, 0, -1, -1, NULL); 00337 uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt); 00338 00339 but = uiDefButR(block, NUM, B_REDR, "Y", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_left", 1, 0, 0, -1, -1, NULL); 00340 uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt); 00341 uiButSetUnitType(but, unit); 00342 } 00343 00344 /* next handle - only if current is Bezier interpolation */ 00345 if (bezt->ipo == BEZT_IPO_BEZ) { 00346 uiItemL(col, "Right Handle:", ICON_NONE); 00347 00348 but = uiDefButR(block, NUM, B_REDR, "X", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_right", 0, 0, 0, -1, -1, NULL); 00349 uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt); 00350 00351 but = uiDefButR(block, NUM, B_REDR, "Y", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_right", 1, 0, 0, -1, -1, NULL); 00352 uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt); 00353 uiButSetUnitType(but, unit); 00354 } 00355 } 00356 else { 00357 if ((fcu->bezt == NULL) && (fcu->modifiers.first)) { 00358 /* modifiers only - so no keyframes to be active */ 00359 uiItemL(layout, "F-Curve only has F-Modifiers", ICON_NONE); 00360 uiItemL(layout, "See Modifiers panel below", ICON_INFO); 00361 } 00362 else if (fcu->fpt) { 00363 /* samples only */ 00364 uiItemL(layout, "F-Curve doesn't have any keyframes as it only contains sampled points", ICON_NONE); 00365 } 00366 else 00367 uiItemL(layout, "No active keyframe on F-Curve", ICON_NONE); 00368 } 00369 00370 MEM_freeN(ale); 00371 } 00372 00373 /* ******************* drivers ******************************** */ 00374 00375 #define B_IPO_DEPCHANGE 10 00376 00377 static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int event) 00378 { 00379 Main *bmain= CTX_data_main(C); 00380 Scene *scene= CTX_data_scene(C); 00381 00382 switch (event) { 00383 case B_IPO_DEPCHANGE: 00384 { 00385 /* rebuild depsgraph for the new deps */ 00386 DAG_scene_sort(bmain, scene); 00387 00388 /* force an update of depsgraph */ 00389 DAG_ids_flush_update(bmain, 0); 00390 } 00391 break; 00392 } 00393 00394 /* default for now */ 00395 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); // XXX could use better notifier 00396 } 00397 00398 /* callback to remove the active driver */ 00399 static void driver_remove_cb (bContext *C, void *ale_v, void *UNUSED(arg)) 00400 { 00401 bAnimListElem *ale= (bAnimListElem *)ale_v; 00402 ID *id= ale->id; 00403 FCurve *fcu= ale->data; 00404 ReportList *reports = CTX_wm_reports(C); 00405 00406 /* try to get F-Curve that driver lives on, and ID block which has this AnimData */ 00407 if (ELEM(NULL, id, fcu)) 00408 return; 00409 00410 /* call API method to remove this driver */ 00411 ANIM_remove_driver(reports, id, fcu->rna_path, fcu->array_index, 0); 00412 } 00413 00414 /* callback to add a target variable to the active driver */ 00415 static void driver_add_var_cb (bContext *UNUSED(C), void *driver_v, void *UNUSED(arg)) 00416 { 00417 ChannelDriver *driver= (ChannelDriver *)driver_v; 00418 00419 /* add a new variable */ 00420 driver_add_new_variable(driver); 00421 } 00422 00423 /* callback to remove target variable from active driver */ 00424 static void driver_delete_var_cb (bContext *UNUSED(C), void *driver_v, void *dvar_v) 00425 { 00426 ChannelDriver *driver= (ChannelDriver *)driver_v; 00427 DriverVar *dvar= (DriverVar *)dvar_v; 00428 00429 /* remove the active variable */ 00430 driver_free_variable(driver, dvar); 00431 } 00432 00433 /* callback to reset the driver's flags */ 00434 static void driver_update_flags_cb (bContext *UNUSED(C), void *fcu_v, void *UNUSED(arg)) 00435 { 00436 FCurve *fcu= (FCurve *)fcu_v; 00437 ChannelDriver *driver= fcu->driver; 00438 00439 /* clear invalid flags */ 00440 fcu->flag &= ~FCURVE_DISABLED; // XXX? 00441 driver->flag &= ~DRIVER_FLAG_INVALID; 00442 } 00443 00444 /* drivers panel poll */ 00445 static int graph_panel_drivers_poll(const bContext *C, PanelType *UNUSED(pt)) 00446 { 00447 SpaceIpo *sipo= CTX_wm_space_graph(C); 00448 00449 if(sipo->mode != SIPO_MODE_DRIVERS) 00450 return 0; 00451 00452 return graph_panel_context(C, NULL, NULL); 00453 } 00454 00455 /* settings for 'single property' driver variable type */ 00456 static void graph_panel_driverVar__singleProp(uiLayout *layout, ID *id, DriverVar *dvar) 00457 { 00458 DriverTarget *dtar= &dvar->targets[0]; 00459 PointerRNA dtar_ptr; 00460 uiLayout *row, *col; 00461 00462 /* initialise RNA pointer to the target */ 00463 RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); 00464 00465 /* Target ID */ 00466 row= uiLayoutRow(layout, 0); 00467 uiTemplateAnyID(row, &dtar_ptr, "id", "id_type", "Prop:"); 00468 00469 /* Target Property */ 00470 // TODO: make this less technical... 00471 if (dtar->id) { 00472 PointerRNA root_ptr; 00473 00474 /* get pointer for resolving the property selected */ 00475 RNA_id_pointer_create(dtar->id, &root_ptr); 00476 00477 col= uiLayoutColumn(layout, 1); 00478 /* rna path */ 00479 uiTemplatePathBuilder(col, &dtar_ptr, "data_path", &root_ptr, "Path"); 00480 } 00481 } 00482 00483 /* settings for 'rotation difference' driver variable type */ 00484 static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *dvar) 00485 { 00486 DriverTarget *dtar= &dvar->targets[0]; 00487 DriverTarget *dtar2= &dvar->targets[1]; 00488 Object *ob1 = (Object *)dtar->id; 00489 Object *ob2 = (Object *)dtar2->id; 00490 PointerRNA dtar_ptr, dtar2_ptr; 00491 uiLayout *col; 00492 00493 /* initialise RNA pointer to the target */ 00494 RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); 00495 RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); 00496 00497 /* Bone 1 */ 00498 col= uiLayoutColumn(layout, 1); 00499 uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", "Bone 1:"); 00500 00501 if (dtar->id && ob1->pose) { 00502 PointerRNA tar_ptr; 00503 00504 RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); 00505 uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); 00506 } 00507 00508 col= uiLayoutColumn(layout, 1); 00509 uiTemplateAnyID(col, &dtar2_ptr, "id", "id_type", "Bone 2:"); 00510 00511 if (dtar2->id && ob2->pose) { 00512 PointerRNA tar_ptr; 00513 00514 RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); 00515 uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); 00516 } 00517 } 00518 00519 /* settings for 'location difference' driver variable type */ 00520 static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *dvar) 00521 { 00522 DriverTarget *dtar= &dvar->targets[0]; 00523 DriverTarget *dtar2= &dvar->targets[1]; 00524 Object *ob1 = (Object *)dtar->id; 00525 Object *ob2 = (Object *)dtar2->id; 00526 PointerRNA dtar_ptr, dtar2_ptr; 00527 uiLayout *col; 00528 00529 /* initialise RNA pointer to the target */ 00530 RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); 00531 RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); 00532 00533 /* Bone 1 */ 00534 col= uiLayoutColumn(layout, 1); 00535 uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", "Ob/Bone 1:"); 00536 00537 if (dtar->id && ob1->pose) { 00538 PointerRNA tar_ptr; 00539 00540 RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); 00541 uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); 00542 } 00543 00544 uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE); 00545 00546 col= uiLayoutColumn(layout, 1); 00547 uiTemplateAnyID(col, &dtar2_ptr, "id", "id_type", "Ob/Bone 2:"); 00548 00549 if (dtar2->id && ob2->pose) { 00550 PointerRNA tar_ptr; 00551 00552 RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); 00553 uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); 00554 } 00555 00556 uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE); 00557 } 00558 00559 /* settings for 'transform channel' driver variable type */ 00560 static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar *dvar) 00561 { 00562 DriverTarget *dtar= &dvar->targets[0]; 00563 Object *ob = (Object *)dtar->id; 00564 PointerRNA dtar_ptr; 00565 uiLayout *col, *sub; 00566 00567 /* initialise RNA pointer to the target */ 00568 RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); 00569 00570 /* properties */ 00571 col= uiLayoutColumn(layout, 1); 00572 uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", "Ob/Bone:"); 00573 00574 if (dtar->id && ob->pose) { 00575 PointerRNA tar_ptr; 00576 00577 RNA_pointer_create(dtar->id, &RNA_Pose, ob->pose, &tar_ptr); 00578 uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); 00579 } 00580 00581 sub= uiLayoutColumn(layout, 1); 00582 uiItemR(sub, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE); 00583 uiItemR(sub, &dtar_ptr, "transform_space", 0, "Space", ICON_NONE); 00584 } 00585 00586 /* driver settings for active F-Curve (only for 'Drivers' mode) */ 00587 static void graph_panel_drivers(const bContext *C, Panel *pa) 00588 { 00589 bAnimListElem *ale; 00590 FCurve *fcu; 00591 ChannelDriver *driver; 00592 DriverVar *dvar; 00593 00594 PointerRNA driver_ptr; 00595 uiLayout *col; 00596 uiBlock *block; 00597 uiBut *but; 00598 00599 /* Get settings from context */ 00600 if (!graph_panel_context(C, &ale, &fcu)) 00601 return; 00602 driver= fcu->driver; 00603 00604 /* set event handler for panel */ 00605 block= uiLayoutGetBlock(pa->layout); // xxx? 00606 uiBlockSetHandleFunc(block, do_graph_region_driver_buttons, NULL); 00607 00608 /* general actions - management */ 00609 col= uiLayoutColumn(pa->layout, 0); 00610 block= uiLayoutGetBlock(col); 00611 but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Update Dependencies", 0, 0, 10*UI_UNIT_X, 22, NULL, 0.0, 0.0, 0, 0, "Force updates of dependencies"); 00612 uiButSetFunc(but, driver_update_flags_cb, fcu, NULL); 00613 00614 but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Remove Driver", 0, 0, 10*UI_UNIT_X, 18, NULL, 0.0, 0.0, 0, 0, "Remove this driver"); 00615 uiButSetNFunc(but, driver_remove_cb, MEM_dupallocN(ale), NULL); 00616 00617 /* driver-level settings - type, expressions, and errors */ 00618 RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr); 00619 00620 col= uiLayoutColumn(pa->layout, 1); 00621 block= uiLayoutGetBlock(col); 00622 uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE); 00623 00624 /* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */ 00625 if (driver->type == DRIVER_TYPE_PYTHON) { 00626 /* expression */ 00627 uiItemR(col, &driver_ptr, "expression", 0, "Expr", ICON_NONE); 00628 00629 /* errors? */ 00630 if (driver->flag & DRIVER_FLAG_INVALID) 00631 uiItemL(col, "ERROR: invalid Python expression", ICON_ERROR); 00632 } 00633 else { 00634 /* errors? */ 00635 if (driver->flag & DRIVER_FLAG_INVALID) 00636 uiItemL(col, "ERROR: invalid target channel(s)", ICON_ERROR); 00637 } 00638 00639 col= uiLayoutColumn(pa->layout, 1); 00640 /* debug setting */ 00641 uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE); 00642 00643 /* value of driver */ 00644 if (driver->flag & DRIVER_FLAG_SHOWDEBUG) { 00645 uiLayout *row= uiLayoutRow(col, 1); 00646 char valBuf[32]; 00647 00648 uiItemL(row, "Driver Value:", ICON_NONE); 00649 00650 BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval); 00651 uiItemL(row, valBuf, ICON_NONE); 00652 } 00653 00654 /* add driver variables */ 00655 col= uiLayoutColumn(pa->layout, 0); 00656 block= uiLayoutGetBlock(col); 00657 but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Add Variable", 0, 0, 10*UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "Add a new target variable for this Driver"); 00658 uiButSetFunc(but, driver_add_var_cb, driver, NULL); 00659 00660 /* loop over targets, drawing them */ 00661 for (dvar= driver->variables.first; dvar; dvar= dvar->next) { 00662 PointerRNA dvar_ptr; 00663 uiLayout *box, *row; 00664 00665 /* sub-layout column for this variable's settings */ 00666 col= uiLayoutColumn(pa->layout, 1); 00667 00668 /* header panel */ 00669 box= uiLayoutBox(col); 00670 /* first row context info for driver */ 00671 RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr); 00672 00673 row= uiLayoutRow(box, 0); 00674 block= uiLayoutGetBlock(row); 00675 /* variable name */ 00676 uiItemR(row, &dvar_ptr, "name", 0, "", ICON_NONE); 00677 00678 /* remove button */ 00679 uiBlockSetEmboss(block, UI_EMBOSSN); 00680 but= uiDefIconBut(block, BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete target variable"); 00681 uiButSetFunc(but, driver_delete_var_cb, driver, dvar); 00682 uiBlockSetEmboss(block, UI_EMBOSS); 00683 00684 /* variable type */ 00685 row= uiLayoutRow(box, 0); 00686 uiItemR(row, &dvar_ptr, "type", 0, "", ICON_NONE); 00687 00688 /* variable type settings */ 00689 box= uiLayoutBox(col); 00690 /* controls to draw depends on the type of variable */ 00691 switch (dvar->type) { 00692 case DVAR_TYPE_SINGLE_PROP: /* single property */ 00693 graph_panel_driverVar__singleProp(box, ale->id, dvar); 00694 break; 00695 case DVAR_TYPE_ROT_DIFF: /* rotational difference */ 00696 graph_panel_driverVar__rotDiff(box, ale->id, dvar); 00697 break; 00698 case DVAR_TYPE_LOC_DIFF: /* location difference */ 00699 graph_panel_driverVar__locDiff(box, ale->id, dvar); 00700 break; 00701 case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */ 00702 graph_panel_driverVar__transChan(box, ale->id, dvar); 00703 break; 00704 } 00705 00706 /* value of variable */ 00707 if (driver->flag & DRIVER_FLAG_SHOWDEBUG) { 00708 char valBuf[32]; 00709 00710 box= uiLayoutBox(col); 00711 row= uiLayoutRow(box, 1); 00712 uiItemL(row, "Value:", ICON_NONE); 00713 00714 BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); 00715 uiItemL(row, valBuf, ICON_NONE); 00716 } 00717 } 00718 00719 /* cleanup */ 00720 MEM_freeN(ale); 00721 } 00722 00723 /* ******************* f-modifiers ******************************** */ 00724 /* all the drawing code is in editors/animation/fmodifier_ui.c */ 00725 00726 #define B_FMODIFIER_REDRAW 20 00727 00728 static void do_graph_region_modifier_buttons(bContext *C, void *UNUSED(arg), int event) 00729 { 00730 switch (event) { 00731 case B_FMODIFIER_REDRAW: // XXX this should send depsgraph updates too 00732 WM_event_add_notifier(C, NC_ANIMATION, NULL); // XXX need a notifier specially for F-Modifiers 00733 break; 00734 } 00735 } 00736 00737 static void graph_panel_modifiers(const bContext *C, Panel *pa) 00738 { 00739 bAnimListElem *ale; 00740 FCurve *fcu; 00741 FModifier *fcm; 00742 uiLayout *col, *row; 00743 uiBlock *block; 00744 00745 if (!graph_panel_context(C, &ale, &fcu)) 00746 return; 00747 00748 block= uiLayoutGetBlock(pa->layout); 00749 uiBlockSetHandleFunc(block, do_graph_region_modifier_buttons, NULL); 00750 00751 /* 'add modifier' button at top of panel */ 00752 { 00753 row= uiLayoutRow(pa->layout, 0); 00754 block= uiLayoutGetBlock(row); 00755 00756 // XXX for now, this will be a operator button which calls a 'add modifier' operator 00757 uiDefButO(block, BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, IFACE_("Add Modifier"), 10, 0, 150, 20, 00758 TIP_("Adds a new F-Curve Modifier for the active F-Curve")); 00759 00760 /* copy/paste (as sub-row)*/ 00761 row= uiLayoutRow(row, 1); 00762 uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_fmodifier_copy"); 00763 uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_fmodifier_paste"); 00764 } 00765 00766 /* draw each modifier */ 00767 for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { 00768 col= uiLayoutColumn(pa->layout, 1); 00769 00770 ANIM_uiTemplate_fmodifier_draw(col, ale->id, &fcu->modifiers, fcm); 00771 } 00772 00773 MEM_freeN(ale); 00774 } 00775 00776 /* ******************* general ******************************** */ 00777 00778 void graph_buttons_register(ARegionType *art) 00779 { 00780 PanelType *pt; 00781 00782 pt= MEM_callocN(sizeof(PanelType), "spacetype graph panel view"); 00783 strcpy(pt->idname, "GRAPH_PT_view"); 00784 strcpy(pt->label, "View Properties"); 00785 pt->draw= graph_panel_view; 00786 pt->flag |= PNL_DEFAULT_CLOSED; 00787 BLI_addtail(&art->paneltypes, pt); 00788 00789 pt= MEM_callocN(sizeof(PanelType), "spacetype graph panel properties"); 00790 strcpy(pt->idname, "GRAPH_PT_properties"); 00791 strcpy(pt->label, "Active F-Curve"); 00792 pt->draw= graph_panel_properties; 00793 pt->poll= graph_panel_poll; 00794 BLI_addtail(&art->paneltypes, pt); 00795 00796 pt= MEM_callocN(sizeof(PanelType), "spacetype graph panel properties"); 00797 strcpy(pt->idname, "GRAPH_PT_key_properties"); 00798 strcpy(pt->label, "Active Keyframe"); 00799 pt->draw= graph_panel_key_properties; 00800 pt->poll= graph_panel_poll; 00801 BLI_addtail(&art->paneltypes, pt); 00802 00803 00804 pt= MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers"); 00805 strcpy(pt->idname, "GRAPH_PT_drivers"); 00806 strcpy(pt->label, "Drivers"); 00807 pt->draw= graph_panel_drivers; 00808 pt->poll= graph_panel_drivers_poll; 00809 BLI_addtail(&art->paneltypes, pt); 00810 00811 pt= MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers"); 00812 strcpy(pt->idname, "GRAPH_PT_modifiers"); 00813 strcpy(pt->label, "Modifiers"); 00814 pt->draw= graph_panel_modifiers; 00815 pt->poll= graph_panel_poll; 00816 BLI_addtail(&art->paneltypes, pt); 00817 } 00818 00819 static int graph_properties(bContext *C, wmOperator *UNUSED(op)) 00820 { 00821 ScrArea *sa= CTX_wm_area(C); 00822 ARegion *ar= graph_has_buttons_region(sa); 00823 00824 if(ar) 00825 ED_region_toggle_hidden(C, ar); 00826 00827 return OPERATOR_FINISHED; 00828 } 00829 00830 void GRAPH_OT_properties(wmOperatorType *ot) 00831 { 00832 ot->name= "Properties"; 00833 ot->idname= "GRAPH_OT_properties"; 00834 ot->description= "Toggle display properties panel"; 00835 00836 ot->exec= graph_properties; 00837 ot->poll= ED_operator_graphedit_active; 00838 00839 /* flags */ 00840 ot->flag= 0; 00841 }