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): Joshua Leung 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00031 #include "BLO_sys_types.h" 00032 00033 #include "DNA_anim_types.h" 00034 #include "DNA_object_types.h" 00035 #include "DNA_scene_types.h" 00036 #include "BLI_math.h" 00037 00038 #include "BKE_context.h" 00039 #include "BKE_global.h" 00040 #include "BKE_nla.h" 00041 #include "BKE_object.h" 00042 00043 #include "ED_anim_api.h" 00044 #include "ED_keyframes_edit.h" 00045 00046 #include "RNA_access.h" 00047 00048 #include "BIF_gl.h" 00049 00050 #include "UI_interface.h" 00051 #include "UI_resources.h" 00052 #include "UI_view2d.h" 00053 00054 /* XXX */ 00055 extern void ui_rasterpos_safe(float x, float y, float aspect); 00056 00057 /* *************************************************** */ 00058 /* TIME CODE FORMATTING */ 00059 00060 /* Generate timecode/frame number string and store in the supplied string 00061 * - buffer: must be at least 13 chars long 00062 * - power: special setting for View2D grid drawing, 00063 * used to specify how detailed we need to be 00064 * - timecodes: boolean specifying whether timecodes or 00065 * frame numbers get drawn 00066 * - cfra: time in frames or seconds, consistent with the values shown by timecodes 00067 */ 00068 // TODO: have this in kernel instead under scene? 00069 void ANIM_timecode_string_from_frame (char *str, Scene *scene, int power, short timecodes, float cfra) 00070 { 00071 if (timecodes) { 00072 int hours=0, minutes=0, seconds=0, frames=0; 00073 float raw_seconds= cfra; 00074 char neg[2]= {'\0'}; 00075 00076 /* get cframes */ 00077 if (cfra < 0) { 00078 /* correction for negative cfraues */ 00079 neg[0]= '-'; 00080 cfra = -cfra; 00081 } 00082 if (cfra >= 3600) { 00083 /* hours */ 00084 /* XXX should we only display a single digit for hours since clips are 00085 * VERY UNLIKELY to be more than 1-2 hours max? However, that would 00086 * go against conventions... 00087 */ 00088 hours= (int)cfra / 3600; 00089 cfra= (float)fmod(cfra, 3600); 00090 } 00091 if (cfra >= 60) { 00092 /* minutes */ 00093 minutes= (int)cfra / 60; 00094 cfra= (float)fmod(cfra, 60); 00095 } 00096 if (power <= 0) { 00097 /* seconds + frames 00098 * Frames are derived from 'fraction' of second. We need to perform some additional rounding 00099 * to cope with 'half' frames, etc., which should be fine in most cases 00100 */ 00101 seconds= (int)cfra; 00102 frames= (int)floor( (((double)cfra - (double)seconds) * FPS) + 0.5 ); 00103 } 00104 else { 00105 /* seconds (with pixel offset rounding) */ 00106 seconds= (int)floor(cfra + 0.375f); 00107 } 00108 00109 switch (U.timecode_style) { 00110 case USER_TIMECODE_MINIMAL: 00111 { 00112 /* - In general, minutes and seconds should be shown, as most clips will be 00113 * within this length. Hours will only be included if relevant. 00114 * - Only show frames when zoomed in enough for them to be relevant 00115 * (using separator of '+' for frames). 00116 * When showing frames, use slightly different display to avoid confusion with mm:ss format 00117 */ 00118 if (power <= 0) { 00119 /* include "frames" in display */ 00120 if (hours) sprintf(str, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames); 00121 else if (minutes) sprintf(str, "%s%02d:%02d+%02d", neg, minutes, seconds, frames); 00122 else sprintf(str, "%s%d+%02d", neg, seconds, frames); 00123 } 00124 else { 00125 /* don't include 'frames' in display */ 00126 if (hours) sprintf(str, "%s%02d:%02d:%02d", neg, hours, minutes, seconds); 00127 else sprintf(str, "%s%02d:%02d", neg, minutes, seconds); 00128 } 00129 } 00130 break; 00131 00132 case USER_TIMECODE_SMPTE_MSF: 00133 { 00134 /* reduced SMPTE format that always shows minutes, seconds, frames. Hours only shown as needed. */ 00135 if (hours) sprintf(str, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); 00136 else sprintf(str, "%s%02d:%02d:%02d", neg, minutes, seconds, frames); 00137 } 00138 break; 00139 00140 case USER_TIMECODE_MILLISECONDS: 00141 { 00142 /* reduced SMPTE. Instead of frames, milliseconds are shown */ 00143 int ms_dp= (power <= 0) ? (1 - power) : 1; /* precision of decimal part */ 00144 int s_pad= ms_dp+3; /* to get 2 digit whole-number part for seconds display (i.e. 3 is for 2 digits + radix, on top of full length) */ 00145 00146 if (hours) sprintf(str, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, cfra); 00147 else sprintf(str, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, cfra); 00148 } 00149 break; 00150 00151 case USER_TIMECODE_SECONDS_ONLY: 00152 { 00153 /* only show the original seconds display */ 00154 /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */ 00155 if (power <= 0) sprintf(str, "%.*f", 1-power, raw_seconds); 00156 else sprintf(str, "%d", (int)floor(raw_seconds + 0.375f)); 00157 } 00158 break; 00159 00160 case USER_TIMECODE_SMPTE_FULL: 00161 default: 00162 { 00163 /* full SMPTE format */ 00164 sprintf(str, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); 00165 } 00166 break; 00167 } 00168 } 00169 else { 00170 /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */ 00171 if (power <= 0) sprintf(str, "%.*f", 1-power, cfra); 00172 else sprintf(str, "%d", (int)floor(cfra + 0.375f)); 00173 } 00174 } 00175 00176 /* *************************************************** */ 00177 /* CURRENT FRAME DRAWING */ 00178 00179 /* Draw current frame number in a little green box beside the current frame indicator */ 00180 static void draw_cfra_number (Scene *scene, View2D *v2d, float cfra, short time) 00181 { 00182 float xscale, yscale, x, y; 00183 char numstr[32] = " t"; /* t is the character to start replacing from */ 00184 short slen; 00185 00186 /* because the frame number text is subject to the same scaling as the contents of the view */ 00187 UI_view2d_getscale(v2d, &xscale, &yscale); 00188 glScalef(1.0f/xscale, 1.0f, 1.0f); 00189 00190 /* get timecode string 00191 * - padding on str-buf passed so that it doesn't sit on the frame indicator 00192 * - power = 0, gives 'standard' behaviour for time 00193 * but power = 1 is required for frames (to get integer frames) 00194 */ 00195 if (time) 00196 ANIM_timecode_string_from_frame(&numstr[4], scene, 0, time, FRA2TIME(cfra)); 00197 else 00198 ANIM_timecode_string_from_frame(&numstr[4], scene, 1, time, cfra); 00199 slen= (short)UI_GetStringWidth(numstr) - 1; 00200 00201 /* get starting coordinates for drawing */ 00202 x= cfra * xscale; 00203 y= 18; 00204 00205 /* draw green box around/behind text */ 00206 UI_ThemeColorShade(TH_CFRAME, 0); 00207 glRectf(x, y, x+slen, y+15); 00208 00209 /* draw current frame number - black text */ 00210 UI_ThemeColor(TH_TEXT); 00211 UI_DrawString(x-5, y+3, numstr); 00212 00213 /* restore view transform */ 00214 glScalef(xscale, 1.0, 1.0); 00215 } 00216 00217 /* General call for drawing current frame indicator in animation editor */ 00218 void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag) 00219 { 00220 Scene *scene= CTX_data_scene(C); 00221 float vec[2]; 00222 00223 /* Draw a light green line to indicate current frame */ 00224 vec[0]= (float)(scene->r.cfra * scene->r.framelen); 00225 00226 UI_ThemeColor(TH_CFRAME); 00227 if (flag & DRAWCFRA_WIDE) 00228 glLineWidth(3.0); 00229 else 00230 glLineWidth(2.0); 00231 00232 glBegin(GL_LINE_STRIP); 00233 vec[1]= v2d->cur.ymin-500.0f; /* XXX arbitrary... want it go to bottom */ 00234 glVertex2fv(vec); 00235 00236 vec[1]= v2d->cur.ymax; 00237 glVertex2fv(vec); 00238 glEnd(); 00239 00240 glLineWidth(1.0); 00241 00242 /* Draw current frame number in a little box */ 00243 if (flag & DRAWCFRA_SHOW_NUMBOX) { 00244 UI_view2d_view_orthoSpecial(CTX_wm_region(C), v2d, 1); 00245 draw_cfra_number(scene, v2d, vec[0], (flag & DRAWCFRA_UNIT_SECONDS)); 00246 } 00247 } 00248 00249 /* *************************************************** */ 00250 /* PREVIEW RANGE 'CURTAINS' */ 00251 /* Note: 'Preview Range' tools are defined in anim_ops.c */ 00252 00253 /* Draw preview range 'curtains' for highlighting where the animation data is */ 00254 void ANIM_draw_previewrange (const bContext *C, View2D *v2d) 00255 { 00256 Scene *scene= CTX_data_scene(C); 00257 00258 /* only draw this if preview range is set */ 00259 if (PRVRANGEON) { 00260 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00261 glEnable(GL_BLEND); 00262 glColor4f(0.0f, 0.0f, 0.0f, 0.4f); 00263 00264 /* only draw two separate 'curtains' if there's no overlap between them */ 00265 if (PSFRA < PEFRA) { 00266 glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); 00267 glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); 00268 } 00269 else { 00270 glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); 00271 } 00272 00273 glDisable(GL_BLEND); 00274 } 00275 } 00276 00277 /* *************************************************** */ 00278 /* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes) */ 00279 00280 /* Obtain the AnimData block providing NLA-mapping for the given channel (if applicable) */ 00281 // TODO: do not supply return this if the animdata tells us that there is no mapping to perform 00282 AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale) 00283 { 00284 /* sanity checks */ 00285 if (ac == NULL) 00286 return NULL; 00287 00288 /* abort if rendering - we may get some race condition issues... */ 00289 if (G.rendering) return NULL; 00290 00291 /* handling depends on the type of animation-context we've got */ 00292 if (ale) 00293 return ale->adt; 00294 else 00295 return NULL; 00296 } 00297 00298 /* ------------------- */ 00299 00300 /* helper function for ANIM_nla_mapping_apply_fcurve() -> "restore", i.e. mapping points back to action-time */ 00301 static short bezt_nlamapping_restore(KeyframeEditData *ked, BezTriple *bezt) 00302 { 00303 /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */ 00304 AnimData *adt= (AnimData *)ked->data; 00305 short only_keys= (short)ked->i1; 00306 00307 /* adjust BezTriple handles only if allowed to */ 00308 if (only_keys == 0) { 00309 bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_UNMAP); 00310 bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_UNMAP); 00311 } 00312 00313 bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_UNMAP); 00314 00315 return 0; 00316 } 00317 00318 /* helper function for ANIM_nla_mapping_apply_fcurve() -> "apply", i.e. mapping points to NLA-mapped global time */ 00319 static short bezt_nlamapping_apply(KeyframeEditData *ked, BezTriple *bezt) 00320 { 00321 /* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */ 00322 AnimData *adt= (AnimData*)ked->data; 00323 short only_keys= (short)ked->i1; 00324 00325 /* adjust BezTriple handles only if allowed to */ 00326 if (only_keys == 0) { 00327 bezt->vec[0][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_MAP); 00328 bezt->vec[2][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_MAP); 00329 } 00330 00331 bezt->vec[1][0]= BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_MAP); 00332 00333 return 0; 00334 } 00335 00336 00337 /* Apply/Unapply NLA mapping to all keyframes in the nominated F-Curve 00338 * - restore = whether to map points back to non-mapped time 00339 * - only_keys = whether to only adjust the location of the center point of beztriples 00340 */ 00341 void ANIM_nla_mapping_apply_fcurve (AnimData *adt, FCurve *fcu, short restore, short only_keys) 00342 { 00343 KeyframeEditData ked= {{NULL}}; 00344 KeyframeEditFunc map_cb; 00345 00346 /* init edit data 00347 * - AnimData is stored in 'data' 00348 * - only_keys is stored in 'i1' 00349 */ 00350 ked.data= (void *)adt; 00351 ked.i1= (int)only_keys; 00352 00353 /* get editing callback */ 00354 if (restore) 00355 map_cb= bezt_nlamapping_restore; 00356 else 00357 map_cb= bezt_nlamapping_apply; 00358 00359 /* apply to F-Curve */ 00360 ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, map_cb, NULL); 00361 } 00362 00363 /* *************************************************** */ 00364 /* UNITS CONVERSION MAPPING (required for drawing and editing keyframes) */ 00365 00366 /* Get unit conversion factor for given ID + F-Curve */ 00367 float ANIM_unit_mapping_get_factor (Scene *scene, ID *id, FCurve *fcu, short restore) 00368 { 00369 /* sanity checks */ 00370 if (id && fcu && fcu->rna_path) 00371 { 00372 PointerRNA ptr, id_ptr; 00373 PropertyRNA *prop; 00374 00375 /* get RNA property that F-Curve affects */ 00376 RNA_id_pointer_create(id, &id_ptr); 00377 if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) 00378 { 00379 /* rotations: radians <-> degrees? */ 00380 if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) 00381 { 00382 /* if the radians flag is not set, default to using degrees which need conversions */ 00383 if ((scene) && (scene->unit.system_rotation == USER_UNIT_ROT_RADIANS) == 0) { 00384 if (restore) 00385 return DEG2RADF(1.0f); /* degrees to radians */ 00386 else 00387 return RAD2DEGF(1.0f); /* radians to degrees */ 00388 } 00389 } 00390 00391 // TODO: other rotation types here as necessary 00392 } 00393 } 00394 00395 /* no mapping needs to occur... */ 00396 return 1.0f; 00397 } 00398 00399 /* ----------------------- */ 00400 00401 /* helper function for ANIM_unit_mapping_apply_fcurve -> mapping callback for unit mapping */ 00402 static short bezt_unit_mapping_apply (KeyframeEditData *ked, BezTriple *bezt) 00403 { 00404 /* mapping factor is stored in f1, flags are stored in i1 */ 00405 short only_keys= (ked->i1 & ANIM_UNITCONV_ONLYKEYS); 00406 short sel_vs= (ked->i1 & ANIM_UNITCONV_SELVERTS); 00407 float fac= ked->f1; 00408 00409 /* adjust BezTriple handles only if allowed to */ 00410 if (only_keys == 0) { 00411 if ((sel_vs==0) || (bezt->f1 & SELECT)) 00412 bezt->vec[0][1] *= fac; 00413 if ((sel_vs==0) || (bezt->f3 & SELECT)) 00414 bezt->vec[2][1] *= fac; 00415 } 00416 00417 if ((sel_vs == 0) || (bezt->f2 & SELECT)) 00418 bezt->vec[1][1] *= fac; 00419 00420 return 0; 00421 } 00422 00423 /* Apply/Unapply units conversions to keyframes */ 00424 void ANIM_unit_mapping_apply_fcurve (Scene *scene, ID *id, FCurve *fcu, short flag) 00425 { 00426 KeyframeEditData ked; 00427 KeyframeEditFunc sel_cb; 00428 float fac; 00429 00430 /* abort if rendering - we may get some race condition issues... */ 00431 if (G.rendering) return; 00432 00433 /* calculate mapping factor, and abort if nothing to change */ 00434 fac= ANIM_unit_mapping_get_factor(scene, id, fcu, (flag & ANIM_UNITCONV_RESTORE)); 00435 if (fac == 1.0f) 00436 return; 00437 00438 /* init edit data 00439 * - mapping factor is stored in f1 00440 * - flags are stored in 'i1' 00441 */ 00442 memset(&ked, 0, sizeof(KeyframeEditData)); 00443 ked.f1= (float)fac; 00444 ked.i1= (int)flag; 00445 00446 /* only selected? */ 00447 if (flag & ANIM_UNITCONV_ONLYSEL) 00448 sel_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED); 00449 else 00450 sel_cb= NULL; 00451 00452 /* apply to F-Curve */ 00453 ANIM_fcurve_keyframes_loop(&ked, fcu, sel_cb, bezt_unit_mapping_apply, NULL); 00454 00455 // FIXME: loop here for samples should be generalised 00456 // TODO: only sel? 00457 if (fcu->fpt) { 00458 FPoint *fpt; 00459 unsigned int i; 00460 00461 for (i=0, fpt=fcu->fpt; i < fcu->totvert; i++, fpt++) { 00462 /* apply unit mapping */ 00463 fpt->vec[1] *= fac; 00464 } 00465 } 00466 } 00467 00468 /* *************************************************** */