Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-02-19 19:11:35 +0300
committerHans Goudey <h.goudey@me.com>2021-02-19 19:11:35 +0300
commit1f5647c07d15d2b298b491ebe260a411f7b0d1b8 (patch)
tree7776a1724a24fa4391f2fd1c93827c2d4de63d63 /source/blender
parent0d94695cc458b1f7666104314b57b174f0ee93d1 (diff)
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
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c3
-rw-r--r--source/blender/blenloader/intern/versioning_290.c13
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c1449
-rw-r--r--source/blender/editors/include/ED_anim_api.h28
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c37
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c37
-rw-r--r--source/blender/makesdna/DNA_anim_types.h11
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c21
8 files changed, 800 insertions, 799 deletions
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index d0018a556ba..4cd49987a83 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -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);
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 089886a1c25..728235e84bf 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -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. */
}
}
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index deebf1d1efc..c17d678d866 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -32,6 +32,7 @@
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
#include "MEM_guardedalloc.h"
@@ -42,6 +43,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
+#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -56,47 +58,208 @@
#include "DEG_depsgraph.h"
-/* ********************************************** */
-/* UI STUFF */
+typedef void (*PanelDrawFn)(const bContext *, struct Panel *);
+static void fmodifier_panel_header(const bContext *C, Panel *panel);
-/* XXX! -------------------------------- */
-/* Temporary definition for limits of float number buttons
- * (FLT_MAX tends to infinity with old system). */
-#define UI_FLT_MAX 10000.0f
+/* -------------------------------------------------------------------- */
+/** \name Panel Registering and Panel Callbacks
+ * \{ */
-#define B_REDR 1
-#define B_FMODIFIER_REDRAW 20
+/**
+ * Get the list of FModifiers from the context (either the NLA or graph editor).
+ */
+static ListBase *fmodifier_list_space_specific(const bContext *C)
+{
+ ScrArea *area = CTX_wm_area(C);
+
+ if (area->spacetype == SPACE_GRAPH) {
+ FCurve *fcu = ANIM_graph_context_fcurve(C);
+ return &fcu->modifiers;
+ }
+
+ if (area->spacetype == SPACE_NLA) {
+ NlaStrip *strip = ANIM_nla_context_strip(C);
+ return &strip->modifiers;
+ }
-/* callback to update depsgraph on value changes */
-static void deg_update(bContext *C, void *owner_id, void *UNUSED(var2))
+ /* This should not be called in any other space. */
+ BLI_assert(false);
+ return NULL;
+}
+
+/**
+ * Get a pointer to the panel's FModifier, and also its owner ID if \a r_owner_id is not NULL.
+ * Also in the graph editor, gray out the panel if the FModifier's FCurve has modifiers turned off.
+ */
+static PointerRNA *fmodifier_get_pointers(const bContext *C, const Panel *panel, ID **r_owner_id)
{
- /* send notifiers */
- /* XXX for now, this is the only way to get updates in all the right places...
- * but would be nice to have a special one in this case. */
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- DEG_id_tag_update(owner_id, ID_RECALC_ANIMATION);
+ PointerRNA *ptr = UI_panel_custom_data_get(panel);
+
+ if (r_owner_id != NULL) {
+ *r_owner_id = ptr->owner_id;
+ }
+
+ if (C != NULL && CTX_wm_space_graph(C)) {
+ FCurve *fcu = ANIM_graph_context_fcurve(C);
+ uiLayoutSetActive(panel->layout, !(fcu->flag & FCURVE_MOD_OFF));
+ }
+
+ return ptr;
}
-/* callback to verify modifier data */
-static void validate_fmodifier_cb(bContext *C, void *fcm_v, void *owner_id)
+/**
+ * Move an FModifier to the index it's moved to after a drag and drop.
+ */
+static void fmodifier_reorder(bContext *C, Panel *panel, int new_index)
{
- FModifier *fcm = (FModifier *)fcm_v;
- const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+ ID *owner_id;
+ PointerRNA *ptr = fmodifier_get_pointers(NULL, panel, &owner_id);
+ FModifier *fcm = ptr->data;
+ const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(fcm->type);
+
+ /* Cycles modifier has to be the first, so make sure it's kept that way. */
+ if (fmi->requires & FMI_REQUIRES_ORIGINAL_DATA) {
+ WM_report(RPT_ERROR, "Modifier requires original data");
+ return;
+ }
- /* call the verify callback on the modifier if applicable */
- if (fmi && fmi->verify_data) {
- fmi->verify_data(fcm);
+ ListBase *modifiers = fmodifier_list_space_specific(C);
+
+ /* Again, make sure we don't move a modifier before a cycles modifier. */
+ FModifier *fcm_first = modifiers->first;
+ const FModifierTypeInfo *fmi_first = get_fmodifier_typeinfo(fcm_first->type);
+ if (fmi_first->requires & FMI_REQUIRES_ORIGINAL_DATA && new_index == 0) {
+ WM_report(RPT_ERROR, "Modifier requires original data");
+ return;
}
- if (owner_id) {
- deg_update(C, owner_id, NULL);
+
+ int current_index = BLI_findindex(modifiers, fcm);
+ BLI_assert(current_index >= 0);
+ BLI_assert(new_index >= 0);
+
+ /* Don't do anything if the drag didn't change the index. */
+ if (current_index == new_index) {
+ return;
}
+
+ /* Move the FModifier in the list. */
+ BLI_listbase_link_move(modifiers, fcm, new_index - current_index);
+
+ ED_undo_push(C, "Reorder F-Curve Modifier");
+
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ DEG_id_tag_update(owner_id, ID_RECALC_ANIMATION);
+}
+
+static short get_fmodifier_expand_flag(const bContext *UNUSED(C), Panel *panel)
+{
+ PointerRNA *ptr = fmodifier_get_pointers(NULL, panel, NULL);
+ FModifier *fcm = (FModifier *)ptr->data;
+
+ return fcm->ui_expand_flag;
+}
+
+static void set_fmodifier_expand_flag(const bContext *UNUSED(C), Panel *panel, short expand_flag)
+{
+ PointerRNA *ptr = fmodifier_get_pointers(NULL, panel, NULL);
+ FModifier *fcm = (FModifier *)ptr->data;
+
+ fcm->ui_expand_flag = expand_flag;
+}
+
+static PanelType *fmodifier_panel_register(ARegionType *region_type,
+ eFModifier_Types type,
+ PanelDrawFn draw,
+ PanelTypePollFn poll,
+ const char *id_prefix)
+{
+ /* Get the name for the modifier's panel. */
+ char panel_idname[BKE_ST_MAXNAME];
+ const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
+ BLI_snprintf(panel_idname, BKE_ST_MAXNAME, "%s_PT_%s", id_prefix, fmi->name);
+
+ PanelType *panel_type = MEM_callocN(sizeof(PanelType), panel_idname);
+
+ /* Intentionally leave the label field blank. The header is filled with buttons. */
+ BLI_strncpy(panel_type->idname, panel_idname, BKE_ST_MAXNAME);
+ BLI_strncpy(panel_type->category, "Modifiers", BKE_ST_MAXNAME);
+ BLI_strncpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA, BKE_ST_MAXNAME);
+
+ panel_type->draw_header = fmodifier_panel_header;
+ panel_type->draw = draw;
+ panel_type->poll = poll;
+
+ /* Give the panel the special flag that says it was built here and corresponds to a
+ * modifer rather than a PanelType. */
+ panel_type->flag = PANEL_TYPE_HEADER_EXPAND | PANEL_TYPE_DRAW_BOX | PANEL_TYPE_INSTANCED;
+ panel_type->reorder = fmodifier_reorder;
+ panel_type->get_list_data_expand_flag = get_fmodifier_expand_flag;
+ panel_type->set_list_data_expand_flag = set_fmodifier_expand_flag;
+
+ BLI_addtail(&region_type->paneltypes, panel_type);
+
+ return panel_type;
}
+/**
+ * Add a child panel to the parent.
+ *
+ * \note To create the panel type's idname, it appends the \a name argument to the \a parent's
+ * idname.
+ */
+static PanelType *fmodifier_subpanel_register(ARegionType *region_type,
+ const char *name,
+ const char *label,
+ PanelDrawFn draw_header,
+ PanelDrawFn draw,
+ PanelTypePollFn poll,
+ PanelType *parent)
+{
+ /* Create the subpanel's ID name. */
+ char panel_idname[BKE_ST_MAXNAME];
+ BLI_snprintf(panel_idname, BKE_ST_MAXNAME, "%s_%s", parent->idname, name);
+
+ PanelType *panel_type = MEM_callocN(sizeof(PanelType), panel_idname);
+
+ BLI_strncpy(panel_type->idname, panel_idname, BKE_ST_MAXNAME);
+ BLI_strncpy(panel_type->label, label, BKE_ST_MAXNAME);
+ BLI_strncpy(panel_type->category, "Modifiers", BKE_ST_MAXNAME);
+ BLI_strncpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA, BKE_ST_MAXNAME);
+
+ panel_type->draw_header = draw_header;
+ panel_type->draw = draw;
+ panel_type->poll = poll;
+ panel_type->flag = PANEL_TYPE_DEFAULT_CLOSED | PANEL_TYPE_DRAW_BOX;
+
+ BLI_assert(parent != NULL);
+ BLI_strncpy(panel_type->parent_id, parent->idname, BKE_ST_MAXNAME);
+ panel_type->parent = parent;
+ BLI_addtail(&parent->children, BLI_genericNodeN(panel_type));
+ BLI_addtail(&region_type->paneltypes, panel_type);
+
+ return panel_type;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name General UI Callbacks and Drawing
+ * \{ */
+
+/* XXX! -------------------------------- */
+/* Temporary definition for limits of float number buttons
+ * (FLT_MAX tends to infinity with old system). */
+#define UI_FLT_MAX 10000.0f
+
+#define B_REDR 1
+#define B_FMODIFIER_REDRAW 20
+
/* callback to remove the given modifier */
typedef struct FModifierDeleteContext {
- ID *fcurve_owner_id;
+ ID *owner_id;
ListBase *modifiers;
} FModifierDeleteContext;
+
static void delete_fmodifier_cb(bContext *C, void *ctx_v, void *fcm_v)
{
FModifierDeleteContext *ctx = (FModifierDeleteContext *)ctx_v;
@@ -108,466 +271,334 @@ static void delete_fmodifier_cb(bContext *C, void *ctx_v, void *fcm_v)
ED_undo_push(C, "Delete F-Curve Modifier");
- deg_update(C, ctx->fcurve_owner_id, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ DEG_id_tag_update(ctx->owner_id, ID_RECALC_ANIMATION);
}
-/* --------------- */
-/* draw settings for generator modifier */
-static void draw_modifier__generator(uiLayout *layout,
- ID *fcurve_owner_id,
- FModifier *fcm,
- short width)
+static void fmodifier_influence_draw(uiLayout *layout, PointerRNA *ptr)
{
+ FModifier *fcm = (FModifier *)ptr->data;
+ uiItemS(layout);
+
+ uiLayout *row = uiLayoutRowWithHeading(layout, true, IFACE_("Influence"));
+ uiItemR(row, ptr, "use_influence", 0, "", ICON_NONE);
+ uiLayout *sub = uiLayoutRow(row, true);
+
+ uiLayoutSetActive(sub, fcm->flag & FMODIFIER_FLAG_USEINFLUENCE);
+ uiItemR(sub, ptr, "influence", 0, "", ICON_NONE);
+}
+
+static void fmodifier_frame_range_header_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
+
+ uiItemR(layout, ptr, "use_restricted_range", 0, NULL, ICON_NONE);
+}
+
+static void fmodifier_frame_range_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *col;
+ uiLayout *layout = panel->layout;
+
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
+
+ uiLayoutSetPropSep(layout, true);
+
+ FModifier *fcm = (FModifier *)ptr->data;
+ uiLayoutSetActive(layout, fcm->flag & FMODIFIER_FLAG_RANGERESTRICT);
+
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
+ uiItemR(col, ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
+
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "blend_in", 0, IFACE_("Blend In"), ICON_NONE);
+ uiItemR(col, ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE);
+}
+
+static void fmodifier_panel_header(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ ID *owner_id;
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, &owner_id);
+ FModifier *fcm = (FModifier *)ptr->data;
+ const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
+
+ uiBlock *block = uiLayoutGetBlock(layout);
+
+ uiLayout *sub = uiLayoutRow(layout, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+ uiLayoutSetEmboss(sub, UI_EMBOSS_NONE);
+
+ /* Checkbox for 'active' status (for now). */
+ uiItemR(sub, ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+
+ /* Name. */
+ if (fmi) {
+ uiItemL(sub, IFACE_(fmi->name), ICON_NONE);
+ }
+ else {
+ uiItemL(sub, IFACE_("<Unknown Modifier>"), ICON_NONE);
+ }
+
+ /* Right align. */
+ sub = uiLayoutRow(layout, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
+ uiLayoutSetEmboss(sub, UI_EMBOSS_NONE);
+
+ /* 'Mute' button. */
+ uiItemR(sub, ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+
+ /* Delete button. */
+ uiBut *but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ B_REDR,
+ ICON_X,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Delete Modifier"));
+ FModifierDeleteContext *ctx = MEM_mallocN(sizeof(FModifierDeleteContext), __func__);
+ ctx->owner_id = owner_id;
+ ctx->modifiers = fmodifier_list_space_specific(C);
+ BLI_assert(ctx->modifiers != NULL);
+
+ UI_but_funcN_set(but, delete_fmodifier_cb, ctx, fcm);
+
+ uiItemS(layout);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generator Modifier
+ * \{ */
+
+static void generator_panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ ID *owner_id;
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, &owner_id);
+ FModifier *fcm = (FModifier *)ptr->data;
FMod_Generator *data = (FMod_Generator *)fcm->data;
- uiLayout /* *col, */ /* UNUSED */ *row;
- uiBlock *block;
- uiBut *but;
- PointerRNA ptr;
- short bwidth = width - 1.5 * UI_UNIT_X; /* max button width */
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
-
- /* basic settings (backdrop + mode selector + some padding) */
- /* col = uiLayoutColumn(layout, true); */ /* UNUSED */
- block = uiLayoutGetBlock(layout);
- UI_block_align_begin(block);
- but = uiDefButR(block,
- UI_BTYPE_MENU,
- B_FMODIFIER_REDRAW,
- NULL,
- 0,
- 0,
- bwidth,
- UI_UNIT_Y,
- &ptr,
- "mode",
- -1,
- 0,
- 0,
- -1,
- -1,
- NULL);
- UI_but_func_set(but, validate_fmodifier_cb, fcm, NULL);
-
- uiDefButR(block,
- UI_BTYPE_TOGGLE,
- B_FMODIFIER_REDRAW,
- NULL,
- 0,
- 0,
- bwidth,
- UI_UNIT_Y,
- &ptr,
- "use_additive",
- -1,
- 0,
- 0,
- -1,
- -1,
- NULL);
- UI_block_align_end(block);
-
- /* now add settings for individual modes */
+
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+
+ uiItemR(layout, ptr, "use_additive", 0, NULL, ICON_NONE);
+
+ uiItemR(layout, ptr, "poly_order", 0, IFACE_("Order"), ICON_NONE);
+
+ PropertyRNA *prop = RNA_struct_find_property(ptr, "coefficients");
+ uiLayout *col = uiLayoutColumn(layout, true);
switch (data->mode) {
- case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
+ case FCM_GENERATOR_POLYNOMIAL: /* Polynomial expression. */
{
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- float *cp = NULL;
+
char xval[32];
- int maxXWidth;
-
- /* draw polynomial order selector */
- row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
-
- but = uiDefButI(
- block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- IFACE_("Poly Order:"),
- 0.5f * UI_UNIT_X,
- 0,
- bwidth,
- UI_UNIT_Y,
- &data->poly_order,
- 1,
- 100,
- 0,
- 0,
- TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
- UI_but_number_step_size_set(but, 1);
- UI_but_func_set(but, validate_fmodifier_cb, fcm, fcurve_owner_id);
-
- /* calculate maximum width of label for "x^n" labels */
- if (data->arraysize > 2) {
- BLI_snprintf(xval, sizeof(xval), "x^%u", data->arraysize);
- /* XXX: UI_fontstyle_string_width is not accurate */
- maxXWidth = UI_fontstyle_string_width(fstyle, xval) + 0.5 * UI_UNIT_X;
- }
- else {
- /* basic size (just "x") */
- maxXWidth = UI_fontstyle_string_width(fstyle, "x") + 0.5 * UI_UNIT_X;
- }
- /* draw controls for each coefficient and a + sign at end of row */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
-
- /* Update depsgraph when values change */
- UI_block_func_set(block, deg_update, fcurve_owner_id, NULL);
-
- cp = data->coefficients;
- for (uint i = 0; (i < data->arraysize) && (cp); i++, cp++) {
- /* To align with first line... */
- if (i) {
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- " ",
- 0,
- 0,
- 2 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- }
- else {
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- "y =",
- 0,
- 0,
- 2 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- }
-
- /* coefficient */
- but = uiDefButF(block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- "",
- 0,
- 0,
- bwidth / 2,
- UI_UNIT_Y,
- cp,
- -UI_FLT_MAX,
- UI_FLT_MAX,
- 0,
- 0,
- TIP_("Coefficient for polynomial"));
- UI_but_number_step_size_set(but, 10);
- UI_but_number_precision_set(but, 3);
-
- /* 'x' param (and '+' if necessary) */
- if (i == 0) {
- BLI_strncpy(xval, " ", sizeof(xval));
- }
- else if (i == 1) {
- BLI_strncpy(xval, "x", sizeof(xval));
- }
- else {
- BLI_snprintf(xval, sizeof(xval), "x^%u", i);
- }
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- xval,
- 0,
- 0,
- maxXWidth,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- TIP_("Power of x"));
-
- if ((i != (data->arraysize - 1)) || ((i == 0) && data->arraysize == 2)) {
- uiDefBut(
- block, UI_BTYPE_LABEL, 1, "+", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- /* next coefficient on a new row */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
- }
- else {
- /* For alignment in UI! */
- uiDefBut(
- block, UI_BTYPE_LABEL, 1, " ", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- }
+ /* The first value gets a "Coefficient" label. */
+ BLI_strncpy(xval, "Coefficient", sizeof(xval));
+
+ for (int i = 0; i < data->arraysize; i++) {
+ uiItemFullR(col, ptr, prop, i, 0, 0, N_(xval), ICON_NONE);
+ BLI_snprintf(xval, sizeof(xval), "x^%d", i + 1);
}
break;
}
-
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* Factorized polynomial expression */
{
- float *cp = NULL;
-
- /* draw polynomial order selector */
- row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
-
- but = uiDefButI(
- block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- IFACE_("Poly Order:"),
- 0,
- 0,
- width - 1.5 * UI_UNIT_X,
- UI_UNIT_Y,
- &data->poly_order,
- 1,
- 100,
- 0,
- 0,
- TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
- UI_but_func_set(but, validate_fmodifier_cb, fcm, fcurve_owner_id);
- UI_but_number_step_size_set(but, 1);
-
- /* draw controls for each pair of coefficients */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
-
- /* Update depsgraph when values change */
- UI_block_func_set(block, deg_update, fcurve_owner_id, NULL);
-
- cp = data->coefficients;
- for (uint i = 0; (i < data->poly_order) && (cp); i++, cp += 2) {
- /* To align with first line */
- if (i) {
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- " ",
- 0,
- 0,
- 2.5 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- }
- else {
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- "y =",
- 0,
- 0,
- 2.5 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- }
- /* opening bracket */
- uiDefBut(
- block, UI_BTYPE_LABEL, 1, "(", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
-
- /* coefficients */
- but = uiDefButF(block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- "",
- 0,
- 0,
- 5 * UI_UNIT_X,
- UI_UNIT_Y,
- cp,
- -UI_FLT_MAX,
- UI_FLT_MAX,
- 0,
- 0,
- TIP_("Coefficient of x"));
- UI_but_number_step_size_set(but, 10);
- UI_but_number_precision_set(but, 3);
-
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- "x +",
- 0,
- 0,
- 2 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
-
- but = uiDefButF(block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- "",
- 0,
- 0,
- 5 * UI_UNIT_X,
- UI_UNIT_Y,
- cp + 1,
- -UI_FLT_MAX,
- UI_FLT_MAX,
- 0,
- 0,
- TIP_("Second coefficient"));
- UI_but_number_step_size_set(but, 10);
- UI_but_number_precision_set(but, 3);
-
- /* closing bracket and multiplication sign */
- if ((i != (data->poly_order - 1)) || ((i == 0) && data->poly_order == 2)) {
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- ") \xc3\x97",
- 0,
- 0,
- 2 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
-
- /* set up new row for the next pair of coefficients */
- row = uiLayoutRow(layout, true);
- block = uiLayoutGetBlock(row);
- }
- else {
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- ") ",
- 0,
- 0,
- 2 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
- }
+ {
+ /* Add column labels above the buttons to prevent confusion.
+ * Fake the property split layout, otherwise the labels use the full row. */
+ uiLayout *split = uiLayoutSplit(col, 0.4f, false);
+ uiLayoutColumn(split, false);
+ uiLayout *title_col = uiLayoutColumn(split, false);
+ uiLayout *title_row = uiLayoutRow(title_col, true);
+ uiItemL(title_row, N_("A"), ICON_NONE);
+ uiItemL(title_row, N_("B"), ICON_NONE);
+ }
+
+ uiLayout *first_row = uiLayoutRow(col, true);
+ uiItemFullR(first_row, ptr, prop, 0, 0, 0, N_("y = (Ax + B)"), ICON_NONE);
+ uiItemFullR(first_row, ptr, prop, 1, 0, 0, "", ICON_NONE);
+ for (int i = 2; i < data->arraysize - 1; i++) {
+ /* \u2715 is the multiplication symbol. */
+ uiLayout *row = uiLayoutRow(col, true);
+ uiItemFullR(row, ptr, prop, i, 0, 0, N_("\u2715 (Ax + B)"), ICON_NONE);
+ uiItemFullR(row, ptr, prop, i + 1, 0, 0, "", ICON_NONE);
}
break;
}
}
+
+ fmodifier_influence_draw(layout, ptr);
}
-/* --------------- */
+static void panel_register_generator(ARegionType *region_type,
+ const char *id_prefix,
+ PanelTypePollFn poll_fn)
+{
+ PanelType *panel_type = fmodifier_panel_register(
+ region_type, FMODIFIER_TYPE_GENERATOR, generator_panel_draw, poll_fn, id_prefix);
+ fmodifier_subpanel_register(region_type,
+ "frame_range",
+ "",
+ fmodifier_frame_range_header_draw,
+ fmodifier_frame_range_draw,
+ poll_fn,
+ panel_type);
+}
+
+/** \} */
-/* draw settings for generator modifier */
-static void draw_modifier__fn_generator(uiLayout *layout,
- ID *fcurve_owner_id,
- FModifier *fcm,
- short UNUSED(width))
+/* -------------------------------------------------------------------- */
+/** \name Function Generator Modifier
+ * \{ */
+
+static void fn_generator_panel_draw(const bContext *C, Panel *panel)
{
uiLayout *col;
- PointerRNA ptr;
+ uiLayout *layout = panel->layout;
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
- /* add the settings */
- col = uiLayoutColumn(layout, true);
- uiItemR(col, &ptr, "function_type", 0, "", ICON_NONE);
- uiItemR(col, &ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
-
- col = uiLayoutColumn(layout, false); /* no grouping for now */
- uiItemR(col, &ptr, "amplitude", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "phase_multiplier", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "phase_offset", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "value_offset", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "function_type", 0, "", ICON_NONE);
+
+ uiLayoutSetPropSep(layout, true);
+
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "use_additive", 0, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "amplitude", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "phase_multiplier", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "phase_offset", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "value_offset", 0, NULL, ICON_NONE);
+
+ fmodifier_influence_draw(layout, ptr);
}
-/* --------------- */
+static void panel_register_fn_generator(ARegionType *region_type,
+ const char *id_prefix,
+ PanelTypePollFn poll_fn)
+{
+ PanelType *panel_type = fmodifier_panel_register(
+ region_type, FMODIFIER_TYPE_FN_GENERATOR, fn_generator_panel_draw, poll_fn, id_prefix);
+ fmodifier_subpanel_register(region_type,
+ "frame_range",
+ "",
+ fmodifier_frame_range_header_draw,
+ fmodifier_frame_range_draw,
+ poll_fn,
+ panel_type);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cycles Modifier
+ * \{ */
+
+static void cycles_panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *col;
+ uiLayout *layout = panel->layout;
+
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
+
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+
+ /* Before. */
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "mode_before", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "cycles_before", 0, IFACE_("Count"), ICON_NONE);
+
+ /* After. */
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "mode_after", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "cycles_after", 0, IFACE_("Count"), ICON_NONE);
+
+ fmodifier_influence_draw(layout, ptr);
+}
-/* draw settings for cycles modifier */
-static void draw_modifier__cycles(uiLayout *layout,
- ID *fcurve_owner_id,
- FModifier *fcm,
- short UNUSED(width))
+static void panel_register_cycles(ARegionType *region_type,
+ const char *id_prefix,
+ PanelTypePollFn poll_fn)
{
- uiLayout *split, *col;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierCycles, fcm, &ptr);
-
- /* split into 2 columns
- * NOTE: the mode combination-boxes shouldn't get labels, otherwise there isn't enough room. */
- split = uiLayoutSplit(layout, 0.5f, false);
-
- /* before range */
- col = uiLayoutColumn(split, true);
- uiItemL(col, IFACE_("Before:"), ICON_NONE);
- uiItemR(col, &ptr, "mode_before", 0, "", ICON_NONE);
- uiItemR(col, &ptr, "cycles_before", 0, NULL, ICON_NONE);
-
- /* after range */
- col = uiLayoutColumn(split, true);
- uiItemL(col, IFACE_("After:"), ICON_NONE);
- uiItemR(col, &ptr, "mode_after", 0, "", ICON_NONE);
- uiItemR(col, &ptr, "cycles_after", 0, NULL, ICON_NONE);
+ PanelType *panel_type = fmodifier_panel_register(
+ region_type, FMODIFIER_TYPE_CYCLES, cycles_panel_draw, poll_fn, id_prefix);
+ fmodifier_subpanel_register(region_type,
+ "frame_range",
+ "",
+ fmodifier_frame_range_header_draw,
+ fmodifier_frame_range_draw,
+ poll_fn,
+ panel_type);
}
-/* --------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Noise Modifier
+ * \{ */
-/* draw settings for noise modifier */
-static void draw_modifier__noise(uiLayout *layout,
- ID *fcurve_owner_id,
- FModifier *fcm,
- short UNUSED(width))
+static void noise_panel_draw(const bContext *C, Panel *panel)
{
- uiLayout *split, *col;
- PointerRNA ptr;
+ uiLayout *col;
+ uiLayout *layout = panel->layout;
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierNoise, fcm, &ptr);
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
- /* blending mode */
- uiItemR(layout, &ptr, "blend_type", 0, NULL, ICON_NONE);
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
- /* split into 2 columns */
- split = uiLayoutSplit(layout, 0.5f, false);
+ uiItemR(layout, ptr, "blend_type", 0, NULL, ICON_NONE);
- /* col 1 */
- col = uiLayoutColumn(split, false);
- uiItemR(col, &ptr, "scale", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "strength", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "offset", 0, NULL, ICON_NONE);
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "scale", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "strength", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "phase", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "depth", 0, NULL, ICON_NONE);
- /* col 2 */
- col = uiLayoutColumn(split, false);
- uiItemR(col, &ptr, "phase", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "depth", 0, NULL, ICON_NONE);
+ fmodifier_influence_draw(layout, ptr);
+}
+
+static void panel_register_noise(ARegionType *region_type,
+ const char *id_prefix,
+ PanelTypePollFn poll_fn)
+{
+ PanelType *panel_type = fmodifier_panel_register(
+ region_type, FMODIFIER_TYPE_NOISE, noise_panel_draw, poll_fn, id_prefix);
+ fmodifier_subpanel_register(region_type,
+ "frame_range",
+ "",
+ fmodifier_frame_range_header_draw,
+ fmodifier_frame_range_draw,
+ poll_fn,
+ panel_type);
}
-/* callback to add new envelope data point */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Enevelope Modifier
+ * \{ */
+
static void fmod_envelope_addpoint_cb(bContext *C, void *fcm_dv, void *UNUSED(arg))
{
Scene *scene = CTX_data_scene(C);
@@ -656,132 +687,60 @@ static void fmod_envelope_deletepoint_cb(bContext *UNUSED(C), void *fcm_dv, void
}
/* draw settings for envelope modifier */
-static void draw_modifier__envelope(uiLayout *layout,
- ID *fcurve_owner_id,
- FModifier *fcm,
- short UNUSED(width))
+static void envelope_panel_draw(const bContext *C, Panel *panel)
{
+ uiLayout *row, *col;
+ uiLayout *layout = panel->layout;
+
+ ID *owner_id;
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, &owner_id);
+ FModifier *fcm = (FModifier *)ptr->data;
FMod_Envelope *env = (FMod_Envelope *)fcm->data;
- FCM_EnvelopeData *fed;
- uiLayout *col, *row;
- uiBlock *block;
- uiBut *but;
- PointerRNA ptr;
- int i;
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierEnvelope, fcm, &ptr);
+ uiLayoutSetPropSep(layout, true);
- /* general settings */
+ /* General settings. */
col = uiLayoutColumn(layout, true);
- uiItemL(col, IFACE_("Envelope:"), ICON_NONE);
- uiItemR(col, &ptr, "reference_value", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "reference_value", 0, IFACE_("Reference"), ICON_NONE);
+ uiItemR(col, ptr, "default_min", 0, IFACE_("Min"), ICON_NONE);
+ uiItemR(col, ptr, "default_max", 0, IFACE_("Max"), ICON_NONE);
- row = uiLayoutRow(col, true);
- uiItemR(row, &ptr, "default_min", 0, IFACE_("Min"), ICON_NONE);
- uiItemR(row, &ptr, "default_max", 0, IFACE_("Max"), ICON_NONE);
+ /* Control points list. */
- /* control points header */
- /* TODO: move this control-point control stuff to using the new special widgets for lists
- * the current way is far too cramped */
row = uiLayoutRow(layout, false);
- block = uiLayoutGetBlock(row);
-
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 1,
- IFACE_("Control Points:"),
- 0,
- 0,
- 7.5 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- "");
-
- but = uiDefBut(block,
- UI_BTYPE_BUT,
- B_FMODIFIER_REDRAW,
- IFACE_("Add Point"),
- 0,
- 0,
- 7.5 * UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Add a new control-point to the envelope on the current frame"));
+ uiBlock *block = uiLayoutGetBlock(row);
+
+ uiBut *but = uiDefBut(block,
+ UI_BTYPE_BUT,
+ B_FMODIFIER_REDRAW,
+ IFACE_("Add Control Point"),
+ 0,
+ 0,
+ 7.5 * UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Add a new control-point to the envelope on the current frame"));
UI_but_func_set(but, fmod_envelope_addpoint_cb, env, NULL);
- /* control points list */
- for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
+ col = uiLayoutColumn(layout, false);
+ uiLayoutSetPropSep(col, false);
+
+ FCM_EnvelopeData *fed = env->data;
+ for (int i = 0; i < env->totvert; i++, fed++) {
PointerRNA ctrl_ptr;
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierEnvelopeControlPoint, fed, &ctrl_ptr);
+ RNA_pointer_create(owner_id, &RNA_FModifierEnvelopeControlPoint, fed, &ctrl_ptr);
/* get a new row to operate on */
- row = uiLayoutRow(layout, true);
+ row = uiLayoutRow(col, true);
block = uiLayoutGetBlock(row);
- UI_block_align_begin(block);
- but = uiDefButR(block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- IFACE_("Fra:"),
- 0,
- 0,
- 4.5 * UI_UNIT_X,
- UI_UNIT_Y,
- &ctrl_ptr,
- "frame",
- -1,
- -MAXFRAMEF,
- MAXFRAMEF,
- 0,
- 0,
- NULL);
- UI_but_number_step_size_set(but, 10);
- UI_but_number_precision_set(but, 1);
- but = uiDefButR(block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- IFACE_("Min:"),
- 0,
- 0,
- 5 * UI_UNIT_X,
- UI_UNIT_Y,
- &ctrl_ptr,
- "min",
- -1,
- -UI_FLT_MAX,
- UI_FLT_MAX,
- 0,
- 0,
- NULL);
- UI_but_number_step_size_set(but, 10);
- UI_but_number_precision_set(but, 2);
- but = uiDefButR(block,
- UI_BTYPE_NUM,
- B_FMODIFIER_REDRAW,
- IFACE_("Max:"),
- 0,
- 0,
- 5 * UI_UNIT_X,
- UI_UNIT_Y,
- &ctrl_ptr,
- "max",
- -1,
- -UI_FLT_MAX,
- UI_FLT_MAX,
- 0,
- 0,
- NULL);
- UI_but_number_step_size_set(but, 10);
- UI_but_number_precision_set(but, 2);
+ uiItemR(row, &ctrl_ptr, "frame", 0, NULL, ICON_NONE);
+ uiItemR(row, &ctrl_ptr, "min", 0, IFACE_("Min"), ICON_NONE);
+ uiItemR(row, &ctrl_ptr, "max", 0, IFACE_("Max"), ICON_NONE);
but = uiDefIconBut(block,
UI_BTYPE_BUT,
@@ -800,251 +759,211 @@ static void draw_modifier__envelope(uiLayout *layout,
UI_but_func_set(but, fmod_envelope_deletepoint_cb, env, POINTER_FROM_INT(i));
UI_block_align_begin(block);
}
-}
-/* --------------- */
+ fmodifier_influence_draw(layout, ptr);
+}
-/* draw settings for limits modifier */
-static void draw_modifier__limits(uiLayout *layout,
- ID *fcurve_owner_id,
- FModifier *fcm,
- short UNUSED(width))
+static void panel_register_envelope(ARegionType *region_type,
+ const char *id_prefix,
+ PanelTypePollFn poll_fn)
{
- uiLayout *split, *col /* , *row */ /* UNUSED */;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierLimits, fcm, &ptr);
-
- /* row 1: minimum */
- {
- /* row = uiLayoutRow(layout, false); */ /* UNUSED */
-
- /* split into 2 columns */
- split = uiLayoutSplit(layout, 0.5f, false);
+ PanelType *panel_type = fmodifier_panel_register(
+ region_type, FMODIFIER_TYPE_ENVELOPE, envelope_panel_draw, poll_fn, id_prefix);
+ fmodifier_subpanel_register(region_type,
+ "frame_range",
+ "",
+ fmodifier_frame_range_header_draw,
+ fmodifier_frame_range_draw,
+ poll_fn,
+ panel_type);
+}
- /* x-minimum */
- col = uiLayoutColumn(split, true);
- uiItemR(col, &ptr, "use_min_x", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "min_x", 0, NULL, ICON_NONE);
+/** \} */
- /* y-minimum*/
- col = uiLayoutColumn(split, true);
- uiItemR(col, &ptr, "use_min_y", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "min_y", 0, NULL, ICON_NONE);
- }
+/* -------------------------------------------------------------------- */
+/** \name Limits Modifier
+ * \{ */
- /* row 2: maximum */
- {
- /* row = uiLayoutRow(layout, false); */ /* UNUSED */
+static void limits_panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *col, *row, *sub;
+ uiLayout *layout = panel->layout;
- /* split into 2 columns */
- split = uiLayoutSplit(layout, 0.5f, false);
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
- /* x-minimum */
- col = uiLayoutColumn(split, true);
- uiItemR(col, &ptr, "use_max_x", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "max_x", 0, NULL, ICON_NONE);
+ uiLayoutSetPropSep(layout, true);
- /* y-minimum*/
- col = uiLayoutColumn(split, true);
- uiItemR(col, &ptr, "use_max_y", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "max_y", 0, NULL, ICON_NONE);
- }
+ /* Minimums. */
+ col = uiLayoutColumn(layout, false);
+ row = uiLayoutRowWithHeading(col, true, IFACE_("Minumum X"));
+ uiItemR(row, ptr, "use_min_x", 0, "", ICON_NONE);
+ sub = uiLayoutColumn(row, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min_x"));
+ uiItemR(sub, ptr, "min_x", 0, "", ICON_NONE);
+
+ row = uiLayoutRowWithHeading(col, true, IFACE_("Y"));
+ uiItemR(row, ptr, "use_min_y", 0, "", ICON_NONE);
+ sub = uiLayoutColumn(row, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min_y"));
+ uiItemR(sub, ptr, "min_y", 0, "", ICON_NONE);
+
+ /* Maximums. */
+ col = uiLayoutColumn(layout, false);
+ row = uiLayoutRowWithHeading(col, true, IFACE_("Maximum X"));
+ uiItemR(row, ptr, "use_max_x", 0, "", ICON_NONE);
+ sub = uiLayoutColumn(row, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max_x"));
+ uiItemR(sub, ptr, "max_x", 0, "", ICON_NONE);
+
+ row = uiLayoutRowWithHeading(col, true, IFACE_("Y"));
+ uiItemR(row, ptr, "use_max_y", 0, "", ICON_NONE);
+ sub = uiLayoutColumn(row, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max_y"));
+ uiItemR(sub, ptr, "max_y", 0, "", ICON_NONE);
+
+ fmodifier_influence_draw(layout, ptr);
}
-/* --------------- */
-
-/* draw settings for stepped interpolation modifier */
-static void draw_modifier__stepped(uiLayout *layout,
- ID *fcurve_owner_id,
- FModifier *fcm,
- short UNUSED(width))
+static void panel_register_limits(ARegionType *region_type,
+ const char *id_prefix,
+ PanelTypePollFn poll_fn)
{
- uiLayout *col, *sub;
- PointerRNA ptr;
+ PanelType *panel_type = fmodifier_panel_register(
+ region_type, FMODIFIER_TYPE_LIMITS, limits_panel_draw, poll_fn, id_prefix);
+ fmodifier_subpanel_register(region_type,
+ "frame_range",
+ "",
+ fmodifier_frame_range_header_draw,
+ fmodifier_frame_range_draw,
+ poll_fn,
+ panel_type);
+}
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifierStepped, fcm, &ptr);
+/** \} */
- /* block 1: "stepping" settings */
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &ptr, "frame_step", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "frame_offset", 0, NULL, ICON_NONE);
+/* -------------------------------------------------------------------- */
+/** \name Stepped Interpolation Modifier
+ * \{ */
- /* block 2: start range settings */
- col = uiLayoutColumn(layout, true);
- uiItemR(col, &ptr, "use_frame_start", 0, NULL, ICON_NONE);
+static void stepped_panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *col, *sub, *row;
+ uiLayout *layout = panel->layout;
- sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_frame_start"));
- uiItemR(sub, &ptr, "frame_start", 0, NULL, ICON_NONE);
+ PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
- /* block 3: end range settings */
- col = uiLayoutColumn(layout, true);
- uiItemR(col, &ptr, "use_frame_end", 0, NULL, ICON_NONE);
+ uiLayoutSetPropSep(layout, true);
- sub = uiLayoutColumn(col, true);
- uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_frame_end"));
- uiItemR(sub, &ptr, "frame_end", 0, NULL, ICON_NONE);
+ /* Stepping Settings. */
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "frame_step", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "frame_offset", 0, NULL, ICON_NONE);
+
+ /* Start range settings. */
+ row = uiLayoutRowWithHeading(layout, true, IFACE_("Start Frame"));
+ uiItemR(row, ptr, "use_frame_start", 0, "", ICON_NONE);
+ sub = uiLayoutColumn(row, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_frame_start"));
+ uiItemR(sub, ptr, "frame_start", 0, "", ICON_NONE);
+
+ /* End range settings. */
+ row = uiLayoutRowWithHeading(layout, true, IFACE_("End Frame"));
+ uiItemR(row, ptr, "use_frame_end", 0, "", ICON_NONE);
+ sub = uiLayoutColumn(row, true);
+ uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_frame_end"));
+ uiItemR(sub, ptr, "frame_end", 0, "", ICON_NONE);
+
+ fmodifier_influence_draw(layout, ptr);
}
-/* --------------- */
-
-void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout,
- ID *fcurve_owner_id,
- ListBase *modifiers,
- FModifier *fcm)
+static void panel_register_stepped(ARegionType *region_type,
+ const char *id_prefix,
+ PanelTypePollFn poll_fn)
{
- const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
- uiLayout *box, *row, *sub, *col;
- uiBlock *block;
- uiBut *but;
- short width = 314;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(fcurve_owner_id, &RNA_FModifier, fcm, &ptr);
+ PanelType *panel_type = fmodifier_panel_register(
+ region_type, FMODIFIER_TYPE_STEPPED, stepped_panel_draw, poll_fn, id_prefix);
+ fmodifier_subpanel_register(region_type,
+ "frame_range",
+ "",
+ fmodifier_frame_range_header_draw,
+ fmodifier_frame_range_draw,
+ poll_fn,
+ panel_type);
+}
- /* draw header */
- {
- /* get layout-row + UI-block for this */
- box = uiLayoutBox(layout);
+/** \} */
- row = uiLayoutRow(box, false);
- block = uiLayoutGetBlock(row); /* err... */
+/* -------------------------------------------------------------------- */
+/** \name Panel Creation
+ *
+ * \{ */
- /* left-align -------------------------------------------- */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+/**
+ * Checks if the panels match the active strip / curve, rebubilds them if they don't.
+ */
+void ANIM_fmodifier_panels(const bContext *C,
+ ID *owner_id,
+ ListBase *fmodifiers,
+ uiListPanelIDFromDataFunc panel_id_fn)
+{
+ ARegion *region = CTX_wm_region(C);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ bool panels_match = UI_panel_list_matches_data(region, fmodifiers, panel_id_fn);
- /* expand */
- uiItemR(sub, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ if (!panels_match) {
+ UI_panels_free_instanced(C, region);
+ FModifier *fcm = fmodifiers->first;
+ for (int i = 0; fcm; i++, fcm = fcm->next) {
+ char panel_idname[MAX_NAME];
+ panel_id_fn(fcm, panel_idname);
- /* checkbox for 'active' status (for now) */
- uiItemR(sub, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ PointerRNA *fcm_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata");
+ RNA_pointer_create(owner_id, &RNA_FModifier, fcm, fcm_ptr);
- /* name */
- if (fmi) {
- uiItemL(sub, IFACE_(fmi->name), ICON_NONE);
- }
- else {
- uiItemL(sub, IFACE_("<Unknown Modifier>"), ICON_NONE);
+ UI_panel_add_instanced(C, region, &region->panels, panel_idname, fcm_ptr);
}
-
- /* right-align ------------------------------------------- */
- sub = uiLayoutRow(row, true);
- uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
-
- /* 'mute' button */
- uiItemR(sub, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- /* delete button */
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- B_REDR,
- ICON_X,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- TIP_("Delete F-Curve Modifier"));
- FModifierDeleteContext *ctx = MEM_mallocN(sizeof(FModifierDeleteContext), "fmodifier ctx");
- ctx->fcurve_owner_id = fcurve_owner_id;
- ctx->modifiers = modifiers;
- UI_but_funcN_set(but, delete_fmodifier_cb, ctx, fcm);
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
-
- /* when modifier is expanded, draw settings */
- if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
- /* set up the flexible-box layout which acts as the backdrop for the modifier settings */
- box = uiLayoutBox(layout);
-
- /* draw settings for individual modifiers */
- switch (fcm->type) {
- case FMODIFIER_TYPE_GENERATOR: /* Generator */
- draw_modifier__generator(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
- draw_modifier__fn_generator(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_CYCLES: /* Cycles */
- draw_modifier__cycles(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
- draw_modifier__envelope(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_LIMITS: /* Limits */
- draw_modifier__limits(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_NOISE: /* Noise */
- draw_modifier__noise(box, fcurve_owner_id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_STEPPED: /* Stepped */
- draw_modifier__stepped(box, fcurve_owner_id, fcm, width);
- break;
-
- default: /* unknown type */
- break;
- }
-
- /* one last panel below this: FModifier range */
- /* TODO: experiment with placement of this */
- {
- box = uiLayoutBox(layout);
-
- /* restricted range ----------------------------------------------------- */
- col = uiLayoutColumn(box, true);
-
- /* top row: use restricted range */
- row = uiLayoutRow(col, true);
- uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE);
-
- if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
- /* second row: settings */
- row = uiLayoutRow(col, true);
-
- uiItemR(row, &ptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
- uiItemR(row, &ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
-
- /* third row: blending influence */
- row = uiLayoutRow(col, true);
-
- uiItemR(row, &ptr, "blend_in", 0, IFACE_("In"), ICON_NONE);
- uiItemR(row, &ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE);
+ else {
+ /* Assuming there's only one group of instanced panels, update the custom data pointers. */
+ Panel *panel = region->panels.first;
+ LISTBASE_FOREACH (FModifier *, fcm, fmodifiers) {
+
+ /* Move to the next instanced panel corresponding to the next modifier. */
+ while ((panel->type == NULL) || !(panel->type->flag & PANEL_TYPE_INSTANCED)) {
+ panel = panel->next;
+ BLI_assert(panel != NULL); /* There shouldn't be fewer panels than modifiers with UIs. */
}
- /* influence -------------------------------------------------------------- */
- col = uiLayoutColumn(box, true);
-
- /* top row: use influence */
- uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE);
+ PointerRNA *fcm_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata");
+ RNA_pointer_create(owner_id, &RNA_FModifier, fcm, fcm_ptr);
+ UI_panel_custom_data_set(panel, fcm_ptr);
- if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) {
- /* second row: influence value */
- uiItemR(col, &ptr, "influence", 0, NULL, ICON_NONE);
- }
+ panel = panel->next;
}
}
}
+void ANIM_modifier_panels_register_graph_and_NLA(ARegionType *region_type,
+ const char *modifier_panel_prefix,
+ PanelTypePollFn poll_function)
+{
+ panel_register_generator(region_type, modifier_panel_prefix, poll_function);
+ panel_register_fn_generator(region_type, modifier_panel_prefix, poll_function);
+ panel_register_noise(region_type, modifier_panel_prefix, poll_function);
+ panel_register_envelope(region_type, modifier_panel_prefix, poll_function);
+ panel_register_limits(region_type, modifier_panel_prefix, poll_function);
+ panel_register_stepped(region_type, modifier_panel_prefix, poll_function);
+}
+
+void ANIM_modifier_panels_register_graph_only(ARegionType *region_type,
+ const char *modifier_panel_prefix,
+ PanelTypePollFn poll_function)
+{
+ panel_register_cycles(region_type, modifier_panel_prefix, poll_function);
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Copy / Paste Buffer Code
*
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 9cf67816df2..2415c85e299 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -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 -------------- */
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 51be5afafe5..d88bf8750c2 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -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"));
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index b82fcf3db47..d019573bf93 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -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);
}
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 4e37a6652a5..c9abb4fb5be 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -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. */
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index b4e864eb4e1..989a41b9ad6 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -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");