int join_mesh_exec(bContext *C, wmOperator *op) { Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_active_object(C); Material **matar, *ma; Mesh *me; MVert *mvert, *mv; MEdge *medge = NULL; MFace *mface = NULL; Key *key, *nkey=NULL; KeyBlock *kb, *okb, *kbn; float imat[4][4], cmat[4][4], *fp1, *fp2, curpos; int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0; int vertofs, *matmap=NULL; int i, j, index, haskey=0, edgeofs, faceofs; bDeformGroup *dg, *odg; MDeformVert *dvert; CustomData vdata, edata, fdata; if(scene->obedit) { BKE_report(op->reports, RPT_WARNING, "Cant join while in editmode"); return OPERATOR_CANCELLED; } /* ob is the object we are adding geometry to */ if(!ob || ob->type!=OB_MESH) { BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh"); return OPERATOR_CANCELLED; } /* count & check */ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { if(base->object->type==OB_MESH) { me= base->object->data; totvert+= me->totvert; totedge+= me->totedge; totface+= me->totface; totmat+= base->object->totcol; if(base->object == ob) ok= 1; /* check for shapekeys */ if(me->key) haskey++; } } CTX_DATA_END; /* that way the active object is always selected */ if(ok==0) { BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh"); return OPERATOR_CANCELLED; } /* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */ me= (Mesh *)ob->data; key= me->key; if(totvert==0 || totvert==me->totvert) { BKE_report(op->reports, RPT_WARNING, "No mesh data to join"); return OPERATOR_CANCELLED; } if(totvert > MESH_MAX_VERTS) { BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is " STRINGIFY(MESH_MAX_VERTS), totvert); return OPERATOR_CANCELLED; } /* new material indices and material array */ matar= MEM_callocN(sizeof(void*)*totmat, "join_mesh matar"); if (totmat) matmap= MEM_callocN(sizeof(int)*totmat, "join_mesh matmap"); totcol= ob->totcol; /* obact materials in new main array, is nicer start! */ for(a=0; a<ob->totcol; a++) { matar[a]= give_current_material(ob, a+1); id_us_plus((ID *)matar[a]); /* increase id->us : will be lowered later */ } /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders * with arrays that are large enough to hold shapekey data for all meshes * - if destination mesh didn't have shapekeys, but we encountered some in the meshes we're * joining, set up a new keyblock and assign to the mesh */ if(key) { /* make a duplicate copy that will only be used here... (must remember to free it!) */ nkey= copy_key(key); /* for all keys in old block, clear data-arrays */ for(kb= key->block.first; kb; kb= kb->next) { if(kb->data) MEM_freeN(kb->data); kb->data= MEM_callocN(sizeof(float)*3*totvert, "join_shapekey"); kb->totelem= totvert; kb->weights= NULL; } } else if(haskey) { /* add a new key-block and add to the mesh */ key= me->key= add_key((ID *)me); key->type = KEY_RELATIVE; } /* first pass over objects - copying materials and vertexgroups across */ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { /* only act if a mesh, and not the one we're joining to */ if((ob!=base->object) && (base->object->type==OB_MESH)) { me= base->object->data; /* Join this object's vertex groups to the base one's */ for(dg=base->object->defbase.first; dg; dg=dg->next) { /* See if this group exists in the object (if it doesn't, add it to the end) */ if(!defgroup_find_name(ob, dg->name)) { odg = MEM_callocN(sizeof(bDeformGroup), "join deformGroup"); memcpy(odg, dg, sizeof(bDeformGroup)); BLI_addtail(&ob->defbase, odg); } } if(ob->defbase.first && ob->actdef==0) ob->actdef=1; if(me->totvert) { /* Add this object's materials to the base one's if they don't exist already (but only if limits not exceeded yet) */ if(totcol < MAXMAT-1) { for(a=1; a<=base->object->totcol; a++) { ma= give_current_material(base->object, a); for(b=0; b<totcol; b++) { if(ma == matar[b]) break; } if(b==totcol) { matar[b]= ma; if(ma) { id_us_plus(&ma->id); } totcol++; } if(totcol>=MAXMAT-1) break; } } /* if this mesh has shapekeys, check if destination mesh already has matching entries too */ if(me->key && key) { for(kb= me->key->block.first; kb; kb= kb->next) { /* if key doesn't exist in destination mesh, add it */ if(key_get_named_keyblock(key, kb->name) == NULL) { /* copy this existing one over to the new shapekey block */ kbn= MEM_dupallocN(kb); kbn->prev= kbn->next= NULL; /* adjust adrcode and other settings to fit (allocate a new data-array) */ kbn->data= MEM_callocN(sizeof(float)*3*totvert, "joined_shapekey"); kbn->totelem= totvert; kbn->weights= NULL; okb= key->block.last; curpos= (okb) ? okb->pos : -0.1f; if(key->type == KEY_RELATIVE) kbn->pos= curpos + 0.1f; else kbn->pos= curpos; BLI_addtail(&key->block, kbn); kbn->adrcode= key->totkey; key->totkey++; if(key->totkey==1) key->refkey= kbn; // XXX 2.5 Animato #if 0 /* also, copy corresponding ipo-curve to ipo-block if applicable */ if(me->key->ipo && key->ipo) { // FIXME... this is a luxury item! puts("FIXME: ignoring IPO's when joining shapekeys on Meshes for now..."); } #endif } } } } } } CTX_DATA_END; /* setup new data for destination mesh */ memset(&vdata, 0, sizeof(vdata)); memset(&edata, 0, sizeof(edata)); memset(&fdata, 0, sizeof(fdata)); mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface); vertofs= 0; edgeofs= 0; faceofs= 0; /* inverse transform for all selected meshes in this object */ invert_m4_m4(imat, ob->obmat); CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { /* only join if this is a mesh */ if(base->object->type==OB_MESH) { me= base->object->data; if(me->totvert) { /* standard data */ CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert); /* vertex groups */ dvert= CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); /* NB: vertex groups here are new version */ if(dvert) { for(i=0; i<me->totvert; i++) { for(j=0; j<dvert[i].totweight; j++) { /* Find the old vertex group */ odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr); if(odg) { /* Search for a match in the new object, and set new index */ for(dg=ob->defbase.first, index=0; dg; dg=dg->next, index++) { if(!strcmp(dg->name, odg->name)) { dvert[i].dw[j].def_nr = index; break; } } } } } } /* if this is the object we're merging into, no need to do anything */ if(base->object != ob) { /* watch this: switch matmul order really goes wrong */ mul_m4_m4m4(cmat, base->object->obmat, imat); /* transform vertex coordinates into new space */ for(a=0, mv=mvert; a < me->totvert; a++, mv++) { mul_m4_v3(cmat, mv->co); } /* for each shapekey in destination mesh: * - if there's a matching one, copy it across (will need to transform vertices into new space...) * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) */ if(key) { /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ for(kb= key->block.first; kb; kb= kb->next) { /* get pointer to where to write data for this mesh in shapekey's data array */ fp1= ((float *)kb->data) + (vertofs*3); /* check if this mesh has such a shapekey */ okb= key_get_named_keyblock(me->key, kb->name); if(okb) { /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ fp2= ((float *)(okb->data)); for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) { VECCOPY(fp1, fp2); mul_m4_v3(cmat, fp1); } } else { /* copy this mesh's vertex coordinates to the destination shapekey */ mv= mvert; for(a=0; a < me->totvert; a++, fp1+=3, mv++) { VECCOPY(fp1, mv->co); } } } } } else { /* for each shapekey in destination mesh: * - if it was an 'original', copy the appropriate data from nkey * - otherwise, copy across plain coordinates (no need to transform coordinates) */ if(key) { for(kb= key->block.first; kb; kb= kb->next) { /* get pointer to where to write data for this mesh in shapekey's data array */ fp1= ((float *)kb->data) + (vertofs*3); /* check if this was one of the original shapekeys */ okb= key_get_named_keyblock(nkey, kb->name); if(okb) { /* copy this mesh's shapekey to the destination shapekey */ fp2= ((float *)(okb->data)); for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) { VECCOPY(fp1, fp2); } } else { /* copy base-coordinates to the destination shapekey */ mv= mvert; for(a=0; a < me->totvert; a++, fp1+=3, mv++) { VECCOPY(fp1, mv->co); } } } } } /* advance mvert pointer to end of base mesh's data */ mvert+= me->totvert; } if(me->totface) { /* make mapping for materials */ for(a=1; a<=base->object->totcol; a++) { ma= give_current_material(base->object, a); for(b=0; b<totcol; b++) { if(ma == matar[b]) { matmap[a-1]= b; break; } } } if(base->object!=ob) multiresModifier_prepare_join(scene, base->object, ob); CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface); CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface); for(a=0; a<me->totface; a++, mface++) { mface->v1+= vertofs; mface->v2+= vertofs; mface->v3+= vertofs; if(mface->v4) mface->v4+= vertofs; if (matmap) mface->mat_nr= matmap[(int)mface->mat_nr]; else mface->mat_nr= 0; } faceofs += me->totface; } if(me->totedge) { CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge); for(a=0; a<me->totedge; a++, medge++) { medge->v1+= vertofs; medge->v2+= vertofs; } edgeofs += me->totedge; } /* vertofs is used to help newly added verts be reattached to their edge/face * (cannot be set earlier, or else reattaching goes wrong) */ vertofs += me->totvert; /* free base, now that data is merged */ if(base->object != ob) ED_base_object_free_and_unlink(bmain, scene, base); } } CTX_DATA_END; /* return to mesh we're merging to */ me= ob->data; CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); me->totvert= totvert; me->totedge= totedge; me->totface= totface; me->vdata= vdata; me->edata= edata; me->fdata= fdata; mesh_update_customdata_pointers(me); /* old material array */ for(a=1; a<=ob->totcol; a++) { ma= ob->mat[a-1]; if(ma) ma->id.us--; } for(a=1; a<=me->totcol; a++) { ma= me->mat[a-1]; if(ma) ma->id.us--; } if(ob->mat) MEM_freeN(ob->mat); if(ob->matbits) MEM_freeN(ob->matbits); if(me->mat) MEM_freeN(me->mat); ob->mat= me->mat= NULL; ob->matbits= NULL; if(totcol) { me->mat= matar; ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar"); ob->matbits= MEM_callocN(sizeof(char)*totcol, "join obmatbits"); } else MEM_freeN(matar); ob->totcol= me->totcol= totcol; ob->colbits= 0; if (matmap) MEM_freeN(matmap); /* other mesh users */ test_object_materials((ID *)me); /* free temp copy of destination shapekeys (if applicable) */ if(nkey) { // XXX 2.5 Animato #if 0 /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */ if(nkey->ipo) { free_ipo(nkey->ipo); BLI_remlink(&bmain->ipo, nkey->ipo); MEM_freeN(nkey->ipo); } #endif free_key(nkey); BLI_remlink(&bmain->key, nkey); MEM_freeN(nkey); } DAG_scene_sort(bmain, scene); // removed objects, need to rebuild dag before editmode call #if 0 ED_object_enter_editmode(C, EM_WAITCURSOR); ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR|EM_DO_UNDO); #else /* toggle editmode using lower level functions so this can be called from python */ make_editMesh(scene, ob); load_editMesh(scene, ob); free_editMesh(me->edit_mesh); MEM_freeN(me->edit_mesh); me->edit_mesh= NULL; DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA); #endif WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; }
static int border_select_exec(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; int i; rcti rect; rctf rectf; bool changed = false; const bool select = !RNA_boolean_get(op->ptr, "deselect"); const bool extend = RNA_boolean_get(op->ptr, "extend"); /* get rectangle from operator */ WM_operator_properties_border_to_rcti(op, &rect); ED_mask_point_pos(sa, ar, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin); ED_mask_point_pos(sa, ar, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax); /* do actual selection */ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } for (spline = masklay->splines.first; spline; spline = spline->next) { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; MaskSplinePoint *point_deform = &points_array[i]; /* TODO: handles? */ /* TODO: uw? */ if (BLI_rctf_isect_pt_v(&rectf, point_deform->bezt.vec[1])) { BKE_mask_point_select_set(point, select); BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select); } else if (!extend) { BKE_mask_point_select_set(point, false); BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, false); } changed = true; } } } if (changed) { ED_mask_select_flush_all(mask); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; }
static int mask_select_more_less(bContext *C, bool more) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } for (spline = masklay->splines.first; spline; spline = spline->next) { const bool cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0; bool start_sel, end_sel, prev_sel, cur_sel; int i; /* reselect point if any handle is selected to make the result more predictable */ for (i = 0; i < spline->tot_point; i++) { BKE_mask_point_select_set(spline->points + i, MASKPOINT_ISSEL_ANY(spline->points + i)); } /* select more/less does not affect empty/single point splines */ if (spline->tot_point < 2) { continue; } if (cyclic) { start_sel = !!MASKPOINT_ISSEL_KNOT(spline->points); end_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[spline->tot_point - 1]); } else { start_sel = false; end_sel = false; } for (i = 0; i < spline->tot_point; i++) { if (i == 0 && !cyclic) { continue; } prev_sel = (i > 0) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i - 1]) : end_sel; cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]); if (cur_sel != more) { if (prev_sel == more) { BKE_mask_point_select_set(&spline->points[i], more); } i++; } } for (i = spline->tot_point - 1; i >= 0; i--) { if (i == spline->tot_point - 1 && !cyclic) { continue; } prev_sel = (i < spline->tot_point - 1) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i + 1]) : start_sel; cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]); if (cur_sel != more) { if (prev_sel == more) { BKE_mask_point_select_set(&spline->points[i], more); } i--; } } } } WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; }
/* create new expression for button (i.e. a "scripted driver"), if it can be created... */ int ui_but_anim_expression_create(uiBut *but, const char *str) { bContext *C = but->block->evil_C; ID *id; FCurve *fcu; char *path; short ok=0; /* button must have RNA-pointer to a numeric-capable property */ if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) { if (G.f & G_DEBUG) printf("ERROR: create expression failed - button has no RNA info attached\n"); return 0; } /* make sure we have animdata for this */ // FIXME: until materials can be handled by depsgraph, don't allow drivers to be created for them id = (ID *)but->rnapoin.id.data; if ((id == NULL) || (GS(id->name)==ID_MA) || (GS(id->name)==ID_TE)) { if (G.f & G_DEBUG) printf("ERROR: create expression failed - invalid id-datablock for adding drivers (%p)\n", id); return 0; } /* get path */ path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop); /* create driver */ fcu = verify_driver_fcurve(id, path, but->rnaindex, 1); if (fcu) { ChannelDriver *driver= fcu->driver; if (driver) { /* set type of driver */ driver->type = DRIVER_TYPE_PYTHON; /* set the expression */ // TODO: need some way of identifying variables used BLI_strncpy(driver->expression, str, sizeof(driver->expression)); /* FIXME: for now, assume that * - for expressions, users are likely to be using "frame" -> current frame" as a variable * - driver_add_new_variable() adds a single-prop variable by default */ { DriverVar *dvar; DriverTarget *dtar; dvar = driver_add_new_variable(driver); BLI_strncpy(dvar->name, "frame", sizeof(dvar->name)); dtar = &dvar->targets[0]; dtar->id = (ID *)CTX_data_scene(C); // XXX: should we check that C is valid first? dtar->rna_path = BLI_sprintfN("frame_current"); } /* updates */ driver->flag |= DRIVER_FLAG_RECOMPILE; WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME, NULL); } } MEM_freeN(path); return ok; }
static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) { Object *obedit = CTX_data_edit_object(C); ListBase *editnurb; Nurb *nu; bool newob = false; bool enter_editmode; unsigned int layer; float dia; float loc[3], rot[3]; float mat[4][4]; WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; if (!isSurf) { /* adding curve */ if (obedit == NULL || obedit->type != OB_CURVE) { Curve *cu; obedit = ED_object_add_type(C, OB_CURVE, loc, rot, true, layer); newob = true; cu = (Curve *)obedit->data; cu->flag |= CU_DEFORM_FILL; if (type & CU_PRIM_PATH) cu->flag |= CU_PATH | CU_3D; } else { DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); } } else { /* adding surface */ if (obedit == NULL || obedit->type != OB_SURF) { obedit = ED_object_add_type(C, OB_SURF, loc, rot, true, layer); newob = true; } else { DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); } } /* rename here, the undo stack checks name for valid undo pushes */ if (newob) { if (obedit->type == OB_CURVE) { rename_id((ID *)obedit, get_curve_defname(type)); rename_id((ID *)obedit->data, get_curve_defname(type)); } else { rename_id((ID *)obedit, get_surf_defname(type)); rename_id((ID *)obedit->data, get_surf_defname(type)); } } /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */ if (newob && enter_editmode) ED_undo_push(C, "Enter Editmode"); ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); dia = RNA_float_get(op->ptr, "radius"); mul_mat3_m4_fl(mat, dia); nu = add_nurbs_primitive(C, obedit, mat, type, newob); editnurb = object_editcurve_get(obedit); BLI_addtail(editnurb, nu); /* userdef */ if (newob && !enter_editmode) { ED_object_editmode_exit(C, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); return OPERATOR_FINISHED; }
/* hardcoded to event TIMERJOBS */ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt) { wmJob *wm_job, *wm_jobnext; float total_progress = 0.f; float jobs_progress = 0; for (wm_job = wm->jobs.first; wm_job; wm_job = wm_jobnext) { wm_jobnext = wm_job->next; if (wm_job->wt == wt) { /* running threads */ if (wm_job->threads.first) { /* let threads get temporary lock over main thread if needed */ wm_job_main_thread_yield(wm_job, false); /* always call note and update when ready */ if (wm_job->do_update || wm_job->ready) { if (wm_job->update) wm_job->update(wm_job->run_customdata); if (wm_job->note) WM_event_add_notifier(C, wm_job->note, NULL); if (wm_job->flag & WM_JOB_PROGRESS) WM_event_add_notifier(C, NC_WM | ND_JOB, NULL); wm_job->do_update = FALSE; } if (wm_job->ready) { if (wm_job->endjob) wm_job->endjob(wm_job->run_customdata); /* free own data */ wm_job->run_free(wm_job->run_customdata); wm_job->run_customdata = NULL; wm_job->run_free = NULL; // if (wm_job->stop) printf("job ready but stopped %s\n", wm_job->name); // else printf("job finished %s\n", wm_job->name); if (G.debug & G_DEBUG_JOBS) { printf("Job '%s' finished in %f seconds\n", wm_job->name, PIL_check_seconds_timer() - wm_job->start_time); } wm_job->running = FALSE; wm_job_main_thread_yield(wm_job, true); BLI_end_threads(&wm_job->threads); wm_job->main_thread_mutex_ending = false; if (wm_job->endnote) WM_event_add_notifier(C, wm_job->endnote, NULL); WM_event_add_notifier(C, NC_WM | ND_JOB, NULL); /* new job added for wm_job? */ if (wm_job->customdata) { // printf("job restarted with new data %s\n", wm_job->name); WM_jobs_start(wm, wm_job); } else { WM_event_remove_timer(wm, wm_job->win, wm_job->wt); wm_job->wt = NULL; /* remove wm_job */ wm_job_free(wm, wm_job); } } else if (wm_job->flag & WM_JOB_PROGRESS) { /* accumulate global progress for running jobs */ jobs_progress++; total_progress += wm_job->progress; } } else if (wm_job->suspended) { WM_jobs_start(wm, wm_job); } } else if (wm_job->threads.first && !wm_job->ready) { if (wm_job->flag & WM_JOB_PROGRESS) { /* accumulate global progress for running jobs */ jobs_progress++; total_progress += wm_job->progress; } } } /* on file load 'winactive' can be NULL, possibly it should not happen but for now do a NULL check - campbell */ if (wm->winactive) { /* if there are running jobs, set the global progress indicator */ if (jobs_progress > 0) { float progress = total_progress / (float)jobs_progress; WM_progress_set(wm->winactive, progress); } else { WM_progress_clear(wm->winactive); } } }
void WM_file_read(bContext *C, const char *filepath, ReportList *reports) { int retval; /* so we can get the error message */ errno = 0; WM_cursor_wait(1); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); /* first try to append data from exotic file formats... */ /* it throws error box when file doesn't exist and returns -1 */ /* note; it should set some error message somewhere... (ton) */ retval = wm_read_exotic(CTX_data_scene(C), filepath); /* we didn't succeed, now try to read Blender file */ if (retval == BKE_READ_EXOTIC_OK_BLEND) { int G_f = G.f; ListBase wmbase; /* assume automated tasks with background, don't write recent file list */ const int do_history = (G.background == FALSE) && (CTX_wm_manager(C)->op_undo_depth == 0); /* put aside screens to match with persistent windows later */ /* also exit screens and editors */ wm_window_match_init(C, &wmbase); /* confusing this global... */ G.relbase_valid = 1; retval = BKE_read_file(C, filepath, reports); /* when loading startup.blend's, we can be left with a blank path */ if (G.main->name[0]) { G.save_over = 1; } else { G.save_over = 0; G.relbase_valid = 0; } /* this flag is initialized by the operator but overwritten on read. * need to re-enable it here else drivers + registered scripts wont work. */ if (G.f != G_f) { const int flags_keep = (G_SCRIPT_AUTOEXEC | G_SCRIPT_OVERRIDE_PREF); G.f = (G.f & ~flags_keep) | (G_f & flags_keep); } /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); WM_check(C); /* opens window(s), checks keymaps */ if (retval == BKE_READ_FILE_OK_USERPREFS) { /* in case a userdef is read from regular .blend */ wm_init_userdef(C, false); } if (retval != BKE_READ_FILE_FAIL) { if (do_history) { write_history(); } } WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); // refresh_interface_font(); CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); ED_editors_init(C); DAG_on_visible_update(CTX_data_main(C), TRUE); #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ BPY_python_reset(C); #endif /* important to do before NULL'ing the context */ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); if (!G.background) { /* in background mode this makes it hard to load * a blend file and do anything since the screen * won't be set to a valid value again */ CTX_wm_window_set(C, NULL); /* exits queues */ } #if 0 /* gives popups on windows but not linux, bug in report API * but disable for now to stop users getting annoyed */ /* TODO, make this show in header info window */ { Scene *sce; for (sce = G.main->scene.first; sce; sce = sce->id.next) { if (sce->r.engine[0] && BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL) { BKE_reportf(reports, RPT_ERROR, "Engine '%s' not available for scene '%s' " "(an addon may need to be installed or enabled)", sce->r.engine, sce->id.name + 2); } } } #endif BKE_reset_undo(); BKE_write_undo(C, "original"); /* save current state */ } else if (retval == BKE_READ_EXOTIC_OK_OTHER) BKE_write_undo(C, "Import file"); else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) { BKE_reportf(reports, RPT_ERROR, "Cannot read file '%s': %s", filepath, errno ? strerror(errno) : TIP_("unable to open the file")); } else if (retval == BKE_READ_EXOTIC_FAIL_FORMAT) { BKE_reportf(reports, RPT_ERROR, "File format is not supported in file '%s'", filepath); } else if (retval == BKE_READ_EXOTIC_FAIL_PATH) { BKE_reportf(reports, RPT_ERROR, "File path '%s' invalid", filepath); } else { BKE_reportf(reports, RPT_ERROR, "Unknown error loading '%s'", filepath); BLI_assert(!"invalid 'retval'"); } WM_cursor_wait(0); }
static int outliner_data_operation_exec(bContext *C, wmOperator *op) { SpaceOops *soops = CTX_wm_space_outliner(C); int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; eOutliner_PropDataOps event; /* check for invalid states */ if (soops == NULL) return OPERATOR_CANCELLED; event = RNA_enum_get(op->ptr, "type"); set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); switch (datalevel) { case TSE_POSE_CHANNEL: { outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); ED_undo_push(C, "PoseChannel operation"); } break; case TSE_BONE: { outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); ED_undo_push(C, "Bone operation"); } break; case TSE_EBONE: { outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); ED_undo_push(C, "EditBone operation"); } break; case TSE_SEQUENCE: { Scene *scene = CTX_data_scene(C); outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb, scene); } break; case TSE_GP_LAYER: { outliner_do_data_operation(soops, datalevel, event, &soops->tree, gp_layer_cb, NULL); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); ED_undo_push(C, "Grease Pencil Layer operation"); } break; case TSE_RNA_STRUCT: if (event == OL_DOP_SELECT_LINKED) { outliner_do_data_operation(soops, datalevel, event, &soops->tree, data_select_linked_cb, C); } break; default: BKE_report(op->reports, RPT_WARNING, "Not yet implemented"); break; } return OPERATOR_FINISHED; }
static int outliner_object_operation_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); int event; const char *str = NULL; /* check for invalid states */ if (soops == NULL) return OPERATOR_CANCELLED; event = RNA_enum_get(op->ptr, "type"); if (event == OL_OP_SELECT) { Scene *sce = scene; // to be able to delete, scenes are set... outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_cb); if (scene != sce) { ED_screen_set_scene(C, CTX_wm_screen(C), sce); } str = "Select Objects"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_SELECT_HIERARCHY) { Scene *sce = scene; // to be able to delete, scenes are set... outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_hierarchy_cb); if (scene != sce) { ED_screen_set_scene(C, CTX_wm_screen(C), sce); } str = "Select Object Hierarchy"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_DESELECT) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_deselect_cb); str = "Deselect Objects"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_DELETE) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_cb); /* XXX: tree management normally happens from draw_outliner(), but when * you're clicking to fast on Delete object from context menu in * outliner several mouse events can be handled in one cycle without * handling notifiers/redraw which leads to deleting the same object twice. * cleanup tree here to prevent such cases. */ outliner_cleanup_tree(soops); DAG_relations_tag_update(bmain); str = "Delete Objects"; WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } else if (event == OL_OP_DELETE_HIERARCHY) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_hierarchy_cb); /* XXX: See OL_OP_DELETE comment above. */ outliner_cleanup_tree(soops); DAG_relations_tag_update(bmain); str = "Delete Object Hierarchy"; WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */ outliner_do_object_operation(C, scene, soops, &soops->tree, id_local_cb); str = "Localized Objects"; } else if (event == OL_OP_TOGVIS) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb); str = "Toggle Visibility"; WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); } else if (event == OL_OP_TOGSEL) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_selectability_cb); str = "Toggle Selectability"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } else if (event == OL_OP_TOGREN) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb); str = "Toggle Renderability"; WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); } else if (event == OL_OP_RENAME) { outliner_do_object_operation(C, scene, soops, &soops->tree, item_rename_cb); str = "Rename Object"; } else { BLI_assert(0); return OPERATOR_CANCELLED; } ED_undo_push(C, str); return OPERATOR_FINISHED; }
static int outliner_id_operation_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; eOutlinerIdOpTypes event; /* check for invalid states */ if (soops == NULL) return OPERATOR_CANCELLED; set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); event = RNA_enum_get(op->ptr, "type"); switch (event) { case OUTLINER_IDOP_UNLINK: { /* unlink datablock from its parent */ switch (idlevel) { case ID_AC: outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_action_cb); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); ED_undo_push(C, "Unlink action"); break; case ID_MA: outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_material_cb); WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, NULL); ED_undo_push(C, "Unlink material"); break; case ID_TE: outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_texture_cb); WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, NULL); ED_undo_push(C, "Unlink texture"); break; case ID_WO: outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_world_cb); WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL); ED_undo_push(C, "Unlink world"); break; default: BKE_report(op->reports, RPT_WARNING, "Not yet implemented"); break; } break; } case OUTLINER_IDOP_LOCAL: { /* make local */ outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb); ED_undo_push(C, "Localized Data"); break; } case OUTLINER_IDOP_SINGLE: { /* make single user */ switch (idlevel) { case ID_AC: outliner_do_libdata_operation(C, scene, soops, &soops->tree, singleuser_action_cb); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); ED_undo_push(C, "Single-User Action"); break; case ID_WO: outliner_do_libdata_operation(C, scene, soops, &soops->tree, singleuser_world_cb); WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL); ED_undo_push(C, "Single-User World"); break; default: BKE_report(op->reports, RPT_WARNING, "Not yet implemented"); break; } break; } case OUTLINER_IDOP_FAKE_ADD: { /* set fake user */ outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_fake_user_set_cb); WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL); ED_undo_push(C, "Add Fake User"); break; } case OUTLINER_IDOP_FAKE_CLEAR: { /* clear fake user */ outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_fake_user_clear_cb); WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL); ED_undo_push(C, "Clear Fake User"); break; } case OUTLINER_IDOP_RENAME: { /* rename */ outliner_do_libdata_operation(C, scene, soops, &soops->tree, item_rename_cb); WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL); ED_undo_push(C, "Rename"); break; } case OUTLINER_IDOP_SELECT_LINKED: outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_select_linked_cb); ED_undo_push(C, "Select"); break; default: // invalid - unhandled break; } /* wrong notifier still... */ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL); // XXX: this is just so that outliner is always up to date WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL); return OPERATOR_FINISHED; }
static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) { SpaceOops *soops = CTX_wm_space_outliner(C); int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; eOutliner_AnimDataOps event; short updateDeps = 0; /* check for invalid states */ if (soops == NULL) return OPERATOR_CANCELLED; event = RNA_enum_get(op->ptr, "type"); set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); if (datalevel != TSE_ANIM_DATA) return OPERATOR_CANCELLED; /* perform the core operation */ switch (event) { case OUTLINER_ANIMOP_CLEAR_ADT: /* Remove Animation Data - this may remove the active action, in some cases... */ outliner_do_data_operation(soops, datalevel, event, &soops->tree, clear_animdata_cb, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); ED_undo_push(C, "Clear Animation Data"); break; case OUTLINER_ANIMOP_SET_ACT: /* delegate once again... */ WM_operator_name_call(C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, NULL); break; case OUTLINER_ANIMOP_CLEAR_ACT: /* clear active action - using standard rules */ outliner_do_data_operation(soops, datalevel, event, &soops->tree, unlinkact_animdata_cb, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); ED_undo_push(C, "Unlink action"); break; case OUTLINER_ANIMOP_REFRESH_DRV: outliner_do_data_operation(soops, datalevel, event, &soops->tree, refreshdrivers_animdata_cb, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL); //ED_undo_push(C, "Refresh Drivers"); /* no undo needed - shouldn't have any impact? */ updateDeps = 1; break; case OUTLINER_ANIMOP_CLEAR_DRV: outliner_do_data_operation(soops, datalevel, event, &soops->tree, cleardrivers_animdata_cb, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL); ED_undo_push(C, "Clear Drivers"); updateDeps = 1; break; default: // invalid break; } /* update dependencies */ if (updateDeps) { /* rebuild depsgraph for the new deps */ DAG_relations_tag_update(CTX_data_main(C)); } return OPERATOR_FINISHED; }
static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { wmWindowManager *wm = CTX_wm_manager(C); ReportList *reports = CTX_wm_reports(C); Report *report; ReportTimerInfo *rti; float progress = 0.0, color_progress = 0.0; float neutral_col[3] = {0.35, 0.35, 0.35}; float neutral_gray = 0.6; float timeout = 0.0, color_timeout = 0.0; int send_note = 0; /* escape if not our timer */ if ((reports->reporttimer == NULL) || (reports->reporttimer != event->customdata) || ((report = BKE_reports_last_displayable(reports)) == NULL) /* may have been deleted */ ) { return OPERATOR_PASS_THROUGH; } rti = (ReportTimerInfo *)reports->reporttimer->customdata; timeout = (report->type & RPT_ERROR_ALL) ? ERROR_TIMEOUT : INFO_TIMEOUT; color_timeout = (report->type & RPT_ERROR_ALL) ? ERROR_COLOR_TIMEOUT : INFO_COLOR_TIMEOUT; /* clear the report display after timeout */ if ((float)reports->reporttimer->duration > timeout) { WM_event_remove_timer(wm, NULL, reports->reporttimer); reports->reporttimer = NULL; WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL); return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); } if (rti->widthfac == 0.0f) { /* initialize colors based on report type */ if (report->type & RPT_ERROR_ALL) { rti->col[0] = 1.0; rti->col[1] = 0.2; rti->col[2] = 0.0; } else if (report->type & RPT_WARNING_ALL) { rti->col[0] = 1.0; rti->col[1] = 1.0; rti->col[2] = 0.0; } else if (report->type & RPT_INFO_ALL) { rti->col[0] = 0.3; rti->col[1] = 0.45; rti->col[2] = 0.7; } rti->grayscale = 0.75; rti->widthfac = 1.0; } progress = (float)reports->reporttimer->duration / timeout; color_progress = (float)reports->reporttimer->duration / color_timeout; /* save us from too many draws */ if (color_progress <= 1.0f) { send_note = 1; /* fade colors out sharply according to progress through fade-out duration */ interp_v3_v3v3(rti->col, rti->col, neutral_col, color_progress); rti->grayscale = interpf(neutral_gray, rti->grayscale, color_progress); } /* collapse report at end of timeout */ if (progress * timeout > timeout - COLLAPSE_TIMEOUT) { rti->widthfac = (progress * timeout - (timeout - COLLAPSE_TIMEOUT)) / COLLAPSE_TIMEOUT; rti->widthfac = 1.0f - rti->widthfac; send_note = 1; } if (send_note) { WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL); } return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); }
static int ED_object_shape_key_remove(bContext *C, Object *ob) { Main *bmain= CTX_data_main(C); KeyBlock *kb, *rkb; Key *key; //IpoCurve *icu; key= ob_get_key(ob); if(key==NULL) return 0; kb= BLI_findlink(&key->block, ob->shapenr-1); if(kb) { for(rkb= key->block.first; rkb; rkb= rkb->next) if(rkb->relative == ob->shapenr-1) rkb->relative= 0; BLI_remlink(&key->block, kb); key->totkey--; if(key->refkey== kb) { key->refkey= key->block.first; if(key->refkey) { /* apply new basis key on original data */ switch(ob->type) { case OB_MESH: key_to_mesh(key->refkey, ob->data); break; case OB_CURVE: case OB_SURF: key_to_curve(key->refkey, ob->data, BKE_curve_nurbs(ob->data)); break; case OB_LATTICE: key_to_latt(key->refkey, ob->data); break; } } } if(kb->data) MEM_freeN(kb->data); MEM_freeN(kb); for(kb= key->block.first; kb; kb= kb->next) if(kb->adrcode>=ob->shapenr) kb->adrcode--; #if 0 // XXX old animation system if(key->ipo) { for(icu= key->ipo->curve.first; icu; icu= icu->next) { if(icu->adrcode==ob->shapenr-1) { BLI_remlink(&key->ipo->curve, icu); free_ipo_curve(icu); break; } } for(icu= key->ipo->curve.first; icu; icu= icu->next) if(icu->adrcode>=ob->shapenr) icu->adrcode--; } #endif // XXX old animation system if(ob->shapenr>1) ob->shapenr--; } if(key->totkey==0) { if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL; else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL; else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL; free_libblock_us(&(bmain->key), key); } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return 1; }
static int object_shape_key_mirror(bContext *C, Object *ob) { KeyBlock *kb; Key *key; key= ob_get_key(ob); if(key==NULL) return 0; kb= BLI_findlink(&key->block, ob->shapenr-1); if(kb) { int i1, i2; float *fp1, *fp2; float tvec[3]; char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror"); if(ob->type==OB_MESH) { Mesh *me= ob->data; MVert *mv; mesh_octree_table(ob, NULL, NULL, 's'); for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) { i2= mesh_get_x_mirror_vert(ob, i1); if(i2==i1) { fp1= ((float *)kb->data) + i1*3; fp1[0] = -fp1[0]; tag_elem[i1]= 1; } else if(i2 != -1) { if(tag_elem[i1]==0 && tag_elem[i2]==0) { fp1= ((float *)kb->data) + i1*3; fp2= ((float *)kb->data) + i2*3; copy_v3_v3(tvec, fp1); copy_v3_v3(fp1, fp2); copy_v3_v3(fp2, tvec); /* flip x axis */ fp1[0] = -fp1[0]; fp2[0] = -fp2[0]; } tag_elem[i1]= tag_elem[i2]= 1; } } mesh_octree_table(ob, NULL, NULL, 'e'); } else if (ob->type == OB_LATTICE) { Lattice *lt= ob->data; int i1, i2; float *fp1, *fp2; int u, v, w; /* half but found up odd value */ const int pntsu_half = (((lt->pntsu / 2) + (lt->pntsu % 2))) ; /* currently editmode isnt supported by mesh so * ignore here for now too */ /* if(lt->editlatt) lt= lt->editlatt->latt; */ for(w=0; w<lt->pntsw; w++) { for(v=0; v<lt->pntsv; v++) { for(u=0; u<pntsu_half; u++) { int u_inv= (lt->pntsu - 1) - u; float tvec[3]; if(u == u_inv) { i1= LT_INDEX(lt, u, v, w); fp1= ((float *)kb->data) + i1*3; fp1[0]= -fp1[0]; } else { i1= LT_INDEX(lt, u, v, w); i2= LT_INDEX(lt, u_inv, v, w); fp1= ((float *)kb->data) + i1*3; fp2= ((float *)kb->data) + i2*3; copy_v3_v3(tvec, fp1); copy_v3_v3(fp1, fp2); copy_v3_v3(fp2, tvec); fp1[0]= -fp1[0]; fp2[0]= -fp2[0]; } } } } } MEM_freeN(tag_elem); } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return 1; }
static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); View3D *v3d = CTX_wm_view3d(C); TransVertStore tvs = {NULL}; TransVert *tv; float imat[3][3], bmat[3][3]; const float *cursor_global; float center_global[3]; float offset_global[3]; int a; const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); cursor_global = ED_view3d_cursor3d_get(scene, v3d); if (use_offset) { if ((v3d && v3d->around == V3D_ACTIVE) && snap_calc_active_center(C, true, center_global)) { /* pass */ } else { snap_curs_to_sel_ex(C, center_global); } sub_v3_v3v3(offset_global, cursor_global, center_global); } if (obedit) { float cursor_local[3]; if (ED_transverts_check_obedit(obedit)) ED_transverts_create_from_obedit(&tvs, obedit, 0); if (tvs.transverts_tot == 0) return OPERATOR_CANCELLED; copy_m3_m4(bmat, obedit->obmat); invert_m3_m3(imat, bmat); /* get the cursor in object space */ sub_v3_v3v3(cursor_local, cursor_global, obedit->obmat[3]); mul_m3_v3(imat, cursor_local); if (use_offset) { float offset_local[3]; mul_v3_m3v3(offset_local, imat, offset_global); tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { add_v3_v3(tv->loc, offset_local); } } else { tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { copy_v3_v3(tv->loc, cursor_local); } } ED_transverts_update_obedit(&tvs, obedit); ED_transverts_free(&tvs); } else if (obact && (obact->mode & OB_MODE_POSE)) { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); bPoseChannel *pchan; bArmature *arm = obact->data; float cursor_local[3]; invert_m4_m4(obact->imat, obact->obmat); mul_v3_m4v3(cursor_local, obact->imat, cursor_global); for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { if ((pchan->bone->flag & BONE_SELECTED) && (PBONE_VISIBLE(arm, pchan->bone)) && /* if the bone has a parent and is connected to the parent, * don't do anything - will break chain unless we do auto-ik. */ (pchan->bone->flag & BONE_CONNECTED) == 0) { pchan->bone->flag |= BONE_TRANSFORM; } else { pchan->bone->flag &= ~BONE_TRANSFORM; } } for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { if ((pchan->bone->flag & BONE_TRANSFORM) && /* check that our parents not transformed (if we have one) */ ((pchan->bone->parent && BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0)) { /* Get position in pchan (pose) space. */ float cursor_pose[3]; if (use_offset) { mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]); add_v3_v3(cursor_pose, offset_global); mul_m4_v3(obact->imat, cursor_pose); BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose); } else { BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose); } /* copy new position */ if ((pchan->protectflag & OB_LOCK_LOCX) == 0) pchan->loc[0] = cursor_pose[0]; if ((pchan->protectflag & OB_LOCK_LOCY) == 0) pchan->loc[1] = cursor_pose[1]; if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) pchan->loc[2] = cursor_pose[2]; /* auto-keyframing */ ED_autokeyframe_pchan(C, scene, obact, pchan, ks); } } for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { pchan->bone->flag &= ~BONE_TRANSFORM; } obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); DAG_id_tag_update(&obact->id, OB_RECALC_DATA); } else { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); Main *bmain = CTX_data_main(C); ListBase ctx_data_list; CollectionPointerLink *ctx_ob; Object *ob; CTX_data_selected_editable_objects(C, &ctx_data_list); /* reset flags */ for (ob = bmain->object.first; ob; ob = ob->id.next) { ob->flag &= ~OB_DONE; } /* tag objects we're transforming */ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) { ob = ctx_ob->ptr.data; ob->flag |= OB_DONE; } for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) { ob = ctx_ob->ptr.data; if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) { float cursor_parent[3]; /* parent-relative */ if (use_offset) { add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); } else { copy_v3_v3(cursor_parent, cursor_global); } sub_v3_v3(cursor_parent, ob->obmat[3]); if (ob->parent) { float originmat[3][3]; BKE_object_where_is_calc_ex(scene, NULL, ob, originmat); invert_m3_m3(imat, originmat); mul_m3_v3(imat, cursor_parent); } if ((ob->protectflag & OB_LOCK_LOCX) == 0) ob->loc[0] += cursor_parent[0]; if ((ob->protectflag & OB_LOCK_LOCY) == 0) ob->loc[1] += cursor_parent[1]; if ((ob->protectflag & OB_LOCK_LOCZ) == 0) ob->loc[2] += cursor_parent[2]; /* auto-keyframing */ ED_autokeyframe_object(C, scene, ob, ks); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } } BLI_freelistN(&ctx_data_list); } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; }
static int lattice_flip_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); Lattice *lt; eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis"); int numU, numV, numW; int totP; float mid = 0.0f; short isOdd = 0; /* get lattice - we need the "edit lattice" from the lattice... confusing... */ lt = (Lattice *)obedit->data; lt = lt->editlatt->latt; numU = lt->pntsu; numV = lt->pntsv; numW = lt->pntsw; totP = numU * numV * numW; /* First Pass: determine midpoint - used for flipping center verts if there are odd number of points on axis */ switch (axis) { case LATTICE_FLIP_U: isOdd = numU & 1; break; case LATTICE_FLIP_V: isOdd = numV & 1; break; case LATTICE_FLIP_W: isOdd = numW & 1; break; default: printf("lattice_flip(): Unknown flipping axis (%d)\n", axis); return OPERATOR_CANCELLED; } if (isOdd) { BPoint *bp; float avgInv = 1.0f / (float)totP; int i; /* midpoint calculation - assuming that u/v/w are axis-aligned */ for (i = 0, bp = lt->def; i < totP; i++, bp++) { mid += bp->vec[axis] * avgInv; } } /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */ switch (axis) { case LATTICE_FLIP_U: { int u, v, w; /* v/w strips - front to back, top to bottom */ for (w = 0; w < numW; w++) { for (v = 0; v < numV; v++) { /* swap coordinates of pairs of vertices on u */ for (u = 0; u < (numU / 2); u++) { lattice_swap_point_pairs(lt, u, v, w, mid, axis); } /* flip u-coordinate of midpoint (i.e. unpaired point on u) */ if (isOdd) { u = (numU / 2); lattice_flip_point_value(lt, u, v, w, mid, axis); } } } break; } case LATTICE_FLIP_V: { int u, v, w; /* u/w strips - front to back, left to right */ for (w = 0; w < numW; w++) { for (u = 0; u < numU; u++) { /* swap coordinates of pairs of vertices on v */ for (v = 0; v < (numV / 2); v++) { lattice_swap_point_pairs(lt, u, v, w, mid, axis); } /* flip v-coordinate of midpoint (i.e. unpaired point on v) */ if (isOdd) { v = (numV / 2); lattice_flip_point_value(lt, u, v, w, mid, axis); } } } break; } case LATTICE_FLIP_W: { int u, v, w; for (v = 0; v < numV; v++) { for (u = 0; u < numU; u++) { /* swap coordinates of pairs of vertices on w */ for (w = 0; w < (numW / 2); w++) { lattice_swap_point_pairs(lt, u, v, w, mid, axis); } /* flip w-coordinate of midpoint (i.e. unpaired point on w) */ if (isOdd) { w = (numW / 2); lattice_flip_point_value(lt, u, v, w, mid, axis); } } } break; } default: /* shouldn't happen, but just in case */ break; } /* updates */ DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; }
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); RegionView3D *rv3d = CTX_wm_region_data(C); TransVertStore tvs = {NULL}; TransVert *tv; float gridf, imat[3][3], bmat[3][3], vec[3]; int a; gridf = rv3d->gridview; if (obedit) { if (ED_transverts_check_obedit(obedit)) ED_transverts_create_from_obedit(&tvs, obedit, 0); if (tvs.transverts_tot == 0) return OPERATOR_CANCELLED; copy_m3_m4(bmat, obedit->obmat); invert_m3_m3(imat, bmat); tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { copy_v3_v3(vec, tv->loc); mul_m3_v3(bmat, vec); add_v3_v3(vec, obedit->obmat[3]); vec[0] = gridf * floorf(0.5f + vec[0] / gridf); vec[1] = gridf * floorf(0.5f + vec[1] / gridf); vec[2] = gridf * floorf(0.5f + vec[2] / gridf); sub_v3_v3(vec, obedit->obmat[3]); mul_m3_v3(imat, vec); copy_v3_v3(tv->loc, vec); } ED_transverts_update_obedit(&tvs, obedit); ED_transverts_free(&tvs); } else { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { if (ob->mode & OB_MODE_POSE) { bPoseChannel *pchan; bArmature *arm = ob->data; invert_m4_m4(ob->imat, ob->obmat); for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone->flag & BONE_SELECTED) { if (pchan->bone->layer & arm->layer) { if ((pchan->bone->flag & BONE_CONNECTED) == 0) { float nLoc[3]; /* get nearest grid point to snap to */ copy_v3_v3(nLoc, pchan->pose_mat[3]); /* We must operate in world space! */ mul_m4_v3(ob->obmat, nLoc); vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf); vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf); vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf); /* Back in object space... */ mul_m4_v3(ob->imat, vec); /* Get location of grid point in pose space. */ BKE_armature_loc_pose_to_bone(pchan, vec, vec); /* adjust location */ if ((pchan->protectflag & OB_LOCK_LOCX) == 0) pchan->loc[0] = vec[0]; if ((pchan->protectflag & OB_LOCK_LOCY) == 0) pchan->loc[1] = vec[1]; if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) pchan->loc[2] = vec[2]; /* auto-keyframing */ ED_autokeyframe_pchan(C, scene, ob, pchan, ks); } /* if the bone has a parent and is connected to the parent, * don't do anything - will break chain unless we do auto-ik. */ } } } ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } else { vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf); vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf); vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf); if (ob->parent) { float originmat[3][3]; BKE_object_where_is_calc_ex(scene, NULL, ob, originmat); invert_m3_m3(imat, originmat); mul_m3_v3(imat, vec); } if ((ob->protectflag & OB_LOCK_LOCX) == 0) ob->loc[0] += vec[0]; if ((ob->protectflag & OB_LOCK_LOCY) == 0) ob->loc[1] += vec[1]; if ((ob->protectflag & OB_LOCK_LOCZ) == 0) ob->loc[2] += vec[2]; /* auto-keyframing */ ED_autokeyframe_object(C, scene, ob, ks); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } } CTX_DATA_END; } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; }
static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) { TreeElement *tep; TreeStoreElem /* *tselem,*/ *tselemp; Object *ob=OBACT; SpaceButs *sbuts=NULL; if(ob==NULL) return 0; // no active object /*tselem= TREESTORE(te);*/ /*UNUSED*/ /* find buttons area (note, this is undefined really still, needs recode in blender) */ /* XXX removed finding sbuts */ /* where is texture linked to? */ tep= te->parent; tselemp= TREESTORE(tep); if(tep->idcode==ID_WO) { World *wrld= (World *)tselemp->id; if(set) { if(sbuts) { // XXX sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c // XXX sbuts->texfrom= 1; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture wrld->texact= te->index; } else if(tselemp->id == (ID *)(scene->world)) { if(wrld->texact==te->index) return 1; } } else if(tep->idcode==ID_LA) { Lamp *la= (Lamp *)tselemp->id; if(set) { if(sbuts) { // XXX sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c // XXX sbuts->texfrom= 2; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture la->texact= te->index; } else { if(tselemp->id == ob->data) { if(la->texact==te->index) return 1; } } } else if(tep->idcode==ID_MA) { Material *ma= (Material *)tselemp->id; if(set) { if(sbuts) { //sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c // XXX sbuts->texfrom= 0; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture ma->texact= (char)te->index; /* also set active material */ ob->actcol= tep->index+1; } else if(tep->flag & TE_ACTIVE) { // this is active material if(ma->texact==te->index) return 1; } } if(set) WM_event_add_notifier(C, NC_TEXTURE, NULL); return 0; }
static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr, idptr; PropertyRNA *prop; /* hook into UI */ UI_context_active_but_prop_get_templateID(C, &ptr, &prop); if (prop) { bAction *action = NULL, *oldact = NULL; AnimData *adt = NULL; PointerRNA oldptr; oldptr = RNA_property_pointer_get(&ptr, prop); oldact = (bAction *)oldptr.id.data; /* stash the old action to prevent it from being lost */ if (ptr.type == &RNA_AnimData) { adt = ptr.data; } else if (ptr.type == &RNA_SpaceDopeSheetEditor) { adt = ED_actedit_animdata_from_context(C); } /* Perform stashing operation - But only if there is an action */ if (adt && oldact) { /* stash the action */ if (BKE_nla_action_stash(adt)) { /* The stash operation will remove the user already * (and unlink the action from the AnimData action slot). * Hence, we must unset the ref to the action in the * action editor too (if this is where we're being called from) * first before setting the new action once it is created, * or else the user gets decremented twice! */ if (ptr.type == &RNA_SpaceDopeSheetEditor) { SpaceAction *saction = (SpaceAction *)ptr.data; saction->action = NULL; } } else { //printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name); } } /* create action */ action = action_create_new(C, oldact); /* set this new action * NOTE: we can't use actedit_change_action, as this function is also called from the NLA */ RNA_id_pointer_create(&action->id, &idptr); RNA_property_pointer_set(&ptr, prop, idptr); RNA_property_update(C, &ptr, prop); } /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); return OPERATOR_FINISHED; }
static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int extend, const float mval[2]) { if(mval[1]>te->ys && mval[1]<te->ys+UI_UNIT_Y) { TreeStoreElem *tselem= TREESTORE(te); int openclose= 0; /* open close icon */ if((te->flag & TE_ICONROW)==0) { // hidden icon, no open/close if( mval[0]>te->xs && mval[0]<te->xs+UI_UNIT_X) openclose= 1; } if(openclose) { /* all below close/open? */ if(extend) { tselem->flag &= ~TSE_CLOSED; outliner_set_flag(soops, &te->subtree, TSE_CLOSED, !outliner_has_one_flag(soops, &te->subtree, TSE_CLOSED, 1)); } else { if(tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED; else tselem->flag |= TSE_CLOSED; } return 1; } /* name and first icon */ else if(mval[0]>te->xs+UI_UNIT_X && mval[0]<te->xend) { /* always makes active object */ if(tselem->type!=TSE_SEQUENCE && tselem->type!=TSE_SEQ_STRIP && tselem->type!=TSE_SEQUENCE_DUP) tree_element_set_active_object(C, scene, soops, te, 1 + (extend!=0 && tselem->type==0)); if(tselem->type==0) { // the lib blocks /* editmode? */ if(te->idcode==ID_SCE) { if(scene!=(Scene *)tselem->id) { ED_screen_set_scene(C, (Scene *)tselem->id); } } else if(te->idcode==ID_GR) { Group *gr= (Group *)tselem->id; GroupObject *gob; if(extend) { int sel= BA_SELECT; for(gob= gr->gobject.first; gob; gob= gob->next) { if(gob->ob->flag & SELECT) { sel= BA_DESELECT; break; } } for(gob= gr->gobject.first; gob; gob= gob->next) { ED_base_object_select(object_in_scene(gob->ob, scene), sel); } } else { scene_deselect_all(scene); for(gob= gr->gobject.first; gob; gob= gob->next) { if((gob->ob->flag & SELECT) == 0) ED_base_object_select(object_in_scene(gob->ob, scene), BA_SELECT); } } WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); } else if(ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) { WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL); } else { // rest of types tree_element_active(C, scene, soops, te, 1); } } else tree_element_type_active(C, scene, soops, te, tselem, 1+(extend!=0)); return 1; } } for(te= te->subtree.first; te; te= te->next) { if(do_outliner_item_activate(C, scene, ar, soops, te, extend, mval)) return 1; } return 0; }
/* custom_file can be NULL */ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file) { ListBase wmbase; char startstr[FILE_MAX]; char prefstr[FILE_MAX]; int success = 0; /* Indicates whether user prefereneces were really load from memory. * * This is used for versioning code, and for this we can not rely on from_memory * passed via argument. This is because there might be configuration folder * exists but it might not have userpref.blend and in this case we fallback to * reading home file from memory. * * And in this case versioning code is to be run. */ bool read_userdef_from_memory = true; /* options exclude eachother */ BLI_assert((from_memory && custom_file) == 0); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); G.relbase_valid = 0; if (!from_memory) { const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); if (custom_file) { BLI_strncpy(startstr, custom_file, FILE_MAX); if (cfgdir) { BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); } else { prefstr[0] = '\0'; } } else if (cfgdir) { BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE); BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); } else { startstr[0] = '\0'; prefstr[0] = '\0'; from_memory = 1; } } /* prevent loading no UI */ G.fileflags &= ~G_FILE_NO_UI; /* put aside screens to match with persistent windows later */ wm_window_match_init(C, &wmbase); if (!from_memory) { if (BLI_access(startstr, R_OK) == 0) { success = (BKE_read_file(C, startstr, NULL) != BKE_READ_FILE_FAIL); } if (U.themes.first == NULL) { if (G.debug & G_DEBUG) printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr); success = 0; } } if (success == 0 && custom_file && reports) { BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", custom_file); /*We can not return from here because wm is already reset*/ } if (success == 0) { success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true); if (wmbase.first == NULL) wm_clear_default_size(C); BLI_init_temporary_dir(U.tempdir); #ifdef WITH_PYTHON_SECURITY /* use alternative setting for security nuts * otherwise we'd need to patch the binary blob - startup.blend.c */ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; #endif } /* check new prefs only after startup.blend was finished */ if (!from_memory && BLI_exists(prefstr)) { int done = BKE_read_file_userdef(prefstr, NULL); if (done) { read_userdef_from_memory = false; printf("Read new prefs: %s\n", prefstr); } } /* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise * can remove this eventually, only in a 2.53 and older, now its not written */ G.fileflags &= ~G_FILE_RELATIVE_REMAP; /* check userdef before open window, keymaps etc */ wm_init_userdef(C, read_userdef_from_memory); /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); WM_check(C); /* opens window(s), checks keymaps */ G.main->name[0] = '\0'; /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ if (!G.background) GPU_default_lights(); /* XXX */ G.save_over = 0; // start with save preference untitled.blend G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */ // refresh_interface_font(); // undo_editmode_clear(); BKE_reset_undo(); BKE_write_undo(C, "original"); /* save current state */ ED_editors_init(C); DAG_on_visible_update(CTX_data_main(C), TRUE); #ifdef WITH_PYTHON if (CTX_py_init_get(C)) { /* sync addons, these may have changed from the defaults */ BPY_string_exec(C, "__import__('addon_utils').reset_all()"); BPY_python_reset(C); } #endif /* important to do before NULL'ing the context */ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); /* in background mode the scene will stay NULL */ if (!G.background) { CTX_wm_window_set(C, NULL); /* exits queues */ } return TRUE; }
/* using context, starts job */ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* new render clears all callbacks */ Main *mainp; Scene *scene = CTX_data_scene(C); SceneRenderLayer *srl = NULL; Render *re; wmJob *wm_job; RenderJob *rj; Image *ima; int jobflag; const bool is_animation = RNA_boolean_get(op->ptr, "animation"); const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport"); View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL; struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL; const char *name; ScrArea *sa; /* only one render job at a time */ if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) return OPERATOR_CANCELLED; if (RE_force_single_renderlayer(scene)) WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); if (!RE_is_rendering_allowed(scene, camera_override, op->reports)) { return OPERATOR_CANCELLED; } if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); return OPERATOR_CANCELLED; } /* stop all running jobs, except screen one. currently previews frustrate Render */ WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C)); /* get main */ if (G.debug_value == 101) { /* thread-safety experiment, copy main from the undo buffer */ mainp = BKE_undo_get_main(&scene); } else mainp = CTX_data_main(C); /* cancel animation playback */ if (ED_screen_animation_playing(CTX_wm_manager(C))) ED_screen_animation_play(C, 0, 0); /* handle UI stuff */ WM_cursor_wait(1); /* flush sculpt and editmode changes */ ED_editors_flush_edits(C, true); /* cleanup sequencer caches before starting user triggered render. * otherwise, invalidated cache entries can make their way into * the output rendering. We can't put that into RE_BlenderFrame, * since sequence rendering can call that recursively... (peter) */ BKE_sequencer_cache_cleanup(); // store spare // get view3d layer, local layer, make this nice api call to render // store spare /* ensure at least 1 area shows result */ sa = render_view_open(C, event->x, event->y); jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS; /* custom scene and single layer re-render */ screen_render_scene_layer_set(op, mainp, &scene, &srl); if (RNA_struct_property_is_set(op->ptr, "layer")) jobflag |= WM_JOB_SUSPEND; /* job custom data */ rj = MEM_callocN(sizeof(RenderJob), "render job"); rj->main = mainp; rj->scene = scene; rj->current_scene = rj->scene; rj->srl = srl; rj->camera_override = camera_override; rj->lay_override = 0; rj->anim = is_animation; rj->write_still = is_write_still && !is_animation; rj->iuser.scene = scene; rj->iuser.ok = 1; rj->reports = op->reports; rj->orig_layer = 0; rj->last_layer = 0; rj->sa = sa; BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings); BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings); if (sa) { SpaceImage *sima = sa->spacedata.first; rj->orig_layer = sima->iuser.layer; } if (v3d) { if (scene->lay != v3d->lay) { rj->lay_override = v3d->lay; rj->v3d_override = true; } else if (camera_override && camera_override != scene->camera) rj->v3d_override = true; if (v3d->localvd) rj->lay_override |= v3d->localvd->lay; } /* Lock the user interface depending on render settings. */ if (scene->r.use_lock_interface) { int renderlay = rj->lay_override ? rj->lay_override : scene->lay; WM_set_locked_interface(CTX_wm_manager(C), true); /* Set flag interface need to be unlocked. * * This is so because we don't have copy of render settings * accessible from render job and copy is needed in case * of non-locked rendering, so we wouldn't try to unlock * anything if option was initially unset but then was * enabled during rendering. */ rj->interface_locked = true; /* Clean memory used by viewport? */ clean_viewport_memory(rj->main, scene, renderlay); } /* setup job */ if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render"; else name = "Render"; wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER); WM_jobs_customdata_set(wm_job, rj, render_freejob); WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0); WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob); /* get a render result image, and make sure it is empty */ ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); BKE_image_backup_render(rj->scene, ima); rj->image = ima; /* setup new render */ re = RE_NewRender(scene->id.name); RE_test_break_cb(re, rj, render_breakjob); RE_draw_lock_cb(re, rj, render_drawlock); RE_display_update_cb(re, rj, image_rect_update); RE_current_scene_update_cb(re, rj, current_scene_update); RE_stats_draw_cb(re, rj, image_renderinfo_cb); RE_progress_cb(re, rj, render_progress_update); rj->re = re; G.is_break = false; /* store actual owner of job, so modal operator could check for it, * the reason of this is that active scene could change when rendering * several layers from compositor [#31800] */ op->customdata = scene; WM_jobs_start(CTX_wm_manager(C), wm_job); WM_cursor_wait(0); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene); /* we set G.is_rendering here already instead of only in the job, this ensure * main loop or other scene updates are disabled in time, since they may * have started before the job thread */ G.is_rendering = true; /* add modal handler for ESC */ WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; }
static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) { ViewContext vc; EditVert *eve; float min[3], max[3]; int done= 0; short use_proj; em_setup_viewcontext(C, &vc); use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) && (vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE); invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); INIT_MINMAX(min, max); for(eve= vc.em->verts.first; eve; eve= eve->next) { if(eve->f & SELECT) { DO_MINMAX(eve->co, min, max); done= 1; } } /* call extrude? */ if(done) { const short rot_src= RNA_boolean_get(op->ptr, "rotate_source"); EditEdge *eed; float vec[3], cent[3], mat[3][3]; float nor[3]= {0.0, 0.0, 0.0}; /* 2D normal calc */ float mval_f[2]; mval_f[0]= (float)event->mval[0]; mval_f[1]= (float)event->mval[1]; done= 0; /* calculate the normal for selected edges */ for(eed= vc.em->edges.first; eed; eed= eed->next) { if(eed->f & SELECT) { float co1[3], co2[3]; mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co); mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co); project_float_noclip(vc.ar, co1, co1); project_float_noclip(vc.ar, co2, co2); /* 2D rotate by 90d while adding. * (x, y) = (y, -x) * * accumulate the screenspace normal in 2D, * with screenspace edge length weighting the result. */ if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) { nor[0] += (co1[1] - co2[1]); nor[1] += -(co1[0] - co2[0]); } else { nor[0] += (co2[1] - co1[1]); nor[1] += -(co2[0] - co1[0]); } done= 1; } } if(done) { float view_vec[3], cross[3]; /* convert the 2D nomal into 3D */ mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */ mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */ /* correct the normal to be aligned on the view plane */ copy_v3_v3(view_vec, vc.rv3d->viewinv[2]); mul_mat3_m4_v3(vc.obedit->imat, view_vec); cross_v3_v3v3(cross, nor, view_vec); cross_v3_v3v3(nor, view_vec, cross); normalize_v3(nor); } /* center */ mid_v3_v3v3(cent, min, max); copy_v3_v3(min, cent); mul_m4_v3(vc.obedit->obmat, min); // view space view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE); mul_m4_v3(vc.obedit->imat, min); // back in object space sub_v3_v3(min, cent); /* calculate rotation */ unit_m3(mat); if(done) { float dot; copy_v3_v3(vec, min); normalize_v3(vec); dot= dot_v3v3(vec, nor); if( fabs(dot)<0.999) { float cross[3], si, q1[4]; cross_v3_v3v3(cross, nor, vec); normalize_v3(cross); dot= 0.5f*saacos(dot); /* halve the rotation if its applied twice */ if(rot_src) dot *= 0.5f; si= (float)sin(dot); q1[0]= (float)cos(dot); q1[1]= cross[0]*si; q1[2]= cross[1]*si; q1[3]= cross[2]*si; quat_to_mat3( mat,q1); } } if(rot_src) { rotateflag(vc.em, SELECT, cent, mat); /* also project the source, for retopo workflow */ if(use_proj) EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em); } extrudeflag(vc.obedit, vc.em, SELECT, nor, 0); rotateflag(vc.em, SELECT, cent, mat); translateflag(vc.em, SELECT, min); recalc_editnormals(vc.em); } else if(vc.em->selectmode & SCE_SELECT_VERTEX) { float imat[4][4]; const float *curs= give_cursor(vc.scene, vc.v3d); copy_v3_v3(min, curs); view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE); eve= addvertlist(vc.em, 0, NULL); invert_m4_m4(imat, vc.obedit->obmat); mul_v3_m4v3(eve->co, imat, min); eve->f= SELECT; } if(use_proj) EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em); WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); DAG_id_tag_update(vc.obedit->data, 0); return OPERATOR_FINISHED; }
static void rna_NlaStrip_remove(NlaTrack *track, bContext *C, ReportList *reports, NlaStrip *strip) { free_nlastrip(&track->strips, strip); WM_event_add_notifier(C, NC_ANIMATION|ND_NLA|NA_REMOVED, NULL); }
static int select_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; MaskSpline *spline; MaskSplinePoint *point = NULL; float co[2]; bool extend = RNA_boolean_get(op->ptr, "extend"); bool deselect = RNA_boolean_get(op->ptr, "deselect"); bool toggle = RNA_boolean_get(op->ptr, "toggle"); eMaskWhichHandle which_handle; const float threshold = 19; RNA_float_get_array(op->ptr, "location", co); point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &which_handle, NULL); if (extend == false && deselect == false && toggle == false) ED_mask_select_toggle_all(mask, SEL_DESELECT); if (point) { if (which_handle != MASK_WHICH_HANDLE_NONE) { if (extend) { masklay->act_spline = spline; masklay->act_point = point; BKE_mask_point_select_set_handle(point, which_handle, true); } else if (deselect) { BKE_mask_point_select_set_handle(point, which_handle, false); } else { masklay->act_spline = spline; masklay->act_point = point; if (!MASKPOINT_ISSEL_HANDLE(point, which_handle)) { BKE_mask_point_select_set_handle(point, which_handle, true); } else if (toggle) { BKE_mask_point_select_set_handle(point, which_handle, false); } } } else { if (extend) { masklay->act_spline = spline; masklay->act_point = point; BKE_mask_point_select_set(point, true); } else if (deselect) { BKE_mask_point_select_set(point, false); } else { masklay->act_spline = spline; masklay->act_point = point; if (!MASKPOINT_ISSEL_ANY(point)) { BKE_mask_point_select_set(point, true); } else if (toggle) { BKE_mask_point_select_set(point, false); } } } masklay->act_spline = spline; masklay->act_point = point; ED_mask_select_flush_all(mask); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; } else { MaskSplinePointUW *uw; if (ED_mask_feather_find_nearest(C, mask, co, threshold, &masklay, &spline, &point, &uw, NULL)) { if (extend) { masklay->act_spline = spline; masklay->act_point = point; if (uw) uw->flag |= SELECT; } else if (deselect) { if (uw) uw->flag &= ~SELECT; } else { masklay->act_spline = spline; masklay->act_point = point; if (uw) { if (!(uw->flag & SELECT)) { uw->flag |= SELECT; } else if (toggle) { uw->flag &= ~SELECT; } } } ED_mask_select_flush_all(mask); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; } } return OPERATOR_PASS_THROUGH; }
/* set the current pose as the restpose */ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object bArmature *arm = BKE_armature_from_object(ob); bPose *pose; bPoseChannel *pchan; EditBone *curbone; /* don't check if editmode (should be done by caller) */ if (ob->type != OB_ARMATURE) return OPERATOR_CANCELLED; if (BKE_object_obdata_is_libdata(ob)) { BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); /* error_libdata(); */ return OPERATOR_CANCELLED; } /* helpful warnings... */ /* TODO: add warnings to be careful about actions, applying deforms first, etc. */ if (ob->adt && ob->adt->action) BKE_report(op->reports, RPT_WARNING, "Actions on this armature will be destroyed by this new rest pose as the " "transforms stored are relative to the old rest pose"); /* Get editbones of active armature to alter */ ED_armature_to_edit(arm); /* get pose of active object and move it out of posemode */ pose = ob->pose; for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { curbone = ED_armature_bone_find_name(arm->edbo, pchan->name); /* simply copy the head/tail values from pchan over to curbone */ copy_v3_v3(curbone->head, pchan->pose_head); copy_v3_v3(curbone->tail, pchan->pose_tail); /* fix roll: * 1. find auto-calculated roll value for this bone now * 2. remove this from the 'visual' y-rotation */ { float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3]; float delta[3], eul[3]; /* obtain new auto y-rotation */ sub_v3_v3v3(delta, curbone->tail, curbone->head); vec_roll_to_mat3(delta, 0.0f, premat); invert_m3_m3(imat, premat); /* get pchan 'visual' matrix */ copy_m3_m4(pmat, pchan->pose_mat); /* remove auto from visual and get euler rotation */ mul_m3_m3m3(tmat, imat, pmat); mat3_to_eul(eul, tmat); /* just use this euler-y as new roll value */ curbone->roll = eul[1]; } /* clear transform values for pchan */ zero_v3(pchan->loc); zero_v3(pchan->eul); unit_qt(pchan->quat); unit_axis_angle(pchan->rotAxis, &pchan->rotAngle); pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f; /* set anim lock */ curbone->flag |= BONE_UNKEYED; } /* convert editbones back to bones, and then free the edit-data */ ED_armature_from_edit(arm); ED_armature_edit_free(arm); /* flush positions of posebones */ BKE_pose_where_is(scene, ob); /* fix parenting of objects which are bone-parented */ applyarmature_fix_boneparents(scene, ob); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); return OPERATOR_FINISHED; }
static int circle_select_exec(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; int i; float zoomx, zoomy, offset[2], ellipse[2]; int width, height; bool changed = false; /* get operator properties */ const int x = RNA_int_get(op->ptr, "x"); const int y = RNA_int_get(op->ptr, "y"); const int radius = RNA_int_get(op->ptr, "radius"); const bool select = !RNA_boolean_get(op->ptr, "deselect"); /* compute ellipse and position in unified coordinates */ ED_mask_get_size(sa, &width, &height); ED_mask_zoom(sa, ar, &zoomx, &zoomy); width = height = max_ii(width, height); ellipse[0] = width * zoomx / radius; ellipse[1] = height * zoomy / radius; ED_mask_point_pos(sa, ar, x, y, &offset[0], &offset[1]); /* do actual selection */ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } for (spline = masklay->splines.first; spline; spline = spline->next) { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; MaskSplinePoint *point_deform = &points_array[i]; if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) { BKE_mask_point_select_set(point, select); BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select); changed = true; } } } } if (changed) { ED_mask_select_flush_all(mask); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; }
void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid, TransformReader *tm) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature); ((ArmatureModifierData *)md)->object = ob_arm; copy_m4_m4(ob->obmat, bind_shape_matrix); object_apply_mat4(ob, ob->obmat, 0, 0); #if 1 bc_set_parent(ob, ob_arm, C); #else Object workob; ob->parent = ob_arm; ob->partype = PAROBJECT; what_does_parent(scene, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA; DAG_scene_sort(bmain, scene); DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); #endif ((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP; // create all vertex groups std::vector<JointData>::iterator it; int joint_index; for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) { const char *name = "Group"; // skip joints that have invalid UID if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) continue; // name group by joint node name if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) { name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]); } ED_vgroup_add_name(ob, (char*)name); } // <vcount> - number of joints per vertex - joints_per_vertex // <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices // ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender? // for each vertex in weight indices // for each bone index in vertex // add vertex to group at group index // treat group index -1 specially // get def group by index with BLI_findlink for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) { unsigned int limit = weight + joints_per_vertex[vertex]; for ( ; weight < limit; weight++) { int joint = joint_indices[weight], joint_weight = weight_indices[weight]; // -1 means "weight towards the bind shape", we just don't assign it to any group if (joint != -1) { bDeformGroup *def = (bDeformGroup*)BLI_findlink(&ob->defbase, joint); ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE); } } } }
static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_loc, bool apply_rot, bool apply_scale) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale; bool changed = true; /* first check if we can execute */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF)) { ID *obdata = ob->data; if (ID_REAL_USERS(obdata) > 1) { BKE_reportf(reports, RPT_ERROR, "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting", ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2); changed = false; } if (obdata->lib) { BKE_reportf(reports, RPT_ERROR, "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting", ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2); changed = false; } } if (ELEM(ob->type, OB_CURVE, OB_SURF)) { ID *obdata = ob->data; Curve *cu; cu = ob->data; if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) { BKE_reportf(reports, RPT_ERROR, "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting", ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2); changed = false; } if (cu->key) { BKE_reportf(reports, RPT_ERROR, "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting", ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2); changed = false; } } } CTX_DATA_END; if (!changed) return OPERATOR_CANCELLED; changed = false; /* now execute */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { /* calculate rotation/scale matrix */ if (apply_scale && apply_rot) BKE_object_to_mat3(ob, rsmat); else if (apply_scale) BKE_object_scale_to_mat3(ob, rsmat); else if (apply_rot) { float tmat[3][3], timat[3][3]; /* simple rotation matrix */ BKE_object_rot_to_mat3(ob, rsmat, true); /* correct for scale, note mul_m3_m3m3 has swapped args! */ BKE_object_scale_to_mat3(ob, tmat); invert_m3_m3(timat, tmat); mul_m3_m3m3(rsmat, timat, rsmat); mul_m3_m3m3(rsmat, rsmat, tmat); } else unit_m3(rsmat); copy_m4_m3(mat, rsmat); /* calculate translation */ if (apply_loc) { copy_v3_v3(mat[3], ob->loc); if (!(apply_scale && apply_rot)) { float tmat[3][3]; /* correct for scale and rotation that is still applied */ BKE_object_to_mat3(ob, obmat); invert_m3_m3(iobmat, obmat); mul_m3_m3m3(tmat, rsmat, iobmat); mul_m3_v3(tmat, mat[3]); } } /* apply to object data */ if (ob->type == OB_MESH) { Mesh *me = ob->data; if (apply_scale) multiresModifier_scale_disp(scene, ob); /* adjust data */ BKE_mesh_transform(me, mat, true); /* update normals */ BKE_mesh_calc_normals(me); } else if (ob->type == OB_ARMATURE) { ED_armature_apply_transform(ob, mat); } else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; BKE_lattice_transform(lt, mat, true); } else if (ob->type == OB_MBALL) { MetaBall *mb = ob->data; BKE_mball_transform(mb, mat); } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu = ob->data; scale = mat3_to_scale(rsmat); BKE_curve_transform_ex(cu, mat, true, scale); } else if (ob->type == OB_CAMERA) { MovieClip *clip = BKE_object_movieclip_get(scene, ob, false); /* applying scale on camera actually scales clip's reconstruction. * of there's clip assigned to camera nothing to do actually. */ if (!clip) continue; if (apply_scale) BKE_tracking_reconstruction_scale(&clip->tracking, ob->size); } else if (ob->type == OB_EMPTY) { /* It's possible for empties too, even though they don't * really have obdata, since we can simply apply the maximum * scaling to the empty's drawsize. * * Core Assumptions: * 1) Most scaled empties have uniform scaling * (i.e. for visibility reasons), AND/OR * 2) Preserving non-uniform scaling is not that important, * and is something that many users would be willing to * sacrifice for having an easy way to do this. */ if ((apply_loc == false) && (apply_rot == false) && (apply_scale == true)) { float max_scale = max_fff(fabsf(ob->size[0]), fabsf(ob->size[1]), fabsf(ob->size[2])); ob->empty_drawsize *= max_scale; } } else { continue; } if (apply_loc) zero_v3(ob->loc); if (apply_scale) ob->size[0] = ob->size[1] = ob->size[2] = 1.0f; if (apply_rot) { zero_v3(ob->rot); unit_qt(ob->quat); unit_axis_angle(ob->rotAxis, &ob->rotAngle); } BKE_object_where_is_calc(scene, ob); if (ob->type == OB_ARMATURE) { BKE_pose_where_is(scene, ob); /* needed for bone parents */ } ignore_parent_tx(bmain, scene, ob); DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); changed = true; } CTX_DATA_END; if (!changed) { BKE_report(reports, RPT_WARNING, "Objects have no data to transform"); return OPERATOR_CANCELLED; } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; }
int join_mesh_shapes_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_active_object(C); Mesh *me= (Mesh *)ob->data; Mesh *selme=NULL; DerivedMesh *dm=NULL; Key *key=me->key; KeyBlock *kb; int ok=0, nonequal_verts=0; CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { if (base->object == ob) continue; if (base->object->type==OB_MESH) { selme = (Mesh *)base->object->data; if (selme->totvert==me->totvert) ok++; else nonequal_verts=1; } } CTX_DATA_END; if (!ok) { if (nonequal_verts) BKE_report(op->reports, RPT_WARNING, "Selected meshes must have equal numbers of vertices."); else BKE_report(op->reports, RPT_WARNING, "No additional selected meshes with equal vertex count to join."); return OPERATOR_CANCELLED; } if(key == NULL) { key= me->key= add_key((ID *)me); key->type= KEY_RELATIVE; /* first key added, so it was the basis. initialise it with the existing mesh */ kb= add_keyblock(key, NULL); mesh_to_key(me, kb); } /* now ready to add new keys from selected meshes */ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { if (base->object == ob) continue; if(base->object->type==OB_MESH) { selme = (Mesh *)base->object->data; if (selme->totvert==me->totvert) { dm = mesh_get_derived_deform(scene, base->object, CD_MASK_BAREMESH); if (!dm) continue; kb= add_keyblock(key, base->object->id.name+2); DM_to_meshkey(dm, me, kb); dm->release(dm); } } } CTX_DATA_END; WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; }