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:
authorAntonio Vazquez <blendergit@gmail.com>2021-07-02 13:04:07 +0300
committerAntonio Vazquez <blendergit@gmail.com>2021-07-02 13:04:07 +0300
commit29b65f5345128ee035599aa7233315a74fe6afe6 (patch)
tree7ba21663688b5eca67c1884a8da5e0aa9a125c64 /source/blender/gpencil_modifiers/intern
parent9f5c0ffb5ec293af2e4f003c2178d21e20805b47 (diff)
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
Diffstat (limited to 'source/blender/gpencil_modifiers/intern')
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c14
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c7
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c111
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c84
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c43
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c335
7 files changed, 432 insertions, 164 deletions
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
index 94285b5032e..a156fca5b7b 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
@@ -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.
*/
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
index 75907aaa781..782b36d47ed 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
@@ -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,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index b28a44a0521..6409c86b6e3 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -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;
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
index 9f03e493ea8..fb75b1e99ac 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -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,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
index 126949cd659..cac700e15f4 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -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,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index 4a6e3df59c7..358b5577b97 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -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) {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c
new file mode 100644
index 00000000000..76960505395
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilweight.c
@@ -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,
+};