Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2020-09-04 18:56:56 +0300
committerHans Goudey <h.goudey@me.com>2020-09-04 18:56:56 +0300
commit417695e4a8bff7927a936797ca01c6461ce0eaf7 (patch)
tree1d7a1ff4b95d09bbb6319f4378520e43f170e6ac /source/blender
parentce67a9d39f0feef89bbb9f7835b52884921e66ed (diff)
Curve Profile: Miscellaneous cleanup
- Declare variables where they are initialized - Use consistent variable and static function names - Use helper functions more for common operations - Remove use of BezTriple struct, use CurveProfilePoint instead - Apply small simplifications to code in some situations
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_curveprofile.h4
-rw-r--r--source/blender/blenkernel/intern/curveprofile.c473
-rw-r--r--source/blender/editors/interface/interface_handlers.c7
3 files changed, 199 insertions, 285 deletions
diff --git a/source/blender/blenkernel/BKE_curveprofile.h b/source/blender/blenkernel/BKE_curveprofile.h
index 9c72a866fa9..08d3da7123c 100644
--- a/source/blender/blenkernel/BKE_curveprofile.h
+++ b/source/blender/blenkernel/BKE_curveprofile.h
@@ -23,6 +23,8 @@
* \ingroup bke
*/
+#include "DNA_curveprofile_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -34,7 +36,7 @@ struct CurveProfilePoint;
void BKE_curveprofile_set_defaults(struct CurveProfile *profile);
-struct CurveProfile *BKE_curveprofile_add(int preset);
+struct CurveProfile *BKE_curveprofile_add(eCurveProfilePresets preset);
void BKE_curveprofile_free_data(struct CurveProfile *profile);
diff --git a/source/blender/blenkernel/intern/curveprofile.c b/source/blender/blenkernel/intern/curveprofile.c
index 068f8845e64..f52619f8c3a 100644
--- a/source/blender/blenkernel/intern/curveprofile.c
+++ b/source/blender/blenkernel/intern/curveprofile.c
@@ -143,6 +143,14 @@ bool BKE_curveprofile_move_point(struct CurveProfile *profile,
const bool snap,
const float delta[2])
{
+ /* Don't move the final point. */
+ if (point == &profile->path[profile->path_len - 1]) {
+ return false;
+ }
+ /* Don't move the first point. */
+ if (point == profile->path) {
+ return false;
+ }
float origx = point->x;
float origy = point->y;
@@ -183,8 +191,6 @@ bool BKE_curveprofile_move_point(struct CurveProfile *profile,
*/
bool BKE_curveprofile_remove_point(CurveProfile *profile, CurveProfilePoint *point)
{
- CurveProfilePoint *pts;
-
/* Must have 2 points minimum. */
if (profile->path_len <= 2) {
return false;
@@ -195,18 +201,20 @@ bool BKE_curveprofile_remove_point(CurveProfile *profile, CurveProfilePoint *poi
return false;
}
- pts = MEM_mallocN(sizeof(CurveProfilePoint) * profile->path_len, "path points");
+ CurveProfilePoint *new_path = MEM_mallocN(sizeof(CurveProfilePoint) * profile->path_len,
+ "profile path");
- uint i_delete = (uint)(point - profile->path);
+ int i_delete = (int)(point - profile->path);
+ BLI_assert(i_delete > 0);
/* Copy the before and after the deleted point. */
- memcpy(pts, profile->path, sizeof(CurveProfilePoint) * i_delete);
- memcpy(pts + i_delete,
+ memcpy(new_path, profile->path, sizeof(CurveProfilePoint) * i_delete);
+ memcpy(new_path + i_delete,
profile->path + i_delete + 1,
sizeof(CurveProfilePoint) * (profile->path_len - i_delete - 1));
MEM_freeN(profile->path);
- profile->path = pts;
+ profile->path = new_path;
profile->path_len -= 1;
return true;
}
@@ -220,31 +228,44 @@ bool BKE_curveprofile_remove_point(CurveProfile *profile, CurveProfilePoint *poi
*/
void BKE_curveprofile_remove_by_flag(CurveProfile *profile, const short flag)
{
- int i_old, i_new, n_removed = 0;
-
/* Copy every point without the flag into the new path. */
- CurveProfilePoint *new_pts = MEM_mallocN(sizeof(CurveProfilePoint) * profile->path_len,
- "profile path");
+ CurveProfilePoint *new_path = MEM_mallocN(sizeof(CurveProfilePoint) * profile->path_len,
+ "profile path");
/* Build the new list without any of the points with the flag. Keep the first and last points. */
- new_pts[0] = profile->path[0];
- for (i_old = 1, i_new = 1; i_old < profile->path_len - 1; i_old++) {
+ int i_new = 1;
+ int i_old = 1;
+ int n_removed = 0;
+ new_path[0] = profile->path[0];
+ for (; i_old < profile->path_len - 1; i_old++) {
if (!(profile->path[i_old].flag & flag)) {
- new_pts[i_new] = profile->path[i_old];
+ new_path[i_new] = profile->path[i_old];
i_new++;
}
else {
n_removed++;
}
}
- new_pts[i_new] = profile->path[i_old];
+ new_path[i_new] = profile->path[i_old];
MEM_freeN(profile->path);
- profile->path = new_pts;
+ profile->path = new_path;
profile->path_len -= n_removed;
}
/**
+ * Shorthand helper function for setting location and interpolation of a point.
+ */
+static void point_init(CurveProfilePoint *point, float x, float y, short flag, char h1, char h2)
+{
+ point->x = x;
+ point->y = y;
+ point->flag = flag;
+ point->h1 = h1;
+ point->h2 = h2;
+}
+
+/**
* Adds a new point at the specified location. The choice for which points to place the new vertex
* between is made by checking which control point line segment is closest to the new point and
* placing the new vertex in between that segment's points.
@@ -253,7 +274,6 @@ void BKE_curveprofile_remove_by_flag(CurveProfile *profile, const short flag)
*/
CurveProfilePoint *BKE_curveprofile_insert(CurveProfile *profile, float x, float y)
{
- CurveProfilePoint *new_pt = NULL;
const float new_loc[2] = {x, y};
/* Don't add more control points than the maximum size of the higher resolution table. */
@@ -262,14 +282,13 @@ CurveProfilePoint *BKE_curveprofile_insert(CurveProfile *profile, float x, float
}
/* Find the index at the line segment that's closest to the new position. */
- float distance;
float min_distance = FLT_MAX;
int i_insert = 0;
for (int i = 0; i < profile->path_len - 1; i++) {
const float loc1[2] = {profile->path[i].x, profile->path[i].y};
const float loc2[2] = {profile->path[i + 1].x, profile->path[i + 1].y};
- distance = dist_squared_to_line_segment_v2(new_loc, loc1, loc2);
+ float distance = dist_squared_to_line_segment_v2(new_loc, loc1, loc2);
if (distance < min_distance) {
min_distance = distance;
i_insert = i + 1;
@@ -278,28 +297,25 @@ CurveProfilePoint *BKE_curveprofile_insert(CurveProfile *profile, float x, float
/* Insert the new point at the location we found and copy all of the old points in as well. */
profile->path_len++;
- CurveProfilePoint *new_pts = MEM_mallocN(sizeof(CurveProfilePoint) * profile->path_len,
- "profile path");
+ CurveProfilePoint *new_path = MEM_mallocN(sizeof(CurveProfilePoint) * profile->path_len,
+ "profile path");
+ CurveProfilePoint *new_pt = NULL;
for (int i_new = 0, i_old = 0; i_new < profile->path_len; i_new++) {
if (i_new != i_insert) {
/* Insert old points. */
- memcpy(&new_pts[i_new], &profile->path[i_old], sizeof(CurveProfilePoint));
- new_pts[i_new].flag &= ~PROF_SELECT; /* Deselect old points. */
+ new_path[i_new] = profile->path[i_old];
+ new_path[i_new].flag &= ~PROF_SELECT; /* Deselect old points. */
i_old++;
}
else {
/* Insert new point. */
- new_pts[i_new].x = x;
- new_pts[i_new].y = y;
- new_pts[i_new].flag = PROF_SELECT;
- new_pt = &new_pts[i_new];
/* Set handles of new point based on its neighbors. */
- if (new_pts[i_new - 1].h2 == HD_VECT && profile->path[i_insert].h1 == HD_VECT) {
- new_pt->h1 = new_pt->h2 = HD_VECT;
- }
- else {
- new_pt->h1 = new_pt->h2 = HD_AUTO;
- }
+ char new_handle_type = (new_path[i_new - 1].h2 == HD_VECT &&
+ profile->path[i_insert].h1 == HD_VECT) ?
+ HD_VECT :
+ HD_AUTO;
+ point_init(&new_path[i_new], x, y, PROF_SELECT, new_handle_type, new_handle_type);
+ new_pt = &new_path[i_new];
/* Give new point a reference to the profile. */
new_pt->profile = profile;
}
@@ -307,7 +323,7 @@ CurveProfilePoint *BKE_curveprofile_insert(CurveProfile *profile, float x, float
/* Free the old path and use the new one. */
MEM_freeN(profile->path);
- profile->path = new_pts;
+ profile->path = new_path;
return new_pt;
}
@@ -331,6 +347,13 @@ void BKE_curveprofile_selected_handle_set(CurveProfile *profile, int type_1, int
}
}
+static CurveProfilePoint mirror_point(const CurveProfilePoint *point)
+{
+ CurveProfilePoint new_point = *point;
+ point_init(&new_point, point->y, point->x, point->flag, point->h2, point->h1);
+ return new_point;
+}
+
/**
* Flips the profile across the diagonal so that its orientation is reversed.
*
@@ -342,135 +365,86 @@ void BKE_curveprofile_reverse(CurveProfile *profile)
if (profile->path_len == 2) {
return;
}
- CurveProfilePoint *new_pts = MEM_mallocN(sizeof(CurveProfilePoint) * profile->path_len,
- "profile path");
+ CurveProfilePoint *new_path = MEM_mallocN(sizeof(CurveProfilePoint) * profile->path_len,
+ "profile path");
/* Mirror the new points across the y = x line */
for (int i = 0; i < profile->path_len; i++) {
int i_reversed = profile->path_len - i - 1;
BLI_assert(i_reversed >= 0);
- new_pts[i_reversed].x = profile->path[i].y;
- new_pts[i_reversed].y = profile->path[i].x;
- new_pts[i_reversed].flag = profile->path[i].flag;
- new_pts[i_reversed].h1 = profile->path[i].h2;
- new_pts[i_reversed].h2 = profile->path[i].h1;
- new_pts[i_reversed].profile = profile;
+ new_path[i_reversed] = mirror_point(&profile->path[i]);
+ new_path[i_reversed].profile = profile;
/* Mirror free handles, they can't be recalculated. */
if (ELEM(profile->path[i].h1, HD_FREE, HD_ALIGN)) {
- new_pts[i_reversed].h1_loc[0] = profile->path[i].h2_loc[1];
- new_pts[i_reversed].h1_loc[1] = profile->path[i].h2_loc[0];
+ new_path[i_reversed].h1_loc[0] = profile->path[i].h2_loc[1];
+ new_path[i_reversed].h1_loc[1] = profile->path[i].h2_loc[0];
}
if (ELEM(profile->path[i].h2, HD_FREE, HD_ALIGN)) {
- new_pts[i_reversed].h2_loc[0] = profile->path[i].h1_loc[1];
- new_pts[i_reversed].h2_loc[1] = profile->path[i].h1_loc[0];
+ new_path[i_reversed].h2_loc[0] = profile->path[i].h1_loc[1];
+ new_path[i_reversed].h2_loc[1] = profile->path[i].h1_loc[0];
}
}
/* Free the old points and use the new ones */
MEM_freeN(profile->path);
- profile->path = new_pts;
+ profile->path = new_path;
}
/**
* Builds a quarter circle profile with space on each side for 'support loops.'
*/
-static void CurveProfile_build_supports(CurveProfile *profile)
+static void curveprofile_build_supports(CurveProfile *profile)
{
int n = profile->path_len;
- profile->path[0].x = 1.0;
- profile->path[0].y = 0.0;
- profile->path[0].flag = 0;
- profile->path[0].h1 = HD_VECT;
- profile->path[0].h2 = HD_VECT;
- profile->path[1].x = 1.0;
- profile->path[1].y = 0.5;
- profile->path[1].flag = 0;
- profile->path[1].h1 = HD_VECT;
- profile->path[1].h2 = HD_VECT;
+ point_init(&profile->path[0], 1.0f, 0.0f, 0, HD_VECT, HD_VECT);
+ point_init(&profile->path[1], 1.0f, 0.5f, 0, HD_VECT, HD_VECT);
for (int i = 1; i < n - 2; i++) {
- profile->path[i + 1].x = 1.0f - (0.5f * (1.0f - cosf((float)((i / (float)(n - 3))) * M_PI_2)));
- profile->path[i + 1].y = 0.5f + 0.5f * sinf((float)((i / (float)(n - 3)) * M_PI_2));
- profile->path[i + 1].flag = 0;
- profile->path[i + 1].h1 = HD_AUTO;
- profile->path[i + 1].h2 = HD_AUTO;
+ const float x = 1.0f - (0.5f * (1.0f - cosf((float)((i / (float)(n - 3))) * M_PI_2)));
+ const float y = 0.5f + 0.5f * sinf((float)((i / (float)(n - 3)) * M_PI_2));
+ point_init(&profile->path[i], x, y, 0, HD_AUTO, HD_AUTO);
}
- profile->path[n - 2].x = 0.5;
- profile->path[n - 2].y = 1.0;
- profile->path[n - 2].flag = 0;
- profile->path[n - 2].h1 = HD_VECT;
- profile->path[n - 2].h2 = HD_VECT;
- profile->path[n - 1].x = 0.0;
- profile->path[n - 1].y = 1.0;
- profile->path[n - 1].flag = 0;
- profile->path[n - 1].h1 = HD_VECT;
- profile->path[n - 1].h2 = HD_VECT;
+ point_init(&profile->path[n - 2], 0.5f, 1.0f, 0, HD_VECT, HD_VECT);
+ point_init(&profile->path[n - 1], 0.0f, 1.0f, 0, HD_VECT, HD_VECT);
}
/**
* Puts the widgets control points in a step pattern.
* Uses vector handles for each point.
*/
-static void CurveProfile_build_steps(CurveProfile *profile)
+static void curveprofile_build_steps(CurveProfile *profile)
{
- int n, step_x, step_y;
- float n_steps_x, n_steps_y;
-
- n = profile->path_len;
+ int n = profile->path_len;
/* Special case for two points to avoid dividing by zero later. */
if (n == 2) {
- profile->path[0].x = 1.0f;
- profile->path[0].y = 0.0f;
- profile->path[0].flag = 0;
- profile->path[0].h1 = HD_VECT;
- profile->path[0].h2 = HD_VECT;
- profile->path[1].x = 0.0f;
- profile->path[1].y = 1.0f;
- profile->path[1].flag = 0;
- profile->path[1].h1 = HD_VECT;
- profile->path[1].h2 = HD_VECT;
+ point_init(&profile->path[0], 1.0f, 0.0f, 0, HD_VECT, HD_VECT);
+ point_init(&profile->path[0], 0.0f, 1.0f, 0, HD_VECT, HD_VECT);
return;
}
- n_steps_x = (n % 2 == 0) ? n : (n - 1);
- n_steps_y = (n % 2 == 0) ? (n - 2) : (n - 1);
+ float n_steps_x = (n % 2 == 0) ? n : (n - 1);
+ float n_steps_y = (n % 2 == 0) ? (n - 2) : (n - 1);
for (int i = 0; i < n; i++) {
- step_x = (i + 1) / 2;
- step_y = i / 2;
- profile->path[i].x = 1.0f - ((float)(2 * step_x) / n_steps_x);
- profile->path[i].y = (float)(2 * step_y) / n_steps_y;
- profile->path[i].flag = 0;
- profile->path[i].h1 = HD_VECT;
- profile->path[i].h2 = HD_VECT;
+ int step_x = (i + 1) / 2;
+ int step_y = i / 2;
+ const float x = 1.0f - ((float)(2 * step_x) / n_steps_x);
+ const float y = (float)(2 * step_y) / n_steps_y;
+ point_init(&profile->path[i], x, y, 0, HD_VECT, HD_VECT);
}
}
/**
- * Shorthand helper function for setting location and interpolation of a point.
- */
-static void point_init(CurveProfilePoint *point, float x, float y, short flag, char h1, char h2)
-{
- point->x = x;
- point->y = y;
- point->flag = flag;
- point->h1 = h1;
- point->h2 = h2;
-}
-
-/**
* Resets the profile to the current preset.
*
* \note Requires #BKE_curveprofile_update call after.
*/
void BKE_curveprofile_reset(CurveProfile *profile)
{
- if (profile->path) {
- MEM_freeN(profile->path);
- }
+ MEM_SAFE_FREE(profile->path);
- int preset = profile->preset;
+ eCurveProfilePresets preset = profile->preset;
switch (preset) {
case PROF_PRESET_LINE:
profile->path_len = 2;
@@ -511,7 +485,7 @@ void BKE_curveprofile_reset(CurveProfile *profile)
point_init(&profile->path[1], 0.0f, 1.0f, 0, HD_AUTO, HD_AUTO);
break;
case PROF_PRESET_SUPPORTS:
- CurveProfile_build_supports(profile);
+ curveprofile_build_supports(profile);
break;
case PROF_PRESET_CORNICE:
point_init(&profile->path[0], 1.0f, 0.0f, 0, HD_VECT, HD_VECT);
@@ -542,7 +516,7 @@ void BKE_curveprofile_reset(CurveProfile *profile)
point_init(&profile->path[10], 0.0f, 1.0f, 0, HD_VECT, HD_VECT);
break;
case PROF_PRESET_STEPS:
- CurveProfile_build_steps(profile);
+ curveprofile_build_steps(profile);
break;
}
@@ -553,68 +527,61 @@ void BKE_curveprofile_reset(CurveProfile *profile)
profile->path[i].profile = profile;
}
- if (profile->table) {
- MEM_freeN(profile->table);
- profile->table = NULL;
- }
+ MEM_SAFE_FREE(profile->table);
+ profile->table = NULL;
}
/**
* Helper for 'curve_profile_create' samples.
* Returns whether both handles that make up the edge are vector handles.
*/
-static bool is_curved_edge(BezTriple *bezt, int i)
+static bool is_curved_edge(CurveProfilePoint *path, int i)
{
- return (bezt[i].h2 != HD_VECT || bezt[i + 1].h1 != HD_VECT);
+ return (path[i].h2 != HD_VECT || path[i + 1].h1 != HD_VECT);
}
/**
* Used to set bezier handle locations in the sample creation process. Reduced copy of
* #calchandleNurb_intern code in curve.c, mostly changed by removing the third dimension.
*/
-static void calchandle_profile(BezTriple *bezt, const BezTriple *prev, const BezTriple *next)
+static void point_calculate_handle(CurveProfilePoint *point,
+ const CurveProfilePoint *prev,
+ const CurveProfilePoint *next)
{
-#define point_handle1 ((point_loc)-3)
-#define point_handle2 ((point_loc) + 3)
-
- const float *prev_loc, *next_loc;
- float *point_loc;
- float pt[3];
- float len, len_a, len_b;
- float dvec_a[2], dvec_b[2];
-
- if (bezt->h1 == 0 && bezt->h2 == 0) {
+ if (point->h1 == HD_FREE && point->h2 == HD_FREE) {
return;
}
- point_loc = bezt->vec[1];
+ float *point_loc = &point->x;
+ float pt[2];
+ const float *prev_loc, *next_loc;
if (prev == NULL) {
- next_loc = next->vec[1];
+ next_loc = &next->x;
pt[0] = 2.0f * point_loc[0] - next_loc[0];
pt[1] = 2.0f * point_loc[1] - next_loc[1];
prev_loc = pt;
}
else {
- prev_loc = prev->vec[1];
+ prev_loc = &prev->x;
}
if (next == NULL) {
- prev_loc = prev->vec[1];
+ prev_loc = &prev->x;
pt[0] = 2.0f * point_loc[0] - prev_loc[0];
pt[1] = 2.0f * point_loc[1] - prev_loc[1];
next_loc = pt;
}
else {
- next_loc = next->vec[1];
+ next_loc = &next->x;
}
+ float dvec_a[2], dvec_b[2];
sub_v2_v2v2(dvec_a, point_loc, prev_loc);
sub_v2_v2v2(dvec_b, next_loc, point_loc);
- len_a = len_v2(dvec_a);
- len_b = len_v2(dvec_b);
-
+ float len_a = len_v2(dvec_a);
+ float len_b = len_v2(dvec_b);
if (len_a == 0.0f) {
len_a = 1.0f;
}
@@ -622,60 +589,65 @@ static void calchandle_profile(BezTriple *bezt, const BezTriple *prev, const Bez
len_b = 1.0f;
}
- if (bezt->h1 == HD_AUTO || bezt->h2 == HD_AUTO) { /* auto */
+ if (point->h1 == HD_AUTO || point->h2 == HD_AUTO) {
float tvec[2];
tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a;
tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a;
- len = len_v2(tvec) * 2.5614f;
+ float len = len_v2(tvec) * 2.5614f;
if (len != 0.0f) {
-
- if (bezt->h1 == HD_AUTO) {
+ if (point->h1 == HD_AUTO) {
len_a /= len;
- madd_v2_v2v2fl(point_handle1, point_loc, tvec, -len_a);
+ madd_v2_v2v2fl(point->h1_loc, point_loc, tvec, -len_a);
}
- if (bezt->h2 == HD_AUTO) {
+ if (point->h2 == HD_AUTO) {
len_b /= len;
- madd_v2_v2v2fl(point_handle2, point_loc, tvec, len_b);
+ madd_v2_v2v2fl(point->h2_loc, point_loc, tvec, len_b);
}
}
}
- if (bezt->h1 == HD_VECT) { /* vector */
- madd_v2_v2v2fl(point_handle1, point_loc, dvec_a, -1.0f / 3.0f);
+ if (point->h1 == HD_VECT) {
+ madd_v2_v2v2fl(point->h1_loc, point_loc, dvec_a, -1.0f / 3.0f);
+ }
+ if (point->h2 == HD_VECT) {
+ madd_v2_v2v2fl(point->h2_loc, point_loc, dvec_b, 1.0f / 3.0f);
}
- if (bezt->h2 == HD_VECT) {
- madd_v2_v2v2fl(point_handle2, point_loc, dvec_b, 1.0f / 3.0f);
+}
+
+static void calculate_path_handles(CurveProfilePoint *path, int path_len)
+{
+ point_calculate_handle(&path[0], NULL, &path[1]);
+ for (int i = 1; i < path_len - 1; i++) {
+ point_calculate_handle(&path[i], &path[i - 1], &path[i + 1]);
}
-#undef point_handle1
-#undef point_handle2
+ point_calculate_handle(&path[path_len - 1], &path[path_len - 2], NULL);
}
/**
- * Helper function for 'BKE_CurveProfile_create_samples.' Calculates the angle between the
+ * Helper function for 'BKE_curveprofile_create_samples.' Calculates the angle between the
* handles on the inside of the edge starting at index i. A larger angle means the edge is
* more curved.
* \param i_edge: The start index of the edge to calculate the angle for.
*/
-static float bezt_edge_handle_angle(const BezTriple *bezt, int i_edge)
+static float bezt_edge_handle_angle(const CurveProfilePoint *path, int i_edge)
{
/* Find the direction of the handles that define this edge along the direction of the path. */
float start_handle_direction[2], end_handle_direction[2];
/* Handle 2 - point location. */
- sub_v2_v2v2(start_handle_direction, bezt[i_edge].vec[2], bezt[i_edge].vec[1]);
+ sub_v2_v2v2(start_handle_direction, path[i_edge].h2_loc, &path[i_edge].x);
/* Point location - handle 1. */
- sub_v2_v2v2(end_handle_direction, bezt[i_edge + 1].vec[1], bezt[i_edge + 1].vec[0]);
+ sub_v2_v2v2(end_handle_direction, &path[i_edge + 1].x, path[i_edge + 1].h1_loc);
- float angle = angle_v2v2(start_handle_direction, end_handle_direction);
- return angle;
+ return angle_v2v2(start_handle_direction, end_handle_direction);
}
/** Struct to sort curvature of control point edges. */
typedef struct {
- /** The index of the corresponding bezier point. */
- int bezt_index;
+ /** The index of the corresponding profile point. */
+ int point_index;
/** The curvature of the edge with the above index. */
- float bezt_curvature;
+ float point_curvature;
} CurvatureSortPoint;
/**
@@ -686,7 +658,7 @@ static int sort_points_curvature(const void *in_a, const void *in_b)
const CurvatureSortPoint *a = (const CurvatureSortPoint *)in_a;
const CurvatureSortPoint *b = (const CurvatureSortPoint *)in_b;
- if (a->bezt_curvature > b->bezt_curvature) {
+ if (a->point_curvature > b->point_curvature) {
return 0;
}
@@ -698,82 +670,52 @@ static int sort_points_curvature(const void *in_a, const void *in_b)
* user-defined points will be evenly distributed among the curved edges.
* Then the remainders will be distributed to the most curved edges.
*
- * \param n_segments: The number of segments to sample along the path. It must be higher than the
- * number of points used to define the profile (profile->path_len).
- * \param sample_straight_edges: Whether to sample points between vector handle control points. If
- * this is true and there are only vector edges the straight edges will still be sampled.
- * \param r_samples: An array of points to put the sampled positions. Must have length n_segments.
- * \return r_samples: Fill the array with the sampled locations and if the point corresponds
- * to a control point, its handle type.
+ * \param n_segments: The number of segments to sample along the path. Ideally it is higher than
+ * the number of points used to define the profile (profile->path_len).
+ * \param sample_straight_edges: Whether to sample points between vector handle control points.
+ * If this is true and there are only vector edges the straight edges will still be sampled.
+ * \param r_samples: Return array of points to put the sampled positions. Must have length
+ * n_segments. Fill the array with the sampled locations and if the point corresponds to a
+ * control point, its handle type.
*/
void BKE_curveprofile_create_samples(CurveProfile *profile,
int n_segments,
bool sample_straight_edges,
CurveProfilePoint *r_samples)
{
- BezTriple *bezt;
- int i, n_left, n_common, i_sample, n_curved_edges;
- int *n_samples;
- CurvatureSortPoint *curve_sorted;
+ CurveProfilePoint *path = profile->path;
int totpoints = profile->path_len;
- int totedges = totpoints - 1;
-
BLI_assert(n_segments > 0);
- /* Create Bezier points for calculating the higher resolution path. */
- bezt = MEM_callocN(sizeof(BezTriple) * totpoints, "beztarr");
- for (i = 0; i < totpoints; i++) {
- bezt[i].vec[1][0] = profile->path[i].x;
- bezt[i].vec[1][1] = profile->path[i].y;
- bezt[i].h1 = profile->path[i].h1;
- bezt[i].h2 = profile->path[i].h2;
- /* Copy handle locations if the handle type is free. */
- if (ELEM(profile->path[i].h1, HD_FREE, HD_ALIGN)) {
- bezt[i].vec[0][0] = profile->path[i].h1_loc[0];
- bezt[i].vec[0][1] = profile->path[i].h1_loc[1];
- }
- if (ELEM(profile->path[i].h1, HD_FREE, HD_ALIGN)) {
- bezt[i].vec[2][0] = profile->path[i].h2_loc[0];
- bezt[i].vec[2][1] = profile->path[i].h2_loc[1];
- }
- }
- /* Get handle positions for the non-free bezier points. */
- calchandle_profile(&bezt[0], NULL, &bezt[1]);
- for (i = 1; i < totpoints - 1; i++) {
- calchandle_profile(&bezt[i], &bezt[i - 1], &bezt[i + 1]);
- }
- calchandle_profile(&bezt[totpoints - 1], &bezt[totpoints - 2], NULL);
-
- /* Copy the handle locations back to the control points. */
- for (i = 0; i < totpoints; i++) {
- profile->path[i].h1_loc[0] = bezt[i].vec[0][0];
- profile->path[i].h1_loc[1] = bezt[i].vec[0][1];
- profile->path[i].h2_loc[0] = bezt[i].vec[2][0];
- profile->path[i].h2_loc[1] = bezt[i].vec[2][1];
- }
+ int totedges = totpoints - 1;
+
+ calculate_path_handles(path, totpoints);
/* Create a list of edge indices with the most curved at the start, least curved at the end. */
- curve_sorted = MEM_callocN(sizeof(CurvatureSortPoint) * totedges, "curve sorted");
- for (i = 0; i < totedges; i++) {
- curve_sorted[i].bezt_index = i;
+ CurvatureSortPoint *curve_sorted = MEM_callocN(sizeof(CurvatureSortPoint) * totedges,
+ "curve sorted");
+ for (int i = 0; i < totedges; i++) {
+ curve_sorted[i].point_index = i;
/* Calculate the curvature of each edge once for use when sorting for curvature. */
- curve_sorted[i].bezt_curvature = bezt_edge_handle_angle(bezt, i);
+ curve_sorted[i].point_curvature = bezt_edge_handle_angle(path, i);
}
- qsort(curve_sorted, (size_t)totedges, sizeof(CurvatureSortPoint), sort_points_curvature);
+ qsort(curve_sorted, totedges, sizeof(CurvatureSortPoint), sort_points_curvature);
/* Assign the number of sampled points for each edge. */
- n_samples = MEM_callocN(sizeof(int) * totedges, "create samples numbers");
+ int16_t *n_samples = MEM_callocN(sizeof(int16_t) * totedges, "samples numbers");
int n_added = 0;
+ int n_left;
if (n_segments >= totedges) {
if (sample_straight_edges) {
/* Assign an even number to each edge if it’s possible, then add the remainder of sampled
* points starting with the most curved edges. */
- n_common = n_segments / totedges;
+ int n_common = n_segments / totedges;
n_left = n_segments % totedges;
/* Assign the points that fill fit evenly to the edges. */
if (n_common > 0) {
- for (i = 0; i < totedges; i++) {
+ BLI_assert(n_common < INT16_MAX);
+ for (int i = 0; i < totedges; i++) {
n_samples[i] = n_common;
n_added += n_common;
}
@@ -781,9 +723,9 @@ void BKE_curveprofile_create_samples(CurveProfile *profile,
}
else {
/* Count the number of curved edges */
- n_curved_edges = 0;
- for (i = 0; i < totedges; i++) {
- if (is_curved_edge(bezt, i)) {
+ int n_curved_edges = 0;
+ for (int i = 0; i < totedges; i++) {
+ if (is_curved_edge(path, i)) {
n_curved_edges++;
}
}
@@ -792,11 +734,12 @@ void BKE_curveprofile_create_samples(CurveProfile *profile,
/* Give all of the curved edges the same number of points and straight edges one point. */
n_left = n_segments - (totedges - n_curved_edges); /* Left after 1 for each straight edge. */
- n_common = n_left / n_curved_edges; /* Number assigned to all curved edges */
+ int n_common = n_left / n_curved_edges; /* Number assigned to all curved edges */
if (n_common > 0) {
- for (i = 0; i < totedges; i++) {
+ for (int i = 0; i < totedges; i++) {
/* Add the common number if it's a curved edge or if edges are curved. */
- if (is_curved_edge(bezt, i) || n_curved_edges == totedges) {
+ if (is_curved_edge(path, i) || n_curved_edges == totedges) {
+ BLI_assert(n_common + n_samples[i] < INT16_MAX);
n_samples[i] += n_common;
n_added += n_common;
}
@@ -815,19 +758,20 @@ void BKE_curveprofile_create_samples(CurveProfile *profile,
}
/* Assign the remainder of the points that couldn't be spread out evenly. */
BLI_assert(n_left < totedges);
- for (i = 0; i < n_left; i++) {
- n_samples[curve_sorted[i].bezt_index]++;
+ for (int i = 0; i < n_left; i++) {
+ BLI_assert(n_samples[curve_sorted[i].point_index] < INT16_MAX);
+ n_samples[curve_sorted[i].point_index]++;
n_added++;
}
BLI_assert(n_added == n_segments); /* n_added is just used for this assert, could remove it. */
/* Sample the points and add them to the locations table. */
- for (i_sample = 0, i = 0; i < totedges; i++) {
+ for (int i_sample = 0, i = 0; i < totedges; i++) {
if (n_samples[i] > 0) {
/* Carry over the handle types from the control point to its first corresponding sample. */
- r_samples[i_sample].h1 = profile->path[i].h1;
- r_samples[i_sample].h2 = profile->path[i].h2;
+ r_samples[i_sample].h1 = path[i].h1;
+ r_samples[i_sample].h2 = path[i].h2;
/* All extra sample points for this control point get "auto" handles. */
for (int j = i_sample + 1; j < i_sample + n_samples[i]; j++) {
r_samples[j].flag = 0;
@@ -837,17 +781,17 @@ void BKE_curveprofile_create_samples(CurveProfile *profile,
}
/* Sample from the bezier points. X then Y values. */
- BKE_curve_forward_diff_bezier(bezt[i].vec[1][0],
- bezt[i].vec[2][0],
- bezt[i + 1].vec[0][0],
- bezt[i + 1].vec[1][0],
+ BKE_curve_forward_diff_bezier(path[i].x,
+ path[i].h2_loc[0],
+ path[i + 1].h1_loc[0],
+ path[i + 1].x,
&r_samples[i_sample].x,
n_samples[i],
sizeof(CurveProfilePoint));
- BKE_curve_forward_diff_bezier(bezt[i].vec[1][1],
- bezt[i].vec[2][1],
- bezt[i + 1].vec[0][1],
- bezt[i + 1].vec[1][1],
+ BKE_curve_forward_diff_bezier(path[i].y,
+ path[i].h2_loc[1],
+ path[i + 1].h1_loc[1],
+ path[i + 1].y,
&r_samples[i_sample].y,
n_samples[i],
sizeof(CurveProfilePoint));
@@ -856,25 +800,6 @@ void BKE_curveprofile_create_samples(CurveProfile *profile,
BLI_assert(i_sample <= n_segments);
}
-#ifdef DEBUG_PROFILE_TABLE
- printf("CURVEPROFILE CREATE SAMPLES\n");
- printf("n_segments: %d\n", n_segments);
- printf("totedges: %d\n", totedges);
- printf("n_common: %d\n", n_common);
- printf("n_left: %d\n", n_left);
- printf("n_samples: ");
- for (i = 0; i < totedges; i++) {
- printf("%d, ", n_samples[i]);
- }
- printf("\n");
- printf("i_curved_sorted: ");
- for (i = 0; i < totedges; i++) {
- printf("(%d %.2f), ", curve_sorted[i].bezt_index, curve_sorted[i].bezt_curvature);
- }
- printf("\n");
-#endif
-
- MEM_freeN(bezt);
MEM_freeN(curve_sorted);
MEM_freeN(n_samples);
}
@@ -887,16 +812,14 @@ static void curveprofile_make_table(CurveProfile *profile)
{
int n_samples = PROF_TABLE_LEN(profile->path_len);
CurveProfilePoint *new_table = MEM_callocN(sizeof(CurveProfilePoint) * (n_samples + 1),
- "high-res table");
+ __func__);
BKE_curveprofile_create_samples(profile, n_samples - 1, false, new_table);
/* Manually add last point at the end of the profile */
new_table[n_samples - 1].x = 0.0f;
new_table[n_samples - 1].y = 1.0f;
- if (profile->table) {
- MEM_freeN(profile->table);
- }
+ MEM_SAFE_FREE(profile->table);
profile->table = new_table;
}
@@ -904,14 +827,14 @@ static void curveprofile_make_table(CurveProfile *profile)
* Creates the table of points used for displaying a preview of the sampled segment locations on
* the widget itself.
*/
-static void CurveProfile_make_segments_table(CurveProfile *profile)
+static void curveprofile_make_segments_table(CurveProfile *profile)
{
int n_samples = profile->segments_len;
if (n_samples <= 0) {
return;
}
CurveProfilePoint *new_table = MEM_callocN(sizeof(CurveProfilePoint) * (n_samples + 1),
- "samples table");
+ __func__);
if (profile->flag & PROF_SAMPLE_EVEN_LENGTHS) {
/* Even length sampling incompatible with only straight edge sampling for now. */
@@ -922,9 +845,7 @@ static void CurveProfile_make_segments_table(CurveProfile *profile)
profile, n_samples, profile->flag & PROF_SAMPLE_STRAIGHT_EDGES, new_table);
}
- if (profile->segments) {
- MEM_freeN(profile->segments);
- }
+ MEM_SAFE_FREE(profile->segments);
profile->segments = new_table;
}
@@ -954,9 +875,8 @@ void BKE_curveprofile_set_defaults(CurveProfile *profile)
/**
* Returns a pointer to a newly allocated curve profile, using the given preset.
- * \param preset: Value in #eCurveProfilePresets.
*/
-struct CurveProfile *BKE_curveprofile_add(int preset)
+struct CurveProfile *BKE_curveprofile_add(eCurveProfilePresets preset)
{
CurveProfile *profile = MEM_callocN(sizeof(CurveProfile), "curve profile");
@@ -978,8 +898,6 @@ void BKE_curveprofile_update(CurveProfile *profile, const int update_flags)
{
CurveProfilePoint *points = profile->path;
rctf *clipr = &profile->clip_rect;
- float thresh;
- int i;
profile->changed_timestamp++;
@@ -987,11 +905,9 @@ void BKE_curveprofile_update(CurveProfile *profile, const int update_flags)
if (profile->flag & PROF_USE_CLIP) {
/* Move points inside the clip rectangle. */
if (update_flags & PROF_UPDATE_CLIP) {
- for (i = 0; i < profile->path_len; i++) {
- points[i].x = max_ff(points[i].x, clipr->xmin);
- points[i].x = min_ff(points[i].x, clipr->xmax);
- points[i].y = max_ff(points[i].y, clipr->ymin);
- points[i].y = min_ff(points[i].y, clipr->ymax);
+ for (int i = 0; i < profile->path_len; i++) {
+ points[i].x = clamp_f(points[i].x, clipr->xmin, clipr->xmax);
+ points[i].y = clamp_f(points[i].y, clipr->ymin, clipr->ymax);
/* Extra sanity assert to make sure the points have the right profile pointer. */
BLI_assert(points[i].profile == profile);
@@ -1009,9 +925,9 @@ void BKE_curveprofile_update(CurveProfile *profile, const int update_flags)
}
/* Remove doubles with a threshold set at 1% of default range. */
- thresh = pow2f(0.01f * BLI_rctf_size_x(clipr));
+ float thresh = pow2f(0.01f * BLI_rctf_size_x(clipr));
if (update_flags & PROF_UPDATE_REMOVE_DOUBLES && profile->path_len > 2) {
- for (i = 0; i < profile->path_len - 1; i++) {
+ for (int i = 0; i < profile->path_len - 1; i++) {
if (len_squared_v2v2(&points[i].x, &points[i + 1].x) < thresh) {
if (i == 0) {
BKE_curveprofile_remove_point(profile, &points[1]);
@@ -1029,7 +945,7 @@ void BKE_curveprofile_update(CurveProfile *profile, const int update_flags)
/* Store a table of samples for the segment locations for a preview and the table's user. */
if (profile->segments_len > 0) {
- CurveProfile_make_segments_table(profile);
+ curveprofile_make_segments_table(profile);
}
}
@@ -1094,7 +1010,6 @@ void BKE_curveprofile_create_samples_even_spacing(CurveProfile *profile,
float length_travelled = 0.0f;
float distance_to_next_table_point = curveprofile_distance_to_next_table_point(profile, 0);
float distance_to_previous_table_point = 0.0f;
- float segment_left, factor;
int i_table = 0;
/* Set the location for the first point. */
@@ -1102,7 +1017,7 @@ void BKE_curveprofile_create_samples_even_spacing(CurveProfile *profile,
r_samples[0].y = profile->table[0].y;
/* Travel along the path, recording the locations of segments as we pass them. */
- segment_left = segment_length;
+ float segment_left = segment_length;
for (int i = 1; i < n_segments; i++) {
/* Travel over all of the points that fit inside this segment. */
while (distance_to_next_table_point < segment_left) {
@@ -1113,12 +1028,12 @@ void BKE_curveprofile_create_samples_even_spacing(CurveProfile *profile,
distance_to_previous_table_point = 0.0f;
}
/* We're at the last table point that fits inside the current segment, use interpolation. */
- factor = (distance_to_previous_table_point + segment_left) /
- (distance_to_previous_table_point + distance_to_next_table_point);
+ float factor = (distance_to_previous_table_point + segment_left) /
+ (distance_to_previous_table_point + distance_to_next_table_point);
r_samples[i].x = interpf(profile->table[i_table + 1].x, profile->table[i_table].x, factor);
r_samples[i].y = interpf(profile->table[i_table + 1].y, profile->table[i_table].y, factor);
-#ifdef DEBUG_CURVEPROFILE_EVALUATE
BLI_assert(factor <= 1.0f && factor >= 0.0f);
+#ifdef DEBUG_CURVEPROFILE_EVALUATE
printf("segment_left: %.3f\n", segment_left);
printf("i_table: %d\n", i_table);
printf("distance_to_previous_table_point: %.3f\n", distance_to_previous_table_point);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index bf38f8bf12f..83cbdeff0d8 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -6954,10 +6954,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block,
const float zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&profile->view_rect);
if (snap) {
- float d[2];
-
- d[0] = mx - data->dragstartx;
- d[1] = my - data->dragstarty;
+ float d[2] = {mx - data->dragstartx, data->dragstarty};
if (len_squared_v2(d) < (9.0f * U.dpi_fac)) {
snap = false;
@@ -6979,7 +6976,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block,
const float delta[2] = {fx, fy};
for (int a = 0; a < profile->path_len; a++) {
/* Don't move the last and first control points. */
- if ((pts[a].flag & PROF_SELECT) && (a != 0) && (a != profile->path_len)) {
+ if (pts[a].flag & PROF_SELECT) {
moved_point |= BKE_curveprofile_move_point(profile, &pts[a], snap, delta);
last_x = pts[a].x;
last_y = pts[a].y;