GPencil: New operator to Normalize strokes
Sometimes is required to reset the thickness or the opacity of the strokes. Actually this was done using a modifier, but this operators solves this. Reviewed By: mendio, filedescriptor Maniphest Tasks: T87427 Differential Revision: https://developer.blender.org/D11453
This commit is contained in:
parent
21de669141
commit
f944121700
Notes:
blender-bot
2023-02-14 10:29:30 +01:00
Referenced by issue #87427, GPencil: New operator to normalize thickness and opacity
|
@ -5035,6 +5035,10 @@ class VIEW3D_MT_edit_gpencil_stroke(Menu):
|
|||
layout.operator("gpencil.stroke_flip", text="Switch Direction")
|
||||
layout.prop(settings, "use_scale_thickness", text="Scale Thickness")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("gpencil.stroke_normalize", text="Normalize Thickness").mode = 'THICKNESS'
|
||||
layout.operator("gpencil.stroke_normalize", text="Normalize Opacity").mode = 'OPACITY'
|
||||
|
||||
layout.separator()
|
||||
layout.operator("gpencil.reset_transform_fill", text="Reset Fill Transform")
|
||||
|
||||
|
|
|
@ -5347,3 +5347,181 @@ void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot)
|
|||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Stroke Normalize Operator
|
||||
* \{ */
|
||||
|
||||
typedef enum eGP_NormalizeMode {
|
||||
GP_NORMALIZE_THICKNESS = 0,
|
||||
GP_NORMALIZE_OPACITY,
|
||||
} eGP_NormalizeMode;
|
||||
|
||||
static bool gpencil_stroke_normalize_poll(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
|
||||
return false;
|
||||
}
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
if (gpd == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
|
||||
|
||||
return ((gpl != NULL) && (ob->mode == OB_MODE_EDIT_GPENCIL));
|
||||
}
|
||||
|
||||
static void gpencil_stroke_normalize_ui(bContext *C, wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
uiLayout *row;
|
||||
|
||||
const eGP_NormalizeMode mode = RNA_enum_get(op->ptr, "mode");
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
row = uiLayoutRow(layout, true);
|
||||
uiItemR(row, op->ptr, "mode", 0, NULL, ICON_NONE);
|
||||
|
||||
if (mode == GP_NORMALIZE_THICKNESS) {
|
||||
row = uiLayoutRow(layout, true);
|
||||
uiItemR(row, op->ptr, "value", 0, NULL, ICON_NONE);
|
||||
}
|
||||
else if (mode == GP_NORMALIZE_OPACITY) {
|
||||
row = uiLayoutRow(layout, true);
|
||||
uiItemR(row, op->ptr, "factor", 0, NULL, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static int gpencil_stroke_normalize_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
||||
|
||||
/* Sanity checks. */
|
||||
if (ELEM(NULL, gpd)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const eGP_NormalizeMode mode = RNA_enum_get(op->ptr, "mode");
|
||||
const int value = RNA_int_get(op->ptr, "value");
|
||||
const float factor = RNA_float_get(op->ptr, "factor");
|
||||
|
||||
/* Go through each editable + selected stroke. */
|
||||
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
||||
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
||||
|
||||
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
||||
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
||||
|
||||
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
||||
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
||||
|
||||
if (gpf == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
|
||||
/* Skip strokes that are invalid for current view. */
|
||||
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool selected = (is_curve_edit) ? gps->editcurve->flag |= GP_CURVE_SELECT :
|
||||
(gps->flag & GP_STROKE_SELECT);
|
||||
if (!selected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float stroke_thickness_inv = 1.0f / max_ii(gps->thickness, 1);
|
||||
/* Fill opacity need to be managed before. */
|
||||
if (mode == GP_NORMALIZE_OPACITY) {
|
||||
gps->fill_opacity_fac = factor;
|
||||
CLAMP(gps->fill_opacity_fac, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/* Loop all Polyline points. */
|
||||
if (!is_curve_edit) {
|
||||
for (int i = 0; i < gps->totpoints; i++) {
|
||||
bGPDspoint *pt = &gps->points[i];
|
||||
if (mode == GP_NORMALIZE_THICKNESS) {
|
||||
pt->pressure = max_ff((float)value * stroke_thickness_inv, 0.0f);
|
||||
}
|
||||
else if (mode == GP_NORMALIZE_OPACITY) {
|
||||
pt->strength = factor;
|
||||
CLAMP(pt->strength, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Loop all Bezier points. */
|
||||
for (int i = 0; i < gps->editcurve->tot_curve_points; i++) {
|
||||
bGPDcurve_point *gpc_pt = &gps->editcurve->curve_points[i];
|
||||
if (mode == GP_NORMALIZE_THICKNESS) {
|
||||
gpc_pt->pressure = max_ff((float)value * stroke_thickness_inv, 0.0f);
|
||||
}
|
||||
else if (mode == GP_NORMALIZE_OPACITY) {
|
||||
gpc_pt->strength = factor;
|
||||
CLAMP(gpc_pt->strength, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
|
||||
BKE_gpencil_stroke_geometry_update(gpd, gps);
|
||||
}
|
||||
}
|
||||
/* If not multiedit, exit loop. */
|
||||
if (!is_multiedit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
/* notifiers */
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GPENCIL_OT_stroke_normalize(wmOperatorType *ot)
|
||||
{
|
||||
static const EnumPropertyItem prop_gpencil_normalize_modes[] = {
|
||||
{GP_NORMALIZE_THICKNESS,
|
||||
"THICKNESS",
|
||||
0,
|
||||
"Thickness",
|
||||
"Normalizes the stroke thickness by making all points use the same thickness value"},
|
||||
{GP_NORMALIZE_OPACITY,
|
||||
"OPACITY",
|
||||
0,
|
||||
"Opacity",
|
||||
"Normalizes the stroke opacity by making all points use the same opacity value"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Normalize Stroke";
|
||||
ot->idname = "GPENCIL_OT_stroke_normalize";
|
||||
ot->description = "Normalize stroke attributes";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = gpencil_stroke_normalize_exec;
|
||||
ot->poll = gpencil_stroke_normalize_poll;
|
||||
ot->ui = gpencil_stroke_normalize_ui;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* props */
|
||||
ot->prop = RNA_def_enum(
|
||||
ot->srna, "mode", prop_gpencil_normalize_modes, 0, "Mode", "Attribute to be normalized");
|
||||
RNA_def_float(ot->srna, "factor", 1.0f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f);
|
||||
RNA_def_int(ot->srna, "value", 10, 0, 1000, "Value", "Value", 0, 1000);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -488,6 +488,7 @@ void GPENCIL_OT_stroke_trim(struct wmOperatorType *ot);
|
|||
void GPENCIL_OT_stroke_merge_by_distance(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_stroke_merge_material(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_stroke_reset_vertex_color(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_stroke_normalize(struct wmOperatorType *ot);
|
||||
|
||||
void GPENCIL_OT_material_to_vertex_color(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_extract_palette_vertex(struct wmOperatorType *ot);
|
||||
|
|
|
@ -649,6 +649,7 @@ void ED_operatortypes_gpencil(void)
|
|||
WM_operatortype_append(GPENCIL_OT_stroke_merge_by_distance);
|
||||
WM_operatortype_append(GPENCIL_OT_stroke_merge_material);
|
||||
WM_operatortype_append(GPENCIL_OT_stroke_reset_vertex_color);
|
||||
WM_operatortype_append(GPENCIL_OT_stroke_normalize);
|
||||
|
||||
WM_operatortype_append(GPENCIL_OT_material_to_vertex_color);
|
||||
WM_operatortype_append(GPENCIL_OT_extract_palette_vertex);
|
||||
|
|
Loading…
Reference in New Issue