GPencil: New modifier to generate weights dynamically

his new modifier allows to generate weights base on:

* Angle of the stroke relative to object or world orientation. For example, if the value is 90, the maximum weights will be for vertical lines and minimum for horizontal lines.

* Distance to Target object. The distance calculated is normalized to get valid weights between 0 and 1.0.

The weights are created in an existing vertex group and the data can be replaced or mixed with the existing value to combine different weight effects. The minimum parameter, allows to define the minimum weight generated. This is useful to avoid very low weights.

The generated weights can be used in any modifier. For example, the angle weight value can be used to mimic FreeStyle Caligraphy modifier using the weight with the thickness modifier.

Also some modifier has been changed to inlude a new option to use the weights as factor of the effect.
As result of this change, the fading option has been removed from Thickness and Opacity modifiers because this can be done using the new modifier, it's not logic to repeat the same.

Reviewed By: mendio, filedescriptor

Differential Revision: https://developer.blender.org/D11604
This commit is contained in:
Antonio Vazquez 2021-07-02 12:04:07 +02:00
parent 9f5c0ffb5e
commit 29b65f5345
14 changed files with 710 additions and 244 deletions

View File

@ -2356,6 +2356,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case eGpencilModifierType_Texture:
data.icon = ICON_TEXTURE;
break;
case eGpencilModifierType_Weight:
data.icon = ICON_MOD_VERTEX_WEIGHT;
break;
/* Default */
default:

View File

@ -68,6 +68,7 @@ set(SRC
intern/MOD_gpencilthick.c
intern/MOD_gpenciltime.c
intern/MOD_gpenciltint.c
intern/MOD_gpencilweight.c
MOD_gpencil_lineart.h
MOD_gpencil_modifiertypes.h

View File

@ -44,6 +44,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Armature;
extern GpencilModifierTypeInfo modifierType_Gpencil_Time;
extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply;
extern GpencilModifierTypeInfo modifierType_Gpencil_Texture;
extern GpencilModifierTypeInfo modifierType_Gpencil_Weight;
extern GpencilModifierTypeInfo modifierType_Gpencil_Lineart;
/* MOD_gpencil_util.c */

View File

@ -203,20 +203,6 @@ void gpencil_modifier_curve_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiTemplateCurveMapping(layout, ptr, "curve", 0, false, false, false, false);
}
void gpencil_modifier_fading_draw(const bContext *UNUSED(C), Panel *panel)
{
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
uiLayout *layout = panel->layout;
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "object", 0, NULL, ICON_CUBE);
uiLayout *sub = uiLayoutColumn(layout, true);
uiItemR(sub, ptr, "fading_start", 0, NULL, ICON_NONE);
uiItemR(sub, ptr, "fading_end", 0, IFACE_("End"), ICON_NONE);
uiItemR(layout, ptr, "fading_end_factor", 0, NULL, ICON_NONE);
}
/**
* Draw modifier error message.
*/

View File

