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:
authorAntonioya <blendergit@gmail.com>2018-08-27 17:29:19 +0300
committerAntonioya <blendergit@gmail.com>2018-08-27 17:31:03 +0300
commit9de320d8829157116878e078eb7801f306d242b6 (patch)
tree157cf7c7016381fb6d3ae568bad5ae255d27f639 /source/blender
parent1e6a5eb0879119808fde8f002eed5ac7909944ec (diff)
GP: New operator to copy layers between objects
The operator allows to copy a complete layer with all frames or only active frame to a new object. Can be found in edit specials menu (W key) or in Layers specials menu (last button near layer list).
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c138
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c1
3 files changed, 140 insertions, 0 deletions
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index d7e58609d2d..954d012fd24 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -418,6 +418,144 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/* ********************* Duplicate Layer in a new object ************************** */
+enum {
+ GP_LAYER_COPY_OBJECT_ALL_FRAME = 0,
+ GP_LAYER_COPY_OBJECT_ACT_FRAME = 1
+};
+
+bool gp_layer_duplicate_object_poll(bContext *C)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL))
+ return false;
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+
+ if (gpl == NULL)
+ return false;
+
+ /* check there are more grease pencil objects */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->object != ob) && (base->object->type == OB_GPENCIL))
+ return true;
+ }
+
+ return false;
+}
+
+static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "object", name);
+
+ if (name[0] == '\0') {
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *ob_dst = (Object *)BKE_scene_object_find_by_name(scene, name);
+
+ int mode = RNA_enum_get(op->ptr, "mode");
+
+ Object *ob_src = CTX_data_active_object(C);
+ bGPdata *gpd_src = (bGPdata *)ob_src->data;
+ bGPDlayer *gpl_src = BKE_gpencil_layer_getactive(gpd_src);
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
+ return OPERATOR_CANCELLED;
+ }
+ /* cannot copy itself and check destination type */
+ if ((ob_src == ob_dst) || (ob_dst->type != OB_GPENCIL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bGPdata *gpd_dst = (bGPdata *)ob_dst->data;
+
+ /* make copy of layer */
+ bGPDlayer *gpl_dst = MEM_dupallocN(gpl_src);
+ gpl_dst->prev = gpl_dst->next = NULL;
+ gpl_dst->runtime.derived_data = NULL;
+ BLI_addtail(&gpd_dst->layers, gpl_dst);
+ BLI_uniquename(&gpd_dst->layers, gpl_dst, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl_dst->info));
+
+ /* copy frames */
+ BLI_listbase_clear(&gpl_dst->frames);
+ for (bGPDframe *gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
+
+ if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
+ continue;
+ }
+
+ /* make a copy of source frame */
+ bGPDframe *gpf_dst = MEM_dupallocN(gpf_src);
+ gpf_dst->prev = gpf_dst->next = NULL;
+ BLI_addtail(&gpl_dst->frames, gpf_dst);
+
+ /* copy strokes */
+ BLI_listbase_clear(&gpf_dst->strokes);
+ for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
+
+ /* make copy of source stroke */
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+
+ /* check if material is in destination object,
+ * otherwise add the slot with the material
+ */
+ Material *ma_src = give_current_material(ob_src, gps_src->mat_nr + 1);
+ int idx = BKE_object_material_slot_find_index(ob_dst, ma_src);
+ if (idx == 0) {
+ BKE_object_material_slot_add(bmain, ob_dst);
+ assign_material(bmain, ob_dst, ma_src, ob_dst->totcol, BKE_MAT_ASSIGN_USERPREF);
+ idx = ob_dst->totcol;
+ }
+
+ /* reasign the stroke material to the right slot in destination object */
+ gps_dst->mat_nr = idx - 1;
+
+ /* add new stroke to frame */
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
+ }
+ }
+
+ /* notifiers */
+ DEG_id_tag_update(&gpd_dst->id, OB_RECALC_OB | OB_RECALC_DATA | DEG_TAG_COPY_ON_WRITE);
+ DEG_id_tag_update(&ob_dst->id, DEG_TAG_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
+{
+ static const EnumPropertyItem copy_mode[] = {
+ {GP_LAYER_COPY_OBJECT_ALL_FRAME, "ALL", 0, "All Frames", ""},
+ {GP_LAYER_COPY_OBJECT_ACT_FRAME, "ACTIVE", 0, "Active Frame", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Duplicate Layer to new Object";
+ ot->idname = "GPENCIL_OT_layer_duplicate_object";
+ ot->description = "Make a copy of the active Grease Pencil layer to new object";
+
+ /* callbacks */
+ ot->exec = gp_layer_duplicate_object_exec;
+ ot->poll = gp_layer_duplicate_object_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_string(ot->srna, "object", NULL, MAX_ID_NAME - 2, "Object", "Name of the destination object");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_COPY_OBJECT_ALL_FRAME, "Mode", "");
+}
+
/* ********************* Duplicate Frame ************************** */
enum {
GP_FRAME_DUP_ACTIVE = 0,
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 9d9fede91af..d2c8435ed70 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -335,6 +335,7 @@ void GPENCIL_OT_layer_add(struct wmOperatorType *ot);
void GPENCIL_OT_layer_remove(struct wmOperatorType *ot);
void GPENCIL_OT_layer_move(struct wmOperatorType *ot);
void GPENCIL_OT_layer_duplicate(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_duplicate_object(struct wmOperatorType *ot);
void GPENCIL_OT_hide(struct wmOperatorType *ot);
void GPENCIL_OT_reveal(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index d39dd085add..ca97a7948e5 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -718,6 +718,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_layer_remove);
WM_operatortype_append(GPENCIL_OT_layer_move);
WM_operatortype_append(GPENCIL_OT_layer_duplicate);
+ WM_operatortype_append(GPENCIL_OT_layer_duplicate_object);
WM_operatortype_append(GPENCIL_OT_hide);
WM_operatortype_append(GPENCIL_OT_reveal);