Sculpt-dev: cross-module ref cleanup
* Removed a bunch of nasty editors->blenkernel dependencies (2 still remain). * Fixed a few bugs in last commit.
This commit is contained in:
parent
e724479ca6
commit
c4781c7243
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "BKE_brush_engine.h"
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_attribute.h"
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -604,6 +605,32 @@ typedef struct SculptFakeNeighbors {
|
|||
|
||||
/* Session data (mode-specific) */
|
||||
|
||||
/* Custom Temporary Attributes */
|
||||
|
||||
typedef struct SculptLayerParams {
|
||||
int simple_array : 1; // cannot be combined with permanent
|
||||
int permanent : 1; // cannot be combined with simple_array
|
||||
int nocopy : 1;
|
||||
int nointerp : 1;
|
||||
} SculptLayerParams;
|
||||
|
||||
typedef struct SculptCustomLayer {
|
||||
AttributeDomain domain;
|
||||
int proptype;
|
||||
SculptLayerParams params;
|
||||
|
||||
char name[512];
|
||||
|
||||
bool is_cdlayer; // false for multires data
|
||||
void *data; // only valid for multires and face
|
||||
int elemsize;
|
||||
int cd_offset; // for bmesh
|
||||
struct CustomDataLayer *layer; // not for multires
|
||||
bool from_bmesh; // note that layers can be fixed arrays but still from a bmesh, e.g. filter
|
||||
// laplacian smooth
|
||||
bool released;
|
||||
} SculptCustomLayer;
|
||||
|
||||
/* These custom attributes have references
|
||||
(SculptCustomLayer pointers) inside of ss->custom_layers
|
||||
that are kept up to date with SCULPT_update_customdata_refs.
|
||||
|
@ -851,8 +878,20 @@ 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);
|
||||
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, struct PBVH *pbvh, int totvert);
|
||||
void BKE_sculptsession_sync_attributes(struct Object *ob, struct Mesh *me);
|
||||
struct BMesh *BKE_sculptsession_empty_bmesh_create();
|
||||
void BKE_sculptsession_bmesh_add_layers(struct Object *ob);
|
||||
bool BKE_sculptsession_customlayer_get(struct Object *ob,
|
||||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name,
|
||||
SculptCustomLayer *scl,
|
||||
SculptLayerParams *params);
|
||||
void BKE_sculptsession_bmesh_attr_update_internal(struct Object *ob);
|
||||
void BKE_sculptsession_update_attr_refs(struct Object *ob);
|
||||
int BKE_sculptsession_get_totvert(const SculptSession *ss);
|
||||
|
||||
/* Create new color layer on object if it doesn't have one and if experimental feature set has
|
||||
/* Create new color layer on object if it doesn't have one and if experimental feature set has
|
||||
* sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */
|
||||
void BKE_sculpt_color_layer_create_if_needed(struct Object *object);
|
||||
|
||||
|
|
|
@ -608,8 +608,7 @@ int BKE_id_attribute_index_from_ref(ID *id,
|
|||
for (int i = 0; i < data->totlayer; i++) {
|
||||
CustomDataLayer *layer = data->layers + i;
|
||||
|
||||
if (layer->type == ref->type &&
|
||||
STREQ(layer->name, ref->name)) {
|
||||
if (layer->type == ref->type && STREQ(layer->name, ref->name)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -643,15 +642,15 @@ bool BKE_id_attribute_ref_from_index(ID *id,
|
|||
for (int i = 0; i < data->totlayer; i++) {
|
||||
CustomDataLayer *layer = data->layers + i;
|
||||
|
||||
if (index == attr_index) {
|
||||
r_ref->domain = domain;
|
||||
r_ref->type = layer->type;
|
||||
BLI_strncpy_utf8(r_ref->name, layer->name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CD_TYPE_AS_MASK(layer->type) & type_filter) {
|
||||
if (index == attr_index) {
|
||||
r_ref->domain = domain;
|
||||
r_ref->type = layer->type;
|
||||
BLI_strncpy_utf8(r_ref->name, layer->name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,10 +38,13 @@
|
|||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
|
||||
#include "BLI_array.h"
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_hash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
@ -82,12 +85,8 @@
|
|||
#include "bmesh.h"
|
||||
|
||||
// TODO: figure out bad cross module refs
|
||||
void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me);
|
||||
void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
|
||||
void SCULPT_dyntopo_node_layers_add(SculptSession *ss, Object *ob);
|
||||
BMesh *SCULPT_dyntopo_empty_bmesh();
|
||||
void SCULPT_undo_ensure_bmlog(Object *ob);
|
||||
void SCULPT_update_customdata_refs(SculptSession *ss, Object *ob);
|
||||
|
||||
static void init_mdyntopo_layer(SculptSession *ss, PBVH *pbvh, int totvert);
|
||||
|
||||
|
@ -1899,7 +1898,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
|
||||
if (idx == -1) {
|
||||
BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_SHAPEKEY, key->name);
|
||||
SCULPT_update_customdata_refs(ss, ob);
|
||||
BKE_sculptsession_update_attr_refs(ob);
|
||||
|
||||
idx = CustomData_get_named_layer_index(&ss->bm->vdata, CD_SHAPEKEY, key->name);
|
||||
ss->bm->vdata.layers[idx].uid = key->uid;
|
||||
|
@ -1945,7 +1944,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
int cd_co = ss->bm->vdata.layers[idx].offset;
|
||||
ss->bm->vdata.layers[idx].uid = newkey->uid;
|
||||
|
||||
SCULPT_update_customdata_refs(ss, ob);
|
||||
BKE_sculptsession_update_attr_refs(ob);
|
||||
|
||||
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
|
||||
float *keyco = BM_ELEM_CD_GET_VOID_P(v, cd_co);
|
||||
|
@ -2026,7 +2025,7 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval)
|
|||
|
||||
BLI_assert(me_eval != NULL);
|
||||
sculpt_update_object(depsgraph, ob_orig, me_eval, false, false, false);
|
||||
SCULPT_dynamic_topology_sync_layers(ob_orig, me_orig);
|
||||
BKE_sculptsession_sync_attributes(ob_orig, me_orig);
|
||||
}
|
||||
|
||||
void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
|
||||
|
@ -2603,7 +2602,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
else if (BKE_pbvh_type(pbvh) == PBVH_BMESH) {
|
||||
// Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
|
||||
SCULPT_dynamic_topology_sync_layers(ob, BKE_object_get_original_mesh(ob));
|
||||
BKE_sculptsession_sync_attributes(ob, BKE_object_get_original_mesh(ob));
|
||||
}
|
||||
return pbvh;
|
||||
}
|
||||
|
@ -2621,7 +2620,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
bool is_dyntopo = (mesh_orig->flag & ME_SCULPT_DYNAMIC_TOPOLOGY);
|
||||
|
||||
if (is_dyntopo) {
|
||||
BMesh *bm = SCULPT_dyntopo_empty_bmesh();
|
||||
BMesh *bm = BKE_sculptsession_empty_bmesh_create();
|
||||
|
||||
ob->sculpt->bm = bm;
|
||||
|
||||
|
@ -2636,12 +2635,12 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
.copy_temp_cdlayers = true,
|
||||
.cd_mask_extra = CD_MASK_DYNTOPO_VERT}));
|
||||
|
||||
SCULPT_dyntopo_node_layers_add(ob->sculpt, ob);
|
||||
BKE_sculptsession_bmesh_add_layers(ob);
|
||||
SCULPT_undo_ensure_bmlog(ob);
|
||||
|
||||
pbvh = build_pbvh_for_dynamic_topology(ob, true);
|
||||
|
||||
SCULPT_update_customdata_refs(ob->sculpt, ob);
|
||||
BKE_sculptsession_update_attr_refs(ob);
|
||||
}
|
||||
else {
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
|
@ -2730,3 +2729,575 @@ void BKE_paint_face_set_overlay_color_get(const int face_set, const int seed, uc
|
|||
&rgba[2]);
|
||||
rgba_float_to_uchar(r_color, rgba);
|
||||
}
|
||||
|
||||
int BKE_sculptsession_get_totvert(const SculptSession *ss)
|
||||
{
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES:
|
||||
return ss->totvert;
|
||||
case PBVH_BMESH:
|
||||
return BM_mesh_elem_count(BKE_pbvh_get_bmesh(ss->pbvh), BM_VERT);
|
||||
case PBVH_GRIDS:
|
||||
return BKE_pbvh_get_grid_num_vertices(ss->pbvh);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Syncs customdata layers with internal bmesh, but ignores deleted layers.
|
||||
*/
|
||||
void BKE_sculptsession_sync_attributes(struct Object *ob, struct Mesh *me)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (!ss || !ss->bm) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool modified = false;
|
||||
BMesh *bm = ss->bm;
|
||||
|
||||
CustomData *cd1[4] = {&me->vdata, &me->edata, &me->ldata, &me->pdata};
|
||||
CustomData *cd2[4] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
|
||||
int badmask = CD_MASK_MLOOP | CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_ORIGINDEX |
|
||||
CD_MASK_ORIGSPACE | CD_MASK_MFACE;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CustomDataLayer **newlayers = NULL;
|
||||
BLI_array_declare(newlayers);
|
||||
|
||||
CustomData *data1 = cd1[i];
|
||||
CustomData *data2 = cd2[i];
|
||||
|
||||
if (!data1->layers) {
|
||||
modified |= data2->layers != NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < data1->totlayer; j++) {
|
||||
CustomDataLayer *cl1 = data1->layers + j;
|
||||
|
||||
if ((1 << cl1->type) & badmask) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
|
||||
if (idx < 0) {
|
||||
BLI_array_append(newlayers, cl1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < BLI_array_len(newlayers); j++) {
|
||||
BM_data_layer_add_named(bm, data2, newlayers[j]->type, newlayers[j]->name);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/* sync various ids */
|
||||
for (int j = 0; j < data1->totlayer; j++) {
|
||||
CustomDataLayer *cl1 = data1->layers + j;
|
||||
|
||||
if ((1 << cl1->type) & badmask) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
|
||||
|
||||
if (idx == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CustomDataLayer *cl2 = data2->layers + idx;
|
||||
|
||||
cl2->anonymous_id = cl1->anonymous_id;
|
||||
cl2->uid = cl1->uid;
|
||||
}
|
||||
|
||||
bool typemap[CD_NUMTYPES] = {0};
|
||||
|
||||
for (int j = 0; j < data1->totlayer; j++) {
|
||||
CustomDataLayer *cl1 = data1->layers + j;
|
||||
|
||||
if ((1 << cl1->type) & badmask) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typemap[cl1->type]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
typemap[cl1->type] = true;
|
||||
|
||||
// find first layer
|
||||
int baseidx = CustomData_get_layer_index(data2, cl1->type);
|
||||
|
||||
if (baseidx < 0) {
|
||||
modified |= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
CustomDataLayer *cl2 = data2->layers + baseidx;
|
||||
|
||||
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active].name);
|
||||
if (idx >= 0) {
|
||||
modified |= idx - baseidx != cl2->active;
|
||||
cl2->active = idx - baseidx;
|
||||
}
|
||||
|
||||
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_rnd].name);
|
||||
if (idx >= 0) {
|
||||
modified |= idx - baseidx != cl2->active_rnd;
|
||||
cl2->active_rnd = idx - baseidx;
|
||||
}
|
||||
|
||||
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_mask].name);
|
||||
if (idx >= 0) {
|
||||
modified |= idx - baseidx != cl2->active_mask;
|
||||
cl2->active_mask = idx - baseidx;
|
||||
}
|
||||
|
||||
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_clone].name);
|
||||
if (idx >= 0) {
|
||||
modified |= idx - baseidx != cl2->active_clone;
|
||||
cl2->active_clone = idx - baseidx;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_array_free(newlayers);
|
||||
}
|
||||
|
||||
if (modified && ss->bm) {
|
||||
CustomData_regen_active_refs(&ss->bm->vdata);
|
||||
CustomData_regen_active_refs(&ss->bm->edata);
|
||||
CustomData_regen_active_refs(&ss->bm->ldata);
|
||||
CustomData_regen_active_refs(&ss->bm->pdata);
|
||||
}
|
||||
|
||||
BKE_sculptsession_update_attr_refs(ob);
|
||||
}
|
||||
|
||||
BMesh *BKE_sculptsession_empty_bmesh_create()
|
||||
{
|
||||
const BMAllocTemplate allocsize = {
|
||||
.totvert = 2048 * 16, .totface = 2048 * 16, .totloop = 4196 * 16, .totedge = 2048 * 16};
|
||||
|
||||
BMesh *bm = BM_mesh_create(
|
||||
&allocsize,
|
||||
&((struct BMeshCreateParams){.use_toolflags = false,
|
||||
.create_unique_ids = true,
|
||||
.id_elem_mask = BM_VERT | BM_EDGE | BM_FACE,
|
||||
.id_map = true,
|
||||
.temporary_ids = false,
|
||||
.no_reuse_ids = false}));
|
||||
|
||||
return bm;
|
||||
}
|
||||
|
||||
char dyntopop_node_idx_layer_id[] = "_dyntopo_node_id";
|
||||
char dyntopop_faces_areas_layer_id[] = "__dyntopo_face_areas";
|
||||
|
||||
void BKE_sculptsession_bmesh_add_layers(Object *ob)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
int cd_node_layer_index, cd_face_node_layer_index;
|
||||
|
||||
BMCustomLayerReq vlayers[] = {
|
||||
{CD_PAINT_MASK, NULL, 0},
|
||||
{CD_DYNTOPO_VERT, NULL, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
|
||||
{CD_PROP_INT32, dyntopop_node_idx_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY}};
|
||||
|
||||
BM_data_layers_ensure(ss->bm, &ss->bm->vdata, vlayers, 3);
|
||||
|
||||
ss->cd_vert_mask_offset = CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK);
|
||||
|
||||
BMCustomLayerReq flayers[] = {
|
||||
{CD_PROP_INT32, dyntopop_node_idx_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
|
||||
{CD_PROP_FLOAT, dyntopop_faces_areas_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
|
||||
};
|
||||
BM_data_layers_ensure(ss->bm, &ss->bm->pdata, flayers, 2);
|
||||
|
||||
// get indices again, as they might have changed after adding new layers
|
||||
cd_node_layer_index = CustomData_get_named_layer_index(
|
||||
&ss->bm->vdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
|
||||
cd_face_node_layer_index = CustomData_get_named_layer_index(
|
||||
&ss->bm->pdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
|
||||
|
||||
ss->cd_sculpt_vert = CustomData_get_offset(&ss->bm->vdata, CD_DYNTOPO_VERT);
|
||||
|
||||
ss->cd_vert_node_offset = CustomData_get_n_offset(
|
||||
&ss->bm->vdata,
|
||||
CD_PROP_INT32,
|
||||
cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT32));
|
||||
|
||||
ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
|
||||
ss->cd_face_node_offset = CustomData_get_n_offset(
|
||||
&ss->bm->pdata,
|
||||
CD_PROP_INT32,
|
||||
cd_face_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT32));
|
||||
|
||||
ss->bm->pdata.layers[cd_face_node_layer_index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
ss->cd_faceset_offset = CustomData_get_offset(&ss->bm->pdata, CD_SCULPT_FACE_SETS);
|
||||
|
||||
ss->cd_face_areas = CustomData_get_named_layer(
|
||||
&ss->bm->pdata, CD_PROP_FLOAT, dyntopop_faces_areas_layer_id);
|
||||
ss->cd_face_areas = ss->bm->pdata.layers[ss->cd_face_areas].offset;
|
||||
|
||||
AttributeDomain domain;
|
||||
CustomDataLayer *cl;
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
|
||||
if (BKE_pbvh_get_color_layer(ss->pbvh, me, &cl, &domain)) {
|
||||
ss->vcol_domain = (int)domain;
|
||||
ss->vcol_type = cl->type;
|
||||
ss->cd_vcol_offset = cl->offset;
|
||||
}
|
||||
else {
|
||||
ss->cd_vcol_offset = -1;
|
||||
ss->vcol_type = -1;
|
||||
ss->vcol_domain = (int)ATTR_DOMAIN_NUM;
|
||||
}
|
||||
}
|
||||
|
||||
static bool sculpt_temp_customlayer_get(SculptSession *ss,
|
||||
Object *ob,
|
||||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name,
|
||||
SculptCustomLayer *out,
|
||||
bool autocreate,
|
||||
SculptLayerParams *params)
|
||||
{
|
||||
if (ss->save_temp_layers && !params->simple_array) {
|
||||
params->permanent = true;
|
||||
}
|
||||
|
||||
bool simple_array = params->simple_array;
|
||||
bool permanent = params->permanent;
|
||||
bool nocopy = params->nocopy;
|
||||
bool nointerp = params->nointerp;
|
||||
|
||||
out->params = *params;
|
||||
out->proptype = proptype;
|
||||
out->domain = domain;
|
||||
BLI_strncpy_utf8(out->name, name, sizeof(out->name));
|
||||
|
||||
if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
|
||||
if (permanent) {
|
||||
printf(
|
||||
"%s: error: tried to make permanent customdata in multires mode; will make local "
|
||||
"array "
|
||||
"instead.\n",
|
||||
__func__);
|
||||
permanent = false;
|
||||
}
|
||||
|
||||
// customdata attribute layers not supported for grids
|
||||
simple_array = true;
|
||||
out->params.simple_array = true;
|
||||
}
|
||||
|
||||
BLI_assert(!(simple_array && permanent));
|
||||
|
||||
if (simple_array) {
|
||||
CustomData *cdata = NULL;
|
||||
int totelem = 0;
|
||||
|
||||
PBVHType pbvhtype = ss->pbvh ? BKE_pbvh_type(ss->pbvh) : (ss->bm ? PBVH_BMESH : PBVH_FACES);
|
||||
|
||||
switch (pbvhtype) {
|
||||
case PBVH_BMESH: {
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &ss->bm->vdata;
|
||||
totelem = ss->bm->totvert;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = &ss->bm->pdata;
|
||||
totelem = ss->bm->totface;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = ss->vdata;
|
||||
totelem = BKE_sculptsession_get_totvert(ss);
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = ss->pdata;
|
||||
totelem = ss->totfaces;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PBVH_FACES: {
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = ss->vdata;
|
||||
totelem = ss->totvert;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = ss->pdata;
|
||||
totelem = ss->totfaces;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CustomData dummy = {0};
|
||||
CustomData_reset(&dummy);
|
||||
CustomData_add_layer(&dummy, proptype, CD_ASSIGN, NULL, 0);
|
||||
int elemsize = (int)CustomData_get_elem_size(dummy.layers);
|
||||
|
||||
CustomData_free(&dummy, 0);
|
||||
|
||||
out->data = MEM_calloc_arrayN(totelem, elemsize, name);
|
||||
|
||||
out->is_cdlayer = false;
|
||||
out->from_bmesh = ss->bm != NULL;
|
||||
out->cd_offset = -1;
|
||||
out->layer = NULL;
|
||||
out->domain = domain;
|
||||
out->proptype = proptype;
|
||||
out->elemsize = elemsize;
|
||||
|
||||
/*grids cannot store normal customdata layers, and thus
|
||||
we cannot rely on the customdata api to keep track of
|
||||
and free their memory for us.
|
||||
|
||||
so instead we queue them in a dynamic array inside of
|
||||
SculptSession.
|
||||
*/
|
||||
if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
|
||||
ss->tot_layers_to_free++;
|
||||
|
||||
if (!ss->layers_to_free) {
|
||||
ss->layers_to_free = MEM_calloc_arrayN(
|
||||
ss->tot_layers_to_free, sizeof(void *), "ss->layers_to_free");
|
||||
}
|
||||
else {
|
||||
ss->layers_to_free = MEM_recallocN(ss->layers_to_free,
|
||||
sizeof(void *) * ss->tot_layers_to_free);
|
||||
}
|
||||
|
||||
SculptCustomLayer *cpy = MEM_callocN(sizeof(SculptCustomLayer), "SculptCustomLayer cpy");
|
||||
*cpy = *out;
|
||||
|
||||
ss->layers_to_free[ss->tot_layers_to_free - 1] = cpy;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH: {
|
||||
CustomData *cdata = NULL;
|
||||
out->from_bmesh = true;
|
||||
|
||||
if (!ss->bm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &ss->bm->vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = &ss->bm->pdata;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (idx < 0) {
|
||||
if (!autocreate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BM_data_layer_add_named(ss->bm, cdata, proptype, name);
|
||||
idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
BKE_sculptsession_bmesh_attr_update_internal(ob);
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
}
|
||||
|
||||
if (nocopy) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_ELEM_NOCOPY;
|
||||
}
|
||||
if (nointerp) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_ELEM_NOINTERP;
|
||||
}
|
||||
|
||||
out->data = NULL;
|
||||
out->is_cdlayer = true;
|
||||
out->layer = cdata->layers + idx;
|
||||
out->cd_offset = out->layer->offset;
|
||||
out->elemsize = CustomData_get_elem_size(out->layer);
|
||||
|
||||
break;
|
||||
}
|
||||
case PBVH_FACES: {
|
||||
CustomData *cdata = NULL;
|
||||
int totelem = 0;
|
||||
|
||||
out->from_bmesh = false;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
totelem = ss->totvert;
|
||||
cdata = ss->vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
totelem = ss->totfaces;
|
||||
cdata = ss->pdata;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (idx < 0) {
|
||||
if (!autocreate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CustomData_add_layer_named(cdata, proptype, CD_CALLOC, NULL, totelem, name);
|
||||
idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
}
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
|
||||
out->data = NULL;
|
||||
out->is_cdlayer = true;
|
||||
out->layer = cdata->layers + idx;
|
||||
out->cd_offset = -1;
|
||||
out->data = out->layer->data;
|
||||
out->elemsize = CustomData_get_elem_size(out->layer);
|
||||
break;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
CustomData *cdata = NULL;
|
||||
int totelem = 0;
|
||||
|
||||
out->from_bmesh = false;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
totelem = BKE_pbvh_get_grid_num_vertices(ss->pbvh);
|
||||
cdata = &ss->temp_vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
// not supported
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (idx < 0) {
|
||||
if (!autocreate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CustomData_add_layer_named(cdata, proptype, CD_CALLOC, NULL, totelem, name);
|
||||
idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
}
|
||||
|
||||
if (nocopy) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_ELEM_NOCOPY;
|
||||
}
|
||||
if (nointerp) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_ELEM_NOINTERP;
|
||||
}
|
||||
|
||||
out->data = NULL;
|
||||
out->is_cdlayer = true;
|
||||
out->layer = cdata->layers + idx;
|
||||
out->cd_offset = -1;
|
||||
out->data = out->layer->data;
|
||||
out->elemsize = CustomData_get_elem_size(out->layer);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BKE_sculptsession_customlayer_get(Object *ob,
|
||||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name,
|
||||
SculptCustomLayer *scl,
|
||||
SculptLayerParams *params)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
bool ret = sculpt_temp_customlayer_get(ss, ob, domain, proptype, name, scl, true, params);
|
||||
BKE_sculptsession_update_attr_refs(ob);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BKE_sculptsession_bmesh_attr_update_internal(Object *ob)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
BKE_sculptsession_bmesh_add_layers(ob);
|
||||
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_update_offsets(ss->pbvh,
|
||||
ss->cd_vert_node_offset,
|
||||
ss->cd_face_node_offset,
|
||||
ss->cd_sculpt_vert,
|
||||
ss->cd_face_areas);
|
||||
}
|
||||
if (ss->bm_log) {
|
||||
BM_log_set_cd_offsets(ss->bm_log, ss->cd_sculpt_vert);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_sculptsession_update_attr_refs(Object *ob)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
/* run twice, in case sculpt_temp_customlayer_get had to recreate a layer and
|
||||
messed up the ordering. */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < SCULPT_SCL_LAYER_MAX; j++) {
|
||||
SculptCustomLayer *scl = ss->custom_layers[j];
|
||||
|
||||
if (scl && !scl->released && !scl->params.simple_array) {
|
||||
sculpt_temp_customlayer_get(
|
||||
ss, ob, scl->domain, scl->proptype, scl->name, scl, true, &scl->params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ss->bm) {
|
||||
BKE_sculptsession_bmesh_attr_update_internal(ob);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace blender::draw {
|
|||
/** \name Extract VCol
|
||||
* \{ */
|
||||
|
||||
ATTR_NO_OPT static void extract_vcol_init(const MeshRenderData *mr,
|
||||
static void extract_vcol_init(const MeshRenderData *mr,
|
||||
struct MeshBatchCache *cache,
|
||||
void *buf,
|
||||
void *UNUSED(tls_data))
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
|
||||
#include "ED_object.h"
|
||||
|
||||
#include "geometry_intern.h"
|
||||
|
@ -154,6 +156,66 @@ void GEOMETRY_OT_attribute_add(wmOperatorType *ot)
|
|||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
static void next_color_attr(struct ID *id, bool is_render)
|
||||
{
|
||||
AttributeRef *ref = is_render ? BKE_id_attributes_render_color_ref_p(id) :
|
||||
BKE_id_attributes_active_color_ref_p(id);
|
||||
|
||||
if (!ref) {
|
||||
return;
|
||||
}
|
||||
|
||||
AttributeDomainMask domain_mask = ATTR_DOMAIN_MASK_POINT | ATTR_DOMAIN_MASK_CORNER;
|
||||
CustomDataMask type_mask = CD_MASK_PROP_COLOR | CD_MASK_MLOOPCOL;
|
||||
|
||||
int length = BKE_id_attributes_length(id, domain_mask, type_mask);
|
||||
int idx = BKE_id_attribute_index_from_ref(id, ref, domain_mask, type_mask);
|
||||
|
||||
if (idx == length - 1) {
|
||||
idx = MAX2(idx - 1, 0);
|
||||
}
|
||||
else {
|
||||
idx++;
|
||||
}
|
||||
|
||||
BKE_id_attribute_ref_from_index(id, idx, domain_mask, type_mask, ref);
|
||||
}
|
||||
|
||||
static void next_color_attrs(struct ID *id)
|
||||
{
|
||||
next_color_attr(id, false); /* active */
|
||||
next_color_attr(id, true); /* render */
|
||||
}
|
||||
|
||||
static int geometry_color_attribute_add_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = ED_object_context(C);
|
||||
ID *id = ob->data;
|
||||
|
||||
char name[MAX_NAME];
|
||||
RNA_string_get(op->ptr, "name", name);
|
||||
CustomDataType type = (CustomDataType)RNA_enum_get(op->ptr, "data_type");
|
||||
AttributeDomain domain = (AttributeDomain)RNA_enum_get(op->ptr, "domain");
|
||||
CustomDataLayer *layer = BKE_id_attribute_new(
|
||||
id, name, type, CD_MASK_PROP_ALL, domain, op->reports);
|
||||
|
||||
if (layer == NULL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_id_attributes_active_color_set(id, layer);
|
||||
|
||||
if (ob->mode == OB_MODE_SCULPT) {
|
||||
BKE_sculpt_update_object_for_edit(
|
||||
CTX_data_ensure_evaluated_depsgraph(C), ob, false, false, false);
|
||||
}
|
||||
|
||||
DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GEOMETRY_OT_color_attribute_add(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
|
@ -163,7 +225,7 @@ void GEOMETRY_OT_color_attribute_add(wmOperatorType *ot)
|
|||
|
||||
/* api callbacks */
|
||||
ot->poll = geometry_attributes_poll;
|
||||
ot->exec = geometry_attribute_add_exec;
|
||||
ot->exec = geometry_color_attribute_add_exec;
|
||||
ot->invoke = WM_operator_props_popup_confirm;
|
||||
|
||||
/* flags */
|
||||
|
@ -211,6 +273,10 @@ static int geometry_attribute_remove_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (layer == BKE_id_attributes_active_color_get(id)) {
|
||||
next_color_attrs(id);
|
||||
}
|
||||
|
||||
if (!BKE_id_attribute_remove(id, layer, op->reports)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@ -220,6 +286,11 @@ static int geometry_attribute_remove_exec(bContext *C, wmOperator *op)
|
|||
*active_index -= 1;
|
||||
}
|
||||
|
||||
if (ob->mode == OB_MODE_SCULPT) {
|
||||
BKE_sculpt_update_object_for_edit(
|
||||
CTX_data_ensure_evaluated_depsgraph(C), ob, false, false, false);
|
||||
}
|
||||
|
||||
DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
|
||||
|
||||
|
@ -241,7 +312,6 @@ void GEOMETRY_OT_attribute_remove(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
|
||||
static int geometry_color_attribute_remove_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = ED_object_context(C);
|
||||
|
@ -252,13 +322,15 @@ static int geometry_color_attribute_remove_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
next_color_attrs(id);
|
||||
|
||||
if (!BKE_id_attribute_remove(id, layer, op->reports)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
int *active_index = BKE_id_attributes_active_index_p(id);
|
||||
if (*active_index > 0) {
|
||||
*active_index -= 1;
|
||||
if (ob->mode == OB_MODE_SCULPT) {
|
||||
BKE_sculpt_update_object_for_edit(
|
||||
CTX_data_ensure_evaluated_depsgraph(C), ob, false, false, false);
|
||||
}
|
||||
|
||||
DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
|
||||
|
@ -281,6 +353,7 @@ static bool geometry_color_attributes_remove_poll(bContext *C)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GEOMETRY_OT_color_attribute_remove(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
|
|
|
@ -319,16 +319,7 @@ void SCULPT_face_random_access_ensure(SculptSession *ss)
|
|||
|
||||
int SCULPT_vertex_count_get(const SculptSession *ss)
|
||||
{
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES:
|
||||
return ss->totvert;
|
||||
case PBVH_BMESH:
|
||||
return BM_mesh_elem_count(BKE_pbvh_get_bmesh(ss->pbvh), BM_VERT);
|
||||
case PBVH_GRIDS:
|
||||
return BKE_pbvh_get_grid_num_vertices(ss->pbvh);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return BKE_sculptsession_get_totvert(ss);
|
||||
}
|
||||
|
||||
MSculptVert *SCULPT_vertex_get_mdyntopo(const SculptSession *ss, SculptVertRef vertex)
|
||||
|
@ -798,311 +789,9 @@ void SCULPT_vertex_persistent_normal_get(SculptSession *ss, SculptVertRef vertex
|
|||
}
|
||||
}
|
||||
|
||||
static bool sculpt_temp_customlayer_get(SculptSession *ss,
|
||||
Object *ob,
|
||||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name,
|
||||
SculptCustomLayer *out,
|
||||
bool autocreate,
|
||||
SculptLayerParams *params)
|
||||
{
|
||||
if (ss->save_temp_layers && !params->simple_array) {
|
||||
params->permanent = true;
|
||||
}
|
||||
|
||||
bool simple_array = params->simple_array;
|
||||
bool permanent = params->permanent;
|
||||
bool nocopy = params->nocopy;
|
||||
bool nointerp = params->nointerp;
|
||||
|
||||
out->params = *params;
|
||||
out->proptype = proptype;
|
||||
out->domain = domain;
|
||||
BLI_strncpy(out->name, name, sizeof(out->name));
|
||||
|
||||
if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
|
||||
if (permanent) {
|
||||
printf(
|
||||
"%s: error: tried to make permanent customdata in multires mode; will make local "
|
||||
"array "
|
||||
"instead.\n",
|
||||
__func__);
|
||||
permanent = false;
|
||||
}
|
||||
|
||||
// customdata attribute layers not supported for grids
|
||||
simple_array = true;
|
||||
out->params.simple_array = true;
|
||||
}
|
||||
|
||||
BLI_assert(!(simple_array && permanent));
|
||||
|
||||
if (simple_array) {
|
||||
CustomData *cdata = NULL;
|
||||
int totelem = 0;
|
||||
|
||||
PBVHType pbvhtype = ss->pbvh ? BKE_pbvh_type(ss->pbvh) : (ss->bm ? PBVH_BMESH : PBVH_FACES);
|
||||
|
||||
switch (pbvhtype) {
|
||||
case PBVH_BMESH: {
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &ss->bm->vdata;
|
||||
totelem = ss->bm->totvert;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = &ss->bm->pdata;
|
||||
totelem = ss->bm->totface;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = ss->vdata;
|
||||
totelem = SCULPT_vertex_count_get(ss);
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = ss->pdata;
|
||||
totelem = ss->totfaces;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PBVH_FACES: {
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = ss->vdata;
|
||||
totelem = ss->totvert;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = ss->pdata;
|
||||
totelem = ss->totfaces;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CustomData dummy = {0};
|
||||
CustomData_reset(&dummy);
|
||||
CustomData_add_layer(&dummy, proptype, CD_ASSIGN, NULL, 0);
|
||||
int elemsize = (int)CustomData_get_elem_size(dummy.layers);
|
||||
|
||||
CustomData_free(&dummy, 0);
|
||||
|
||||
out->data = MEM_calloc_arrayN(totelem, elemsize, name);
|
||||
|
||||
out->is_cdlayer = false;
|
||||
out->from_bmesh = ss->bm != NULL;
|
||||
out->cd_offset = -1;
|
||||
out->layer = NULL;
|
||||
out->domain = domain;
|
||||
out->proptype = proptype;
|
||||
out->elemsize = elemsize;
|
||||
|
||||
/*grids cannot store normal customdata layers, and thus
|
||||
we cannot rely on the customdata api to keep track of
|
||||
and free their memory for us.
|
||||
|
||||
so instead we queue them in a dynamic array inside of
|
||||
SculptSession.
|
||||
*/
|
||||
if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
|
||||
ss->tot_layers_to_free++;
|
||||
|
||||
if (!ss->layers_to_free) {
|
||||
ss->layers_to_free = MEM_calloc_arrayN(
|
||||
ss->tot_layers_to_free, sizeof(void *), "ss->layers_to_free");
|
||||
}
|
||||
else {
|
||||
ss->layers_to_free = MEM_recallocN(ss->layers_to_free,
|
||||
sizeof(void *) * ss->tot_layers_to_free);
|
||||
}
|
||||
|
||||
SculptCustomLayer *cpy = MEM_callocN(sizeof(SculptCustomLayer), "SculptCustomLayer cpy");
|
||||
*cpy = *out;
|
||||
|
||||
ss->layers_to_free[ss->tot_layers_to_free - 1] = cpy;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH: {
|
||||
CustomData *cdata = NULL;
|
||||
out->from_bmesh = true;
|
||||
|
||||
if (!ss->bm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &ss->bm->vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = &ss->bm->pdata;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (idx < 0) {
|
||||
if (!autocreate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BM_data_layer_add_named(ss->bm, cdata, proptype, name);
|
||||
idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
SCULPT_dyntopo_node_layers_update_offsets(ss, ob);
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
}
|
||||
|
||||
if (nocopy) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_ELEM_NOCOPY;
|
||||
}
|
||||
if (nointerp) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_ELEM_NOINTERP;
|
||||
}
|
||||
|
||||
out->data = NULL;
|
||||
out->is_cdlayer = true;
|
||||
out->layer = cdata->layers + idx;
|
||||
out->cd_offset = out->layer->offset;
|
||||
out->elemsize = CustomData_get_elem_size(out->layer);
|
||||
|
||||
break;
|
||||
}
|
||||
case PBVH_FACES: {
|
||||
CustomData *cdata = NULL;
|
||||
int totelem = 0;
|
||||
|
||||
out->from_bmesh = false;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
totelem = ss->totvert;
|
||||
cdata = ss->vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
totelem = ss->totfaces;
|
||||
cdata = ss->pdata;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (idx < 0) {
|
||||
if (!autocreate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CustomData_add_layer_named(cdata, proptype, CD_CALLOC, NULL, totelem, name);
|
||||
idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
}
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
|
||||
out->data = NULL;
|
||||
out->is_cdlayer = true;
|
||||
out->layer = cdata->layers + idx;
|
||||
out->cd_offset = -1;
|
||||
out->data = out->layer->data;
|
||||
out->elemsize = CustomData_get_elem_size(out->layer);
|
||||
break;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
CustomData *cdata = NULL;
|
||||
int totelem = 0;
|
||||
|
||||
out->from_bmesh = false;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
totelem = BKE_pbvh_get_grid_num_vertices(ss->pbvh);
|
||||
cdata = &ss->temp_vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
// not supported
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (idx < 0) {
|
||||
if (!autocreate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CustomData_add_layer_named(cdata, proptype, CD_CALLOC, NULL, totelem, name);
|
||||
idx = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
}
|
||||
|
||||
if (nocopy) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_ELEM_NOCOPY;
|
||||
}
|
||||
if (nointerp) {
|
||||
cdata->layers[idx].flag |= CD_FLAG_ELEM_NOINTERP;
|
||||
}
|
||||
|
||||
out->data = NULL;
|
||||
out->is_cdlayer = true;
|
||||
out->layer = cdata->layers + idx;
|
||||
out->cd_offset = -1;
|
||||
out->data = out->layer->data;
|
||||
out->elemsize = CustomData_get_elem_size(out->layer);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SCULPT_update_customdata_refs(SculptSession *ss, Object *ob)
|
||||
{
|
||||
/* run twice, in case sculpt_temp_customlayer_get had to recreate a layer and
|
||||
messed up the ordering. */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < SCULPT_SCL_LAYER_MAX; j++) {
|
||||
SculptCustomLayer *scl = ss->custom_layers[j];
|
||||
|
||||
if (scl && !scl->released && !scl->params.simple_array) {
|
||||
sculpt_temp_customlayer_get(
|
||||
ss, ob, scl->domain, scl->proptype, scl->name, scl, true, &scl->params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ss->bm) {
|
||||
SCULPT_dyntopo_node_layers_update_offsets(ss, ob);
|
||||
}
|
||||
BKE_sculptsession_update_attr_refs(ob);
|
||||
}
|
||||
|
||||
float SCULPT_vertex_mask_get(SculptSession *ss, SculptVertRef index)
|
||||
|
@ -1141,7 +830,7 @@ bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
|
|||
// thoeretically it can allocate new layers
|
||||
SCULPT_update_customdata_refs(ss, ob);
|
||||
|
||||
bool ret = sculpt_temp_customlayer_get(ss, ob, domain, proptype, name, &scl, true, params);
|
||||
bool ret = SCULPT_temp_customlayer_get(ss, ob, domain, proptype, name, &scl, params);
|
||||
|
||||
SCULPT_update_customdata_refs(ss, ob);
|
||||
|
||||
|
@ -1246,10 +935,7 @@ bool SCULPT_temp_customlayer_get(SculptSession *ss,
|
|||
SculptCustomLayer *scl,
|
||||
SculptLayerParams *params)
|
||||
{
|
||||
bool ret = sculpt_temp_customlayer_get(ss, ob, domain, proptype, name, scl, true, params);
|
||||
SCULPT_update_customdata_refs(ss, ob);
|
||||
|
||||
return ret;
|
||||
return BKE_sculptsession_customlayer_get(ob, domain, proptype, name, scl, params);
|
||||
}
|
||||
|
||||
SculptVertRef SCULPT_active_vertex_get(SculptSession *ss)
|
||||
|
|
|
@ -85,19 +85,7 @@
|
|||
|
||||
BMesh *SCULPT_dyntopo_empty_bmesh()
|
||||
{
|
||||
const BMAllocTemplate allocsize = {
|
||||
.totvert = 2048 * 16, .totface = 2048 * 16, .totloop = 4196 * 16, .totedge = 2048 * 16};
|
||||
|
||||
BMesh *bm = BM_mesh_create(
|
||||
&allocsize,
|
||||
&((struct BMeshCreateParams){.use_toolflags = false,
|
||||
.create_unique_ids = true,
|
||||
.id_elem_mask = BM_VERT | BM_EDGE | BM_FACE,
|
||||
.id_map = true,
|
||||
.temporary_ids = false,
|
||||
.no_reuse_ids = false}));
|
||||
|
||||
return bm;
|
||||
return BKE_sculptsession_empty_bmesh_create();
|
||||
}
|
||||
// TODO: check if (mathematically speaking) is it really necassary
|
||||
// to sort the edge lists around verts
|
||||
|
@ -540,29 +528,20 @@ void SCULPT_dyntopo_save_origverts(SculptSession *ss)
|
|||
}
|
||||
}
|
||||
|
||||
char dyntopop_node_idx_layer_id[] = "_dyntopo_node_id";
|
||||
extern char dyntopop_node_idx_layer_id[];
|
||||
|
||||
void SCULPT_dyntopo_node_layers_update_offsets(SculptSession *ss, Object *ob)
|
||||
{
|
||||
SCULPT_dyntopo_node_layers_add(ss, ob);
|
||||
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_update_offsets(ss->pbvh,
|
||||
ss->cd_vert_node_offset,
|
||||
ss->cd_face_node_offset,
|
||||
ss->cd_sculpt_vert,
|
||||
ss->cd_face_areas);
|
||||
}
|
||||
if (ss->bm_log) {
|
||||
BM_log_set_cd_offsets(ss->bm_log, ss->cd_sculpt_vert);
|
||||
}
|
||||
BKE_sculptsession_bmesh_attr_update_internal(ob);
|
||||
}
|
||||
|
||||
/* DEPRECATED */
|
||||
bool SCULPT_dyntopo_has_templayer(SculptSession *ss, int type, const char *name)
|
||||
{
|
||||
return CustomData_get_named_layer_index(&ss->bm->vdata, type, name) >= 0;
|
||||
}
|
||||
|
||||
/* DEPRECATED */
|
||||
void SCULPT_dyntopo_ensure_templayer(
|
||||
SculptSession *ss, Object *ob, int type, const char *name, bool not_temporary)
|
||||
{
|
||||
|
@ -581,6 +560,7 @@ void SCULPT_dyntopo_ensure_templayer(
|
|||
}
|
||||
}
|
||||
|
||||
/* DEPRECATED */
|
||||
int SCULPT_dyntopo_get_templayer(SculptSession *ss, int type, const char *name)
|
||||
{
|
||||
int li = CustomData_get_named_layer_index(&ss->bm->vdata, type, name);
|
||||
|
@ -593,68 +573,11 @@ int SCULPT_dyntopo_get_templayer(SculptSession *ss, int type, const char *name)
|
|||
&ss->bm->vdata, type, li - CustomData_get_layer_index(&ss->bm->vdata, type));
|
||||
}
|
||||
|
||||
char dyntopop_faces_areas_layer_id[] = "__dyntopo_face_areas";
|
||||
extern char dyntopop_faces_areas_layer_id[];
|
||||
|
||||
void SCULPT_dyntopo_node_layers_add(SculptSession *ss, Object *ob)
|
||||
{
|
||||
int cd_node_layer_index, cd_face_node_layer_index;
|
||||
|
||||
BMCustomLayerReq vlayers[] = {
|
||||
{CD_PAINT_MASK, NULL, 0},
|
||||
{CD_DYNTOPO_VERT, NULL, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
|
||||
{CD_PROP_INT32, dyntopop_node_idx_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY}};
|
||||
|
||||
BM_data_layers_ensure(ss->bm, &ss->bm->vdata, vlayers, 3);
|
||||
|
||||
ss->cd_vert_mask_offset = CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK);
|
||||
|
||||
BMCustomLayerReq flayers[] = {
|
||||
{CD_PROP_INT32, dyntopop_node_idx_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
|
||||
{CD_PROP_FLOAT, dyntopop_faces_areas_layer_id, CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY},
|
||||
};
|
||||
BM_data_layers_ensure(ss->bm, &ss->bm->pdata, flayers, 2);
|
||||
|
||||
// get indices again, as they might have changed after adding new layers
|
||||
cd_node_layer_index = CustomData_get_named_layer_index(
|
||||
&ss->bm->vdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
|
||||
cd_face_node_layer_index = CustomData_get_named_layer_index(
|
||||
&ss->bm->pdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
|
||||
|
||||
ss->cd_sculpt_vert = CustomData_get_offset(&ss->bm->vdata, CD_DYNTOPO_VERT);
|
||||
|
||||
ss->cd_vert_node_offset = CustomData_get_n_offset(
|
||||
&ss->bm->vdata,
|
||||
CD_PROP_INT32,
|
||||
cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT32));
|
||||
|
||||
ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
|
||||
ss->cd_face_node_offset = CustomData_get_n_offset(
|
||||
&ss->bm->pdata,
|
||||
CD_PROP_INT32,
|
||||
cd_face_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT32));
|
||||
|
||||
ss->bm->pdata.layers[cd_face_node_layer_index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
ss->cd_faceset_offset = CustomData_get_offset(&ss->bm->pdata, CD_SCULPT_FACE_SETS);
|
||||
|
||||
ss->cd_face_areas = CustomData_get_named_layer(
|
||||
&ss->bm->pdata, CD_PROP_FLOAT, dyntopop_faces_areas_layer_id);
|
||||
ss->cd_face_areas = ss->bm->pdata.layers[ss->cd_face_areas].offset;
|
||||
|
||||
AttributeDomain domain;
|
||||
CustomDataLayer *cl;
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
|
||||
if (BKE_pbvh_get_color_layer(ss->pbvh, me, &cl, &domain)) {
|
||||
ss->vcol_domain = (int)domain;
|
||||
ss->vcol_type = cl->type;
|
||||
ss->cd_vcol_offset = cl->offset;
|
||||
}
|
||||
else {
|
||||
ss->cd_vcol_offset = -1;
|
||||
ss->vcol_type = -1;
|
||||
ss->vcol_domain = (int)ATTR_DOMAIN_NUM;
|
||||
}
|
||||
BKE_sculptsession_bmesh_add_layers(ob);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -662,131 +585,7 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss, Object *ob)
|
|||
*/
|
||||
void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (!ss || !ss->bm) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool modified = false;
|
||||
BMesh *bm = ss->bm;
|
||||
|
||||
CustomData *cd1[4] = {&me->vdata, &me->edata, &me->ldata, &me->pdata};
|
||||
CustomData *cd2[4] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
|
||||
int badmask = CD_MASK_MLOOP | CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_ORIGINDEX |
|
||||
CD_MASK_ORIGSPACE | CD_MASK_MFACE;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CustomDataLayer **newlayers = NULL;
|
||||
BLI_array_declare(newlayers);
|
||||
|
||||
CustomData *data1 = cd1[i];
|
||||
CustomData *data2 = cd2[i];
|
||||
|
||||
if (!data1->layers) {
|
||||
modified |= data2->layers != NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < data1->totlayer; j++) {
|
||||
CustomDataLayer *cl1 = data1->layers + j;
|
||||
|
||||
if ((1 << cl1->type) & badmask) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
|
||||
if (idx < 0) {
|
||||
BLI_array_append(newlayers, cl1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < BLI_array_len(newlayers); j++) {
|
||||
BM_data_layer_add_named(bm, data2, newlayers[j]->type, newlayers[j]->name);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
/* sync various ids */
|
||||
for (int j = 0; j < data1->totlayer; j++) {
|
||||
CustomDataLayer *cl1 = data1->layers + j;
|
||||
|
||||
if ((1 << cl1->type) & badmask) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
|
||||
|
||||
if (idx == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CustomDataLayer *cl2 = data2->layers + idx;
|
||||
|
||||
cl2->anonymous_id = cl1->anonymous_id;
|
||||
cl2->uid = cl1->uid;
|
||||
}
|
||||
|
||||
bool typemap[CD_NUMTYPES] = {0};
|
||||
|
||||
for (int j = 0; j < data1->totlayer; j++) {
|
||||
CustomDataLayer *cl1 = data1->layers + j;
|
||||
|
||||
if ((1 << cl1->type) & badmask) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typemap[cl1->type]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
typemap[cl1->type] = true;
|
||||
|
||||
// find first layer
|
||||
int baseidx = CustomData_get_layer_index(data2, cl1->type);
|
||||
|
||||
if (baseidx < 0) {
|
||||
modified |= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
CustomDataLayer *cl2 = data2->layers + baseidx;
|
||||
|
||||
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active].name);
|
||||
if (idx >= 0) {
|
||||
modified |= idx - baseidx != cl2->active;
|
||||
cl2->active = idx - baseidx;
|
||||
}
|
||||
|
||||
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_rnd].name);
|
||||
if (idx >= 0) {
|
||||
modified |= idx - baseidx != cl2->active_rnd;
|
||||
cl2->active_rnd = idx - baseidx;
|
||||
}
|
||||
|
||||
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_mask].name);
|
||||
if (idx >= 0) {
|
||||
modified |= idx - baseidx != cl2->active_mask;
|
||||
cl2->active_mask = idx - baseidx;
|
||||
}
|
||||
|
||||
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_clone].name);
|
||||
if (idx >= 0) {
|
||||
modified |= idx - baseidx != cl2->active_clone;
|
||||
cl2->active_clone = idx - baseidx;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_array_free(newlayers);
|
||||
}
|
||||
|
||||
if (modified && ss->bm) {
|
||||
CustomData_regen_active_refs(&ss->bm->vdata);
|
||||
CustomData_regen_active_refs(&ss->bm->edata);
|
||||
CustomData_regen_active_refs(&ss->bm->ldata);
|
||||
CustomData_regen_active_refs(&ss->bm->pdata);
|
||||
}
|
||||
|
||||
SCULPT_update_customdata_refs(ss, ob);
|
||||
BKE_sculptsession_sync_attributes(ob, me);
|
||||
}
|
||||
|
||||
BMesh *BM_mesh_bm_from_me_threaded(BMesh *bm,
|
||||
|
|
|
@ -52,30 +52,6 @@ struct BrushChannelSet;
|
|||
|
||||
enum ePaintSymmetryFlags;
|
||||
|
||||
typedef struct SculptLayerParams {
|
||||
int simple_array : 1; // cannot be combined with permanent
|
||||
int permanent : 1; // cannot be combined with simple_array
|
||||
int nocopy : 1;
|
||||
int nointerp : 1;
|
||||
} SculptLayerParams;
|
||||
|
||||
typedef struct SculptCustomLayer {
|
||||
AttributeDomain domain;
|
||||
int proptype;
|
||||
SculptLayerParams params;
|
||||
|
||||
char name[512];
|
||||
|
||||
bool is_cdlayer; // false for multires data
|
||||
void *data; // only valid for multires and face
|
||||
int elemsize;
|
||||
int cd_offset; // for bmesh
|
||||
CustomDataLayer *layer; // not for multires
|
||||
bool from_bmesh; // note that layers can be fixed arrays but still from a bmesh, e.g. filter
|
||||
// laplacian smooth
|
||||
bool released;
|
||||
} SculptCustomLayer;
|
||||
|
||||
void SCULPT_clear_scl_pointers(SculptSession *ss);
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue