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) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Joshua Leung 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 /* System includes ----------------------------------------------------- */ 00034 00035 #include <math.h> 00036 #include <stdlib.h> 00037 #include <string.h> 00038 #include <float.h> 00039 00040 #include "BLI_blenlib.h" 00041 #include "BLI_math.h" 00042 #include "BLI_utildefines.h" 00043 00044 /* Types --------------------------------------------------------------- */ 00045 00046 #include "DNA_anim_types.h" 00047 #include "DNA_screen_types.h" 00048 00049 #include "BKE_action.h" 00050 #include "BKE_context.h" 00051 00052 00053 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 00054 00055 #include "BIF_gl.h" 00056 00057 #include "UI_interface.h" 00058 #include "UI_resources.h" 00059 #include "UI_view2d.h" 00060 00061 #include "ED_anim_api.h" 00062 #include "ED_keyframes_draw.h" 00063 00064 #include "action_intern.h" 00065 00066 /* ************************************************************************* */ 00067 /* Channel List */ 00068 00069 /* left hand part */ 00070 void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) 00071 { 00072 ListBase anim_data = {NULL, NULL}; 00073 bAnimListElem *ale; 00074 int filter; 00075 00076 View2D *v2d= &ar->v2d; 00077 float y= 0.0f; 00078 size_t items; 00079 int height; 00080 00081 /* build list of channels to draw */ 00082 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); 00083 items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00084 00085 /* Update max-extent of channels here (taking into account scrollers): 00086 * - this is done to allow the channel list to be scrollable, but must be done here 00087 * to avoid regenerating the list again and/or also because channels list is drawn first 00088 * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 00089 * start of list offset, and the second is as a correction for the scrollers. 00090 */ 00091 height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2)); 00092 if (height > (v2d->mask.ymax - v2d->mask.ymin)) { 00093 /* don't use totrect set, as the width stays the same 00094 * (NOTE: this is ok here, the configuration is pretty straightforward) 00095 */ 00096 v2d->tot.ymin= (float)(-height); 00097 } 00098 /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ 00099 UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); 00100 00101 /* loop through channels, and set up drawing depending on their type */ 00102 { /* first pass: just the standard GL-drawing for backdrop + text */ 00103 y= (float)ACHANNEL_FIRST; 00104 00105 for (ale= anim_data.first; ale; ale= ale->next) { 00106 float yminc= (float)(y - ACHANNEL_HEIGHT_HALF); 00107 float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF); 00108 00109 /* check if visible */ 00110 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || 00111 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 00112 { 00113 /* draw all channels using standard channel-drawing API */ 00114 ANIM_channel_draw(ac, ale, yminc, ymaxc); 00115 } 00116 00117 /* adjust y-position for next one */ 00118 y -= ACHANNEL_STEP; 00119 } 00120 } 00121 { /* second pass: widgets */ 00122 uiBlock *block= uiBeginBlock(C, ar, __func__, UI_EMBOSS); 00123 size_t channel_index = 0; 00124 00125 y= (float)ACHANNEL_FIRST; 00126 00127 for (ale= anim_data.first; ale; ale= ale->next) { 00128 float yminc= (float)(y - ACHANNEL_HEIGHT_HALF); 00129 float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF); 00130 00131 /* check if visible */ 00132 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || 00133 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 00134 { 00135 /* draw all channels using standard channel-drawing API */ 00136 ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index); 00137 } 00138 00139 /* adjust y-position for next one */ 00140 y -= ACHANNEL_STEP; 00141 channel_index++; 00142 } 00143 00144 uiEndBlock(C, block); 00145 uiDrawBlock(C, block); 00146 } 00147 00148 /* free tempolary channels */ 00149 BLI_freelistN(&anim_data); 00150 } 00151 00152 /* ************************************************************************* */ 00153 /* Keyframes */ 00154 00155 /* extra padding for lengths (to go under scrollers) */ 00156 #define EXTRA_SCROLL_PAD 100.0f 00157 00158 /* draw keyframes in each channel */ 00159 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) 00160 { 00161 ListBase anim_data = {NULL, NULL}; 00162 bAnimListElem *ale; 00163 int filter; 00164 00165 View2D *v2d= &ar->v2d; 00166 bDopeSheet *ads= &saction->ads; 00167 AnimData *adt= NULL; 00168 00169 float act_start, act_end, y; 00170 size_t items; 00171 int height; 00172 00173 unsigned char col1[3], col2[3]; 00174 unsigned char col1a[3], col2a[3]; 00175 unsigned char col1b[3], col2b[3]; 00176 00177 00178 /* get theme colors */ 00179 UI_GetThemeColor3ubv(TH_BACK, col2); 00180 UI_GetThemeColor3ubv(TH_HILITE, col1); 00181 00182 UI_GetThemeColor3ubv(TH_GROUP, col2a); 00183 UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a); 00184 00185 UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b); 00186 UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b); 00187 00188 /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */ 00189 00190 /* if in NLA there's a strip active, map the view */ 00191 if (ac->datatype == ANIMCONT_ACTION) { 00192 /* adt= ANIM_nla_mapping_get(ac, NULL); */ /* UNUSED */ 00193 00194 /* start and end of action itself */ 00195 calc_action_range(ac->data, &act_start, &act_end, 0); 00196 } 00197 00198 /* build list of channels to draw */ 00199 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); 00200 items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00201 00202 /* Update max-extent of channels here (taking into account scrollers): 00203 * - this is done to allow the channel list to be scrollable, but must be done here 00204 * to avoid regenerating the list again and/or also because channels list is drawn first 00205 * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 00206 * start of list offset, and the second is as a correction for the scrollers. 00207 */ 00208 height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2)); 00209 /* don't use totrect set, as the width stays the same 00210 * (NOTE: this is ok here, the configuration is pretty straightforward) 00211 */ 00212 v2d->tot.ymin= (float)(-height); 00213 00214 /* first backdrop strips */ 00215 y= (float)(-ACHANNEL_HEIGHT); 00216 glEnable(GL_BLEND); 00217 00218 for (ale= anim_data.first; ale; ale= ale->next) { 00219 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF); 00220 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF); 00221 00222 /* check if visible */ 00223 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || 00224 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 00225 { 00226 bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); 00227 int sel=0; 00228 00229 /* determine if any need to draw channel */ 00230 if (ale->datatype != ALE_NONE) { 00231 /* determine if channel is selected */ 00232 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) 00233 sel= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT); 00234 00235 if (ELEM3(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) { 00236 switch (ale->type) { 00237 case ANIMTYPE_SUMMARY: 00238 { 00239 // FIXME: hardcoded colors - reddish color from NLA 00240 glColor4f(0.8f, 0.2f, 0.0f, 0.4f); 00241 } 00242 break; 00243 00244 case ANIMTYPE_SCENE: 00245 case ANIMTYPE_OBJECT: 00246 { 00247 if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); 00248 else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); 00249 } 00250 break; 00251 00252 case ANIMTYPE_FILLACTD: 00253 case ANIMTYPE_DSSKEY: 00254 case ANIMTYPE_DSWOR: 00255 { 00256 if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); 00257 else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); 00258 } 00259 break; 00260 00261 case ANIMTYPE_GROUP: 00262 { 00263 if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22); 00264 else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22); 00265 } 00266 break; 00267 00268 default: 00269 { 00270 if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); 00271 else glColor4ub(col2[0], col2[1], col2[2], 0x22); 00272 } 00273 break; 00274 } 00275 00276 /* draw region twice: firstly backdrop, then the current range */ 00277 glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD, (float)y+ACHANNEL_HEIGHT_HALF); 00278 00279 if (ac->datatype == ANIMCONT_ACTION) 00280 glRectf(act_start, (float)y-ACHANNEL_HEIGHT_HALF, act_end, (float)y+ACHANNEL_HEIGHT_HALF); 00281 } 00282 else if (ac->datatype == ANIMCONT_GPENCIL) { 00283 /* frames less than one get less saturated background */ 00284 if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); 00285 else glColor4ub(col2[0], col2[1], col2[2], 0x22); 00286 glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y+ACHANNEL_HEIGHT_HALF); 00287 00288 /* frames one and higher get a saturated background */ 00289 if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44); 00290 else glColor4ub(col2[0], col2[1], col2[2], 0x44); 00291 glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD, (float)y+ACHANNEL_HEIGHT_HALF); 00292 } 00293 } 00294 } 00295 00296 /* Increment the step */ 00297 y -= ACHANNEL_STEP; 00298 } 00299 glDisable(GL_BLEND); 00300 00301 /* Draw keyframes 00302 * 1) Only channels that are visible in the Action Editor get drawn/evaluated. 00303 * This is to try to optimise this for heavier data sets 00304 * 2) Keyframes which are out of view horizontally are disregarded 00305 */ 00306 y= (float)(-ACHANNEL_HEIGHT); 00307 00308 for (ale= anim_data.first; ale; ale= ale->next) { 00309 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF); 00310 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF); 00311 00312 /* check if visible */ 00313 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || 00314 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 00315 { 00316 /* check if anything to show for this channel */ 00317 if (ale->datatype != ALE_NONE) { 00318 adt= ANIM_nla_mapping_get(ac, ale); 00319 00320 /* draw 'keyframes' for each specific datatype */ 00321 switch (ale->datatype) { 00322 case ALE_ALL: 00323 draw_summary_channel(v2d, ale->data, y); 00324 break; 00325 case ALE_SCE: 00326 draw_scene_channel(v2d, ads, ale->key_data, y); 00327 break; 00328 case ALE_OB: 00329 draw_object_channel(v2d, ads, ale->key_data, y); 00330 break; 00331 case ALE_ACT: 00332 draw_action_channel(v2d, adt, ale->key_data, y); 00333 break; 00334 case ALE_GROUP: 00335 draw_agroup_channel(v2d, adt, ale->data, y); 00336 break; 00337 case ALE_FCURVE: 00338 draw_fcurve_channel(v2d, adt, ale->key_data, y); 00339 break; 00340 case ALE_GPFRAME: 00341 draw_gpl_channel(v2d, ads, ale->data, y); 00342 break; 00343 } 00344 } 00345 } 00346 00347 y-= ACHANNEL_STEP; 00348 } 00349 00350 /* free tempolary channels used for drawing */ 00351 BLI_freelistN(&anim_data); 00352 00353 /* black line marking 'current frame' for Time-Slide transform mode */ 00354 if (saction->flag & SACTION_MOVING) { 00355 glColor3f(0.0f, 0.0f, 0.0f); 00356 00357 glBegin(GL_LINES); 00358 glVertex2f(saction->timeslide, v2d->cur.ymin-EXTRA_SCROLL_PAD); 00359 glVertex2f(saction->timeslide, v2d->cur.ymax); 00360 glEnd(); 00361 } 00362 }