UI: FModifier layout updates, drag and drop

This patch implements the list panel system D7490 for FCurve modifiers.

The UI layouts are updated to make use of subpanels and to be consistent
with the rest of the interface, and easier to understand.

See the differential revision for screenshots.

This commit also significantly cleans up the FModifier UI code, and
improves, mainly by replacing the old button creation code is with
the newer interface API using RNA. In turn there is a bit of complexity
added because each FModifier has a separate panel.

Although reordering of FModifiers was not implemented before, we get
drag and drop basically for free here, so it is also included.
As noted in some older to do tasks, FModifiers aren't evaluated
in perfect order, which may be a point of improvement for the future.

Differential Revision: https://developer.blender.org/D7997
This commit is contained in:
Hans Goudey 2021-02-19 10:11:35 -06:00
parent 0d94695cc4
commit 1f5647c07d
Notes: blender-bot 2023-02-14 07:39:46 +01:00
Referenced by commit 32073993a8, i18n messages extraction script: fix handling of C unicode-escapes.
Referenced by issue #80338, FModifier Layout Updates
8 changed files with 798 additions and 797 deletions

View File

@ -32,6 +32,7 @@
#include "CLG_log.h"
#include "DNA_anim_types.h"
#include "DNA_screen_types.h"
#include "BLT_translation.h"
@ -1133,7 +1134,7 @@ FModifier *add_fmodifier(ListBase *modifiers, int type, FCurve *owner_fcu)
/* add modifier itself */
fcm = MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
fcm->type = type;
fcm->flag = FMODIFIER_FLAG_EXPANDED;
fcm->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT; /* Expand the main panel, not the subpanels. */
fcm->curve = owner_fcu;
fcm->influence = 1.0f;
BLI_addtail(modifiers, fcm);

View File

@ -1748,6 +1748,19 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
/* Add subpanels for FModifiers, which requires a field to store expansion. */
if (!DNA_struct_elem_find(fd->filesdna, "FModifier", "short", "ui_expand_flag")) {
LISTBASE_FOREACH (bAction *, act, &bmain->actions) {
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
LISTBASE_FOREACH (FModifier *, fcm, &fcu->modifiers) {
SET_FLAG_FROM_TEST(fcm->ui_expand_flag,
fcm->flag & FMODIFIER_FLAG_EXPANDED,
UI_PANEL_DATA_EXPAND_ROOT);
}
}
}
}
/* Keep this block, even when empty. */
}
}

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,11 @@ struct ID;
struct ListBase;
struct ARegion;
struct ARegionType;
struct Main;
struct NlaStrip;
struct FModifier;
struct PanelType;
struct ReportList;
struct ScrArea;
struct SpaceLink;
@ -675,11 +679,25 @@ void ANIM_draw_framerange(struct Scene *scene, struct View2D *v2d);
/* ------------- UI Panel Drawing -------------- */
/* draw a given F-Modifier for some layout/UI-Block */
void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout,
struct ID *fcurve_owner_id,
ListBase *modifiers,
struct FModifier *fcm);
struct NlaStrip *ANIM_nla_context_strip(const struct bContext *C);
struct FCurve *ANIM_graph_context_fcurve(const struct bContext *C);
/* Needed for abstraction between the graph editor and the NLA editor. */
typedef bool (*PanelTypePollFn)(const struct bContext *C, struct PanelType *pt);
/* Avoid including "UI_interface.h" here. */
typedef void (*uiListPanelIDFromDataFunc)(void *data_link, char *r_idname);
void ANIM_fmodifier_panels(const struct bContext *C,
struct ID *owner_id,
struct ListBase *fmodifiers,
uiListPanelIDFromDataFunc panel_id_fn);
void ANIM_modifier_panels_register_graph_and_NLA(struct ARegionType *region_type,
const char *modifier_panel_prefix,
PanelTypePollFn poll_function);
void ANIM_modifier_panels_register_graph_only(struct ARegionType *region_type,
const char *modifier_panel_prefix,
PanelTypePollFn poll_function);
/* ------------- Copy/Paste Buffer -------------- */

View File

