Changeset View
Standalone View
source/blender/blenkernel/intern/customdata.cc
| Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||||||||||||
| #include "bmesh.h" | #include "bmesh.h" | ||||||||||||||
| #include "CLG_log.h" | #include "CLG_log.h" | ||||||||||||||
| /* only for customdata_data_transfer_interp_normal_normals */ | /* only for customdata_data_transfer_interp_normal_normals */ | ||||||||||||||
| #include "data_transfer_intern.h" | #include "data_transfer_intern.h" | ||||||||||||||
| using blender::float2; | |||||||||||||||
| using blender::IndexRange; | using blender::IndexRange; | ||||||||||||||
| using blender::Set; | using blender::Set; | ||||||||||||||
| using blender::Span; | using blender::Span; | ||||||||||||||
| using blender::StringRef; | using blender::StringRef; | ||||||||||||||
| using blender::Vector; | using blender::Vector; | ||||||||||||||
| /* number of layers to add when growing a CustomData object */ | /* number of layers to add when growing a CustomData object */ | ||||||||||||||
| #define CUSTOMDATA_GROW 5 | #define CUSTOMDATA_GROW 5 | ||||||||||||||
| ▲ Show 20 Lines • Show All 937 Lines • ▼ Show 20 Lines | static void layerInterp_mloopcol(const void **sources, | ||||||||||||||
| mc->g = round_fl_to_uchar_clamp(col.g); | mc->g = round_fl_to_uchar_clamp(col.g); | ||||||||||||||
| mc->b = round_fl_to_uchar_clamp(col.b); | mc->b = round_fl_to_uchar_clamp(col.b); | ||||||||||||||
| mc->a = round_fl_to_uchar_clamp(col.a); | mc->a = round_fl_to_uchar_clamp(col.a); | ||||||||||||||
| } | } | ||||||||||||||
| /** \} */ | /** \} */ | ||||||||||||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||||||||||||
| /** \name Callbacks for (#MLoopUV, #CD_MLOOPUV) | /** \name Callbacks for #OrigSpaceLoop | ||||||||||||||
| * \{ */ | * \{ */ | ||||||||||||||
| static void layerCopyValue_mloopuv(const void *source, | |||||||||||||||
| void *dest, | |||||||||||||||
| const int mixmode, | |||||||||||||||
| const float mixfactor) | |||||||||||||||
| { | |||||||||||||||
| const MLoopUV *luv1 = static_cast<const MLoopUV *>(source); | |||||||||||||||
| MLoopUV *luv2 = static_cast<MLoopUV *>(dest); | |||||||||||||||
| /* We only support a limited subset of advanced mixing here - | |||||||||||||||
| * namely the mixfactor interpolation. */ | |||||||||||||||
| if (mixmode == CDT_MIX_NOMIX) { | |||||||||||||||
| copy_v2_v2(luv2->uv, luv1->uv); | |||||||||||||||
| } | |||||||||||||||
| else { | |||||||||||||||
| interp_v2_v2v2(luv2->uv, luv2->uv, luv1->uv, mixfactor); | |||||||||||||||
| } | |||||||||||||||
| } | |||||||||||||||
| static bool layerEqual_mloopuv(const void *data1, const void *data2) | |||||||||||||||
| { | |||||||||||||||
| const MLoopUV *luv1 = static_cast<const MLoopUV *>(data1); | |||||||||||||||
| const MLoopUV *luv2 = static_cast<const MLoopUV *>(data2); | |||||||||||||||
| return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f; | |||||||||||||||
| } | |||||||||||||||
| static void layerMultiply_mloopuv(void *data, const float fac) | |||||||||||||||
| { | |||||||||||||||
| MLoopUV *luv = static_cast<MLoopUV *>(data); | |||||||||||||||
| mul_v2_fl(luv->uv, fac); | |||||||||||||||
| } | |||||||||||||||
| static void layerInitMinMax_mloopuv(void *vmin, void *vmax) | |||||||||||||||
| { | |||||||||||||||
| MLoopUV *min = static_cast<MLoopUV *>(vmin); | |||||||||||||||
| MLoopUV *max = static_cast<MLoopUV *>(vmax); | |||||||||||||||
| INIT_MINMAX2(min->uv, max->uv); | |||||||||||||||
| } | |||||||||||||||
| static void layerDoMinMax_mloopuv(const void *data, void *vmin, void *vmax) | |||||||||||||||
| { | |||||||||||||||
| const MLoopUV *luv = static_cast<const MLoopUV *>(data); | |||||||||||||||
| MLoopUV *min = static_cast<MLoopUV *>(vmin); | |||||||||||||||
| MLoopUV *max = static_cast<MLoopUV *>(vmax); | |||||||||||||||
| minmax_v2v2_v2(min->uv, max->uv, luv->uv); | |||||||||||||||
| } | |||||||||||||||
| static void layerAdd_mloopuv(void *data1, const void *data2) | |||||||||||||||
| { | |||||||||||||||
| MLoopUV *l1 = static_cast<MLoopUV *>(data1); | |||||||||||||||
| const MLoopUV *l2 = static_cast<const MLoopUV *>(data2); | |||||||||||||||
| add_v2_v2(l1->uv, l2->uv); | |||||||||||||||
| } | |||||||||||||||
| static void layerInterp_mloopuv(const void **sources, | |||||||||||||||
| const float *weights, | |||||||||||||||
| const float * /*sub_weights*/, | |||||||||||||||
| int count, | |||||||||||||||
| void *dest) | |||||||||||||||
| { | |||||||||||||||
| float uv[2]; | |||||||||||||||
| int flag = 0; | |||||||||||||||
| zero_v2(uv); | |||||||||||||||
| for (int i = 0; i < count; i++) { | |||||||||||||||
| const float interp_weight = weights[i]; | |||||||||||||||
| const MLoopUV *src = static_cast<const MLoopUV *>(sources[i]); | |||||||||||||||
| madd_v2_v2fl(uv, src->uv, interp_weight); | |||||||||||||||
| if (interp_weight > 0.0f) { | |||||||||||||||
| flag |= src->flag; | |||||||||||||||
| } | |||||||||||||||
| } | |||||||||||||||
| /* Delay writing to the destination in case dest is in sources. */ | |||||||||||||||
| copy_v2_v2(((MLoopUV *)dest)->uv, uv); | |||||||||||||||
| ((MLoopUV *)dest)->flag = flag; | |||||||||||||||
| } | |||||||||||||||
| static bool layerValidate_mloopuv(void *data, const uint totitems, const bool do_fixes) | |||||||||||||||
| { | |||||||||||||||
| MLoopUV *uv = static_cast<MLoopUV *>(data); | |||||||||||||||
| bool has_errors = false; | |||||||||||||||
| for (int i = 0; i < totitems; i++, uv++) { | |||||||||||||||
| if (!is_finite_v2(uv->uv)) { | |||||||||||||||
| if (do_fixes) { | |||||||||||||||
| zero_v2(uv->uv); | |||||||||||||||
| } | |||||||||||||||
| has_errors = true; | |||||||||||||||
| } | |||||||||||||||
| } | |||||||||||||||
| return has_errors; | |||||||||||||||
| } | |||||||||||||||
| /* origspace is almost exact copy of mloopuv's, keep in sync */ | /* origspace is almost exact copy of mloopuv's, keep in sync */ | ||||||||||||||
| static void layerCopyValue_mloop_origspace(const void *source, | static void layerCopyValue_mloop_origspace(const void *source, | ||||||||||||||
| void *dest, | void *dest, | ||||||||||||||
| const int /*mixmode*/, | const int /*mixmode*/, | ||||||||||||||
| const float /*mixfactor*/) | const float /*mixfactor*/) | ||||||||||||||
| { | { | ||||||||||||||
| const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(source); | const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(source); | ||||||||||||||
| OrigSpaceLoop *luv2 = static_cast<OrigSpaceLoop *>(dest); | OrigSpaceLoop *luv2 = static_cast<OrigSpaceLoop *>(dest); | ||||||||||||||
| ▲ Show 20 Lines • Show All 485 Lines • ▼ Show 20 Lines | if (!isfinite(values[i])) { | ||||||||||||||
| values[i] = 0.0f; | values[i] = 0.0f; | ||||||||||||||
| } | } | ||||||||||||||
| has_errors = true; | has_errors = true; | ||||||||||||||
| } | } | ||||||||||||||
| } | } | ||||||||||||||
| return has_errors; | return has_errors; | ||||||||||||||
| } | } | ||||||||||||||
| static bool layerEqual_propfloat2(const void *data1, const void *data2) | |||||||||||||||
| { | |||||||||||||||
| const float2 &a = *static_cast<const float2 *>(data1); | |||||||||||||||
| const float2 &b = *static_cast<const float2 *>(data2); | |||||||||||||||
| return blender::math::distance_squared(a, b) < 0.00001f; | |||||||||||||||
chrisbblend: TODO: Confirm epsilon value here.
Tolerance of sqrt(0.00001) ~= 0.003 is larger than 1 texel on… | |||||||||||||||
Done Inline ActionsThis layerequal functions has been copied verbatim from the CD_MLOOPUV case. While I agree it would be a good thing to re-evaluate this epsilon I'd prefer to have that in a separate patch. I'd like to keep this one as similar to the original CD_MLOOPUV behaviour as possible. Baardaap: This layerequal functions has been copied verbatim from the CD_MLOOPUV case.
While I agree it… | |||||||||||||||
| } | |||||||||||||||
| static void layerInitMinMax_propfloat2(void *vmin, void *vmax) | |||||||||||||||
| { | |||||||||||||||
| float2 &min = *static_cast<float2 *>(vmin); | |||||||||||||||
| float2 &max = *static_cast<float2 *>(vmax); | |||||||||||||||
| INIT_MINMAX2(min, max); | |||||||||||||||
| } | |||||||||||||||
| static void layerDoMinMax_propfloat2(const void *data, void *vmin, void *vmax) | |||||||||||||||
| { | |||||||||||||||
| const float2 &value = *static_cast<const float2 *>(data); | |||||||||||||||
| float2 &a = *static_cast<float2 *>(vmin); | |||||||||||||||
| float2 &b = *static_cast<float2 *>(vmax); | |||||||||||||||
| blender::math::min_max(value, a, b); | |||||||||||||||
| } | |||||||||||||||
| static void layerCopyValue_propfloat2(const void *source, | |||||||||||||||
| void *dest, | |||||||||||||||
| const int mixmode, | |||||||||||||||
| const float mixfactor) | |||||||||||||||
| { | |||||||||||||||
| const float2 &a = *static_cast<const float2 *>(source); | |||||||||||||||
| float2 &b = *static_cast<float2 *>(dest); | |||||||||||||||
| /* We only support a limited subset of advanced mixing here- | |||||||||||||||
| * namely the mixfactor interpolation. */ | |||||||||||||||
| if (mixmode == CDT_MIX_NOMIX) { | |||||||||||||||
| b = a; | |||||||||||||||
| } | |||||||||||||||
| else { | |||||||||||||||
| b = blender::math::interpolate(b, a, mixfactor); | |||||||||||||||
| } | |||||||||||||||
| } | |||||||||||||||
| /** \} */ | /** \} */ | ||||||||||||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||||||||||||
| /** \name Callbacks for (`bool`, #CD_PROP_BOOL) | /** \name Callbacks for (`bool`, #CD_PROP_BOOL) | ||||||||||||||
| * \{ */ | * \{ */ | ||||||||||||||
| static void layerInterp_propbool(const void **sources, | static void layerInterp_propbool(const void **sources, | ||||||||||||||
| const float *weights, | const float *weights, | ||||||||||||||
| ▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { | ||||||||||||||
| layerSwap_origspace_face, | layerSwap_origspace_face, | ||||||||||||||
| layerDefault_origspace_face}, | layerDefault_origspace_face}, | ||||||||||||||
| /* 14: CD_ORCO */ | /* 14: CD_ORCO */ | ||||||||||||||
| {sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, | {sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, | ||||||||||||||
| /* 15: CD_MTEXPOLY */ /* DEPRECATED */ | /* 15: CD_MTEXPOLY */ /* DEPRECATED */ | ||||||||||||||
| /* NOTE: when we expose the UV Map / TexFace split to the user, | /* NOTE: when we expose the UV Map / TexFace split to the user, | ||||||||||||||
| * change this back to face Texture. */ | * change this back to face Texture. */ | ||||||||||||||
| {sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, | {sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, | ||||||||||||||
| /* 16: CD_MLOOPUV */ | /* 16: CD_MLOOPUV */ /* DEPRECATED */ | ||||||||||||||
| {sizeof(MLoopUV), | {sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap")}, | ||||||||||||||
| "MLoopUV", | |||||||||||||||
| 1, | |||||||||||||||
| N_("UVMap"), | |||||||||||||||
| nullptr, | |||||||||||||||
| nullptr, | |||||||||||||||
| layerInterp_mloopuv, | |||||||||||||||
| nullptr, | |||||||||||||||
| nullptr, | |||||||||||||||
| nullptr, | |||||||||||||||
| layerValidate_mloopuv, | |||||||||||||||
| layerEqual_mloopuv, | |||||||||||||||
| layerMultiply_mloopuv, | |||||||||||||||
| layerInitMinMax_mloopuv, | |||||||||||||||
| layerAdd_mloopuv, | |||||||||||||||
| layerDoMinMax_mloopuv, | |||||||||||||||
| layerCopyValue_mloopuv, | |||||||||||||||
| nullptr, | |||||||||||||||
| nullptr, | |||||||||||||||
| nullptr, | |||||||||||||||
| layerMaxNum_tface}, | |||||||||||||||
| /* 17: CD_PROP_BYTE_COLOR */ | /* 17: CD_PROP_BYTE_COLOR */ | ||||||||||||||
| {sizeof(MLoopCol), | {sizeof(MLoopCol), | ||||||||||||||
| "MLoopCol", | "MLoopCol", | ||||||||||||||
| 1, | 1, | ||||||||||||||
| N_("Col"), | N_("Col"), | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| layerInterp_mloopcol, | layerInterp_mloopcol, | ||||||||||||||
| ▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { | ||||||||||||||
| N_("Float2"), | N_("Float2"), | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| layerInterp_propfloat2, | layerInterp_propfloat2, | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| layerValidate_propfloat2, | layerValidate_propfloat2, | ||||||||||||||
| nullptr, | layerEqual_propfloat2, | ||||||||||||||
| layerMultiply_propfloat2, | layerMultiply_propfloat2, | ||||||||||||||
| nullptr, | layerInitMinMax_propfloat2, | ||||||||||||||
| layerAdd_propfloat2}, | layerAdd_propfloat2, | ||||||||||||||
| layerDoMinMax_propfloat2, | |||||||||||||||
| layerCopyValue_propfloat2}, | |||||||||||||||
| /* 50: CD_PROP_BOOL */ | /* 50: CD_PROP_BOOL */ | ||||||||||||||
| {sizeof(bool), | {sizeof(bool), | ||||||||||||||
| "bool", | "bool", | ||||||||||||||
| 1, | 1, | ||||||||||||||
| N_("Boolean"), | N_("Boolean"), | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| nullptr, | nullptr, | ||||||||||||||
| layerInterp_propbool, | layerInterp_propbool, | ||||||||||||||
| ▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | const CustomData_MeshMasks CD_MASK_MESH = { | ||||||||||||||
| /* vmask */ (CD_MASK_PROP_FLOAT3 | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | | /* vmask */ (CD_MASK_PROP_FLOAT3 | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | | ||||||||||||||
| CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_CREASE | CD_MASK_BWEIGHT), | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_CREASE | CD_MASK_BWEIGHT), | ||||||||||||||
| /* emask */ | /* emask */ | ||||||||||||||
| (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_BWEIGHT | CD_MASK_CREASE), | (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_BWEIGHT | CD_MASK_CREASE), | ||||||||||||||
| /* fmask */ 0, | /* fmask */ 0, | ||||||||||||||
| /* pmask */ | /* pmask */ | ||||||||||||||
| (CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), | (CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), | ||||||||||||||
| /* lmask */ | /* lmask */ | ||||||||||||||
| (CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | | (CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | | ||||||||||||||
| CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL), | CD_MASK_PROP_ALL), | ||||||||||||||
| }; | }; | ||||||||||||||
| const CustomData_MeshMasks CD_MASK_DERIVEDMESH = { | const CustomData_MeshMasks CD_MASK_DERIVEDMESH = { | ||||||||||||||
| /* vmask */ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN | | /* vmask */ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN | | ||||||||||||||
| CD_MASK_PAINT_MASK | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL | | CD_MASK_PAINT_MASK | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL | | ||||||||||||||
| CD_MASK_CREASE | CD_MASK_BWEIGHT), | CD_MASK_CREASE | CD_MASK_BWEIGHT), | ||||||||||||||
| /* emask */ | /* emask */ | ||||||||||||||
| (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_BWEIGHT | CD_MASK_PROP_ALL | | (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_BWEIGHT | CD_MASK_PROP_ALL | | ||||||||||||||
| CD_MASK_CREASE), | CD_MASK_CREASE), | ||||||||||||||
| /* fmask */ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT), | /* fmask */ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT), | ||||||||||||||
| /* pmask */ | /* pmask */ | ||||||||||||||
| (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL), | (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL), | ||||||||||||||
| /* lmask */ | /* lmask */ | ||||||||||||||
| (CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL | | (CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP | | ||||||||||||||
| CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */ | CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */ | ||||||||||||||
| }; | }; | ||||||||||||||
| const CustomData_MeshMasks CD_MASK_BMESH = { | const CustomData_MeshMasks CD_MASK_BMESH = { | ||||||||||||||
| /* vmask */ (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY | | /* vmask */ (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY | | ||||||||||||||
| CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_CREASE), | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_CREASE), | ||||||||||||||
| /* emask */ (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), | /* emask */ (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), | ||||||||||||||
| /* fmask */ 0, | /* fmask */ 0, | ||||||||||||||
| /* pmask */ | /* pmask */ | ||||||||||||||
| (CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL), | (CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL), | ||||||||||||||
| /* lmask */ | /* lmask */ | ||||||||||||||
| (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | | (CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL), | ||||||||||||||
| CD_MASK_PROP_ALL), | |||||||||||||||
| }; | }; | ||||||||||||||
| const CustomData_MeshMasks CD_MASK_EVERYTHING = { | const CustomData_MeshMasks CD_MASK_EVERYTHING = { | ||||||||||||||
| /* vmask */ (CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | | /* vmask */ (CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | | ||||||||||||||
| CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | | ||||||||||||||
| CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | | ||||||||||||||
| CD_MASK_PROP_ALL | CD_MASK_CREASE), | CD_MASK_PROP_ALL | CD_MASK_CREASE), | ||||||||||||||
| /* emask */ | /* emask */ | ||||||||||||||
| (CD_MASK_MEDGE | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_BWEIGHT | CD_MASK_CREASE | | (CD_MASK_MEDGE | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_BWEIGHT | CD_MASK_CREASE | | ||||||||||||||
| CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), | ||||||||||||||
| /* fmask */ | /* fmask */ | ||||||||||||||
| (CD_MASK_MFACE | CD_MASK_ORIGINDEX | CD_MASK_NORMAL | CD_MASK_MTFACE | CD_MASK_MCOL | | (CD_MASK_MFACE | CD_MASK_ORIGINDEX | CD_MASK_NORMAL | CD_MASK_MTFACE | CD_MASK_MCOL | | ||||||||||||||
| CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL | | CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL | | ||||||||||||||
| CD_MASK_PROP_ALL), | CD_MASK_PROP_ALL), | ||||||||||||||
| /* pmask */ | /* pmask */ | ||||||||||||||
| (CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP | | (CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP | | ||||||||||||||
| CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), | ||||||||||||||
| /* lmask */ | /* lmask */ | ||||||||||||||
| (CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_MLOOPUV | | (CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | | ||||||||||||||
| CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | | ||||||||||||||
| CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL), | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL), | ||||||||||||||
| }; | }; | ||||||||||||||
| static const LayerTypeInfo *layerType_getInfo(int type) | static const LayerTypeInfo *layerType_getInfo(int type) | ||||||||||||||
| { | { | ||||||||||||||
| if (type < 0 || type >= CD_NUMTYPES) { | if (type < 0 || type >= CD_NUMTYPES) { | ||||||||||||||
| return nullptr; | return nullptr; | ||||||||||||||
| ▲ Show 20 Lines • Show All 210 Lines • ▼ Show 20 Lines | if (!(mask & CD_TYPE_AS_MASK(layer.type))) { | ||||||||||||||
| continue; | continue; | ||||||||||||||
| } | } | ||||||||||||||
| dst_layers.append(layer); | dst_layers.append(layer); | ||||||||||||||
| } | } | ||||||||||||||
| CustomData dst = *src; | CustomData dst = *src; | ||||||||||||||
| dst.layers = static_cast<CustomDataLayer *>( | dst.layers = static_cast<CustomDataLayer *>( | ||||||||||||||
| MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__)); | MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__)); | ||||||||||||||
| dst.totlayer = dst_layers.size(); | dst.maxlayer = dst.totlayer = dst_layers.size(); | ||||||||||||||
| memcpy(dst.layers, dst_layers.data(), dst_layers.as_span().size_in_bytes()); | memcpy(dst.layers, dst_layers.data(), dst_layers.as_span().size_in_bytes()); | ||||||||||||||
| CustomData_update_typemap(&dst); | CustomData_update_typemap(&dst); | ||||||||||||||
| return dst; | return dst; | ||||||||||||||
| } | } | ||||||||||||||
| void CustomData_realloc(CustomData *data, const int old_size, const int new_size) | void CustomData_realloc(CustomData *data, const int old_size, const int new_size) | ||||||||||||||
| ▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | if (data->layers[i].type == type) { | ||||||||||||||
| return i; | return i; | ||||||||||||||
| } | } | ||||||||||||||
| } | } | ||||||||||||||
| } | } | ||||||||||||||
| return -1; | return -1; | ||||||||||||||
| } | } | ||||||||||||||
| int CustomData_get_named_layer_index_notype(const CustomData *data, const char *name) | |||||||||||||||
| { | |||||||||||||||
| for (int i = 0; i < data->totlayer; i++) { | |||||||||||||||
| if (STREQ(data->layers[i].name, name)) { | |||||||||||||||
| return i; | |||||||||||||||
| } | |||||||||||||||
| } | |||||||||||||||
| return -1; | |||||||||||||||
| } | |||||||||||||||
| int CustomData_get_active_layer_index(const CustomData *data, const int type) | int CustomData_get_active_layer_index(const CustomData *data, const int type) | ||||||||||||||
| { | { | ||||||||||||||
| const int layer_index = data->typemap[type]; | const int layer_index = data->typemap[type]; | ||||||||||||||
| BLI_assert(customdata_typemap_is_valid(data)); | BLI_assert(customdata_typemap_is_valid(data)); | ||||||||||||||
| return (layer_index != -1) ? layer_index + data->layers[layer_index].active : -1; | return (layer_index != -1) ? layer_index + data->layers[layer_index].active : -1; | ||||||||||||||
| } | } | ||||||||||||||
| int CustomData_get_render_layer_index(const CustomData *data, const int type) | int CustomData_get_render_layer_index(const CustomData *data, const int type) | ||||||||||||||
| ▲ Show 20 Lines • Show All 982 Lines • ▼ Show 20 Lines | |||||||||||||||
| const char *CustomData_get_layer_name(const CustomData *data, const int type, const int n) | const char *CustomData_get_layer_name(const CustomData *data, const int type, const int n) | ||||||||||||||
| { | { | ||||||||||||||
| const int layer_index = CustomData_get_layer_index_n(data, type, n); | const int layer_index = CustomData_get_layer_index_n(data, type, n); | ||||||||||||||
| return (layer_index == -1) ? nullptr : data->layers[layer_index].name; | return (layer_index == -1) ? nullptr : data->layers[layer_index].name; | ||||||||||||||
| } | } | ||||||||||||||
| /* BMesh functions */ | /* BMesh functions */ | ||||||||||||||
| void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char htype) | void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char htype) | ||||||||||||||
Done Inline ActionsI *think* it's not really needed to handle EDGESEL/VERTSEL layers here, as I think CD_MTFACE doesn't have them? Baardaap: I *think* it's not really needed to handle EDGESEL/VERTSEL layers here, as I think CD_MTFACE… | |||||||||||||||
Done Inline ActionsMTFace is deprecated, only used on a runtime basis for interfacing with the old particle system code, which shouldn't care about any of the selection layers. So this change looks correct to me. HooglyBoogly: MTFace is deprecated, only used on a runtime basis for interfacing with the old particle system… | |||||||||||||||
| { | { | ||||||||||||||
| int chunksize; | int chunksize; | ||||||||||||||
| /* Dispose old pools before calling here to avoid leaks */ | /* Dispose old pools before calling here to avoid leaks */ | ||||||||||||||
| BLI_assert(data->pool == nullptr); | BLI_assert(data->pool == nullptr); | ||||||||||||||
| switch (htype) { | switch (htype) { | ||||||||||||||
| case BM_VERT: | case BM_VERT: | ||||||||||||||
| ▲ Show 20 Lines • Show All 632 Lines • ▼ Show 20 Lines | |||||||||||||||
| void CustomData_from_bmesh_block(const CustomData *source, | void CustomData_from_bmesh_block(const CustomData *source, | ||||||||||||||
| CustomData *dest, | CustomData *dest, | ||||||||||||||
| void *src_block, | void *src_block, | ||||||||||||||
| int dest_index) | int dest_index) | ||||||||||||||
| { | { | ||||||||||||||
| /* copies a layer at a time */ | /* copies a layer at a time */ | ||||||||||||||
| int dest_i = 0; | int dest_i = 0; | ||||||||||||||
| for (int src_i = 0; src_i < source->totlayer; src_i++) { | for (int src_i = 0; src_i < source->totlayer; src_i++) { | ||||||||||||||
| if (source->layers[src_i].flag & CD_FLAG_NOCOPY) { | |||||||||||||||
| continue; | |||||||||||||||
| } | |||||||||||||||
| /* find the first dest layer with type >= the source type | /* find the first dest layer with type >= the source type | ||||||||||||||
| * (this should work because layers are ordered by type) | * (this should work because layers are ordered by type) | ||||||||||||||
| */ | */ | ||||||||||||||
| while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) { | while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) { | ||||||||||||||
| dest_i++; | dest_i++; | ||||||||||||||
| } | } | ||||||||||||||
| ▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | |||||||||||||||
| }; | }; | ||||||||||||||
| static bool customdata_unique_check(void *arg, const char *name) | static bool customdata_unique_check(void *arg, const char *name) | ||||||||||||||
| { | { | ||||||||||||||
| CustomDataUniqueCheckData *data_arg = static_cast<CustomDataUniqueCheckData *>(arg); | CustomDataUniqueCheckData *data_arg = static_cast<CustomDataUniqueCheckData *>(arg); | ||||||||||||||
| return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index); | return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index); | ||||||||||||||
| } | } | ||||||||||||||
| int CustomData_name_max_length_calc(const blender::StringRef name) | |||||||||||||||
| { | |||||||||||||||
| if (name.startswith(".")) { | |||||||||||||||
| return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX; | |||||||||||||||
| } | |||||||||||||||
| for (const blender::StringRef prefix : | |||||||||||||||
| {"." UV_VERTSEL_NAME, UV_EDGESEL_NAME ".", UV_PINNED_NAME "."}) { | |||||||||||||||
| if (name.startswith(prefix)) { | |||||||||||||||
| return MAX_CUSTOMDATA_LAYER_NAME; | |||||||||||||||
| } | |||||||||||||||
| } | |||||||||||||||
| return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX; | |||||||||||||||
| } | |||||||||||||||
| void CustomData_set_layer_unique_name(CustomData *data, const int index) | void CustomData_set_layer_unique_name(CustomData *data, const int index) | ||||||||||||||
| { | { | ||||||||||||||
| CustomDataLayer *nlayer = &data->layers[index]; | CustomDataLayer *nlayer = &data->layers[index]; | ||||||||||||||
| const LayerTypeInfo *typeInfo = layerType_getInfo(nlayer->type); | const LayerTypeInfo *typeInfo = layerType_getInfo(nlayer->type); | ||||||||||||||
| CustomDataUniqueCheckData data_arg{data, nlayer->type, index}; | CustomDataUniqueCheckData data_arg{data, nlayer->type, index}; | ||||||||||||||
| if (!typeInfo->defaultname) { | if (!typeInfo->defaultname) { | ||||||||||||||
| return; | return; | ||||||||||||||
| } | } | ||||||||||||||
| const int max_length = CustomData_name_max_length_calc(nlayer->name); | |||||||||||||||
| /* Set default name if none specified. Note we only call DATA_() when | /* Set default name if none specified. Note we only call DATA_() when | ||||||||||||||
| * needed to avoid overhead of locale lookups in the depsgraph. */ | * needed to avoid overhead of locale lookups in the depsgraph. */ | ||||||||||||||
| if (nlayer->name[0] == '\0') { | if (nlayer->name[0] == '\0') { | ||||||||||||||
| STRNCPY(nlayer->name, DATA_(typeInfo->defaultname)); | STRNCPY(nlayer->name, DATA_(typeInfo->defaultname)); | ||||||||||||||
| } | } | ||||||||||||||
Not Done Inline ActionsAs this is being done elsewhere it would be better to make into a shared function (my patch added bke_id_attribute_name_max_length_calc), so that could be made public and reused. campbellbarton: As this is being done elsewhere it would be better to make into a shared function (my patch… | |||||||||||||||
Not Done Inline ActionsI added this to CustomData, since the limitation really comes from there, and I thought it was important to maintain the fact that attributes are implemented with CustomData and not the other way around. HooglyBoogly: I added this to `CustomData`, since the limitation really comes from there, and I thought it… | |||||||||||||||
| BLI_uniquename_cb( | BLI_uniquename_cb(customdata_unique_check, &data_arg, nullptr, '.', nlayer->name, max_length); | ||||||||||||||
| customdata_unique_check, &data_arg, nullptr, '.', nlayer->name, sizeof(nlayer->name)); | |||||||||||||||
| } | } | ||||||||||||||
| void CustomData_validate_layer_name(const CustomData *data, | void CustomData_validate_layer_name(const CustomData *data, | ||||||||||||||
| int type, | int type, | ||||||||||||||
| const char *name, | const char *name, | ||||||||||||||
| char *outname) | char *outname) | ||||||||||||||
| { | { | ||||||||||||||
| int index = -1; | int index = -1; | ||||||||||||||
| ▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | static bool CustomData_layer_ensure_data_exists(CustomDataLayer *layer, size_t count) | ||||||||||||||
| BLI_assert(typeInfo); | BLI_assert(typeInfo); | ||||||||||||||
| if (layer->data || count == 0) { | if (layer->data || count == 0) { | ||||||||||||||
| return false; | return false; | ||||||||||||||
| } | } | ||||||||||||||
| switch (layer->type) { | switch (layer->type) { | ||||||||||||||
| /* When more instances of corrupt files are found, add them here. */ | /* When more instances of corrupt files are found, add them here. */ | ||||||||||||||
| case CD_PROP_BOOL: /* See T84935. */ | case CD_PROP_BOOL: /* See T84935. */ | ||||||||||||||
| case CD_MLOOPUV: /* See T90620. */ | case CD_MLOOPUV: /* See T90620. */ | ||||||||||||||
| case CD_PROP_FLOAT2: /* See T90620. */ | |||||||||||||||
| layer->data = MEM_calloc_arrayN(count, typeInfo->size, layerType_getName(layer->type)); | layer->data = MEM_calloc_arrayN(count, typeInfo->size, layerType_getName(layer->type)); | ||||||||||||||
| BLI_assert(layer->data); | BLI_assert(layer->data); | ||||||||||||||
| if (typeInfo->set_default_value) { | if (typeInfo->set_default_value) { | ||||||||||||||
| typeInfo->set_default_value(layer->data, count); | typeInfo->set_default_value(layer->data, count); | ||||||||||||||
| } | } | ||||||||||||||
| return true; | return true; | ||||||||||||||
| break; | break; | ||||||||||||||
| ▲ Show 20 Lines • Show All 795 Lines • ▼ Show 20 Lines | |||||||||||||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||||||||||||
| /** \name Custom Data Debugging | /** \name Custom Data Debugging | ||||||||||||||
| * \{ */ | * \{ */ | ||||||||||||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||||||||||||
| void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr) | void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr) | ||||||||||||||
| { | { | ||||||||||||||
Done Inline ActionsDon't use std::string for concatenation like this, it's inefficient and this is performance critical code in RNA get/set functions. brecht: Don't use `std::string` for concatenation like this, it's inefficient and this is performance… | |||||||||||||||
| for (int type = 0; type < CD_NUMTYPES; type++) { | for (int type = 0; type < CD_NUMTYPES; type++) { | ||||||||||||||
| if (CustomData_has_layer(data, type)) { | if (CustomData_has_layer(data, type)) { | ||||||||||||||
| /* NOTE: doesn't account for multiple layers. */ | /* NOTE: doesn't account for multiple layers. */ | ||||||||||||||
| const char *name = CustomData_layertype_name(type); | const char *name = CustomData_layertype_name(type); | ||||||||||||||
| const int size = CustomData_sizeof(type); | const int size = CustomData_sizeof(type); | ||||||||||||||
| const void *pt = CustomData_get_layer(data, type); | const void *pt = CustomData_get_layer(data, type); | ||||||||||||||
| const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0; | const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0; | ||||||||||||||
| const char *structname; | const char *structname; | ||||||||||||||
| ▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type) | ||||||||||||||
| if (type.is<int8_t>()) { | if (type.is<int8_t>()) { | ||||||||||||||
| return CD_PROP_INT8; | return CD_PROP_INT8; | ||||||||||||||
| } | } | ||||||||||||||
| if (type.is<ColorGeometry4b>()) { | if (type.is<ColorGeometry4b>()) { | ||||||||||||||
| return CD_PROP_BYTE_COLOR; | return CD_PROP_BYTE_COLOR; | ||||||||||||||
| } | } | ||||||||||||||
| if (type.is<MStringProperty>()) { | if (type.is<MStringProperty>()) { | ||||||||||||||
| return CD_PROP_STRING; | return CD_PROP_STRING; | ||||||||||||||
| } | } | ||||||||||||||
| return static_cast<eCustomDataType>(-1); | return static_cast<eCustomDataType>(-1); | ||||||||||||||
| } | } | ||||||||||||||
Done Inline Actions
HooglyBoogly: | |||||||||||||||
| /** \} */ | /** \} */ | ||||||||||||||
| } // namespace blender::bke | } // namespace blender::bke | ||||||||||||||
| size_t CustomData_get_elem_size(CustomDataLayer *layer) | size_t CustomData_get_elem_size(CustomDataLayer *layer) | ||||||||||||||
| { | { | ||||||||||||||
| return LAYERTYPEINFO[layer->type].size; | return LAYERTYPEINFO[layer->type].size; | ||||||||||||||
| } | } | ||||||||||||||
TODO: Confirm epsilon value here.
Tolerance of sqrt(0.00001) ~= 0.003 is larger than 1 texel on a 512x512 texture.
Elsewhere we're using:
const float epsilon = 0.25f / 65536.0f; /* i.e. Quarter of a texel on a 65536 x 65536 texture. */