@ -37,8 +37,6 @@ void gpencil_modifier_masking_panel_draw(Panel *panel, bool use_material, bool u
void gpencil_modifier_curve_header_draw(const bContext *C, Panel *panel);
void gpencil_modifier_curve_panel_draw(const bContext *C, Panel *panel);
void gpencil_modifier_fading_draw(const bContext *UNUSED(C), Panel *panel);
void gpencil_modifier_panel_end(struct uiLayout *layout, PointerRNA *ptr);
struct PointerRNA *gpencil_modifier_panel_get_property_pointers(struct Panel *panel,

View File

@ -63,6 +63,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
INIT_GP_TYPE(Time);
INIT_GP_TYPE(Multiply);
INIT_GP_TYPE(Texture);
INIT_GP_TYPE(Weight);
INIT_GP_TYPE(Lineart);
#undef INIT_GP_TYPE
}
@ -152,16 +153,16 @@ float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr)
if ((dvert != NULL) && (def_nr != -1)) {
MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
weight = dw ? dw->weight : -1.0f;
if ((weight >= 0.0f) && (inverse == 1)) {
if ((weight >= 0.0f) && (inverse)) {
return -1.0f;
}
if ((weight < 0.0f) && (inverse == 0)) {
if ((weight < 0.0f) && (!inverse)) {
return -1.0f;
}
/* if inverse, weight is always 1 */
if ((weight < 0.0f) && (inverse == 1)) {
if ((weight < 0.0f) && (inverse)) {
return 1.0f;
}
}

View File

@ -47,8 +47,6 @@
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
#include "UI_resources.h"
@ -86,39 +84,6 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity);
}
static float give_opacity_fading_factor(OpacityGpencilModifierData *mmd,
Object *ob_this,
float *pos,
bool apply_obmat)
{
float factor_depth = 1.0f;
if (((mmd->flag & GP_OPACITY_FADING) == 0) || ((mmd->object) == NULL)) {
return factor_depth;
}
float gvert[3];
if (apply_obmat) {
mul_v3_m4v3(gvert, ob_this->obmat, pos);
}
float dist = len_v3v3(mmd->object->obmat[3], gvert);
float fading_max = MAX2(mmd->fading_start, mmd->fading_end);
float fading_min = MIN2(mmd->fading_start, mmd->fading_end);
/* Better with ratiof() function from line art. */
if (dist > fading_max) {
factor_depth = 0.0f;
}
else if (dist <= fading_max && dist > fading_min) {
factor_depth = (fading_max - dist) / (fading_max - fading_min);
}
else {
factor_depth = 1.0f;
}
return factor_depth;
}
/* opacity strokes */
static void deformStroke(GpencilModifierData *md,
Depsgraph *UNUSED(depsgraph),
@ -130,6 +95,9 @@ static void deformStroke(GpencilModifierData *md,
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
const bool use_curve = (mmd->flag & GP_OPACITY_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
const bool is_normalized = (mmd->flag & GP_OPACITY_NORMALIZE);
bool is_inverted = ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) == 0) &&
((mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0);
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@ -161,11 +129,17 @@ static void deformStroke(GpencilModifierData *md,
/* Stroke using strength. */
if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
/* verify vertex group */
float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr);
float weight = get_modifier_point_weight(dvert, is_inverted, def_nr);
if (weight < 0.0f) {
continue;
}
/* Apply weight directly. */
if ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) && (!is_normalized)) {
pt->strength *= ((mmd->flag & GP_OPACITY_INVERT_VGROUP) ? 1.0f - weight : weight);
continue;
}
/* Custom curve to modulate value. */
float factor_curve = mmd->factor;
if (use_curve) {
@ -173,9 +147,6 @@ static void deformStroke(GpencilModifierData *md,
factor_curve *= BKE_curvemapping_evaluateF(mmd->curve_intensity, 0, value);
}
float factor_depth = give_opacity_fading_factor(mmd, ob, &pt->x, true);
factor_curve = interpf(factor_curve, mmd->fading_end_factor, factor_depth);
if (def_nr < 0) {
if (mmd->flag & GP_OPACITY_NORMALIZE) {
pt->strength = factor_curve;
@ -204,9 +175,19 @@ static void deformStroke(GpencilModifierData *md,
/* Fill using opacity factor. */
if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
float factor_depth = give_opacity_fading_factor(mmd, ob, ob->obmat[3], true);
gps->fill_opacity_fac = interpf(mmd->factor, mmd->fading_end_factor, factor_depth);
float fill_factor = mmd->factor;
if ((mmd->flag & GP_OPACITY_WEIGHT_FACTOR) && (!is_normalized)) {
/* Use first point for weight. */
MDeformVert *dvert = (gps->dvert != NULL) ? &gps->dvert[0] : NULL;
float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr);
if (weight >= 0.0f) {
fill_factor = ((mmd->flag & GP_OPACITY_INVERT_VGROUP) ? 1.0f - weight : weight);
}
}
gps->fill_opacity_fac = fill_factor;
CLAMP(gps->fill_opacity_fac, 0.0f, 1.0f);
}
}
@ -241,18 +222,6 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk,
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(GpencilModifierData *md,
const ModifierUpdateDepsgraphContext *ctx,
const int UNUSED(mode))
{
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
if (mmd->object != NULL) {
DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Opacity Modifier");
}
DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Opacity Modifier");
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@ -271,29 +240,25 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(layout, ptr, "hardness", 0, NULL, ICON_NONE);
}
else {
const bool is_normalized = RNA_boolean_get(ptr, "normalize_opacity");
const bool is_weighted = RNA_boolean_get(ptr, "use_weight_factor");
uiItemR(layout, ptr, "normalize_opacity", 0, NULL, ICON_NONE);
const char *text = (RNA_boolean_get(ptr, "normalize_opacity")) ? IFACE_("Strength") :
IFACE_("Opacity Factor");
uiItemR(layout, ptr, "factor", 0, text, ICON_NONE);
const char *text = (is_normalized) ? IFACE_("Strength") : IFACE_("Opacity Factor");
uiLayout *row = uiLayoutRow(layout, true);
uiLayoutSetActive(row, !is_weighted || is_normalized);
uiItemR(row, ptr, "factor", 0, text, ICON_NONE);
if (!is_normalized) {
uiLayout *sub = uiLayoutRow(row, true);
uiLayoutSetActive(sub, true);
uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT);
}
}
gpencil_modifier_panel_end(layout, ptr);
}
static void fading_header_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
uiItemR(layout, ptr, "use_fading", 0, NULL, ICON_NONE);
}
static void fading_panel_draw(const bContext *C, Panel *panel)
{
gpencil_modifier_fading_draw(C, panel);
}
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
@ -333,8 +298,6 @@ static void panelRegister(ARegionType *region_type)
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Opacity, panel_draw);
gpencil_modifier_subpanel_register(
region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type);
PanelType *mask_panel_type = gpencil_modifier_subpanel_register(
region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
@ -358,7 +321,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
/* initData */ initData,
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ updateDepsgraph,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* foreachIDLink */ foreachIDLink,
/* foreachTexLink */ NULL,

View File

@ -43,8 +43,6 @@
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
#include "UI_resources.h"
@ -118,42 +116,28 @@ static void deformStroke(GpencilModifierData *md,
}
float stroke_thickness_inv = 1.0f / max_ii(gps->thickness, 1);
const bool is_normalized = (mmd->flag & GP_THICK_NORMALIZE);
bool is_inverted = ((mmd->flag & GP_THICK_WEIGHT_FACTOR) == 0) &&
((mmd->flag & GP_THICK_INVERT_VGROUP) != 0);
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
/* Verify point is part of vertex group. */
float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr);
float weight = get_modifier_point_weight(dvert, is_inverted, def_nr);
if (weight < 0.0f) {
continue;
}
float curvef = 1.0f;
float factor_depth = 1.0f;
if (mmd->flag & GP_THICK_FADING) {
if (mmd->object) {
float gvert[3];
mul_v3_m4v3(gvert, ob->obmat, &pt->x);
float dist = len_v3v3(mmd->object->obmat[3], gvert);
float fading_max = MAX2(mmd->fading_start, mmd->fading_end);
float fading_min = MIN2(mmd->fading_start, mmd->fading_end);
/* Better with ratiof() function from line art. */
if (dist > fading_max) {
factor_depth = 0.0f;
}
else if (dist <= fading_max && dist > fading_min) {
factor_depth = (fading_max - dist) / (fading_max - fading_min);
}
else {
factor_depth = 1.0f;
}
}
/* Apply weight directly. */
if ((!is_normalized) && (mmd->flag & GP_THICK_WEIGHT_FACTOR)) {
pt->pressure *= ((mmd->flag & GP_THICK_INVERT_VGROUP) ? 1.0f - weight : weight);
CLAMP_MIN(pt->pressure, 0.0f);
continue;
}
float curvef = 1.0f;
if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) {
/* Normalize value to evaluate curve. */
float value = (float)i / (gps->totpoints - 1);
@ -161,7 +145,7 @@ static void deformStroke(GpencilModifierData *md,
}
float target;
if (mmd->flag & GP_THICK_NORMALIZE) {
if (is_normalized) {
target = mmd->thickness * stroke_thickness_inv;
target *= curvef;
}
@ -170,11 +154,6 @@ static void deformStroke(GpencilModifierData *md,
weight *= curvef;
}
/* Apply distance fading. */
if (mmd->flag & GP_THICK_FADING) {
target = interpf(target, mmd->fading_end_factor, factor_depth);
}
pt->pressure = interpf(target, pt->pressure, weight);
CLAMP_MIN(pt->pressure, 0.0f);
@ -202,32 +181,6 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk,
ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md;
walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(GpencilModifierData *md,
const ModifierUpdateDepsgraphContext *ctx,
const int UNUSED(mode))
{
ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md;
if (mmd->object != NULL) {
DEG_add_object_relation(ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "Thickness Modifier");
}
DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Thickness Modifier");
}
static void fading_header_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
uiItemR(layout, ptr, "use_fading", 0, NULL, ICON_NONE);
}
static void fading_panel_draw(const bContext *C, Panel *panel)
{
gpencil_modifier_fading_draw(C, panel);
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@ -239,12 +192,17 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "normalize_thickness", 0, NULL, ICON_NONE);
if (RNA_boolean_get(ptr, "normalize_thickness")) {
uiItemR(layout, ptr, "thickness", 0, NULL, ICON_NONE);
}
else {
uiItemR(layout, ptr, "thickness_factor", 0, NULL, ICON_NONE);
const bool is_weighted = !RNA_boolean_get(ptr, "use_weight_factor");
uiLayout *row = uiLayoutRow(layout, true);
uiLayoutSetActive(row, is_weighted);
uiItemR(row, ptr, "thickness_factor", 0, NULL, ICON_NONE);
uiLayout *sub = uiLayoutRow(row, true);
uiLayoutSetActive(sub, true);
uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT);
}
gpencil_modifier_panel_end(layout, ptr);
@ -259,8 +217,6 @@ static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Thick, panel_draw);
gpencil_modifier_subpanel_register(
region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type);
PanelType *mask_panel_type = gpencil_modifier_subpanel_register(
region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
gpencil_modifier_subpanel_register(region_type,
@ -288,7 +244,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Thick = {
/* initData */ initData,
/* freeData */ freeData,
/* isDisabled */ NULL,
/* updateDepsgraph */ updateDepsgraph,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* foreachIDLink */ foreachIDLink,
/* foreachTexLink */ NULL,

View File

@ -127,6 +127,8 @@ static void deformStroke(GpencilModifierData *md,
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
const bool use_curve = (mmd->flag & GP_TINT_CUSTOM_CURVE) != 0 && mmd->curve_intensity;
bool is_inverted = ((mmd->flag & GP_TINT_WEIGHT_FACTOR) == 0) &&
((mmd->flag & GP_TINT_INVERT_VGROUP) != 0);
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@ -169,6 +171,17 @@ static void deformStroke(GpencilModifierData *md,
if (!fill_done) {
/* Apply to fill. */
if (mmd->mode != GPPAINT_MODE_STROKE) {
float fill_factor = mmd->factor;
/* Use weightened factor. */
if (mmd->flag & GP_TINT_WEIGHT_FACTOR) {
/* Use first point for weight. */
MDeformVert *dvert = (gps->dvert != NULL) ? &gps->dvert[0] : NULL;
float weight = get_modifier_point_weight(dvert, is_inverted, def_nr);
if (weight >= 0.0f) {
fill_factor = ((mmd->flag & GP_TINT_INVERT_VGROUP) ? 1.0f - weight : weight);
}
}
/* If not using Vertex Color, use the material color. */
if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
@ -188,13 +201,13 @@ static void deformStroke(GpencilModifierData *md,
BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, coba_res, mmd->factor);
gps->vert_color_fill[3] = clamp_f(mmd->factor, 0.0f, 1.0f);
gps->vert_color_fill[3] = clamp_f(fill_factor, 0.0f, 1.0f);
}
else {
interp_v3_v3v3(gps->vert_color_fill,
gps->vert_color_fill,
mmd->rgb,
clamp_f(mmd->factor, 0.0f, 1.0f));
clamp_f(fill_factor, 0.0f, 1.0f));
}
/* If no stroke, cancel loop. */
if (mmd->mode != GPPAINT_MODE_BOTH) {
@ -207,11 +220,13 @@ static void deformStroke(GpencilModifierData *md,
/* Verify vertex group. */
if (mmd->mode != GPPAINT_MODE_FILL) {
float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_TINT_INVERT_VGROUP) != 0, def_nr);
float weight = get_modifier_point_weight(dvert, is_inverted, def_nr);
if (weight < 0.0f) {
continue;
}
float factor = mmd->factor;
/* Custom curve to modulate value. */
if (use_curve) {
float value = (float)i / (gps->totpoints - 1);
@ -224,6 +239,12 @@ static void deformStroke(GpencilModifierData *md,
pt->vert_color[3] = 1.0f;
}
/* Apply weight directly. */
if (mmd->flag & GP_TINT_WEIGHT_FACTOR) {
factor = ((mmd->flag & GP_TINT_INVERT_VGROUP) ? 1.0f - weight : weight);
weight = 1.0f;
}
if (is_gradient) {
/* Calc world position of point. */
float pt_loc[3];
@ -237,11 +258,11 @@ static void deformStroke(GpencilModifierData *md,
interp_v3_v3v3(pt->vert_color,
pt->vert_color,
coba_res,
clamp_f(mmd->factor, 0.0f, 1.0f) * weight * coba_res[3]);
clamp_f(factor, 0.0f, 1.0f) * weight * coba_res[3]);
}
else {
interp_v3_v3v3(
pt->vert_color, pt->vert_color, mmd->rgb, clamp_f(mmd->factor * weight, 0.0, 1.0f));
pt->vert_color, pt->vert_color, mmd->rgb, clamp_f(factor * weight, 0.0, 1.0f));
}
}
}
@ -338,7 +359,15 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "vertex_mode", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "factor", 0, NULL, ICON_NONE);
const bool is_weighted = !RNA_boolean_get(ptr, "use_weight_factor");
uiLayout *row = uiLayoutRow(layout, true);
uiLayoutSetActive(row, is_weighted);
uiItemR(row, ptr, "factor", 0, NULL, ICON_NONE);
uiLayout *sub = uiLayoutRow(row, true);
uiLayoutSetActive(sub, true);
uiItemR(row, ptr, "use_weight_factor", 0, "", ICON_MOD_VERTEX_WEIGHT);
uiItemR(layout, ptr, "tint_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
if (tint_type == GP_TINT_UNIFORM) {

View File

@ -0,0 +1,335 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021, Blender Foundation
* This is a new part of Blender
*/
/** \file
* \ingroup modifiers
*/
#include <stdio.h>
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_lib_query.h"
#include "BKE_modifier.h"
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "RNA_access.h"
#include "MOD_gpencil_modifiertypes.h"
#include "MOD_gpencil_ui_common.h"
#include "MOD_gpencil_util.h"
static void initData(GpencilModifierData *md)
{
WeightGpencilModifierData *gpmd = (WeightGpencilModifierData *)md;
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier));
MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(WeightGpencilModifierData), modifier);
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
{
BKE_gpencil_modifier_copydata_generic(md, target);
}
/* Calc distance between point and target object. */
static float calc_point_weight_by_distance(Object *ob,
WeightGpencilModifierData *mmd,
const float dist_max,
const float dist_min,
bGPDspoint *pt)
{
float weight;
float gvert[3];
mul_v3_m4v3(gvert, ob->obmat, &pt->x);
float dist = len_v3v3(mmd->object->obmat[3], gvert);
if (dist > dist_max) {
weight = 0.0f;
}
else if (dist <= dist_max && dist > dist_min) {
weight = (dist_max - dist) / max_ff((dist_max - dist_min), 0.0001f);
}
else {
weight = 1.0f;
}
return weight;
}
/* change stroke thickness */
static void deformStroke(GpencilModifierData *md,
Depsgraph *UNUSED(depsgraph),
Object *ob,
bGPDlayer *gpl,
bGPDframe *UNUSED(gpf),
bGPDstroke *gps)
{
WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md;
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
const eWeightGpencilModifierMode mode = mmd->mode;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
mmd->material,
mmd->pass_index,
mmd->layer_pass,
1,
gpl,
gps,
mmd->flag & GP_WEIGHT_INVERT_LAYER,
mmd->flag & GP_WEIGHT_INVERT_PASS,
mmd->flag & GP_WEIGHT_INVERT_LAYERPASS,
mmd->flag & GP_WEIGHT_INVERT_MATERIAL)) {
return;
}
const float dist_max = MAX2(mmd->dist_start, mmd->dist_end);
const float dist_min = MIN2(mmd->dist_start, mmd->dist_end);
const int target_def_nr = BKE_object_defgroup_name_index(ob, mmd->target_vgname);
if (target_def_nr == -1) {
return;
}
/* Use default Z up. */
float vec_axis[3] = {0.0f, 0.0f, 1.0f};
float axis[3] = {0.0f, 0.0f, 0.0f};
axis[mmd->axis] = 1.0f;
float vec_ref[3];
/* Apply modifier rotation (sub 90 degrees for Y axis due Z-Up vector). */
float rot_angle = mmd->angle - ((mmd->axis == 1) ? M_PI_2 : 0.0f);
rotate_normalized_v3_v3v3fl(vec_ref, vec_axis, axis, rot_angle);
/* Apply the rotation of the object. */
if (mmd->space == GP_SPACE_LOCAL) {
mul_mat3_m4_v3(ob->obmat, vec_ref);
}
/* Ensure there is a vertex group. */
BKE_gpencil_dvert_ensure(gps);
float weight_pt = 1.0f;
for (int i = 0; i < gps->totpoints; i++) {
MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
/* Verify point is part of vertex group. */
float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_WEIGHT_INVERT_VGROUP) != 0, def_nr);
if (weight < 0.0f) {
continue;
}
switch (mode) {
case GP_WEIGHT_MODE_DISTANCE: {
if (mmd->object) {
bGPDspoint *pt = &gps->points[i];
weight_pt = calc_point_weight_by_distance(ob, mmd, dist_max, dist_min, pt);
}
break;
}
case GP_WEIGHT_MODE_ANGLE: {
/* Special case for single points. */
if (gps->totpoints == 1) {
weight_pt = 1.0f;
break;
}
bGPDspoint *pt1 = (i > 0) ? &gps->points[i] : &gps->points[i + 1];
bGPDspoint *pt2 = (i > 0) ? &gps->points[i - 1] : &gps->points[i];
float fpt1[3], fpt2[3];
mul_v3_m4v3(fpt1, ob->obmat, &pt1->x);
mul_v3_m4v3(fpt2, ob->obmat, &pt2->x);
float vec[3];
sub_v3_v3v3(vec, fpt1, fpt2);
float angle = angle_on_axis_v3v3_v3(vec_ref, vec, axis);
/* Use sin to get a value between 0 and 1. */
weight_pt = 1.0f - sin(angle);
break;
}
default:
break;
}
/* Invert weight if required. */
if (mmd->flag & GP_WEIGHT_INVERT_OUTPUT) {
weight_pt = 1.0f - weight_pt;
}
/* Assign weight. */
dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
if (dvert != NULL) {
MDeformWeight *dw = BKE_defvert_ensure_index(dvert, target_def_nr);
if (dw) {
dw->weight = (mmd->flag & GP_WEIGHT_BLEND_DATA) ? dw->weight * weight_pt : weight_pt;
CLAMP(dw->weight, mmd->min_weight, 1.0f);
}
}
}
}
static void bakeModifier(struct Main *UNUSED(bmain),
Depsgraph *depsgraph,
GpencilModifierData *md,
Object *ob)
{
bGPdata *gpd = ob->data;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
}
}
static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md;
walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(GpencilModifierData *md,
const ModifierUpdateDepsgraphContext *ctx,
const int UNUSED(mode))
{
WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md;
if (mmd->object != NULL) {
DEG_add_object_relation(
ctx->node, mmd->object, DEG_OB_COMP_TRANSFORM, "GPencil Weight Modifier");
}
DEG_add_object_relation(
ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "GPencil Weight Modifier");
}
static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
{
WeightGpencilModifierData *mmd = (WeightGpencilModifierData *)md;
return !(mmd->target_vgname && mmd->target_vgname[0] != '\0');
}
static void distance_panel_draw(const bContext *C, Panel *panel)
{
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
uiLayout *layout = panel->layout;
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "object", 0, NULL, ICON_CUBE);
uiLayout *sub = uiLayoutColumn(layout, true);
uiItemR(sub, ptr, "distance_start", 0, NULL, ICON_NONE);
uiItemR(sub, ptr, "distance_end", 0, "End", ICON_NONE);
}
static void panel_draw(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA ob_ptr;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
uiLayoutSetPropSep(layout, true);
uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
const eWeightGpencilModifierMode mode = RNA_enum_get(ptr, "mode");
uiItemPointerR(layout, ptr, "target_vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
uiItemR(layout, ptr, "minimum_weight", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_invert_output", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_blend", 0, NULL, ICON_NONE);
switch (mode) {
case GP_WEIGHT_MODE_DISTANCE:
distance_panel_draw(C, panel);
break;
case GP_WEIGHT_MODE_ANGLE:
uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "axis", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "space", 0, NULL, ICON_NONE);
break;
default:
break;
}
gpencil_modifier_panel_end(layout, ptr);
}
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
gpencil_modifier_masking_panel_draw(panel, true, true);
}
static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = gpencil_modifier_panel_register(
region_type, eGpencilModifierType_Weight, panel_draw);
gpencil_modifier_subpanel_register(
region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
}
GpencilModifierTypeInfo modifierType_Gpencil_Weight = {
/* name */ "Vertex Weight",
/* structName */ "WeightGpencilModifierData",
/* structSize */ sizeof(WeightGpencilModifierData),
/* type */ eGpencilModifierTypeType_Gpencil,
/* flags */ 0,
/* copyData */ copyData,
/* deformStroke */ deformStroke,
/* generateStrokes */ NULL,
/* bakeModifier */ bakeModifier,
/* remapTime */ NULL,
/* initData */ initData,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* foreachIDLink */ foreachIDLink,
/* foreachTexLink */ NULL,
/* panelRegister */ panelRegister,
};

