GPv3: Move to Layer
This PR adds the Move to Layer operator from GPv2. Pull Request: https://projects.blender.org/blender/blender/pulls/117244
This commit is contained in:
committed by
Falk David
parent
6f0e27abad
commit
dcc5725741
@@ -4642,6 +4642,9 @@ def km_grease_pencil_edit_mode(params):
|
||||
# Active layer
|
||||
op_menu("GREASE_PENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
|
||||
# Move to layer
|
||||
op_menu("GREASE_PENCIL_MT_move_to_layer", {"type": 'M', "value": 'PRESS'}),
|
||||
|
||||
# Context menu
|
||||
*_template_items_context_menu("VIEW3D_MT_greasepencil_edit_context_menu", params.context_menu_event),
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ class DATA_PT_grease_pencil_layers(DataButtonsPanel, Panel):
|
||||
|
||||
col = row.column()
|
||||
sub = col.column(align=True)
|
||||
sub.operator_context = 'EXEC_DEFAULT'
|
||||
sub.operator("grease_pencil.layer_add", icon='ADD', text="")
|
||||
sub.menu("GREASE_PENCIL_MT_grease_pencil_add_layer_extra", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
|
||||
@@ -274,6 +274,30 @@ class GPENCIL_MT_layer_active(Menu):
|
||||
i -= 1
|
||||
|
||||
|
||||
class GREASE_PENCIL_MT_move_to_layer(Menu):
|
||||
bl_label = "Move to Layer"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
grease_pencil = context.active_object.data
|
||||
|
||||
layout.operator("grease_pencil.move_to_layer", text="New Layer", icon='ADD').add_new_layer = True
|
||||
|
||||
if not grease_pencil.layers:
|
||||
return
|
||||
|
||||
layout.separator()
|
||||
|
||||
for i in range(len(grease_pencil.layers) - 1, -1, -1):
|
||||
layer = grease_pencil.layers[i]
|
||||
if layer == grease_pencil.layers.active:
|
||||
icon = 'GREASEPENCIL'
|
||||
else:
|
||||
icon = 'NONE'
|
||||
layout.operator("grease_pencil.move_to_layer", text=layer.name, icon=icon).target_layer_name = layer.name
|
||||
|
||||
|
||||
class GREASE_PENCIL_MT_layer_active(Menu):
|
||||
bl_label = "Change Active Layer"
|
||||
|
||||
@@ -942,6 +966,7 @@ classes = (
|
||||
GPENCIL_UL_layer,
|
||||
GPENCIL_UL_masks,
|
||||
|
||||
GREASE_PENCIL_MT_move_to_layer,
|
||||
GREASE_PENCIL_MT_layer_active,
|
||||
|
||||
GreasePencilFlipTintColors,
|
||||
|
||||
@@ -5855,6 +5855,7 @@ class VIEW3D_MT_edit_greasepencil_stroke(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("GREASE_PENCIL_MT_move_to_layer")
|
||||
layout.menu("VIEW3D_MT_grease_pencil_assign_material")
|
||||
layout.operator("grease_pencil.set_active_material")
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_stack.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
@@ -34,13 +35,13 @@
|
||||
|
||||
#include "ED_curves.hh"
|
||||
#include "ED_grease_pencil.hh"
|
||||
#include "ED_screen.hh"
|
||||
|
||||
#include "GEO_join_geometries.hh"
|
||||
#include "GEO_reorder.hh"
|
||||
#include "GEO_smooth_curves.hh"
|
||||
#include "GEO_subdivide_curves.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "UI_resources.hh"
|
||||
|
||||
namespace blender::ed::greasepencil {
|
||||
@@ -1693,6 +1694,122 @@ static void GREASE_PENCIL_OT_stroke_reorder(wmOperatorType *ot)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Move To Layer Operator
|
||||
* \{ */
|
||||
|
||||
static int grease_pencil_move_to_layer_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
using namespace bke::greasepencil;
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
bool changed = false;
|
||||
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
|
||||
int target_layer_name_length;
|
||||
char *target_layer_name = nullptr;
|
||||
BLI_SCOPED_DEFER([&] { MEM_SAFE_FREE(target_layer_name); });
|
||||
const bool add_new_layer = RNA_boolean_get(op->ptr, "add_new_layer");
|
||||
if (add_new_layer) {
|
||||
Layer &new_layer = grease_pencil.add_layer("Layer");
|
||||
target_layer_name = BLI_strdup_null(new_layer.name().c_str());
|
||||
}
|
||||
else {
|
||||
target_layer_name = RNA_string_get_alloc(
|
||||
op->ptr, "target_layer_name", nullptr, 0, &target_layer_name_length);
|
||||
}
|
||||
|
||||
TreeNode *target_node = grease_pencil.find_node_by_name(target_layer_name);
|
||||
if (target_node == nullptr) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "There is no layer '%s'", target_layer_name);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
Layer *layer_dst = &target_node->as_layer();
|
||||
if (layer_dst->is_locked()) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "'%s' Layer is locked", target_layer_name);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Iterate through all the drawings at current scene frame. */
|
||||
const Array<MutableDrawingInfo> drawings_src = retrieve_editable_drawings(*scene, grease_pencil);
|
||||
for (const MutableDrawingInfo &info : drawings_src) {
|
||||
bke::CurvesGeometry &curves_src = info.drawing.strokes_for_write();
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask selected_strokes = ed::curves::retrieve_selected_curves(curves_src, memory);
|
||||
if (selected_strokes.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!layer_dst->has_drawing_at(info.frame_number)) {
|
||||
/* Move geometry to a new drawing in target layer. */
|
||||
grease_pencil.insert_blank_frame(*layer_dst, info.frame_number, 0, BEZT_KEYTYPE_KEYFRAME);
|
||||
Drawing &drawing_dst = *grease_pencil.get_editable_drawing_at(*layer_dst, info.frame_number);
|
||||
drawing_dst.strokes_for_write() = bke::curves_copy_curve_selection(
|
||||
curves_src, selected_strokes, {});
|
||||
|
||||
curves_src.remove_curves(selected_strokes, {});
|
||||
|
||||
drawing_dst.tag_topology_changed();
|
||||
}
|
||||
else {
|
||||
/* Append geometry to drawing in target layer. */
|
||||
Drawing &drawing_dst = *grease_pencil.get_editable_drawing_at(*layer_dst, info.frame_number);
|
||||
bke::CurvesGeometry selected_elems = curves_copy_curve_selection(
|
||||
curves_src, selected_strokes, {});
|
||||
Curves *selected_curves = bke::curves_new_nomain(std::move(selected_elems));
|
||||
Curves *layer_curves = bke::curves_new_nomain(std::move(drawing_dst.strokes_for_write()));
|
||||
std::array<GeometrySet, 2> geometry_sets{GeometrySet::from_curves(selected_curves),
|
||||
GeometrySet::from_curves(layer_curves)};
|
||||
GeometrySet joined = geometry::join_geometries(geometry_sets, {});
|
||||
drawing_dst.strokes_for_write() = std::move(joined.get_curves_for_write()->geometry.wrap());
|
||||
|
||||
curves_src.remove_curves(selected_strokes, {});
|
||||
|
||||
drawing_dst.tag_topology_changed();
|
||||
}
|
||||
|
||||
info.drawing.tag_topology_changed();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
/* updates */
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, nullptr);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_move_to_layer(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers. */
|
||||
ot->name = "Move to Layer";
|
||||
ot->idname = "GREASE_PENCIL_OT_move_to_layer";
|
||||
ot->description = "Move selected strokes to another layer";
|
||||
|
||||
/* callbacks. */
|
||||
ot->exec = grease_pencil_move_to_layer_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
|
||||
/* flags. */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
prop = RNA_def_string(
|
||||
ot->srna, "target_layer_name", "Layer", INT16_MAX, "Name", "Target Grease Pencil Layer");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
prop = RNA_def_boolean(
|
||||
ot->srna, "add_new_layer", false, "New Layer", "Move selection to a new layer");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::ed::greasepencil
|
||||
|
||||
void ED_operatortypes_grease_pencil_edit()
|
||||
@@ -1715,4 +1832,5 @@ void ED_operatortypes_grease_pencil_edit()
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_clean_loose);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_stroke_subdivide);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_stroke_reorder);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_move_to_layer);
|
||||
}
|
||||
|
||||
@@ -76,13 +76,14 @@ static void GREASE_PENCIL_OT_layer_add(wmOperatorType *ot)
|
||||
ot->description = "Add a new Grease Pencil layer in the active object";
|
||||
|
||||
/* callbacks */
|
||||
ot->invoke = WM_operator_props_popup_confirm;
|
||||
ot->exec = grease_pencil_layer_add_exec;
|
||||
ot->poll = active_grease_pencil_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
PropertyRNA *prop = RNA_def_string(
|
||||
ot->srna, "new_layer_name", nullptr, INT16_MAX, "Name", "Name of the new layer");
|
||||
ot->srna, "new_layer_name", "Layer", INT16_MAX, "Name", "Name of the new layer");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
ot->prop = prop;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "ED_keyframes_edit.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
struct bContext;
|
||||
struct Main;
|
||||
struct Object;
|
||||
|
||||
Reference in New Issue
Block a user