/* this makes sure we can extend for non-cyclic. * * returns OK: 1/0 */ static bool where_on_path_deform( Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius) { BevList *bl; float ctime1; int cycl = 0; /* test for cyclic */ bl = ob->runtime.curve_cache->bev.first; if (!bl->nr) { return false; } if (bl->poly > -1) { cycl = 1; } if (cycl == 0) { ctime1 = CLAMPIS(ctime, 0.0f, 1.0f); } else { ctime1 = ctime; } /* vec needs 4 items */ if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) { if (cycl == 0) { Path *path = ob->runtime.curve_cache->path; float dvec[3]; if (ctime < 0.0f) { sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec); mul_v3_fl(dvec, ctime * (float)path->len); add_v3_v3(vec, dvec); if (quat) { copy_qt_qt(quat, path->data[0].quat); } if (radius) { *radius = path->data[0].radius; } } else if (ctime > 1.0f) { sub_v3_v3v3(dvec, path->data[path->len - 1].vec, path->data[path->len - 2].vec); mul_v3_fl(dvec, (ctime - 1.0f) * (float)path->len); add_v3_v3(vec, dvec); if (quat) { copy_qt_qt(quat, path->data[path->len - 1].quat); } if (radius) { *radius = path->data[path->len - 1].radius; } /* weight - not used but could be added */ } } return true; } return false; }
/* this makes sure we can extend for non-cyclic. *vec needs 4 items! */ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius) /* returns OK */ { Curve *cu= ob->data; BevList *bl; float ctime1; int cycl=0; /* test for cyclic */ bl= cu->bev.first; if (!bl->nr) return 0; if(bl && bl->poly> -1) cycl= 1; if(cycl==0) { ctime1= CLAMPIS(ctime, 0.0f, 1.0f); } else ctime1= ctime; /* vec needs 4 items */ if(where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) { if(cycl==0) { Path *path= cu->path; float dvec[3]; if(ctime < 0.0f) { sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec); mul_v3_fl(dvec, ctime*(float)path->len); add_v3_v3(vec, dvec); if(quat) copy_qt_qt(quat, path->data[0].quat); if(radius) *radius= path->data[0].radius; } else if(ctime > 1.0f) { sub_v3_v3v3(dvec, path->data[path->len-1].vec, path->data[path->len-2].vec); mul_v3_fl(dvec, (ctime-1.0f)*(float)path->len); add_v3_v3(vec, dvec); if(quat) copy_qt_qt(quat, path->data[path->len-1].quat); if(radius) *radius= path->data[path->len-1].radius; /* weight - not used but could be added */ } } return 1; } return 0; }
static void precalculate_effector(EffectorCache *eff) { unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra); if (!eff->pd->rng) eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra); else BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra); if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) { Curve *cu= eff->ob->data; if (cu->flag & CU_PATH) { if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL) BKE_displist_make_curveTypes(eff->scene, eff->ob, 0); if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) { where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL); mul_m4_v3(eff->ob->obmat, eff->guide_loc); mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir); } } } else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) { eff->surmd = (SurfaceModifierData *)modifiers_findByType( eff->ob, eModifierType_Surface ); if (eff->ob->type == OB_CURVE) eff->flag |= PE_USE_NORMAL_DATA; } else if (eff->psys) psys_update_particle_tree(eff->psys, eff->scene->r.cfra); /* Store object velocity */ if (eff->ob) { float old_vel[3]; BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f); copy_v3_v3(old_vel, eff->ob->obmat[3]); BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra); sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel); } }
/* Evaluate spline IK for a given bone */ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, int index, float ctime) { bSplineIKConstraint *ikData = tree->ikData; float poseHead[3], poseTail[3], poseMat[4][4]; float splineVec[3], scaleFac, radius = 1.0f; /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */ BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); copy_v3_v3(poseHead, pchan->pose_head); copy_v3_v3(poseTail, pchan->pose_tail); /* step 1: determine the positions for the endpoints of the bone */ { float vec[4], dir[3], rad; float tailBlendFac = 1.0f; /* determine if the bone should still be affected by SplineIK */ if (tree->points[index + 1] >= 1.0f) { /* spline doesn't affect the bone anymore, so done... */ pchan->flag |= POSE_DONE; return; } else if ((tree->points[index] >= 1.0f) && (tree->points[index + 1] < 1.0f)) { /* blending factor depends on the amount of the bone still left on the chain */ tailBlendFac = (1.0f - tree->points[index + 1]) / (tree->points[index] - tree->points[index + 1]); } /* tail endpoint */ if (where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad, NULL)) { /* apply curve's object-mode transforms to the position * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) */ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) mul_m4_v3(ikData->tar->obmat, vec); /* convert the position to pose-space, then store it */ mul_m4_v3(ob->imat, vec); interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac); /* set the new radius */ radius = rad; } /* head endpoint */ if (where_on_path(ikData->tar, tree->points[index + 1], vec, dir, NULL, &rad, NULL)) { /* apply curve's object-mode transforms to the position * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) */ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) mul_m4_v3(ikData->tar->obmat, vec); /* store the position, and convert it to pose space */ mul_m4_v3(ob->imat, vec); copy_v3_v3(poseHead, vec); /* set the new radius (it should be the average value) */ radius = (radius + rad) / 2; } } /* step 2: determine the implied transform from these endpoints * - splineVec: the vector direction that the spline applies on the bone * - scaleFac: the factor that the bone length is scaled by to get the desired amount */ sub_v3_v3v3(splineVec, poseTail, poseHead); scaleFac = len_v3(splineVec) / pchan->bone->length; /* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis * - this uses the same method as is used for the Damped Track Constraint (see the code there for details) */ { float dmat[3][3], rmat[3][3], tmat[3][3]; float raxis[3], rangle; /* compute the raw rotation matrix from the bone's current matrix by extracting only the * orientation-relevant axes, and normalizing them */ copy_v3_v3(rmat[0], pchan->pose_mat[0]); copy_v3_v3(rmat[1], pchan->pose_mat[1]); copy_v3_v3(rmat[2], pchan->pose_mat[2]); normalize_m3(rmat); /* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */ normalize_v3(splineVec); /* calculate smallest axis-angle rotation necessary for getting from the * current orientation of the bone, to the spline-imposed direction */ cross_v3_v3v3(raxis, rmat[1], splineVec); rangle = dot_v3v3(rmat[1], splineVec); CLAMP(rangle, -1.0f, 1.0f); rangle = acosf(rangle); /* multiply the magnitude of the angle by the influence of the constraint to * control the influence of the SplineIK effect */ rangle *= tree->con->enforce; /* construct rotation matrix from the axis-angle rotation found above * - this call takes care to make sure that the axis provided is a unit vector first */ axis_angle_to_mat3(dmat, raxis, rangle); /* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates, * while still maintaining roll control from the existing bone animation */ mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */ normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */ copy_m4_m3(poseMat, tmat); } /* step 4: set the scaling factors for the axes */ { /* only multiply the y-axis by the scaling factor to get nice volume-preservation */ mul_v3_fl(poseMat[1], scaleFac); /* set the scaling factors of the x and z axes from... */ switch (ikData->xzScaleMode) { case CONSTRAINT_SPLINEIK_XZS_ORIGINAL: { /* original scales get used */ float scale; /* x-axis scale */ scale = len_v3(pchan->pose_mat[0]); mul_v3_fl(poseMat[0], scale); /* z-axis scale */ scale = len_v3(pchan->pose_mat[2]); mul_v3_fl(poseMat[2], scale); break; } case CONSTRAINT_SPLINEIK_XZS_INVERSE: { /* old 'volume preservation' method using the inverse scale */ float scale; /* calculate volume preservation factor which is * basically the inverse of the y-scaling factor */ if (fabsf(scaleFac) != 0.0f) { scale = 1.0f / fabsf(scaleFac); /* we need to clamp this within sensible values */ /* NOTE: these should be fine for now, but should get sanitised in future */ CLAMP(scale, 0.0001f, 100000.0f); } else scale = 1.0f; /* apply the scaling */ mul_v3_fl(poseMat[0], scale); mul_v3_fl(poseMat[2], scale); break; } case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC: { /* improved volume preservation based on the Stretch To constraint */ float final_scale; /* as the basis for volume preservation, we use the inverse scale factor... */ if (fabsf(scaleFac) != 0.0f) { /* NOTE: The method here is taken wholesale from the Stretch To constraint */ float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge); if (bulge > 1.0f) { if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) { float bulge_max = max_ff(ikData->bulge_max, 1.0f); float hard = min_ff(bulge, bulge_max); float range = bulge_max - 1.0f; float scale = (range > 0.0f) ? 1.0f / range : 0.0f; float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2; bulge = interpf(soft, hard, ikData->bulge_smooth); } } if (bulge < 1.0f) { if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) { float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f); float hard = max_ff(bulge, bulge_min); float range = 1.0f - bulge_min; float scale = (range > 0.0f) ? 1.0f / range : 0.0f; float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2; bulge = interpf(soft, hard, ikData->bulge_smooth); } } /* compute scale factor for xz axes from this value */ final_scale = sqrtf(bulge); } else { /* no scaling, so scale factor is simple */ final_scale = 1.0f; } /* apply the scaling (assuming normalised scale) */ mul_v3_fl(poseMat[0], final_scale); mul_v3_fl(poseMat[2], final_scale); break; } } /* finally, multiply the x and z scaling by the radius of the curve too, * to allow automatic scales to get tweaked still */ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { mul_v3_fl(poseMat[0], radius); mul_v3_fl(poseMat[2], radius); } } /* step 5: set the location of the bone in the matrix */ if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) { /* when the 'no-root' option is affected, the chain can retain * the shape but be moved elsewhere */ copy_v3_v3(poseHead, pchan->pose_head); } else if (tree->con->enforce < 1.0f) { /* when the influence is too low * - blend the positions for the 'root' bone * - stick to the parent for any other */ if (pchan->parent) { copy_v3_v3(poseHead, pchan->pose_head); } else { /* FIXME: this introduces popping artifacts when we reach 0.0 */ interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce); } } copy_v3_v3(poseMat[3], poseHead); /* finally, store the new transform */ copy_m4_m4(pchan->pose_mat, poseMat); copy_v3_v3(pchan->pose_head, poseHead); /* recalculate tail, as it's now outdated after the head gets adjusted above! */ BKE_pose_where_is_bone_tail(pchan); /* done! */ pchan->flag |= POSE_DONE; }
/* added "sizecorr" here, to allow armatures to be scaled and still have striding. Only works for uniform scaling. In general I'd advise against scaling armatures ever though! (ton) */ static float stridechannel_frame(Object *ob, float sizecorr, bActionStrip *strip, Path *path, float pathdist, float *stride_offset) { bAction *act= strip->act; const char *name= strip->stridechannel; bActionChannel *achan= get_action_channel(act, name); int stride_axis= strip->stride_axis; if(achan && achan->ipo) { IpoCurve *icu= NULL; float minx=0.0f, maxx=0.0f, miny=0.0f, maxy=0.0f; int foundvert= 0; if(stride_axis==0) stride_axis= AC_LOC_X; else if(stride_axis==1) stride_axis= AC_LOC_Y; else stride_axis= AC_LOC_Z; /* calculate the min/max */ for (icu=achan->ipo->curve.first; icu; icu=icu->next) { if(icu->adrcode==stride_axis) { if(icu->totvert>1) { foundvert= 1; minx= icu->bezt[0].vec[1][0]; maxx= icu->bezt[icu->totvert-1].vec[1][0]; miny= icu->bezt[0].vec[1][1]; maxy= icu->bezt[icu->totvert-1].vec[1][1]; } break; } } if(foundvert && miny!=maxy) { float stridelen= sizecorr*fabs(maxy-miny), striptime; float actiondist, pdist, pdistNewNormalized, offs; float vec1[4], vec2[4], dir[3]; /* internal cycling, actoffs is in frames */ offs= stridelen*strip->actoffs/(maxx-minx); /* amount path moves object */ pdist = (float)fmod (pathdist+offs, stridelen); striptime= pdist/stridelen; /* amount stride bone moves */ actiondist= sizecorr*eval_icu(icu, minx + striptime*(maxx-minx)) - miny; pdist = fabs(actiondist) - pdist; pdistNewNormalized = (pathdist+pdist)/path->totdist; /* now we need to go pdist further (or less) on cu path */ where_on_path(ob, (pathdist)/path->totdist, vec1, dir); /* vec needs size 4 */ if (pdistNewNormalized <= 1) { // search for correction in positive path-direction where_on_path(ob, pdistNewNormalized, vec2, dir); /* vec needs size 4 */ sub_v3_v3v3(stride_offset, vec2, vec1); } else { // we reached the end of the path, search backwards instead where_on_path(ob, (pathdist-pdist)/path->totdist, vec2, dir); /* vec needs size 4 */ sub_v3_v3v3(stride_offset, vec1, vec2); } mul_mat3_m4_v3(ob->obmat, stride_offset); return striptime; } } return 0.0f; }
struct chartrans *BKE_text_to_curve(Main *bmain, Scene *scene, Object *ob, int mode) { VFont *vfont, *oldvfont; VFontData *vfd= NULL; Curve *cu; CharInfo *info = NULL, *custrinfo; TextBox *tb; VChar *che; struct chartrans *chartransdata=NULL, *ct; float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4; float twidth, maxlen= 0; int i, slen, j; int curbox; int selstart, selend; int utf8len; short cnr=0, lnr=0, wsnr= 0; wchar_t *mem, *tmp, ascii; /* renark: do calculations including the trailing '\0' of a string * because the cursor can be at that location */ if (ob->type!=OB_FONT) return NULL; // Set font data cu= (Curve *) ob->data; vfont= cu->vfont; if (cu->str == NULL) return NULL; if (vfont == NULL) return NULL; // Create unicode string utf8len = BLI_strlen_utf8(cu->str); mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem"); BLI_strncpy_wchar_from_utf8(mem, cu->str, utf8len + 1); // Count the wchar_t string length slen = wcslen(mem); if (cu->ulheight == 0.0f) cu->ulheight = 0.05f; if (cu->strinfo==NULL) /* old file */ cu->strinfo = MEM_callocN((slen+4) * sizeof(CharInfo), "strinfo compat"); custrinfo= cu->strinfo; if (cu->editfont) custrinfo= cu->editfont->textbufinfo; if (cu->tb==NULL) cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBox compat"); vfd= vfont_get_data(bmain, vfont); /* The VFont Data can not be found */ if (!vfd) { if (mem) MEM_freeN(mem); return NULL; } /* calc offset and rotation of each char */ ct = chartransdata = (struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext"); /* We assume the worst case: 1 character per line (is freed at end anyway) */ linedata= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext2"); linedata2= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext3"); linedata3= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext4"); linedata4= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext5"); linedist= cu->linedist; xof= cu->xof + (cu->tb[0].x/cu->fsize); yof= cu->yof + (cu->tb[0].y/cu->fsize); xtrax= 0.5f*cu->spacing-0.5f; oldvfont = NULL; for (i=0; i<slen; i++) custrinfo[i].flag &= ~(CU_CHINFO_WRAP|CU_CHINFO_SMALLCAPS_CHECK); if (cu->selboxes) MEM_freeN(cu->selboxes); cu->selboxes = NULL; if (BKE_font_getselection(ob, &selstart, &selend)) cu->selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes"); tb = &(cu->tb[0]); curbox= 0; for (i = 0 ; i<=slen ; i++) { makebreak: // Characters in the list info = &(custrinfo[i]); ascii = mem[i]; if (info->flag & CU_CHINFO_SMALLCAPS) { ascii = towupper(ascii); if (mem[i] != ascii) { mem[i]= ascii; info->flag |= CU_CHINFO_SMALLCAPS_CHECK; } } vfont = which_vfont(cu, info); if (vfont==NULL) break; che= find_vfont_char(vfd, ascii); /* * The character wasn't in the current curve base so load it * But if the font is FO_BUILTIN_NAME then do not try loading since * whole font is in the memory already */ if (che == NULL && strcmp(vfont->name, FO_BUILTIN_NAME)) { BLI_vfontchar_from_freetypefont(vfont, ascii); } /* Try getting the character again from the list */ che= find_vfont_char(vfd, ascii); /* No VFont found */ if (vfont==NULL) { if (mem) MEM_freeN(mem); MEM_freeN(chartransdata); return NULL; } if (vfont != oldvfont) { vfd= vfont_get_data(bmain, vfont); oldvfont = vfont; } /* VFont Data for VFont couldn't be found */ if (!vfd) { if (mem) MEM_freeN(mem); MEM_freeN(chartransdata); return NULL; } twidth = char_width(cu, che, info); // Calculate positions if ((tb->w != 0.0f) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w + cu->xof*cu->fsize) { // fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]); for (j=i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak==0); j--) { if (mem[j]==' ' || mem[j]=='-') { ct -= (i-(j-1)); cnr -= (i-(j-1)); if (mem[j] == ' ') wsnr--; if (mem[j] == '-') wsnr++; i = j-1; xof = ct->xof; ct[1].dobreak = 1; custrinfo[i+1].flag |= CU_CHINFO_WRAP; goto makebreak; } if (chartransdata[j].dobreak) { // fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]); ct->dobreak= 1; custrinfo[i+1].flag |= CU_CHINFO_WRAP; ct -= 1; cnr -= 1; i--; xof = ct->xof; goto makebreak; } } } if (ascii== '\n' || ascii== '\r' || ascii==0 || ct->dobreak) { ct->xof= xof; ct->yof= yof; ct->linenr= lnr; ct->charnr= cnr; yof-= linedist; maxlen= MAX2(maxlen, (xof-tb->x/cu->fsize)); linedata[lnr]= xof-tb->x/cu->fsize; linedata2[lnr]= cnr; linedata3[lnr]= tb->w/cu->fsize; linedata4[lnr]= wsnr; if ( (tb->h != 0.0f) && ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize)) - cu->yof) && (cu->totbox > (curbox+1)) ) { maxlen= 0; tb++; curbox++; yof= cu->yof + tb->y/cu->fsize; } /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */ #if 0 if (ascii == '\n' || ascii == '\r') xof = cu->xof; else xof= cu->xof + (tb->x/cu->fsize); #else xof= cu->xof + (tb->x/cu->fsize); #endif lnr++; cnr= 0; wsnr= 0; } else if (ascii==9) { /* TAB */ float tabfac; ct->xof= xof; ct->yof= yof; ct->linenr= lnr; ct->charnr= cnr++; tabfac= (xof-cu->xof+0.01f); tabfac= 2.0f*ceilf(tabfac/2.0f); xof= cu->xof+tabfac; } else { SelBox *sb= NULL; float wsfac; ct->xof= xof; ct->yof= yof; ct->linenr= lnr; ct->charnr= cnr++; if (cu->selboxes && (i>=selstart) && (i<=selend)) { sb = &(cu->selboxes[i-selstart]); sb->y = yof*cu->fsize-linedist*cu->fsize*0.1f; sb->h = linedist*cu->fsize; sb->w = xof*cu->fsize; } if (ascii==32) { wsfac = cu->wordspace; wsnr++; } else wsfac = 1.0f; // Set the width of the character twidth = char_width(cu, che, info); xof += (twidth*wsfac*(1.0f+(info->kern/40.0f)) ) + xtrax; if (sb) sb->w = (xof*cu->fsize) - sb->w; } ct++; } cu->lines= 1; ct= chartransdata; tmp = mem; for (i= 0; i<=slen; i++, tmp++, ct++) { ascii = *tmp; if (ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++; } // linedata is now: width of line // linedata2 is now: number of characters // linedata3 is now: maxlen of that line // linedata4 is now: number of whitespaces of line if (cu->spacemode!=CU_LEFT) { ct= chartransdata; if (cu->spacemode==CU_RIGHT) { for (i=0;i<lnr;i++) linedata[i]= linedata3[i]-linedata[i]; for (i=0; i<=slen; i++) { ct->xof+= linedata[ct->linenr]; ct++; } } else if (cu->spacemode==CU_MIDDLE) { for (i=0;i<lnr;i++) linedata[i]= (linedata3[i]-linedata[i])/2; for (i=0; i<=slen; i++) { ct->xof+= linedata[ct->linenr]; ct++; } } else if ((cu->spacemode==CU_FLUSH) && (cu->tb[0].w != 0.0f)) { for (i=0;i<lnr;i++) if (linedata2[i]>1) linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1); for (i=0; i<=slen; i++) { for (j=i; (!ELEM3(mem[j], '\0', '\n', '\r')) && (chartransdata[j].dobreak == 0) && (j < slen); j++) { /* do nothing */ } // if ((mem[j]!='\r') && (mem[j]!='\n') && (mem[j])) { ct->xof+= ct->charnr*linedata[ct->linenr]; // } ct++; } } else if ((cu->spacemode==CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) { float curofs= 0.0f; for (i=0; i<=slen; i++) { for (j=i; (mem[j]) && (mem[j]!='\n') && (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++); if ((mem[j]!='\r') && (mem[j]!='\n') && ((chartransdata[j].dobreak!=0))) { if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr]; ct->xof+= curofs; } if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0; ct++; } } } /* TEXT ON CURVE */ /* Note: Only OB_CURVE objects could have a path */ if (cu->textoncurve && cu->textoncurve->type==OB_CURVE) { Curve *cucu= cu->textoncurve->data; int oldflag= cucu->flag; cucu->flag |= (CU_PATH+CU_FOLLOW); if (cucu->path==NULL) makeDispListCurveTypes(scene, cu->textoncurve, 0); if (cucu->path) { float distfac, imat[4][4], imat3[3][3], cmat[3][3]; float minx, maxx, miny, maxy; float timeofs, sizefac; invert_m4_m4(imat, ob->obmat); copy_m3_m4(imat3, imat); copy_m3_m4(cmat, cu->textoncurve->obmat); mul_m3_m3m3(cmat, cmat, imat3); sizefac= normalize_v3(cmat[0])/cu->fsize; minx=miny= 1.0e20f; maxx=maxy= -1.0e20f; ct= chartransdata; for (i=0; i<=slen; i++, ct++) { if (minx>ct->xof) minx= ct->xof; if (maxx<ct->xof) maxx= ct->xof; if (miny>ct->yof) miny= ct->yof; if (maxy<ct->yof) maxy= ct->yof; } /* we put the x-coordinaat exact at the curve, the y is rotated */ /* length correction */ distfac= sizefac*cucu->path->totdist/(maxx-minx); timeofs= 0.0f; if (distfac > 1.0f) { /* path longer than text: spacemode involves */ distfac= 1.0f/distfac; if (cu->spacemode==CU_RIGHT) { timeofs= 1.0f-distfac; } else if (cu->spacemode==CU_MIDDLE) { timeofs= (1.0f-distfac)/2.0f; } else if (cu->spacemode==CU_FLUSH) distfac= 1.0f; } else distfac= 1.0; distfac/= (maxx-minx); timeofs+= distfac*cu->xof; /* not cyclic */ ct= chartransdata; for (i=0; i<=slen; i++, ct++) { float ctime, dtime, vec[4], tvec[4], rotvec[3]; float si, co; /* rotate around center character */ ascii = mem[i]; che= find_vfont_char(vfd, ascii); twidth = char_width(cu, che, info); dtime= distfac*0.5f*twidth; ctime= timeofs + distfac*( ct->xof - minx); CLAMP(ctime, 0.0f, 1.0f); /* calc the right loc AND the right rot separately */ /* vec, tvec need 4 items */ where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL); where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL, NULL); mul_v3_fl(vec, sizefac); ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0])); si= (float)sin(ct->rot); co= (float)cos(ct->rot); yof= ct->yof; ct->xof= vec[0] + si*yof; ct->yof= vec[1] + co*yof; } cucu->flag= oldflag; } } if (cu->selboxes) { ct= chartransdata; for (i=0; i<=selend; i++, ct++) { if (i>=selstart) { cu->selboxes[i-selstart].x = ct->xof*cu->fsize; cu->selboxes[i-selstart].y = ct->yof*cu->fsize; } } } if (mode==FO_CURSUP || mode==FO_CURSDOWN || mode==FO_PAGEUP || mode==FO_PAGEDOWN) { /* 2: curs up * 3: curs down */ ct= chartransdata+cu->pos; if ((mode==FO_CURSUP || mode==FO_PAGEUP) && ct->linenr==0); else if ((mode==FO_CURSDOWN || mode==FO_PAGEDOWN) && ct->linenr==lnr); else { switch(mode) { case FO_CURSUP: lnr= ct->linenr-1; break; case FO_CURSDOWN: lnr= ct->linenr+1; break; case FO_PAGEUP: lnr= ct->linenr-10; break; case FO_PAGEDOWN: lnr= ct->linenr+10; break; } cnr= ct->charnr; /* seek for char with lnr en cnr */ cu->pos= 0; ct= chartransdata; for (i= 0; i<slen; i++) { if (ct->linenr==lnr) { if (ct->charnr==cnr) break; if ( (ct+1)->charnr==0) break; } else if (ct->linenr>lnr) break; cu->pos++; ct++; } } } /* cursor first */ if (cu->editfont) { float si, co; ct= chartransdata+cu->pos; si= (float)sin(ct->rot); co= (float)cos(ct->rot); f= cu->editfont->textcurs[0]; f[0]= cu->fsize*(-0.1f*co + ct->xof); f[1]= cu->fsize*(0.1f*si + ct->yof); f[2]= cu->fsize*(0.1f*co + ct->xof); f[3]= cu->fsize*(-0.1f*si + ct->yof); f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof); f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof); f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof); f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof); } MEM_freeN(linedata); MEM_freeN(linedata2); MEM_freeN(linedata3); MEM_freeN(linedata4); if (mode == FO_SELCHANGE) { MEM_freeN(chartransdata); MEM_freeN(mem); return NULL; } if (mode == FO_EDIT) { /* make nurbdata */ freeNurblist(&cu->nurb); ct= chartransdata; if (cu->sepchar==0) { for (i= 0; i<slen; i++) { unsigned long cha = (uintptr_t) mem[i]; info = &(custrinfo[i]); if (info->mat_nr > (ob->totcol)) { /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */ info->mat_nr = 0; } // We do not want to see any character for \n or \r if (cha != '\n' && cha != '\r') buildchar(bmain, cu, cha, info, ct->xof, ct->yof, ct->rot, i); if ((info->flag & CU_CHINFO_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) { float ulwidth, uloverlap= 0.0f; if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') && ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_CHINFO_UNDERLINE)) && ((custrinfo[i+1].flag & CU_CHINFO_WRAP)==0) ) { uloverlap = xtrax + 0.1f; } // Find the character, the characters has to be in the memory already // since character checking has been done earlier already. che= find_vfont_char(vfd, cha); twidth = char_width(cu, che, info); ulwidth = cu->fsize * ((twidth* (1.0f+(info->kern/40.0f)))+uloverlap); build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05f)*cu->fsize, ct->xof*cu->fsize + ulwidth, ct->yof*cu->fsize + (cu->ulpos-0.05f)*cu->fsize - cu->ulheight*cu->fsize, i, info->mat_nr); } ct++; } } else { int outta = 0; for (i= 0; (i<slen) && (outta==0); i++) { ascii = mem[i]; info = &(custrinfo[i]); if (cu->sepchar == (i+1)) { float vecyo[3]; vecyo[0]= ct->xof; vecyo[1]= ct->yof; vecyo[2]= 0.0f; mem[0] = ascii; mem[1] = 0; custrinfo[0]= *info; cu->pos = 1; cu->len = 1; mul_v3_m4v3(ob->loc, ob->obmat, vecyo); outta = 1; cu->sepchar = 0; } ct++; } } } if (mode==FO_DUPLI) { MEM_freeN(mem); return chartransdata; } if (mem) MEM_freeN(mem); MEM_freeN(chartransdata); return NULL; }