View File

@ -184,8 +184,6 @@
.layer_pass = 0, \
.hardeness = 1.0f, \
.curve_intensity = NULL, \
.fading_end = 10.0f, \
.fading_end_factor = 0.2f, \
}
#define _DNA_DEFAULT_SimplifyGpencilModifierData \
@ -253,8 +251,6 @@
.thickness_fac = 1.0f, \
.thickness = 30, \
.layer_pass = 0, \
.fading_end = 10.0f, \
.fading_end_factor = 0.2f, \
}
#define _DNA_DEFAULT_TimeGpencilModifierData \
@ -287,6 +283,20 @@
.colorband = NULL, \
}
#define _DNA_DEFAULT_WeightGpencilModifierData \
{ \
.target_vgname = "", \
.material = NULL, \
.layername = "", \
.vgname = "", \
.pass_index = 0, \
.flag = 0, \
.axis = 1, \
.layer_pass = 0, \
.dist_start = 0.0f, \
.dist_end = 20.0f, \
}
#define _DNA_DEFAULT_LineartGpencilModifierData \
{ \
.edge_types = LRT_EDGE_FLAG_ALL_TYPE, \

View File

@ -55,6 +55,7 @@ typedef enum GpencilModifierType {
eGpencilModifierType_Texture = 18,
eGpencilModifierType_Lineart = 19,
eGpencilModifierType_Length = 20,
eGpencilModifierType_Weight = 21,
/* Keep last. */
NUM_GREASEPENCIL_MODIFIER_TYPES,
} GpencilModifierType;
@ -188,12 +189,7 @@ typedef struct ThickGpencilModifierData {
int thickness;
/** Custom index for passes. */
int layer_pass;
/** Start/end distances of the fading effect. */
float fading_start;
float fading_end;
float fading_end_factor;
/** Fading reference object */
struct Object *object;
char _pad[4];
struct CurveMapping *curve_thickness;
} ThickGpencilModifierData;
@ -205,7 +201,7 @@ typedef enum eThickGpencil_Flag {
GP_THICK_NORMALIZE = (1 << 4),
GP_THICK_INVERT_LAYERPASS = (1 << 5),
GP_THICK_INVERT_MATERIAL = (1 << 6),
GP_THICK_FADING = (1 << 7),
GP_THICK_WEIGHT_FACTOR = (1 << 7),
} eThickGpencil_Flag;
typedef struct TimeGpencilModifierData {
@ -298,16 +294,9 @@ typedef struct OpacityGpencilModifierData {
int flag;
/** Main Opacity factor. */
float factor;
/** Fading controlling object */
int _pad0;
struct Object *object;
/** Start/end distances of the fading effect. */
float fading_start;
float fading_end;
float fading_end_factor;
/** Modify stroke, fill or both. */
char modify_color;
char _pad1[3];
char _pad[3];
/** Custom index for passes. */
int layer_pass;
@ -323,7 +312,7 @@ typedef enum eOpacityGpencil_Flag {
GP_OPACITY_INVERT_MATERIAL = (1 << 5),
GP_OPACITY_CUSTOM_CURVE = (1 << 6),
GP_OPACITY_NORMALIZE = (1 << 7),
GP_OPACITY_FADING = (1 << 8),
GP_OPACITY_WEIGHT_FACTOR = (1 << 8),
} eOpacityGpencil_Flag;
typedef struct ArrayGpencilModifierData {
@ -814,6 +803,7 @@ typedef enum eTintGpencil_Flag {
GP_TINT_INVERT_LAYERPASS = (1 << 4),
GP_TINT_INVERT_MATERIAL = (1 << 5),
GP_TINT_CUSTOM_CURVE = (1 << 6),
GP_TINT_WEIGHT_FACTOR = (1 << 7),
} eTintGpencil_Flag;
typedef struct TextureGpencilModifierData {
@ -867,6 +857,61 @@ typedef enum eTextureGpencil_Mode {
STROKE_AND_FILL = 2,
} eTextureGpencil_Mode;
typedef struct WeightGpencilModifierData {
GpencilModifierData modifier;
/** Target vertexgroup name, MAX_VGROUP_NAME. */
char target_vgname[64];
/** Material for filtering. */
struct Material *material;
/** Layer name. */
char layername[64];
/** Optional vertexgroup filter name, MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
/** Flags. */
int flag;
/** Minimum valid weight (clamp value). */
float min_weight;
/** Custom index for passes. */
int layer_pass;
/** Calculation Mode. */
short mode;
/** Axis. */
short axis;
/** Angle */
float angle;
/** Start/end distances. */
float dist_start;
float dist_end;
/** Space (Local/World). */
short space;
char _pad[6];
/** Reference object */
struct Object *object;
} WeightGpencilModifierData;
typedef enum eWeightGpencil_Flag {
GP_WEIGHT_INVERT_LAYER = (1 << 0),
GP_WEIGHT_INVERT_PASS = (1 << 1),
GP_WEIGHT_INVERT_VGROUP = (1 << 2),
GP_WEIGHT_INVERT_LAYERPASS = (1 << 3),
GP_WEIGHT_INVERT_MATERIAL = (1 << 4),
GP_WEIGHT_BLEND_DATA = (1 << 5),
GP_WEIGHT_INVERT_OUTPUT = (1 << 6),
} eWeightGpencil_Flag;
typedef enum eWeightGpencilModifierMode {
GP_WEIGHT_MODE_DISTANCE = 0,
GP_WEIGHT_MODE_ANGLE = 1,
} eWeightGpencilModifierMode;
typedef enum eGpencilModifierSpace {
GP_SPACE_LOCAL = 0,
GP_SPACE_WORLD = 1,
} eGpencilModifierSpace;
typedef enum eLineartGpencilModifierSource {
LRT_SOURCE_COLLECTION = 0,
LRT_SOURCE_OBJECT = 1,

View File

@ -315,6 +315,7 @@ SDNA_DEFAULT_DECL_STRUCT(TextureGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(ThickGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(TimeGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(TintGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(WeightGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(LineartGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(LengthGpencilModifierData);
@ -541,6 +542,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
SDNA_DEFAULT_DECL(ThickGpencilModifierData),
SDNA_DEFAULT_DECL(TimeGpencilModifierData),
SDNA_DEFAULT_DECL(TintGpencilModifierData),
SDNA_DEFAULT_DECL(WeightGpencilModifierData),
SDNA_DEFAULT_DECL(LineartGpencilModifierData),
SDNA_DEFAULT_DECL(LengthGpencilModifierData),
};

View File

@ -93,6 +93,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = {
ICON_MOD_SUBSURF,
"Subdivide",
"Subdivide stroke adding more control points"},
{eGpencilModifierType_Weight,
"GP_WEIGHT",
ICON_MOD_VERTEX_WEIGHT,
"Vertex Weight",
"Generate Vertex Weights"},
{0, "", 0, N_("Deform"), ""},
{eGpencilModifierType_Armature,
"GP_ARMATURE",
@ -233,6 +238,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr)
return &RNA_TintGpencilModifier;
case eGpencilModifierType_Time:
return &RNA_TimeGpencilModifier;
case eGpencilModifierType_Weight:
return &RNA_WeightGpencilModifier;
case eGpencilModifierType_Color:
return &RNA_ColorGpencilModifier;
case eGpencilModifierType_Array:
@ -331,6 +338,8 @@ RNA_GP_MOD_VGROUP_NAME_SET(Offset, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Armature, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Texture, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Tint, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Weight, target_vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Weight, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Lineart, vgname);
# undef RNA_GP_MOD_VGROUP_NAME_SET
@ -363,8 +372,7 @@ static void greasepencil_modifier_object_set(Object *self,
RNA_GP_MOD_OBJECT_SET(Armature, object, OB_ARMATURE);
RNA_GP_MOD_OBJECT_SET(Lattice, object, OB_LATTICE);
RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY);
RNA_GP_MOD_OBJECT_SET(Opacity, object, OB_EMPTY);
RNA_GP_MOD_OBJECT_SET(Thick, object, OB_EMPTY);
RNA_GP_MOD_OBJECT_SET(Weight, object, OB_EMPTY);
# undef RNA_GP_MOD_OBJECT_SET
@ -538,6 +546,16 @@ static void rna_ThickGpencilModifier_material_set(PointerRNA *ptr,
rna_GpencilModifier_material_set(ptr, value, ma_target, reports);
}
static void rna_WeightGpencilModifier_material_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *reports)
{
WeightGpencilModifierData *tmd = (WeightGpencilModifierData *)ptr->data;
Material **ma_target = &tmd->material;
rna_GpencilModifier_material_set(ptr, value, ma_target, reports);
}
static void rna_OffsetGpencilModifier_material_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *reports)
@ -1143,35 +1161,9 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Thickness Factor", "Factor to multiply the thickness with");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_FADING);
RNA_def_property_ui_text(prop, "Fading", "Fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
/* Distance reference object */
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Object used as distance reference");
RNA_def_property_pointer_funcs(prop, NULL, "rna_ThickGpencilModifier_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "fading_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_start");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Fading Start", "Start distance of fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "fading_end", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_end");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Fading End", "End distance of fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "fading_end_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_end_factor");
RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 10.0, 0.1, 3);
RNA_def_property_ui_text(prop, "End Factor", "Fading end thickness factor");
prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_WEIGHT_FACTOR);
RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
@ -1440,6 +1432,11 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Strength", "Factor for tinting");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_WEIGHT_FACTOR);
RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "radius");
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
@ -1726,35 +1723,9 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Hardness", "Factor of stroke hardness");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_FADING);
RNA_def_property_ui_text(prop, "Fading", "Fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
/* Distance reference object */
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Object used as distance reference");
RNA_def_property_pointer_funcs(prop, NULL, "rna_OpacityGpencilModifier_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "fading_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_start");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Fading Start", "Start distance of fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "fading_end", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_end");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Fading End", "End distance of fading effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "fading_end_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fading_end_factor");
RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 10.0, 0.1, 3);
RNA_def_property_ui_text(prop, "End Factor", "Fading end thickness factor");
prop = RNA_def_property(srna, "use_weight_factor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_WEIGHT_FACTOR);
RNA_def_property_ui_text(prop, "Weighted", "Use weight to modulate effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
@ -2733,6 +2704,170 @@ static void rna_def_modifier_gpenciltexture(BlenderRNA *brna)
RNA_define_lib_overridable(false);
}
static void rna_def_modifier_gpencilweight(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem mode_items[] = {
{GP_WEIGHT_MODE_DISTANCE,
"DISTANCE",
0,
"Distance",
"Calculate weights depending on the distance to the target object"},
{GP_WEIGHT_MODE_ANGLE,
"ANGLE",
0,
"Angle",
"Calculate weights depending on the stroke orientation"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem axis_items[] = {
{0, "X", 0, "X", ""},
{1, "Y", 0, "Y", ""},
{2, "Z", 0, "Z", ""},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem space_items[] = {
{GP_SPACE_LOCAL, "LOCAL", 0, "Local Space", ""},
{GP_SPACE_WORLD, "WORLD", 0, "World Space", ""},
{0, NULL, 0, NULL, NULL},
};
srna = RNA_def_struct(brna, "WeightGpencilModifier", "GpencilModifier");
RNA_def_struct_ui_text(srna, "Weight Modifier", "Calculate Vertex Weight dynamically");
RNA_def_struct_sdna(srna, "WeightGpencilModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT);
RNA_define_lib_overridable(true);
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "target_vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "target_vgname");
RNA_def_property_ui_text(prop, "Output", "Output Vertex group");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightGpencilModifier_target_vgname_set");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_blend", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_BLEND_DATA);
RNA_def_property_ui_text(
prop, "Blend", "Blend results with existing weights in output weight group");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "use_invert_output", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_OUTPUT);
RNA_def_property_ui_text(prop, "Invert", "Invert weight values");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "angle");
RNA_def_property_ui_text(prop, "Angle", "Angle");
RNA_def_property_range(prop, 0.0f, DEG2RAD(180.0f));
RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "axis");
RNA_def_property_enum_items(prop, axis_items);
RNA_def_property_ui_text(prop, "Axis", "");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "space");
RNA_def_property_enum_items(prop, space_items);
RNA_def_property_ui_text(prop, "Space", "Coordinates space");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "layername");
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop,
NULL,
"rna_WeightGpencilModifier_material_set",
NULL,
"rna_GpencilModifier_material_poll");
RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "vgname");
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_WeightGpencilModifier_vgname_set");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
/* Distance reference object */
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Object used as distance reference");
RNA_def_property_pointer_funcs(prop, NULL, "rna_WeightGpencilModifier_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "distance_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "dist_start");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Distance Start", "Start value for distance calculation");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "minimum_weight", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "min_weight");
RNA_def_property_ui_text(prop, "Minimum", "Minimum value for vertex weight");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "distance_end", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "dist_end");
RNA_def_property_ui_range(prop, 0, 1000.0, 1.0, 2);
RNA_def_property_ui_text(prop, "Distance End", "End value for distance calculation");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "pass_index");
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_text(prop, "Pass", "Pass index");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_LAYER);
RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_MATERIAL);
RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_PASS);
RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "layer_pass");
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_text(prop, "Pass", "Layer pass index");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "invert_layer_pass", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_WEIGHT_INVERT_LAYERPASS);
RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
RNA_define_lib_overridable(false);
}
static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
{
StructRNA *srna;
@ -3187,6 +3322,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna)
rna_def_modifier_gpencilarmature(brna);
rna_def_modifier_gpencilmultiply(brna);
rna_def_modifier_gpenciltexture(brna);
rna_def_modifier_gpencilweight(brna);
rna_def_modifier_gpencillineart(brna);
rna_def_modifier_gpencillength(brna);
}