Fix #103244: ghosting in Eevee with sculpt paint brush and canvas #104557

Open
Colin Marmond wants to merge 9 commits from Kdaf/blender:fix-103244-sculpt-lighting-using-paint-brush-on-image into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
15 changed files with 116 additions and 39 deletions
Showing only changes of commit 6d92120b42 - Show all commits

View File

@ -105,6 +105,7 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
}
case METAL_GPU_AMD: {
max_threads_per_threadgroup = 128;
use_metalrt = info.use_metalrt;
break;
}
case METAL_GPU_APPLE: {

View File

@ -3478,7 +3478,8 @@ def km_animation_channels(params):
# Selection.
*_template_items_select_actions(params, "anim.channels_select_all"),
("anim.channels_select_box", {"type": 'B', "value": 'PRESS'}, None),
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'}, None),
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'},
{"properties": [("extend", False)]}),
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG', "shift": True},
{"properties": [("extend", True)]}),
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG', "ctrl": True},

View File

@ -2329,6 +2329,9 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
({"property": "use_override_templates"},
("blender/blender/issues/73318",
"Milestone 4")),
({"property": "use_new_volume_nodes"},
("blender/blender/issues/103248",
"#103248")),
),
)

View File

@ -2289,26 +2289,12 @@ bool CustomData_merge(const CustomData *source,
return changed;
}
static bool attribute_stored_in_bmesh_flag(const StringRef name)
{
return ELEM(name,
"position",
".hide_vert",
".hide_edge",
".hide_poly",
".select_vert",
".select_edge",
".select_poly",
"material_index",
"sharp_edge");
}
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src,
const eCustomDataMask mask)
{
Vector<CustomDataLayer> dst_layers;
for (const CustomDataLayer &layer : Span<CustomDataLayer>{src->layers, src->totlayer}) {
if (attribute_stored_in_bmesh_flag(layer.name)) {
if (BM_attribute_stored_in_bmesh_builtin(layer.name)) {
continue;
}
if (!(mask & CD_TYPE_AS_MASK(layer.type))) {

View File

@ -1261,7 +1261,9 @@ bGPDframe *BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_
found = true;
break;
}
if ((gpf->next) && (gpf->next->framenum > cframe)) {
/* If this is the last frame or the next frame is at a later time, we found the right
* frame. */
if (!(gpf->next) || (gpf->next->framenum > cframe)) {
found = true;
break;
}

View File

@ -133,6 +133,20 @@ static char bm_face_flag_to_mflag(const BMFace *f)
return ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0);
}
bool BM_attribute_stored_in_bmesh_builtin(const StringRef name)
{
return ELEM(name,
"position",
".hide_vert",
".hide_edge",
".hide_poly",
".select_vert",
".select_edge",
".select_poly",
"material_index",
"sharp_edge");
}
/* Static function for alloc (duplicate in modifiers_bmesh.c) */
static BMFace *bm_face_create_from_mpoly(BMesh &bm,
Span<MLoop> loops,

View File

@ -9,6 +9,16 @@
#include "bmesh.h"
#ifdef __cplusplus
# include "BLI_string_ref.hh"
/**
* \return Whether attributes with the given name are stored in special flags or fields in BMesh
* rather than in the regular custom data blocks.
*/
bool BM_attribute_stored_in_bmesh_builtin(const blender::StringRef name);
#endif
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -3499,7 +3499,8 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
return OPERATOR_FINISHED;
return WM_operator_flag_only_pass_through_on_press(OPERATOR_FINISHED | OPERATOR_PASS_THROUGH,
event);
}
static void ANIM_OT_channels_click(wmOperatorType *ot)

View File

@ -3327,6 +3327,14 @@ void ED_gpencil_layer_merge(bGPdata *gpd,
gpf_dst->key_type = gpf_src->key_type;
BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum), gpf_dst);
}
/* Copy current source frame to further frames
* that are keyframes in destination layer and not in source layer
* to keep the image equals. */
if (gpf_dst->next && (!gpf_src->next || (gpf_dst->next->framenum < gpf_src->next->framenum))) {
gpf_dst = gpf_dst->next;
BKE_gpencil_layer_frame_get(gpl_src, gpf_dst->framenum, GP_GETFRAME_ADD_COPY);
}
}
/* Read all frames from merge layer and add strokes. */

View File

@ -19,7 +19,13 @@ struct bContext;
void ED_sequencer_select_sequence_single(struct Scene *scene,
struct Sequence *seq,
bool deselect_all);
void ED_sequencer_deselect_all(struct Scene *scene);
/**
* Iterates over a scene's sequences and deselects all of them.
*
* \param scene: scene containing sequences to be deselected.
* \return true if any sequences were deselected; false otherwise.
*/
bool ED_sequencer_deselect_all(struct Scene *scene);
bool ED_space_sequencer_maskedit_mask_poll(struct bContext *C);
bool ED_space_sequencer_check_show_maskedit(struct SpaceSeq *sseq, struct Scene *scene);

View File

