Commit: affd1eacb58d715dd4d09e0dd8b378de2d8173d9
Author: Joshua Leung
Date:   Sun Oct 18 03:29:23 2015 +1300
Branches: GPencil_Editing_Stage3
https://developer.blender.org/rBaffd1eacb58d715dd4d09e0dd8b378de2d8173d9

GP Editing: "Move to Layer" operator (MKEY)

This commit adds an operator which can be used to move the selected strokes
to another layer (including to a new layer).

Currently this can only move entire strokes. Later we can check on doing
partial strokes too (just like copy/paste can handle now).

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

M       release/scripts/startup/bl_ui/space_view3d.py
M       source/blender/editors/gpencil/gpencil_edit.c
M       source/blender/editors/gpencil/gpencil_intern.h
M       source/blender/editors/gpencil/gpencil_ops.c
M       source/blender/editors/gpencil/gpencil_utils.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d.py 
b/release/scripts/startup/bl_ui/space_view3d.py
index d8e5fb9..1ed7cac 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2896,6 +2896,7 @@ class VIEW3D_MT_edit_gpencil(Menu):
 
         layout.separator()
 
+        layout.operator("gpencil.move_to_layer", text="Move to Layer")
         layout.operator("gpencil.convert", text="Convert to Geometry...")
 
 
diff --git a/source/blender/editors/gpencil/gpencil_edit.c 
b/source/blender/editors/gpencil/gpencil_edit.c
index 32c6cb2..4f8031a 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -59,12 +59,14 @@
 #include "BKE_screen.h"
 
 #include "UI_interface.h"
+#include "UI_resources.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
+#include "RNA_enum_types.h"
 
 #include "UI_view2d.h"
 
@@ -511,6 +513,111 @@ void GPENCIL_OT_paste(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/* ******************* Move To Layer ****************************** */
+
+static int gp_move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent 
*UNUSED(evt))
+{
+       uiPopupMenu *pup;
+       uiLayout *layout;
+       
+       /* call the menu, which will call this operator again, hence the 
canceled */
+       pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+       layout = UI_popup_menu_layout(pup);
+       uiItemsEnumO(layout, "GPENCIL_OT_move_to_layer", "layer");
+       UI_popup_menu_end(C, pup);
+       
+       return OPERATOR_INTERFACE;
+}
+
+// FIXME: allow moving partial strokes
+static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
+{
+       bGPdata *gpd = CTX_data_gpencil_data(C);
+       bGPDlayer *target_layer = NULL;
+       ListBase strokes = {NULL, NULL};
+       int layer_num = RNA_enum_get(op->ptr, "layer");
+       
+       /* Get layer or create new one */
+       if (layer_num == -1) {
+               /* Create layer */
+               target_layer = gpencil_layer_addnew(gpd, DATA_("GP_Layer"), 
true);
+       }
+       else {
+               /* Try to get layer */
+               target_layer = BLI_findlink(&gpd->layers, layer_num);
+               
+               if (target_layer == NULL) {
+                       BKE_reportf(op->reports, RPT_ERROR, "There is no layer 
number %d", layer_num);
+                       return OPERATOR_CANCELLED;
+               }
+       }
+       
+       /* Extract all strokes to move to this layer
+        * NOTE: We need to do this in a two-pass system to avoid conflicts 
with strokes
+        *       getting repeatedly moved
+        */
+       CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+       {
+               bGPDframe *gpf = gpl->actframe;
+               bGPDstroke *gps, *gpsn;
+               
+               /* skip if no frame with strokes, or if this is the layer we're 
moving strokes to */
+               if ((gpl == target_layer) || (gpf == NULL))
+                       continue;
+               
+               /* make copies of selected strokes, and deselect these once 
we're done */
+               for (gps = gpf->strokes.first; gps; gps = gpsn) {
+                       gpsn = gps->next;
+                       
+                       /* skip strokes that are invalid for current view */
+                       if (ED_gpencil_stroke_can_use(C, gps) == false)
+                               continue;
+                       
+                       /* TODO: Don't just move entire strokes - instead, only 
copy the selected portions... */
+                       if (gps->flag & GP_STROKE_SELECT) {
+                               BLI_remlink(&gpf->strokes, gps);
+                               BLI_addtail(&strokes, gps);
+                       }
+               }
+       }
+       CTX_DATA_END;
+       
+       /* Paste them all in one go */
+       if (strokes.first) {
+               Scene *scene = CTX_data_scene(C);
+               bGPDframe *gpf = gpencil_layer_getframe(target_layer, CFRA, 
true);
+               
+               BLI_movelisttolist(&gpf->strokes, &strokes);
+               BLI_assert((strokes.first == strokes.last) && (atrokes.first == 
NULL));
+       }
+       
+       /* updates */
+       WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Move Strokes to Layer";
+       ot->idname = "GPENCIL_OT_move_to_layer";
+       ot->description = "Move selected strokes to another layer"; // XXX: 
allow moving individual points too?
+       
+       /* callbacks */
+       ot->invoke = gp_move_to_layer_invoke;
+       ot->exec = gp_move_to_layer_exec;
+       ot->poll = gp_stroke_edit_poll; // XXX?
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       
+       /* gp layer to use (dynamic enum) */
+       ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, 
"Grease Pencil Layer", "");
+       RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
+
+}
+
 /* ******************* Delete Active Frame ************************ */
 
 static int gp_actframe_delete_poll(bContext *C)
diff --git a/source/blender/editors/gpencil/gpencil_intern.h 
b/source/blender/editors/gpencil/gpencil_intern.h
index fdebea3..2480d92 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -44,6 +44,10 @@ struct ARegion;
 struct View2D;
 struct wmOperatorType;
 
