GPencil: Make Sculpt Auto-masking Global and not by Brush
The auto-masking was working by Brush and this was very inconvenient because it was necessary set the options by Brush, now the options are global and can be set at once. Also, the automa-masking now works with `and` logic and not with `or` as before. That means that a stroke must meet all the conditions of the masking. Added new Layer and Material options to masking the strokes using the same Layer/Material of the selected stroke. Before, only Active Layer and Active Material could be masked. The options of masking has been moved to the top-bar using the same design of Mesh Sculpt masking. As result of the changes above, the following props changed: Removed: `brush.gpencil_settings.use_automasking_strokes` `brush.gpencil_settings.use_automasking_layer` `brush.gpencil_settings.use_automasking_material` Added: `tool_settings.gpencil_sculpt.use_automasking_stroke` `tool_settings.gpencil_sculpt.use_automasking_layer_stroke` `tool_settings.gpencil_sculpt.use_automasking_material_stroke` `tool_settings.gpencil_sculpt.use_automasking_layer_active` `tool_settings.gpencil_sculpt.use_automasking_material_active` Reviewed by: Julien Kaspar, Matias Mendiola, Daniel Martinez Lara
This commit is contained in:
parent
bbb1d3e5e7
commit
4c182aef7c
|
@ -3969,6 +3969,8 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}),
|
||||
# Context menu
|
||||
*_template_items_context_panel("VIEW3D_PT_gpencil_sculpt_context_menu", params.context_menu_event),
|
||||
# Automasking Pie menu
|
||||
op_menu_pie("VIEW3D_MT_sculpt_gpencil_automasking_pie", {"type": 'A', "shift": True, "alt": True, "value": 'PRESS'}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
|
|
@ -51,11 +51,6 @@ class GreasePencilSculptAdvancedPanel:
|
|||
tool = brush.gpencil_sculpt_tool
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
col = layout.column(heading="Auto-Masking", align=True)
|
||||
col.prop(gp_settings, "use_automasking_stroke", text="Stroke")
|
||||
col.prop(gp_settings, "use_automasking_layer", text="Layer")
|
||||
col.prop(gp_settings, "use_automasking_material", text="Material")
|
||||
|
||||
if tool in {'SMOOTH', 'RANDOMIZE'}:
|
||||
col = layout.column(heading="Affect", align=True)
|
||||
col.prop(gp_settings, "use_edit_position", text="Position")
|
||||
|
|
|
@ -108,7 +108,7 @@ class VIEW3D_HT_tool_header(Header):
|
|||
brush = context.tool_settings.gpencil_sculpt_paint.brush
|
||||
if brush:
|
||||
tool = brush.gpencil_sculpt_tool
|
||||
if tool != 'CLONE':
|
||||
if tool in {'SMOOTH', 'RANDOMIZE'}:
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
|
||||
elif tool_mode == 'WEIGHT_GPENCIL':
|
||||
|
@ -837,14 +837,18 @@ class VIEW3D_HT_header(Header):
|
|||
panel="VIEW3D_PT_gpencil_guide",
|
||||
text="Guides",
|
||||
)
|
||||
|
||||
if object_mode == 'SCULPT_GPENCIL':
|
||||
layout.popover(
|
||||
panel="VIEW3D_PT_gpencil_sculpt_automasking",
|
||||
text="",
|
||||
icon="MOD_MASK"
|
||||
)
|
||||
elif object_mode == 'SCULPT':
|
||||
layout.popover(
|
||||
panel="VIEW3D_PT_sculpt_automasking",
|
||||
text="",
|
||||
icon="MOD_MASK"
|
||||
)
|
||||
|
||||
else:
|
||||
# Transform settings depending on tool header visibility
|
||||
VIEW3D_HT_header.draw_xform_template(layout, context)
|
||||
|
@ -5519,6 +5523,22 @@ class VIEW3D_MT_sculpt_automasking_pie(Menu):
|
|||
pie.prop(sculpt, "use_automasking_view_normal", text="View Normal")
|
||||
|
||||
|
||||
class VIEW3D_MT_sculpt_gpencil_automasking_pie(Menu):
|
||||
bl_label = "Automasking"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
pie = layout.menu_pie()
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
|
||||
pie.prop(tool_settings.gpencil_sculpt, "use_automasking_stroke", text="Stroke")
|
||||
pie.prop(tool_settings.gpencil_sculpt, "use_automasking_layer_stroke", text="Layer")
|
||||
pie.prop(tool_settings.gpencil_sculpt, "use_automasking_material_stroke", text="Material")
|
||||
pie.prop(tool_settings.gpencil_sculpt, "use_automasking_layer_active", text="Active Layer")
|
||||
pie.prop(tool_settings.gpencil_sculpt, "use_automasking_material_active", text="Active Material")
|
||||
|
||||
|
||||
class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
|
||||
|
||||
bl_label = "Face Sets Edit"
|
||||
|
@ -7467,6 +7487,27 @@ def draw_gpencil_material_active(context, layout):
|
|||
row.prop(ma, "name", text="")
|
||||
|
||||
|
||||
class VIEW3D_PT_gpencil_sculpt_automasking(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_label = "Auto-masking"
|
||||
bl_ui_units_x = 10
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
tool_settings = context.scene.tool_settings
|
||||
layout.label(text="Auto-masking")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(tool_settings.gpencil_sculpt, "use_automasking_stroke", text="Stroke")
|
||||
col.prop(tool_settings.gpencil_sculpt, "use_automasking_layer_stroke", text="Layer")
|
||||
col.prop(tool_settings.gpencil_sculpt, "use_automasking_material_stroke", text="Material")
|
||||
col.separator()
|
||||
col.prop(tool_settings.gpencil_sculpt, "use_automasking_layer_active", text="Active Layer")
|
||||
col.prop(tool_settings.gpencil_sculpt, "use_automasking_material_active", text="Active Material")
|
||||
|
||||
|
||||
class VIEW3D_PT_gpencil_sculpt_context_menu(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'WINDOW'
|
||||
|
@ -8103,6 +8144,7 @@ classes = (
|
|||
VIEW3D_MT_proportional_editing_falloff_pie,
|
||||
VIEW3D_MT_sculpt_mask_edit_pie,
|
||||
VIEW3D_MT_sculpt_automasking_pie,
|
||||
VIEW3D_MT_sculpt_gpencil_automasking_pie,
|
||||
VIEW3D_MT_wpaint_vgroup_lock_pie,
|
||||
VIEW3D_MT_sculpt_face_sets_edit_pie,
|
||||
VIEW3D_MT_sculpt_curves,
|
||||
|
@ -8117,6 +8159,7 @@ classes = (
|
|||
VIEW3D_PT_annotation_onion,
|
||||
VIEW3D_PT_gpencil_multi_frame,
|
||||
VIEW3D_PT_gpencil_curve_edit,
|
||||
VIEW3D_PT_gpencil_sculpt_automasking,
|
||||
VIEW3D_PT_quad_view,
|
||||
VIEW3D_PT_view3d_stereo,
|
||||
VIEW3D_PT_shading,
|
||||
|
|
|
@ -1964,7 +1964,7 @@ class VIEW3D_PT_tools_grease_pencil_sculpt_brush_advanced(GreasePencilSculptAdva
|
|||
return False
|
||||
|
||||
tool = brush.gpencil_sculpt_tool
|
||||
return tool != 'CLONE'
|
||||
return tool in {'SMOOTH', 'RANDOMIZE'}
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover(GreasePencilSculptAdvancedPanel, View3DPanel, Panel):
|
||||
|
@ -1982,7 +1982,7 @@ class VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover(GreasePencilSculptAdvan
|
|||
return False
|
||||
|
||||
tool = brush.gpencil_sculpt_tool
|
||||
return tool != 'CLONE'
|
||||
return tool in {'SMOOTH', 'RANDOMIZE'}
|
||||
|
||||
|
||||
# Grease Pencil weight painting tools
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
|
||||
#include "gpencil_intern.h"
|
||||
|
||||
#define SEARCH_RADIUS_PIXEL 20
|
||||
|
||||
/* ************************************************ */
|
||||
/* General Brush Editing Context */
|
||||
|
||||
|
@ -78,6 +80,7 @@ typedef struct tGP_BrushEditData {
|
|||
Main *bmain;
|
||||
Scene *scene;
|
||||
Object *object;
|
||||
Object *ob_eval;
|
||||
|
||||
ScrArea *area;
|
||||
ARegion *region;
|
||||
|
@ -1181,6 +1184,8 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
|
|||
}
|
||||
/* Check if some modifier can transform the stroke. */
|
||||
gso->is_transformed = BKE_gpencil_has_transform_modifiers(ob);
|
||||
|
||||
gso->ob_eval = (Object *)DEG_get_evaluated_id(gso->depsgraph, &ob->id);
|
||||
}
|
||||
else {
|
||||
unit_m4(gso->inv_mat);
|
||||
|
@ -1196,9 +1201,13 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
|
|||
gso->brush = brush;
|
||||
BKE_curvemapping_init(gso->brush->curve);
|
||||
|
||||
if (brush->gpencil_settings->sculpt_mode_flag &
|
||||
(GP_SCULPT_FLAGMODE_AUTOMASK_STROKE | GP_SCULPT_FLAGMODE_AUTOMASK_LAYER |
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL)) {
|
||||
const bool is_automasking = (ts->gp_sculpt.flag &
|
||||
(GP_SCULPT_SETT_FLAG_AUTOMASK_STROKE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_STROKE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_STROKE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_ACTIVE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_ACTIVE)) != 0;
|
||||
if (is_automasking) {
|
||||
gso->automasking_strokes = BLI_ghash_ptr_new(__func__);
|
||||
}
|
||||
else {
|
||||
|
@ -1604,13 +1613,16 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
|
|||
bGPdata *gpd = ob->data;
|
||||
const char tool = gso->brush->gpencil_sculpt_tool;
|
||||
GP_SpaceConversion *gsc = &gso->gsc;
|
||||
ToolSettings *ts = gso->scene->toolsettings;
|
||||
Brush *brush = gso->brush;
|
||||
const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
|
||||
gso->brush->size;
|
||||
const bool is_automasking = (brush->gpencil_settings->sculpt_mode_flag &
|
||||
(GP_SCULPT_FLAGMODE_AUTOMASK_STROKE |
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_LAYER |
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL)) != 0;
|
||||
const bool is_automasking = (ts->gp_sculpt.flag &
|
||||
(GP_SCULPT_SETT_FLAG_AUTOMASK_STROKE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_STROKE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_STROKE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_ACTIVE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_ACTIVE)) != 0;
|
||||
/* Calc bound box matrix. */
|
||||
float bound_mat[4][4];
|
||||
BKE_gpencil_layer_transform_matrix_get(gso->depsgraph, gso->object, gpl, bound_mat);
|
||||
|
@ -1743,27 +1755,111 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
|
|||
return changed;
|
||||
}
|
||||
|
||||
/* Find the stroke nearer to the brush. */
|
||||
static void get_nearest_stroke_to_brush(tGP_BrushEditData *gso,
|
||||
int mval_i[2],
|
||||
bGPDlayer **r_gpl,
|
||||
bGPDstroke **r_gps)
|
||||
{
|
||||
const int radius = SEARCH_RADIUS_PIXEL;
|
||||
|
||||
Object *ob_eval = gso->ob_eval;
|
||||
bGPdata *gpd = (bGPdata *)ob_eval->data;
|
||||
GP_SpaceConversion *gsc = &gso->gsc;
|
||||
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
||||
float dist = FLT_MAX;
|
||||
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
if (!BKE_gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
|
||||
continue;
|
||||
}
|
||||
/* Calculate bound box matrix. */
|
||||
float bound_mat[4][4];
|
||||
BKE_gpencil_layer_transform_matrix_get(gso->depsgraph, gso->object, gpl, bound_mat);
|
||||
|
||||
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
||||
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
|
||||
if (gps->totpoints == 0) {
|
||||
continue;
|
||||
}
|
||||
/* Check if the color is editable. */
|
||||
if (ED_gpencil_stroke_material_editable(gso->object, gpl, gps) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if the stroke collide with brush. */
|
||||
if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bGPDspoint *pt;
|
||||
int pc2D[2] = {0};
|
||||
bGPDspoint npt;
|
||||
|
||||
for (int i = 0; i < gps->totpoints; i++) {
|
||||
pt = gps->points + i;
|
||||
gpencil_point_to_world_space(pt, bound_mat, &npt);
|
||||
gpencil_point_to_xy(gsc, gps, &npt, &pc2D[0], &pc2D[1]);
|
||||
float d = len_v2v2_int(mval_i, pc2D);
|
||||
if (d < dist) {
|
||||
dist = d;
|
||||
*r_gpl = gpl;
|
||||
*r_gps = gps_active;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If not multi-edit, exit loop. */
|
||||
if (!is_multiedit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get list of Auto-Masking strokes. */
|
||||
static bool get_automasking_strokes_list(tGP_BrushEditData *gso)
|
||||
{
|
||||
bGPdata *gpd = gso->gpd;
|
||||
Object *ob_eval = gso->ob_eval;
|
||||
bGPdata *gpd = (bGPdata *)ob_eval->data;
|
||||
GP_SpaceConversion *gsc = &gso->gsc;
|
||||
Brush *brush = gso->brush;
|
||||
ToolSettings *ts = gso->scene->toolsettings;
|
||||
Object *ob = gso->object;
|
||||
Material *mat_active = BKE_gpencil_material(ob, ob->actcol);
|
||||
const eGP_Sculpt_SettingsFlag flag = ts->gp_sculpt.flag;
|
||||
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
||||
const bool is_masking_stroke = (brush->gpencil_settings->sculpt_mode_flag &
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_STROKE) != 0;
|
||||
const bool is_masking_layer = (brush->gpencil_settings->sculpt_mode_flag &
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_LAYER) != 0;
|
||||
const bool is_masking_material = (brush->gpencil_settings->sculpt_mode_flag &
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL) != 0;
|
||||
const bool is_masking_stroke = (flag & GP_SCULPT_SETT_FLAG_AUTOMASK_STROKE) != 0;
|
||||
const bool is_masking_layer_stroke = (flag & GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_STROKE) != 0;
|
||||
const bool is_masking_material_stroke = (flag & GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_STROKE) !=
|
||||
0;
|
||||
const bool is_masking_layer_active = (flag & GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_ACTIVE) != 0;
|
||||
const bool is_masking_material_active = (flag & GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_ACTIVE) !=
|
||||
0;
|
||||
int mval_i[2];
|
||||
round_v2i_v2fl(mval_i, gso->mval);
|
||||
|
||||
/* Define a fix number of pixel as cursor radius. */
|
||||
const int radius = 10;
|
||||
const int radius = SEARCH_RADIUS_PIXEL;
|
||||
bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
|
||||
Material *mat_active = BKE_gpencil_material(ob, ob->actcol);
|
||||
|
||||
/* By default use active values. */
|
||||
bGPDlayer *gpl_active_stroke = gpl_active;
|
||||
Material *mat_active_stroke = mat_active;
|
||||
/* Find nearest stroke to find the layer and material. */
|
||||
if (is_masking_layer_stroke || is_masking_material_stroke) {
|
||||
bGPDlayer *gpl_near = NULL;
|
||||
bGPDstroke *gps_near = NULL;
|
||||
get_nearest_stroke_to_brush(gso, mval_i, &gpl_near, &gps_near);
|
||||
if (gps_near != NULL) {
|
||||
if (is_masking_layer_stroke) {
|
||||
gpl_active_stroke = gpl_near;
|
||||
}
|
||||
if (is_masking_material_stroke) {
|
||||
mat_active_stroke = BKE_object_material_get(ob, gps_near->mat_nr + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
/* Only editable and visible layers are considered. */
|
||||
|
@ -1777,87 +1873,113 @@ static bool get_automasking_strokes_list(tGP_BrushEditData *gso)
|
|||
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
||||
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
|
||||
bool pick_stroke = false;
|
||||
bool pick_layer_stroke = false;
|
||||
bool pick_material_stroke = false;
|
||||
bool pick_layer_active = false;
|
||||
bool pick_material_active = false;
|
||||
|
||||
if (gps->totpoints == 0) {
|
||||
continue;
|
||||
}
|
||||
/* Check if the color is editable. */
|
||||
/* Check if the material is editable. */
|
||||
if (ED_gpencil_stroke_material_editable(gso->object, gpl, gps) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Layer Auto-Masking. */
|
||||
if ((is_masking_layer) && (gpl == gpl_active)) {
|
||||
BLI_ghash_insert(gso->automasking_strokes, gps, gps);
|
||||
continue;
|
||||
/* Stroke Layer Auto-Masking. */
|
||||
if (is_masking_layer_stroke && (gpl == gpl_active_stroke)) {
|
||||
pick_layer_stroke = true;
|
||||
}
|
||||
/* Material Auto-Masking. */
|
||||
if (is_masking_material) {
|
||||
/* Active Layer Auto-Masking. */
|
||||
if (is_masking_layer_active && (gpl == gpl_active)) {
|
||||
pick_layer_active = true;
|
||||
}
|
||||
/* Stroke Material Auto-Masking. */
|
||||
if (is_masking_material_stroke) {
|
||||
Material *mat = BKE_object_material_get(ob, gps->mat_nr + 1);
|
||||
if (mat == mat_active) {
|
||||
BLI_ghash_insert(gso->automasking_strokes, gps, gps);
|
||||
continue;
|
||||
if (mat == mat_active_stroke) {
|
||||
pick_material_stroke = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If Stroke Auto-Masking is not enabled, nothing else to do. */
|
||||
if (!is_masking_stroke) {
|
||||
continue;
|
||||
/* Active Material Auto-Masking. */
|
||||
if (is_masking_material_active) {
|
||||
Material *mat = BKE_object_material_get(ob, gps->mat_nr + 1);
|
||||
if (mat == mat_active) {
|
||||
pick_material_active = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the stroke collide with brush. */
|
||||
if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) {
|
||||
if ((is_masking_stroke) &&
|
||||
ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) {
|
||||
|
||||
bGPDspoint *pt1, *pt2;
|
||||
int pc1[2] = {0};
|
||||
int pc2[2] = {0};
|
||||
bGPDspoint npt;
|
||||
|
||||
if (gps->totpoints == 1) {
|
||||
gpencil_point_to_world_space(gps->points, bound_mat, &npt);
|
||||
gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
|
||||
|
||||
/* Only check if point is inside. */
|
||||
if (len_v2v2_int(mval_i, pc1) <= radius) {
|
||||
pick_stroke = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Loop over the points in the stroke, checking for intersections
|
||||
* - an intersection means that we touched the stroke.
|
||||
*/
|
||||
for (int i = 0; (i + 1) < gps->totpoints && !pick_stroke; i++) {
|
||||
/* Get points to work with. */
|
||||
pt1 = gps->points + i;
|
||||
pt2 = gps->points + i + 1;
|
||||
|
||||
/* Check first point. */
|
||||
gpencil_point_to_world_space(pt1, bound_mat, &npt);
|
||||
gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
|
||||
if (len_v2v2_int(mval_i, pc1) <= radius) {
|
||||
pick_stroke = true;
|
||||
i = gps->totpoints;
|
||||
}
|
||||
|
||||
/* Check second point. */
|
||||
gpencil_point_to_world_space(pt2, bound_mat, &npt);
|
||||
gpencil_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]);
|
||||
if (len_v2v2_int(mval_i, pc2) <= radius) {
|
||||
pick_stroke = true;
|
||||
i = gps->totpoints;
|
||||
}
|
||||
|
||||
/* Check segment. */
|
||||
if (!pick_stroke && gpencil_stroke_inside_circle(
|
||||
gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
|
||||
pick_stroke = true;
|
||||
i = gps->totpoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if the stroke meets all the masking conditions, add to the hash table. */
|
||||
if (is_masking_stroke && !pick_stroke) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bGPDspoint *pt1, *pt2;
|
||||
int pc1[2] = {0};
|
||||
int pc2[2] = {0};
|
||||
bGPDspoint npt;
|
||||
|
||||
if (gps->totpoints == 1) {
|
||||
gpencil_point_to_world_space(gps->points, bound_mat, &npt);
|
||||
gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
|
||||
|
||||
/* Only check if point is inside. */
|
||||
if (len_v2v2_int(mval_i, pc1) <= radius) {
|
||||
BLI_ghash_insert(gso->automasking_strokes, gps, gps);
|
||||
}
|
||||
if (is_masking_layer_stroke && !pick_layer_stroke) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
/* Loop over the points in the stroke, checking for intersections
|
||||
* - an intersection means that we touched the stroke.
|
||||
*/
|
||||
for (int i = 0; (i + 1) < gps->totpoints; i++) {
|
||||
/* Get points to work with. */
|
||||
pt1 = gps->points + i;
|
||||
pt2 = gps->points + i + 1;
|
||||
|
||||
/* Check first point. */
|
||||
gpencil_point_to_world_space(pt1, bound_mat, &npt);
|
||||
gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
|
||||
if (len_v2v2_int(mval_i, pc1) <= radius) {
|
||||
BLI_ghash_insert(gso->automasking_strokes, gps, gps);
|
||||
i = gps->totpoints;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check second point. */
|
||||
gpencil_point_to_world_space(pt2, bound_mat, &npt);
|
||||
gpencil_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]);
|
||||
if (len_v2v2_int(mval_i, pc2) <= radius) {
|
||||
BLI_ghash_insert(gso->automasking_strokes, gps, gps);
|
||||
i = gps->totpoints;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check segment. */
|
||||
if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
|
||||
BLI_ghash_insert(gso->automasking_strokes, gps, gps);
|
||||
i = gps->totpoints;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (is_masking_material_stroke && !pick_material_stroke) {
|
||||
continue;
|
||||
}
|
||||
if (is_masking_layer_active && !pick_layer_active) {
|
||||
continue;
|
||||
}
|
||||
if (is_masking_material_active && !pick_material_active) {
|
||||
continue;
|
||||
}
|
||||
BLI_ghash_insert(gso->automasking_strokes, gps_active, gps_active);
|
||||
}
|
||||
/* If not multi-edit, exit loop. */
|
||||
if (!is_multiedit) {
|
||||
|
@ -1877,7 +1999,7 @@ static bool gpencil_sculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *
|
|||
Object *obact = gso->object;
|
||||
bool changed = false;
|
||||
|
||||
Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obact->id);
|
||||
Object *ob_eval = gso->ob_eval;
|
||||
bGPdata *gpd = (bGPdata *)ob_eval->data;
|
||||
|
||||
/* Calculate brush-specific data which applies equally to all points */
|
||||
|
@ -1971,6 +2093,7 @@ static void gpencil_sculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *
|
|||
{
|
||||
tGP_BrushEditData *gso = op->customdata;
|
||||
Brush *brush = gso->brush;
|
||||
ToolSettings *ts = gso->scene->toolsettings;
|
||||
const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
|
||||
gso->brush->size;
|
||||
float mousef[2];
|
||||
|
@ -2012,9 +2135,10 @@ static void gpencil_sculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *
|
|||
|
||||
/* Get list of Auto-Masking strokes. */
|
||||
if ((!gso->automasking_ready) &&
|
||||
(brush->gpencil_settings->sculpt_mode_flag &
|
||||
(GP_SCULPT_FLAGMODE_AUTOMASK_STROKE | GP_SCULPT_FLAGMODE_AUTOMASK_LAYER |
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL))) {
|
||||
(ts->gp_sculpt.flag &
|
||||
(GP_SCULPT_SETT_FLAG_AUTOMASK_STROKE | GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_STROKE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_STROKE | GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_ACTIVE |
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_ACTIVE))) {
|
||||
gso->automasking_ready = get_automasking_strokes_list(gso);
|
||||
}
|
||||
|
||||
|
@ -2082,20 +2206,6 @@ static void gpencil_sculpt_brush_apply_event(bContext *C, wmOperator *op, const
|
|||
if (gso->brush == NULL) {
|
||||
gso->brush = gso->brush_prev;
|
||||
}
|
||||
Brush *brush = gso->brush;
|
||||
if (brush->gpencil_settings->sculpt_mode_flag &
|
||||
(GP_SCULPT_FLAGMODE_AUTOMASK_STROKE | GP_SCULPT_FLAGMODE_AUTOMASK_LAYER |
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL)) {
|
||||
if (gso->automasking_strokes == NULL) {
|
||||
gso->automasking_strokes = BLI_ghash_ptr_new(__func__);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gso->automasking_strokes != NULL) {
|
||||
BLI_ghash_free(gso->automasking_strokes, NULL, NULL);
|
||||
}
|
||||
gso->automasking_strokes = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gso->brush_prev != NULL) {
|
||||
|
|
|
@ -315,12 +315,6 @@ typedef enum eGP_Sculpt_Mode_Flag {
|
|||
GP_SCULPT_FLAGMODE_APPLY_THICKNESS = (1 << 2),
|
||||
/* apply brush to uv data */
|
||||
GP_SCULPT_FLAGMODE_APPLY_UV = (1 << 3),
|
||||
/* Stroke Auto-Masking for sculpt. */
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_STROKE = (1 << 4),
|
||||
/* Layer Auto-Masking for sculpt. */
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_LAYER = (1 << 5),
|
||||
/* Material Auto-Masking for sculpt. */
|
||||
GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL = (1 << 6),
|
||||
} eGP_Sculpt_Mode_Flag;
|
||||
|
||||
typedef enum eAutomasking_flag {
|
||||
|
|
|
@ -1155,6 +1155,16 @@ typedef enum eGP_Sculpt_SettingsFlag {
|
|||
GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE = (1 << 1),
|
||||
/** Scale thickness. */
|
||||
GP_SCULPT_SETT_FLAG_SCALE_THICKNESS = (1 << 3),
|
||||
/* Stroke Auto-Masking for sculpt. */
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_STROKE = (1 << 4),
|
||||
/* Stroke Layer Auto-Masking for sculpt. */
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_STROKE = (1 << 5),
|
||||
/* Stroke Material Auto-Masking for sculpt. */
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_STROKE = (1 << 6),
|
||||
/* Active Layer Auto-Masking for sculpt. */
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_ACTIVE = (1 << 7),
|
||||
/* Active Material Auto-Masking for sculpt. */
|
||||
GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_ACTIVE = (1 << 8),
|
||||
} eGP_Sculpt_SettingsFlag;
|
||||
|
||||
/** #GP_Sculpt_Settings.gpencil_selectmode_sculpt */
|
||||
|
|
|
@ -1919,26 +1919,6 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
|
|||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_automasking_stroke", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, NULL, "sculpt_mode_flag", GP_SCULPT_FLAGMODE_AUTOMASK_STROKE);
|
||||
RNA_def_property_ui_text(prop, "Auto-Masking Strokes", "Mask strokes below brush cursor");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_automasking_layer", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "sculpt_mode_flag", GP_SCULPT_FLAGMODE_AUTOMASK_LAYER);
|
||||
RNA_def_property_ui_text(prop, "Auto-Masking Layer", "Mask strokes using active layer");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_automasking_material", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, NULL, "sculpt_mode_flag", GP_SCULPT_FLAGMODE_AUTOMASK_MATERIAL);
|
||||
RNA_def_property_ui_text(prop, "Auto-Masking Material", "Mask strokes using active material");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
/* Material */
|
||||
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Material");
|
||||
|
|
|
@ -1638,6 +1638,36 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna)
|
|||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_automasking_stroke", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_AUTOMASK_STROKE);
|
||||
RNA_def_property_ui_text(prop, "Auto-Masking Strokes", "Affect only strokes below the cursor");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_automasking_layer_stroke", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_STROKE);
|
||||
RNA_def_property_ui_text(prop, "Auto-Masking Layer", "Affect only strokes below the cursor");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_automasking_material_stroke", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_STROKE);
|
||||
RNA_def_property_ui_text(prop, "Auto-Masking Material", "Affect only strokes below the cursor");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_automasking_layer_active", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_ACTIVE);
|
||||
RNA_def_property_ui_text(prop, "Auto-Masking Layer", "Affect only the Active Layer");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_automasking_material_active", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_ACTIVE);
|
||||
RNA_def_property_ui_text(prop, "Auto-Masking Material", "Affect only the Active Material");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
/* custom falloff curve */
|
||||
prop = RNA_def_property(srna, "multiframe_falloff_curve", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "cur_falloff");
|
||||
|
|
Loading…
Reference in New Issue