Compare commits
27 Commits
temp-ui-cp
...
temp-gpenc
Author | SHA1 | Date | |
---|---|---|---|
aa9b976e9f | |||
410b87ca78 | |||
2b9994257f | |||
a035861d9d | |||
8712f952e0 | |||
28de4468d9 | |||
9c717dcff8 | |||
2c3ee8854f | |||
e3ab75d17d | |||
67e053b1fb | |||
3150277d0c | |||
7437b6b4bc | |||
0dd98c54b9 | |||
910b579aff | |||
f1dbbbbd45 | |||
101819bdf9 | |||
62b29f71b9 | |||
3d2dc8c897 | |||
3ebd01675e | |||
9b24e5d54f | |||
535662cd0d | |||
dc6281d87f | |||
ad87f81e38 | |||
8965118eec | |||
71e26f6eff | |||
1e286d7f8f | |||
2ec1e38b91 |
@@ -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");
|
||||
|
Reference in New Issue
Block a user