2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2008-12-22 08:13:25 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2008-12-22 08:13:25 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup spaction
|
2011-02-27 20:29:51 +00:00
|
|
|
*/
|
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* System includes ----------------------------------------------------- */
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <float.h>
|
2008-12-22 08:13:25 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2019-04-05 16:20:31 +02:00
|
|
|
#include "BLI_math.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2008-12-22 08:13:25 +00:00
|
|
|
|
|
|
|
/* Types --------------------------------------------------------------- */
|
|
|
|
|
2009-01-20 11:07:42 +00:00
|
|
|
#include "DNA_anim_types.h"
|
2018-04-19 16:04:26 +02:00
|
|
|
#include "DNA_cachefile_types.h"
|
2019-04-05 16:20:31 +02:00
|
|
|
#include "DNA_gpencil_types.h"
|
2018-04-19 16:04:26 +02:00
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_screen_types.h"
|
2008-12-22 08:13:25 +00:00
|
|
|
|
|
|
|
#include "BKE_action.h"
|
|
|
|
#include "BKE_context.h"
|
2018-04-19 16:04:26 +02:00
|
|
|
#include "BKE_pointcache.h"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2018-06-04 09:31:30 +02:00
|
|
|
/* Everything from source (BIF, BDR, BSE) ------------------------------ */
|
2008-12-22 08:13:25 +00:00
|
|
|
|
2018-04-19 16:04:26 +02:00
|
|
|
#include "GPU_immediate.h"
|
|
|
|
#include "GPU_matrix.h"
|
2018-06-27 19:07:23 -06:00
|
|
|
#include "GPU_state.h"
|
2018-04-19 16:04:26 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
#include "UI_interface.h"
|
|
|
|
#include "UI_resources.h"
|
|
|
|
#include "UI_view2d.h"
|
|
|
|
|
|
|
|
#include "ED_anim_api.h"
|
|
|
|
#include "ED_keyframes_draw.h"
|
|
|
|
|
2011-02-14 17:55:27 +00:00
|
|
|
#include "action_intern.h"
|
2008-12-22 08:13:25 +00:00
|
|
|
|
2008-12-22 09:43:54 +00:00
|
|
|
/* ************************************************************************* */
|
|
|
|
/* Channel List */
|
2008-12-22 08:13:25 +00:00
|
|
|
|
|
|
|
/* left hand part */
|
2020-03-06 16:56:42 +01:00
|
|
|
void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
|
2008-12-22 08:13:25 +00:00
|
|
|
{
|
|
|
|
ListBase anim_data = {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
|
|
|
int filter;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
View2D *v2d = ®ion->v2d;
|
2011-06-21 04:01:51 +00:00
|
|
|
size_t items;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* build list of channels to draw */
|
2012-05-08 16:02:13 +00:00
|
|
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
|
|
|
|
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-03 13:00:18 +02:00
|
|
|
int height = ACHANNEL_TOT_HEIGHT(ac, items);
|
|
|
|
v2d->tot.ymin = -height;
|
|
|
|
|
2010-10-16 05:07:33 +00:00
|
|
|
/* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
|
2020-04-03 13:25:03 +02:00
|
|
|
UI_view2d_sync(NULL, ac->area, v2d, V2D_LOCK_COPY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
/* loop through channels, and set up drawing depending on their type */
|
2012-05-08 16:02:13 +00:00
|
|
|
{ /* first pass: just the standard GL-drawing for backdrop + text */
|
2015-04-04 01:38:56 +13:00
|
|
|
size_t channel_index = 0;
|
2019-05-03 13:00:18 +02:00
|
|
|
float ymax = ACHANNEL_FIRST_TOP(ac);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-03 13:00:18 +02:00
|
|
|
for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
|
|
|
|
float ymin = ymax - ACHANNEL_HEIGHT(ac);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-08-16 02:21:43 +00:00
|
|
|
/* check if visible */
|
2019-05-03 13:00:18 +02:00
|
|
|
if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
|
|
|
|
IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
|
2009-08-16 02:21:43 +00:00
|
|
|
/* draw all channels using standard channel-drawing API */
|
2019-05-03 13:00:18 +02:00
|
|
|
ANIM_channel_draw(ac, ale, ymin, ymax, channel_index);
|
2009-08-16 02:21:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-08 16:02:13 +00:00
|
|
|
{ /* second pass: widgets */
|
2020-03-06 16:56:42 +01:00
|
|
|
uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
|
Animation channels can now be renamed by Ctrl-Clicking on them, as in
the Outliner
Channels which can be renamed include:
- Scenes, Objects, World, Material, Texture, etc. (i.e. "ID-blocks",
or the dark and light blue channels)
- Action Groups (green channels)
- Action expanders (i.e. "CubeAction", "WorldAction", etc.)
- Grease Pencil stuff
Channels which CANNOT be renamed, as they mostly use hardcoded values
or otherwise include:
- Drivers expander
- FCurves (they don't technically have a "name"; what is shown is just
a user-friendly representation of their rna_paths)
2011-08-03 01:22:31 +00:00
|
|
|
size_t channel_index = 0;
|
2019-05-03 13:00:18 +02:00
|
|
|
float ymax = ACHANNEL_FIRST_TOP(ac);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-03 13:00:18 +02:00
|
|
|
for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
|
|
|
|
float ymin = ymax - ACHANNEL_HEIGHT(ac);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-08-16 02:21:43 +00:00
|
|
|
/* check if visible */
|
2019-05-03 13:00:18 +02:00
|
|
|
if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
|
|
|
|
IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
|
2009-08-16 02:21:43 +00:00
|
|
|
/* draw all channels using standard channel-drawing API */
|
2019-03-18 17:28:36 +01:00
|
|
|
rctf channel_rect;
|
2019-05-03 13:00:18 +02:00
|
|
|
BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, ymin, ymax);
|
2019-03-18 17:28:36 +01:00
|
|
|
ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
|
2009-08-16 02:21:43 +00:00
|
|
|
}
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-11-09 21:20:40 +01:00
|
|
|
UI_block_end(C, block);
|
|
|
|
UI_block_draw(C, block);
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* free tempolary channels */
|
2014-05-19 00:24:45 +10:00
|
|
|
ANIM_animdata_freelist(&anim_data);
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
|
|
|
|
2008-12-22 09:43:54 +00:00
|
|
|
/* ************************************************************************* */
|
|
|
|
/* Keyframes */
|
|
|
|
|
2009-07-09 13:14:51 +00:00
|
|
|
/* extra padding for lengths (to go under scrollers) */
|
2012-05-08 16:02:13 +00:00
|
|
|
#define EXTRA_SCROLL_PAD 100.0f
|
2008-12-22 08:13:25 +00:00
|
|
|
|
2008-12-22 09:43:54 +00:00
|
|
|
/* draw keyframes in each channel */
|
2020-03-06 16:56:42 +01:00
|
|
|
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region)
|
2008-12-22 08:13:25 +00:00
|
|
|
{
|
|
|
|
ListBase anim_data = {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
View2D *v2d = ®ion->v2d;
|
2012-05-08 16:02:13 +00:00
|
|
|
bDopeSheet *ads = &saction->ads;
|
|
|
|
AnimData *adt = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-03 16:21:24 +11:00
|
|
|
uchar col1[4], col2[4];
|
|
|
|
uchar col1a[4], col2a[4];
|
|
|
|
uchar col1b[4], col2b[4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-30 10:57:46 +01:00
|
|
|
const bool show_group_colors = U.animation_flag & USER_ANIM_SHOW_CHANNEL_GROUP_COLORS;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* get theme colors */
|
2018-10-18 23:48:06 +03:00
|
|
|
UI_GetThemeColor4ubv(TH_SHADE2, col2);
|
|
|
|
UI_GetThemeColor4ubv(TH_HILITE, col1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-18 23:48:06 +03:00
|
|
|
UI_GetThemeColor4ubv(TH_GROUP, col2a);
|
|
|
|
UI_GetThemeColor4ubv(TH_GROUP_ACTIVE, col1a);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-18 23:48:06 +03:00
|
|
|
UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELOB, col1b);
|
|
|
|
UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* build list of channels to draw */
|
2017-02-11 00:24:59 -05:00
|
|
|
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
|
|
|
|
size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-03 13:00:18 +02:00
|
|
|
int height = ACHANNEL_TOT_HEIGHT(ac, items);
|
|
|
|
v2d->tot.ymin = -height;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
GPUVertFormat *format = immVertexFormat();
|
|
|
|
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-11-14 22:54:56 -05:00
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-16 15:38:34 +02:00
|
|
|
GPU_blend(GPU_BLEND_ALPHA);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-03 13:00:18 +02:00
|
|
|
/* first backdrop strips */
|
|
|
|
float ymax = ACHANNEL_FIRST_TOP(ac);
|
|
|
|
|
|
|
|
for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
|
|
|
|
float ymin = ymax - ACHANNEL_HEIGHT(ac);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* check if visible */
|
2019-05-03 13:00:18 +02:00
|
|
|
if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
|
|
|
|
IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
|
2015-03-30 21:29:20 +11:00
|
|
|
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
|
2012-05-08 16:02:13 +00:00
|
|
|
int sel = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* determine if any need to draw channel */
|
|
|
|
if (ale->datatype != ALE_NONE) {
|
|
|
|
/* determine if channel is selected */
|
2019-04-22 09:19:45 +10:00
|
|
|
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) {
|
2012-05-08 16:02:13 +00:00
|
|
|
sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-07-20 01:30:29 +10:00
|
|
|
if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
|
2008-12-22 08:13:25 +00:00
|
|
|
switch (ale->type) {
|
2009-10-13 11:21:02 +00:00
|
|
|
case ANIMTYPE_SUMMARY: {
|
2012-06-04 01:17:37 +00:00
|
|
|
/* reddish color from NLA */
|
2017-02-07 20:53:20 -02:00
|
|
|
immUniformThemeColor(TH_ANIM_ACTIVE);
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2009-10-13 11:21:02 +00:00
|
|
|
}
|
2009-02-13 06:33:07 +00:00
|
|
|
case ANIMTYPE_SCENE:
|
2008-12-22 08:13:25 +00:00
|
|
|
case ANIMTYPE_OBJECT: {
|
2018-10-18 23:48:06 +03:00
|
|
|
immUniformColor3ubvAlpha(col1b, sel ? col1[3] : col1b[3]);
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
2009-01-22 10:53:22 +00:00
|
|
|
case ANIMTYPE_FILLACTD:
|
2008-12-22 08:13:25 +00:00
|
|
|
case ANIMTYPE_DSSKEY:
|
2009-02-13 06:33:07 +00:00
|
|
|
case ANIMTYPE_DSWOR: {
|
2018-10-18 23:48:06 +03:00
|
|
|
immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
|
2013-07-19 15:23:42 +00:00
|
|
|
break;
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
|
|
|
case ANIMTYPE_GROUP: {
|
2017-01-20 18:14:28 +13:00
|
|
|
bActionGroup *agrp = ale->data;
|
|
|
|
if (show_group_colors && agrp->customCol) {
|
|
|
|
if (sel) {
|
2020-04-03 16:21:24 +11:00
|
|
|
immUniformColor3ubvAlpha((uchar *)agrp->cs.select, col1a[3]);
|
2017-01-20 18:14:28 +13:00
|
|
|
}
|
|
|
|
else {
|
2020-04-03 16:21:24 +11:00
|
|
|
immUniformColor3ubvAlpha((uchar *)agrp->cs.solid, col2a[3]);
|
2017-01-20 18:14:28 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-10-18 23:48:06 +03:00
|
|
|
immUniformColor4ubv(sel ? col1a : col2a);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
break;
|
2017-01-20 18:14:28 +13:00
|
|
|
}
|
|
|
|
case ANIMTYPE_FCURVE: {
|
|
|
|
FCurve *fcu = ale->data;
|
|
|
|
if (show_group_colors && fcu->grp && fcu->grp->customCol) {
|
2020-04-03 16:21:24 +11:00
|
|
|
immUniformColor3ubvAlpha((uchar *)fcu->grp->cs.active, sel ? col1[3] : col2[3]);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2017-01-20 18:14:28 +13:00
|
|
|
else {
|
2018-10-18 23:48:06 +03:00
|
|
|
immUniformColor4ubv(sel ? col1 : col2);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
break;
|
2017-01-20 18:14:28 +13:00
|
|
|
}
|
|
|
|
default: {
|
2018-10-18 23:48:06 +03:00
|
|
|
immUniformColor4ubv(sel ? col1 : col2);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2017-01-20 18:14:28 +13:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-19 15:23:42 +00:00
|
|
|
/* draw region twice: firstly backdrop, then the current range */
|
2019-05-03 13:00:18 +02:00
|
|
|
immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
2008-12-22 09:43:54 +00:00
|
|
|
else if (ac->datatype == ANIMCONT_GPENCIL) {
|
2020-04-03 16:21:24 +11:00
|
|
|
uchar *color;
|
|
|
|
uchar gpl_col[4];
|
2019-04-05 16:20:31 +02:00
|
|
|
if ((show_group_colors) && (ale->type == ANIMTYPE_GPLAYER)) {
|
|
|
|
bGPDlayer *gpl = (bGPDlayer *)ale->data;
|
|
|
|
rgb_float_to_uchar(gpl_col, gpl->color);
|
|
|
|
gpl_col[3] = col1[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-05 16:20:31 +02:00
|
|
|
color = sel ? col1 : gpl_col;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
color = sel ? col1 : col2;
|
|
|
|
}
|
2008-12-22 08:13:25 +00:00
|
|
|
/* frames less than one get less saturated background */
|
2018-10-18 23:48:06 +03:00
|
|
|
immUniformColor4ubv(color);
|
2019-05-03 13:00:18 +02:00
|
|
|
immRectf(pos, 0.0f, ymin, v2d->cur.xmin, ymax);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-08 14:31:38 +00:00
|
|
|
/* frames one and higher get a saturated background */
|
2018-10-21 16:22:46 +11:00
|
|
|
immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
|
2019-05-03 13:00:18 +02:00
|
|
|
immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
|
2012-06-08 14:31:38 +00:00
|
|
|
}
|
|
|
|
else if (ac->datatype == ANIMCONT_MASK) {
|
|
|
|
/* TODO --- this is a copy of gpencil */
|
|
|
|
/* frames less than one get less saturated background */
|
2020-04-03 16:21:24 +11:00
|
|
|
uchar *color = sel ? col1 : col2;
|
2018-10-18 23:48:06 +03:00
|
|
|
immUniformColor4ubv(color);
|
2019-05-03 13:00:18 +02:00
|
|
|
immRectf(pos, 0.0f, ymin, v2d->cur.xmin, ymax);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* frames one and higher get a saturated background */
|
2018-10-21 16:22:46 +11:00
|
|
|
immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
|
2019-05-03 13:00:18 +02:00
|
|
|
immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2020-08-16 15:38:34 +02:00
|
|
|
GPU_blend(GPU_BLEND_NONE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-02-11 00:24:59 -05:00
|
|
|
/* black line marking 'current frame' for Time-Slide transform mode */
|
|
|
|
if (saction->flag & SACTION_MOVING) {
|
|
|
|
immUniformColor3f(0.0f, 0.0f, 0.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
immBegin(GPU_PRIM_LINES, 2);
|
2017-02-11 00:24:59 -05:00
|
|
|
immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
|
|
|
|
immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
|
|
|
|
immEnd();
|
|
|
|
}
|
|
|
|
immUnbindProgram();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-02-11 00:24:59 -05:00
|
|
|
/* Draw keyframes
|
2018-11-14 12:53:15 +11:00
|
|
|
* 1) Only channels that are visible in the Action Editor get drawn/evaluated.
|
|
|
|
* This is to try to optimize this for heavier data sets
|
|
|
|
* 2) Keyframes which are out of view horizontally are disregarded
|
2008-12-22 08:13:25 +00:00
|
|
|
*/
|
2019-04-14 16:34:06 +03:00
|
|
|
int action_flag = saction->flag;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-14 16:34:06 +03:00
|
|
|
if (saction->mode == SACTCONT_TIMELINE) {
|
|
|
|
action_flag &= ~(SACTION_SHOW_INTERPOLATION | SACTION_SHOW_EXTREMES);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-03 13:00:18 +02:00
|
|
|
ymax = ACHANNEL_FIRST_TOP(ac);
|
|
|
|
|
|
|
|
for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
|
|
|
|
float ymin = ymax - ACHANNEL_HEIGHT(ac);
|
|
|
|
float ycenter = (ymin + ymax) / 2.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* check if visible */
|
2019-05-03 13:00:18 +02:00
|
|
|
if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
|
|
|
|
IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
|
2008-12-22 08:13:25 +00:00
|
|
|
/* check if anything to show for this channel */
|
|
|
|
if (ale->datatype != ALE_NONE) {
|
2012-05-08 16:02:13 +00:00
|
|
|
adt = ANIM_nla_mapping_get(ac, ale);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-22 08:13:25 +00:00
|
|
|
/* draw 'keyframes' for each specific datatype */
|
|
|
|
switch (ale->datatype) {
|
2009-10-13 11:21:02 +00:00
|
|
|
case ALE_ALL:
|
2019-05-03 13:00:18 +02:00
|
|
|
draw_summary_channel(v2d, ale->data, ycenter, ac->yscale_fac, action_flag);
|
2009-10-13 11:21:02 +00:00
|
|
|
break;
|
2009-02-13 06:33:07 +00:00
|
|
|
case ALE_SCE:
|
2019-05-03 13:00:18 +02:00
|
|
|
draw_scene_channel(v2d, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
|
2009-02-13 06:33:07 +00:00
|
|
|
break;
|
2008-12-22 08:13:25 +00:00
|
|
|
case ALE_OB:
|
2019-05-03 13:00:18 +02:00
|
|
|
draw_object_channel(v2d, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
|
2008-12-22 08:13:25 +00:00
|
|
|
break;
|
|
|
|
case ALE_ACT:
|
2019-05-03 13:00:18 +02:00
|
|
|
draw_action_channel(v2d, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
|
2008-12-22 08:13:25 +00:00
|
|
|
break;
|
|
|
|
case ALE_GROUP:
|
2019-05-03 13:00:18 +02:00
|
|
|
draw_agroup_channel(v2d, adt, ale->data, ycenter, ac->yscale_fac, action_flag);
|
2008-12-22 08:13:25 +00:00
|
|
|
break;
|
2009-01-20 11:07:42 +00:00
|
|
|
case ALE_FCURVE:
|
2019-05-03 13:00:18 +02:00
|
|
|
draw_fcurve_channel(v2d, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
|
2008-12-22 08:13:25 +00:00
|
|
|
break;
|
|
|
|
case ALE_GPFRAME:
|
2019-05-03 13:00:18 +02:00
|
|
|
draw_gpl_channel(v2d, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
|
2008-12-22 08:13:25 +00:00
|
|
|
break;
|
2012-06-08 14:31:38 +00:00
|
|
|
case ALE_MASKLAY:
|
2019-05-03 13:00:18 +02:00
|
|
|
draw_masklay_channel(v2d, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
|
2012-06-08 14:31:38 +00:00
|
|
|
break;
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-02-11 00:24:59 -05:00
|
|
|
/* free temporary channels used for drawing */
|
|
|
|
ANIM_animdata_freelist(&anim_data);
|
2008-12-22 08:13:25 +00:00
|
|
|
}
|
2018-04-19 16:04:26 +02:00
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
/* Timeline - Caches */
|
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
static bool timeline_cache_is_hidden_by_setting(SpaceAction *saction, PTCacheID *pid)
|
2018-04-19 16:04:26 +02:00
|
|
|
{
|
2019-08-21 17:21:06 +02:00
|
|
|
switch (pid->type) {
|
|
|
|
case PTCACHE_TYPE_SOFTBODY:
|
|
|
|
if ((saction->cache_display & TIME_CACHE_SOFTBODY) == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_PARTICLES:
|
2020-06-08 15:41:41 +02:00
|
|
|
case PTCACHE_TYPE_SIM_PARTICLES:
|
2019-08-21 17:21:06 +02:00
|
|
|
if ((saction->cache_display & TIME_CACHE_PARTICLES) == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_CLOTH:
|
|
|
|
if ((saction->cache_display & TIME_CACHE_CLOTH) == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_SMOKE_DOMAIN:
|
|
|
|
case PTCACHE_TYPE_SMOKE_HIGHRES:
|
|
|
|
if ((saction->cache_display & TIME_CACHE_SMOKE) == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_DYNAMICPAINT:
|
|
|
|
if ((saction->cache_display & TIME_CACHE_DYNAMICPAINT) == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_RIGIDBODY:
|
|
|
|
if ((saction->cache_display & TIME_CACHE_RIGIDBODY) == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-08-21 17:21:06 +02:00
|
|
|
return false;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
static void timeline_cache_color_get(PTCacheID *pid, float color[4])
|
|
|
|
{
|
|
|
|
switch (pid->type) {
|
|
|
|
case PTCACHE_TYPE_SOFTBODY:
|
|
|
|
color[0] = 1.0;
|
|
|
|
color[1] = 0.4;
|
|
|
|
color[2] = 0.02;
|
|
|
|
color[3] = 0.1;
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_PARTICLES:
|
2020-06-08 15:41:41 +02:00
|
|
|
case PTCACHE_TYPE_SIM_PARTICLES:
|
2019-08-21 17:21:06 +02:00
|
|
|
color[0] = 1.0;
|
|
|
|
color[1] = 0.1;
|
|
|
|
color[2] = 0.02;
|
|
|
|
color[3] = 0.1;
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_CLOTH:
|
|
|
|
color[0] = 0.1;
|
|
|
|
color[1] = 0.1;
|
|
|
|
color[2] = 0.75;
|
|
|
|
color[3] = 0.1;
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_SMOKE_DOMAIN:
|
|
|
|
case PTCACHE_TYPE_SMOKE_HIGHRES:
|
|
|
|
color[0] = 0.2;
|
|
|
|
color[1] = 0.2;
|
|
|
|
color[2] = 0.2;
|
|
|
|
color[3] = 0.1;
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_DYNAMICPAINT:
|
|
|
|
color[0] = 1.0;
|
|
|
|
color[1] = 0.1;
|
|
|
|
color[2] = 0.75;
|
|
|
|
color[3] = 0.1;
|
|
|
|
break;
|
|
|
|
case PTCACHE_TYPE_RIGIDBODY:
|
|
|
|
color[0] = 1.0;
|
|
|
|
color[1] = 0.6;
|
|
|
|
color[2] = 0.0;
|
|
|
|
color[3] = 0.1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
color[0] = 1.0;
|
|
|
|
color[1] = 0.0;
|
|
|
|
color[2] = 1.0;
|
|
|
|
color[3] = 0.1;
|
|
|
|
BLI_assert(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
static void timeline_cache_modify_color_based_on_state(PointCache *cache, float color[4])
|
|
|
|
{
|
|
|
|
if (cache->flag & PTCACHE_BAKED) {
|
|
|
|
color[0] -= 0.4f;
|
|
|
|
color[1] -= 0.4f;
|
|
|
|
color[2] -= 0.4f;
|
|
|
|
}
|
|
|
|
else if (cache->flag & PTCACHE_OUTDATED) {
|
|
|
|
color[0] += 0.4f;
|
|
|
|
color[1] += 0.4f;
|
|
|
|
color[2] += 0.4f;
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
static bool timeline_cache_find_next_cached_segment(PointCache *cache,
|
|
|
|
int search_start_frame,
|
|
|
|
int *r_segment_start,
|
|
|
|
int *r_segment_end)
|
|
|
|
{
|
|
|
|
int offset = cache->startframe;
|
|
|
|
int current = search_start_frame;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
/* Find segment start frame. */
|
|
|
|
while (true) {
|
|
|
|
if (current > cache->endframe) {
|
|
|
|
return false;
|
2018-04-19 16:04:26 +02:00
|
|
|
}
|
2019-08-21 17:21:06 +02:00
|
|
|
if (cache->cached_frames[current - offset]) {
|
|
|
|
*r_segment_start = current;
|
|
|
|
break;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-08-21 17:21:06 +02:00
|
|
|
current++;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
/* Find segment end frame. */
|
|
|
|
while (true) {
|
|
|
|
if (current > cache->endframe) {
|
|
|
|
*r_segment_end = current - 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!cache->cached_frames[current - offset]) {
|
|
|
|
*r_segment_end = current - 1;
|
|
|
|
return true;
|
2018-04-19 16:04:26 +02:00
|
|
|
}
|
2019-08-21 17:21:06 +02:00
|
|
|
current++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint timeline_cache_segments_count(PointCache *cache)
|
|
|
|
{
|
|
|
|
uint count = 0;
|
|
|
|
|
|
|
|
int current = cache->startframe;
|
|
|
|
int segment_start;
|
|
|
|
int segment_end;
|
|
|
|
while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) {
|
|
|
|
count++;
|
|
|
|
current = segment_end + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
static void timeline_cache_draw_cached_segments(PointCache *cache, uint pos_id)
|
|
|
|
{
|
|
|
|
uint segments_count = timeline_cache_segments_count(cache);
|
|
|
|
if (segments_count == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
immBeginAtMost(GPU_PRIM_TRIS, segments_count * 6);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
int current = cache->startframe;
|
|
|
|
int segment_start;
|
|
|
|
int segment_end;
|
|
|
|
while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) {
|
|
|
|
immRectf_fast(pos_id, segment_start - 0.5f, 0, segment_end + 0.5f, 1.0f);
|
|
|
|
current = segment_end + 1;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
immEnd();
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
static void timeline_cache_draw_single(PTCacheID *pid, float y_offset, float height, uint pos_id)
|
|
|
|
{
|
|
|
|
GPU_matrix_push();
|
|
|
|
GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HANDLE_HEIGHT + y_offset);
|
|
|
|
GPU_matrix_scale_2f(1.0, height);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
float color[4];
|
|
|
|
timeline_cache_color_get(pid, color);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
immUniformColor4fv(color);
|
|
|
|
immRectf(pos_id, (float)pid->cache->startframe, 0.0, (float)pid->cache->endframe, 1.0);
|
|
|
|
|
|
|
|
color[3] = 0.4f;
|
|
|
|
timeline_cache_modify_color_based_on_state(pid->cache, color);
|
|
|
|
immUniformColor4fv(color);
|
|
|
|
|
|
|
|
timeline_cache_draw_cached_segments(pid->cache, pos_id);
|
|
|
|
|
|
|
|
GPU_matrix_pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
|
|
|
|
{
|
|
|
|
if ((saction->cache_display & TIME_CACHE_DISPLAY) == 0 || ob == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListBase pidlist;
|
|
|
|
BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
|
|
|
|
|
|
|
|
uint pos_id = GPU_vertformat_attr_add(
|
|
|
|
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
|
|
|
|
2020-08-16 15:38:34 +02:00
|
|
|
GPU_blend(GPU_BLEND_ALPHA);
|
2019-08-21 17:21:06 +02:00
|
|
|
|
|
|
|
/* Iterate over pointcaches on the active object, and draw each one's range. */
|
|
|
|
float y_offset = 0.0f;
|
|
|
|
const float cache_draw_height = 4.0f * UI_DPI_FAC * U.pixelsize;
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
|
2019-08-21 17:21:06 +02:00
|
|
|
if (timeline_cache_is_hidden_by_setting(saction, pid)) {
|
|
|
|
continue;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
if (pid->cache->cached_frames == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
timeline_cache_draw_single(pid, y_offset, cache_draw_height, pos_id);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-21 17:21:06 +02:00
|
|
|
y_offset += cache_draw_height;
|
2018-04-19 16:04:26 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-16 15:38:34 +02:00
|
|
|
GPU_blend(GPU_BLEND_NONE);
|
2018-04-19 16:04:26 +02:00
|
|
|
immUnbindProgram();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-19 16:04:26 +02:00
|
|
|
BLI_freelistN(&pidlist);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|