UI: Asset Shelf (Experimental Feature) #104831

Closed
Julian Eisel wants to merge 399 commits from asset-shelf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
1 changed files with 269 additions and 250 deletions
Showing only changes of commit df0816430d - Show all commits

View File

@ -181,15 +181,8 @@ static void draw_channel_action_ranges(ListBase *anim_data, View2D *v2d)
}
}
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region)
static void draw_backdrops(bAnimContext *ac, ListBase &anim_data, View2D *v2d, uint pos)
{
ListBase anim_data = {nullptr, nullptr};
bAnimListElem *ale;
View2D *v2d = &region->v2d;
bDopeSheet *ads = &saction->ads;
AnimData *adt = nullptr;
uchar col1[4], col2[4];
uchar col1a[4], col2a[4];
uchar col1b[4], col2b[4];
@ -208,6 +201,272 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region
UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELOB, col1b);
UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
float ymax = ANIM_UI_get_first_channel_top(v2d);
const float channel_step = ANIM_UI_get_channel_step();
bAnimListElem *ale;
for (ale = static_cast<bAnimListElem *>(anim_data.first); ale;
ale = ale->next, ymax -= channel_step)
{
const float ymin = ymax - ANIM_UI_get_channel_height();
/* check if visible */
if (!(IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)))
{
continue;
}
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
int sel = 0;
/* determine if any need to draw channel */
if (ale->datatype == ALE_NONE) {
continue;
}
/* determine if channel is selected */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) {
sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
}
if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
switch (ale->type) {
case ANIMTYPE_SUMMARY: {
/* reddish color from NLA */
immUniformThemeColor(TH_ANIM_ACTIVE);
break;
}
case ANIMTYPE_SCENE:
case ANIMTYPE_OBJECT: {
immUniformColor3ubvAlpha(col1b, sel ? col1[3] : col1b[3]);
break;
}
case ANIMTYPE_FILLACTD:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR: {
immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
break;
}
case ANIMTYPE_GROUP: {
bActionGroup *agrp = static_cast<bActionGroup *>(ale->data);
if (show_group_colors && agrp->customCol) {
if (sel) {
immUniformColor3ubvAlpha((uchar *)agrp->cs.select, col1a[3]);
}
else {
immUniformColor3ubvAlpha((uchar *)agrp->cs.solid, col2a[3]);
}
}
else {
immUniformColor4ubv(sel ? col1a : col2a);
}
break;
}
case ANIMTYPE_FCURVE: {
FCurve *fcu = static_cast<FCurve *>(ale->data);
if (show_group_colors && fcu->grp && fcu->grp->customCol) {
immUniformColor3ubvAlpha((uchar *)fcu->grp->cs.active, sel ? col1[3] : col2[3]);
}
else {
immUniformColor4ubv(sel ? col1 : col2);
}
break;
}
case ANIMTYPE_GPLAYER: {
if (show_group_colors) {
uchar gpl_col[4];
bGPDlayer *gpl = (bGPDlayer *)ale->data;
rgb_float_to_uchar(gpl_col, gpl->color);
gpl_col[3] = col1[3];
immUniformColor4ubv(sel ? col1 : gpl_col);
}
else {
immUniformColor4ubv(sel ? col1 : col2);
}
break;
}
default: {
immUniformColor4ubv(sel ? col1 : col2);
}
}
/* draw region twice: firstly backdrop, then the current range */
immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
uchar *color;
uchar gpl_col[4];
if (ale->type == ANIMTYPE_SUMMARY) {
color = col_summary;
}
else 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];
color = sel ? col1 : gpl_col;
}
else {
color = sel ? col1 : col2;
}
/* Color overlay on frames between the start/end frames. */
immUniformColor4ubv(color);
immRectf(pos, ac->scene->r.sfra, ymin, ac->scene->r.efra, ymax);
/* Color overlay outside the start/end frame range get a more transparent overlay. */
immUniformColor3ubvAlpha(color, MIN2(255, color[3] / 2));
immRectf(pos, v2d->cur.xmin, ymin, ac->scene->r.sfra, ymax);
immRectf(pos, ac->scene->r.efra, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
else if (ac->datatype == ANIMCONT_MASK) {
/* TODO: this is a copy of gpencil. */
uchar *color;
if (ale->type == ANIMTYPE_SUMMARY) {
color = col_summary;
}
else {
color = sel ? col1 : col2;
}
/* Color overlay on frames between the start/end frames. */
immUniformColor4ubv(color);
immRectf(pos, ac->scene->r.sfra, ymin, ac->scene->r.efra, ymax);
/* Color overlay outside the start/end frame range get a more transparent overlay. */
immUniformColor3ubvAlpha(color, MIN2(255, color[3] / 2));
immRectf(pos, v2d->cur.xmin, ymin, ac->scene->r.sfra, ymax);
immRectf(pos, ac->scene->r.efra, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
}
}
static void draw_keyframes(bAnimContext *ac,
View2D *v2d,
SpaceAction *saction,
ListBase &anim_data)
{
/* Draw keyframes
* 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
*/
int action_flag = saction->flag;
bDopeSheet *ads = &saction->ads;
if (saction->mode == SACTCONT_TIMELINE) {
action_flag &= ~(SACTION_SHOW_INTERPOLATION | SACTION_SHOW_EXTREMES);
}
const float channel_step = ANIM_UI_get_channel_step();
float ymax = ANIM_UI_get_first_channel_top(v2d);
AnimKeylistDrawList *draw_list = ED_keylist_draw_list_create();
const float scale_factor = ANIM_UI_get_keyframe_scale_factor();
bAnimListElem *ale;
for (ale = static_cast<bAnimListElem *>(anim_data.first); ale;
ale = ale->next, ymax -= channel_step)
{
const float ymin = ymax - ANIM_UI_get_channel_height();
float ycenter = (ymin + ymax) / 2.0f;
/* check if visible */
if (!(IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)))
{
continue;
}
/* check if anything to show for this channel */
if (ale->datatype == ALE_NONE) {
continue;
}
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* draw 'keyframes' for each specific datatype */
switch (ale->datatype) {
case ALE_ALL:
draw_summary_channel(
draw_list, static_cast<bAnimContext *>(ale->data), ycenter, scale_factor, action_flag);
break;
case ALE_SCE:
draw_scene_channel(draw_list,
ads,
static_cast<Scene *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_OB:
draw_object_channel(draw_list,
ads,
static_cast<Object *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_ACT:
draw_action_channel(draw_list,
adt,
static_cast<bAction *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_GROUP:
draw_agroup_channel(draw_list,
adt,
static_cast<bActionGroup *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_FCURVE:
draw_fcurve_channel(draw_list,
adt,
static_cast<FCurve *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_GREASE_PENCIL_CELS:
draw_grease_pencil_cels_channel(draw_list,
ads,
static_cast<GreasePencilLayer *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_GPFRAME:
draw_gpl_channel(draw_list,
ads,
static_cast<bGPDlayer *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_MASKLAY:
draw_masklay_channel(draw_list,
ads,
static_cast<MaskLayer *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
}
}
ED_keylist_draw_list_flush(draw_list, v2d);
ED_keylist_draw_list_free(draw_list);
}
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region)
{
ListBase anim_data = {nullptr, nullptr};
View2D *v2d = &region->v2d;
/* build list of channels to draw */
eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_LIST_CHANNELS);
@ -233,139 +492,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region
GPU_blend(GPU_BLEND_ALPHA);
/* first backdrop strips */
float ymax = ANIM_UI_get_first_channel_top(v2d);
const float channel_step = ANIM_UI_get_channel_step();
for (ale = static_cast<bAnimListElem *>(anim_data.first); ale;
ale = ale->next, ymax -= channel_step)
{
const float ymin = ymax - ANIM_UI_get_channel_height();
draw_backdrops(ac, anim_data, v2d, pos);
/* check if visible */
if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
int sel = 0;
/* determine if any need to draw channel */
if (ale->datatype != ALE_NONE) {
/* determine if channel is selected */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) {
sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
}
if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
switch (ale->type) {
case ANIMTYPE_SUMMARY: {
/* reddish color from NLA */
immUniformThemeColor(TH_ANIM_ACTIVE);
break;
}
case ANIMTYPE_SCENE:
case ANIMTYPE_OBJECT: {
immUniformColor3ubvAlpha(col1b, sel ? col1[3] : col1b[3]);
break;
}
case ANIMTYPE_FILLACTD:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR: {
immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
break;
}
case ANIMTYPE_GROUP: {
bActionGroup *agrp = static_cast<bActionGroup *>(ale->data);
if (show_group_colors && agrp->customCol) {
if (sel) {
immUniformColor3ubvAlpha((uchar *)agrp->cs.select, col1a[3]);
}
else {
immUniformColor3ubvAlpha((uchar *)agrp->cs.solid, col2a[3]);
}
}
else {
immUniformColor4ubv(sel ? col1a : col2a);
}
break;
}
case ANIMTYPE_FCURVE: {
FCurve *fcu = static_cast<FCurve *>(ale->data);
if (show_group_colors && fcu->grp && fcu->grp->customCol) {
immUniformColor3ubvAlpha((uchar *)fcu->grp->cs.active, sel ? col1[3] : col2[3]);
}
else {
immUniformColor4ubv(sel ? col1 : col2);
}
break;
}
case ANIMTYPE_GPLAYER: {
if (show_group_colors) {
uchar gpl_col[4];
bGPDlayer *gpl = (bGPDlayer *)ale->data;
rgb_float_to_uchar(gpl_col, gpl->color);
gpl_col[3] = col1[3];
immUniformColor4ubv(sel ? col1 : gpl_col);
}
else {
immUniformColor4ubv(sel ? col1 : col2);
}
break;
}
default: {
immUniformColor4ubv(sel ? col1 : col2);
}
}
/* draw region twice: firstly backdrop, then the current range */
immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
uchar *color;
uchar gpl_col[4];
if (ale->type == ANIMTYPE_SUMMARY) {
color = col_summary;
}
else 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];
color = sel ? col1 : gpl_col;
}
else {
color = sel ? col1 : col2;
}
/* Color overlay on frames between the start/end frames. */
immUniformColor4ubv(color);
immRectf(pos, ac->scene->r.sfra, ymin, ac->scene->r.efra, ymax);
/* Color overlay outside the start/end frame range get a more transparent overlay. */
immUniformColor3ubvAlpha(color, MIN2(255, color[3] / 2));
immRectf(pos, v2d->cur.xmin, ymin, ac->scene->r.sfra, ymax);
immRectf(pos, ac->scene->r.efra, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
else if (ac->datatype == ANIMCONT_MASK) {
/* TODO: this is a copy of gpencil. */
uchar *color;
if (ale->type == ANIMTYPE_SUMMARY) {
color = col_summary;
}
else {
color = sel ? col1 : col2;
}
/* Color overlay on frames between the start/end frames. */
immUniformColor4ubv(color);
immRectf(pos, ac->scene->r.sfra, ymin, ac->scene->r.efra, ymax);
/* Color overlay outside the start/end frame range get a more transparent overlay. */
immUniformColor3ubvAlpha(color, MIN2(255, color[3] / 2));
immRectf(pos, v2d->cur.xmin, ymin, ac->scene->r.sfra, ymax);
immRectf(pos, ac->scene->r.efra, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
}
}
}
GPU_blend(GPU_BLEND_NONE);
/* black line marking 'current frame' for Time-Slide transform mode */
@ -379,116 +507,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region
}
immUnbindProgram();
/* Draw keyframes
* 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
*/
int action_flag = saction->flag;
if (saction->mode == SACTCONT_TIMELINE) {
action_flag &= ~(SACTION_SHOW_INTERPOLATION | SACTION_SHOW_EXTREMES);
}
ymax = ANIM_UI_get_first_channel_top(v2d);
AnimKeylistDrawList *draw_list = ED_keylist_draw_list_create();
const float scale_factor = ANIM_UI_get_keyframe_scale_factor();
for (ale = static_cast<bAnimListElem *>(anim_data.first); ale;
ale = ale->next, ymax -= channel_step)
{
const float ymin = ymax - ANIM_UI_get_channel_height();
float ycenter = (ymin + ymax) / 2.0f;
/* check if visible */
if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* check if anything to show for this channel */
if (ale->datatype != ALE_NONE) {
adt = ANIM_nla_mapping_get(ac, ale);
/* draw 'keyframes' for each specific datatype */
switch (ale->datatype) {
case ALE_ALL:
draw_summary_channel(draw_list,
static_cast<bAnimContext *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_SCE:
draw_scene_channel(draw_list,
ads,
static_cast<Scene *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_OB:
draw_object_channel(draw_list,
ads,
static_cast<Object *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_ACT:
draw_action_channel(draw_list,
adt,
static_cast<bAction *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_GROUP:
draw_agroup_channel(draw_list,
adt,
static_cast<bActionGroup *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_FCURVE:
draw_fcurve_channel(draw_list,
adt,
static_cast<FCurve *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_GREASE_PENCIL_CELS:
draw_grease_pencil_cels_channel(draw_list,
ads,
static_cast<GreasePencilLayer *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_GPFRAME:
draw_gpl_channel(draw_list,
ads,
static_cast<bGPDlayer *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_MASKLAY:
draw_masklay_channel(draw_list,
ads,
static_cast<MaskLayer *>(ale->data),
ycenter,
scale_factor,
action_flag);
break;
}
}
}
}
ED_keylist_draw_list_flush(draw_list, v2d);
ED_keylist_draw_list_free(draw_list);
draw_keyframes(ac, v2d, saction, anim_data);
/* free temporary channels used for drawing */
ANIM_animdata_freelist(&anim_data);