@ -105,6 +105,16 @@ static bool graph_panel_context(const bContext *C, bAnimListElem **ale, FCurve *
return true;
}
FCurve *ANIM_graph_context_fcurve(const bContext *C)
{
FCurve *fcu;
if (!graph_panel_context(C, NULL, &fcu)) {
return NULL;
}
return fcu;
}
static bool graph_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
return graph_panel_context(C, NULL, NULL);
@ -1312,6 +1322,16 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *panel)
/* All the drawing code is in editors/animation/fmodifier_ui.c */
#define B_FMODIFIER_REDRAW 20
/** The start of FModifier panels registered for the graph editor. */
#define GRAPH_FMODIFIER_PANEL_PREFIX "GRAPH"
static void graph_fmodifier_panel_id(void *fcm_link, char *r_name)
{
FModifier *fcm = (FModifier *)fcm_link;
eFModifier_Types type = fcm->type;
const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
BLI_snprintf(r_name, BKE_ST_MAXNAME, "%s_PT_%s", GRAPH_FMODIFIER_PANEL_PREFIX, fmi->name);
}
static void do_graph_region_modifier_buttons(bContext *C, void *UNUSED(arg), int event)
{
@ -1327,10 +1347,8 @@ static void graph_panel_modifiers(const bContext *C, Panel *panel)
{
bAnimListElem *ale;
FCurve *fcu;
FModifier *fcm;
uiLayout *col, *row;
uiLayout *row;
uiBlock *block;
bool active;
if (!graph_panel_context(C, &ale, &fcu)) {
return;
@ -1355,14 +1373,7 @@ static void graph_panel_modifiers(const bContext *C, Panel *panel)
uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_fmodifier_paste");
}
active = !(fcu->flag & FCURVE_MOD_OFF);
/* draw each modifier */
for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) {
col = uiLayoutColumn(panel->layout, true);
uiLayoutSetActive(col, active);
ANIM_uiTemplate_fmodifier_draw(col, ale->fcurve_owner_id, &fcu->modifiers, fcm);
}
ANIM_fmodifier_panels(C, ale->fcurve_owner_id, &fcu->modifiers, graph_fmodifier_panel_id);
MEM_freeN(ale);
}
@ -1426,10 +1437,14 @@ void graph_buttons_register(ARegionType *art)
strcpy(pt->label, N_("Modifiers"));
strcpy(pt->category, "Modifiers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PANEL_TYPE_NO_HEADER;
pt->draw = graph_panel_modifiers;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
ANIM_modifier_panels_register_graph_and_NLA(art, GRAPH_FMODIFIER_PANEL_PREFIX, graph_panel_poll);
ANIM_modifier_panels_register_graph_only(art, GRAPH_FMODIFIER_PANEL_PREFIX, graph_panel_poll);
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view");
strcpy(pt->idname, "GRAPH_PT_view");
strcpy(pt->label, N_("Show Cursor"));

View File

@ -37,6 +37,7 @@
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_screen.h"
@ -184,6 +185,17 @@ bool nla_panel_context(const bContext *C,
return (found != 0);
}
NlaStrip *ANIM_nla_context_strip(const bContext *C)
{
PointerRNA strip_ptr;
if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) {
return NULL;
}
NlaStrip *strip = strip_ptr.data;
return strip;
}
#if 0
static bool nla_panel_poll(const bContext *C, PanelType *pt)
{
@ -535,13 +547,23 @@ static void nla_panel_animated_strip_time(const bContext *C, Panel *panel)
uiItemR(layout, &strip_ptr, "strip_time", 0, NULL, ICON_NONE);
}
#define NLA_FMODIFIER_PANEL_PREFIX "NLA"
static void nla_fmodifier_panel_id(void *fcm_link, char *r_name)
{
FModifier *fcm = (FModifier *)fcm_link;
eFModifier_Types type = fcm->type;
snprintf(r_name, BKE_ST_MAXNAME, "%s_PT_", NLA_FMODIFIER_PANEL_PREFIX);
const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
BLI_snprintf(r_name, BKE_ST_MAXNAME, "%s_PT_%s", NLA_FMODIFIER_PANEL_PREFIX, fmi->name);
}
/* F-Modifiers for active NLA-Strip */
static void nla_panel_modifiers(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
NlaStrip *strip;
FModifier *fcm;
uiLayout *col, *row;
uiLayout *row;
uiBlock *block;
/* check context and also validity of pointer */
@ -569,12 +591,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *panel)
uiItemO(row, "", ICON_PASTEDOWN, "NLA_OT_fmodifier_paste");
}
/* draw each modifier */
for (fcm = strip->modifiers.first; fcm; fcm = fcm->next) {
col = uiLayoutColumn(panel->layout, true);
ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.owner_id, &strip->modifiers, fcm);
}
ANIM_fmodifier_panels(C, strip_ptr.owner_id, &strip->modifiers, nla_fmodifier_panel_id);
}
/* ******************* general ******************************** */
@ -657,5 +674,9 @@ void nla_buttons_register(ARegionType *art)
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_modifiers;
pt->poll = nla_strip_eval_panel_poll;
pt->flag = PANEL_TYPE_NO_HEADER;
BLI_addtail(&art->paneltypes, pt);
ANIM_modifier_panels_register_graph_and_NLA(
art, NLA_FMODIFIER_PANEL_PREFIX, nla_strip_eval_panel_poll);
}

