Fix transform crash in rare cases

In some cases transform modes would use the custom-data pointer,
other times the transform conversion functions would.

However with some combinations (bone mirror + bend for eg),
both conversion & transform mode would use this pointer causing a crash.

Fix this by having 2 custom-data pointers:
one for the mode, another for the data-type.

This also simplifies time-slide which was conditionally mixing mode/type data in the one array.
This commit is contained in:
Campbell Barton 2016-02-01 15:15:10 +11:00
parent 17429dce00
commit c2508b0aaf
5 changed files with 160 additions and 151 deletions

View File

@ -2858,7 +2858,7 @@ static void initBend(TransInfo *t)
t->num.unit_type[0] = B_UNIT_ROTATION;
t->num.unit_type[1] = B_UNIT_LENGTH;
t->flag |= T_NO_CONSTRAINT | T_FREE_CUSTOMDATA;
t->flag |= T_NO_CONSTRAINT;
//copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
calculateCenterCursor(t, t->center);
@ -2886,7 +2886,8 @@ static void initBend(TransInfo *t)
data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
t->customData = data;
t->custom.mode.data = data;
t->custom.mode.use_free = true;
}
static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event)
@ -2908,7 +2909,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
float warp_end_radius[3];
int i;
char str[MAX_INFO_LEN];
const struct BendCustomData *data = t->customData;
const struct BendCustomData *data = t->custom.mode.data;
const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
union {
@ -3065,27 +3066,27 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
eRedrawFlag status = TREDRAW_NOTHING;
if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
// Use customData pointer to signal Shear direction
if (t->customData == NULL) {
/* Use custom.mode.data pointer to signal Shear direction */
if (t->custom.mode.data == NULL) {
initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
t->customData = (void *)1;
t->custom.mode.data = (void *)1;
}
else {
initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
t->customData = NULL;
t->custom.mode.data = NULL;
}
status = TREDRAW_HARD;
}
else if (event->type == XKEY && event->val == KM_PRESS) {
initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
t->customData = NULL;
t->custom.mode.data = NULL;
status = TREDRAW_HARD;
}
else if (event->type == YKEY && event->val == KM_PRESS) {
initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
t->customData = (void *)1;
t->custom.mode.data = (void *)1;
status = TREDRAW_HARD;
}
@ -3131,7 +3132,7 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
unit_m3(smat);
// Custom data signals shear direction
if (t->customData == NULL)
if (t->custom.mode.data == NULL)
smat[1][0] = value;
else
smat[0][1] = value;
@ -5680,7 +5681,7 @@ static void slide_origdata_free_date(
static void calcEdgeSlideCustomPoints(struct TransInfo *t)
{
EdgeSlideData *sld = t->customData;
EdgeSlideData *sld = t->custom.mode.data;
setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
@ -6425,7 +6426,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, bool use_even, bool f
sld->perc = 0.0f;
t->customData = sld;
t->custom.mode.data = sld;
MEM_freeN(sv_table);
@ -6627,7 +6628,7 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, bool use_even, bool f
sld->perc = 0.0f;
t->customData = sld;
t->custom.mode.data = sld;
MEM_freeN(sv_table);
@ -6636,7 +6637,7 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, bool use_even, bool f
void projectEdgeSlideData(TransInfo *t, bool is_final)
{
EdgeSlideData *sld = t->customData;
EdgeSlideData *sld = t->custom.mode.data;
SlideOrigData *sod = &sld->orig_data;
if (sod->use_origfaces == false) {
@ -6651,9 +6652,9 @@ void freeEdgeSlideTempFaces(EdgeSlideData *sld)
slide_origdata_free_date(&sld->orig_data);
}
void freeEdgeSlideVerts(TransInfo *t)
void freeEdgeSlideVerts(TransInfo *UNUSED(t), TransCustomData *custom_data)
{
EdgeSlideData *sld = t->customData;
EdgeSlideData *sld = custom_data->data;
if (!sld)
return;
@ -6665,7 +6666,7 @@ void freeEdgeSlideVerts(TransInfo *t)
MEM_freeN(sld->sv);
MEM_freeN(sld);
t->customData = NULL;
custom_data->data = NULL;
}
static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
@ -6689,12 +6690,12 @@ static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even,
return;
}
sld = t->customData;
sld = t->custom.mode.data;
if (!sld)
return;
t->customFree = freeEdgeSlideVerts;
t->custom.mode.free_cb = freeEdgeSlideVerts;
/* set custom point first if you want value to be initialized by init */
calcEdgeSlideCustomPoints(t);
@ -6721,7 +6722,7 @@ static void initEdgeSlide(TransInfo *t)
static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event)
{
if (t->mode == TFM_EDGE_SLIDE) {
EdgeSlideData *sld = t->customData;
EdgeSlideData *sld = t->custom.mode.data;
if (sld) {
switch (event->type) {
@ -6770,8 +6771,8 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
static void drawEdgeSlide(TransInfo *t)
{
if ((t->mode == TFM_EDGE_SLIDE) && t->customData) {
EdgeSlideData *sld = t->customData;
if ((t->mode == TFM_EDGE_SLIDE) && t->custom.mode.data) {
EdgeSlideData *sld = t->custom.mode.data;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
/* Even mode */
@ -6886,7 +6887,7 @@ static void drawEdgeSlide(TransInfo *t)
static void doEdgeSlide(TransInfo *t, float perc)
{
EdgeSlideData *sld = t->customData;
EdgeSlideData *sld = t->custom.mode.data;
TransDataEdgeSlideVert *svlist = sld->sv, *sv;
int i;
@ -6959,7 +6960,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
char str[MAX_INFO_LEN];
size_t ofs = 0;
float final;
EdgeSlideData *sld = t->customData;
EdgeSlideData *sld = t->custom.mode.data;
bool flipped = sld->flipped;
bool use_even = sld->use_even;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
@ -7013,7 +7014,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
static void calcVertSlideCustomPoints(struct TransInfo *t)
{
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
const float *co_orig_3d = sv->co_orig_3d;
@ -7048,7 +7049,7 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
*/
static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
{
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
float mval_fl[2] = {UNPACK2(mval)};
TransDataVertSlideVert *sv;
@ -7075,7 +7076,7 @@ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
*/
static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2])
{
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
float imval_fl[2] = {UNPACK2(t->mouse.imval)};
float mval_fl[2] = {UNPACK2(mval)};
@ -7209,7 +7210,7 @@ static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool
sld->perc = 0.0f;
t->customData = sld;
t->custom.mode.data = sld;
/* most likely will be set below */
unit_m4(sld->proj_mat);
@ -7233,7 +7234,7 @@ static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool
void projectVertSlideData(TransInfo *t, bool is_final)
{
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
SlideOrigData *sod = &sld->orig_data;
if (sod->use_origfaces == false) {
@ -7248,9 +7249,9 @@ void freeVertSlideTempFaces(VertSlideData *sld)
slide_origdata_free_date(&sld->orig_data);
}
void freeVertSlideVerts(TransInfo *t)
void freeVertSlideVerts(TransInfo *UNUSED(t), TransCustomData *custom_data)
{
VertSlideData *sld = t->customData;
VertSlideData *sld = custom_data->data;
if (!sld)
return;
@ -7270,7 +7271,7 @@ void freeVertSlideVerts(TransInfo *t)
MEM_freeN(sld->sv);
MEM_freeN(sld);
t->customData = NULL;
custom_data->data = NULL;
}
static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
@ -7286,12 +7287,12 @@ static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use
return;
}
sld = t->customData;
sld = t->custom.mode.data;
if (!sld)
return;
t->customFree = freeVertSlideVerts;
t->custom.mode.free_cb = freeVertSlideVerts;
/* set custom point first if you want value to be initialized by init */
calcVertSlideCustomPoints(t);
@ -7318,7 +7319,7 @@ static void initVertSlide(TransInfo *t)
static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event)
{
if (t->mode == TFM_VERT_SLIDE) {
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
if (sld) {
switch (event->type) {
@ -7378,8 +7379,8 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
static void drawVertSlide(TransInfo *t)
{
if ((t->mode == TFM_VERT_SLIDE) && t->customData) {
VertSlideData *sld = t->customData;
if ((t->mode == TFM_VERT_SLIDE) && t->custom.mode.data) {
VertSlideData *sld = t->custom.mode.data;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
/* Non-Prop mode */
@ -7483,7 +7484,7 @@ static void drawVertSlide(TransInfo *t)
static void doVertSlide(TransInfo *t, float perc)
{
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
TransDataVertSlideVert *svlist = sld->sv, *sv;
int i;
@ -7527,7 +7528,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
char str[MAX_INFO_LEN];
size_t ofs = 0;
float final;
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
const bool flipped = sld->flipped;
const bool use_even = sld->use_even;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
@ -8277,10 +8278,34 @@ static void initTimeSlide(TransInfo *t)
t->mode = TFM_TIME_SLIDE;
t->transform = applyTimeSlide;
t->flag |= T_FREE_CUSTOMDATA;
initMouseInputMode(t, &t->mouse, INPUT_NONE);
{
Scene *scene = t->scene;
float *range;
t->custom.mode.data = range = MEM_mallocN(sizeof(float[2]), "TimeSlide Min/Max");
t->custom.mode.use_free = true;
float min = 999999999.0f, max = -999999999.0f;
int i;
TransData *td = t->data;
for (i = 0; i < t->total; i++, td++) {
if (min > *(td->val)) min = *(td->val);
if (max < *(td->val)) max = *(td->val);
}
if (min == max) {
/* just use the current frame ranges */
min = (float)PSFRA;
max = (float)PEFRA;
}
range[0] = min;
range[1] = max;
}
/* num-input has max of (n-1) */
t->idx_max = 0;
t->num.flag = 0;
@ -8304,8 +8329,9 @@ static void headerTimeSlide(TransInfo *t, const float sval, char str[MAX_INFO_LE
outputNumInput(&(t->num), tvec, &t->scene->unit);
}
else {
float minx = *((float *)(t->customData));
float maxx = *((float *)(t->customData) + 1);
const float *range = t->custom.mode.data;
float minx = range[0];
float maxx = range[1];
float cval = t->values[0];
float val;
@ -8322,9 +8348,9 @@ static void applyTimeSlideValue(TransInfo *t, float sval)
{
TransData *td = t->data;
int i;
float minx = *((float *)(t->customData));
float maxx = *((float *)(t->customData) + 1);
const float *range = t->custom.mode.data;
float minx = range[0];
float maxx = range[1];
/* set value for drawing black line */
if (t->spacetype == SPACE_ACTION) {
@ -8369,8 +8395,9 @@ static void applyTimeSlide(TransInfo *t, const int mval[2])
{
View2D *v2d = (View2D *)t->view;
float cval[2], sval[2];
float minx = *((float *)(t->customData));
float maxx = *((float *)(t->customData) + 1);
const float *range = t->custom.mode.data;
float minx = range[0];
float maxx = range[1];
char str[MAX_INFO_LEN];
/* calculate mouse co-ordinates */

View File

@ -357,6 +357,12 @@ typedef struct MouseInput {
} virtual_mval;
} MouseInput;
typedef struct TransCustomData {
void *data;
void (*free_cb)(struct TransInfo *, struct TransCustomData *);
unsigned int use_free : 1;
} TransCustomData;
typedef struct TransInfo {
int mode; /* current mode */
int flag; /* generic flags for special behaviors */
@ -408,8 +414,22 @@ typedef struct TransInfo {
struct Object *poseobj; /* if t->flag & T_POSE, this denotes pose object */
void *customData; /* Per Transform custom data */
void (*customFree)(struct TransInfo *); /* if a special free function is needed */
/**
* Rule of thumb for choosing between mode/type:
* - If transform mode uses the data, assign to `mode`
* (typically in transform.c).
* - If conversion uses the data as an extension to the #TransData, assign to `type`
* (typically in transform_conversion.c).
*/
struct {
/* owned by the mode (grab, scale, bend... )*/
union {
TransCustomData mode, first_elem;
};
/* owned by the type (mesh, armature, nla...) */
TransCustomData type;
} custom;
#define TRANS_CUSTOM_DATA_ELEM_MAX (sizeof(((TransInfo *)NULL)->custom) / sizeof(TransCustomData))
/*************** NEW STUFF *********************/
short launch_event; /* event type used to launch transform */
@ -484,7 +504,6 @@ typedef struct TransInfo {
#define T_2D_EDIT (1 << 15)
#define T_CLIP_UV (1 << 16)
#define T_FREE_CUSTOMDATA (1 << 17)
/* auto-ik is on */
#define T_AUTOIK (1 << 18)
@ -758,11 +777,11 @@ int getTransformOrientation_ex(const struct bContext *C, float normal[3], float
int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]);
void freeEdgeSlideTempFaces(EdgeSlideData *sld);
void freeEdgeSlideVerts(TransInfo *t);
void freeEdgeSlideVerts(TransInfo *t, TransCustomData *custom_data);
void projectEdgeSlideData(TransInfo *t, bool is_final);
void freeVertSlideTempFaces(VertSlideData *sld);
void freeVertSlideVerts(TransInfo *t);
void freeVertSlideVerts(TransInfo *t, TransCustomData *custom_data);
void projectVertSlideData(TransInfo *t, bool is_final);

View File

@ -1088,7 +1088,7 @@ static void createTransPose(TransInfo *t, Object *ob)
void restoreBones(TransInfo *t)
{
bArmature *arm = t->obedit->data;
BoneInitData *bid = t->customData;
BoneInitData *bid = t->custom.type.data;
EditBone *ebo;
while (bid->bone) {
@ -1177,8 +1177,8 @@ static void createTransArmatureVerts(TransInfo *t)
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransEditBone");
if (mirror) {
t->customData = bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
t->flag |= T_FREE_CUSTOMDATA;
t->custom.type.data = bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
t->custom.type.use_free = true;
}
i = 0;
@ -3087,9 +3087,8 @@ static void createTransNlaData(bContext *C, TransInfo *t)
t->data = MEM_callocN(t->total * sizeof(TransData), "TransData(NLA Editor)");
td = t->data;
t->customData = MEM_callocN(t->total * sizeof(TransDataNla), "TransDataNla (NLA Editor)");
tdn = t->customData;
t->flag |= T_FREE_CUSTOMDATA;
t->custom.type.data = tdn = MEM_callocN(t->total * sizeof(TransDataNla), "TransDataNla (NLA Editor)");
t->custom.type.use_free = true;
/* loop 2: build transdata array */
for (ale = anim_data.first; ale; ale = ale->next) {
@ -3550,15 +3549,9 @@ typedef struct tGPFtransdata {
/* This function helps flush transdata written to tempdata into the gp-frames */
void flushTransIntFrameActionData(TransInfo *t)
{
tGPFtransdata *tfd;
tGPFtransdata *tfd = t->custom.type.data;
int i;
/* find the first one to start from */
if (t->mode == TFM_TIME_SLIDE)
tfd = (tGPFtransdata *)((float *)(t->customData) + 2);
else
tfd = (tGPFtransdata *)(t->customData);
/* flush data! */
for (i = 0; i < t->total; i++, tfd++) {
*(tfd->sdata) = iroundf(tfd->val);
@ -3726,20 +3719,8 @@ static void createTransActionData(bContext *C, TransInfo *t)
td2d = t->data2d;
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
if (t->mode == TFM_TIME_SLIDE) {
t->customData = MEM_callocN((sizeof(float) * 2) + (sizeof(tGPFtransdata) * count), "TimeSlide + tGPFtransdata");
t->flag |= T_FREE_CUSTOMDATA;
tfd = (tGPFtransdata *)((float *)(t->customData) + 2);
}
else {
t->customData = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
t->flag |= T_FREE_CUSTOMDATA;
tfd = (tGPFtransdata *)(t->customData);
}
}
else if (t->mode == TFM_TIME_SLIDE) {
t->customData = MEM_callocN(sizeof(float) * 2, "TimeSlide Min/Max");
t->flag |= T_FREE_CUSTOMDATA;
t->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
t->custom.type.use_free = true;
}
/* loop 2: build transdata array */
@ -3781,31 +3762,6 @@ static void createTransActionData(bContext *C, TransInfo *t)
td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos);
}
}
/* check if we're supposed to be setting minx/maxx for TimeSlide */
if (t->mode == TFM_TIME_SLIDE) {
float min = 999999999.0f, max = -999999999.0f;
int i;
td = t->data;
for (i = 0; i < count; i++, td++) {
if (min > *(td->val)) min = *(td->val);
if (max < *(td->val)) max = *(td->val);
}
if (min == max) {
/* just use the current frame ranges */
min = (float)PSFRA;
max = (float)PEFRA;
}
/* minx/maxx values used by TimeSlide are stored as a
* calloced 2-float array in t->customData. This gets freed
* in postTrans (T_FREE_CUSTOMDATA).
*/
*((float *)(t->customData)) = min;
*((float *)(t->customData) + 1) = max;
}
/* calculate distances for proportional editing */
if (is_prop_edit) {
@ -4158,12 +4114,12 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
t->data = MEM_callocN(t->total * sizeof(TransData), "TransData (Graph Editor)");
/* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */
t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransData2D (Graph Editor)");
t->customData = MEM_callocN(t->total * sizeof(TransDataGraph), "TransDataGraph");
t->flag |= T_FREE_CUSTOMDATA;
t->custom.type.data = MEM_callocN(t->total * sizeof(TransDataGraph), "TransDataGraph");
t->custom.type.use_free = true;
td = t->data;
td2d = t->data2d;
tdg = t->customData;
tdg = t->custom.type.data;
/* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */
unit_m3(mtx);
@ -4565,7 +4521,7 @@ void flushTransGraphData(TransInfo *t)
int a;
/* flush to 2d vector from internally used 3d vector */
for (a = 0, td = t->data, td2d = t->data2d, tdg = t->customData;
for (a = 0, td = t->data, td2d = t->data2d, tdg = t->custom.type.data;
a < t->total;
a++, td++, td2d++, tdg++)
{
@ -4928,7 +4884,7 @@ static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
}
static void freeSeqData(TransInfo *t)
static void freeSeqData(TransInfo *t, TransCustomData *custom_data)
{
Editing *ed = BKE_sequencer_editing_get(t->scene, false);
@ -5089,11 +5045,11 @@ static void freeSeqData(TransInfo *t)
}
}
if ((t->customData != NULL) && (t->flag & T_FREE_CUSTOMDATA)) {
TransSeq *ts = t->customData;
if ((custom_data->data != NULL) && custom_data->use_free) {
TransSeq *ts = custom_data->data;
MEM_freeN(ts->tdseq);
MEM_freeN(t->customData);
t->customData = NULL;
MEM_freeN(custom_data->data);
custom_data->data = NULL;
}
if (t->data) {
MEM_freeN(t->data); // XXX postTrans usually does this
@ -5121,7 +5077,7 @@ static void createTransSeqData(bContext *C, TransInfo *t)
return;
}
t->customFree = freeSeqData;
t->custom.type.free_cb = freeSeqData;
xmouse = (int)UI_view2d_region_to_view_x(v2d, t->mouse.imval[0]);
@ -5167,11 +5123,11 @@ static void createTransSeqData(bContext *C, TransInfo *t)
return;
}
t->customData = ts = MEM_mallocN(sizeof(TransSeq), "transseq");
t->custom.type.data = ts = MEM_mallocN(sizeof(TransSeq), "transseq");
t->custom.type.use_free = true;
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransSeq TransData");
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransSeq TransData2D");
ts->tdseq = tdsq = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
t->flag |= T_FREE_CUSTOMDATA;
/* loop 2: build transdata array */
SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
@ -5956,10 +5912,13 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
if (t->obedit) {
/* Special Exception:
* We don't normally access 't->custom.mode' here, but its needed in this case. */
if (canceled == 0) {
/* we need to delete the temporary faces before automerging */
if (t->mode == TFM_EDGE_SLIDE) {
EdgeSlideData *sld = t->customData;
EdgeSlideData *sld = t->custom.mode.data;
/* handle multires re-projection, done
* on transform completion since it's
@ -5972,7 +5931,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
else if (t->mode == TFM_VERT_SLIDE) {
/* as above */
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
projectVertSlideData(t, true);
freeVertSlideTempFaces(sld);
}
@ -5983,13 +5942,13 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
else {
if (t->mode == TFM_EDGE_SLIDE) {
EdgeSlideData *sld = t->customData;
EdgeSlideData *sld = t->custom.mode.data;
sld->perc = 0.0;
projectEdgeSlideData(t, false);
}
else if (t->mode == TFM_VERT_SLIDE) {
VertSlideData *sld = t->customData;
VertSlideData *sld = t->custom.mode.data;
sld->perc = 0.0;
projectVertSlideData(t, false);
@ -6749,16 +6708,15 @@ static void planeTrackToTransData(const int framenr, TransData *td, TransData2D
}
}
static void transDataTrackingFree(TransInfo *t)
static void transDataTrackingFree(TransInfo *UNUSED(t), TransCustomData *custom_data)
{
TransDataTracking *tdt = t->customData;
if (tdt) {
if (custom_data->data) {
TransDataTracking *tdt = custom_data->data;
if (tdt->smarkers)
MEM_freeN(tdt->smarkers);
MEM_freeN(tdt);
t->customData = NULL;
custom_data->data = NULL;
}
}
@ -6810,9 +6768,9 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransTracking TransData");
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransTracking TransData2D");
tdt = t->customData = MEM_callocN(t->total * sizeof(TransDataTracking), "TransTracking TransDataTracking");
tdt = t->custom.type.data = MEM_callocN(t->total * sizeof(TransDataTracking), "TransTracking TransDataTracking");
t->customFree = transDataTrackingFree;
t->custom.type.free_cb = transDataTrackingFree;
/* create actual data */
track = tracksbase->first;
@ -6947,9 +6905,8 @@ static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransTracking TransData");
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransTracking TransData2D");
tdt = t->customData = MEM_callocN(t->total * sizeof(TransDataTracking), "TransTracking TransDataTracking");
t->customFree = transDataTrackingFree;
t->custom.type.data = tdt = MEM_callocN(t->total * sizeof(TransDataTracking), "TransTracking TransDataTracking");
t->custom.type.free_cb = transDataTrackingFree;
/* create actual data */
track = tracksbase->first;
@ -7013,10 +6970,11 @@ static void cancelTransTracking(TransInfo *t)
{
SpaceClip *sc = t->sa->spacedata.first;
int i, framenr = ED_space_clip_get_clip_frame_number(sc);
TransDataTracking *tdt_array = t->custom.type.data;
i = 0;
while (i < t->total) {
TransDataTracking *tdt = (TransDataTracking *) t->customData + i;
TransDataTracking *tdt = &tdt_array[i];
if (tdt->mode == transDataTracking_ModeTracks) {
MovieTrackingTrack *track = tdt->track;
@ -7073,7 +7031,7 @@ void flushTransTracking(TransInfo *t)
cancelTransTracking(t);
/* flush to 2d vector from internally used 3d vector */
for (a = 0, td = t->data, td2d = t->data2d, tdt = t->customData; a < t->total; a++, td2d++, td++, tdt++) {
for (a = 0, td = t->data, td2d = t->data2d, tdt = t->custom.type.data; a < t->total; a++, td2d++, td++, tdt++) {
if (tdt->mode == transDataTracking_ModeTracks) {
float loc2d[2];
@ -7404,9 +7362,8 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
/* for each 2d uv coord a 3d vector is allocated, so that they can be
* treated just as if they were 3d verts */
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransObData2D(Mask Editing)");
tdm = t->customData = MEM_callocN(t->total * sizeof(TransDataMasking), "TransDataMasking(Mask Editing)");
t->flag |= T_FREE_CUSTOMDATA;
t->custom.type.data = tdm = MEM_callocN(t->total * sizeof(TransDataMasking), "TransDataMasking(Mask Editing)");
t->custom.type.use_free = true;
/* create data */
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
@ -7468,7 +7425,7 @@ void flushTransMasking(TransInfo *t)
inv[1] = 1.0f / asp[1];
/* flush to 2d vector from internally used 3d vector */
for (a = 0, td = t->data2d, tdm = t->customData; a < t->total; a++, td++, tdm++) {
for (a = 0, td = t->data2d, tdm = t->custom.type.data; a < t->total; a++, td++, tdm++) {
td->loc2d[0] = td->loc[0] * inv[0];
td->loc2d[1] = td->loc[1] * inv[1];
mul_m3_v2(tdm->parent_inverse_matrix, td->loc2d);
@ -7616,8 +7573,8 @@ static void createTransPaintCurveVerts(bContext *C, TransInfo *t)
t->total = total;
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransData2D");
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransData");
tdpc = t->customData = MEM_callocN(t->total * sizeof(TransDataPaintCurve), "TransDataPaintCurve");
t->flag |= T_FREE_CUSTOMDATA;
t->custom.type.data = tdpc = MEM_callocN(t->total * sizeof(TransDataPaintCurve), "TransDataPaintCurve");
t->custom.type.use_free = true;
for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
if (PC_IS_ANY_SEL(pcp)) {
@ -7649,7 +7606,7 @@ void flushTransPaintCurve(TransInfo *t)
{
int i;
TransData2D *td2d = t->data2d;
TransDataPaintCurve *tdpc = (TransDataPaintCurve *)t->customData;
TransDataPaintCurve *tdpc = t->custom.type.data;
for (i = 0; i < t->total; i++, tdpc++, td2d++) {
PaintCurvePoint *pcp = tdpc->pcp;

View File

@ -422,7 +422,7 @@ static void recalcData_graphedit(TransInfo *t)
/* helper for recalcData() - for NLA Editor transforms */
static void recalcData_nla(TransInfo *t)
{
TransDataNla *tdn = (TransDataNla *)t->customData;
TransDataNla *tdn = t->custom.type.data;
SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
Scene *scene = t->scene;
double secf = FPS;
@ -1055,10 +1055,10 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
void resetTransModal(TransInfo *t)
{
if (t->mode == TFM_EDGE_SLIDE) {
freeEdgeSlideVerts(t);
freeEdgeSlideVerts(t, &t->custom.mode);
}
else if (t->mode == TFM_VERT_SLIDE) {
freeVertSlideVerts(t);
freeVertSlideVerts(t, &t->custom.mode);
}
}
@ -1441,14 +1441,20 @@ void postTrans(bContext *C, TransInfo *t)
if (t->draw_handle_cursor)
WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
if (t->customFree) {
/* Can take over freeing t->data and data2d etc... */
t->customFree(t);
BLI_assert(t->customData == NULL);
}
else if ((t->customData != NULL) && (t->flag & T_FREE_CUSTOMDATA)) {
MEM_freeN(t->customData);
t->customData = NULL;
/* Free all custom-data */
{
TransCustomData *custom_data = &t->custom.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 data2d etc... */
custom_data->free_cb(t, 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;
}
}
}
/* postTrans can be called when nothing is selected, so data is NULL already */

View File

@ -2528,7 +2528,7 @@ void snapSequenceBounds(TransInfo *t, const int mval[2])
float xmouse, ymouse;
int frame;
int mframe;
TransSeq *ts = t->customData;
TransSeq *ts = t->custom.type.data;
/* reuse increment, strictly speaking could be another snap mode, but leave as is */
if (!(t->modifiers & MOD_SNAP_INVERT))
return;