+struct PointerRNA;
+struct PropertyRNA;
+struct EnumPropertyItem;
+
 
 /* ***************************************************** */
 /* Internal API */
@@ -118,6 +122,11 @@ int gp_active_layer_poll(struct bContext *C);
 
 extern ListBase gp_strokes_copypastebuf;
 
+/* Layers Enums -------------------------------------- */
+
+struct EnumPropertyItem *ED_gpencil_layers_enum_itemf(struct bContext *C, 
struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
+struct EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(struct bContext 
*C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
+
 /* ***************************************************** */
 /* Operator Defines */
 
@@ -153,6 +162,9 @@ void GPENCIL_OT_dissolve(struct wmOperatorType *ot);
 void GPENCIL_OT_copy(struct wmOperatorType *ot);
 void GPENCIL_OT_paste(struct wmOperatorType *ot);
 
+void GPENCIL_OT_move_to_layer(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_change(struct wmOperatorType *ot);
+
 /* stroke sculpting -- */
 
 void GPENCIL_OT_brush_paint(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c 
b/source/blender/editors/gpencil/gpencil_ops.c
index e925523..df02626 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -212,6 +212,8 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
        kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, 
KM_SHIFT, 0);
        RNA_boolean_set(kmi->ptr, "unselected", true);
        
+       /* Move to Layer */
+       WM_keymap_add_item(keymap, "GPENCIL_OT_move_to_layer", MKEY, KM_PRESS, 
0, 0);
        
        /* Brush-Based Editing:
         *   EKEY + LMB                          = Single stroke, draw 
immediately 
@@ -311,6 +313,8 @@ void ED_operatortypes_gpencil(void)
        WM_operatortype_append(GPENCIL_OT_copy);
        WM_operatortype_append(GPENCIL_OT_paste);
        
+       WM_operatortype_append(GPENCIL_OT_move_to_layer);
+       
        WM_operatortype_append(GPENCIL_OT_brush_paint);
        
        /* Editing (Buttons) ------------ */
diff --git a/source/blender/editors/gpencil/gpencil_utils.c 
b/source/blender/editors/gpencil/gpencil_utils.c
index 32c4a6d..2e27f3f 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -51,7 +51,9 @@
 
 #include "RNA_access.h"
 #include "RNA_define.h"
+#include "RNA_enum_types.h"
 
+#include "UI_resources.h"
 #include "UI_view2d.h"
 
 #include "ED_gpencil.h"
@@ -231,6 +233,92 @@ int gp_active_layer_poll(bContext *C)
 }
 
 /* ******************************************************** */
+/* Dynamic Enums of GP Layers */
+/* NOTE: These include an option to create a new layer and use that... */
+
+/* Just existing layers */
+EnumPropertyItem *ED_gpencil_layers_enum_itemf(bContext *C, PointerRNA 
*UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+       bGPdata *gpd = CTX_data_gpencil_data(C);
+       bGPDlayer *gpl;
+       EnumPropertyItem *item = NULL, item_tmp = {0};
+       int totitem = 0;
+       int i = 0;
+       
+       if (ELEM(NULL, C, gpd)) {
+               return DummyRNA_DEFAULT_items;
+       }
+       
+       /* Existing layers */
+       for (gpl = gpd->layers.first; gpl; gpl = gpl->next, i++) {
+               item_tmp.identifier = gpl->info;
+               item_tmp.name = gpl->info;
+               item_tmp.value = i;
+               
+               if (gpl->flag & GP_LAYER_ACTIVE)
+                       item_tmp.icon = ICON_RESTRICT_VIEW_OFF;
+               else 
+                       item_tmp.icon = ICON_NONE;
+               
+               RNA_enum_item_add(&item, &totitem, &item_tmp);
+       }
+       
+       RNA_enum_item_end(&item, &totitem);
+       *r_free = true;
+
+       return item;
+}
+
+/* Existing + Option to add/use new layer */
+EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, 
PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+       bGPdata *gpd = CTX_data_gpencil_data(C);
+       bGPDlayer *gpl;
+       EnumPropertyItem *item = NULL, item_tmp = {0};
+       int totitem = 0;
+       int i = 0;
+       
+       if (ELEM(NULL, C, gpd)) {
+               return DummyRNA_DEFAULT_items;
+       }
+       
+       /* Create new layer */
+       /* TODO: have some way of specifying that we don't want this? */
+       {
+               /* active Keying Set */
+               item_tmp.identifier = "__CREATE__";
+               item_tmp.name = "New Layer";
+               item_tmp.value = -1;
+               item_tmp.icon = ICON_ZOOMIN;
+               RNA_enum_item_add(&item, &totitem, &item_tmp);
+               
+               /* separator */
+               RNA_enum_item_add_separator(&item, &totitem);
+       }
+       
+       /* Existing layers */
+       for (gpl = gpd->layers.first, i = 0; gpl; gpl = gpl->next, i++) {
+               item_tmp.identifier = gpl->info;
+               item_tmp.name = gpl->info;
+               item_tmp.value = i;
+               
+               if (gpl->flag & GP_LAYER_ACTIVE)
+                       item_tmp.icon = ICON_RESTRICT_VIEW_OFF;
+               else 
+                       item_tmp.icon = ICON_NONE;
+               
+               RNA_enum_item_add(&item, &totitem, &item_tmp);
+       }
+       
+       RNA_enum_item_end(&item, &totitem);
+       *r_free = true;
+
+       return item;
+}
+
+
+
+/* ******************************************************** */
 /* Brush Tool Core */
 
 /* Check if part of stroke occurs within last segment drawn by eraser */

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to