View File

@ -57,6 +57,13 @@ typedef struct FModifier {
short type;
/** Settings for the modifier. */
short flag;
/**
* Expansion state for the modifier panel and its subpanels, stored as a bitfield
* in depth-first order. (Maximum of sizeof(short) total panels).
*/
short ui_expand_flag;
char _pad[6];
/** The amount that the modifier should influence the value. */
float influence;
@ -96,8 +103,10 @@ typedef enum eFModifier_Types {
typedef enum eFModifier_Flags {
/** Modifier is not able to be evaluated for some reason, and should be skipped (internal). */
FMODIFIER_FLAG_DISABLED = (1 << 0),
/** Modifier's data is expanded (in UI). */
#ifdef DNA_DEPRECATED_ALLOW
/** Modifier's data is expanded (in UI). Deprecated, use `ui_expand_flag`. */
FMODIFIER_FLAG_EXPANDED = (1 << 1),
#endif
/** Modifier is active one (in UI) for editing purposes. */
FMODIFIER_FLAG_ACTIVE = (1 << 2),
/** User wants modifier to be skipped. */

View File

@ -1129,6 +1129,12 @@ static void rna_Keyframe_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *p
rna_tag_animation_update(bmain, ptr->owner_id);
}
static void rna_FModifier_show_expanded_set(PointerRNA *ptr, bool value)
{
FModifier *fcm = ptr->data;
SET_FLAG_FROM_TEST(fcm->ui_expand_flag, value, UI_PANEL_DATA_EXPAND_ROOT);
}
#else
static void rna_def_fmodifier_generator(BlenderRNA *brna)
@ -1187,6 +1193,8 @@ static void rna_def_fmodifier_generator(BlenderRNA *brna)
NULL);
RNA_def_property_ui_text(
prop, "Coefficients", "Coefficients for 'x' (starting from lowest power of x^0)");
RNA_def_property_update(
prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_verify_data_update");
}
/* --------- */
@ -1219,7 +1227,7 @@ static void rna_def_fmodifier_function_generator(BlenderRNA *brna)
prop = RNA_def_property(srna, "phase_multiplier", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(
prop, "Phase Multiplier", "Scale factor determining the 'speed' of the function");
prop, "Phase Multiple", "Scale factor determining the 'speed' of the function");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update");
prop = RNA_def_property(srna, "phase_offset", PROP_FLOAT, PROP_NONE);
@ -1632,13 +1640,14 @@ static void rna_def_fmodifier(BlenderRNA *brna)
/* settings */
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_EXPANDED);
RNA_def_property_boolean_sdna(prop, NULL, "ui_expand_flag", 0);
RNA_def_property_boolean_funcs(prop, NULL, "rna_FModifier_show_expanded_set");
RNA_def_property_ui_text(prop, "Expanded", "F-Curve Modifier's panel is expanded in UI");
RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1);
prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_MUTED);
RNA_def_property_ui_text(prop, "Muted", "Disable F-Curve Modifier evaluation");
RNA_def_property_ui_text(prop, "Enabled", "Enable F-Curve modifier evaluation");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update");
RNA_def_property_ui_icon(prop, ICON_CHECKBOX_HLT, -1);
@ -1652,7 +1661,7 @@ static void rna_def_fmodifier(BlenderRNA *brna)
/* TODO: setting this to true must ensure that all others in stack are turned off too... */
prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_ACTIVE);
RNA_def_property_ui_text(prop, "Active", "F-Curve Modifier is the one being edited");
RNA_def_property_ui_text(prop, "Active", "F-Curve modifier will show settings in the editor");
RNA_def_property_boolean_funcs(prop, NULL, "rna_FModifier_active_set");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_active_update");
RNA_def_property_ui_icon(prop, ICON_RADIOBUT_OFF, 1);
@ -1666,8 +1675,6 @@ static void rna_def_fmodifier(BlenderRNA *brna)
"F-Curve Modifier is only applied for the specified frame range to help "
"mask off effects in order to chain them");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update");
RNA_def_property_ui_icon(
prop, ICON_DISCLOSURE_TRI_RIGHT, 1); /* XXX: depends on UI implementation */
prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sfra");
@ -1709,8 +1716,6 @@ static void rna_def_fmodifier(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use Influence", "F-Curve Modifier's effects will be tempered by a default factor");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, "rna_FModifier_update");
RNA_def_property_ui_icon(
prop, ICON_DISCLOSURE_TRI_RIGHT, 1); /* XXX: depends on UI implementation */
prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "influence");