Sculpt-dev: all vertex colors now live in single
UI list. * Added an index to Mesh for active color attribute. This seems janky to me, shouldn't this (along with the active attribute index) be a domain, name, cdtype triplet? * Added a little api to preserve the active attribute and color indices when changing mesh customdata layouts. See above comment. * The vertex color panel is now completely unified. * TODO: allow setting render color layer (not sure how to do this).
This commit is contained in:
parent
78d62d9be7
commit
f0d0369506
|
@ -433,6 +433,44 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
|
|||
col.operator("mesh.uv_texture_add", icon='ADD', text="")
|
||||
col.operator("mesh.uv_texture_remove", icon='REMOVE', text="")
|
||||
|
||||
class MESH_UL_color_attributes(UIList):
|
||||
display_domain_names = {
|
||||
'POINT': "Vertex",
|
||||
'EDGE': "Edge",
|
||||
'FACE': "Face",
|
||||
'CORNER': "Face Corner",
|
||||
}
|
||||
|
||||
def filter_items(self, context, data, property):
|
||||
attrs = getattr(data, property)
|
||||
ret = []
|
||||
idxs = []
|
||||
idx = 0
|
||||
|
||||
for item in attrs:
|
||||
bad = item.domain not in ["POINT", "CORNER"]
|
||||
bad = bad or item.data_type not in ["FLOAT_COLOR", "BYTE_COLOR"]
|
||||
|
||||
ret.append(self.bitflag_filter_item if not bad else 0)
|
||||
idxs.append(idx)
|
||||
|
||||
idx += 1
|
||||
|
||||
return ret, idxs
|
||||
|
||||
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
|
||||
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
|
||||
|
||||
domain_name = self.display_domain_names.get(attribute.domain, "")
|
||||
|
||||
split = layout.split(factor=0.50)
|
||||
split.emboss = 'NONE'
|
||||
split.prop(attribute, "name", text="")
|
||||
sub = split.row()
|
||||
sub.alignment = 'RIGHT'
|
||||
sub.active = False
|
||||
sub.label(text="%s ▶ %s" % (domain_name, data_type.name))
|
||||
|
||||
|
||||
class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
|
||||
bl_label = "Vertex Colors"
|
||||
|
@ -440,18 +478,62 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
|
|||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
||||
def draw(self, context):
|
||||
mesh = context.mesh
|
||||
|
||||
layout = self.layout
|
||||
|
||||
me = context.mesh
|
||||
|
||||
row = layout.row()
|
||||
col = row.column()
|
||||
|
||||
col.template_list("MESH_UL_vcols", "vcols", me, "vertex_colors", me.vertex_colors, "active_index", rows=2)
|
||||
col = row.column()
|
||||
col.template_list("MESH_UL_color_attributes",
|
||||
"attributes",
|
||||
mesh,
|
||||
"attributes",
|
||||
mesh.attributes,
|
||||
"active_color_index",
|
||||
rows=3,)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("mesh.vertex_color_add", icon='ADD', text="")
|
||||
col.operator("mesh.vertex_color_remove", icon='REMOVE', text="")
|
||||
col.operator("geometry.color_attribute_add", icon='ADD', text="")
|
||||
col.operator("geometry.attribute_remove", icon='REMOVE', text="")
|
||||
|
||||
active = mesh.attributes.active
|
||||
|
||||
if active and (active.domain == "POINT" and active.data_type == "FLOAT_COLOR"):
|
||||
layout.operator("sculpt.vertex_to_loop_colors", text="Save To Corners")
|
||||
layout.operator("sculpt.loop_to_vertex_colors", text="Load From Corners")
|
||||
|
||||
self.draw_attribute_warnings(context, layout)
|
||||
|
||||
def draw_attribute_warnings(self, context, layout):
|
||||
attributes_by_name = defaultdict(list)
|
||||
|
||||
ob = context.object
|
||||
mesh = ob.data
|
||||
|
||||
builtin_attribute = object()
|
||||
|
||||
def add_builtin(name):
|
||||
attributes_by_name[name].append(builtin_attribute)
|
||||
|
||||
def add_attributes(layers):
|
||||
for layer in layers:
|
||||
attributes_by_name[layer.name].append(layer)
|
||||
|
||||
add_builtin("position")
|
||||
add_builtin("material_index")
|
||||
add_builtin("shade_smooth")
|
||||
add_builtin("normal")
|
||||
add_builtin("crease")
|
||||
|
||||
add_attributes(mesh.attributes)
|
||||
add_attributes(mesh.uv_layers)
|
||||
add_attributes(ob.vertex_groups)
|
||||
|
||||
colliding_names = [name for name, layers in attributes_by_name.items() if len(layers) >= 2]
|
||||
if len(colliding_names) == 0:
|
||||
return
|
||||
|
||||
layout.label(text="Name collisions: {}".format(", ".join(colliding_names)), icon='ERROR')
|
||||
|
||||
class DATA_PT_remesh(MeshButtonsPanel, Panel):
|
||||
bl_label = "Remesh"
|
||||
|
@ -615,6 +697,7 @@ classes = (MESH_MT_vertex_group_context_menu,
|
|||
MESH_UL_uvmaps,
|
||||
MESH_UL_vcols,
|
||||
MESH_UL_attributes,
|
||||
MESH_UL_color_attributes,
|
||||
DATA_PT_context_mesh,
|
||||
DATA_PT_vertex_groups,
|
||||
DATA_PT_shape_keys,
|
||||
|
|
|
@ -86,6 +86,11 @@ void BKE_id_attributes_active_set(struct ID *id, struct CustomDataLayer *layer);
|
|||
int *BKE_id_attributes_active_index_p(struct ID *id);
|
||||
|
||||
CustomData *BKE_id_attributes_iterator_next_domain(struct ID *id, struct CustomDataLayer *layers);
|
||||
CustomDataLayer *BKE_id_attribute_from_index(const struct ID *id, int lookup_index);
|
||||
|
||||
int *BKE_id_attributes_active_color_index_p(struct ID *id);
|
||||
void BKE_id_attributes_active_color_set(struct ID *id, struct CustomDataLayer *active_layer);
|
||||
struct CustomDataLayer *BKE_id_attributes_active_color_get(struct ID *id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -465,6 +465,14 @@ int CustomData_layertype_layers_max(const int type);
|
|||
/* make sure the name of layer at index is unique */
|
||||
void CustomData_set_layer_unique_name(struct CustomData *data, int index);
|
||||
|
||||
/* get unique layer name for a layer that doesn't currently exist */
|
||||
void CustomData_find_unique_layer_name(CustomData *data,
|
||||
int type,
|
||||
const char *name,
|
||||
char *outname);
|
||||
|
||||
/* try to find layer with name name; if it does not exist,
|
||||
load the active layer name into outname*/
|
||||
void CustomData_validate_layer_name(const struct CustomData *data,
|
||||
int type,
|
||||
const char *name,
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_mesh_types.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -662,6 +664,37 @@ BLI_INLINE int BKE_mesh_origindex_mface_mpoly(const int *index_mf_to_mpoly,
|
|||
return (j != -1) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : -1;
|
||||
}
|
||||
|
||||
/* ensures attribute active indices are kept up to date */
|
||||
bool BKE_mesh_customdata_merge(struct Mesh *me,
|
||||
AttributeDomain domain,
|
||||
CustomData *src,
|
||||
CustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
void BKE_mesh_customdata_copy(struct Mesh *me,
|
||||
AttributeDomain domain,
|
||||
CustomData *src,
|
||||
CustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
void BKE_mesh_attributes_update_pre(struct Mesh *me,
|
||||
AttributeDomain domain,
|
||||
CustomData **r_dst,
|
||||
CustomData *src,
|
||||
int *active_type,
|
||||
char active_name[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int *active_color_type,
|
||||
char active_color_name[MAX_CUSTOMDATA_LAYER_NAME]);
|
||||
void BKE_mesh_attributes_update_post(struct Mesh *me,
|
||||
AttributeDomain domain,
|
||||
CustomData *dst,
|
||||
CustomData *src,
|
||||
int *active_type,
|
||||
char active_name[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int *active_color_type,
|
||||
char active_color_name[MAX_CUSTOMDATA_LAYER_NAME]);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -409,6 +409,7 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
|
|||
/* Drawing */
|
||||
|
||||
void BKE_pbvh_draw_cb(PBVH *pbvh,
|
||||
struct Mesh *me,
|
||||
bool update_only_visible,
|
||||
PBVHFrustumPlanes *update_frustum,
|
||||
PBVHFrustumPlanes *draw_frustum,
|
||||
|
|
|
@ -149,7 +149,7 @@ bool BKE_id_attribute_rename(ID *id,
|
|||
return true;
|
||||
}
|
||||
|
||||
CustomDataLayer *BKE_id_attribute_new(
|
||||
ATTR_NO_OPT CustomDataLayer *BKE_id_attribute_new(
|
||||
ID *id, const char *name, const int type, const AttributeDomain domain, ReportList *reports)
|
||||
{
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
|
@ -161,25 +161,30 @@ CustomDataLayer *BKE_id_attribute_new(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
char uniquename[sizeof(customdata->layers->name)];
|
||||
CustomData_find_unique_layer_name(customdata, type, name, uniquename);
|
||||
|
||||
switch (GS(id->name)) {
|
||||
case ID_ME: {
|
||||
Mesh *me = (Mesh *)id;
|
||||
BMEditMesh *em = me->edit_mesh;
|
||||
if (em != NULL) {
|
||||
BM_data_layer_add_named(em->bm, customdata, type, name);
|
||||
BM_data_layer_add_named(em->bm, customdata, type, uniquename);
|
||||
}
|
||||
else {
|
||||
CustomData_add_layer_named(customdata, type, CD_DEFAULT, NULL, info[domain].length, name);
|
||||
CustomData_add_layer_named(
|
||||
customdata, type, CD_DEFAULT, NULL, info[domain].length, uniquename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
CustomData_add_layer_named(customdata, type, CD_DEFAULT, NULL, info[domain].length, name);
|
||||
CustomData_add_layer_named(
|
||||
customdata, type, CD_DEFAULT, NULL, info[domain].length, uniquename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const int index = CustomData_get_named_layer_index(customdata, type, name);
|
||||
const int index = CustomData_get_named_layer_index(customdata, type, uniquename);
|
||||
return (index == -1) ? NULL : &(customdata->layers[index]);
|
||||
}
|
||||
|
||||
|
@ -246,6 +251,33 @@ CustomDataLayer *BKE_id_attribute_find(const ID *id,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT CustomDataLayer *BKE_id_attribute_from_index(const ID *id, int lookup_index)
|
||||
{
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
get_domains(id, info);
|
||||
|
||||
int index = 0;
|
||||
for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
|
||||
CustomData *customdata = info[domain].customdata;
|
||||
|
||||
if (!customdata) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < customdata->totlayer; i++) {
|
||||
if (CD_MASK_PROP_ALL & CD_TYPE_AS_MASK(customdata->layers[i].type)) {
|
||||
if (index == lookup_index) {
|
||||
return customdata->layers + i;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BKE_id_attributes_length(ID *id, const CustomDataMask mask)
|
||||
{
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
|
@ -380,6 +412,90 @@ int *BKE_id_attributes_active_index_p(ID *id)
|
|||
}
|
||||
}
|
||||
|
||||
CustomDataLayer *BKE_id_attributes_active_color_get(ID *id)
|
||||
{
|
||||
int active_index = *BKE_id_attributes_active_color_index_p(id);
|
||||
if (active_index > BKE_id_attributes_length(id, CD_MASK_PROP_ALL)) {
|
||||
fprintf(stderr, "bad active color index %d; was out of bounds\n", active_index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
get_domains(id, info);
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
|
||||
CustomData *customdata = info[domain].customdata;
|
||||
if (customdata) {
|
||||
for (int i = 0; i < customdata->totlayer; i++) {
|
||||
CustomDataLayer *layer = &customdata->layers[i];
|
||||
if (CD_MASK_PROP_ALL & CD_TYPE_AS_MASK(layer->type)) {
|
||||
if (index == active_index) {
|
||||
if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER) &&
|
||||
ELEM(layer->type, CD_PROP_COLOR, CD_MLOOPCOL)) {
|
||||
return layer;
|
||||
}
|
||||
else {
|
||||
fprintf(
|
||||
stderr, "bad active color index %d; type was: %d\n", active_index, layer->type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_id_attributes_active_color_set(ID *id, CustomDataLayer *active_layer)
|
||||
{
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
get_domains(id, info);
|
||||
|
||||
if (!active_layer || !ELEM(active_layer->type, CD_PROP_COLOR, CD_MLOOPCOL)) {
|
||||
fprintf(stderr,
|
||||
"bad active color layer %p; type was %d\n",
|
||||
active_layer,
|
||||
active_layer ? active_layer->type : -1);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
|
||||
CustomData *customdata = info[domain].customdata;
|
||||
|
||||
if (customdata) {
|
||||
for (int i = 0; i < customdata->totlayer; i++) {
|
||||
CustomDataLayer *layer = &customdata->layers[i];
|
||||
if (layer == active_layer && ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
|
||||
*BKE_id_attributes_active_color_index_p(id) = index;
|
||||
return;
|
||||
}
|
||||
if (CD_MASK_PROP_ALL & CD_TYPE_AS_MASK(layer->type)) {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int *BKE_id_attributes_active_color_index_p(ID *id)
|
||||
{
|
||||
switch (GS(id->name)) {
|
||||
case ID_ME: {
|
||||
return &((Mesh *)id)->active_color_index;
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CustomData *BKE_id_attributes_iterator_next_domain(ID *id, CustomDataLayer *layers)
|
||||
{
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
|
|
|
@ -5022,9 +5022,33 @@ static bool customdata_unique_check(void *arg, const char *name)
|
|||
int type;
|
||||
int index;
|
||||
} *data_arg = arg;
|
||||
|
||||
return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
|
||||
}
|
||||
|
||||
void CustomData_find_unique_layer_name(CustomData *data, int type, const char *name, char *outname)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
||||
struct {
|
||||
CustomData *data;
|
||||
int type;
|
||||
int index;
|
||||
} data_arg;
|
||||
|
||||
if (!typeInfo->defaultname) {
|
||||
return;
|
||||
}
|
||||
|
||||
data_arg.data = data;
|
||||
data_arg.type = type;
|
||||
data_arg.index = -1;
|
||||
|
||||
BLI_strncpy(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
BLI_uniquename_cb(
|
||||
customdata_unique_check, &data_arg, NULL, '.', outname, MAX_CUSTOMDATA_LAYER_NAME);
|
||||
}
|
||||
|
||||
void CustomData_set_layer_unique_name(CustomData *data, int index)
|
||||
{
|
||||
CustomDataLayer *nlayer = &data->layers[index];
|
||||
|
@ -5053,10 +5077,10 @@ void CustomData_set_layer_unique_name(CustomData *data, int index)
|
|||
customdata_unique_check, &data_arg, NULL, '.', nlayer->name, sizeof(nlayer->name));
|
||||
}
|
||||
|
||||
void CustomData_validate_layer_name(const CustomData *data,
|
||||
int type,
|
||||
const char *name,
|
||||
char *outname)
|
||||
ATTR_NO_OPT void CustomData_validate_layer_name(const CustomData *data,
|
||||
int type,
|
||||
const char *name,
|
||||
char *outname)
|
||||
{
|
||||
int index = -1;
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_global.h"
|
||||
|
@ -2270,3 +2271,164 @@ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_attributes_update_pre(Mesh *me,
|
||||
AttributeDomain domain,
|
||||
CustomData **r_dst,
|
||||
CustomData *src,
|
||||
int *active_type,
|
||||
char active_name[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int *active_color_type,
|
||||
char active_color_name[MAX_CUSTOMDATA_LAYER_NAME])
|
||||
{
|
||||
CustomDataLayer *active = BKE_id_attributes_active_get((ID *)me);
|
||||
CustomDataLayer *active_color = BKE_id_attributes_active_color_get((ID *)me);
|
||||
|
||||
CustomData *dst = NULL;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
dst = &me->vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
dst = &me->edata;
|
||||
break;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
dst = &me->ldata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
dst = &me->pdata;
|
||||
break;
|
||||
default:
|
||||
// should never happen
|
||||
fprintf(stderr, "%s: bad domain!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
*r_dst = dst;
|
||||
|
||||
/* check that domain is correct */
|
||||
active = active && BKE_id_attribute_domain((ID *)me, active) != domain ? NULL : active;
|
||||
active_color = active_color && BKE_id_attribute_domain((ID *)me, active_color) != domain ?
|
||||
NULL :
|
||||
active_color;
|
||||
|
||||
if (active) {
|
||||
*active_type = active->type;
|
||||
BLI_strncpy(active_name, active->name, sizeof(active_name));
|
||||
}
|
||||
else {
|
||||
*active_type = -1;
|
||||
}
|
||||
|
||||
if (active_color) {
|
||||
*active_color_type = active_color->type;
|
||||
BLI_strncpy(active_color_name, active_color->name, sizeof(active_color_name));
|
||||
}
|
||||
else {
|
||||
*active_color_type = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_attributes_update_post(Mesh *me,
|
||||
AttributeDomain domain,
|
||||
CustomData *dst,
|
||||
CustomData *src,
|
||||
int *active_type,
|
||||
char active_name[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int *active_color_type,
|
||||
char active_color_name[MAX_CUSTOMDATA_LAYER_NAME])
|
||||
{
|
||||
|
||||
int active_idx = *active_type != -1 ?
|
||||
CustomData_get_named_layer_index(dst, *active_type, active_name) :
|
||||
-1;
|
||||
int active_color_idx = *active_color_type != -1 ?
|
||||
CustomData_get_named_layer_index(
|
||||
dst, *active_color_type, active_color_name) :
|
||||
-1;
|
||||
|
||||
if (active_idx != -1) {
|
||||
BKE_id_attributes_active_set((ID *)me, dst->layers + active_idx);
|
||||
}
|
||||
|
||||
if (active_color_idx != -1) {
|
||||
BKE_id_attributes_active_set((ID *)me, dst->layers + active_idx);
|
||||
}
|
||||
else if (*active_color_type != -1) {
|
||||
bool ok = false;
|
||||
|
||||
// layer disappeared, find a new one
|
||||
for (int i = 0; i < dst->totlayer; i++) {
|
||||
if (ELEM(dst->layers[i].type, CD_PROP_COLOR, CD_MLOOPCOL)) {
|
||||
ok = true;
|
||||
BKE_id_attributes_active_set((ID *)me, dst->layers + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
// failed to find one? try other color attribute domain
|
||||
CustomData *other = domain == ATTR_DOMAIN_POINT ? &me->ldata : &me->vdata;
|
||||
|
||||
for (int i = 0; i < other->totlayer; i++) {
|
||||
if (ELEM(other->layers[i].type, CD_PROP_COLOR, CD_MLOOPCOL)) {
|
||||
BKE_id_attributes_active_set((ID *)me, other->layers + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_mesh_customdata_merge(Mesh *me,
|
||||
AttributeDomain domain,
|
||||
CustomData *src,
|
||||
CustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem)
|
||||
{
|
||||
int active_type, active_color_type;
|
||||
char active_name[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
char active_color_name[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
CustomData *dst = NULL;
|
||||
|
||||
BKE_mesh_attributes_update_pre(
|
||||
me, domain, &dst, src, &active_type, active_name, &active_color_type, active_color_name);
|
||||
|
||||
if (!dst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = CustomData_merge(src, dst, mask, alloctype, totelem);
|
||||
|
||||
BKE_mesh_attributes_update_post(
|
||||
me, domain, dst, src, &active_type, active_name, &active_color_type, active_color_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BKE_mesh_customdata_copy(Mesh *me,
|
||||
AttributeDomain domain,
|
||||
CustomData *src,
|
||||
CustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem)
|
||||
{
|
||||
int active_type, active_color_type;
|
||||
char active_name[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
char active_color_name[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
CustomData *dst = NULL;
|
||||
|
||||
BKE_mesh_attributes_update_pre(
|
||||
me, domain, &dst, src, &active_type, active_name, &active_color_type, active_color_name);
|
||||
|
||||
if (!dst) {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomData_copy(src, dst, mask, alloctype, totelem);
|
||||
|
||||
BKE_mesh_attributes_update_post(
|
||||
me, domain, dst, src, &active_type, active_name, &active_color_type, active_color_name);
|
||||
}
|
||||
|
|
|
@ -1134,6 +1134,7 @@ typedef struct PBVHUpdateData {
|
|||
int flag;
|
||||
bool show_sculpt_face_sets;
|
||||
bool flat_vcol_shading;
|
||||
Mesh *mesh;
|
||||
} PBVHUpdateData;
|
||||
|
||||
static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
|
||||
|
@ -1376,7 +1377,7 @@ ATTR_NO_OPT bool BKE_pbvh_get_color_layer(PBVH *pbvh,
|
|||
CustomDataLayer **r_cl,
|
||||
AttributeDomain *r_attr)
|
||||
{
|
||||
CustomDataLayer *cl = BKE_id_attributes_active_get((ID *)me);
|
||||
CustomDataLayer *cl = BKE_id_attributes_active_color_get((ID *)me);
|
||||
AttributeDomain domain;
|
||||
|
||||
if (!cl || !ELEM(cl->type, CD_PROP_COLOR, CD_MLOOPCOL)) {
|
||||
|
@ -1454,6 +1455,12 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
|||
PBVHUpdateData *data = userdata;
|
||||
PBVH *pbvh = data->pbvh;
|
||||
PBVHNode *node = data->nodes[n];
|
||||
Mesh *me = data->mesh;
|
||||
|
||||
CustomDataLayer *vcol_layer = NULL;
|
||||
AttributeDomain vcol_domain;
|
||||
|
||||
BKE_pbvh_get_color_layer(pbvh, me, &vcol_layer, &vcol_domain);
|
||||
|
||||
if (node->flag & PBVH_RebuildDrawBuffers) {
|
||||
node->updategen++;
|
||||
|
@ -1567,7 +1574,8 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
|||
.flat_vcol = data->flat_vcol_shading,
|
||||
.mat_nr = node->tri_buffers[i].mat_nr,
|
||||
.active_vcol_domain = pbvh->vcol_domain,
|
||||
.active_vcol_type = pbvh->vcol_type};
|
||||
.active_vcol_type = pbvh->vcol_type,
|
||||
.active_vcol_layer = vcol_layer};
|
||||
|
||||
GPU_pbvh_bmesh_buffers_update(&args);
|
||||
}
|
||||
|
@ -1623,7 +1631,8 @@ void pbvh_update_free_all_draw_buffers(PBVH *pbvh, PBVHNode *node)
|
|||
}
|
||||
}
|
||||
|
||||
static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag)
|
||||
static void pbvh_update_draw_buffers(
|
||||
PBVH *pbvh, Mesh *me, PBVHNode **nodes, int totnode, int update_flag)
|
||||
{
|
||||
|
||||
CustomData *vdata;
|
||||
|
@ -1643,12 +1652,17 @@ static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode,
|
|||
ldata = pbvh->ldata;
|
||||
}
|
||||
|
||||
CustomDataLayer *vcol_layer = NULL;
|
||||
AttributeDomain domain;
|
||||
BKE_pbvh_get_color_layer(pbvh, me, &vcol_layer, &domain);
|
||||
|
||||
GPU_pbvh_update_attribute_names(vdata,
|
||||
ldata,
|
||||
GPU_pbvh_need_full_render_get(),
|
||||
pbvh->flags & PBVH_FAST_DRAW,
|
||||
pbvh->vcol_type,
|
||||
pbvh->vcol_domain);
|
||||
pbvh->vcol_domain,
|
||||
vcol_layer);
|
||||
|
||||
if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
|
||||
/* Free buffers uses OpenGL, so not in parallel. */
|
||||
|
@ -1665,7 +1679,7 @@ static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode,
|
|||
|
||||
/* Parallel creation and update of draw buffers. */
|
||||
PBVHUpdateData data = {
|
||||
.pbvh = pbvh, .nodes = nodes, .flat_vcol_shading = pbvh->flat_vcol_shading};
|
||||
.pbvh = pbvh, .nodes = nodes, .flat_vcol_shading = pbvh->flat_vcol_shading, .mesh = me};
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
|
||||
|
@ -3177,6 +3191,7 @@ static bool pbvh_draw_search_cb(PBVHNode *node, void *data_v)
|
|||
}
|
||||
|
||||
void BKE_pbvh_draw_cb(PBVH *pbvh,
|
||||
Mesh *me,
|
||||
bool update_only_visible,
|
||||
PBVHFrustumPlanes *update_frustum,
|
||||
PBVHFrustumPlanes *draw_frustum,
|
||||
|
@ -3221,11 +3236,11 @@ void BKE_pbvh_draw_cb(PBVH *pbvh,
|
|||
|
||||
pbvh->need_full_render = GPU_pbvh_need_full_render_get();
|
||||
BKE_pbvh_draw_cb(
|
||||
pbvh, update_only_visible, update_frustum, draw_frustum, draw_fn, user_data);
|
||||
pbvh, me, update_only_visible, update_frustum, draw_frustum, draw_fn, user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag);
|
||||
pbvh_update_draw_buffers(pbvh, me, nodes, totnode, update_flag);
|
||||
}
|
||||
MEM_SAFE_FREE(nodes);
|
||||
|
||||
|
|
|
@ -1035,6 +1035,8 @@ void BM_mesh_bm_to_me(
|
|||
BMIter iter;
|
||||
int i, j;
|
||||
|
||||
CustomData *srcdatas[] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
|
||||
|
||||
if (params->copy_temp_cdlayers) {
|
||||
bm_unmark_temp_cdlayers(bm);
|
||||
}
|
||||
|
@ -1066,6 +1068,24 @@ void BM_mesh_bm_to_me(
|
|||
#endif
|
||||
}
|
||||
|
||||
int active_types[4], active_color_types[4];
|
||||
CustomData *active_dsts[4];
|
||||
char active_names[4][MAX_CUSTOMDATA_LAYER_NAME];
|
||||
char active_color_names[4][MAX_CUSTOMDATA_LAYER_NAME];
|
||||
int active_domains[4] = {
|
||||
ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_CORNER, ATTR_DOMAIN_FACE};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BKE_mesh_attributes_update_pre(me,
|
||||
active_domains[i],
|
||||
active_dsts + i,
|
||||
srcdatas[i],
|
||||
active_types + i,
|
||||
active_names[i],
|
||||
active_color_types + i,
|
||||
active_color_names[i]);
|
||||
}
|
||||
|
||||
/* Free custom data. */
|
||||
CustomData_free(&me->vdata, me->totvert);
|
||||
CustomData_free(&me->edata, me->totedge);
|
||||
|
@ -1083,7 +1103,6 @@ void BM_mesh_bm_to_me(
|
|||
me->totface = 0;
|
||||
me->act_face = -1;
|
||||
|
||||
CustomData *srcdatas[] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
|
||||
int id_flags[4] = {-1, -1, -1, -1};
|
||||
|
||||
{
|
||||
|
@ -1121,6 +1140,18 @@ void BM_mesh_bm_to_me(
|
|||
|
||||
me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CustomData *dst;
|
||||
BKE_mesh_attributes_update_post(me,
|
||||
active_domains[i],
|
||||
active_dsts[i],
|
||||
srcdatas[i],
|
||||
active_types + i,
|
||||
active_names[i],
|
||||
active_color_types + i,
|
||||
active_color_names[i]);
|
||||
}
|
||||
|
||||
/* This is called again, 'dotess' arg is used there. */
|
||||
BKE_mesh_update_customdata_pointers(me, 0);
|
||||
|
||||
|
@ -1530,10 +1561,12 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
|||
CustomData_MeshMasks_update(&mask, cd_mask_extra);
|
||||
}
|
||||
mask.vmask &= ~CD_MASK_SHAPEKEY;
|
||||
CustomData_merge(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert);
|
||||
CustomData_merge(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge);
|
||||
CustomData_merge(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop);
|
||||
CustomData_merge(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly);
|
||||
|
||||
BKE_mesh_customdata_merge(me, ATTR_DOMAIN_POINT, &bm->vdata, mask.vmask, CD_CALLOC, me->totvert);
|
||||
BKE_mesh_customdata_merge(me, ATTR_DOMAIN_EDGE, &bm->edata, mask.emask, CD_CALLOC, me->totedge);
|
||||
BKE_mesh_customdata_merge(
|
||||
me, ATTR_DOMAIN_CORNER, &bm->ldata, mask.lmask, CD_CALLOC, me->totloop);
|
||||
BKE_mesh_customdata_merge(me, ATTR_DOMAIN_FACE, &bm->pdata, mask.pmask, CD_CALLOC, me->totpoly);
|
||||
|
||||
BKE_mesh_update_customdata_pointers(me, false);
|
||||
|
||||
|
|
|
@ -1088,6 +1088,7 @@ static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd)
|
|||
BKE_pbvh_update_normals(pbvh, mesh->runtime.subdiv_ccg);
|
||||
|
||||
BKE_pbvh_draw_cb(pbvh,
|
||||
mesh,
|
||||
update_only_visible,
|
||||
&update_frustum,
|
||||
&draw_frustum,
|
||||
|
|
|
@ -23,6 +23,7 @@ set(INC
|
|||
../../makesdna
|
||||
../../makesrna
|
||||
../../windowmanager
|
||||
../../../../intern/atomic
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_paint.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
@ -96,6 +98,11 @@ static int geometry_attribute_add_exec(bContext *C, wmOperator *op)
|
|||
|
||||
BKE_id_attributes_active_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);
|
||||
|
||||
|
@ -141,6 +148,53 @@ void GEOMETRY_OT_attribute_add(wmOperatorType *ot)
|
|||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
void GEOMETRY_OT_color_attribute_add(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Add Geometry Attribute";
|
||||
ot->description = "Add attribute to geometry";
|
||||
ot->idname = "GEOMETRY_OT_color_attribute_add";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = geometry_attributes_poll;
|
||||
ot->exec = geometry_attribute_add_exec;
|
||||
ot->invoke = WM_operator_props_popup_confirm;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_string(ot->srna, "name", "Color", MAX_NAME, "Name", "Name of color attribute");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
static EnumPropertyItem domains[3] = {{ATTR_DOMAIN_POINT, "POINT", -1, "Point", ""},
|
||||
{ATTR_DOMAIN_CORNER, "CORNER", -1, "Face Corner", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem types[3] = {{CD_PROP_COLOR, "COLOR", -1, "Color", ""},
|
||||
{CD_MLOOPCOL, "BYTE_COLOR", -1, "Byte Color", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
prop = RNA_def_enum(ot->srna,
|
||||
"domain",
|
||||
domains,
|
||||
ATTR_DOMAIN_POINT,
|
||||
"Domain",
|
||||
"Type of element that attribute is stored on");
|
||||
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_enum(ot->srna,
|
||||
"data_type",
|
||||
types,
|
||||
CD_PROP_COLOR,
|
||||
"Data Type",
|
||||
"Type of data stored in attribute");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
static int geometry_attribute_remove_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = ED_object_context(C);
|
||||
|
|
|
@ -27,4 +27,5 @@ struct wmOperatorType;
|
|||
|
||||
/* *** geometry_attributes.c *** */
|
||||
void GEOMETRY_OT_attribute_add(struct wmOperatorType *ot);
|
||||
void GEOMETRY_OT_color_attribute_add(struct wmOperatorType *ot);
|
||||
void GEOMETRY_OT_attribute_remove(struct wmOperatorType *ot);
|
||||
|
|
|
@ -32,5 +32,6 @@
|
|||
void ED_operatortypes_geometry(void)
|
||||
{
|
||||
WM_operatortype_append(GEOMETRY_OT_attribute_add);
|
||||
WM_operatortype_append(GEOMETRY_OT_color_attribute_add);
|
||||
WM_operatortype_append(GEOMETRY_OT_attribute_remove);
|
||||
}
|
||||
|
|
|
@ -138,7 +138,9 @@ typedef struct SculptUndoStep {
|
|||
|
||||
// active vcol layer
|
||||
SculptAttrRef active_attr_start;
|
||||
SculptAttrRef active_vcol_attr_start;
|
||||
SculptAttrRef active_attr_end;
|
||||
SculptAttrRef active_vcol_attr_end;
|
||||
|
||||
bContext *C;
|
||||
} SculptUndoStep;
|
||||
|
@ -146,6 +148,7 @@ typedef struct SculptUndoStep {
|
|||
static UndoSculpt *sculpt_undo_get_nodes(void);
|
||||
static bool sculpt_attr_ref_equals(SculptAttrRef *a, SculptAttrRef *b);
|
||||
static void sculpt_save_active_attr(Object *ob, SculptAttrRef *attr);
|
||||
static void sculpt_save_active_vcol_attr(Object *ob, SculptAttrRef *attr);
|
||||
|
||||
static void update_unode_bmesh_memsize(SculptUndoNode *unode);
|
||||
static UndoSculpt *sculpt_undo_get_nodes(void);
|
||||
|
@ -2216,6 +2219,24 @@ static void sculpt_save_active_attr(Object *ob, SculptAttrRef *attr)
|
|||
attr->was_set = true;
|
||||
}
|
||||
|
||||
static void sculpt_save_active_vcol_attr(Object *ob, SculptAttrRef *attr)
|
||||
{
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
CustomDataLayer *cl;
|
||||
|
||||
if (ob && me && (cl = BKE_id_attributes_active_color_get((ID *)me))) {
|
||||
attr->domain = BKE_id_attribute_domain((ID *)me, cl);
|
||||
BLI_strncpy(attr->name, cl->name, sizeof(attr->name));
|
||||
attr->type = cl->type;
|
||||
}
|
||||
else {
|
||||
attr->domain = NO_ACTIVE_LAYER;
|
||||
attr->name[0] = 0;
|
||||
}
|
||||
|
||||
attr->was_set = true;
|
||||
}
|
||||
|
||||
void sculpt_undo_push_begin_ex(Object *ob, const char *name, bool no_first_entry_check)
|
||||
{
|
||||
UndoStack *ustack = ED_undo_stack_get();
|
||||
|
@ -2244,6 +2265,10 @@ void sculpt_undo_push_begin_ex(Object *ob, const char *name, bool no_first_entry
|
|||
sculpt_save_active_attr(ob, &us->active_attr_start);
|
||||
}
|
||||
|
||||
if (!us->active_vcol_attr_start.was_set) {
|
||||
sculpt_save_active_vcol_attr(ob, &us->active_vcol_attr_start);
|
||||
}
|
||||
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
/*when pusing an undo node after
|
||||
|
@ -2306,6 +2331,7 @@ void SCULPT_undo_push_end_ex(struct Object *ob, const bool use_nested_undo)
|
|||
ustack, BKE_UNDOSYS_TYPE_SCULPT);
|
||||
|
||||
sculpt_save_active_attr(ob, &us->active_attr_end);
|
||||
sculpt_save_active_vcol_attr(ob, &us->active_vcol_attr_end);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -2339,6 +2365,33 @@ static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr
|
|||
}
|
||||
}
|
||||
|
||||
static void sculpt_undo_set_active_vcol_layer(struct bContext *C, SculptAttrRef *attr)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
|
||||
if (attr->domain == NO_ACTIVE_LAYER) {
|
||||
// from reading the code, it appears you cannot set
|
||||
// the active layer to NULL, so don't worry about it.
|
||||
// BKE_id_attributes_active_set(&me->id, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
SculptAttrRef existing;
|
||||
sculpt_save_active_vcol_attr(ob, &existing);
|
||||
|
||||
if (!sculpt_attr_ref_equals(&existing, attr) && ob->sculpt && ob->sculpt->pbvh) {
|
||||
BKE_pbvh_update_vertex_data(ob->sculpt->pbvh, PBVH_UpdateColor);
|
||||
}
|
||||
|
||||
CustomDataLayer *cl;
|
||||
cl = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain);
|
||||
|
||||
if (cl) {
|
||||
BKE_id_attributes_active_color_set(&me->id, cl);
|
||||
}
|
||||
}
|
||||
|
||||
static void sculpt_undosys_step_encode_init(struct bContext *C, UndoStep *us_p)
|
||||
{
|
||||
SculptUndoStep *us = (SculptUndoStep *)us_p;
|
||||
|
@ -2407,12 +2460,16 @@ static void sculpt_undosys_step_decode_undo(struct bContext *C,
|
|||
BLI_assert(us_iter->step.type == us->step.type); /* Previous loop ensures this. */
|
||||
|
||||
sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start);
|
||||
sculpt_undo_set_active_vcol_layer(C, &((SculptUndoStep *)us_iter)->active_vcol_attr_start);
|
||||
|
||||
sculpt_undosys_step_decode_undo_impl(C, depsgraph, us_iter);
|
||||
// sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start);
|
||||
|
||||
if (us_iter == us) {
|
||||
if (us_iter->step.prev && us_iter->step.prev->type == BKE_UNDOSYS_TYPE_SCULPT) {
|
||||
sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter->step.prev)->active_attr_end);
|
||||
sculpt_undo_set_active_vcol_layer(
|
||||
C, &((SculptUndoStep *)us_iter->step.prev)->active_vcol_attr_end);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2434,10 +2491,12 @@ static void sculpt_undosys_step_decode_redo(struct bContext *C,
|
|||
}
|
||||
while (us_iter && (us_iter->step.is_applied == false)) {
|
||||
sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start);
|
||||
sculpt_undo_set_active_vcol_layer(C, &((SculptUndoStep *)us_iter)->active_vcol_attr_start);
|
||||
sculpt_undosys_step_decode_redo_impl(C, depsgraph, us_iter);
|
||||
|
||||
if (us_iter == us) {
|
||||
sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_end);
|
||||
sculpt_undo_set_active_vcol_layer(C, &((SculptUndoStep *)us_iter)->active_vcol_attr_end);
|
||||
break;
|
||||
}
|
||||
us_iter = (SculptUndoStep *)us_iter->step.next;
|
||||
|
|
|
@ -67,6 +67,7 @@ typedef struct PBVHGPUBuildArgs {
|
|||
int face_sets_color_default;
|
||||
bool flat_vcol;
|
||||
short mat_nr, active_vcol_type, active_vcol_domain;
|
||||
struct CustomDataLayer *active_vcol_layer;
|
||||
} PBVHGPUBuildArgs;
|
||||
|
||||
/* Build must be called once before using the other functions, used every time
|
||||
|
@ -114,7 +115,9 @@ void GPU_pbvh_update_attribute_names(
|
|||
bool need_full_render,
|
||||
bool fast_mode,
|
||||
int active_vcol_type,
|
||||
int active_vcol_domain); // fast mode renders without vcol, uv, facesets, even mask, etc
|
||||
int active_vcol_domain,
|
||||
struct CustomDataLayer
|
||||
*active_vcol_layer); // fast mode renders without vcol, uv, facesets, even mask, etc
|
||||
|
||||
void GPU_pbvh_bmesh_buffers_update(PBVHGPUBuildArgs *args);
|
||||
|
||||
|
|
|
@ -365,7 +365,7 @@ static void free_cd_layers(CDAttrLayers *cdattr)
|
|||
|
||||
void gpu_pbvh_init()
|
||||
{
|
||||
GPU_pbvh_update_attribute_names(NULL, NULL, false, false, -1, -1);
|
||||
GPU_pbvh_update_attribute_names(NULL, NULL, false, false, -1, -1, NULL);
|
||||
}
|
||||
|
||||
void gpu_pbvh_exit()
|
||||
|
@ -1322,14 +1322,15 @@ static int gpu_pbvh_bmesh_make_vcol_offs(CustomData *vdata,
|
|||
ColorRef r_cd_vcols[MAX_GPU_MCOL],
|
||||
bool active_only,
|
||||
int active_type,
|
||||
int active_domain)
|
||||
int active_domain,
|
||||
CustomDataLayer *active_vcol_layer)
|
||||
{
|
||||
if (active_only) {
|
||||
CustomData *cdata = active_domain == ATTR_DOMAIN_POINT ? vdata : ldata;
|
||||
|
||||
int idx = active_type != -1 ? CustomData_get_active_layer_index(cdata, active_type) : -1;
|
||||
int idx = active_vcol_layer ? active_vcol_layer - cdata->layers : -1;
|
||||
|
||||
if (idx >= 0) {
|
||||
if (idx >= 0 && idx < cdata->totlayer) {
|
||||
r_cd_vcols[0].cd_offset = cdata->layers[idx].offset;
|
||||
r_cd_vcols[0].domain = active_domain;
|
||||
r_cd_vcols[0].type = active_type;
|
||||
|
@ -1395,7 +1396,8 @@ ATTR_NO_OPT void GPU_pbvh_update_attribute_names(CustomData *vdata,
|
|||
bool need_full_render,
|
||||
bool fast_mode,
|
||||
int active_vcol_type,
|
||||
int active_vcol_domain)
|
||||
int active_vcol_domain,
|
||||
CustomDataLayer *active_vcol_layer)
|
||||
{
|
||||
const bool active_only = !need_full_render;
|
||||
|
||||
|
@ -1462,26 +1464,31 @@ ATTR_NO_OPT void GPU_pbvh_update_attribute_names(CustomData *vdata,
|
|||
|
||||
#if !defined(NEW_ATTR_SYSTEM) && !defined(GPU_PERF_TEST)
|
||||
if (active_vcol_type != -1) {
|
||||
const int act = CustomData_get_active_layer_index(
|
||||
active_vcol_domain == ATTR_DOMAIN_POINT ? vdata : ldata, active_vcol_type);
|
||||
int ci = 0;
|
||||
|
||||
ColorRef vcol_layers[MAX_GPU_MCOL];
|
||||
int totlayer = gpu_pbvh_bmesh_make_vcol_offs(
|
||||
vdata, ldata, vcol_layers, active_only, active_vcol_type, active_vcol_domain);
|
||||
int totlayer = gpu_pbvh_bmesh_make_vcol_offs(vdata,
|
||||
ldata,
|
||||
vcol_layers,
|
||||
active_only,
|
||||
active_vcol_type,
|
||||
active_vcol_domain,
|
||||
active_vcol_layer);
|
||||
|
||||
for (int i = 0; i < totlayer; i++) {
|
||||
ColorRef *ref = vcol_layers + i;
|
||||
CustomDataLayer *cl = vdata->layers + ref->layer_idx;
|
||||
CustomData *cdata = ref->domain == ATTR_DOMAIN_POINT ? vdata : ldata;
|
||||
|
||||
CustomDataLayer *cl = cdata->layers + ref->layer_idx;
|
||||
|
||||
if (g_vbo_id.totcol < MAX_GPU_MCOL) {
|
||||
g_vbo_id.col[ci++] = GPU_vertformat_attr_add(
|
||||
&g_vbo_id.format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
g_vbo_id.totcol++;
|
||||
|
||||
DRW_make_cdlayer_attr_aliases(&g_vbo_id.format, "c", vdata, cl);
|
||||
DRW_make_cdlayer_attr_aliases(&g_vbo_id.format, "c", cdata, cl);
|
||||
|
||||
if ((int)ref->layer_idx == act && (int)ref->domain == active_vcol_domain) {
|
||||
if (cl == active_vcol_layer) {
|
||||
GPU_vertformat_alias_add(&g_vbo_id.format, "ac");
|
||||
}
|
||||
}
|
||||
|
@ -1579,7 +1586,8 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
|
|||
int face_sets_color_default,
|
||||
short mat_nr,
|
||||
int active_vcol_type,
|
||||
int active_vcol_domain)
|
||||
int active_vcol_domain,
|
||||
CustomDataLayer *active_vcol_layer)
|
||||
{
|
||||
bool active_vcol_only = g_vbo_id.active_vcol_only;
|
||||
|
||||
|
@ -1592,8 +1600,13 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
|
|||
|
||||
ColorRef cd_vcols[MAX_GPU_MCOL];
|
||||
|
||||
const int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(
|
||||
&bm->vdata, &bm->ldata, cd_vcols, active_vcol_only, active_vcol_type, active_vcol_domain);
|
||||
const int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(&bm->vdata,
|
||||
&bm->ldata,
|
||||
cd_vcols,
|
||||
active_vcol_only,
|
||||
active_vcol_type,
|
||||
active_vcol_domain,
|
||||
active_vcol_layer);
|
||||
|
||||
/* Count visible triangles */
|
||||
tottri = gpu_bmesh_face_visible_count(tribuf, mat_nr) * 6;
|
||||
|
@ -1764,7 +1777,8 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
|
|||
bool flat_vcol,
|
||||
short mat_nr,
|
||||
int active_vcol_type,
|
||||
int active_vcol_domain)
|
||||
int active_vcol_domain,
|
||||
CustomDataLayer *active_vcol_layer)
|
||||
{
|
||||
|
||||
bool active_vcol_only = g_vbo_id.active_vcol_only;
|
||||
|
@ -1785,8 +1799,13 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
|
|||
|
||||
ColorRef cd_vcols[MAX_GPU_MCOL];
|
||||
|
||||
int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(
|
||||
&bm->vdata, &bm->ldata, cd_vcols, active_vcol_only, active_vcol_type, active_vcol_domain);
|
||||
int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(&bm->vdata,
|
||||
&bm->ldata,
|
||||
cd_vcols,
|
||||
active_vcol_only,
|
||||
active_vcol_type,
|
||||
active_vcol_domain,
|
||||
active_vcol_layer);
|
||||
|
||||
/* Count visible triangles */
|
||||
tottri = gpu_bmesh_face_visible_count(tribuf, mat_nr);
|
||||
|
@ -1936,7 +1955,8 @@ ATTR_NO_OPT void GPU_pbvh_bmesh_buffers_update(PBVHGPUBuildArgs *args)
|
|||
args->face_sets_color_default,
|
||||
mat_nr,
|
||||
args->active_vcol_type,
|
||||
args->active_vcol_domain);
|
||||
args->active_vcol_domain,
|
||||
args->active_vcol_layer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1959,7 +1979,8 @@ ATTR_NO_OPT void GPU_pbvh_bmesh_buffers_update(PBVHGPUBuildArgs *args)
|
|||
cd_vcols,
|
||||
active_vcol_only,
|
||||
args->active_vcol_type,
|
||||
args->active_vcol_domain);
|
||||
args->active_vcol_domain,
|
||||
args->active_vcol_layer);
|
||||
|
||||
/* Count visible triangles */
|
||||
if (buffers->smooth) {
|
||||
|
@ -1976,7 +1997,8 @@ ATTR_NO_OPT void GPU_pbvh_bmesh_buffers_update(PBVHGPUBuildArgs *args)
|
|||
args->flat_vcol,
|
||||
mat_nr,
|
||||
args->active_vcol_type,
|
||||
args->active_vcol_domain);
|
||||
args->active_vcol_domain,
|
||||
args->active_vcol_layer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -197,6 +197,11 @@ typedef struct Mesh {
|
|||
int attributes_active_index;
|
||||
int vertex_group_active_index;
|
||||
|
||||
/* note that this can be inside of either vdata or ldata,
|
||||
and can reference a layer of type CD_PROP_COLOR or
|
||||
CD_MLOOPCOL */
|
||||
int active_color_index;
|
||||
|
||||
/* the last selected vertex/edge/face are used for the active face however
|
||||
* this means the active face must always be selected, this is to keep track
|
||||
* of the last selected face and is similar to the old active face flag where
|
||||
|
@ -228,15 +233,14 @@ typedef struct Mesh {
|
|||
* consistently ensure that this symmetry is maintained. */
|
||||
char symmetry;
|
||||
|
||||
char _pad1[2];
|
||||
char _pad1[6];
|
||||
|
||||
int face_sets_color_seed;
|
||||
/* Stores the initial Face Set to be rendered white. This way the overlay can be enabled by
|
||||
* default and Face Sets can be used without affecting the color of the mesh. */
|
||||
int face_sets_color_default;
|
||||
|
||||
void *_pad2;
|
||||
Mesh_Runtime runtime;
|
||||
void *_pad2;
|
||||
} Mesh;
|
||||
|
||||
/* deprecated by MTFace, only here for file reading */
|
||||
|
|
|
@ -412,6 +412,64 @@ static void rna_AttributeGroup_update_active(Main *bmain, Scene *scene, PointerR
|
|||
rna_Attribute_update_data(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
static PointerRNA rna_AttributeGroup_active_color_get(PointerRNA *ptr)
|
||||
{
|
||||
ID *id = ptr->owner_id;
|
||||
CustomDataLayer *layer = BKE_id_attributes_active_color_get(id);
|
||||
|
||||
PointerRNA attribute_ptr;
|
||||
RNA_pointer_create(id, &RNA_Attribute, layer, &attribute_ptr);
|
||||
return attribute_ptr;
|
||||
}
|
||||
|
||||
static void rna_AttributeGroup_active_color_set(PointerRNA *ptr,
|
||||
PointerRNA attribute_ptr,
|
||||
ReportList *UNUSED(reports))
|
||||
{
|
||||
ID *id = ptr->owner_id;
|
||||
CustomDataLayer *layer = attribute_ptr.data;
|
||||
|
||||
BKE_id_attributes_active_color_set(id, layer);
|
||||
}
|
||||
|
||||
static int rna_AttributeGroup_active_color_index_get(PointerRNA *ptr)
|
||||
{
|
||||
int *active = BKE_id_attributes_active_color_index_p(ptr->owner_id);
|
||||
|
||||
return active ? *active : -1;
|
||||
}
|
||||
|
||||
static void rna_AttributeGroup_active_color_index_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
ID *id = ptr->owner_id;
|
||||
int *active = BKE_id_attributes_active_color_index_p(ptr->owner_id);
|
||||
|
||||
if (active) {
|
||||
CustomDataLayer *layer = BKE_id_attribute_from_index(id, value);
|
||||
|
||||
if (layer) {
|
||||
BKE_id_attributes_active_color_set(id, layer);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s: error setting active color index to %d\n", __func__, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_AttributeGroup_active_color_index_range(
|
||||
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
|
||||
{
|
||||
*min = 0;
|
||||
*max = BKE_id_attributes_length(ptr->owner_id, CD_MASK_PROP_ALL);
|
||||
|
||||
*softmin = *min;
|
||||
*softmax = *max;
|
||||
}
|
||||
|
||||
static void rna_AttributeGroup_update_active_color(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
rna_Attribute_update_data(bmain, scene, ptr);
|
||||
}
|
||||
#else
|
||||
|
||||
static void rna_def_attribute_float(BlenderRNA *brna)
|
||||
|
@ -772,6 +830,25 @@ static void rna_def_attribute_group(BlenderRNA *brna)
|
|||
"rna_AttributeGroup_active_index_set",
|
||||
"rna_AttributeGroup_active_index_range");
|
||||
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active");
|
||||
|
||||
prop = RNA_def_property(srna, "active_color", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Attribute");
|
||||
RNA_def_property_pointer_funcs(prop,
|
||||
"rna_AttributeGroup_active_color_get",
|
||||
"rna_AttributeGroup_active_color_set",
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
|
||||
RNA_def_property_ui_text(prop, "Active Color", "Active color attribute");
|
||||
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active_color");
|
||||
|
||||
prop = RNA_def_property(srna, "active_color_index", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_int_funcs(prop,
|
||||
"rna_AttributeGroup_active_color_index_get",
|
||||
"rna_AttributeGroup_active_color_index_set",
|
||||
"rna_AttributeGroup_active_color_index_range");
|
||||
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active_color");
|
||||
}
|
||||
|
||||
void rna_def_attributes_common(StructRNA *srna)
|
||||
|
|
Loading…
Reference in New Issue