@ -28,6 +28,8 @@
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BLI_index_range.hh"
#include "DEG_depsgraph.h"
#include "WM_api.h"
@ -42,6 +44,8 @@
#include "bmesh.h"
#include "bmesh_tools.h"
using blender::IndexRange;
void SCULPT_dynamic_topology_triangulate(BMesh *bm)
{
if (bm->totloop != bm->totface * 3) {
@ -281,8 +285,8 @@ static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoW
uiLayout *layout = UI_popup_menu_layout(pup);
if (flag & (DYNTOPO_WARN_VDATA | DYNTOPO_WARN_EDATA | DYNTOPO_WARN_LDATA)) {
const char *msg_error = TIP_("Vertex Data Detected!");
const char *msg = TIP_("Dyntopo will not preserve vertex colors, UVs, or other customdata");
const char *msg_error = TIP_("Attribute Data Detected");
const char *msg = TIP_("Dyntopo will not preserve colors, UVs, or other attributes");
uiItemL(layout, msg_error, ICON_INFO);
uiItemL(layout, msg, ICON_NONE);
uiItemS(layout);
@ -305,6 +309,39 @@ static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoW
return OPERATOR_INTERFACE;
}
static bool dyntopo_supports_customdata_layers(const blender::Span<CustomDataLayer> layers,
int totelem)
{
for (const CustomDataLayer &layer : layers) {
if (CD_TYPE_AS_MASK(layer.type) & CD_MASK_PROP_ALL) {
if (layer.name[0] == '\0') {
return false;
}
if (STREQ(layer.name, ".sculpt_face_sets") && totelem > 0) {
int *fsets = static_cast<int *>(layer.data);
int fset = fsets[0];
/* Check if only one face set exists. */
for (int i : IndexRange(totelem)) {
if (fsets[i] != fset) {
return false;
}
}
return true;
}
/* Some data is stored as generic attributes on #Mesh but in flags or field on #BMesh. */
return BM_attribute_stored_in_bmesh_builtin(layer.name);
}
/* Some layers just encode #Mesh topology or are handled as special cases for dyntopo. */
return ELEM(layer.type, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX);
}
return true;
}
enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob)
{
Mesh *me = static_cast<Mesh *>(ob->data);
@ -315,18 +352,17 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob)
BLI_assert(ss->bm == nullptr);
UNUSED_VARS_NDEBUG(ss);
for (int i = 0; i < CD_NUMTYPES; i++) {
if (!ELEM(i, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX)) {
if (CustomData_has_layer(&me->vdata, i)) {
flag |= DYNTOPO_WARN_VDATA;
}
if (CustomData_has_layer(&me->edata, i)) {
flag |= DYNTOPO_WARN_EDATA;
}
if (CustomData_has_layer(&me->ldata, i)) {
flag |= DYNTOPO_WARN_LDATA;
}
}
if (!dyntopo_supports_customdata_layers({me->vdata.layers, me->vdata.totlayer}, me->totvert)) {
flag |= DYNTOPO_WARN_VDATA;
}
if (!dyntopo_supports_customdata_layers({me->edata.layers, me->edata.totlayer}, me->totedge)) {
flag |= DYNTOPO_WARN_EDATA;
}
if (!dyntopo_supports_customdata_layers({me->pdata.layers, me->pdata.totlayer}, me->totpoly)) {
flag |= DYNTOPO_WARN_LDATA;
}
if (!dyntopo_supports_customdata_layers({me->ldata.layers, me->ldata.totlayer}, me->totloop)) {
flag |= DYNTOPO_WARN_LDATA;
}
{

View File

@ -2492,17 +2492,22 @@ void SEQUENCER_OT_copy(wmOperatorType *ot)
/** \name Paste Operator
* \{ */
void ED_sequencer_deselect_all(Scene *scene)
bool ED_sequencer_deselect_all(Scene *scene)
{
Editing *ed = SEQ_editing_get(scene);
bool changed = false;
if (ed == NULL) {
return;
return changed;
}
LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
seq->flag &= ~SEQ_ALLSEL;
if (seq->flag & SEQ_ALLSEL) {
seq->flag &= ~SEQ_ALLSEL;
changed = true;
}
}
return changed;
}
static void sequencer_paste_animation(bContext *C)

View File

@ -974,8 +974,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
/* Deselect everything */
if (deselect_all || (seq && (extend == false && deselect == false && toggle == false))) {
ED_sequencer_deselect_all(scene);
changed = true;
changed |= ED_sequencer_deselect_all(scene);
}
/* Nothing to select, but strips could be deselected. */

View File

@ -653,7 +653,8 @@ typedef struct UserDef_Experimental {
char enable_eevee_next;
char use_sculpt_texture_paint;
char enable_workbench_next;
char _pad[7];
char use_new_volume_nodes;
char _pad[6];
/** `makesdna` does not allow empty structs. */
} UserDef_Experimental;

View File

@ -6456,6 +6456,10 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
"All Linked Data Direct",
"Forces all linked data to be considered as directly linked. Workaround for current "
"issues/limitations in BAT (Blender studio pipeline tool)");
prop = RNA_def_property(srna, "use_new_volume_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(
prop, "New Volume Nodes", "Enables visibility of the new Volume nodes in the UI");
}
static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)