diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d.py | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_editstrands.h | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_hair.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/editstrands.c | 18 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/hair.c | 124 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 1 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 4 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_strands.c | 16 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_sculpt_paint.c | 7 |
13 files changed, 141 insertions, 54 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 8056b14dc70..8a438cf9802 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -57,6 +57,7 @@ class VIEW3D_HT_header(Header): row.prop(toolsettings.hair_edit, "hair_draw_mode", text="", expand=True) if toolsettings.hair_edit.hair_draw_mode == 'FIBERS': row.prop(toolsettings.hair_edit, "hair_draw_size", text="Size") + row.prop(toolsettings.hair_edit, "hair_draw_subdivision", text="Subdivide") # Occlude geometry if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or diff --git a/source/blender/blenkernel/BKE_editstrands.h b/source/blender/blenkernel/BKE_editstrands.h index e5858160f65..1e0ed8cf3c4 100644 --- a/source/blender/blenkernel/BKE_editstrands.h +++ b/source/blender/blenkernel/BKE_editstrands.h @@ -84,12 +84,10 @@ void BKE_editstrands_free(struct BMEditStrands *es); bool BKE_editstrands_hair_ensure(struct BMEditStrands *es); void BKE_editstrands_hair_free(struct BMEditStrands *es); -int* BKE_editstrands_hair_get_fiber_lengths(struct BMEditStrands *es); -void BKE_editstrands_hair_get_texture_buffer_size(struct BMEditStrands *es, int *r_size, - int *r_strand_map_start, - int *r_strand_vertex_start, - int *r_fiber_start); -void BKE_editstrands_hair_get_texture_buffer(struct BMEditStrands *es, void *texbuffer); +int* BKE_editstrands_hair_get_fiber_lengths(struct BMEditStrands *es, int subdiv); +void BKE_editstrands_hair_get_texture_buffer_size(struct BMEditStrands *es, int subdiv, int *r_size, + int *r_strand_map_start, int *r_strand_vertex_start, int *r_fiber_start); +void BKE_editstrands_hair_get_texture_buffer(struct BMEditStrands *es, int subdiv, void *texbuffer); /* === Constraints === */ diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h index 5eafc14e66f..367741fb4fe 100644 --- a/source/blender/blenkernel/BKE_hair.h +++ b/source/blender/blenkernel/BKE_hair.h @@ -66,13 +66,13 @@ struct HairFiber* BKE_hair_fibers_create(const struct StrandsView *strands, unsigned int seed); int* BKE_hair_get_fiber_lengths(const struct HairFiber *fibers, int totfibers, - const struct StrandsView *strands); + const struct StrandsView *strands, int subdiv); -void BKE_hair_get_texture_buffer_size(const struct StrandsView *strands, int totfibers, +void BKE_hair_get_texture_buffer_size(const struct StrandsView *strands, int totfibers, int subdiv, int *r_size, int *r_strand_map_start, int *r_strand_vertex_start, int *r_fiber_start); void BKE_hair_get_texture_buffer(const struct StrandsView *strands, struct DerivedMesh *scalp, - const struct HairFiber *fibers, int totfibers, + const struct HairFiber *fibers, int totfibers, int subdiv, void *texbuffer); #endif diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c index 0fe286a5d3a..8cfc0bb606c 100644 --- a/source/blender/blenkernel/intern/editstrands.c +++ b/source/blender/blenkernel/intern/editstrands.c @@ -233,26 +233,24 @@ void BKE_editstrands_hair_free(BMEditStrands *es) } } -int* BKE_editstrands_hair_get_fiber_lengths(BMEditStrands *es) +int* BKE_editstrands_hair_get_fiber_lengths(BMEditStrands *es, int subdiv) { EditStrandsView strands = editstrands_get_view(es); - return BKE_hair_get_fiber_lengths(es->hair_fibers, es->hair_totfibers, &strands.base); + return BKE_hair_get_fiber_lengths(es->hair_fibers, es->hair_totfibers, &strands.base, subdiv); } -void BKE_editstrands_hair_get_texture_buffer_size(BMEditStrands *es, int *r_size, - int *r_strand_map_start, - int *r_strand_vertex_start, - int *r_fiber_start) +void BKE_editstrands_hair_get_texture_buffer_size(BMEditStrands *es, int subdiv, int *r_size, + int *r_strand_map_start, int *r_strand_vertex_start, int *r_fiber_start) { EditStrandsView strands = editstrands_get_view(es); - BKE_hair_get_texture_buffer_size(&strands.base, es->hair_totfibers, - r_size, r_strand_map_start, r_strand_vertex_start, r_fiber_start); + BKE_hair_get_texture_buffer_size(&strands.base, es->hair_totfibers, subdiv, r_size, + r_strand_map_start, r_strand_vertex_start, r_fiber_start); } -void BKE_editstrands_hair_get_texture_buffer(BMEditStrands *es, void *texbuffer) +void BKE_editstrands_hair_get_texture_buffer(BMEditStrands *es, int subdiv, void *texbuffer) { EditStrandsView strands = editstrands_get_view(es); - BKE_hair_get_texture_buffer(&strands.base, es->root_dm, es->hair_fibers, es->hair_totfibers, texbuffer); + BKE_hair_get_texture_buffer(&strands.base, es->root_dm, es->hair_fibers, es->hair_totfibers, subdiv, texbuffer); } /* === Constraints === */ diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 59677a25bc1..ee02d92c193 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -256,13 +256,26 @@ HairFiber* BKE_hair_fibers_create(const StrandsView *strands, return fibers; } -int* BKE_hair_get_fiber_lengths(const HairFiber *fibers, int totfibers, const StrandsView *strands) +static int hair_get_strand_subdiv_numverts(int numstrands, int numverts, int subdiv) +{ + return ((numverts - numstrands) << subdiv) + numstrands; +} + +static void hair_get_strand_subdiv_lengths(int *lengths, const int *orig_lengths, int num_strands, int subdiv) +{ + for (int i = 0; i < num_strands; ++i) { + lengths[i] = ((orig_lengths[i] - 1) << subdiv) + 1; + } +} + +int* BKE_hair_get_fiber_lengths(const HairFiber *fibers, int totfibers, const StrandsView *strands, int subdiv) { int *fiber_length = MEM_mallocN(sizeof(int) * totfibers, "fiber length"); const int num_strands = strands->get_num_strands(strands); - int *strand_length = MEM_mallocN(sizeof(int) * num_strands, "strand length"); - strands->get_strand_lengths(strands, strand_length); + int *lengths = MEM_mallocN(sizeof(int) * num_strands, "strand length"); + strands->get_strand_lengths(strands, lengths); + hair_get_strand_subdiv_lengths(lengths, lengths, num_strands, subdiv); for (int i = 0; i < totfibers; ++i) { @@ -276,14 +289,14 @@ int* BKE_hair_get_fiber_lengths(const HairFiber *fibers, int totfibers, const St } BLI_assert(si < num_strands); - fiblen += (float)strand_length[si] * sw; + fiblen += (float)lengths[si] * sw; } // use rounded number of segments fiber_length[i] = (int)(fiblen + 0.5f); } - MEM_freeN(strand_length); + MEM_freeN(lengths); return fiber_length; } @@ -328,8 +341,8 @@ static void hair_strand_transport_frame(const float co1[3], const float co2[3], copy_v3_v3(prev_nor, r_nor); } -static void hair_strand_calc_verts(const float (*positions)[3], int num_verts, float rootmat[3][3], - HairStrandVertexTextureBuffer *strand) +static void hair_strand_calc_vectors(const float (*positions)[3], int num_verts, float rootmat[3][3], + HairStrandVertexTextureBuffer *strand) { for (int i = 0; i < num_verts; ++i) { copy_v3_v3(strand[i].co, positions[i]); @@ -360,6 +373,50 @@ static void hair_strand_calc_verts(const float (*positions)[3], int num_verts, f } } +static int hair_strand_subdivide(float (*verts)[3], const float (*verts_orig)[3], int numverts_orig, int subdiv) +{ + { + /* Move vertex positions from the dense array to their initial configuration for subdivision. */ + const int step = (1 << subdiv); + const float (*src)[3] = verts_orig; + float (*dst)[3] = verts; + for (int i = 0; i < numverts_orig; ++i) { + copy_v3_v3(*dst, *src); + + ++src; + dst += step; + } + } + + /* Subdivide */ + for (int d = 0; d < subdiv; ++d) { + const int num_edges = (numverts_orig - 1) << d; + const int hstep = 1 << (subdiv - d - 1); + const int step = 1 << (subdiv - d); + + /* Calculate edge points */ + { + int index = 0; + for (int k = 0; k < num_edges; ++k, index += step) { + add_v3_v3v3(verts[index + hstep], verts[index], verts[index + step]); + mul_v3_fl(verts[index + hstep], 0.5f); + } + } + + /* Move original points */ + { + int index = step; + for (int k = 1; k < num_edges; ++k, index += step) { + add_v3_v3v3(verts[index], verts[index - hstep], verts[index + hstep]); + mul_v3_fl(verts[index], 0.5f); + } + } + } + + const int num_verts = ((numverts_orig - 1) << subdiv) + 1; + return num_verts; +} + static void hair_get_fiber_buffer(const HairFiber *fibers, int totfibers, DerivedMesh *scalp, HairFiberTextureBuffer *fiber_buf) { @@ -374,60 +431,85 @@ static void hair_get_fiber_buffer(const HairFiber *fibers, int totfibers, Derive } } -void BKE_hair_get_texture_buffer_size(const StrandsView *strands, int totfibers, +void BKE_hair_get_texture_buffer_size(const StrandsView *strands, int totfibers, int subdiv, int *r_size, int *r_strand_map_start, int *r_strand_vertex_start, int *r_fiber_start) { const int totstrands = strands->get_num_strands(strands); const int totverts = strands->get_num_verts(strands); + const int totverts_subdiv = hair_get_strand_subdiv_numverts(totstrands, totverts, subdiv); *r_strand_map_start = 0; *r_strand_vertex_start = *r_strand_map_start + totstrands * sizeof(HairStrandMapTextureBuffer); - *r_fiber_start = *r_strand_vertex_start + totverts * sizeof(HairStrandVertexTextureBuffer); + *r_fiber_start = *r_strand_vertex_start + totverts_subdiv * sizeof(HairStrandVertexTextureBuffer); *r_size = *r_fiber_start + totfibers * sizeof(HairFiberTextureBuffer); } void BKE_hair_get_texture_buffer(const StrandsView *strands, DerivedMesh *scalp, - const HairFiber *fibers, int totfibers, + const HairFiber *fibers, int totfibers, int subdiv, void *buffer) { const int totstrands = strands->get_num_strands(strands); - const int totverts = strands->get_num_verts(strands); + const int totverts_orig = strands->get_num_verts(strands); + const int totverts = hair_get_strand_subdiv_numverts(totstrands, totverts_orig, subdiv); const int strand_map_start = 0; const int strand_vertex_start = strand_map_start + totstrands * sizeof(HairStrandMapTextureBuffer); const int fiber_start = strand_vertex_start + totverts * sizeof(HairStrandVertexTextureBuffer); - int *lengths = MEM_mallocN(sizeof(int) * totstrands, "strand lengths"); + int *lengths_orig = MEM_mallocN(sizeof(int) * totstrands, "strand lengths"); + float (*positions_orig)[3] = MEM_mallocN(sizeof(float[3]) * totverts_orig, "strand vertex positions"); MeshSample *roots = MEM_mallocN(sizeof(MeshSample) * totstrands, "strand roots"); - float (*positions)[3] = MEM_mallocN(sizeof(float[3]) * totverts, "strand vertex positions"); - - strands->get_strand_lengths(strands, lengths); + strands->get_strand_lengths(strands, lengths_orig); + strands->get_strand_vertices(strands, positions_orig); strands->get_strand_roots(strands, roots); - strands->get_strand_vertices(strands, positions); + + int *lengths; + float (*positions)[3]; + if (subdiv > 0) { + lengths = MEM_mallocN(sizeof(int) * totstrands, "strand lengths subdivided"); + hair_get_strand_subdiv_lengths(lengths, lengths_orig, totstrands, subdiv); + + positions = MEM_mallocN(sizeof(float[3]) * totverts, "strand vertex positions subdivided"); + } + else { + lengths = lengths_orig; + positions = positions_orig; + } HairStrandMapTextureBuffer *smap = (HairStrandMapTextureBuffer*)((char*)buffer + strand_map_start); HairStrandVertexTextureBuffer *svert = (HairStrandVertexTextureBuffer*)((char*)buffer + strand_vertex_start); - unsigned int vertex_start = 0; + int vertex_orig_start = 0; + int vertex_start = 0; for (int i = 0; i < totstrands; ++i) { - const unsigned int len = lengths[i]; + const int len_orig = lengths_orig[i]; + const int len = lengths[i]; smap->vertex_start = vertex_start; smap->vertex_count = len; + if (subdiv > 0) { + hair_strand_subdivide(positions + vertex_start, positions_orig + vertex_orig_start, len_orig, subdiv); + } + { float pos[3]; float matrix[3][3]; BKE_mesh_sample_eval(scalp, &roots[i], pos, matrix[2], matrix[0]); cross_v3_v3v3(matrix[1], matrix[2], matrix[0]); - hair_strand_calc_verts(positions + vertex_start, len, matrix, svert); + hair_strand_calc_vectors(positions + vertex_start, len, matrix, svert); } + vertex_orig_start += len_orig; vertex_start += len; ++smap; svert += len; } - MEM_freeN(lengths); + MEM_freeN(lengths_orig); + MEM_freeN(positions_orig); MEM_freeN(roots); - MEM_freeN(positions); + if (subdiv > 0) { + MEM_freeN(lengths); + MEM_freeN(positions); + } hair_get_fiber_buffer(fibers, totfibers, scalp, (HairFiberTextureBuffer*)((char*)buffer + fiber_start)); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index e2fcef83abb..eada47fbb5f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -802,6 +802,7 @@ void BKE_scene_init(Scene *sce) sce->toolsettings->hair_edit.select_mode = HAIR_SELECT_VERTEX; sce->toolsettings->hair_edit.hair_draw_mode = HAIR_DRAW_FIBERS; sce->toolsettings->hair_edit.hair_draw_size = 2.5f; + sce->toolsettings->hair_edit.hair_draw_subdiv = 2; sce->physics_settings.gravity[0] = 0.0f; sce->physics_settings.gravity[1] = 0.0f; diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index a50b5b62e62..9772666d3ae 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -1136,7 +1136,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl use_fibers = true; copy_m4_m4(mat, ob->obmat); - hair_geom = DRW_cache_editstrands_get_hair_fibers(edit, true, &fiber_buffer); + hair_geom = DRW_cache_editstrands_get_hair_fibers(edit, true, tsettings->hair_draw_subdiv, &fiber_buffer); if (!edit->texture) { edit->texture = DRW_texture_create_2D(fiber_buffer->width, fiber_buffer->height, diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index f2772c47d67..a4753c9b55b 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -2610,8 +2610,8 @@ Gwn_Batch *DRW_cache_editstrands_get_wires(struct BMEditStrands *es) return DRW_editstrands_batch_cache_get_wires(es); } -Gwn_Batch *DRW_cache_editstrands_get_hair_fibers(struct BMEditStrands *es, bool use_ribbons, +Gwn_Batch *DRW_cache_editstrands_get_hair_fibers(struct BMEditStrands *es, bool use_ribbons, int subdiv, const struct DRWHairFiberTextureBuffer **r_buffer) { - return DRW_editstrands_batch_cache_get_hair_fibers(es, use_ribbons, r_buffer); + return DRW_editstrands_batch_cache_get_hair_fibers(es, use_ribbons, subdiv, r_buffer); } diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index ebf4dbafe2c..c536bd81084 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -164,7 +164,7 @@ struct Gwn_Batch *DRW_cache_editstrands_get_roots(struct BMEditStrands *es); struct Gwn_Batch *DRW_cache_editstrands_get_points(struct BMEditStrands *es); struct Gwn_Batch *DRW_cache_editstrands_get_wires(struct BMEditStrands *es); -struct Gwn_Batch *DRW_cache_editstrands_get_hair_fibers(struct BMEditStrands *es, bool use_ribbons, +struct Gwn_Batch *DRW_cache_editstrands_get_hair_fibers(struct BMEditStrands *es, bool use_ribbons, int subdiv, const struct DRWHairFiberTextureBuffer **r_buffer); #endif /* __DRAW_CACHE_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 9c1ad374de1..a6f4c486e2f 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -112,7 +112,7 @@ struct Gwn_Batch *DRW_editstrands_batch_cache_get_wires(struct BMEditStrands *es struct Gwn_Batch *DRW_editstrands_batch_cache_get_tips(struct BMEditStrands *es); struct Gwn_Batch *DRW_editstrands_batch_cache_get_roots(struct BMEditStrands *es); struct Gwn_Batch *DRW_editstrands_batch_cache_get_points(struct BMEditStrands *es); -struct Gwn_Batch *DRW_editstrands_batch_cache_get_hair_fibers(struct BMEditStrands *es, bool use_ribbons, +struct Gwn_Batch *DRW_editstrands_batch_cache_get_hair_fibers(struct BMEditStrands *es, bool use_ribbons, int subdiv, const struct DRWHairFiberTextureBuffer **r_buffer); #endif /* __DRAW_CACHE_IMPL_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl_strands.c b/source/blender/draw/intern/draw_cache_impl_strands.c index 2d57d7e20ac..d3e9406fcfb 100644 --- a/source/blender/draw/intern/draw_cache_impl_strands.c +++ b/source/blender/draw/intern/draw_cache_impl_strands.c @@ -364,12 +364,12 @@ Gwn_Batch *DRW_editstrands_batch_cache_get_points(BMEditStrands *es) return cache->points; } -static void editstrands_batch_cache_ensure_hair_fibers(BMEditStrands *es, StrandsBatchCache *cache, bool use_ribbons) +static void editstrands_batch_cache_ensure_hair_fibers(BMEditStrands *es, StrandsBatchCache *cache, bool use_ribbons, int subdiv) { GWN_VERTBUF_DISCARD_SAFE(cache->hair.verts); GWN_INDEXBUF_DISCARD_SAFE(cache->hair.segments); - int *fiber_lengths = BKE_editstrands_hair_get_fiber_lengths(es); + int *fiber_lengths = BKE_editstrands_hair_get_fiber_lengths(es, subdiv); int totpoint = 0; for (int i = 0; i < es->hair_totfibers; ++i) { totpoint += fiber_lengths[i]; @@ -446,7 +446,7 @@ static void editstrands_batch_cache_ensure_hair_fibers(BMEditStrands *es, Strand cache->hair.segments = GWN_indexbuf_build(&elb); } -static void editstrands_batch_cache_ensure_hair_fiber_texbuffer(BMEditStrands *es, StrandsBatchCache *cache, bool UNUSED(use_ribbons)) +static void editstrands_batch_cache_ensure_hair_fiber_texbuffer(BMEditStrands *es, StrandsBatchCache *cache, bool UNUSED(use_ribbons), int subdiv) { DRWHairFiberTextureBuffer *buffer = &cache->hair.texbuffer; static const int elemsize = 8; @@ -455,7 +455,7 @@ static void editstrands_batch_cache_ensure_hair_fiber_texbuffer(BMEditStrands *e // Offsets in bytes int b_size, b_strand_map_start, b_strand_vertex_start, b_fiber_start; - BKE_editstrands_hair_get_texture_buffer_size(es, &b_size, + BKE_editstrands_hair_get_texture_buffer_size(es, subdiv, &b_size, &b_strand_map_start, &b_strand_vertex_start, &b_fiber_start); // Pad for alignment b_size += align - b_size % align; @@ -465,7 +465,7 @@ static void editstrands_batch_cache_ensure_hair_fiber_texbuffer(BMEditStrands *e const int height = size / width; buffer->data = MEM_mallocN(b_size, "hair fiber texture buffer"); - BKE_editstrands_hair_get_texture_buffer(es, buffer->data); + BKE_editstrands_hair_get_texture_buffer(es, subdiv, buffer->data); buffer->width = width; buffer->height = height; @@ -474,7 +474,7 @@ static void editstrands_batch_cache_ensure_hair_fiber_texbuffer(BMEditStrands *e buffer->fiber_start = b_fiber_start / elemsize; } -Gwn_Batch *DRW_editstrands_batch_cache_get_hair_fibers(BMEditStrands *es, bool use_ribbons, +Gwn_Batch *DRW_editstrands_batch_cache_get_hair_fibers(BMEditStrands *es, bool use_ribbons, int subdiv, const DRWHairFiberTextureBuffer **r_buffer) { StrandsBatchCache *cache = editstrands_batch_cache_get(es); @@ -484,13 +484,13 @@ Gwn_Batch *DRW_editstrands_batch_cache_get_hair_fibers(BMEditStrands *es, bool u } if (cache->hair.fibers == NULL) { - editstrands_batch_cache_ensure_hair_fibers(es, cache, use_ribbons); + editstrands_batch_cache_ensure_hair_fibers(es, cache, use_ribbons, subdiv); Gwn_PrimType prim_type = use_ribbons ? GWN_PRIM_TRIS : GWN_PRIM_LINES; cache->hair.fibers = GWN_batch_create(prim_type, cache->hair.verts, cache->hair.segments); cache->hair.use_ribbons = use_ribbons; - editstrands_batch_cache_ensure_hair_fiber_texbuffer(es, cache, use_ribbons); + editstrands_batch_cache_ensure_hair_fiber_texbuffer(es, cache, use_ribbons, subdiv); } if (r_buffer) { diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b73c1aa63a6..83747527432 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1145,7 +1145,7 @@ typedef struct HairEditSettings { short select_mode; short hair_draw_mode; float hair_draw_size; - int pad; + int hair_draw_subdiv; struct Brush *brush; struct Object *shape_object; diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 83c47be3496..b72e88cd79f 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -1206,6 +1206,13 @@ static void rna_def_hair_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Hair Draw Size", "Width of hair fibers in pixels"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_HairEdit_update"); + prop = RNA_def_property(srna, "hair_draw_subdivision", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "hair_draw_subdiv"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_range(prop, 0, 5, 1, -1); + RNA_def_property_ui_text(prop, "Hair Draw Subdivision", "Subdivide hair fibers"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_HairEdit_update"); + prop = RNA_def_property(srna, "shape_object", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Shape Object", "Outer shape to use for tools"); |