Cleanup: Decrease variable scope in UV sculpt
This commit is contained in:
@@ -161,14 +161,13 @@ static void HC_relaxation_iteration_uv(UvSculptData *sculptdata,
|
||||
float radius,
|
||||
float aspectRatio)
|
||||
{
|
||||
Temp_UVData *tmp_uvdata;
|
||||
float diff[2];
|
||||
int i;
|
||||
float radius_root = sqrtf(radius);
|
||||
Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
|
||||
|
||||
tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData),
|
||||
"Temporal data");
|
||||
Temp_UVData *tmp_uvdata = (Temp_UVData *)MEM_callocN(
|
||||
sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data");
|
||||
|
||||
/* counting neighbors */
|
||||
for (i = 0; i < sculptdata->totalUvEdges; i++) {
|
||||
@@ -248,14 +247,13 @@ static void laplacian_relaxation_iteration_uv(UvSculptData *sculptdata,
|
||||
float radius,
|
||||
float aspectRatio)
|
||||
{
|
||||
Temp_UVData *tmp_uvdata;
|
||||
float diff[2];
|
||||
int i;
|
||||
float radius_root = sqrtf(radius);
|
||||
Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
|
||||
|
||||
tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData),
|
||||
"Temporal data");
|
||||
Temp_UVData *tmp_uvdata = (Temp_UVData *)MEM_callocN(
|
||||
sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data");
|
||||
|
||||
/* counting neighbors */
|
||||
for (i = 0; i < sculptdata->totalUvEdges; i++) {
|
||||
@@ -462,108 +460,107 @@ static void uv_sculpt_stroke_apply(bContext *C,
|
||||
const wmEvent *event,
|
||||
Object *obedit)
|
||||
{
|
||||
float co[2], radius, radius_root;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
uint tool;
|
||||
UvSculptData *sculptdata = (UvSculptData *)op->customdata;
|
||||
SpaceImage *sima;
|
||||
int invert;
|
||||
int width, height;
|
||||
float aspectRatio;
|
||||
float alpha, zoomx, zoomy;
|
||||
Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
|
||||
ToolSettings *toolsettings = CTX_data_tool_settings(C);
|
||||
tool = sculptdata->tool;
|
||||
invert = sculptdata->invert ? -1 : 1;
|
||||
alpha = BKE_brush_alpha_get(scene, brush);
|
||||
eBrushUVSculptTool tool = eBrushUVSculptTool(sculptdata->tool);
|
||||
int invert = sculptdata->invert ? -1 : 1;
|
||||
float alpha = BKE_brush_alpha_get(scene, brush);
|
||||
|
||||
float co[2];
|
||||
UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
|
||||
|
||||
sima = CTX_wm_space_image(C);
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
|
||||
int width, height;
|
||||
ED_space_image_get_size(sima, &width, &height);
|
||||
|
||||
float zoomx, zoomy;
|
||||
ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
|
||||
|
||||
radius = BKE_brush_size_get(scene, brush) / (width * zoomx);
|
||||
aspectRatio = width / float(height);
|
||||
float radius = BKE_brush_size_get(scene, brush) / (width * zoomx);
|
||||
float aspectRatio = width / float(height);
|
||||
|
||||
/* We will compare squares to save some computation */
|
||||
radius = radius * radius;
|
||||
radius_root = sqrtf(radius);
|
||||
float radius_root = sqrtf(radius);
|
||||
|
||||
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_PROP_FLOAT2);
|
||||
|
||||
switch (tool) {
|
||||
case UV_SCULPT_TOOL_PINCH: {
|
||||
int i;
|
||||
alpha *= invert;
|
||||
for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
|
||||
if (sculptdata->uv[i].is_locked) {
|
||||
continue;
|
||||
}
|
||||
int i;
|
||||
alpha *= invert;
|
||||
for (i = 0; i < sculptdata->totalUniqueUvs; i++) {
|
||||
if (sculptdata->uv[i].is_locked) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float diff[2];
|
||||
sub_v2_v2v2(diff, sculptdata->uv[i].uv, co);
|
||||
diff[1] /= aspectRatio;
|
||||
float dist = dot_v2v2(diff, diff);
|
||||
if (dist <= radius) {
|
||||
UvElement *element;
|
||||
float strength;
|
||||
strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
|
||||
normalize_v2(diff);
|
||||
float diff[2];
|
||||
sub_v2_v2v2(diff, sculptdata->uv[i].uv, co);
|
||||
diff[1] /= aspectRatio;
|
||||
float dist = dot_v2v2(diff, diff);
|
||||
if (dist <= radius) {
|
||||
UvElement *element;
|
||||
float strength;
|
||||
strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
|
||||
normalize_v2(diff);
|
||||
|
||||
sculptdata->uv[i].uv[0] -= strength * diff[0] * 0.001f;
|
||||
sculptdata->uv[i].uv[1] -= strength * diff[1] * 0.001f;
|
||||
sculptdata->uv[i].uv[0] -= strength * diff[0] * 0.001f;
|
||||
sculptdata->uv[i].uv[1] -= strength * diff[1] * 0.001f;
|
||||
|
||||
apply_sculpt_data_constraints(sculptdata, sculptdata->uv[i].uv);
|
||||
apply_sculpt_data_constraints(sculptdata, sculptdata->uv[i].uv);
|
||||
|
||||
for (element = sculptdata->uv[i].element; element; element = element->next) {
|
||||
if (element->separate && element != sculptdata->uv[i].element) {
|
||||
break;
|
||||
for (element = sculptdata->uv[i].element; element; element = element->next) {
|
||||
if (element->separate && element != sculptdata->uv[i].element) {
|
||||
break;
|
||||
}
|
||||
float(*luv)[2] = BM_ELEM_CD_GET_FLOAT2_P(element->l, cd_loop_uv_offset);
|
||||
copy_v2_v2(*luv, sculptdata->uv[i].uv);
|
||||
}
|
||||
float(*luv)[2] = BM_ELEM_CD_GET_FLOAT2_P(element->l, cd_loop_uv_offset);
|
||||
copy_v2_v2(*luv, sculptdata->uv[i].uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UV_SCULPT_TOOL_RELAX: {
|
||||
relaxation_iteration_uv(sculptdata,
|
||||
cd_loop_uv_offset,
|
||||
co,
|
||||
alpha,
|
||||
radius,
|
||||
aspectRatio,
|
||||
toolsettings->uv_relax_method);
|
||||
relaxation_iteration_uv(sculptdata,
|
||||
cd_loop_uv_offset,
|
||||
co,
|
||||
alpha,
|
||||
radius,
|
||||
aspectRatio,
|
||||
toolsettings->uv_relax_method);
|
||||
break;
|
||||
}
|
||||
case UV_SCULPT_TOOL_GRAB: {
|
||||
int i;
|
||||
float diff[2];
|
||||
sub_v2_v2v2(diff, co, sculptdata->initial_stroke->init_coord);
|
||||
int i;
|
||||
float diff[2];
|
||||
sub_v2_v2v2(diff, co, sculptdata->initial_stroke->init_coord);
|
||||
|
||||
for (i = 0; i < sculptdata->initial_stroke->totalInitialSelected; i++) {
|
||||
UvElement *element;
|
||||
int uvindex = sculptdata->initial_stroke->initialSelection[i].uv;
|
||||
float strength = sculptdata->initial_stroke->initialSelection[i].strength;
|
||||
sculptdata->uv[uvindex].uv[0] =
|
||||
sculptdata->initial_stroke->initialSelection[i].initial_uv[0] + strength * diff[0];
|
||||
sculptdata->uv[uvindex].uv[1] =
|
||||
sculptdata->initial_stroke->initialSelection[i].initial_uv[1] + strength * diff[1];
|
||||
for (i = 0; i < sculptdata->initial_stroke->totalInitialSelected; i++) {
|
||||
UvElement *element;
|
||||
int uvindex = sculptdata->initial_stroke->initialSelection[i].uv;
|
||||
float strength = sculptdata->initial_stroke->initialSelection[i].strength;
|
||||
sculptdata->uv[uvindex].uv[0] =
|
||||
sculptdata->initial_stroke->initialSelection[i].initial_uv[0] + strength * diff[0];
|
||||
sculptdata->uv[uvindex].uv[1] =
|
||||
sculptdata->initial_stroke->initialSelection[i].initial_uv[1] + strength * diff[1];
|
||||
|
||||
apply_sculpt_data_constraints(sculptdata, sculptdata->uv[uvindex].uv);
|
||||
apply_sculpt_data_constraints(sculptdata, sculptdata->uv[uvindex].uv);
|
||||
|
||||
for (element = sculptdata->uv[uvindex].element; element; element = element->next) {
|
||||
if (element->separate && element != sculptdata->uv[uvindex].element) {
|
||||
break;
|
||||
for (element = sculptdata->uv[uvindex].element; element; element = element->next) {
|
||||
if (element->separate && element != sculptdata->uv[uvindex].element) {
|
||||
break;
|
||||
}
|
||||
float(*luv)[2] = BM_ELEM_CD_GET_FLOAT2_P(element->l, cd_loop_uv_offset);
|
||||
copy_v2_v2(*luv, sculptdata->uv[uvindex].uv);
|
||||
}
|
||||
float(*luv)[2] = BM_ELEM_CD_GET_FLOAT2_P(element->l, cd_loop_uv_offset);
|
||||
copy_v2_v2(*luv, sculptdata->uv[uvindex].uv);
|
||||
}
|
||||
}
|
||||
if (sima->flag & SI_LIVE_UNWRAP) {
|
||||
ED_uvedit_live_unwrap_re_solve();
|
||||
if (sima->flag & SI_LIVE_UNWRAP) {
|
||||
ED_uvedit_live_unwrap_re_solve();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -648,255 +645,251 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
|
||||
BKE_curvemapping_init(brush->curve);
|
||||
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
float co[2];
|
||||
BMFace *efa;
|
||||
float(*luv)[2];
|
||||
BMLoop *l;
|
||||
BMIter iter, liter;
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
float co[2];
|
||||
BMFace *efa;
|
||||
float(*luv)[2];
|
||||
BMLoop *l;
|
||||
BMIter iter, liter;
|
||||
|
||||
UvEdge *edges;
|
||||
GHash *edgeHash;
|
||||
GHashIterator gh_iter;
|
||||
GHashIterator gh_iter;
|
||||
|
||||
bool do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS);
|
||||
int island_index = 0;
|
||||
data->tool = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_SMOOTH) ?
|
||||
UV_SCULPT_TOOL_RELAX :
|
||||
eBrushUVSculptTool(brush->uv_sculpt_tool);
|
||||
data->invert = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT) ? 1 : 0;
|
||||
bool do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS);
|
||||
int island_index = 0;
|
||||
data->tool = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_SMOOTH) ?
|
||||
UV_SCULPT_TOOL_RELAX :
|
||||
eBrushUVSculptTool(brush->uv_sculpt_tool);
|
||||
data->invert = (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT) ? 1 : 0;
|
||||
|
||||
data->uvsculpt = &ts->uvsculpt->paint;
|
||||
data->uvsculpt = &ts->uvsculpt->paint;
|
||||
|
||||
/* Winding was added to island detection in 5197aa04c6bd
|
||||
* However the sculpt tools can flip faces, potentially creating orphaned islands.
|
||||
* See #100132 */
|
||||
const bool use_winding = false;
|
||||
const bool use_seams = true;
|
||||
data->elementMap = BM_uv_element_map_create(
|
||||
bm, scene, false, use_winding, use_seams, do_island_optimization);
|
||||
/* Winding was added to island detection in 5197aa04c6bd
|
||||
* However the sculpt tools can flip faces, potentially creating orphaned islands.
|
||||
* See #100132 */
|
||||
const bool use_winding = false;
|
||||
const bool use_seams = true;
|
||||
data->elementMap = BM_uv_element_map_create(
|
||||
bm, scene, false, use_winding, use_seams, do_island_optimization);
|
||||
|
||||
if (!data->elementMap) {
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
return nullptr;
|
||||
if (!data->elementMap) {
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Mouse coordinates, useful for some functions like grab and sculpt all islands */
|
||||
UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
|
||||
|
||||
/* We need to find the active island here. */
|
||||
if (do_island_optimization) {
|
||||
UvNearestHit hit = uv_nearest_hit_init_max(®ion->v2d);
|
||||
uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit);
|
||||
|
||||
UvElement *element = BM_uv_element_get(data->elementMap, hit.l);
|
||||
if (element) {
|
||||
island_index = element->island;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mouse coordinates, useful for some functions like grab and sculpt all islands */
|
||||
UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
|
||||
/* Count 'unique' UVs */
|
||||
int unique_uvs = data->elementMap->total_unique_uvs;
|
||||
if (do_island_optimization) {
|
||||
unique_uvs = data->elementMap->island_total_unique_uvs[island_index];
|
||||
}
|
||||
|
||||
/* We need to find the active island here. */
|
||||
if (do_island_optimization) {
|
||||
UvNearestHit hit = uv_nearest_hit_init_max(®ion->v2d);
|
||||
uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit);
|
||||
|
||||
UvElement *element = BM_uv_element_get(data->elementMap, hit.l);
|
||||
if (element) {
|
||||
island_index = element->island;
|
||||
}
|
||||
/* Allocate the unique uv buffers */
|
||||
data->uv = MEM_cnew_array<UvAdjacencyElement>(unique_uvs, __func__);
|
||||
/* Holds, for each UvElement in elementMap, an index of its unique UV. */
|
||||
int *uniqueUv = static_cast<int *>(
|
||||
MEM_mallocN(sizeof(*uniqueUv) * data->elementMap->total_uvs, __func__));
|
||||
GHash *edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "uv_brush_edge_hash");
|
||||
/* we have at most totalUVs edges */
|
||||
UvEdge *edges = MEM_cnew_array<UvEdge>(data->elementMap->total_uvs, __func__);
|
||||
if (!data->uv || !uniqueUv || !edgeHash || !edges) {
|
||||
MEM_SAFE_FREE(edges);
|
||||
MEM_SAFE_FREE(uniqueUv);
|
||||
if (edgeHash) {
|
||||
BLI_ghash_free(edgeHash, nullptr, nullptr);
|
||||
}
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Count 'unique' UVs */
|
||||
int unique_uvs = data->elementMap->total_unique_uvs;
|
||||
if (do_island_optimization) {
|
||||
unique_uvs = data->elementMap->island_total_unique_uvs[island_index];
|
||||
}
|
||||
data->totalUniqueUvs = unique_uvs;
|
||||
/* Index for the UvElements. */
|
||||
int counter = -1;
|
||||
|
||||
/* Allocate the unique uv buffers */
|
||||
data->uv = MEM_cnew_array<UvAdjacencyElement>(unique_uvs, __func__);
|
||||
/* Holds, for each UvElement in elementMap, an index of its unique UV. */
|
||||
int *uniqueUv = static_cast<int *>(
|
||||
MEM_mallocN(sizeof(*uniqueUv) * data->elementMap->total_uvs, __func__));
|
||||
edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "uv_brush_edge_hash");
|
||||
/* we have at most totalUVs edges */
|
||||
edges = MEM_cnew_array<UvEdge>(data->elementMap->total_uvs, __func__);
|
||||
if (!data->uv || !uniqueUv || !edgeHash || !edges) {
|
||||
MEM_SAFE_FREE(edges);
|
||||
MEM_SAFE_FREE(uniqueUv);
|
||||
if (edgeHash) {
|
||||
BLI_ghash_free(edgeHash, nullptr, nullptr);
|
||||
}
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
data->totalUniqueUvs = unique_uvs;
|
||||
/* Index for the UvElements. */
|
||||
int counter = -1;
|
||||
|
||||
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
|
||||
/* initialize the unique UVs */
|
||||
for (int i = 0; i < bm->totvert; i++) {
|
||||
UvElement *element = data->elementMap->vertex[i];
|
||||
for (; element; element = element->next) {
|
||||
if (element->separate) {
|
||||
if (do_island_optimization && (element->island != island_index)) {
|
||||
/* skip this uv if not on the active island */
|
||||
for (; element->next && !(element->next->separate); element = element->next) {
|
||||
/* pass */
|
||||
}
|
||||
continue;
|
||||
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
|
||||
/* initialize the unique UVs */
|
||||
for (int i = 0; i < bm->totvert; i++) {
|
||||
UvElement *element = data->elementMap->vertex[i];
|
||||
for (; element; element = element->next) {
|
||||
if (element->separate) {
|
||||
if (do_island_optimization && (element->island != island_index)) {
|
||||
/* skip this uv if not on the active island */
|
||||
for (; element->next && !(element->next->separate); element = element->next) {
|
||||
/* pass */
|
||||
}
|
||||
|
||||
luv = BM_ELEM_CD_GET_FLOAT2_P(element->l, offsets.uv);
|
||||
|
||||
counter++;
|
||||
data->uv[counter].element = element;
|
||||
data->uv[counter].uv = *luv;
|
||||
if (data->tool != UV_SCULPT_TOOL_GRAB) {
|
||||
if (BM_ELEM_CD_GET_BOOL(element->l, offsets.pin)) {
|
||||
data->uv[counter].is_locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Pointer arithmetic to the rescue, as always :). */
|
||||
uniqueUv[element - data->elementMap->storage] = counter;
|
||||
}
|
||||
}
|
||||
BLI_assert(counter + 1 == unique_uvs);
|
||||
|
||||
/* Now, on to generate our uv connectivity data */
|
||||
counter = 0;
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||
int itmp1 = uv_element_offset_from_face_get(
|
||||
data->elementMap, l, island_index, do_island_optimization);
|
||||
int itmp2 = uv_element_offset_from_face_get(
|
||||
data->elementMap, l->next, island_index, do_island_optimization);
|
||||
|
||||
/* Skip edge if not found(unlikely) or not on valid island */
|
||||
if (itmp1 == -1 || itmp2 == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int offset1 = uniqueUv[itmp1];
|
||||
int offset2 = uniqueUv[itmp2];
|
||||
luv = BM_ELEM_CD_GET_FLOAT2_P(element->l, offsets.uv);
|
||||
|
||||
/* Using an order policy, sort UVs according to address space.
|
||||
* This avoids having two different UvEdges with the same UVs on different positions. */
|
||||
if (offset1 < offset2) {
|
||||
edges[counter].uv1 = offset1;
|
||||
edges[counter].uv2 = offset2;
|
||||
}
|
||||
else {
|
||||
edges[counter].uv1 = offset2;
|
||||
edges[counter].uv2 = offset1;
|
||||
}
|
||||
UvEdge *prev_edge = static_cast<UvEdge *>(BLI_ghash_lookup(edgeHash, &edges[counter]));
|
||||
if (prev_edge) {
|
||||
prev_edge->is_interior = true;
|
||||
edges[counter].is_interior = true;
|
||||
}
|
||||
else {
|
||||
BLI_ghash_insert(edgeHash, &edges[counter], &edges[counter]);
|
||||
counter++;
|
||||
data->uv[counter].element = element;
|
||||
data->uv[counter].uv = *luv;
|
||||
if (data->tool != UV_SCULPT_TOOL_GRAB) {
|
||||
if (BM_ELEM_CD_GET_BOOL(element->l, offsets.pin)) {
|
||||
data->uv[counter].is_locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Pointer arithmetic to the rescue, as always :). */
|
||||
uniqueUv[element - data->elementMap->storage] = counter;
|
||||
}
|
||||
}
|
||||
BLI_assert(counter + 1 == unique_uvs);
|
||||
|
||||
/* Now, on to generate our uv connectivity data */
|
||||
counter = 0;
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||
int itmp1 = uv_element_offset_from_face_get(
|
||||
data->elementMap, l, island_index, do_island_optimization);
|
||||
int itmp2 = uv_element_offset_from_face_get(
|
||||
data->elementMap, l->next, island_index, do_island_optimization);
|
||||
|
||||
/* Skip edge if not found(unlikely) or not on valid island */
|
||||
if (itmp1 == -1 || itmp2 == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int offset1 = uniqueUv[itmp1];
|
||||
int offset2 = uniqueUv[itmp2];
|
||||
|
||||
/* Using an order policy, sort UVs according to address space.
|
||||
* This avoids having two different UvEdges with the same UVs on different positions. */
|
||||
if (offset1 < offset2) {
|
||||
edges[counter].uv1 = offset1;
|
||||
edges[counter].uv2 = offset2;
|
||||
}
|
||||
else {
|
||||
edges[counter].uv1 = offset2;
|
||||
edges[counter].uv2 = offset1;
|
||||
}
|
||||
UvEdge *prev_edge = static_cast<UvEdge *>(BLI_ghash_lookup(edgeHash, &edges[counter]));
|
||||
if (prev_edge) {
|
||||
prev_edge->is_interior = true;
|
||||
edges[counter].is_interior = true;
|
||||
}
|
||||
else {
|
||||
BLI_ghash_insert(edgeHash, &edges[counter], &edges[counter]);
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(uniqueUv);
|
||||
|
||||
/* Allocate connectivity data, we allocate edges once */
|
||||
data->uvedges = MEM_cnew_array<UvEdge>(BLI_ghash_len(edgeHash), __func__);
|
||||
if (!data->uvedges) {
|
||||
BLI_ghash_free(edgeHash, nullptr, nullptr);
|
||||
MEM_SAFE_FREE(edges);
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* fill the edges with data */
|
||||
{
|
||||
int i = 0;
|
||||
GHASH_ITER (gh_iter, edgeHash) {
|
||||
data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
|
||||
}
|
||||
data->totalUvEdges = BLI_ghash_len(edgeHash);
|
||||
}
|
||||
|
||||
/* cleanup temporary stuff */
|
||||
BLI_ghash_free(edgeHash, nullptr, nullptr);
|
||||
MEM_SAFE_FREE(edges);
|
||||
|
||||
/* transfer boundary edge property to UVs */
|
||||
for (int i = 0; i < data->totalUvEdges; i++) {
|
||||
if (!data->uvedges[i].is_interior) {
|
||||
data->uv[data->uvedges[i].uv1].is_boundary = true;
|
||||
data->uv[data->uvedges[i].uv2].is_boundary = true;
|
||||
if (ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS) {
|
||||
data->uv[data->uvedges[i].uv1].is_locked = true;
|
||||
data->uv[data->uvedges[i].uv2].is_locked = true;
|
||||
}
|
||||
set_element_flag(data->uv[data->uvedges[i].uv1].element, MARK_BOUNDARY);
|
||||
set_element_flag(data->uv[data->uvedges[i].uv2].element, MARK_BOUNDARY);
|
||||
}
|
||||
}
|
||||
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
data->constrain_to_bounds = (sima->flag & SI_CLIP_UV);
|
||||
BKE_image_find_nearest_tile_with_offset(sima->image, co, data->uv_base_offset);
|
||||
|
||||
/* Allocate initial selection for grab tool */
|
||||
if (data->tool == UV_SCULPT_TOOL_GRAB) {
|
||||
UvSculptData *sculptdata = (UvSculptData *)op->customdata;
|
||||
Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
|
||||
|
||||
float alpha = BKE_brush_alpha_get(scene, brush);
|
||||
|
||||
float radius = BKE_brush_size_get(scene, brush);
|
||||
int width, height;
|
||||
ED_space_image_get_size(sima, &width, &height);
|
||||
float zoomx, zoomy;
|
||||
ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
|
||||
|
||||
float aspectRatio = width / float(height);
|
||||
radius /= (width * zoomx);
|
||||
radius = radius * radius;
|
||||
float radius_root = sqrtf(radius);
|
||||
|
||||
/* Allocate selection stack */
|
||||
data->initial_stroke = static_cast<UVInitialStroke *>(
|
||||
MEM_mallocN(sizeof(*data->initial_stroke), __func__));
|
||||
if (!data->initial_stroke) {
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
}
|
||||
data->initial_stroke->initialSelection = static_cast<UVInitialStrokeElement *>(MEM_mallocN(
|
||||
sizeof(*data->initial_stroke->initialSelection) * data->totalUniqueUvs, __func__));
|
||||
if (!data->initial_stroke->initialSelection) {
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
}
|
||||
|
||||
copy_v2_v2(data->initial_stroke->init_coord, co);
|
||||
|
||||
counter = 0;
|
||||
for (int i = 0; i < data->totalUniqueUvs; i++) {
|
||||
if (data->uv[i].is_locked) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float diff[2];
|
||||
sub_v2_v2v2(diff, data->uv[i].uv, co);
|
||||
diff[1] /= aspectRatio;
|
||||
float dist = dot_v2v2(diff, diff);
|
||||
if (dist <= radius) {
|
||||
float strength;
|
||||
strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
|
||||
|
||||
data->initial_stroke->initialSelection[counter].uv = i;
|
||||
data->initial_stroke->initialSelection[counter].strength = strength;
|
||||
copy_v2_v2(data->initial_stroke->initialSelection[counter].initial_uv, data->uv[i].uv);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(uniqueUv);
|
||||
|
||||
/* Allocate connectivity data, we allocate edges once */
|
||||
data->uvedges = MEM_cnew_array<UvEdge>(BLI_ghash_len(edgeHash), __func__);
|
||||
if (!data->uvedges) {
|
||||
BLI_ghash_free(edgeHash, nullptr, nullptr);
|
||||
MEM_SAFE_FREE(edges);
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
return nullptr;
|
||||
data->initial_stroke->totalInitialSelected = counter;
|
||||
if (sima->flag & SI_LIVE_UNWRAP) {
|
||||
ED_uvedit_live_unwrap_begin(scene, obedit);
|
||||
}
|
||||
|
||||
/* fill the edges with data */
|
||||
{
|
||||
int i = 0;
|
||||
GHASH_ITER (gh_iter, edgeHash) {
|
||||
data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
|
||||
}
|
||||
data->totalUvEdges = BLI_ghash_len(edgeHash);
|
||||
}
|
||||
|
||||
/* cleanup temporary stuff */
|
||||
BLI_ghash_free(edgeHash, nullptr, nullptr);
|
||||
MEM_SAFE_FREE(edges);
|
||||
|
||||
/* transfer boundary edge property to UVs */
|
||||
for (int i = 0; i < data->totalUvEdges; i++) {
|
||||
if (!data->uvedges[i].is_interior) {
|
||||
data->uv[data->uvedges[i].uv1].is_boundary = true;
|
||||
data->uv[data->uvedges[i].uv2].is_boundary = true;
|
||||
if (ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS) {
|
||||
data->uv[data->uvedges[i].uv1].is_locked = true;
|
||||
data->uv[data->uvedges[i].uv2].is_locked = true;
|
||||
}
|
||||
set_element_flag(data->uv[data->uvedges[i].uv1].element, MARK_BOUNDARY);
|
||||
set_element_flag(data->uv[data->uvedges[i].uv2].element, MARK_BOUNDARY);
|
||||
}
|
||||
}
|
||||
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
data->constrain_to_bounds = (sima->flag & SI_CLIP_UV);
|
||||
BKE_image_find_nearest_tile_with_offset(sima->image, co, data->uv_base_offset);
|
||||
|
||||
/* Allocate initial selection for grab tool */
|
||||
if (data->tool == UV_SCULPT_TOOL_GRAB) {
|
||||
float radius, radius_root;
|
||||
UvSculptData *sculptdata = (UvSculptData *)op->customdata;
|
||||
int width, height;
|
||||
float aspectRatio;
|
||||
float alpha, zoomx, zoomy;
|
||||
Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
|
||||
|
||||
alpha = BKE_brush_alpha_get(scene, brush);
|
||||
|
||||
radius = BKE_brush_size_get(scene, brush);
|
||||
ED_space_image_get_size(sima, &width, &height);
|
||||
ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
|
||||
|
||||
aspectRatio = width / float(height);
|
||||
radius /= (width * zoomx);
|
||||
radius = radius * radius;
|
||||
radius_root = sqrtf(radius);
|
||||
|
||||
/* Allocate selection stack */
|
||||
data->initial_stroke = static_cast<UVInitialStroke *>(
|
||||
MEM_mallocN(sizeof(*data->initial_stroke), __func__));
|
||||
if (!data->initial_stroke) {
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
}
|
||||
data->initial_stroke->initialSelection = static_cast<UVInitialStrokeElement *>(MEM_mallocN(
|
||||
sizeof(*data->initial_stroke->initialSelection) * data->totalUniqueUvs, __func__));
|
||||
if (!data->initial_stroke->initialSelection) {
|
||||
uv_sculpt_stroke_exit(C, op);
|
||||
}
|
||||
|
||||
copy_v2_v2(data->initial_stroke->init_coord, co);
|
||||
|
||||
counter = 0;
|
||||
for (int i = 0; i < data->totalUniqueUvs; i++) {
|
||||
if (data->uv[i].is_locked) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float diff[2];
|
||||
sub_v2_v2v2(diff, data->uv[i].uv, co);
|
||||
diff[1] /= aspectRatio;
|
||||
float dist = dot_v2v2(diff, diff);
|
||||
if (dist <= radius) {
|
||||
float strength;
|
||||
strength = alpha * BKE_brush_curve_strength_clamped(brush, sqrtf(dist), radius_root);
|
||||
|
||||
data->initial_stroke->initialSelection[counter].uv = i;
|
||||
data->initial_stroke->initialSelection[counter].strength = strength;
|
||||
copy_v2_v2(data->initial_stroke->initialSelection[counter].initial_uv, data->uv[i].uv);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
data->initial_stroke->totalInitialSelected = counter;
|
||||
if (sima->flag & SI_LIVE_UNWRAP) {
|
||||
ED_uvedit_live_unwrap_begin(scene, obedit);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<UvSculptData *>(op->customdata);
|
||||
|
||||
Reference in New Issue
Block a user