diff options
author | Joshua Leung <aligorith@gmail.com> | 2015-12-10 09:11:19 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2015-12-10 09:11:19 +0300 |
commit | 5368505ef32b39c1c12e1090bf69f25de78f959f (patch) | |
tree | 9a9906b3fa790b83395b996c87c9b761d3f9e342 | |
parent | dda03a24b901321bf4b1fac241134578ac058928 (diff) |
GPencil Layer Management: Lock/Unlock All + Isolate Layer
This commit introduces a few operators to make it easier to perform a few common
layer-manipulation operations. Some of these have been sorely needed for quite
a while now...
* Lock/Unlock All - Just as their names suggest, these operators will lock and unlock
all layers in the GP datablock. This is a quick way to unlock all layers previously
locked. These can be found in the new dropdown which replaces the old "Duplicate"
below the +/- (for adding/removing layers); also featured in the dropdown are
the "Duplicate Layers" operator, as well as the show/hide ones.
* Isolate Layer - This operator makes it easy to focus on just a single layer (e.g. the
outlines for a particular character). The "star" button affects editability, while the
"eye" below it toggles editability + visibility.
If any layer is visible/unlocked, this operator will lock and/or hide all; otherwise,
it will unlock/unhide all (to reverse the previous operation).
-rw-r--r-- | release/scripts/startup/bl_ui/properties_grease_pencil_common.py | 27 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_data.c | 150 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_intern.h | 5 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_ops.c | 3 |
4 files changed, 184 insertions, 1 deletions
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index ab574abddef..f7d80ea1d3c 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -451,6 +451,25 @@ class GPENCIL_UL_layer(UIList): layout.label(text="", icon_value=icon) +class GPENCIL_MT_layer_specials(Menu): + bl_label = "Layer" + + def draw(self, context): + layout = self.layout + + layout.operator("gpencil.layer_duplicate", icon='COPY_ID') # XXX: needs a dedicated icon + + layout.separator() + + layout.operator("gpencil.reveal", icon='RESTRICT_VIEW_OFF', text="Show All") + layout.operator("gpencil.hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True + + layout.separator() + + layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All") + layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="UnLock All") + + class GreasePencilDataPanel: # subclass must set # bl_space_type = 'IMAGE_EDITOR' @@ -502,7 +521,7 @@ class GreasePencilDataPanel: gpl = context.active_gpencil_layer if gpl: - sub.operator("gpencil.layer_duplicate", icon='COPY_ID', text="") # XXX: needs a dedicated icon + sub.menu("GPENCIL_MT_layer_specials", icon='DOWNARROW_HLT', text="") if len(gpd.layers) > 1: col.separator() @@ -511,6 +530,12 @@ class GreasePencilDataPanel: sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP' sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN' + col.separator() + + sub = col.column(align=True) + sub.operator("gpencil.layer_isolate", icon='SOLO_OFF', text="").affect_visibility = False + sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True + if gpl: self.draw_layer(layout, gpl) diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 10dfe9aa106..4f03a53e736 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -446,6 +446,156 @@ void GPENCIL_OT_reveal(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* ***************** Lock/Unlock All Layers ************************ */ + +static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op)) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl; + + /* sanity checks */ + if (gpd == NULL) + return OPERATOR_CANCELLED; + + /* make all layers non-editable */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + gpl->flag |= GP_LAYER_LOCKED; + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_lock_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Lock All Layers"; + ot->idname = "GPENCIL_OT_lock_all"; + ot->description = "Lock all Grease Pencil layers to prevent them from being accidentally modified"; + + /* callbacks */ + ot->exec = gp_lock_all_exec; + ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */ + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------- */ + +static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op)) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl; + + /* sanity checks */ + if (gpd == NULL) + return OPERATOR_CANCELLED; + + /* make all layers editable again */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + gpl->flag &= ~GP_LAYER_LOCKED; + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_unlock_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Unlock All Layers"; + ot->idname = "GPENCIL_OT_unlock_all"; + ot->description = "unlock all Grease Pencil layers so that they can be edited"; + + /* callbacks */ + ot->exec = gp_unlock_all_exec; + ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */ + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ********************** Isolate Layer **************************** */ + +static int gp_isolate_layer_exec(bContext *C, wmOperator *op) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *layer = gpencil_layer_getactive(gpd); + bGPDlayer *gpl; + int flags = GP_LAYER_LOCKED; + bool isolate = false; + + if (RNA_boolean_get(op->ptr, "affect_visibility")) + flags |= GP_LAYER_HIDE; + + if (ELEM(NULL, gpd, layer)) { + BKE_report(op->reports, RPT_ERROR, "No active layer to isolate"); + return OPERATOR_CANCELLED; + } + + /* Test whether to isolate or clear all flags */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + /* Skip if this is the active layer */ + if (gpl == layer) + continue; + + /* If the flags aren't set, that means that the layer is + * not alone, so we have some layers to isolate still + */ + if ((gpl->flag & flags) == 0) { + isolate = true; + break; + } + } + + /* Set/Clear flags as appropriate */ + /* TODO: Include onionskinning on this list? */ + if (isolate) { + /* Set flags on all "other" layers */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl == layer) + continue; + else + gpl->flag |= flags; + } + } + else { + /* Clear flags - Restore everything else */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + gpl->flag &= ~flags; + } + } + + /* notifiers */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_layer_isolate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Isolate Layer"; + ot->idname = "GPENCIL_OT_layer_isolate"; + ot->description = "Toggle whether the active layer is the only one that can be edited and/or visible"; + + /* callbacks */ + ot->exec = gp_isolate_layer_exec; + ot->poll = gp_active_layer_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "affect_visibility", false, "Affect Visibility", + "In addition to toggling the editability, also affect the visibility"); +} + /* ********************** Change Layer ***************************** */ static int gp_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt)) diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 340b1cabe3c..4032e43a811 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -188,6 +188,11 @@ void GPENCIL_OT_layer_duplicate(struct wmOperatorType *ot); void GPENCIL_OT_hide(struct wmOperatorType *ot); void GPENCIL_OT_reveal(struct wmOperatorType *ot); +void GPENCIL_OT_lock_all(struct wmOperatorType *ot); +void GPENCIL_OT_unlock_all(struct wmOperatorType *ot); + +void GPENCIL_OT_layer_isolate(struct wmOperatorType *ot); + void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot); void GPENCIL_OT_convert(struct wmOperatorType *ot); diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 3ed6b35d12e..05e95df5da5 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -330,6 +330,9 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_hide); WM_operatortype_append(GPENCIL_OT_reveal); + WM_operatortype_append(GPENCIL_OT_lock_all); + WM_operatortype_append(GPENCIL_OT_unlock_all); + WM_operatortype_append(GPENCIL_OT_layer_isolate); WM_operatortype_append(GPENCIL_OT_active_frame_delete); |