Animation: Add in Parent space alignment option to the Transform Orientation gizmo #104724

Merged
Nate Rupsis merged 47 commits from nrupsis/blender:parent-space into main 2023-04-20 17:40:31 +02:00
44 changed files with 568 additions and 368 deletions
Showing only changes of commit 2cd3ca19d0 - Show all commits

View File

@ -78,12 +78,7 @@ include(cmake/tbb.cmake)
include(cmake/python.cmake)
include(cmake/llvm.cmake)
include(cmake/osl.cmake)
option(USE_PIP_NUMPY "Install NumPy using pip wheel instead of building from source" OFF)
if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64"))
set(USE_PIP_NUMPY ON)
else()
include(cmake/numpy.cmake)
endif()
include(cmake/numpy.cmake)
include(cmake/python_site_packages.cmake)
include(cmake/package_python.cmake)
include(cmake/openimageio.cmake)

View File

@ -38,15 +38,6 @@ ExternalProject_Add(external_python_site_packages
--no-binary :all:
)
if(USE_PIP_NUMPY)
# Use only wheel (and not build from source) to stop NumPy from linking against buggy
# Accelerate framework backend on macOS. Official wheels are built with OpenBLAS.
ExternalProject_Add_Step(external_python_site_packages after_install
COMMAND ${PYTHON_BINARY} -m pip install --no-cache-dir numpy==${NUMPY_VERSION} --only-binary :all:
DEPENDEES install
)
endif()
add_dependencies(
external_python_site_packages
external_python

View File

@ -104,26 +104,6 @@ void BKE_mesh_ensure_default_orig_index_customdata(struct Mesh *mesh);
*/
void BKE_mesh_ensure_default_orig_index_customdata_no_check(struct Mesh *mesh);
/**
* Find the index of the loop in 'poly' which references vertex,
* returns -1 if not found
*/
int poly_find_loop_from_vert(const struct MPoly *poly, const int *poly_verts, int vert);
/**
* Fill \a r_adj with the loop indices in \a poly adjacent to the
* vertex. Returns the index of the loop matching vertex, or -1 if the
* vertex is not in \a poly
*/
int poly_get_adj_loops_from_vert(const struct MPoly *poly,
const int *corner_verts,
int vert,
int r_adj[2]);
/**
* Return the index of the edge vert that is not equal to \a v. If
* neither edge vertex is equal to \a v, returns -1.
*/
int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
/**
* Sets each output array element to the edge index if it is a real edge, or -1.
*/

View File

@ -142,7 +142,71 @@ void edges_sharp_from_angle_set(Span<MPoly> polys,
const float split_angle,
MutableSpan<bool> sharp_edges);
} // namespace blender::bke::mesh
/** \} */
/* -------------------------------------------------------------------- */
/** \name Topology Queries
* \{ */
/**
* Find the index of the next corner in the polygon, looping to the start if necessary.
* The indices are into the entire corners array, not just the polygon's corners.
*/
inline int poly_corner_prev(const MPoly &poly, const int corner)
{
return corner - 1 + (corner == poly.loopstart) * poly.totloop;
}
/**
* Find the index of the previous corner in the polygon, looping to the end if necessary.
* The indices are into the entire corners array, not just the polygon's corners.
*/
inline int poly_corner_next(const MPoly &poly, const int corner)
{
if (corner == poly.loopstart + poly.totloop - 1) {
return poly.loopstart;
}
return corner + 1;
}
/**
* Find the index of the corner in the polygon that uses the given vertex.
* The index is into the entire corners array, not just the polygon's corners.
*/
inline int poly_find_corner_from_vert(const MPoly &poly,
const Span<int> corner_verts,
const int vert)
{
return poly.loopstart + corner_verts.slice(poly.loopstart, poly.totloop).first_index(vert);
}
/**
* Return the vertex indices on either side of the given vertex, ordered based on the winding
* direction of the polygon. The vertex must be in the polygon.
*/
inline int2 poly_find_adjecent_verts(const MPoly &poly,
const Span<int> corner_verts,
const int vert)
{
const int corner = poly_find_corner_from_vert(poly, corner_verts, vert);
return {corner_verts[poly_corner_prev(poly, corner)],
corner_verts[poly_corner_next(poly, corner)]};
}
/**
* Return the index of the edge's vertex that is not the \a vert.
* If neither edge vertex is equal to \a v, returns -1.
*/
inline int edge_other_vert(const MEdge &edge, const int vert)
{
if (edge.v1 == vert) {
return edge.v2;
}
if (edge.v2 == vert) {
return edge.v1;
}
return -1;
}
/** \} */
@ -150,6 +214,8 @@ void edges_sharp_from_angle_set(Span<MPoly> polys,
/** \name Inline Mesh Data Access
* \{ */
} // namespace blender::bke::mesh
inline blender::Span<blender::float3> Mesh::vert_positions() const
{
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_positions(this)), this->totvert};

View File

@ -363,18 +363,5 @@ Array<Vector<int, 2>> build_edge_to_poly_map(Span<MPoly> polys,
int edges_num);
Vector<Vector<int>> build_edge_to_loop_map_resizable(Span<int> corner_edges, int edges_num);
inline int poly_loop_prev(const MPoly &poly, int loop_i)
{
return loop_i - 1 + (loop_i == poly.loopstart) * poly.totloop;
}
inline int poly_loop_next(const MPoly &poly, int loop_i)
{
if (loop_i == poly.loopstart + poly.totloop - 1) {
return poly.loopstart;
}
return loop_i + 1;
}
} // namespace blender::bke::mesh_topology
#endif

View File

