From 86755334483960679b1d262611d60d0b64b3c5d2 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Fri, 11 Oct 2024 12:31:23 -0700 Subject: [PATCH 1/3] Fix #128868: Hide Sharp Corners in Docking Split While splitting areas the two parts are shown with rounded outlines, but some of the underlying content can show through in the corners, spoiling the effect. This PR just erases anything in those corners, making it look cleaner and rounder. Accidentally merged to main first with c3ea941273. --- source/blender/editors/screen/screen_draw.cc | 82 ++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/source/blender/editors/screen/screen_draw.cc b/source/blender/editors/screen/screen_draw.cc index 2a7fa291250..a15abe658dc 100644 --- a/source/blender/editors/screen/screen_draw.cc +++ b/source/blender/editors/screen/screen_draw.cc @@ -450,6 +450,73 @@ void screen_draw_join_highlight(const wmWindow *win, ScrArea *sa1, ScrArea *sa2, win->eventstate->xy[0], win->eventstate->xy[1], sa1, IFACE_("Join Areas")); } +static void rounded_corners(rctf rect, float color[4], int corners) +{ + GPUVertFormat *format = immVertexFormat(); + const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + const float rad = 7 * U.pixelsize; + + float vec[4][2] = { + {0.195, 0.02}, + {0.55, 0.169}, + {0.831, 0.45}, + {0.98, 0.805}, + }; + for (int a = 0; a < 4; a++) { + mul_v2_fl(vec[a], rad); + } + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(color); + + if (corners & UI_CNR_TOP_LEFT) { + immBegin(GPU_PRIM_TRI_FAN, 7); + immVertex2f(pos, rect.xmin - 1, rect.ymax); + immVertex2f(pos, rect.xmin, rect.ymax - rad); + for (int a = 0; a < 4; a++) { + immVertex2f(pos, rect.xmin + vec[a][1], rect.ymax - rad + vec[a][0]); + } + immVertex2f(pos, rect.xmin + rad, rect.ymax); + immEnd(); + } + + if (corners & UI_CNR_TOP_RIGHT) { + immBegin(GPU_PRIM_TRI_FAN, 7); + immVertex2f(pos, rect.xmax + 1, rect.ymax); + immVertex2f(pos, rect.xmax - rad, rect.ymax); + for (int a = 0; a < 4; a++) { + immVertex2f(pos, rect.xmax - rad + vec[a][0], rect.ymax - vec[a][1]); + } + immVertex2f(pos, rect.xmax, rect.ymax - rad); + immEnd(); + } + + if (corners & UI_CNR_BOTTOM_RIGHT) { + immBegin(GPU_PRIM_TRI_FAN, 7); + immVertex2f(pos, rect.xmax + 1, rect.ymin); + immVertex2f(pos, rect.xmax, rect.ymin + rad); + for (int a = 0; a < 4; a++) { + immVertex2f(pos, rect.xmax - vec[a][1], rect.ymin + rad - vec[a][0]); + } + immVertex2f(pos, rect.xmax - rad, rect.ymin); + immEnd(); + } + + if (corners & UI_CNR_BOTTOM_LEFT) { + immBegin(GPU_PRIM_TRI_FAN, 7); + immVertex2f(pos, rect.xmin - 1, rect.ymin); + immVertex2f(pos, rect.xmin + rad, rect.ymin); + for (int a = 0; a < 4; a++) { + immVertex2f(pos, rect.xmin + rad - vec[a][0], rect.ymin + vec[a][1]); + } + immVertex2f(pos, rect.xmin, rect.ymin + rad); + immEnd(); + } + + immUnbindProgram(); +} + void screen_draw_dock_preview( ScrArea *source, ScrArea *target, AreaDockTarget dock_target, float factor, int x, int y) { @@ -470,32 +537,38 @@ void screen_draw_dock_preview( BLI_rctf_rcti_copy(&remainder, &target->totrct); float split; + int corners = UI_CNR_NONE; if (dock_target == AreaDockTarget::Right) { split = std::min(dest.xmin + target->winx * (1.0f - factor), dest.xmax - AREAMINX * UI_SCALE_FAC); dest.xmin = split + half_line_width; remainder.xmax = split - half_line_width; + corners = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT; } else if (dock_target == AreaDockTarget::Left) { split = std::max(dest.xmax - target->winx * (1.0f - factor), dest.xmin + AREAMINX * UI_SCALE_FAC); dest.xmax = split - half_line_width; remainder.xmin = split + half_line_width; + corners = UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT; } else if (dock_target == AreaDockTarget::Top) { split = std::min(dest.ymin + target->winy * (1.0f - factor), dest.ymax - HEADERY * UI_SCALE_FAC); dest.ymin = split + half_line_width; remainder.ymax = split - half_line_width; + corners = UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT; } else if (dock_target == AreaDockTarget::Bottom) { split = std::max(dest.ymax - target->winy * (1.0f - factor), dest.ymin + HEADERY * UI_SCALE_FAC); dest.ymax = split - half_line_width; remainder.ymin = split + half_line_width; + corners = UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT; } + rounded_corners(dest, border, corners); UI_draw_roundbox_4fv_ex(&dest, inner, nullptr, 1.0f, outline, U.pixelsize, 6 * U.pixelsize); if (dock_target != AreaDockTarget::Center) { @@ -545,6 +618,10 @@ void screen_draw_split_preview(ScrArea *area, const eScreenAxis dir_axis, const rect.xmax = (dir_axis == SCREEN_AXIS_V) ? x - half_line_width : rect.xmax; rect.ymax = (dir_axis == SCREEN_AXIS_H) ? y - half_line_width : rect.ymax; + rounded_corners(rect, + border, + (dir_axis == SCREEN_AXIS_H) ? UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT : + UI_CNR_BOTTOM_RIGHT | UI_CNR_TOP_RIGHT); UI_draw_roundbox_4fv_ex(&rect, inner, nullptr, 1.0f, outline, U.pixelsize, 7 * U.pixelsize); /* Outlined rectangle to right/below split position. */ @@ -556,6 +633,11 @@ void screen_draw_split_preview(ScrArea *area, const eScreenAxis dir_axis, const rect.xmin = x + half_line_width; rect.xmax = area->totrct.xmax; } + + rounded_corners(rect, + border, + (dir_axis == SCREEN_AXIS_H) ? UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT : + UI_CNR_BOTTOM_LEFT | UI_CNR_TOP_LEFT); UI_draw_roundbox_4fv_ex(&rect, inner, nullptr, 1.0f, outline, U.pixelsize, 7 * U.pixelsize); /* Darken the split position itself. */ From d17738897979baac2b16acf3d35bb4b436f624ec Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 11 Oct 2024 22:08:14 +0200 Subject: [PATCH 2/3] Sculpt/Paint: Tag brushes for unsaved changes for UI indication Part of the brush assets project followups, see #116337. Based on feedback, it seems important to indicate to the user when a brush has unsaved changes. There's no reliable updating mechanism we can use or hook into here, except for RNA "update" callbacks. Brush data gets changed in many places in code, the only way to do this seems manual tagging every time a brush property gets changed. This PR introduces `BKE_brush_tag_unsaved_changes()` for this. I spent some time going through all brush properties to ensure changes call the tagging function. A known limitation with this will be that changes to dependencies won't be indicated in the brush. E.g. Changing the texture attached to a brush won't make the brush be indicated as changed. The UI to indicate the changed brushes is being discussed still, see #128846. Pull Request: https://projects.blender.org/blender/blender/pulls/128845 --- .../startup/bl_ui/properties_paint_common.py | 22 ++- source/blender/blenkernel/BKE_brush.hh | 13 ++ source/blender/blenkernel/intern/brush.cc | 16 ++ .../blenkernel/intern/gpencil_legacy.cc | 2 + source/blender/blenkernel/intern/texture.cc | 2 + .../intern/grease_pencil_weight_paint.cc | 1 + .../eyedropper_grease_pencil_color.cc | 2 + .../editors/interface/interface_handlers.cc | 1 + .../blender/editors/render/render_update.cc | 4 + .../editors/sculpt_paint/brush_asset_ops.cc | 2 + .../editors/sculpt_paint/curves_sculpt_ops.cc | 1 + .../sculpt_paint/grease_pencil_draw_ops.cc | 3 +- .../editors/sculpt_paint/paint_curve.cc | 5 + .../editors/sculpt_paint/paint_image.cc | 3 + .../blender/editors/sculpt_paint/paint_ops.cc | 7 + .../editors/sculpt_paint/paint_utils.cc | 1 + .../transform/transform_convert_paintcurve.cc | 7 + .../editors/transform/transform_generics.cc | 2 + source/blender/makesdna/DNA_brush_types.h | 10 +- source/blender/makesrna/intern/rna_brush.cc | 179 +++++++++++++----- source/blender/makesrna/intern/rna_texture.cc | 2 + 21 files changed, 234 insertions(+), 51 deletions(-) diff --git a/scripts/startup/bl_ui/properties_paint_common.py b/scripts/startup/bl_ui/properties_paint_common.py index 0647ea7cd90..bc08fdfe284 100644 --- a/scripts/startup/bl_ui/properties_paint_common.py +++ b/scripts/startup/bl_ui/properties_paint_common.py @@ -136,9 +136,13 @@ class BrushAssetShelf: if not shelf_name: return + display_name = brush.name if (brush and show_name) else None + if display_name and brush.has_unsaved_changes: + display_name = display_name + "*" + layout.template_asset_shelf_popover( shelf_name, - name=brush.name if (brush and show_name) else None, + name=display_name, icon='BRUSH_DATA' if not preview_icon_id else 'NONE', icon_value=preview_icon_id, ) @@ -302,6 +306,22 @@ class BrushPanel(UnifiedPaintPanel): class BrushSelectPanel(BrushPanel): bl_label = "Brush Asset" + # Use header preset function to right align the layout. + def draw_header_preset(self, context): + layout = self.layout + + settings = self.paint_settings(context) + if settings is None: + return + + brush = settings.brush + if brush is None: + return + + if brush.has_unsaved_changes and bpy.ops.brush.asset_update.poll(): + layout.label(text="*Unsaved Changes") + layout.separator() + def draw(self, context): layout = self.layout settings = self.paint_settings(context) diff --git a/source/blender/blenkernel/BKE_brush.hh b/source/blender/blenkernel/BKE_brush.hh index 501fd1002be..f867c754841 100644 --- a/source/blender/blenkernel/BKE_brush.hh +++ b/source/blender/blenkernel/BKE_brush.hh @@ -50,6 +50,19 @@ void BKE_brush_init_gpencil_settings(Brush *brush); void BKE_brush_init_curves_sculpt_settings(Brush *brush); +/** + * Tag a linked brush as having changed settings so an indicator can be displayed to the user, + * showing that the brush settings differ from the state of the imported brush asset. Call + * everytime a user visible change to the brush is done. + * + * Since this is meant to indicate brushes that are known to differ from the linked source file, + * tagging is only performed for linked brushes. File local brushes are normal data-blocks that get + * saved with the file, and don't need special attention by the user. + * + * For convenience, null may be passed for \a brush. + */ +void BKE_brush_tag_unsaved_changes(Brush *brush); + Brush *BKE_brush_first_search(Main *bmain, eObjectMode ob_mode); void BKE_brush_jitter_pos(const Scene &scene, diff --git a/source/blender/blenkernel/intern/brush.cc b/source/blender/blenkernel/intern/brush.cc index 7b650472108..e5d88344455 100644 --- a/source/blender/blenkernel/intern/brush.cc +++ b/source/blender/blenkernel/intern/brush.cc @@ -10,6 +10,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_ID.h" #include "DNA_brush_types.h" #include "DNA_defaults.h" #include "DNA_material_types.h" @@ -364,6 +365,7 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id) BKE_previewimg_blend_read(reader, brush->preview); brush->icon_imbuf = nullptr; + brush->has_unsaved_changes = false; } static void brush_blend_read_after_liblink(BlendLibReader * /*reader*/, ID *id) @@ -616,6 +618,13 @@ void BKE_brush_init_curves_sculpt_settings(Brush *brush) settings->curve_parameter_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); } +void BKE_brush_tag_unsaved_changes(Brush *brush) +{ + if (brush && ID_IS_LINKED(brush)) { + brush->has_unsaved_changes = true; + } +} + Brush *BKE_brush_first_search(Main *bmain, const eObjectMode ob_mode) { LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { @@ -747,6 +756,7 @@ void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset) cuma = b->curve->cm; BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_NEGATIVE); BKE_curvemapping_changed(cumap, false); + BKE_brush_tag_unsaved_changes(b); } const MTex *BKE_brush_mask_texture_get(const Brush *brush, const eObjectMode object_mode) @@ -1037,6 +1047,7 @@ void BKE_brush_color_set(Scene *scene, Brush *brush, const float color[3]) } else { copy_v3_v3(brush->rgb, color); + BKE_brush_tag_unsaved_changes(brush); } } @@ -1052,6 +1063,7 @@ void BKE_brush_size_set(Scene *scene, Brush *brush, int size) } else { brush->size = size; + BKE_brush_tag_unsaved_changes(brush); } } @@ -1109,6 +1121,7 @@ void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojec } else { brush->unprojected_radius = unprojected_radius; + BKE_brush_tag_unsaved_changes(brush); } } @@ -1128,6 +1141,7 @@ void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha) } else { brush->alpha = alpha; + BKE_brush_tag_unsaved_changes(brush); } } @@ -1154,6 +1168,7 @@ void BKE_brush_weight_set(const Scene *scene, Brush *brush, float value) } else { brush->weight = value; + BKE_brush_tag_unsaved_changes(brush); } } @@ -1173,6 +1188,7 @@ void BKE_brush_input_samples_set(const Scene *scene, Brush *brush, int value) } else { brush->input_samples = value; + BKE_brush_tag_unsaved_changes(brush); } } diff --git a/source/blender/blenkernel/intern/gpencil_legacy.cc b/source/blender/blenkernel/intern/gpencil_legacy.cc index 1992bc15b38..5a34f507391 100644 --- a/source/blender/blenkernel/intern/gpencil_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_legacy.cc @@ -36,6 +36,7 @@ #include "BKE_action.hh" #include "BKE_anim_data.hh" +#include "BKE_brush.hh" #include "BKE_collection.hh" #include "BKE_colortools.hh" #include "BKE_deform.hh" @@ -1370,6 +1371,7 @@ void BKE_gpencil_brush_material_set(Brush *brush, Material *ma) id_us_plus(&ma->id); } brush->gpencil_settings->material = ma; + BKE_brush_tag_unsaved_changes(brush); } } diff --git a/source/blender/blenkernel/intern/texture.cc b/source/blender/blenkernel/intern/texture.cc index b439032a31b..75c17b1e4df 100644 --- a/source/blender/blenkernel/intern/texture.cc +++ b/source/blender/blenkernel/intern/texture.cc @@ -36,6 +36,7 @@ #include "DNA_object_types.h" #include "DNA_particle_types.h" +#include "BKE_brush.hh" #include "BKE_colorband.hh" #include "BKE_colortools.hh" #include "BKE_icons.h" @@ -551,6 +552,7 @@ void set_current_brush_texture(Brush *br, Tex *newtex) br->mtex.tex = newtex; id_us_plus(&newtex->id); } + BKE_brush_tag_unsaved_changes(br); } Tex *give_current_particle_texture(ParticleSettings *part) diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_weight_paint.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_weight_paint.cc index 7ccf7bf2994..dffbbc5b58e 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_weight_paint.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_weight_paint.cc @@ -567,6 +567,7 @@ static int toggle_weight_tool_direction(bContext *C, wmOperator * /*op*/) /* Toggle direction flag. */ brush->flag ^= BRUSH_DIR_IN; + BKE_brush_tag_unsaved_changes(brush); /* Update brush settings in UI. */ WM_main_add_notifier(NC_BRUSH | NA_EDITED, nullptr); diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_grease_pencil_color.cc b/source/blender/editors/interface/eyedroppers/eyedropper_grease_pencil_color.cc index 7e4967e2a67..3a038ba6a17 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_grease_pencil_color.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_grease_pencil_color.cc @@ -23,6 +23,7 @@ #include "DNA_material_types.h" #include "DNA_space_types.h" +#include "BKE_brush.hh" #include "BKE_context.hh" #include "BKE_grease_pencil.hh" #include "BKE_lib_id.hh" @@ -292,6 +293,7 @@ static void eyedropper_set_brush_color(bContext *C, const float3 &col_conv) } copy_v3_v3(brush->rgb, col_conv); + BKE_brush_tag_unsaved_changes(brush); } /* Set the material or the palette color. */ diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index 79b21ebe5a7..35fc30e2d79 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -6505,6 +6505,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) { RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target); } + BKE_brush_tag_unsaved_changes(brush); } else { Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/render/render_update.cc b/source/blender/editors/render/render_update.cc index 236f26a5bba..3f863101bab 100644 --- a/source/blender/editors/render/render_update.cc +++ b/source/blender/editors/render/render_update.cc @@ -27,6 +27,7 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BKE_brush.hh" #include "BKE_context.hh" #include "BKE_icons.h" #include "BKE_main.hh" @@ -337,6 +338,9 @@ void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id) case ID_SCE: scene_changed(bmain, (Scene *)id); break; + case ID_BR: + BKE_brush_tag_unsaved_changes(reinterpret_cast(id)); + break; default: break; } diff --git a/source/blender/editors/sculpt_paint/brush_asset_ops.cc b/source/blender/editors/sculpt_paint/brush_asset_ops.cc index 224bd48a06b..095a958d74f 100644 --- a/source/blender/editors/sculpt_paint/brush_asset_ops.cc +++ b/source/blender/editors/sculpt_paint/brush_asset_ops.cc @@ -272,6 +272,7 @@ static int brush_asset_save_as_exec(bContext *C, wmOperator *op) brush = reinterpret_cast( bke::asset_edit_id_from_weak_reference(*bmain, ID_BR, brush_asset_reference)); + brush->has_unsaved_changes = false; if (!WM_toolsystem_activate_brush_and_tool(C, paint, brush)) { /* Note brush asset was still saved in editable asset library, so was not a no-op. */ @@ -751,6 +752,7 @@ static int brush_asset_update_exec(bContext *C, wmOperator *op) BLI_assert(ID_IS_ASSET(brush)); bke::asset_edit_id_save(*bmain, brush->id, *op->reports); + brush->has_unsaved_changes = false; refresh_asset_library(C, *user_library); WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST | NA_EDITED, nullptr); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index 48c0fa719e5..254f9444f4f 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -1129,6 +1129,7 @@ static int min_distance_edit_modal(bContext *C, wmOperator *op, const wmEvent *e case LEFTMOUSE: { if (event->val == KM_PRESS) { finish(); + BKE_brush_tag_unsaved_changes(op_data.brush); return OPERATOR_FINISHED; } break; diff --git a/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc b/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc index 2ea0cebe5fe..fd0bbfb4cde 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc @@ -1354,7 +1354,7 @@ static bool grease_pencil_apply_fill(bContext &C, wmOperator &op, const wmEvent GreasePencil &grease_pencil = *static_cast(object.data); auto &op_data = *static_cast(op.customdata); const ToolSettings &ts = *CTX_data_tool_settings(&C); - const Brush &brush = *BKE_paint_brush(&ts.gp_paint->paint); + Brush &brush = *BKE_paint_brush(&ts.gp_paint->paint); const float2 mouse_position = float2(event.mval); const int simplify_levels = brush.gpencil_settings->fill_simplylvl; const std::optional alpha_threshold = @@ -1429,6 +1429,7 @@ static bool grease_pencil_apply_fill(bContext &C, wmOperator &op, const wmEvent /* Save extend value for next operation. */ brush.gpencil_settings->fill_extend_fac = op_data.extension_length; + BKE_brush_tag_unsaved_changes(&brush); return true; } diff --git a/source/blender/editors/sculpt_paint/paint_curve.cc b/source/blender/editors/sculpt_paint/paint_curve.cc index 0c4d9b929f3..f37a4cffe43 100644 --- a/source/blender/editors/sculpt_paint/paint_curve.cc +++ b/source/blender/editors/sculpt_paint/paint_curve.cc @@ -21,6 +21,7 @@ #include "BLT_translation.hh" +#include "BKE_brush.hh" #include "BKE_context.hh" #include "BKE_paint.hh" @@ -152,6 +153,7 @@ static int paintcurve_new_exec(bContext *C, wmOperator * /*op*/) if (brush) { brush->paint_curve = BKE_paint_curve_add(bmain, DATA_("PaintCurve")); + BKE_brush_tag_unsaved_changes(brush); } WM_event_add_notifier(C, NC_PAINTCURVE | NA_ADDED, nullptr); @@ -232,6 +234,7 @@ static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2]) } ED_paintcurve_undo_push_end(C); + BKE_brush_tag_unsaved_changes(br); WM_paint_cursor_tag_redraw(window, region); } @@ -344,6 +347,7 @@ static int paintcurve_delete_point_exec(bContext *C, wmOperator *op) #undef DELETE_TAG ED_paintcurve_undo_push_end(C); + BKE_brush_tag_unsaved_changes(br); WM_paint_cursor_tag_redraw(window, region); @@ -590,6 +594,7 @@ static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *e /* only select the active point */ PAINT_CURVE_POINT_SELECT(pcp, psd->select); BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points); + BKE_brush_tag_unsaved_changes(br); WM_event_add_modal_handler(C, op); WM_paint_cursor_tag_redraw(window, region); diff --git a/source/blender/editors/sculpt_paint/paint_image.cc b/source/blender/editors/sculpt_paint/paint_image.cc index 0a0db55bd26..77856691e0c 100644 --- a/source/blender/editors/sculpt_paint/paint_image.cc +++ b/source/blender/editors/sculpt_paint/paint_image.cc @@ -518,6 +518,7 @@ static void grab_clone_apply(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "delta", delta); add_v2_v2(brush->clone.offset, delta); + BKE_brush_tag_unsaved_changes(brush); ED_region_tag_redraw(CTX_wm_region(C)); } @@ -569,6 +570,7 @@ static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event) RNA_float_set_array(op->ptr, "delta", delta); copy_v2_v2(brush->clone.offset, cmv->startoffset); + BKE_brush_tag_unsaved_changes(brush); grab_clone_apply(C, op); break; @@ -1038,6 +1040,7 @@ static int brush_colors_flip_exec(bContext *C, wmOperator * /*op*/) } else if (br) { swap_v3_v3(br->rgb, br->secondary_rgb); + BKE_brush_tag_unsaved_changes(br); } else { return OPERATOR_CANCELLED; diff --git a/source/blender/editors/sculpt_paint/paint_ops.cc b/source/blender/editors/sculpt_paint/paint_ops.cc index c5b92a31661..2864dc8babb 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.cc +++ b/source/blender/editors/sculpt_paint/paint_ops.cc @@ -80,6 +80,7 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op) } else { brush->size = max_ii(size, 1); + BKE_brush_tag_unsaved_changes(brush); } } @@ -98,6 +99,7 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op) } else { brush->unprojected_radius = unprojected_radius; + BKE_brush_tag_unsaved_changes(brush); } } @@ -668,6 +670,7 @@ static void stencil_control_calculate(StencilControlData *scd, const int mval[2] CLAMP(scd->pos_target[1], -scd->dim_target[1] + PIXEL_MARGIN, scd->area_size[1] + scd->dim_target[1] - PIXEL_MARGIN); + BKE_brush_tag_unsaved_changes(scd->br); break; case STENCIL_SCALE: { @@ -684,6 +687,7 @@ static void stencil_control_calculate(StencilControlData *scd, const int mval[2] } clamp_v2(mdiff, 5.0f, 10000.0f); copy_v2_v2(scd->dim_target, mdiff); + BKE_brush_tag_unsaved_changes(scd->br); break; } case STENCIL_ROTATE: { @@ -698,6 +702,7 @@ static void stencil_control_calculate(StencilControlData *scd, const int mval[2] angle -= float(2 * M_PI); } *scd->rot_target = angle; + BKE_brush_tag_unsaved_changes(scd->br); break; } } @@ -860,6 +865,7 @@ static int stencil_fit_image_aspect_exec(bContext *C, wmOperator *op) br->stencil_dimension[0] = fabsf(factor * aspx); br->stencil_dimension[1] = fabsf(factor * aspy); } + BKE_brush_tag_unsaved_changes(br); } WM_event_add_notifier(C, NC_WINDOW, nullptr); @@ -917,6 +923,7 @@ static int stencil_reset_transform_exec(bContext *C, wmOperator *op) br->mtex.rot = 0; } + BKE_brush_tag_unsaved_changes(br); WM_event_add_notifier(C, NC_WINDOW, nullptr); return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/paint_utils.cc b/source/blender/editors/sculpt_paint/paint_utils.cc index 03f8200b27c..f6b992b361e 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.cc +++ b/source/blender/editors/sculpt_paint/paint_utils.cc @@ -526,6 +526,7 @@ static int brush_sculpt_curves_falloff_preset_exec(bContext *C, wmOperator *op) mapping->preset = RNA_enum_get(op->ptr, "shape"); CurveMap *map = mapping->cm; BKE_curvemap_reset(map, &mapping->clipr, mapping->preset, CURVEMAP_SLOPE_POSITIVE); + BKE_brush_tag_unsaved_changes(brush); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/transform/transform_convert_paintcurve.cc b/source/blender/editors/transform/transform_convert_paintcurve.cc index ea4f4df20ec..b89909cbf80 100644 --- a/source/blender/editors/transform/transform_convert_paintcurve.cc +++ b/source/blender/editors/transform/transform_convert_paintcurve.cc @@ -13,6 +13,7 @@ #include "BLI_math_matrix.h" #include "BLI_math_vector.h" +#include "BKE_brush.hh" #include "BKE_paint.hh" #include "transform.hh" @@ -203,6 +204,12 @@ static void flushTransPaintCurve(TransInfo *t) PaintCurvePoint *pcp = tdpc->pcp; copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc); } + + if (t->context) { + Paint *paint = BKE_paint_get_active_from_context(t->context); + Brush *br = (paint) ? BKE_paint_brush(paint) : nullptr; + BKE_brush_tag_unsaved_changes(br); + } } /** \} */ diff --git a/source/blender/editors/transform/transform_generics.cc b/source/blender/editors/transform/transform_generics.cc index 89bdeff534f..98e64d08b71 100644 --- a/source/blender/editors/transform/transform_generics.cc +++ b/source/blender/editors/transform/transform_generics.cc @@ -18,6 +18,7 @@ #include "RNA_access.hh" +#include "BKE_brush.hh" #include "BKE_context.hh" #include "BKE_layer.hh" #include "BKE_mask.h" @@ -1104,6 +1105,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) Brush *br = BKE_paint_brush(paint); PaintCurve *pc = br->paint_curve; copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]); + BKE_brush_tag_unsaved_changes(br); r_center[2] = 0.0f; return true; } diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 686ce4ce355..41c95189864 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -166,6 +166,10 @@ typedef struct BrushCurvesSculptSettings { /** Max number of propagation steps for automasking settings. */ #define AUTOMASKING_BOUNDARY_EDGES_MAX_PROPAGATION_STEPS 20 +/** + * \note Any change to members that is user visible and that may make the brush differ from the one + * saved in the asset library should be followed by a #BKE_brush_tag_unsaved_changes() call. + */ typedef struct Brush { DNA_DEFINE_CXX_METHODS(Brush) @@ -264,7 +268,11 @@ typedef struct Brush { /** Source for fill brush color gradient application. */ char gradient_fill_mode; - char _pad0; + /** + * Tag to indicate to the user that the brush has been changed since being imported. Only set for + * brushes that are actually imported (must have #ID.lib set). Runtime only. + */ + char has_unsaved_changes; /** Projection shape (sphere, circle). */ char falloff_shape; diff --git a/source/blender/makesrna/intern/rna_brush.cc b/source/blender/makesrna/intern/rna_brush.cc index f35cd095ee4..c92b998e9e8 100644 --- a/source/blender/makesrna/intern/rna_brush.cc +++ b/source/blender/makesrna/intern/rna_brush.cc @@ -714,12 +714,15 @@ static void rna_Brush_reset_icon(Brush *br) static void rna_Brush_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; + BKE_brush_tag_unsaved_changes(br); WM_main_add_notifier(NC_BRUSH | NA_EDITED, br); // WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, nullptr); } -static void rna_Brush_material_update(bContext * /*C*/, PointerRNA * /*ptr*/) +static void rna_Brush_material_update(bContext * /*C*/, PointerRNA *ptr) { + Brush *br = (Brush *)ptr->data; + BKE_brush_tag_unsaved_changes(br); /* number of material users changed */ WM_main_add_notifier(NC_SPACE | ND_SPACE_PROPERTIES, nullptr); } @@ -1025,6 +1028,12 @@ static std::optional rna_BrushGpencilSettings_path(const PointerRNA return "gpencil_settings"; } +static void rna_BrushGpencilSettings_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr) +{ + Brush *br = (Brush *)ptr->owner_id; + BKE_brush_tag_unsaved_changes(br); +} + static void rna_BrushGpencilSettings_use_material_pin_update(bContext *C, PointerRNA *ptr) { const Scene *scene = CTX_data_scene(C); @@ -1041,6 +1050,7 @@ static void rna_BrushGpencilSettings_use_material_pin_update(bContext *C, Pointe BKE_gpencil_brush_material_set(brush, nullptr); } + rna_BrushGpencilSettings_update(CTX_data_main(C), CTX_data_scene(C), ptr); /* number of material users changed */ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_PROPERTIES, nullptr); } @@ -1083,6 +1093,15 @@ static void rna_GPencilBrush_pin_mode_update(bContext *C, PointerRNA *ptr) GP_BRUSH_MODE_MATERIAL; } } + rna_BrushGpencilSettings_update(CTX_data_main(C), CTX_data_scene(C), ptr); +} + +static void rna_BrushCurvesSculptSettings_update(Main * /*bmain*/, + Scene * /*scene*/, + PointerRNA *ptr) +{ + Brush *br = (Brush *)ptr->owner_id; + BKE_brush_tag_unsaved_changes(br); } static const EnumPropertyItem *rna_BrushTextureSlot_map_mode_itemf(bContext *C, @@ -1382,7 +1401,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Strength", "Color strength for new strokes (affect alpha factor of color)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Jitter factor for new strokes */ prop = RNA_def_property(srna, "pen_jitter", PROP_FLOAT, PROP_FACTOR); @@ -1392,7 +1411,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Jitter", "Jitter factor of brush radius for new strokes"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_BRUSH); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Randomness factor for pressure */ prop = RNA_def_property(srna, "random_pressure", PROP_FLOAT, PROP_FACTOR); @@ -1401,7 +1420,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Pressure Randomness", "Randomness factor for pressure in new strokes"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Randomness factor for strength */ prop = RNA_def_property(srna, "random_strength", PROP_FLOAT, PROP_FACTOR); @@ -1410,7 +1429,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Strength Randomness", "Randomness factor strength in new strokes"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Angle when brush is full size */ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); @@ -1421,7 +1440,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Direction of the stroke at which brush gives maximal thickness " "(0" BLI_STR_UTF8_DEGREE_SIGN " for horizontal)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Factor to change brush size depending of angle */ prop = RNA_def_property(srna, "angle_factor", PROP_FLOAT, PROP_FACTOR); @@ -1432,7 +1451,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Angle Factor", "Reduce brush thickness by this factor when stroke is perpendicular to 'Angle' direction"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Smoothing factor for new strokes */ prop = RNA_def_property(srna, "pen_smooth_factor", PROP_FLOAT, PROP_NONE); @@ -1445,7 +1464,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Amount of smoothing to apply after finish newly created strokes, to reduce jitter/noise"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_AMOUNT); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Iterations of the Smoothing factor */ prop = RNA_def_property(srna, "pen_smooth_steps", PROP_INT, PROP_NONE); @@ -1453,7 +1472,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_text(prop, "Iterations", "Number of times to smooth newly created strokes"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Subdivision level for new strokes */ prop = RNA_def_property(srna, "pen_subdivision_steps", PROP_INT, PROP_NONE); @@ -1464,7 +1483,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Subdivision Steps", "Number of times to subdivide newly created strokes, for less jagged strokes"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Simplify factor */ prop = RNA_def_property(srna, "simplify_factor", PROP_FLOAT, PROP_NONE); @@ -1473,6 +1492,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0, 100.0, 1.0f, 3); RNA_def_property_ui_text(prop, "Simplify", "Factor of Simplify using adaptive algorithm"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "simplify_pixel_threshold", PROP_FLOAT, PROP_PIXEL); RNA_def_property_float_sdna(prop, nullptr, "simplify_px"); @@ -1484,6 +1504,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Threashold in screen space used for the simplify algorithm. Points within this threashold " "are treated as if they were in a straight line."); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); /* Curves for pressure */ prop = RNA_def_property(srna, "curve_sensitivity", PROP_POINTER, PROP_NONE); @@ -1491,63 +1512,63 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Curve Sensitivity", "Curve used for the sensitivity"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "curve_strength", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, nullptr, "curve_strength"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Curve Strength", "Curve used for the strength"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "curve_jitter", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, nullptr, "curve_jitter"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Curve Jitter", "Curve used for the jitter effect"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "curve_random_pressure", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, nullptr, "curve_rand_pressure"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "curve_random_strength", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, nullptr, "curve_rand_strength"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "curve_random_uv", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, nullptr, "curve_rand_uv"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "curve_random_hue", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, nullptr, "curve_rand_hue"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "curve_random_saturation", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, nullptr, "curve_rand_saturation"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "curve_random_value", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, nullptr, "curve_rand_value"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Fill threshold for transparency. */ prop = RNA_def_property(srna, "fill_threshold", PROP_FLOAT, PROP_FACTOR); @@ -1556,7 +1577,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Threshold", "Threshold to consider color transparent for filling"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* fill factor size */ prop = RNA_def_property(srna, "fill_factor", PROP_FLOAT, PROP_NONE); @@ -1567,7 +1588,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Precision", "Factor for fill boundary accuracy, higher values are more accurate but slower"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* fill simplify steps */ prop = RNA_def_property(srna, "fill_simplify_level", PROP_INT, PROP_NONE); @@ -1576,14 +1597,14 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Simplify", "Number of simplify steps (large values reduce fill accuracy)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "uv_random", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, nullptr, "uv_random"); RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_ui_text(prop, "UV Random", "Random factor for auto-generated UV rotation"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* gradient control */ prop = RNA_def_property(srna, "hardness", PROP_FLOAT, PROP_FACTOR); @@ -1595,6 +1616,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Hardness", "Gradient from the center of Dot and Box strokes (set to 1 for a solid stroke)"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); /* gradient shape ratio */ prop = RNA_def_property(srna, "aspect", PROP_FLOAT, PROP_XYZ); @@ -1604,6 +1626,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Aspect", ""); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "input_samples", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, nullptr, "input_samples"); @@ -1613,7 +1636,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Input Samples", "Generated intermediate points for very fast mouse movements (Set to 0 to disable)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* active smooth factor while drawing */ prop = RNA_def_property(srna, "active_smooth_factor", PROP_FLOAT, PROP_FACTOR); @@ -1621,7 +1644,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Active Smooth", "Amount of smoothing while drawing"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "eraser_strength_factor", PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_float_sdna(prop, nullptr, "era_strength_f"); @@ -1629,7 +1652,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 100.0, 10, 1); RNA_def_property_ui_text(prop, "Affect Stroke Strength", "Amount of erasing for strength"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "eraser_thickness_factor", PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_float_sdna(prop, nullptr, "era_thickness_f"); @@ -1637,7 +1660,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 100.0, 10, 1); RNA_def_property_ui_text(prop, "Affect Stroke Thickness", "Amount of erasing for thickness"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Mode type. */ prop = RNA_def_property(srna, "vertex_mode", PROP_ENUM, PROP_NONE); @@ -1645,6 +1668,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_enum_items(prop, gppaint_mode_types_items); RNA_def_property_ui_text(prop, "Mode Type", "Defines how vertex color affect to the strokes"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); /* Vertex Color mix factor. */ prop = RNA_def_property(srna, "vertex_color_factor", PROP_FLOAT, PROP_FACTOR); @@ -1653,6 +1677,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text( prop, "Vertex Color Factor", "Factor used to mix vertex color to get final color"); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); /* Hue randomness. */ prop = RNA_def_property(srna, "random_hue_factor", PROP_FLOAT, PROP_FACTOR); @@ -1669,6 +1694,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_float_default(prop, 0.0f); RNA_def_property_ui_text(prop, "Saturation", "Random factor to modify original saturation"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); /* Value randomness. */ prop = RNA_def_property(srna, "random_value_factor", PROP_FLOAT, PROP_FACTOR); @@ -1677,6 +1703,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_float_default(prop, 0.0f); RNA_def_property_ui_text(prop, "Value", "Random factor to modify original value"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); /* Factor to extend stroke extremes in Fill brush. */ prop = RNA_def_property(srna, "extend_stroke_factor", PROP_FLOAT, PROP_NONE); @@ -1686,6 +1713,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Closure Size", "Strokes end extension for closing gaps, use zero to disable"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "fill_extend_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "fill_extend_mode"); @@ -1693,6 +1721,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Closure Mode", "Types of stroke extensions used for closing gaps"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); /* Number of pixels to dilate fill area. Negative values contract the filled area. */ prop = RNA_def_property(srna, "dilate", PROP_INT, PROP_PIXEL); @@ -1702,7 +1731,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Dilate/Contract", "Number of pixels to expand or contract fill area"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); /* Factor to determine outline external perimeter thickness. */ prop = RNA_def_property(srna, "outline_thickness_factor", PROP_FLOAT, PROP_FACTOR); @@ -1712,6 +1741,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Thickness", "Thickness of the outline stroke relative to current brush thickness"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0)); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); /* Flags */ prop = RNA_def_property(srna, "use_pressure", PROP_BOOLEAN, PROP_NONE); @@ -1719,7 +1749,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Use Pressure", "Use tablet pressure"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_strength_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_USE_STRENGTH_PRESSURE); @@ -1727,98 +1757,98 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Pressure Strength", "Use tablet pressure for color strength"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_jitter_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_USE_JITTER_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Use Pressure Jitter", "Use tablet pressure for jitter"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_stroke_random_hue", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_HUE_AT_STROKE); RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_stroke_random_sat", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_SAT_AT_STROKE); RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_stroke_random_val", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_VAL_AT_STROKE); RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_stroke_random_radius", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_PRESS_AT_STROKE); RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_stroke_random_strength", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_STRENGTH_AT_STROKE); RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_stroke_random_uv", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_UV_AT_STROKE); RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_random_press_hue", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_HUE_RAND_PRESS); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_random_press_sat", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_SAT_RAND_PRESS); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_random_press_val", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_VAL_RAND_PRESS); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_random_press_radius", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_PRESSURE_RAND_PRESS); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_random_press_strength", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_STRENGTH_RAND_PRESS); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_random_press_uv", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", GP_BRUSH_USE_UV_RAND_PRESS); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_settings_stabilizer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_STABILIZE_MOUSE); @@ -1828,6 +1858,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) "Draw lines with a delay to allow smooth strokes (press Shift key to " "override while drawing)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "eraser_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "eraser_mode"); @@ -1835,7 +1866,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Mode", "Eraser Mode"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_GPENCIL); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, nullptr); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "caps_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "caps_type"); @@ -1843,24 +1874,28 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Caps Type", "The shape of the start and end of the stroke"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_GPENCIL); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "fill_draw_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "fill_draw_mode"); RNA_def_property_enum_items(prop, rna_enum_gpencil_fill_draw_modes_items); RNA_def_property_ui_text(prop, "Mode", "Mode to draw boundary limits"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "fill_layer_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "fill_layer_mode"); RNA_def_property_enum_items(prop, rna_enum_gpencil_fill_layers_modes_items); RNA_def_property_ui_text(prop, "Layer Mode", "Layers used as boundaries"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "fill_direction", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "fill_direction"); RNA_def_property_enum_items(prop, rna_enum_gpencil_fill_direction_items); RNA_def_property_ui_text(prop, "Direction", "Direction of the fill"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "pin_draw_mode", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs( @@ -1876,25 +1911,28 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_modes_items); RNA_def_property_ui_text(prop, "Mode", "Preselected mode when using this brush"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_trim", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_TRIM_STROKE); RNA_def_property_boolean_default(prop, false); RNA_def_property_ui_text(prop, "Trim Stroke Ends", "Trim intersecting stroke ends"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_settings_outline", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_OUTLINE_STROKE); RNA_def_property_boolean_default(prop, false); RNA_def_property_ui_text(prop, "Outline", "Convert stroke to outline"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_edit_position", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna( prop, nullptr, "sculpt_mode_flag", GP_SCULPT_FLAGMODE_APPLY_POSITION); RNA_def_property_ui_text(prop, "Affect Position", "The brush affects the position of the point"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_edit_strength", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna( @@ -1902,7 +1940,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Affect Strength", "The brush affects the color strength of the point"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_edit_thickness", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna( @@ -1910,13 +1948,13 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Affect Thickness", "The brush affects the thickness of the point"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_edit_uv", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "sculpt_mode_flag", GP_SCULPT_FLAGMODE_APPLY_UV); RNA_def_property_ui_text(prop, "Affect UV", "The brush affects the UV rotation of the point"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_BrushGpencilSettings_update"); /* Material */ prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); @@ -1943,12 +1981,14 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Show Lines", "Show help lines for filling to see boundaries"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "show_fill_extend", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_FILL_SHOW_EXTENDLINES); RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Visual Aids", "Show help lines for stroke extension"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_collide_strokes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_FILL_STROKE_COLLIDE); @@ -1956,6 +1996,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Strokes Collision", "Check if extend lines collide with strokes"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "show_fill", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, nullptr, "flag", GP_BRUSH_FILL_HIDE); @@ -1963,23 +2004,27 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Show Fill", "Show transparent lines to use as boundary for filling"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_fill_limit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_FILL_FIT_DISABLE); RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text(prop, "Limit to Viewport", "Fill only visible areas in viewport"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_settings_postprocess", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_GROUP_SETTINGS); RNA_def_property_ui_text( prop, "Use Post-Process Settings", "Additional post processing options for new strokes"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_settings_random", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_GROUP_RANDOM); RNA_def_property_ui_text(prop, "Random Settings", "Random brush settings"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_material_pin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_MATERIAL_PINNED); @@ -1995,22 +2040,26 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Show Lasso", "Do not display fill color while drawing the stroke"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_occlude_eraser", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_OCCLUDE_ERASER); RNA_def_property_ui_text(prop, "Occlude Eraser", "Erase only strokes visible and not occluded"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_keep_caps_eraser", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_ERASER_KEEP_CAPS); RNA_def_property_ui_text( prop, "Keep Caps", "Keep the caps as they are and don't flatten them when erasing"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); prop = RNA_def_property(srna, "use_active_layer_only", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_BRUSH_ACTIVE_LAYER_ONLY); RNA_def_property_ui_text(prop, "Active Layer", "Only edit the active layer of the object"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_BrushGpencilSettings_update"); } static void rna_def_curves_sculpt_options(BlenderRNA *brna) @@ -2046,11 +2095,13 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna) prop = RNA_def_property(srna, "add_amount", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 1, INT32_MAX); RNA_def_property_ui_text(prop, "Count", "Number of curves added by the Add brush"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "points_per_curve", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 2, INT32_MAX); RNA_def_property_ui_text( prop, "Points per Curve", "Number of control points in a newly added curve"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "use_uniform_scale", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_SCALE_UNIFORM); @@ -2058,6 +2109,7 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna) "Scale Uniform", "Grow or shrink curves by changing their size uniformly instead of " "using trimming or extrapolation"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "minimum_length", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.0f, FLT_MAX); @@ -2069,6 +2121,7 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna) prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_LENGTH); RNA_def_property_ui_text( prop, "Interpolate Length", "Use length of the curves in close proximity"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "use_radius_interpolate", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna( @@ -2076,6 +2129,7 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna) RNA_def_property_boolean_default(prop, true); RNA_def_property_ui_text( prop, "Interpolate Radius", "Use radius of the curves in close proximity"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "use_point_count_interpolate", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna( @@ -2083,11 +2137,13 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Interpolate Point Count", "Use the number of points from the curves in close proximity"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "use_shape_interpolate", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_SHAPE); RNA_def_property_ui_text( prop, "Interpolate Shape", "Use shape of the curves in close proximity"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "curve_length", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.0, FLT_MAX); @@ -2095,12 +2151,14 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna) prop, "Curve Length", "Length of newly added curves when it is not interpolated from other curves"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "minimum_distance", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_range(prop, 0.0, 1000.0f, 0.001, 2); RNA_def_property_ui_text( prop, "Minimum Distance", "Goal distance between curve roots for the Density brush"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "curve_radius", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.0, FLT_MAX); @@ -2110,23 +2168,27 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna) prop, "Curve Radius", "Radius of newly added curves when it is not interpolated from other curves"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "density_add_attempts", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, INT32_MAX); RNA_def_property_ui_text( prop, "Density Add Attempts", "How many times the Density brush tries to add a new curve"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "density_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, density_mode_items); RNA_def_property_ui_text( prop, "Density Mode", "Determines whether the brush adds or removes curves"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_OPERATOR_DEFAULT); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); prop = RNA_def_property(srna, "curve_parameter_falloff", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Curve Parameter Falloff", "Falloff that is applied from the tip to the root of each curve"); + RNA_def_property_update(prop, 0, "rna_BrushCurvesSculptSettings_update"); } static void rna_def_brush(BlenderRNA *brna) @@ -2460,6 +2522,13 @@ static void rna_def_brush(BlenderRNA *brna) srna, "Brush", "Brush data-block for storing brush settings for painting and sculpting"); RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA); + prop = RNA_def_property(srna, "has_unsaved_changes", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, + "Has unsaved changes", + "Indicates that there are any user visible changes since the brush has " + "been imported or read from the file"); + /* enums */ prop = RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_blend_items); @@ -2503,12 +2572,14 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Brush Type", ""); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_BRUSH); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "gpencil_vertex_tool", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "gpencil_vertex_brush_type"); RNA_def_property_enum_items(prop, rna_enum_brush_gpencil_vertex_types_items); RNA_def_property_ui_text(prop, "Brush Type", ""); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "gpencil_sculpt_tool", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "gpencil_sculpt_brush_type"); @@ -2516,12 +2587,14 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Brush Type", ""); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_GPENCIL); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "gpencil_weight_tool", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "gpencil_weight_brush_type"); RNA_def_property_enum_items(prop, rna_enum_brush_gpencil_weight_types_items); RNA_def_property_ui_text(prop, "Brush Type", ""); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "curves_sculpt_tool", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, nullptr, "curves_sculpt_brush_type"); @@ -2529,6 +2602,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Brush Type", ""); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVES); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_Brush_update"); /** End per mode brush type properties. */ @@ -3360,6 +3434,7 @@ static void rna_def_brush(BlenderRNA *brna) prop = RNA_def_property(srna, "use_paint_antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "sampling_flag", BRUSH_PAINT_ANTIALIASING); RNA_def_property_ui_text(prop, "Anti-Aliasing", "Smooths the edges of the strokes"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_multiplane_scrape_dynamic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag2", BRUSH_MULTIPLANE_SCRAPE_DYNAMIC); @@ -3642,35 +3717,43 @@ static void rna_def_brush(BlenderRNA *brna) prop = RNA_def_property(srna, "use_paint_sculpt", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "ob_mode", OB_MODE_SCULPT); RNA_def_property_ui_text(prop, "Use Sculpt", "Use this brush in sculpt mode"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_paint_uv_sculpt", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "ob_mode", OB_MODE_EDIT); RNA_def_property_ui_text(prop, "Use UV Sculpt", "Use this brush in UV sculpt mode"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_paint_vertex", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "ob_mode", OB_MODE_VERTEX_PAINT); RNA_def_property_ui_text(prop, "Use Vertex", "Use this brush in vertex paint mode"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_paint_weight", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "ob_mode", OB_MODE_WEIGHT_PAINT); RNA_def_property_ui_text(prop, "Use Weight", "Use this brush in weight paint mode"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_paint_image", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "ob_mode", OB_MODE_TEXTURE_PAINT); RNA_def_property_ui_text(prop, "Use Texture", "Use this brush in texture paint mode"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_paint_grease_pencil", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "ob_mode", OB_MODE_PAINT_GREASE_PENCIL); RNA_def_property_ui_text(prop, "Use Paint", "Use this brush in grease pencil drawing mode"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_vertex_grease_pencil", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "ob_mode", OB_MODE_VERTEX_GREASE_PENCIL); RNA_def_property_ui_text( prop, "Use Vertex", "Use this brush in grease pencil vertex color mode"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_paint_sculpt_curves", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "ob_mode", OB_MODE_SCULPT_CURVES); RNA_def_property_ui_text(prop, "Use Sculpt", "Use this brush in sculpt curves mode"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); /* texture */ prop = RNA_def_property(srna, "texture_slot", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_texture.cc b/source/blender/makesrna/intern/rna_texture.cc index 03066f242bb..6d9693e7d03 100644 --- a/source/blender/makesrna/intern/rna_texture.cc +++ b/source/blender/makesrna/intern/rna_texture.cc @@ -134,6 +134,7 @@ static const EnumPropertyItem blend_type_items[] = { # include "RNA_access.hh" +# include "BKE_brush.hh" # include "BKE_colorband.hh" # include "BKE_context.hh" # include "BKE_image.h" @@ -269,6 +270,7 @@ void rna_TextureSlot_update(bContext *C, PointerRNA *ptr) MTex *mtex = static_cast(ptr->data); ViewLayer *view_layer = CTX_data_view_layer(C); BKE_paint_invalidate_overlay_tex(scene, view_layer, mtex->tex); + BKE_brush_tag_unsaved_changes(reinterpret_cast(id)); WM_main_add_notifier(NC_BRUSH, id); break; } From bcf6524ca1eef214c36775a9599673d3333f6d32 Mon Sep 17 00:00:00 2001 From: Pratik Borhade Date: Sat, 12 Oct 2024 00:23:49 +0200 Subject: [PATCH 3/3] Fix #128601: Redoing move operation crash in sculpt mode PBVH is null when redoing the move operation. To fix this, update active object data from evaluated object before sending undo_push. Also fixed the crash in cache_init() after updating depsgraph Pull Request: https://projects.blender.org/blender/blender/pulls/128625 --- source/blender/editors/sculpt_paint/sculpt_transform.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.cc b/source/blender/editors/sculpt_paint/sculpt_transform.cc index d3b95b26d99..fe36c780a40 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.cc +++ b/source/blender/editors/sculpt_paint/sculpt_transform.cc @@ -56,7 +56,7 @@ void init_transform(bContext *C, Object &ob, const float mval_fl[2], const char const Scene &scene = *CTX_data_scene(C); const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt; SculptSession &ss = *ob.sculpt; - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ss.init_pivot_pos = ss.pivot_pos; ss.init_pivot_rot = ss.pivot_rot; @@ -66,8 +66,8 @@ void init_transform(bContext *C, Object &ob, const float mval_fl[2], const char ss.prev_pivot_rot = ss.pivot_rot; ss.prev_pivot_scale = ss.pivot_scale; - undo::push_begin_ex(scene, ob, undo_name); BKE_sculpt_update_object_for_edit(depsgraph, &ob, false); + undo::push_begin_ex(scene, ob, undo_name); ss.pivot_rot[3] = 1.0f;