Fix vertex slide regression from multi-edit

- Invalid casts.
- Leaked memory on mode switching.
This commit is contained in:
Campbell Barton 2018-04-26 10:08:41 +02:00
parent ba9b01d3c0
commit 7fcdccbb6c
3 changed files with 47 additions and 33 deletions

View File

@ -1041,11 +1041,13 @@ int transformEvent(TransInfo *t, const wmEvent *event)
initEdgeSlide(t);
/* if that fails, do vertex slide */
if (t->state == TRANS_CANCEL) {
resetTransModal(t);
t->state = TRANS_STARTING;
initVertSlide(t);
}
/* vert slide can fail on unconnected vertices (rare but possible) */
if (t->state == TRANS_CANCEL) {
resetTransModal(t);
t->mode = TFM_TRANSLATION;
t->state = TRANS_STARTING;
restoreTransObjects(t);
@ -6937,7 +6939,7 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
static void drawEdgeSlide(TransInfo *t)
{
if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
EdgeSlideParams *slp = t->custom.mode.data;
const EdgeSlideParams *slp = t->custom.mode.data;
EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
@ -7189,6 +7191,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
static void calcVertSlideCustomPoints(struct TransInfo *t)
{
VertSlideParams *slp = t->custom.mode.data;
VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
@ -7206,7 +7209,7 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]);
ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]);
if (sld->flipped && sld->use_even) {
if (slp->flipped && slp->use_even) {
setCustomPoints(t, &t->mouse, mval_start, mval_end);
}
else {
@ -7567,6 +7570,7 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
static void drawVertSlide(TransInfo *t)
{
if ((t->mode == TFM_VERT_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
const VertSlideParams *slp = t->custom.mode.data;
VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
@ -7623,7 +7627,7 @@ static void drawVertSlide(TransInfo *t)
glPointSize(ctrl_size);
immBegin(GWN_PRIM_POINTS, 1);
immVertex3fv(shdr_pos, (sld->flipped && sld->use_even) ?
immVertex3fv(shdr_pos, (slp->flipped && slp->use_even) ?
curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
curr_sv->co_orig_3d);
immEnd();
@ -7683,15 +7687,18 @@ static void drawVertSlide(TransInfo *t)
static void doVertSlide(TransInfo *t, float perc)
{
VertSlideParams *slp = t->custom.mode.data;
slp->perc = perc;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
VertSlideData *sld = tc->custom.mode.data;
TransDataVertSlideVert *svlist = sld->sv, *sv;
int i;
sld->perc = perc;
sv = svlist;
if (sld->use_even == false) {
if (slp->use_even == false) {
for (i = 0; i < sld->totsv; i++, sv++) {
interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc);
}
@ -7709,7 +7716,7 @@ static void doVertSlide(TransInfo *t, float perc)
edge_len = normalize_v3(dir);
if (edge_len > FLT_EPSILON) {
if (sld->flipped) {
if (slp->flipped) {
madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc);
}
else {
@ -7729,7 +7736,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
char str[UI_MAX_DRAW_STR];
size_t ofs = 0;
float final;
VertSlideData *slp = t->custom.mode.data;
VertSlideParams *slp = t->custom.mode.data;
const bool flipped = slp->flipped;
const bool use_even = slp->use_even;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);

View File

@ -307,11 +307,6 @@ typedef struct VertSlideData {
SlideOrigData orig_data;
float perc;
bool use_even;
bool flipped;
int curr_sv_index;
/* result of ED_view3d_ob_project_mat_get */
@ -800,6 +795,7 @@ void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float val
void initTransDataContainers_FromObjectData(TransInfo *t);
void initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, const struct wmEvent *event);
void freeTransCustomDataForMode(TransInfo *t);
void postTrans(struct bContext *C, TransInfo *t);
void resetTransModal(TransInfo *t);
void resetTransRestrictions(TransInfo *t);

View File

@ -1142,18 +1142,7 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
*/
void resetTransModal(TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
if (t->mode == TFM_EDGE_SLIDE) {
freeEdgeSlideVerts(t, tc, &tc->custom.mode);
}
else if (t->mode == TFM_VERT_SLIDE) {
freeVertSlideVerts(t, tc, &tc->custom.mode);
}
else {
/* no need to keep looping... */
break;
}
}
freeTransCustomDataForMode(t);
}
void resetTransRestrictions(TransInfo *t)
@ -1577,19 +1566,41 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
initNumInput(&t->num);
}
static void freeTransCustomData(
TransInfo *t, TransDataContainer *tc,
TransCustomData *custom_data)
{
if (custom_data->free_cb) {
/* Can take over freeing t->data and data_2d etc... */
custom_data->free_cb(t, tc, custom_data);
BLI_assert(custom_data->data == NULL);
}
else if ((custom_data->data != NULL) && custom_data->use_free) {
MEM_freeN(custom_data->data);
custom_data->data = NULL;
}
/* In case modes are switched in the same transform session. */
custom_data->free_cb = false;
custom_data->use_free = false;
}
static void freeTransCustomDataContainer(TransInfo *t, TransDataContainer *tc, TransCustomDataContainer *tcdc)
{
TransCustomData *custom_data = &tcdc->first_elem;
for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
if (custom_data->free_cb) {
/* Can take over freeing t->data and data_2d etc... */
custom_data->free_cb(t, tc, custom_data);
BLI_assert(custom_data->data == NULL);
}
else if ((custom_data->data != NULL) && custom_data->use_free) {
MEM_freeN(custom_data->data);
custom_data->data = NULL;
}
freeTransCustomData(t, tc, custom_data);
}
}
/**
* Needed for mode switching.
*/
void freeTransCustomDataForMode(TransInfo *t)
{
freeTransCustomData(t, NULL, &t->custom.mode);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
freeTransCustomData(t, tc, &tc->custom.mode);
}
}