@ -51,6 +51,7 @@ struct PaletteColor;
struct Scene;
struct StrokeCache;
struct Sculpt;
struct SculptSession;
struct SubdivCCG;
struct Tex;
struct ToolSettings;
@ -563,6 +564,8 @@ typedef struct SculptAttributePointers {
SculptAttribute *dyntopo_node_id_face;
} SculptAttributePointers;
#ifdef __cplusplus
typedef struct SculptSession {
/* Mesh data (not copied) can come either directly from a Mesh, or from a MultiresDM */
struct { /* Special handling for multires meshes */
@ -576,8 +579,8 @@ typedef struct SculptSession {
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
float (*vert_positions)[3];
const struct MPoly *polys;
const int *corner_verts;
blender::Span<MPoly> polys;
blender::Span<int> corner_verts;
/* These contain the vertex and poly counts of the final mesh. */
int totvert, totpoly;
@ -758,12 +761,14 @@ typedef struct SculptSession {
bool islands_valid; /* Is attrs.topology_island_key valid? */
} SculptSession;
#endif
void BKE_sculptsession_free(struct Object *ob);
void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
int BKE_sculptsession_vertex_count(const SculptSession *ss);
int BKE_sculptsession_vertex_count(const struct SculptSession *ss);
/* Ensure an attribute layer exists. */
SculptAttribute *BKE_sculpt_attribute_ensure(struct Object *ob,
@ -911,6 +916,11 @@ bool BKE_object_attributes_active_color_fill(struct Object *ob,
const float fill_color[4],
bool only_selected);
/** C accessor for #Object::sculpt::pbvh. */
struct PBVH *BKE_object_sculpt_pbvh_get(struct Object *object);
bool BKE_object_sculpt_use_dyntopo(const struct Object *object);
void BKE_object_sculpt_dyntopo_smooth_shading_set(struct Object *object, bool value);
/* paint_canvas.cc */
/**

View File

@ -37,6 +37,7 @@ struct PBVH;
struct PBVHBatches;
struct PBVHNode;
struct PBVH_GPU_Args;
struct SculptSession;
struct SubdivCCG;
struct TaskParallelSettings;
struct Image;

View File

@ -310,6 +310,7 @@ typedef enum SubdivCCGAdjacencyType {
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
const int *corner_verts,
int corners_num,
const struct MPoly *mpoly,
int *r_v1,
int *r_v2);

View File

@ -606,7 +606,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
/* For every corner, mix the values from the adjacent edges on the face. */
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int loop_index_prev = mesh_topology::poly_loop_prev(poly, loop_index);
const int loop_index_prev = mesh::poly_corner_prev(poly, loop_index);
const int edge = corner_edges[loop_index];
const int edge_prev = corner_edges[loop_index_prev];
mixer.mix_in(loop_index, old_values[edge]);
@ -633,7 +633,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
for (const int poly_index : range) {
const MPoly &poly = polys[poly_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int loop_index_prev = mesh_topology::poly_loop_prev(poly, loop_index);
const int loop_index_prev = mesh::poly_corner_prev(poly, loop_index);
const int edge = corner_edges[loop_index];
const int edge_prev = corner_edges[loop_index_prev];
if (old_values[edge] && old_values[edge_prev]) {

View File

@ -1505,45 +1505,6 @@ void BKE_mesh_auto_smooth_flag_set(Mesh *me,
}
}
int poly_find_loop_from_vert(const MPoly *poly, const int *poly_corner_verts, int vert)
{
for (int j = 0; j < poly->totloop; j++) {
if (poly_corner_verts[j] == vert) {
return j;
}
}
return -1;
}
int poly_get_adj_loops_from_vert(const MPoly *poly,
const int *corner_verts,
int vert,
int r_adj[2])
{
int corner = poly_find_loop_from_vert(poly, &corner_verts[poly->loopstart], vert);
if (corner != -1) {
/* vertex was found */
r_adj[0] = corner_verts[ME_POLY_LOOP_PREV(poly, corner)];
r_adj[1] = corner_verts[ME_POLY_LOOP_NEXT(poly, corner)];
}
return corner;
}
int BKE_mesh_edge_other_vert(const MEdge *edge, int v)
{
if (edge->v1 == v) {
return edge->v2;
}
if (edge->v2 == v) {
return edge->v1;
}
return -1;
}
void BKE_mesh_looptri_get_real_edges(const MEdge *edges,
const int *corner_verts,
const int *corner_edges,

View File

@ -237,11 +237,12 @@ class MeshFairingContext : public FairingContext {
float r_adj_next[3],
float r_adj_prev[3]) override
{
using namespace blender;
const int vert = corner_verts_[loop];
const MPoly &poly = polys[loop_to_poly_map_[loop]];
const int corner = poly_find_loop_from_vert(&poly, &corner_verts_[poly.loopstart], vert);
copy_v3_v3(r_adj_next, co_[corner_verts_[ME_POLY_LOOP_NEXT(&poly, corner)]]);
copy_v3_v3(r_adj_prev, co_[corner_verts_[ME_POLY_LOOP_PREV(&poly, corner)]]);
const int2 adjecent_verts = bke::mesh::poly_find_adjecent_verts(poly, corner_verts_, vert);
copy_v3_v3(r_adj_next, co_[adjecent_verts[0]]);
copy_v3_v3(r_adj_prev, co_[adjecent_verts[1]]);
}
int other_vertex_index_from_loop(const int loop, const uint v) override

View File

@ -1284,7 +1284,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
const MPoly &poly = polys[poly_index];
for (const int ml_curr_index : IndexRange(poly.loopstart, poly.totloop)) {
const int ml_prev_index = mesh_topology::poly_loop_prev(poly, ml_curr_index);
const int ml_prev_index = mesh::poly_corner_prev(poly, ml_curr_index);
#if 0
printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)",

View File

@ -740,13 +740,13 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
nearest.index = -1;
for (i = 0; i < numedges_dst; i++) {
const MEdge *e_dst = &edges_dst[i];
const MEdge &e_dst = edges_dst[i];
float best_totdist = FLT_MAX;
int best_eidx_src = -1;
int j = 2;
while (j--) {
const uint vidx_dst = j ? e_dst->v1 : e_dst->v2;
const uint vidx_dst = j ? e_dst.v1 : e_dst.v2;
/* Compute closest verts only once! */
if (v_dst_to_src_map[vidx_dst].hit_dist == -1.0f) {
@ -772,7 +772,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
/* Now, check all source edges of closest sources vertices,
* and select the one giving the smallest total verts-to-verts distance. */
for (j = 2; j--;) {
const uint vidx_dst = j ? e_dst->v1 : e_dst->v2;
const uint vidx_dst = j ? e_dst.v1 : e_dst.v2;
const float first_dist = v_dst_to_src_map[vidx_dst].hit_dist;
const int vidx_src = v_dst_to_src_map[vidx_dst].index;
int *eidx_src, k;
@ -785,10 +785,11 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
k = vert_to_edge_src_map[vidx_src].count;
for (; k--; eidx_src++) {
const MEdge *edge_src = &edges_src[*eidx_src];
const float *other_co_src = vcos_src[BKE_mesh_edge_other_vert(edge_src, vidx_src)];
const MEdge &edge_src = edges_src[*eidx_src];
const float *other_co_src =
vcos_src[blender::bke::mesh::edge_other_vert(edge_src, vidx_src)];
const float *other_co_dst =
vert_positions_dst[BKE_mesh_edge_other_vert(e_dst, int(vidx_dst))];
vert_positions_dst[blender::bke::mesh::edge_other_vert(e_dst, int(vidx_dst))];
const float totdist = first_dist + len_v3v3(other_co_src, other_co_dst);
if (totdist < best_totdist) {
@ -801,8 +802,8 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
if (best_eidx_src >= 0) {
const float *co1_src = vcos_src[edges_src[best_eidx_src].v1];
const float *co2_src = vcos_src[edges_src[best_eidx_src].v2];
const float *co1_dst = vert_positions_dst[e_dst->v1];
const float *co2_dst = vert_positions_dst[e_dst->v2];
const float *co1_dst = vert_positions_dst[e_dst.v1];
const float *co2_dst = vert_positions_dst[e_dst.v2];
float co_src[3], co_dst[3];
/* TODO: would need an isect_seg_seg_v3(), actually! */

View File

@ -4357,7 +4357,7 @@ void BKE_object_handle_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_object_sculpt_data_create(Object *ob)
{
BLI_assert((ob->sculpt == nullptr) && (ob->mode & OB_MODE_ALL_SCULPT));
ob->sculpt = MEM_cnew<SculptSession>(__func__);
ob->sculpt = MEM_new<SculptSession>(__func__);
ob->sculpt->mode_type = (eObjectMode)ob->mode;
}

View File

@ -1696,16 +1696,16 @@ static void sculpt_update_object(
/* These are assigned to the base mesh in Multires. This is needed because Face Sets operators
* and tools use the Face Sets data from the base mesh when Multires is active. */
ss->vert_positions = BKE_mesh_vert_positions_for_write(me);
ss->polys = me->polys().data();
ss->corner_verts = me->corner_verts().data();
ss->polys = me->polys();
ss->corner_verts = me->corner_verts();
}
else {
ss->totvert = me->totvert;
ss->totpoly = me->totpoly;
ss->totfaces = me->totpoly;
ss->vert_positions = BKE_mesh_vert_positions_for_write(me);
ss->polys = me->polys().data();
ss->corner_verts = me->corner_verts().data();
ss->polys = me->polys();
ss->corner_verts = me->corner_verts();
ss->multires.active = false;
ss->multires.modifier = nullptr;
ss->multires.level = 0;
@ -1999,12 +1999,11 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
int level = max_ii(1, mmd->sculptlvl);
int gridsize = BKE_ccg_gridsize(level);
int gridarea = gridsize * gridsize;
int i, j;
gmask = static_cast<GridPaintMask *>(
CustomData_add_layer(&me->ldata, CD_GRID_PAINT_MASK, CD_SET_DEFAULT, me->totloop));
for (i = 0; i < me->totloop; i++) {
for (int i = 0; i < me->totloop; i++) {
GridPaintMask *gpm = &gmask[i];
gpm->level = level;
@ -2012,29 +2011,28 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
MEM_callocN(sizeof(float) * gridarea, "GridPaintMask.data"));
}
/* if vertices already have mask, copy into multires data */
/* If vertices already have mask, copy into multires data. */
if (paint_mask) {
for (i = 0; i < me->totpoly; i++) {
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
float avg = 0;
/* mask center */
for (j = 0; j < poly.totloop; j++) {
const int vert = corner_verts[poly.loopstart + j];
/* Mask center. */
float avg = 0.0f;
for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) {
avg += paint_mask[vert];
}
avg /= float(poly.totloop);
/* fill in multires mask corner */
for (j = 0; j < poly.totloop; j++) {
GridPaintMask *gpm = &gmask[poly.loopstart + j];
const int vert = corner_verts[poly.loopstart + j];
const int prev = ME_POLY_LOOP_PREV(&poly, j);
const int next = ME_POLY_LOOP_NEXT(&poly, j);
/* Fill in multires mask corner. */
for (const int corner : blender::IndexRange(poly.loopstart, poly.totloop)) {
GridPaintMask *gpm = &gmask[corner];
const int vert = corner_verts[corner];
const int prev = corner_verts[blender::bke::mesh::poly_corner_prev(poly, vert)];
const int next = corner_verts[blender::bke::mesh::poly_corner_next(poly, vert)];
gpm->data[0] = avg;
gpm->data[1] = (paint_mask[vert] + paint_mask[corner_verts[next]]) * 0.5f;
gpm->data[2] = (paint_mask[vert] + paint_mask[corner_verts[prev]]) * 0.5f;
gpm->data[1] = (paint_mask[vert] + paint_mask[next]) * 0.5f;
gpm->data[2] = (paint_mask[vert] + paint_mask[prev]) * 0.5f;
gpm->data[3] = paint_mask[vert];
}
}
@ -2285,6 +2283,24 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
return pbvh;
}
PBVH *BKE_object_sculpt_pbvh_get(Object *object)
{
if (!object->sculpt) {
return nullptr;
}
return object->sculpt->pbvh;
}
bool BKE_object_sculpt_use_dyntopo(const Object *object)
{
return object->sculpt && object->sculpt->bm;
}
void BKE_object_sculpt_dyntopo_smooth_shading_set(Object *object, const bool value)
{
object->sculpt->bm_smooth_shading = value;
}
void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg)
{
CCGKey key;

View File

@ -1986,7 +1986,7 @@ const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg)
static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
const int *corner_verts,
const blender::Span<int> corner_verts,
const MPoly *polys,
int *r_v1,
int *r_v2)
@ -1996,13 +1996,13 @@ static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_cc
const MPoly &poly = polys[poly_index];
*r_v1 = corner_verts[coord->grid_index];
const int corner = poly_find_loop_from_vert(&poly, &corner_verts[poly.loopstart], *r_v1);
const int corner = blender::bke::mesh::poly_find_corner_from_vert(poly, corner_verts, *r_v1);
if (coord->x == grid_size_1) {
const int next = ME_POLY_LOOP_NEXT(&poly, corner);
const int next = blender::bke::mesh::poly_corner_next(poly, corner);
*r_v2 = corner_verts[next];
}
if (coord->y == grid_size_1) {
const int prev = ME_POLY_LOOP_PREV(&poly, corner);
const int prev = blender::bke::mesh::poly_corner_prev(poly, corner);
*r_v2 = corner_verts[prev];
}
}
@ -2010,6 +2010,7 @@ static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_cc
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
const int *corner_verts,
const int corners_num,
const MPoly *polys,
int *r_v1,
int *r_v2)
@ -2027,7 +2028,8 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const Subdi
return SUBDIV_CCG_ADJACENT_VERTEX;
}
/* Grid corner adjacent to the middle of a coarse mesh edge. */
adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2);
adjacet_vertices_index_from_adjacent_edge(
subdiv_ccg, coord, {corner_verts, corners_num}, polys, r_v1, r_v2);
return SUBDIV_CCG_ADJACENT_EDGE;
}
@ -2035,7 +2037,7 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const Subdi
if (!is_inner_edge_grid_coordinate(subdiv_ccg, coord)) {
/* Grid boundary adjacent to a coarse mesh edge. */
adjacet_vertices_index_from_adjacent_edge(
subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2);
subdiv_ccg, coord, {corner_verts, corners_num}, polys, r_v1, r_v2);
return SUBDIV_CCG_ADJACENT_EDGE;
}
}

View File

@ -222,10 +222,10 @@ static void basic_cache_populate(void *vedata, Object *ob)
}
}
if (G.debug_value == 889 && ob->sculpt && ob->sculpt->pbvh) {
if (G.debug_value == 889 && ob->sculpt && BKE_object_sculpt_pbvh_get(ob)) {
int debug_node_nr = 0;
DRW_debug_modelmat(ob->object_to_world);
BKE_pbvh_draw_debug_cb(ob->sculpt->pbvh, DRW_sculpt_debug_cb, &debug_node_nr);
BKE_pbvh_draw_debug_cb(BKE_object_sculpt_pbvh_get(ob), DRW_sculpt_debug_cb, &debug_node_nr);
}
}
}

View File

@ -814,8 +814,8 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
if (ob->sculpt && ob->sculpt->pbvh) {
BKE_pbvh_is_drawing_set(ob->sculpt->pbvh, use_sculpt_pbvh);
if (ob->sculpt && BKE_object_sculpt_pbvh_get(ob)) {
BKE_pbvh_is_drawing_set(BKE_object_sculpt_pbvh_get(ob), use_sculpt_pbvh);
}
/* First get materials for this mesh. */
@ -887,10 +887,11 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
}
}
if (G.debug_value == 889 && ob->sculpt && ob->sculpt->pbvh) {
if (G.debug_value == 889 && ob->sculpt && BKE_object_sculpt_pbvh_get(ob)) {
int debug_node_nr = 0;
DRW_debug_modelmat(ob->object_to_world);
BKE_pbvh_draw_debug_cb(ob->sculpt->pbvh, DRW_sculpt_debug_cb, &debug_node_nr);
BKE_pbvh_draw_debug_cb(
BKE_object_sculpt_pbvh_get(ob), DRW_sculpt_debug_cb, &debug_node_nr);
}
}

View File

@ -277,8 +277,8 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
* of vertex color arrays from being sent to the GPU (e.g.
* when switching from eevee to workbench).
*/
if (ob->sculpt && ob->sculpt->pbvh) {
BKE_pbvh_is_drawing_set(ob->sculpt->pbvh, is_sculpt_pbvh);
if (ob->sculpt && BKE_object_sculpt_pbvh_get(ob)) {
BKE_pbvh_is_drawing_set(BKE_object_sculpt_pbvh_get(ob), is_sculpt_pbvh);
}
bool has_color = false;
@ -334,7 +334,7 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
}
if (is_sculpt_pbvh && color_type == V3D_SHADING_TEXTURE_COLOR &&
BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES) {
BKE_pbvh_type(BKE_object_sculpt_pbvh_get(ob)) != PBVH_FACES) {
/* Force use of material color for sculpt. */
color_type = V3D_SHADING_MATERIAL_COLOR;
}

View File

@ -12,34 +12,44 @@
* - Custom context menus
* - Notifier listening
* - Drag controllers (dragging view items)
* - Drop controllers (dropping onto/into view items)
* - Drop targets (dropping onto/into view items)
*/
#pragma once
#include <array>
#include <memory>
#include <optional>
#include "DNA_defs.h"
#include "DNA_vec_types.h"
#include "BLI_span.hh"
#include "BLI_string_ref.hh"
#include "UI_interface.hh"
struct bContext;
struct uiBlock;
struct uiLayout;
struct uiViewItemHandle;
struct ViewLink;
struct wmDrag;
struct wmNotifier;
namespace blender::ui {
class AbstractViewItem;
class AbstractViewItemDropController;
class AbstractViewItemDropTarget;
class AbstractViewItemDragController;
/** The view drop target can share logic with the view item drop target for now, so just an alias.
*/
using AbstractViewDropTarget = AbstractViewItemDropTarget;
class AbstractView {
friend class AbstractViewItem;
friend struct ::ViewLink;
bool is_reconstructed_ = false;
/**
@ -51,9 +61,21 @@ class AbstractView {
*/
std::unique_ptr<std::array<char, MAX_NAME>> rename_buffer_;
/* See #get_bounds(). */
std::optional<rcti> bounds_;
public:
virtual ~AbstractView() = default;
/**
* If a view wants to support dropping data into it, it has to return a drop target here.
* That is an object implementing #AbstractViewDropTarget.
*
* \note This drop target may be requested for each event. The view doesn't keep the drop target
* around currently. So it cannot contain persistent state.
*/
virtual std::unique_ptr<AbstractViewDropTarget> create_drop_target() const;
/** Listen to a notifier, returning true if a redraw is needed. */
virtual bool listen(const wmNotifier &) const;
@ -70,6 +92,11 @@ class AbstractView {
void end_renaming();
Span<char> get_rename_buffer() const;
MutableSpan<char> get_rename_buffer();
/**
* Get the rectangle containing all the view items that are in the layout, in button space.
* Updated as part of #UI_block_end(), before that it's unset.
*/
std::optional<rcti> get_bounds() const;
protected:
AbstractView() = default;
@ -133,13 +160,13 @@ class AbstractViewItem {
*/
virtual std::unique_ptr<AbstractViewItemDragController> create_drag_controller() const;
/**
* If an item wants to support dropping data into it, it has to return a drop controller here.
* That is an object implementing #AbstractViewItemDropController.
* If an item wants to support dropping data into it, it has to return a drop target here.
* That is an object implementing #AbstractViewItemDropTarget.
*
* \note This drop controller may be requested for each event. The view doesn't keep a drop
* controller around currently. So it can not contain persistent state.
* \note This drop target may be requested for each event. The view doesn't keep a drop target
* around currently. So it can not contain persistent state.
*/
virtual std::unique_ptr<AbstractViewItemDropController> create_drop_controller() const;
virtual std::unique_ptr<AbstractViewItemDropTarget> create_drop_target() const;
/** Get the view this item is registered for using #AbstractView::register_item(). */
AbstractView &get_view() const;
@ -200,7 +227,7 @@ template<typename ToType> ToType *AbstractViewItem::from_item_handle(uiViewItemH
* \{ */
/**
* Class to enable dragging a view item. An item can return a drop controller for itself by
* Class to enable dragging a view item. An item can return a drag controller for itself by
* implementing #AbstractViewItem::create_drag_controller().
*/
class AbstractViewItemDragController {
@ -222,38 +249,15 @@ class AbstractViewItemDragController {
/**
* Class to define the behavior when dropping something onto/into a view item, plus the behavior
* when dragging over this item. An item can return a drop controller for itself via a custom
* implementation of #AbstractViewItem::create_drop_controller().
* when dragging over this item. An item can return a drop target for itself via a custom
* implementation of #AbstractViewItem::create_drop_target().
*/
class AbstractViewItemDropController {
class AbstractViewItemDropTarget : public DropTargetInterface {
protected:
AbstractView &view_;
public:
AbstractViewItemDropController(AbstractView &view);
virtual ~AbstractViewItemDropController() = default;
/**
* Check if the data dragged with \a drag can be dropped on the item this controller is for.
* \param r_disabled_hint: Return a static string to display to the user, explaining why dropping
* isn't possible on this item. Shouldn't be done too aggressively, e.g.
* don't set this if the drag-type can't be dropped here; only if it can
* but there's another reason it can't be dropped.
* Can assume this is a non-null pointer.
*/
virtual bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const = 0;
/**
* Custom text to display when dragging over a view item. Should explain what happens when
* dropping the data onto this item. Will only be used if #AbstractViewItem::can_drop()
* returns true, so the implementing override doesn't have to check that again.
* The returned value must be a translated string.
*/
virtual std::string drop_tooltip(const wmDrag &drag) const = 0;
/**
* Execute the logic to apply a drop of the data dragged with \a drag onto/into the item this
* controller is for.
*/
virtual bool on_drop(struct bContext *C, const wmDrag &drag) = 0;
AbstractViewItemDropTarget(AbstractView &view);
/** Request the view the item is registered for as type #ViewType. Throws a `std::bad_cast`
* exception if the view is not of the requested type. */
@ -267,7 +271,7 @@ template<class ViewType> ViewType &AbstractViewItemDragController::get_view() co
return dynamic_cast<ViewType &>(view_);
}
template<class ViewType> ViewType &AbstractViewItemDropController::get_view() const
template<class ViewType> ViewType &AbstractViewItemDropTarget::get_view() const
{
static_assert(std::is_base_of<AbstractView, ViewType>::value,
"Type must derive from and implement the ui::AbstractView interface");

View File

@ -3274,18 +3274,12 @@ void UI_view_item_context_menu_build(struct bContext *C,
* \return True if dragging started successfully, otherwise false.
*/
bool UI_view_item_drag_start(struct bContext *C, const uiViewItemHandle *item_);
bool UI_view_item_can_drop(const uiViewItemHandle *item_,
const struct wmDrag *drag,
const char **r_disabled_hint);
char *UI_view_item_drop_tooltip(const uiViewItemHandle *item, const struct wmDrag *drag);
/**
* Let a view item handle a drop event.
* \return True if the drop was handled by the view item.
*/
bool UI_view_item_drop_handle(struct bContext *C,
const uiViewItemHandle *item_,
const struct ListBase *drags);
/**
* \param xy: Coordinate to find a view item at, in window space.
* \param pad: Extra padding added to the bounding box of the view.
*/
uiViewHandle *UI_region_view_find_at(const struct ARegion *region, const int xy[2], int pad);
/**
* \param xy: Coordinate to find a view item at, in window space.
*/

View File

@ -18,11 +18,17 @@ namespace blender::nodes::geo_eval_log {
struct GeometryAttributeInfo;
}
struct ARegion;
struct bContext;
struct PointerRNA;
struct StructRNA;
struct uiBlock;
struct uiLayout;
struct uiList;
struct uiSearchItems;
struct uiViewHandle;
struct uiViewItemHandle;
struct wmDrag;
namespace blender::ui {
@ -54,6 +60,67 @@ void attribute_search_add_items(StringRefNull str,
uiSearchItems *items,
bool is_first);
/**
* This provides a common interface for UI elements that want to support dragging & dropping
* entities into/onto them. With it, the element can determine if the dragged entity can be dropped
* onto itself, provide feedback while dragging and run custom code for the dropping.
*
* Note that this is just an interface. A #wmDropBox is needed to request instances of it from a UI
* element and call its functions. For example the drop box using "UI_OT_view_drop" implements
* dropping for views and view items via this interface. To support other kinds of UI elements,
* similar drop boxes would be necessary.
*/
class DropTargetInterface {
public:
DropTargetInterface() = default;
virtual ~DropTargetInterface() = default;
/**
* Check if the data dragged with \a drag can be dropped on the element this drop target is for.
* \param r_disabled_hint: Return a static string to display to the user, explaining why dropping
* isn't possible on this UI element. Shouldn't be done too aggressively,
* e.g. don't set this if the drag-type can't be dropped here; only if it
* can but there's another reason it can't be dropped. Can assume this is
* a non-null pointer.
*/
virtual bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const = 0;
/**
* Custom text to display when dragging over the element using this drop target. Should
* explain what happens when dropping the data onto this UI element. Will only be used if
* #DropTargetInterface::can_drop() returns true, so the implementing override doesn't have
* to check that again. The returned value must be a translated string.
*/
virtual std::string drop_tooltip(const wmDrag &drag) const = 0;
/**
* Execute the logic to apply a drop of the data dragged with \a drag onto/into the UI element
* this drop target is for.
*/
virtual bool on_drop(bContext *C, const wmDrag &drag) const = 0;
};
/**
* Let a drop target handle a drop event.
* \return True if the dropping was successful.
*/
bool drop_target_apply_drop(bContext &C,
const DropTargetInterface &drop_target,
const ListBase &drags);
/**
* Call #DropTargetInterface::drop_tooltip() and return the result as newly allocated C string
* (unless the result is empty, returns null then). Needs freeing with MEM_freeN().
*/
char *drop_target_tooltip(const DropTargetInterface &drop_target, const wmDrag &drag);
std::unique_ptr<DropTargetInterface> view_drop_target(const uiViewHandle *view_handle);
std::unique_ptr<DropTargetInterface> view_item_drop_target(const uiViewItemHandle *item_handle);
/**
* Try to find a view item with a drop target under the mouse cursor, or if not found, a view
* with a drop target.
* \param xy: Coordinate to find a drop target at, in window space.
*/
std::unique_ptr<DropTargetInterface> region_views_find_drop_target_at(const ARegion *region,
const int xy[2]);
} // namespace blender::ui
enum eUIListFilterResult {

View File

@ -46,6 +46,7 @@ set(SRC
interface_context_path.cc
interface_drag.cc
interface_draw.cc
interface_drop.cc
interface_dropboxes.cc
interface_handlers.cc
interface_icons.cc

View File

@ -2014,6 +2014,8 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
break;
}
ui_block_views_bounds_calc(block);
if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
UI_block_bounds_set_normal(block, 0);
}

View File

@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edinterface
*/
#include "UI_interface.hh"
namespace blender::ui {
bool drop_target_apply_drop(bContext &C,
const DropTargetInterface &drop_target,
const ListBase &drags)
{
const char *disabled_hint_dummy = nullptr;
LISTBASE_FOREACH (const wmDrag *, drag, &drags) {
if (drop_target.can_drop(*drag, &disabled_hint_dummy)) {
return drop_target.on_drop(&C, *drag);
}
}
return false;
}
char *drop_target_tooltip(const DropTargetInterface &drop_target, const wmDrag &drag)
{
const std::string tooltip = drop_target.drop_tooltip(drag);
return tooltip.empty() ? nullptr : BLI_strdup(tooltip.c_str());
}
} // namespace blender::ui

View File

@ -20,6 +20,9 @@
#include "WM_api.h"
#include "UI_interface.h"
#include "UI_interface.hh"
using namespace blender::ui;
/* -------------------------------------------------------------------- */
/** \name View Drag/Drop Callbacks
@ -28,28 +31,28 @@
static bool ui_view_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
const ARegion *region = CTX_wm_region(C);
const uiViewItemHandle *hovered_item = UI_region_views_find_item_at(region, event->xy);
if (!hovered_item) {
std::unique_ptr<DropTargetInterface> drop_target = region_views_find_drop_target_at(
region, event->xy);
if (!drop_target) {
return false;
}
if (drag->drop_state.free_disabled_info) {
MEM_SAFE_FREE(drag->drop_state.disabled_info);
}
drag->drop_state.free_disabled_info = false;
return UI_view_item_can_drop(hovered_item, drag, &drag->drop_state.disabled_info);
return drop_target->can_drop(*drag, &drag->drop_state.disabled_info);
}
static char *ui_view_drop_tooltip(bContext *C, wmDrag *drag, const int xy[2], wmDropBox * /*drop*/)
{
const ARegion *region = CTX_wm_region(C);
const uiViewItemHandle *hovered_item = UI_region_views_find_item_at(region, xy);
if (!hovered_item) {
return nullptr;
}
std::unique_ptr<DropTargetInterface> drop_target = region_views_find_drop_target_at(region,
xy);
return UI_view_item_drop_tooltip(hovered_item, drag);
return drop_target_tooltip(*drop_target, *drag);
}
/** \} */

View File

@ -1452,6 +1452,7 @@ void ui_interface_tag_script_reload_queries();
/* interface_view.cc */
void ui_block_free_views(uiBlock *block);
void ui_block_views_bounds_calc(const uiBlock *block);
void ui_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params);
uiViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_block,
const uiViewHandle *new_view);

View File

@ -47,6 +47,7 @@
#include "RNA_types.h"
#include "UI_interface.h"
#include "UI_interface.hh"
#include "interface_intern.hh"
@ -65,6 +66,8 @@
#include "ED_screen.h"
#include "ED_text.h"
using namespace blender::ui;
/* -------------------------------------------------------------------- */
/** \name Immediate redraw helper
*
@ -2351,7 +2354,7 @@ static void UI_OT_list_start_filter(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name UI Tree-View Drop Operator
/** \name UI View Drop Operator
* \{ */
static bool ui_view_drop_poll(bContext *C)
@ -2361,9 +2364,7 @@ static bool ui_view_drop_poll(bContext *C)
if (region == nullptr) {
return false;
}
const uiViewItemHandle *hovered_item = UI_region_views_find_item_at(region, win->eventstate->xy);
return hovered_item != nullptr;
return region_views_find_drop_target_at(region, win->eventstate->xy) != nullptr;
}
static int ui_view_drop_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *event)
@ -2373,10 +2374,11 @@ static int ui_view_drop_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *
}
const ARegion *region = CTX_wm_region(C);
uiViewItemHandle *hovered_item = UI_region_views_find_item_at(region, event->xy);
std::unique_ptr<DropTargetInterface> drop_target = region_views_find_drop_target_at(
region, event->xy);
if (!UI_view_item_drop_handle(
C, hovered_item, static_cast<const ListBase *>(event->customdata))) {
if (!drop_target_apply_drop(
*C, *drop_target, *static_cast<const ListBase *>(event->customdata))) {
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
@ -2385,9 +2387,9 @@ static int ui_view_drop_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *
static void UI_OT_view_drop(wmOperatorType *ot)
{
ot->name = "View drop";
ot->name = "View Drop";
ot->idname = "UI_OT_view_drop";
ot->description = "Drag and drop items onto a data-set item";
ot->description = "Drag and drop onto a data-set or item within the data-set";
ot->invoke = ui_view_drop_invoke;
ot->poll = ui_view_drop_poll;

View File

@ -62,6 +62,12 @@ void AbstractView::update_from_old(uiBlock &new_block)
/** \name Default implementations of virtual functions
* \{ */
std::unique_ptr<AbstractViewDropTarget> AbstractView::create_drop_target() const
{
/* There's no drop target (and hence no drop support) by default. */
return nullptr;
}
bool AbstractView::listen(const wmNotifier & /*notifier*/) const
{
/* Nothing by default. */
@ -104,6 +110,23 @@ MutableSpan<char> AbstractView::get_rename_buffer()
return *rename_buffer_;
}
std::optional<rcti> AbstractView::get_bounds() const
{
return bounds_;
}
/** \} */
/* ---------------------------------------------------------------------- */
/** \name General API functions
* \{ */
std::unique_ptr<DropTargetInterface> view_drop_target(const uiViewHandle *view_handle)
{
const AbstractView &view = reinterpret_cast<const AbstractView &>(*view_handle);
return view.create_drop_target();
}
/** \} */
} // namespace blender::ui

View File

@ -174,9 +174,9 @@ std::unique_ptr<AbstractViewItemDragController> AbstractViewItem::create_drag_co
return nullptr;
}
std::unique_ptr<AbstractViewItemDropController> AbstractViewItem::create_drop_controller() const
std::unique_ptr<AbstractViewItemDropTarget> AbstractViewItem::create_drop_target() const
{
/* There's no drop controller (and hence no drop support) by default. */
/* There's no drop target (and hence no drop support) by default. */
return nullptr;
}
@ -189,7 +189,7 @@ void AbstractViewItemDragController::on_drag_start()
/* Do nothing by default. */
}
AbstractViewItemDropController::AbstractViewItemDropController(AbstractView &view) : view_(view)
AbstractViewItemDropTarget::AbstractViewItemDropTarget(AbstractView &view) : view_(view)
{
}
@ -217,6 +217,18 @@ bool AbstractViewItem::is_active() const
/** \} */
/* ---------------------------------------------------------------------- */
/** \name General API functions
* \{ */
std::unique_ptr<DropTargetInterface> view_item_drop_target(const uiViewItemHandle *item_handle)
{
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
return item.create_drop_target();
}
/** \} */
} // namespace blender::ui
/* ---------------------------------------------------------------------- */
@ -264,45 +276,6 @@ class ViewItemAPIWrapper {
return true;
}
static bool can_drop(const AbstractViewItem &item,
const wmDrag &drag,
const char **r_disabled_hint)
{
const std::unique_ptr<AbstractViewItemDropController> drop_controller =
item.create_drop_controller();
if (!drop_controller) {
return false;
}
return drop_controller->can_drop(drag, r_disabled_hint);
}
static std::string drop_tooltip(const AbstractViewItem &item, const wmDrag &drag)
{
const std::unique_ptr<AbstractViewItemDropController> drop_controller =
item.create_drop_controller();
if (!drop_controller) {
return {};
}
return drop_controller->drop_tooltip(drag);
}
static bool drop_handle(bContext &C, const AbstractViewItem &item, const ListBase &drags)
{
std::unique_ptr<AbstractViewItemDropController> drop_controller =
item.create_drop_controller();
const char *disabled_hint_dummy = nullptr;
LISTBASE_FOREACH (const wmDrag *, drag, &drags) {
if (drop_controller->can_drop(*drag, &disabled_hint_dummy)) {
return drop_controller->on_drop(&C, *drag);
}
}
return false;
}
};
} // namespace blender::ui
@ -348,26 +321,4 @@ bool UI_view_item_drag_start(bContext *C, const uiViewItemHandle *item_)
return ViewItemAPIWrapper::drag_start(*C, item);
}
bool UI_view_item_can_drop(const uiViewItemHandle *item_,
const wmDrag *drag,
const char **r_disabled_hint)
{
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_);
return ViewItemAPIWrapper::can_drop(item, *drag, r_disabled_hint);
}
char *UI_view_item_drop_tooltip(const uiViewItemHandle *item_, const wmDrag *drag)
{
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_);
const std::string tooltip = ViewItemAPIWrapper::drop_tooltip(item, *drag);
return tooltip.empty() ? nullptr : BLI_strdup(tooltip.c_str());
}
bool UI_view_item_drop_handle(bContext *C, const uiViewItemHandle *item_, const ListBase *drags)
{
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_);
return ViewItemAPIWrapper::drop_handle(*C, item, *drags);
}
/** \} */

View File

@ -24,6 +24,7 @@
#include "BKE_screen.h"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "ED_screen.h"
@ -44,6 +45,8 @@ using namespace blender::ui;
struct ViewLink : public Link {
std::string idname;
std::unique_ptr<AbstractView> view;
static void views_bounds_calc(const uiBlock &block);
};
template<class T>
@ -81,6 +84,51 @@ void ui_block_free_views(uiBlock *block)
}
}
void ViewLink::views_bounds_calc(const uiBlock &block)
{
Map<AbstractView *, rcti> views_bounds;
rcti minmax;
BLI_rcti_init_minmax(&minmax);
LISTBASE_FOREACH (ViewLink *, link, &block.views) {
views_bounds.add(link->view.get(), minmax);
}
LISTBASE_FOREACH (uiBut *, but, &block.buttons) {
if (but->type != UI_BTYPE_VIEW_ITEM) {
continue;
}
uiButViewItem *view_item_but = static_cast<uiButViewItem *>(but);
if (!view_item_but->view_item) {
continue;
}
/* Get the view from the button. */
AbstractViewItem &view_item = reinterpret_cast<AbstractViewItem &>(*view_item_but->view_item);
AbstractView &view = view_item.get_view();
rcti &bounds = views_bounds.lookup(&view);
rcti but_rcti{};
BLI_rcti_rctf_copy_round(&but_rcti, &view_item_but->rect);
BLI_rcti_do_minmax_rcti(&bounds, &but_rcti);
}
for (const auto item : views_bounds.items()) {
const rcti &bounds = item.value;
if (BLI_rcti_is_empty(&bounds)) {
continue;
}
AbstractView &view = *item.key;
view.bounds_ = bounds;
}
}
void ui_block_views_bounds_calc(const uiBlock *block)
{
ViewLink::views_bounds_calc(*block);
}
void ui_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params)
{
ARegion *region = listener_params->region;
@ -92,6 +140,35 @@ void ui_block_views_listen(const uiBlock *block, const wmRegionListenerParams *l
}
}
/* Similar to #ui_but_find_mouse_over_ex(). */
uiViewHandle *UI_region_view_find_at(const ARegion *region, const int xy[2], const int pad)
{
if (!ui_region_contains_point_px(region, xy)) {
return nullptr;
}
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
float mx = xy[0], my = xy[1];
ui_window_to_block_fl(region, block, &mx, &my);
LISTBASE_FOREACH (ViewLink *, view_link, &block->views) {
std::optional<rcti> bounds = view_link->view->get_bounds();
if (!bounds) {
continue;
}
rcti padded_bounds = *bounds;
if (pad) {
BLI_rcti_pad(&padded_bounds, pad, pad);
}
if (BLI_rcti_isect_pt(&padded_bounds, mx, my)) {
return reinterpret_cast<uiViewHandle *>(view_link->view.get());
}
}
}
return nullptr;
}
uiViewItemHandle *UI_region_views_find_item_at(const ARegion *region, const int xy[2])
{
uiButViewItem *item_but = (uiButViewItem *)ui_view_item_find_mouse_over(region, xy);
@ -112,6 +189,34 @@ uiViewItemHandle *UI_region_views_find_active_item(const ARegion *region)
return item_but->view_item;
}
namespace blender::ui {
std::unique_ptr<DropTargetInterface> region_views_find_drop_target_at(const ARegion *region,
const int xy[2])
{
const uiViewItemHandle *hovered_view_item = UI_region_views_find_item_at(region, xy);
if (hovered_view_item) {
std::unique_ptr<DropTargetInterface> drop_target = view_item_drop_target(hovered_view_item);
if (drop_target) {
return drop_target;
}
}
/* Get style for some sensible padding around the view items. */
const uiStyle *style = UI_style_get_dpi();
const uiViewHandle *hovered_view = UI_region_view_find_at(region, xy, style->buttonspacex);
if (hovered_view) {
std::unique_ptr<DropTargetInterface> drop_target = view_drop_target(hovered_view);
if (drop_target) {
return drop_target;
}
}
return nullptr;
}
} // namespace blender::ui
static StringRef ui_block_view_find_idname(const uiBlock &block, const AbstractView &view)
{
/* First get the idname the of the view we're looking for. */

View File

@ -768,7 +768,13 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex)
coord.y = vertex_index / key->grid_size;
int v1, v2;
const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
ss->subdiv_ccg, &coord, ss->corner_verts, ss->polys, &v1, &v2);
ss->subdiv_ccg,
&coord,
ss->corner_verts.data(),
ss->corner_verts.size(),
ss->polys.data(),
&v1,
&v2);
switch (adjacency) {
case SUBDIV_CCG_ADJACENT_VERTEX:
return sculpt_check_unique_face_set_in_base_mesh(ss, v1);
@ -888,12 +894,11 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
continue;
}
const MPoly &poly = ss->polys[vert_map->indices[i]];
int f_adj_v[2];
if (poly_get_adj_loops_from_vert(&poly, ss->corner_verts, vertex.i, f_adj_v) != -1) {
for (int j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
if (f_adj_v[j] != vertex.i) {
sculpt_vertex_neighbor_add(iter, BKE_pbvh_make_vref(f_adj_v[j]), f_adj_v[j]);
}
const blender::int2 f_adj_v = blender::bke::mesh::poly_find_adjecent_verts(
poly, ss->corner_verts, vertex.i);
for (int j = 0; j < 2; j++) {
if (f_adj_v[j] != vertex.i) {
sculpt_vertex_neighbor_add(iter, BKE_pbvh_make_vref(f_adj_v[j]), f_adj_v[j]);
}
}
}
@ -1003,7 +1008,13 @@ bool SCULPT_vertex_is_boundary(const SculptSession *ss, const PBVHVertRef vertex
coord.y = vertex_index / key->grid_size;
int v1, v2;
const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
ss->subdiv_ccg, &coord, ss->corner_verts, ss->polys, &v1, &v2);
ss->subdiv_ccg,
&coord,
ss->corner_verts.data(),
ss->corner_verts.size(),
ss->polys.data(),
&v1,
&v2);
switch (adjacency) {
case SUBDIV_CCG_ADJACENT_VERTEX:
return sculpt_check_boundary_vertex_in_base_mesh(ss, v1);

View File

@ -129,7 +129,6 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
const Span<float3> positions(
reinterpret_cast<const float3 *>(SCULPT_mesh_deformed_positions_get(ss)),
SCULPT_vertex_count_get(ss));
const Span<int> corner_verts(ss->corner_verts, data->me->totloop);
AutomaskingNodeData automask_data;
SCULPT_automasking_node_begin(
data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]);
@ -144,7 +143,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
const MPoly &poly = ss->polys[vert_map->indices[j]];
const float3 poly_center = bke::mesh::poly_center_calc(
positions, corner_verts.slice(poly.loopstart, poly.totloop));
positions, ss->corner_verts.slice(poly.loopstart, poly.totloop));
if (!sculpt_brush_test_sq_fn(&test, poly_center)) {
continue;

View File

@ -273,7 +273,7 @@ static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene,
if (ob->sculpt != nullptr) {
BKE_sculptsession_free(ob);
}
ob->sculpt = MEM_cnew<SculptSession>(__func__);
ob->sculpt = MEM_new<SculptSession>(__func__);
ob->sculpt->mode_type = OB_MODE_SCULPT;
/* Trigger evaluation of modifier stack to ensure

View File

@ -49,7 +49,7 @@ class AssetCatalogTreeView : public ui::AbstractTreeView {
SpaceFile &space_file_;
friend class AssetCatalogTreeViewItem;
friend class AssetCatalogDropController;
friend class AssetCatalogDropTarget;
friend class AssetCatalogTreeViewAllItem;
public:
@ -90,7 +90,7 @@ class AssetCatalogTreeViewItem : public ui::BasicTreeViewItem {
/** Add drag support for catalog items. */
std::unique_ptr<ui::AbstractViewItemDragController> create_drag_controller() const override;
/** Add dropping support for catalog items. */
std::unique_ptr<ui::AbstractViewItemDropController> create_drop_controller() const override;
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() const override;
};
class AssetCatalogDragController : public ui::AbstractViewItemDragController {
@ -105,15 +105,15 @@ class AssetCatalogDragController : public ui::AbstractViewItemDragController {
void on_drag_start() override;
};
class AssetCatalogDropController : public ui::AbstractViewItemDropController {
class AssetCatalogDropTarget : public ui::AbstractViewItemDropTarget {
AssetCatalogTreeItem &catalog_item_;
public:
AssetCatalogDropController(AssetCatalogTreeView &tree_view, AssetCatalogTreeItem &catalog_item);
AssetCatalogDropTarget(AssetCatalogTreeView &tree_view, AssetCatalogTreeItem &catalog_item);
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
std::string drop_tooltip(const wmDrag &drag) const override;
bool on_drop(struct bContext *C, const wmDrag &drag) override;
bool on_drop(struct bContext *C, const wmDrag &drag) const override;
::AssetLibrary &get_asset_library() const;
@ -146,29 +146,29 @@ class AssetCatalogTreeViewAllItem : public ui::BasicTreeViewItem {
void build_row(uiLayout &row) override;
struct DropController : public ui::AbstractViewItemDropController {
DropController(AssetCatalogTreeView &tree_view);
struct DropTarget : public ui::AbstractViewItemDropTarget {
DropTarget(AssetCatalogTreeView &tree_view);
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
std::string drop_tooltip(const wmDrag &drag) const override;
bool on_drop(struct bContext *C, const wmDrag &drag) override;
bool on_drop(struct bContext *C, const wmDrag &drag) const override;
};
std::unique_ptr<ui::AbstractViewItemDropController> create_drop_controller() const override;
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() const override;
};
class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
using BasicTreeViewItem::BasicTreeViewItem;
struct DropController : public ui::AbstractViewItemDropController {
DropController(AssetCatalogTreeView &tree_view);
struct DropTarget : public ui::AbstractViewItemDropTarget {
DropTarget(AssetCatalogTreeView &tree_view);
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
std::string drop_tooltip(const wmDrag &drag) const override;
bool on_drop(struct bContext *C, const wmDrag &drag) override;
bool on_drop(struct bContext *C, const wmDrag &drag) const override;
};
std::unique_ptr<ui::AbstractViewItemDropController> create_drop_controller() const override;
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() const override;
};
/* ---------------------------------------------------------------------- */
@ -339,10 +339,10 @@ bool AssetCatalogTreeViewItem::rename(StringRefNull new_name)
return true;
}
std::unique_ptr<ui::AbstractViewItemDropController> AssetCatalogTreeViewItem::
create_drop_controller() const
std::unique_ptr<ui::AbstractViewItemDropTarget> AssetCatalogTreeViewItem::create_drop_target()
const
{
return std::make_unique<AssetCatalogDropController>(
return std::make_unique<AssetCatalogDropTarget>(
static_cast<AssetCatalogTreeView &>(get_tree_view()), catalog_item_);
}
@ -355,13 +355,13 @@ std::unique_ptr<ui::AbstractViewItemDragController> AssetCatalogTreeViewItem::
/* ---------------------------------------------------------------------- */
AssetCatalogDropController::AssetCatalogDropController(AssetCatalogTreeView &tree_view,
AssetCatalogTreeItem &catalog_item)
: ui::AbstractViewItemDropController(tree_view), catalog_item_(catalog_item)
AssetCatalogDropTarget::AssetCatalogDropTarget(AssetCatalogTreeView &tree_view,
AssetCatalogTreeItem &catalog_item)
: ui::AbstractViewItemDropTarget(tree_view), catalog_item_(catalog_item)
{
}
bool AssetCatalogDropController::can_drop(const wmDrag &drag, const char **r_disabled_hint) const
bool AssetCatalogDropTarget::can_drop(const wmDrag &drag, const char **r_disabled_hint) const
{
if (drag.type == WM_DRAG_ASSET_CATALOG) {
const ::AssetLibrary &library = get_asset_library();
@ -389,7 +389,7 @@ bool AssetCatalogDropController::can_drop(const wmDrag &drag, const char **r_dis
return false;
}
std::string AssetCatalogDropController::drop_tooltip(const wmDrag &drag) const
std::string AssetCatalogDropTarget::drop_tooltip(const wmDrag &drag) const
{
if (drag.type == WM_DRAG_ASSET_CATALOG) {
return drop_tooltip_asset_catalog(drag);
@ -397,7 +397,7 @@ std::string AssetCatalogDropController::drop_tooltip(const wmDrag &drag) const
return drop_tooltip_asset_list(drag);
}
std::string AssetCatalogDropController::drop_tooltip_asset_catalog(const wmDrag &drag) const
std::string AssetCatalogDropTarget::drop_tooltip_asset_catalog(const wmDrag &drag) const
{
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
const AssetCatalog *src_catalog = get_drag_catalog(drag, get_asset_library());
@ -406,7 +406,7 @@ std::string AssetCatalogDropController::drop_tooltip_asset_catalog(const wmDrag
TIP_("into") + " '" + catalog_item_.get_name() + "'";
}
std::string AssetCatalogDropController::drop_tooltip_asset_list(const wmDrag &drag) const
std::string AssetCatalogDropTarget::drop_tooltip_asset_list(const wmDrag &drag) const
{
BLI_assert(drag.type == WM_DRAG_ASSET_LIST);
@ -429,7 +429,7 @@ std::string AssetCatalogDropController::drop_tooltip_asset_list(const wmDrag &dr
return basic_tip;
}
bool AssetCatalogDropController::on_drop(struct bContext *C, const wmDrag &drag)
bool AssetCatalogDropTarget::on_drop(struct bContext *C, const wmDrag &drag) const
{
if (drag.type == WM_DRAG_ASSET_CATALOG) {
return drop_asset_catalog_into_catalog(
@ -442,7 +442,7 @@ bool AssetCatalogDropController::on_drop(struct bContext *C, const wmDrag &drag)
catalog_item_.get_simple_name());
}
bool AssetCatalogDropController::drop_asset_catalog_into_catalog(
bool AssetCatalogDropTarget::drop_asset_catalog_into_catalog(
const wmDrag &drag,
AssetCatalogTreeView &tree_view,
const std::optional<CatalogID> drop_catalog_id)
@ -456,11 +456,11 @@ bool AssetCatalogDropController::drop_asset_catalog_into_catalog(
return true;
}
bool AssetCatalogDropController::drop_assets_into_catalog(struct bContext *C,
const AssetCatalogTreeView &tree_view,
const wmDrag &drag,
CatalogID catalog_id,
StringRefNull simple_name)
bool AssetCatalogDropTarget::drop_assets_into_catalog(struct bContext *C,
const AssetCatalogTreeView &tree_view,
const wmDrag &drag,
CatalogID catalog_id,
StringRefNull simple_name)
{
BLI_assert(drag.type == WM_DRAG_ASSET_LIST);
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
@ -491,8 +491,8 @@ bool AssetCatalogDropController::drop_assets_into_catalog(struct bContext *C,
return true;
}
AssetCatalog *AssetCatalogDropController::get_drag_catalog(const wmDrag &drag,
const ::AssetLibrary &asset_library)
AssetCatalog *AssetCatalogDropTarget::get_drag_catalog(const wmDrag &drag,
const ::AssetLibrary &asset_library)
{
if (drag.type != WM_DRAG_ASSET_CATALOG) {
return nullptr;
@ -504,8 +504,7 @@ AssetCatalog *AssetCatalogDropController::get_drag_catalog(const wmDrag &drag,
return catalog_service->find_catalog(catalog_drag->drag_catalog_id);
}
bool AssetCatalogDropController::has_droppable_asset(const wmDrag &drag,
const char **r_disabled_hint)
bool AssetCatalogDropTarget::has_droppable_asset(const wmDrag &drag, const char **r_disabled_hint)
{
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
@ -521,8 +520,8 @@ bool AssetCatalogDropController::has_droppable_asset(const wmDrag &drag,
return false;
}
bool AssetCatalogDropController::can_modify_catalogs(const ::AssetLibrary &library,
const char **r_disabled_hint)
bool AssetCatalogDropTarget::can_modify_catalogs(const ::AssetLibrary &library,
const char **r_disabled_hint)
{
if (ED_asset_catalogs_read_only(library)) {
*r_disabled_hint = "Catalogs cannot be edited in this asset library";
@ -531,7 +530,7 @@ bool AssetCatalogDropController::can_modify_catalogs(const ::AssetLibrary &libra
return true;
}
::AssetLibrary &AssetCatalogDropController::get_asset_library() const
::AssetLibrary &AssetCatalogDropTarget::get_asset_library() const
{
return *get_view<AssetCatalogTreeView>().asset_library_;
}
@ -580,30 +579,30 @@ void AssetCatalogTreeViewAllItem::build_row(uiLayout &row)
RNA_string_set(props, "parent_path", nullptr);
}
std::unique_ptr<ui::AbstractViewItemDropController> AssetCatalogTreeViewAllItem::
create_drop_controller() const
std::unique_ptr<ui::AbstractViewItemDropTarget> AssetCatalogTreeViewAllItem::create_drop_target()
const
{
return std::make_unique<AssetCatalogTreeViewAllItem::DropController>(
return std::make_unique<AssetCatalogTreeViewAllItem::DropTarget>(
static_cast<AssetCatalogTreeView &>(get_tree_view()));
}
AssetCatalogTreeViewAllItem::DropController::DropController(AssetCatalogTreeView &tree_view)
: ui::AbstractViewItemDropController(tree_view)
AssetCatalogTreeViewAllItem::DropTarget::DropTarget(AssetCatalogTreeView &tree_view)
: ui::AbstractViewItemDropTarget(tree_view)
{
}
bool AssetCatalogTreeViewAllItem::DropController::can_drop(const wmDrag &drag,
const char **r_disabled_hint) const
bool AssetCatalogTreeViewAllItem::DropTarget::can_drop(const wmDrag &drag,
const char **r_disabled_hint) const
{
if (drag.type != WM_DRAG_ASSET_CATALOG) {
return false;
}
::AssetLibrary &library = *get_view<AssetCatalogTreeView>().asset_library_;
if (!AssetCatalogDropController::can_modify_catalogs(library, r_disabled_hint)) {
if (!AssetCatalogDropTarget::can_modify_catalogs(library, r_disabled_hint)) {
return false;
}
const AssetCatalog *drag_catalog = AssetCatalogDropController::get_drag_catalog(drag, library);
const AssetCatalog *drag_catalog = AssetCatalogDropTarget::get_drag_catalog(drag, library);
if (drag_catalog->path.parent() == "") {
*r_disabled_hint = "Catalog is already placed at the highest level";
return false;
@ -612,21 +611,21 @@ bool AssetCatalogTreeViewAllItem::DropController::can_drop(const wmDrag &drag,
return true;
}
std::string AssetCatalogTreeViewAllItem::DropController::drop_tooltip(const wmDrag &drag) const
std::string AssetCatalogTreeViewAllItem::DropTarget::drop_tooltip(const wmDrag &drag) const
{
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
const AssetCatalog *drag_catalog = AssetCatalogDropController::get_drag_catalog(
const AssetCatalog *drag_catalog = AssetCatalogDropTarget::get_drag_catalog(
drag, *get_view<AssetCatalogTreeView>().asset_library_);
return std::string(TIP_("Move Catalog")) + " '" + drag_catalog->path.name() + "' " +
TIP_("to the top level of the tree");
}
bool AssetCatalogTreeViewAllItem::DropController::on_drop(struct bContext * /*C*/,
const wmDrag &drag)
bool AssetCatalogTreeViewAllItem::DropTarget::on_drop(struct bContext * /*C*/,
const wmDrag &drag) const
{
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
return AssetCatalogDropController::drop_asset_catalog_into_catalog(
return AssetCatalogDropTarget::drop_asset_catalog_into_catalog(
drag,
get_view<AssetCatalogTreeView>(),
/* No value to drop into the root level. */
@ -635,29 +634,28 @@ bool AssetCatalogTreeViewAllItem::DropController::on_drop(struct bContext * /*C*
/* ---------------------------------------------------------------------- */
std::unique_ptr<ui::AbstractViewItemDropController> AssetCatalogTreeViewUnassignedItem::
create_drop_controller() const
std::unique_ptr<ui::AbstractViewItemDropTarget> AssetCatalogTreeViewUnassignedItem::
create_drop_target() const
{
return std::make_unique<AssetCatalogTreeViewUnassignedItem::DropController>(
return std::make_unique<AssetCatalogTreeViewUnassignedItem::DropTarget>(
static_cast<AssetCatalogTreeView &>(get_tree_view()));
}
AssetCatalogTreeViewUnassignedItem::DropController::DropController(AssetCatalogTreeView &tree_view)
: ui::AbstractViewItemDropController(tree_view)
AssetCatalogTreeViewUnassignedItem::DropTarget::DropTarget(AssetCatalogTreeView &tree_view)
: ui::AbstractViewItemDropTarget(tree_view)
{
}
bool AssetCatalogTreeViewUnassignedItem::DropController::can_drop(
const wmDrag &drag, const char **r_disabled_hint) const
bool AssetCatalogTreeViewUnassignedItem::DropTarget::can_drop(const wmDrag &drag,
const char **r_disabled_hint) const
{
if (drag.type != WM_DRAG_ASSET_LIST) {
return false;
}
return AssetCatalogDropController::has_droppable_asset(drag, r_disabled_hint);
return AssetCatalogDropTarget::has_droppable_asset(drag, r_disabled_hint);
}
std::string AssetCatalogTreeViewUnassignedItem::DropController::drop_tooltip(
const wmDrag &drag) const
std::string AssetCatalogTreeViewUnassignedItem::DropTarget::drop_tooltip(const wmDrag &drag) const
{
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
const bool is_multiple_assets = !BLI_listbase_is_single(asset_drags);
@ -666,11 +664,11 @@ std::string AssetCatalogTreeViewUnassignedItem::DropController::drop_tooltip(
TIP_("Move asset out of any catalog");
}
bool AssetCatalogTreeViewUnassignedItem::DropController::on_drop(struct bContext *C,
const wmDrag &drag)
bool AssetCatalogTreeViewUnassignedItem::DropTarget::on_drop(struct bContext *C,
const wmDrag &drag) const
{
/* Assign to nil catalog ID. */
return AssetCatalogDropController::drop_assets_into_catalog(
return AssetCatalogDropTarget::drop_assets_into_catalog(
C, get_view<AssetCatalogTreeView>(), drag, CatalogID{});
}

View File

@ -251,8 +251,8 @@ static int adjacent_edge(const Span<int> corner_verts,
const int vertex)
{
const int adjacent_loop_i = (corner_verts[loop_i] == vertex) ?
bke::mesh_topology::poly_loop_prev(poly, loop_i) :
bke::mesh_topology::poly_loop_next(poly, loop_i);
bke::mesh::poly_corner_prev(poly, loop_i) :
bke::mesh::poly_corner_next(poly, loop_i);
return corner_edges[adjacent_loop_i];
}

View File

@ -1476,7 +1476,6 @@ struct EdgeFeatData {
Object *ob_eval; /* For evaluated materials. */
const int *material_indices;
blender::Span<MEdge> edges;
blender::Span<MPoly> polys;
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
blender::Span<MLoopTri> looptris;
@ -2106,7 +2105,6 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info,
edge_feat_data.ob_eval = ob_info->original_ob_eval;
edge_feat_data.material_indices = material_indices;
edge_feat_data.edges = me->edges();
edge_feat_data.polys = me->polys();
edge_feat_data.corner_verts = me->corner_verts();
edge_feat_data.corner_edges = me->corner_edges();
edge_feat_data.looptris = looptris;

View File

@ -398,10 +398,6 @@ enum {
/** \name Utility Macros
* \{ */
#define ME_POLY_LOOP_PREV(poly, i) \
((poly)->loopstart + (((i) + (poly)->totloop - 1) % (poly)->totloop))
#define ME_POLY_LOOP_NEXT(poly, i) ((poly)->loopstart + (((i) + 1) % (poly)->totloop))
/** Number of tri's that make up this polygon once tessellated. */
#define ME_POLY_TRI_TOT(poly) ((poly)->totloop - 2)

View File

@ -2242,8 +2242,7 @@ bool rna_GPencil_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
bool rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
{
SculptSession *ss = ((Object *)ptr->owner_id)->sculpt;
return (ss && ss->bm);
return BKE_object_sculpt_use_dyntopo((Object *)ptr->owner_id);
}
static void rna_object_lineart_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)

View File

@ -385,8 +385,8 @@ static void rna_Sculpt_update(bContext *C, PointerRNA *UNUSED(ptr))
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
if (ob->sculpt) {
ob->sculpt->bm_smooth_shading = ((scene->toolsettings->sculpt->flags &
SCULPT_DYNTOPO_SMOOTH_SHADING) != 0);
BKE_object_sculpt_dyntopo_smooth_shading_set(
ob, ((scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING) != 0));
}
}
}

View File

@ -245,8 +245,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
sculpt_session->totvert = mesh->totvert;
sculpt_session->totpoly = mesh->totpoly;
sculpt_session->vert_positions = nullptr;
sculpt_session->polys = nullptr;
sculpt_session->corner_verts = nullptr;
sculpt_session->polys = {};
sculpt_session->corner_verts = {};
}
// BKE_subdiv_stats_print(&subdiv->stats);
}

View File

@ -464,8 +464,8 @@ static Frame **collect_hull_frames(int v,
hull_frames = MEM_cnew_array<Frame *>(*tothullframe, __func__);
hull_frames_num = 0;
for (i = 0; i < emap[v].count; i++) {
const MEdge *edge = &edges[emap[v].indices[i]];
f = &frames[BKE_mesh_edge_other_vert(edge, v)];
const MEdge &edge = edges[emap[v].indices[i]];
f = &frames[blender::bke::mesh::edge_other_vert(edge, v)];
/* Can't have adjacent branch nodes yet */
if (f->totframe) {
hull_frames[hull_frames_num++] = &f->frames[0];
@ -745,7 +745,7 @@ static void build_emats_stack(BLI_Stack *stack,
parent_is_branch = ((emap[parent_v].count > 2) || (vs[parent_v].flag & MVERT_SKIN_ROOT));
v = BKE_mesh_edge_other_vert(&edges[e], parent_v);
v = blender::bke::mesh::edge_other_vert(edges[e], parent_v);
emat[e].origin = parent_v;
/* If parent is a branch node, start a new edge chain */
@ -796,9 +796,10 @@ static EMat *build_edge_mats(const MVertSkin *vs,
for (v = 0; v < verts_num; v++) {
if (vs[v].flag & MVERT_SKIN_ROOT) {
if (emap[v].count >= 1) {
const MEdge *edge = &edges[emap[v].indices[0]];
calc_edge_mat(
stack_elem.mat, vert_positions[v], vert_positions[BKE_mesh_edge_other_vert(edge, v)]);
const MEdge &edge = edges[emap[v].indices[0]];
calc_edge_mat(stack_elem.mat,
vert_positions[v],
vert_positions[blender::bke::mesh::edge_other_vert(edge, v)]);
stack_elem.parent_v = v;
/* Add adjacent edges to stack */

View File

@ -82,7 +82,7 @@ class CornerPreviousEdgeFieldInput final : public bke::MeshFieldInput {
mesh.totloop,
[polys, corner_edges, loop_to_poly_map = std::move(loop_to_poly_map)](const int corner_i) {
const MPoly &poly = polys[loop_to_poly_map[corner_i]];
return corner_edges[bke::mesh_topology::poly_loop_prev(poly, corner_i)];
return corner_edges[bke::mesh::poly_corner_prev(poly, corner_i)];
});
}

View File

@ -48,7 +48,7 @@ static void report_deprecated_call(const char *function_name)
}
char message[256];
SNPRINTF(message,
"'bgl.gl%s' is deprecated and will be removed in Blender 3.7. Report or update your "
"'bgl.gl%s' is deprecated and will be removed in Blender 4.0. Report or update your "
"script to use 'gpu' module.",
function_name);
CLOG_WARN(&LOG, "%s", message);
@ -2653,7 +2653,7 @@ PyObject *BPyInit_bgl(void)
if (GPU_backend_get_type() != GPU_BACKEND_OPENGL) {
CLOG_WARN(&LOG,
"'bgl' imported without an OpenGL backend. Please update your add-ons to use the "
"'gpu' module. In Blender 3.7 'bgl' will be removed.");
"'gpu' module. In Blender 4.0 'bgl' will be removed.");
}
PyModule_AddObject(submodule, "Buffer", (PyObject *)&BGL_bufferType);