[Bf-blender-cvs] [1f5647c07d1] master: UI: FModifier layout updates, drag and drop

Hans Goudey noreply at git.blender.org
Fri Feb 19 17:11:43 CET 2021


Commit: 1f5647c07d15d2b298b491ebe260a411f7b0d1b8
Author: Hans Goudey
Date:   Fri Feb 19 10:11:35 2021 -0600
Branches: master
https://developer.blender.org/rB1f5647c07d15d2b298b491ebe260a411f7b0d1b8

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

===================================================================

M	source/blender/blenkernel/intern/fmodifier.c
M	source/blender/blenloader/intern/versioning_290.c
M	source/blender/editors/animation/fmodifier_ui.c
M	source/blender/editors/include/ED_anim_api.h
M	source/blender/editors/space_graph/graph_buttons.c
M	source/blender/editors/space_nla/nla_buttons.c
M	source/blender/makesdna/DNA_anim_types.h
M	source/blender/makesrna/intern/rna_fcurve.c

===================================================================

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;
+}
+
+/** \} */
+
+/* --------------------------------------

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list