Sculpt-dev: Code cleanup

This commit is contained in:
Joseph Eagar 2022-02-08 20:09:25 -08:00
parent 5f631ca7c8
commit a5cc113c7b
13 changed files with 448 additions and 162 deletions

View File

@ -489,7 +489,7 @@ class MESH_UL_color_attributes(UIList):
class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
bl_label = "Vertex Colors"
bl_label = "Color Attributes"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}

View File

@ -457,8 +457,8 @@ void BKE_brush_channelset_foreach_id(void *userdata,
/******** brush mapping stuff *******/
void BKE_brush_mapping_copy_data(BrushMapping *dst, BrushMapping *src);
const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping);
const char *BKE_brush_mapping_type_to_typename(BrushMappingType mapping);
const char *BKE_brush_mapping_type_to_str(eBrushMappingType mapping);
const char *BKE_brush_mapping_type_to_typename(eBrushMappingType mapping);
/********* misc utility functions *********/

View File

@ -261,9 +261,9 @@ template<typename T> class BrushChannelIF {
continue;
}
float inputf = (reinterpret_cast<float *>(mapping))[i] * mp->premultiply;
float inputf = (reinterpret_cast<float *>(mapping))[i] * mp->premultiply_factor;
switch ((BrushMappingFunc)mp->mapfunc) {
switch ((eBrushMappingFunc)mp->mapfunc) {
case BRUSH_MAPFUNC_NONE:
break;
case BRUSH_MAPFUNC_SAW:
@ -361,8 +361,8 @@ class BrushChannelSetIF {
void destroy()
{
if (_chset) {
if (_chset->namemap) {
BLI_ghash_free(_chset->namemap, nullptr, nullptr);
if (_chset->channelmap) {
BLI_ghash_free(_chset->channelmap, nullptr, nullptr);
}
LISTBASE_FOREACH (BrushChannel *, ch, &_chset->channels) {
@ -385,7 +385,7 @@ class BrushChannelSetIF {
template<typename T> BrushChannelIF<T> lookup(const char *idname)
{
BrushChannel *ch = static_cast<BrushChannel *>(
BLI_ghash_lookup(_chset->namemap, static_cast<const void *>(idname)));
BLI_ghash_lookup(_chset->channelmap, static_cast<const void *>(idname)));
BrushChannelIF<T> chif(ch);
return chif;

View File

@ -538,7 +538,7 @@ void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
mp->blendmode = !mdef->no_default ? MA_RAMP_MULT : mdef->blendmode;
mp->factor = mdef->factor == 0.0f ? 1.0f : mdef->factor;
mp->premultiply = 1.0f;
mp->premultiply_factor = 1.0f;
mp->func_cutoff = mdef->func_cutoff != 0.0f ? mdef->func_cutoff : 0.5f;
if (i == BRUSH_MAPPING_STROKE_T) {
@ -616,7 +616,7 @@ BrushChannelSet *BKE_brush_channelset_create(const char *info)
BrushChannelSet *chset = (BrushChannelSet *)MEM_callocN(sizeof(BrushChannelSet),
info ? tag : "BrushChannelSet");
chset->namemap = BLI_ghash_str_new("BrushChannelSet ghash");
chset->channelmap = BLI_ghash_str_new("BrushChannelSet ghash");
return chset;
}
@ -625,7 +625,7 @@ void BKE_brush_channelset_free(BrushChannelSet *chset)
{
BrushChannel *ch, *next;
BLI_ghash_free(chset->namemap, NULL, NULL);
BLI_ghash_free(chset->channelmap, NULL, NULL);
for (ch = chset->channels.first; ch; ch = next) {
next = ch->next;
@ -692,22 +692,22 @@ void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch)
BKE_brush_channel_ensure_unque_name(chset, ch);
BLI_addtail(&chset->channels, ch);
BLI_ghash_insert(chset->namemap, ch->idname, ch);
BLI_ghash_insert(chset->channelmap, ch->idname, ch);
chset->totchannel++;
}
void BKE_brush_channel_rename(BrushChannelSet *chset, BrushChannel *ch, const char *newname)
{
BLI_ghash_remove(chset->namemap, ch->idname, NULL, NULL);
BLI_ghash_remove(chset->channelmap, ch->idname, NULL, NULL);
BLI_strncpy(ch->idname, newname, sizeof(ch->idname));
BKE_brush_channel_ensure_unque_name(chset, ch);
BLI_ghash_insert(chset->namemap, ch->idname, ch);
BLI_ghash_insert(chset->channelmap, ch->idname, ch);
}
void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch)
{
BLI_ghash_remove(chset->namemap, ch->idname, NULL, NULL);
BLI_ghash_remove(chset->channelmap, ch->idname, NULL, NULL);
BLI_remlink(&chset->channels, ch);
chset->totchannel--;
@ -742,7 +742,7 @@ void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, BrushChannel *ch
BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname)
{
return BLI_ghash_lookup(chset->namemap, idname);
return BLI_ghash_lookup(chset->channelmap, idname);
}
BrushChannel *BKE_brush_channelset_lookup_final(BrushChannelSet *child,
@ -1060,9 +1060,9 @@ double BKE_brush_channel_eval_mappings(BrushChannel *ch,
continue;
}
float inputf = ((float *)mapdata)[i] * mp->premultiply;
float inputf = ((float *)mapdata)[i] * mp->premultiply_factor;
switch ((BrushMappingFunc)mp->mapfunc) {
switch ((eBrushMappingFunc)mp->mapfunc) {
case BRUSH_MAPFUNC_NONE:
break;
case BRUSH_MAPFUNC_SAW:
@ -1085,7 +1085,7 @@ double BKE_brush_channel_eval_mappings(BrushChannel *ch,
break;
case BRUSH_MAPFUNC_SQUARE:
inputf -= floorf(inputf);
inputf = inputf > mp->func_cutoff ? 1.0f : 0.0f; //(float)(inputf > 0.5f);
inputf = inputf > mp->func_cutoff ? 1.0f : 0.0f;
break;
default:
break;
@ -1988,7 +1988,7 @@ void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *chset)
{
BLO_read_list(reader, &chset->channels);
chset->namemap = BLI_ghash_str_new("BrushChannelSet");
chset->channelmap = BLI_ghash_str_new("BrushChannelSet");
BrushChannel *ch;
// regenerate chset->totchannel just to be safe
@ -1997,7 +1997,7 @@ void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *chset)
for (ch = chset->channels.first; ch; ch = ch->next) {
chset->totchannel++;
BLI_ghash_insert(chset->namemap, ch->idname, ch);
BLI_ghash_insert(chset->channelmap, ch->idname, ch);
BLO_read_data_address(reader, &ch->curve.curve);
if (ch->curve.curve) {
@ -2012,8 +2012,8 @@ void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *chset)
CurveMapping *curve = mp->curve;
if (mp->premultiply == 0.0f) {
mp->premultiply = 1.0f;
if (mp->premultiply_factor == 0.0f) {
mp->premultiply_factor = 1.0f;
}
if (mp->func_cutoff == 0.0f) {
@ -2084,7 +2084,7 @@ void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *chset)
}
}
const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping)
const char *BKE_brush_mapping_type_to_str(eBrushMappingType mapping)
{
switch (mapping) {
case BRUSH_MAPPING_PRESSURE:
@ -2108,7 +2108,7 @@ const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping)
return "Error";
}
const char *BKE_brush_mapping_type_to_typename(BrushMappingType mapping)
const char *BKE_brush_mapping_type_to_typename(eBrushMappingType mapping)
{
switch (mapping) {
case BRUSH_MAPPING_PRESSURE:
@ -2153,13 +2153,10 @@ void BKE_brush_mapping_copy_data(BrushMapping *dst, BrushMapping *src)
dst->max = src->max;
dst->factor = src->factor;
dst->flag = src->flag;
dst->input_channel = src->input_channel;
dst->blendmode = src->blendmode;
dst->func_cutoff = src->func_cutoff;
dst->mapfunc = src->mapfunc;
dst->premultiply = src->premultiply;
memcpy(dst->name, src->name, sizeof(dst->name));
dst->premultiply_factor = src->premultiply_factor;
}
void BKE_brush_channelset_to_unified_settings(BrushChannelSet *chset, UnifiedPaintSettings *ups)

View File

@ -228,7 +228,7 @@ static void fix_mesh(PBVH *pbvh, BMesh *bm)
// rebuild disk cycles
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_edge_exists(e->v1, e->v2)) {
printf("duplicate edge %p!", e);
printf("duplicate edge %p!\n", e);
bm_kill_only_edge(bm, e);
continue;
@ -333,6 +333,8 @@ CHECKMESH_ATTR static bool check_face_is_manifold(PBVH *pbvh, BMesh *bm, BMFace
continue;
}
int i = 0;
do {
if (!e) {
break;
@ -340,8 +342,14 @@ CHECKMESH_ATTR static bool check_face_is_manifold(PBVH *pbvh, BMesh *bm, BMFace
bool same = e->v1 == v1 && e->v2 == v2;
same = same || (e->v1 == v2 && e->v2 == v1);
if (same && e != l->e) {
printf("duplicate edges!");
// printf("duplicate edges in face!\n");
}
if (i++ > 5000) {
printf("infinite loop in edge disk cycle! v: %p, e: %p\n", v, e);
break;
}
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
}
@ -450,6 +458,35 @@ static bool validate_edge(PBVH *pbvh, BMesh *bm, BMEdge *e, bool autofix, bool c
return ret;
}
CHECKMESH_ATTR bool face_verts_are_same(PBVH *pbvh, BMesh *bm, BMFace *f1, BMFace *f2)
{
BMLoop *l1 = f1->l_first;
BMLoop *l2 = f2->l_first;
int count1 = 0;
do {
count1++;
} while ((l1 = l1->next) != f1->l_first);
do {
bool ok = false;
do {
if (l2->v == l1->v) {
ok = true;
break;
}
} while ((l2 = l2->next) != f2->l_first);
if (!ok) {
return false;
}
} while ((l1 = l1->next) != f1->l_first);
return true;
}
CHECKMESH_ATTR
static bool validate_face(PBVH *pbvh, BMesh *bm, BMFace *f, bool autofix, bool check_manifold)
{
@ -475,6 +512,14 @@ static bool validate_face(PBVH *pbvh, BMesh *bm, BMFace *f, bool autofix, bool c
goto error;
}
BMLoop *l2 = l->radial_next;
do {
if (l2->f != f && face_verts_are_same(pbvh, bm, l2->f, f)) {
_debugprint("Duplicate faces!\n");
goto error;
}
} while ((l2 = l2->radial_next) != l);
BLI_array_append(ls, l);
} while ((l = l->next) != f->l_first);
@ -1420,9 +1465,9 @@ static float maskcb_get(EdgeQueueContext *eq_ctx, BMVert *v1, BMVert *v2)
float w1 = eq_ctx->mask_cb(sv1, eq_ctx->mask_cb_data);
float w2 = eq_ctx->mask_cb(sv2, eq_ctx->mask_cb_data);
//float limit = 0.5;
//if (w1 > limit || w2 > limit) {
return min_ff(w1, w2);
// float limit = 0.5;
// if (w1 > limit || w2 > limit) {
return min_ff(w1, w2);
//}
return (w1 + w2) * 0.5f;
@ -1441,15 +1486,14 @@ BLI_INLINE float calc_weighted_length(EdgeQueueContext *eq_ctx, BMVert *v1, BMVe
float w = 1.0 - maskcb_get(eq_ctx, v1, v2);
float len = len_squared_v3v3(v1->co, v2->co);
w = 1.0 + w*sign;
w = 1.0 + w * sign;
return len * w;
}
static void edge_queue_insert_unified(EdgeQueueContext *eq_ctx, BMEdge *e)
{
if (/*BLI_mm_heap_len(eq_ctx->heap_mm) < eq_ctx->max_heap_mm &&*/ !(e->head.hflag &
BM_ELEM_TAG)) {
if (/*BLI_mm_heap_len(eq_ctx->heap_mm) < eq_ctx->max_heap_mm &&*/ !(e->head.hflag & BM_ELEM_TAG)) {
float len = len_squared_v3v3(e->v1->co, e->v2->co);
len += (BLI_thread_frand(0) - 0.5f) * 0.1 * eq_ctx->limit_mid;
@ -1461,14 +1505,6 @@ static void edge_queue_insert_unified(EdgeQueueContext *eq_ctx, BMEdge *e)
static void edge_queue_insert_val34_vert(EdgeQueueContext *eq_ctx, BMVert *v)
{
MSculptVert *mv = BKE_PBVH_SCULPTVERT(eq_ctx->cd_sculpt_vert, v);
// prevent double adding
if (mv->flag & SCULPTVERT_VALENCE_TEMP) {
return;
}
mv->flag |= SCULPTVERT_VALENCE_TEMP;
BLI_table_gset_add(eq_ctx->used_verts, v);
}
@ -1927,6 +1963,15 @@ static void unified_edge_queue_task_cb(void *__restrict userdata,
}
# endif
do {
/* kind of tricky to atomicly update flags here. . . */
BMEdge edge = *l->e;
edge.head.hflag &= ~BM_ELEM_TAG;
intptr_t *t1 = (uintptr_t*) &edge.head.index;
intptr_t *t2 = (uintptr_t *) &l->e->head.index;
atomic_cas_int64(t2, *t2, *t1);
l->e->head.hflag &= ~BM_ELEM_TAG;
l = l->next;
} while (l != f->l_first);
@ -2135,7 +2180,6 @@ static bool check_face_is_tri(PBVH *pbvh, BMFace *f)
static bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
{
// return;
bm_logstack_push();
static int max_faces = 64;
@ -2427,7 +2471,17 @@ static bool edge_queue_test(EdgeQueueContext *eq_ctx, PBVH *pbvh, BMEdge *e)
float min = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len;
float max = pbvh->bm_max_edge_len * pbvh->bm_max_edge_len;
return len < min || len > max;
bool ret = false;
if (eq_ctx->mode & PBVH_Subdivide) {
ret |= len > max;
}
if (eq_ctx->mode & PBVH_Collapse) {
ret |= len < min;
}
return ret;
}
/* Create a priority queue containing vertex pairs connected by a long
@ -2965,13 +3019,13 @@ static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
return false;
}
static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
BMEdge *e,
BMVert *v1,
BMVert *v2,
GHash *deleted_verts,
BLI_Buffer *deleted_faces,
EdgeQueueContext *eq_ctx)
ATTR_NO_OPT static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
BMEdge *e,
BMVert *v1,
BMVert *v2,
GHash *deleted_verts,
BLI_Buffer *deleted_faces,
EdgeQueueContext *eq_ctx)
{
bm_logstack_push();
@ -3217,6 +3271,7 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
}
pbvh_bmesh_check_nodes(pbvh);
validate_vert_faces(pbvh, pbvh->bm, v_conn, false, true);
if (!snap) {
float co[3];
@ -3225,7 +3280,6 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
// full non-manifold collapse
BM_edge_collapse(pbvh->bm, e, v_del, true, true, true, true);
// non_manifold_collapse(pbvh->bm, e, v_conn);
copy_v3_v3(v_conn->co, co);
}
else {
@ -3236,7 +3290,6 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
// full non-manifold collapse
BM_edge_collapse(pbvh->bm, e, v_del, true, true, true, true);
// non_manifold_collapse(pbvh->bm, e, v_conn);
copy_v3_v3(v_conn->co, co);
}
@ -3245,6 +3298,8 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
return v_conn;
}
validate_vert_faces(pbvh, pbvh->bm, v_conn, false, true);
e2 = v_conn->e;
do {
BMLoop *l = e2->l;
@ -3343,6 +3398,19 @@ static BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
MSculptVert *mv3 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v_conn);
MV_ADD_FLAG(mv3, mupdateflag);
if (!v_conn->e) {
// delete isolated vertex
if (BM_ELEM_CD_GET_INT(v_conn, pbvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
pbvh_bmesh_vert_remove(pbvh, v_conn);
}
BM_log_vert_removed(pbvh->bm_log, v_conn, 0);
BM_vert_kill(pbvh->bm, v_conn);
bm_logstack_pop();
return NULL;
}
if (BM_ELEM_CD_GET_INT(v_conn, pbvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
printf("%s: error: failed to remove vert from pbvh?\n", __func__);
}
@ -3389,8 +3457,6 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
const bool use_frontface,
const bool use_projected)
{
return false;
bool modified = false;
bm_logstack_push();
@ -3422,15 +3488,13 @@ cleanup_valence_3_4(EdgeQueueContext *ectx,
SculptVertRef sv = {.i = (intptr_t)v};
if (len_squared_v3v3(v->co, center) >= rsqr || !v->e || ectx->mask_cb(sv, ectx->mask_cb_data) < 0.5f) {
if (len_squared_v3v3(v->co, center) >= rsqr || !v->e ||
ectx->mask_cb(sv, ectx->mask_cb_data) < 0.5f) {
continue;
}
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v);
mv->flag &= ~SCULPTVERT_VALENCE_TEMP;
validate_vert(pbvh, pbvh->bm, v, false, true);
check_vert_fan_are_tris(pbvh, v);
validate_vert(pbvh, pbvh->bm, v, true, true);
@ -3972,7 +4036,7 @@ ATTR_NO_OPT bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
#ifdef DYNTOPO_USE_MINMAX_HEAP
eq_ctx.heap_mm = BLI_mm_heap_new_ex(max_ii(DYNTOPO_MAX_ITER, custom_max_steps));
eq_ctx.used_verts = BLI_table_gset_new(__func__);
eq_ctx.max_heap_mm = DYNTOPO_MAX_ITER << 2;
eq_ctx.max_heap_mm = DYNTOPO_MAX_ITER << 8;
eq_ctx.limit_min = pbvh->bm_min_edge_len;
eq_ctx.limit_max = pbvh->bm_max_edge_len;
eq_ctx.limit_mid = eq_ctx.limit_max * 0.5f + eq_ctx.limit_min * 0.5f;
@ -3991,6 +4055,9 @@ ATTR_NO_OPT bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
use_projected,
mode & PBVH_LocalSubdivide);
}
else {
edge_queue_init(&eq_ctx, use_projected, use_frontface, center, view_normal, radius);
}
#ifdef SKINNY_EDGE_FIX
// prevent remesher thrashing by throttling edge splitting in pathological case of skinny
@ -4115,6 +4182,11 @@ ATTR_NO_OPT bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
MEM_SAFE_FREE(edges);
if (mode & PBVH_Cleanup) {
modified |= do_cleanup_3_4(
&eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected);
}
if (modified) {
// avoid potential infinite loops
const int totnode = pbvh->totnode;
@ -4136,11 +4208,6 @@ ATTR_NO_OPT bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
}
}
if (mode & PBVH_Cleanup) {
modified |= do_cleanup_3_4(
&eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected);
}
/* clear PBVH_UpdateTopology flags */
for (int i = 0; i < pbvh->totnode; i++) {
PBVHNode *node = pbvh->nodes + i;
@ -4296,12 +4363,12 @@ static const int splitmap[43][16] = {
{6, -1, 3, -1, 5, -1, 1, -1}, // 42
};
static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
PBVH *pbvh,
BMesh *bm,
BMEdge **edges1,
int totedge,
bool ignore_isolated_edges)
ATTR_NO_OPT static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
PBVH *pbvh,
BMesh *bm,
BMEdge **edges1,
int totedge,
bool ignore_isolated_edges)
{
bm_logstack_push();
@ -4384,24 +4451,6 @@ static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
BMEdge *e = edges[i];
BMLoop *l = e->l;
#if 0
int ni = BM_ELEM_CD_GET_INT(e->v1, pbvh->cd_vert_node_offset);
if (ni >= 0) {
PBVHNode *node = pbvh->nodes + ni;
BLI_table_gset_remove(node->bm_unique_verts, e->v1, NULL);
BM_ELEM_CD_SET_INT(e->v1, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
}
ni = BM_ELEM_CD_GET_INT(e->v2, pbvh->cd_vert_node_offset);
if (ni >= 0) {
PBVHNode *node = pbvh->nodes + ni;
BLI_table_gset_remove(node->bm_unique_verts, e->v2, NULL);
BM_ELEM_CD_SET_INT(e->v2, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
}
#endif
check_vert_fan_are_tris(pbvh, e->v1);
check_vert_fan_are_tris(pbvh, e->v2);
@ -4599,7 +4648,6 @@ static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
MV_ADD_FLAG(mv,
SCULPTVERT_NEED_DISK_SORT | SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_BOUNDARY);
mv->flag &= ~SCULPTVERT_VALENCE_TEMP;
BM_ELEM_CD_SET_INT(newv, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
@ -4772,9 +4820,29 @@ static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
continue;
}
bool log_edge = !BM_edge_exists(v1, v2);
validate_face(pbvh, bm, f2, false, true);
bool log_edge = true;
BMFace *newf = NULL;
BMEdge *exist_e;
if ((exist_e = BM_edge_exists(v1, v2))) {
log_edge = false;
BMLoop *l1 = exist_e->l;
if (l1 && l1->f == f2) {
l1 = l1->radial_next;
}
if (l1 && l1->f != f2) {
// newf = l1->f;
}
}
else {
newf = BM_face_split(bm, f2, l1, l2, &rl, NULL, false);
}
BMFace *newf = BM_face_split(bm, f2, l1, l2, &rl, NULL, false);
if (newf) {
// rl->e->head.hflag &= ~BM_ELEM_TAG;
// edge_queue_insert_unified(eq_ctx, rl->e);
@ -4818,12 +4886,12 @@ static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
newfaces[count++] = newf;
}
else {
printf("error!\n");
printf("%s: error 4!\n", __func__);
}
f2 = newf;
}
else {
printf("error!\n");
// printf("%s: error 2!\n", __func__);
continue;
}
}

View File

@ -722,7 +722,10 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if ((p1_nv == p2_nv) && (memcmp(p1_v, p2_v, p1_nv * sizeof(*p1_v)) == 0)) {
if (do_verbose) {
/* TODO: convert list to string */
PRINT_ERR("\tPolys %u and %u use same vertices (%d", prev_sp->index, sp->index, *p1_v);
PRINT_ERR("\tPolys %u(len=%d) and %u use same vertices (%d",
prev_sp->index,
p1_nv, sp->index,
*p1_v);
for (j = 1; j < p1_nv; j++) {
PRINT_ERR(", %d", p1_v[j]);
}

View File

@ -2752,8 +2752,8 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
if (ch->mappings[i].premultiply == 0.0f) {
ch->mappings[i].premultiply = 1.0f;
if (ch->mappings[i].premultiply_factor == 0.0f) {
ch->mappings[i].premultiply_factor = 1.0f;
}
if (ch->mappings[i].blendmode == MA_RAMP_BLEND) {
@ -2788,7 +2788,7 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
LISTBASE_FOREACH (BrushChannel *, ch, &brush->channels->channels) {
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
ch->mappings[i].premultiply = 1.0f;
ch->mappings[i].premultiply_factor = 1.0f;
}
BrushMapping *mp = ch->mappings + BRUSH_MAPPING_STROKE_T;

View File

@ -788,8 +788,6 @@ int bmesh_elem_check(void *element, const char htype)
#endif /* NDEBUG */
int bleh = 0;
/**
* low level function, only frees the vert,
* doesn't change or adjust surrounding geometry
@ -811,10 +809,6 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v)
BLI_mempool_free(bm->vtoolflagpool, flags->flag);
flags->flag = NULL;
if (bleh) {
printf("eek\n");
}
}
if (v->head.data) {
@ -926,6 +920,8 @@ void bm_kill_only_edge(BMesh *bm, BMEdge *e)
CustomData_bmesh_free_block(&bm->edata, &e->head.data);
}
e->l = NULL;
BLI_mempool_free(bm->epool, e);
}
@ -2085,8 +2081,8 @@ static char *obj_append_line(char *line, char *str, char *fixed, int *size, int
{
int len = (int)strlen(line);
if (*i + len >= *size) {
*size += *size >> 1;
if (*i + len + 1 >= *size) {
*size += len + ((*size) >> 1);
if (str == fixed) {
str = MEM_mallocN(*size, "buf");
@ -2113,14 +2109,18 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
buf[0] = 0;
BMVert **vs = NULL;
BMEdge **es = NULL;
BMFace **fs = NULL;
BMVert **vs = NULL, **initial_vs = NULL;
BMEdge **es = NULL, **initial_es = NULL;
BMFace **fs = NULL, **initial_fs = NULL;
BLI_array_staticdeclare(vs, 64);
BLI_array_staticdeclare(es, 64);
BLI_array_staticdeclare(fs, 64);
BLI_array_staticdeclare(initial_vs, 8);
BLI_array_staticdeclare(initial_es, 8);
BLI_array_staticdeclare(initial_fs, 8);
SmallHash visit;
BLI_smallhash_init(&visit);
@ -2136,12 +2136,15 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
switch (*c) {
case 'v':
BLI_array_append(vs, (BMVert *)ptr);
BLI_array_append(initial_vs, (BMVert *)ptr);
break;
case 'e':
BLI_array_append(es, (BMEdge *)ptr);
BLI_array_append(initial_es, (BMEdge *)ptr);
break;
case 'f':
BLI_array_append(fs, (BMFace *)ptr);
BLI_array_append(initial_fs, (BMFace *)ptr);
break;
}
@ -2204,10 +2207,11 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
} while ((l = l->next) != f->l_first);
}
struct {
struct stack {
BMVert *v;
int depth;
} stack[256];
} *stack = NULL;
BLI_array_staticdeclare(stack, 256);
SmallHash elemset;
BLI_smallhash_init(&elemset);
@ -2225,16 +2229,26 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
for (int i = 0; i < BLI_array_len(vs); i++) {
int si = 0;
BLI_array_clear(stack);
// connected islands only
if (i > 0) {
break;
}
BLI_array_grow_one(stack);
stack[si].v = vs[i];
stack[si].depth = 0;
si++;
while (si > 0) {
BLI_array_len_set(stack, BLI_array_len(stack) - 1);
if (si >= 8192) {
printf("%s: stack error\n", __func__);
}
si--;
BMVert *v = stack[si].v;
@ -2254,11 +2268,15 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
BMEdge *e = v->e;
do {
if (!BLI_smallhash_ensure_p(&visit, (uintptr_t)e, &val)) {
BLI_array_grow_one(stack);
*val = NULL;
stack[si].v = e->v1;
stack[si].depth = startdepth + 1;
si++;
BLI_array_grow_one(stack);
stack[si].v = e->v2;
stack[si].depth = startdepth + 1;
si++;
@ -2279,6 +2297,8 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
BMLoop *l2 = l;
do {
if (!BLI_smallhash_ensure_p(&visit, (uintptr_t)l->v, &val)) {
BLI_array_grow_one(stack);
*val = NULL;
stack[si].v = l->v;
stack[si].depth = startdepth + 1;
@ -2299,11 +2319,48 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
es[i]->head.api_flag &= ~tag;
}
char line[256];
char line[128];
line[0] = 0;
for (int i = 0; i < BLI_array_len(vs); i++) {
vs[i]->head.api_flag &= ~tag;
}
for (int i = 0; i < BLI_array_len(es); i++) {
es[i]->head.api_flag &= ~tag;
}
for (int i = 0; i < BLI_array_len(fs); i++) {
fs[i]->head.api_flag &= ~tag;
}
for (int i = 0; i < BLI_array_len(initial_vs); i++) {
initial_vs[i]->head.api_flag |= tag;
}
for (int i = 0; i < BLI_array_len(initial_es); i++) {
initial_es[i]->head.api_flag |= tag;
initial_es[i]->v1->head.api_flag |= tag;
initial_es[i]->v2->head.api_flag |= tag;
}
for (int i = 0; i < BLI_array_len(initial_fs); i++) {
BMFace *f = initial_fs[i];
f->head.api_flag |= tag;
BMLoop *l = f->l_first;
do {
l->v->head.api_flag |= tag;
} while ((l = l->next) != f->l_first);
}
for (int i = 0; i < BLI_array_len(vs); i++) {
BMVert *v = vs[i];
if (v->head.api_flag & tag) {
sprintf(line, "#select\n");
str = obj_append_line(line, str, buf, &size, &stri);
}
v->head.index = i + 1;
sprintf(line, "v %.4f %.4f %.4f\n", v->co[0], v->co[1], v->co[2]);
@ -2319,6 +2376,7 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
do {
sprintf(line, " %d", l->v->head.index);
str = obj_append_line(line, str, buf, &size, &stri);
} while ((l = l->next) != f->l_first);
@ -2331,6 +2389,11 @@ ATTR_NO_OPT static char *bm_save_local_obj_text(
BLI_array_free(vs);
BLI_array_free(es);
BLI_array_free(fs);
BLI_array_free(stack);
BLI_array_free(initial_vs);
BLI_array_free(initial_es);
BLI_array_free(initial_fs);
return str;
}
@ -2374,14 +2437,21 @@ char *_last_local_obj = NULL;
# define JVKE_CHECK_ELEMENT(elem)
#endif
BMVert *bmesh_kernel_join_vert_kill_edge(
ATTR_NO_OPT BMVert *bmesh_kernel_join_vert_kill_edge(
BMesh *bm, BMEdge *e, BMVert *v_kill, const bool do_del, const bool combine_flags)
{
BMVert *v_conn = BM_edge_other_vert(e, v_kill);
#ifdef JVKE_DEBUG
char buf[LOCAL_OBJ_SIZE];
char *saved_obj = _last_local_obj = bm_save_local_obj_text(bm, 2, buf, "e", e);
if (_last_local_obj) {
free(_last_local_obj);
}
char *saved_obj = bm_save_local_obj_text(bm, 2, buf, "e", e);
_last_local_obj = strdup(saved_obj);
bm_local_obj_free(saved_obj, buf);
#endif
@ -2392,6 +2462,7 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
BMVert *v_del = BM_edge_other_vert(e, v_conn);
const int tag = _FLAG_WALK_ALT; // using bmhead.api_flag here
const int dup_tag = _FLAG_OVERLAP;
JVKE_CHECK_ELEMENT(v_conn);
JVKE_CHECK_ELEMENT(v_del);
@ -2408,6 +2479,10 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
BMLoop *l = e2->l;
do {
BM_ELEM_API_FLAG_DISABLE(l->f, tag);
BM_ELEM_API_FLAG_DISABLE(l->f, dup_tag);
BM_ELEM_API_FLAG_DISABLE(l->e, dup_tag);
BM_ELEM_API_FLAG_DISABLE(l->v, dup_tag);
} while ((l = l->radial_next) != e2->l);
} while ((e2 = BM_DISK_EDGE_NEXT(e2, v)) != v->e);
}
@ -2605,6 +2680,10 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
}
bmesh_radial_loop_append(l->e, l);
BM_ELEM_API_FLAG_DISABLE(l->e, dup_tag);
BM_ELEM_API_FLAG_DISABLE(l->v, dup_tag);
BM_ELEM_API_FLAG_DISABLE(l->f, dup_tag);
} while ((l = l->next) != f->l_first);
}
@ -2635,6 +2714,89 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
}
#endif
/* use euler criteria to check for duplicate faces */
if (do_del && v_conn->e) {
int tote = 0, totv = 0, totf = 0;
BMVert *v = v_conn;
BMEdge *e2 = v->e;
if (!BM_ELEM_API_FLAG_TEST(v, dup_tag)) {
BM_ELEM_API_FLAG_ENABLE(v, dup_tag);
totv++;
}
do {
BMVert *v2 = BM_edge_other_vert(e2, v);
if (!BM_ELEM_API_FLAG_TEST(e2, dup_tag)) {
BM_ELEM_API_FLAG_ENABLE(e2, dup_tag);
tote++;
}
if (!BM_ELEM_API_FLAG_TEST(v2, dup_tag)) {
BM_ELEM_API_FLAG_ENABLE(v2, dup_tag);
totv++;
}
if (e2->l) {
BMLoop *l_radial = e2->l;
do {
if (BM_ELEM_API_FLAG_TEST(l_radial->f, dup_tag)) {
continue;
}
totf++;
BM_ELEM_API_FLAG_ENABLE(l_radial->f, dup_tag);
BMLoop *l = l_radial;
do {
if (!BM_ELEM_API_FLAG_TEST(l->v, dup_tag)) {
BM_ELEM_API_FLAG_ENABLE(l->v, dup_tag);
totv++;
}
if (!BM_ELEM_API_FLAG_TEST(l->e, dup_tag)) {
BM_ELEM_API_FLAG_ENABLE(l->e, dup_tag);
tote++;
}
} while ((l = l->next) != l_radial);
} while ((l_radial = l_radial->radial_next) != e2->l);
}
} while ((e2 = BM_DISK_EDGE_NEXT(e2, v)) != v->e);
int eul = totv - tote + totf;
if (eul != 1) {
//printf("%s: possible duplicate geometry! %d\n", __func__, eul);
e2 = v->e;
do {
BMLoop *l = e2->l;
if (!l) {
continue;
}
BMLoop *l_next = l;
do {
/* no guarantee each face has only one loop in radial
list */
l_next = l->radial_next;
while (l_next != l && l_next->f == l->f) {
l_next = l->radial_next;
}
BMFace *f;
if ((f = BM_face_find_double(l->f))) {
BM_face_kill(bm, l->f);
}
} while (e2->l && (l = l_next) != e2->l);
} while ((e2 = BM_DISK_EDGE_NEXT(e2, v)) != v->e);
}
}
// printf("v_del: %p, v_conn: %p\n", v_del->e, v_conn->e);
if (do_del) {
JVKE_CHECK_ELEMENT(v_del);
@ -2648,13 +2810,13 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
}
/*original version of bmesh_kernel_join_vert_kill_edge*/
BMVert *bmesh_kernel_join_vert_kill_edge_fast(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
const bool do_del,
const bool check_edge_exists,
const bool kill_degenerate_faces,
const bool combine_flags)
ATTR_NO_OPT BMVert *bmesh_kernel_join_vert_kill_edge_fast(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
const bool do_del,
const bool check_edge_exists,
const bool kill_degenerate_faces,
const bool combine_flags)
{
BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *);
BMVert *v_target = BM_edge_other_vert(e_kill, v_kill);
@ -2735,7 +2897,7 @@ BMVert *bmesh_kernel_join_vert_kill_edge_fast(BMesh *bm,
return v_target;
}
BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
ATTR_NO_OPT BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
{
BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL;
int newlen = 0, i, f1len = 0, f2len = 0;

View File

@ -464,7 +464,7 @@ BMVert *BM_edge_collapse(BMesh *bm,
const bool combine_flags,
const bool full_non_manifold_collapse)
{
if (full_non_manifold_collapse) {
if (full_non_manifold_collapse||true) {
return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, combine_flags);
}
else {

View File

@ -413,7 +413,7 @@ void bmesh_radial_loop_append(BMEdge *e, BMLoop *l)
l->e = e;
}
void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l)
ATTR_NO_OPT void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l)
{
/* if e is non-NULL, l must be in the radial cycle of e */
if (UNLIKELY(e != l->e)) {

View File

@ -455,7 +455,9 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op)
BMO_op_finish(bm, &weldop);
}
void bmo_collapse_exec(BMesh *bm, BMOperator *op)
#define USE_BM_EDGE_COLLAPSE
ATTR_NO_OPT void bmo_collapse_exec(BMesh *bm, BMOperator *op)
{
BMOperator weldop;
BMWalker walker;
@ -521,6 +523,12 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
uint j;
BLI_stack_pop(edge_stack, &e);
#ifdef USE_BM_EDGE_COLLAPSE
if (e->head.htype != BM_EDGE) {
continue;
}
#endif
for (j = 0; j < 2; j++) {
BMVert *v_src = *((&e->v1) + j);
@ -528,6 +536,11 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
BM_elem_flag_enable(v_src, BM_ELEM_TAG);
BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar);
#ifdef USE_BM_EDGE_COLLAPSE
BM_edge_collapse(bm, e, v_src, true, true, true, true);
break;
#endif
}
}
}
@ -536,7 +549,10 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
BLI_stack_free(edge_stack);
#ifndef USE_BM_EDGE_COLLAPSE
BMO_op_exec(bm, &weldop);
#endif
BMO_op_finish(bm, &weldop);
BMW_end(&walker);

View File

@ -29,26 +29,48 @@
struct GHash;
typedef struct BrushMapping {
char name[64];
/* Input mapping struct. An input mapping transform
stroke inputs intos outputs. Inputs can be device
events (like pen pressure/tilt) or synethesize
(cumulative stroke distance, random, etc).
/*reference to a cached curve, see BKE_curvemapping_cache*/
Inspired by Krita.
*/
typedef struct BrushMapping {
/* note that we use a curve cache (see BKE_curvemapping_cache)
and copy on write semantics. BrushChannels are copied
extensively (mostly to cache input mappings and resolve
channel inheritance), to the point that copying the
channel curves was a problem.
*/
CurveMapping *curve;
float factor;
short blendmode;
short input_channel;
int blendmode; /* blendmode, a subset of the MA_BLEND_XXX enums*/
int flag, type;
float min, max;
float premultiply; // premultiply input data
int mapfunc;
float premultiply_factor; /** factor to premultiply input data with */
int mapfunc; /** mapping function, see eBrushMappingFunc. Most are periodic. */
/** threshold for BRUSH_MAPFUNC_CUTOFF and BRUSH_MAPFUNC_SQUARE mapping functions */
float func_cutoff;
/** controls whether this channel should inherit from scene defaults,
* see eBrushMappingInheritMode */
char inherit_mode, _pad[3];
} BrushMapping;
typedef struct BrushCurve {
CurveMapping *curve;
int preset; // see eBrushCurvePreset, this differs from the one in BrushMappingDef
/** curve preset, see eBrushCurvePreset.
Note: this differs from BrushMappingDef's preset field
*/
int preset;
char preset_slope_negative;
char _pad[3];
} BrushCurve;
@ -56,60 +78,78 @@ typedef struct BrushCurve {
typedef struct BrushChannel {
struct BrushChannel *next, *prev;
char idname[64];
char name[64];
char *category; // if NULL, def->category will be used
/** Channel id. Avoid calling API methods that take strings directly.
There are API facilities to check channel idnames at compile time:
the BRUSHSET_XXX macros, SCULPT_get_XXX, etc. On the C++ side
BrushChannelSetIF has accessor methods, e.g. BrushChannelSet::radius.
*/
char idname[64];
char name[64]; /** user-friendly name */
char *category; /** category; if NULL, def->category will be used */
struct BrushChannelType *def;
struct BrushChannelType *def; /* Brush channel definition */
float fvalue;
int ivalue;
float vector[4];
/*
Need to investigate whether we
can use ID properties here. ID properties
don't support CurveMappings and do support
things we don't want, like groups, strings and
ID pointer properties.
We could implement an ID property CurveMapping
type and prevent the creation of group properties
at the API level though.
*/
float fvalue; /** floating point value */
int ivalue; /** stores integer, boolean, enum and bitmasks */
float vector[4]; /* stores 3 and 4 component vectors */
BrushCurve curve;
BrushMapping mappings[7]; // should always be BRUSH_MAPPING_MAX
BrushMapping mappings[7]; /* dimension should always be BRUSH_MAPPING_MAX */
short type, ui_order;
int flag;
short type; /** eBrushChannelType */
short ui_order;
int flag; /** eBrushChannelFlag */
} BrushChannel;
typedef struct BrushChannelSet {
ListBase channels;
int totchannel, _pad[1];
struct GHash *namemap;
struct GHash *channelmap; /** quick lookup ghash, maps idnames to brush channels */
} BrushChannelSet;
#define BRUSH_CHANNEL_MAX_IDNAME sizeof(((BrushChannel){0}).idname)
/* BrushMapping->flag */
enum {
typedef enum eBrushMappingFlags {
BRUSH_MAPPING_ENABLED = 1 << 0,
BRUSH_MAPPING_INVERT = 1 << 1,
BRUSH_MAPPING_UI_EXPANDED = 1 << 2,
};
} eBrushMappingFlags;
/* BrushMapping->inherit_mode */
enum {
typedef enum eBrushMappingInheritMode {
/* never inherit */
BRUSH_MAPPING_INHERIT_NEVER,
/* always inherit */
BRUSH_MAPPING_INHERIT_ALWAYS,
/* use channel's inheritance mode */
BRUSH_MAPPING_INHERIT_CHANNEL
};
} eBrushMappingInheritMode;
/* BrushMapping->mapfunc */
typedef enum {
typedef enum eBrushMappingFunc {
BRUSH_MAPFUNC_NONE,
BRUSH_MAPFUNC_SAW,
BRUSH_MAPFUNC_TENT,
BRUSH_MAPFUNC_COS,
BRUSH_MAPFUNC_CUTOFF,
BRUSH_MAPFUNC_SQUARE,
} BrushMappingFunc;
BRUSH_MAPFUNC_SQUARE, /* square wave */
} eBrushMappingFunc;
// mapping types
typedef enum {
typedef enum eBrushMappingType {
BRUSH_MAPPING_PRESSURE = 0,
BRUSH_MAPPING_XTILT = 1,
BRUSH_MAPPING_YTILT = 2,
@ -118,7 +158,7 @@ typedef enum {
BRUSH_MAPPING_RANDOM = 5,
BRUSH_MAPPING_STROKE_T = 6,
BRUSH_MAPPING_MAX = 7 // see BrushChannel.mappings
} BrushMappingType;
} eBrushMappingType;
#ifndef __GNUC__
static_assert(offsetof(BrushChannel, type) - offsetof(BrushChannel, mappings) ==
@ -127,7 +167,7 @@ static_assert(offsetof(BrushChannel, type) - offsetof(BrushChannel, mappings) ==
#endif
// BrushChannel->flag
typedef enum {
typedef enum eBrushChannelFlag {
BRUSH_CHANNEL_INHERIT = 1 << 0,
BRUSH_CHANNEL_INHERIT_IF_UNSET = 1 << 1,
BRUSH_CHANNEL_NO_MAPPINGS = 1 << 2,
@ -139,7 +179,7 @@ typedef enum {
} eBrushChannelFlag;
// BrushChannelType->type
enum {
typedef enum eBrushChannelType {
BRUSH_CHANNEL_TYPE_FLOAT = 1 << 0,
BRUSH_CHANNEL_TYPE_INT = 1 << 1,
BRUSH_CHANNEL_TYPE_ENUM = 1 << 2,
@ -148,15 +188,15 @@ enum {
BRUSH_CHANNEL_TYPE_VEC3 = 1 << 5,
BRUSH_CHANNEL_TYPE_VEC4 = 1 << 6,
BRUSH_CHANNEL_TYPE_CURVE = 1 << 7
};
} eBrushChannelType;
/* clang-format off */
enum {
typedef enum eBrushChannelSubType {
BRUSH_CHANNEL_NONE,
BRUSH_CHANNEL_COLOR,
BRUSH_CHANNEL_FACTOR,
BRUSH_CHANNEL_PERCENT,
BRUSH_CHANNEL_PIXEL,
BRUSH_CHANNEL_ANGLE
};
} eBrushChannelSubType;
/* clang-format on */

View File

@ -689,7 +689,7 @@ void RNA_def_brush_mapping(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Factor", "Mapping factor");
prop = RNA_def_property(srna, "premultiply", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "premultiply");
RNA_def_property_float_sdna(prop, NULL, "premultiply_factor");
RNA_def_property_range(prop, -100000, 100000);
RNA_def_property_ui_range(prop, -100, 100, 0.01, 3);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);