Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Blender Foundation, 2002-2008 full recode 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <stdlib.h> 00032 #include <string.h> 00033 00034 #include "DNA_anim_types.h" 00035 #include "DNA_armature_types.h" 00036 #include "DNA_key_types.h" 00037 #include "DNA_meshdata_types.h" 00038 #include "DNA_object_types.h" 00039 #include "DNA_scene_types.h" 00040 #include "DNA_group_types.h" 00041 00042 #include "BLI_math.h" 00043 #include "BLI_editVert.h" 00044 #include "BLI_listbase.h" 00045 #include "BLI_utildefines.h" 00046 00047 #include "BKE_context.h" 00048 #include "BKE_curve.h" 00049 #include "BKE_depsgraph.h" 00050 #include "BKE_main.h" 00051 #include "BKE_mesh.h" 00052 #include "BKE_object.h" 00053 #include "BKE_report.h" 00054 #include "BKE_multires.h" 00055 #include "BKE_armature.h" 00056 00057 #include "RNA_define.h" 00058 #include "RNA_access.h" 00059 00060 #include "WM_api.h" 00061 #include "WM_types.h" 00062 00063 #include "ED_armature.h" 00064 #include "ED_keyframing.h" 00065 #include "ED_mesh.h" 00066 #include "ED_screen.h" 00067 #include "ED_view3d.h" 00068 00069 #include "object_intern.h" 00070 00071 /*************************** Clear Transformation ****************************/ 00072 00073 /* clear location of object */ 00074 static void object_clear_loc(Object *ob) 00075 { 00076 /* clear location if not locked */ 00077 if ((ob->protectflag & OB_LOCK_LOCX)==0) 00078 ob->loc[0]= ob->dloc[0]= 0.0f; 00079 if ((ob->protectflag & OB_LOCK_LOCY)==0) 00080 ob->loc[1]= ob->dloc[1]= 0.0f; 00081 if ((ob->protectflag & OB_LOCK_LOCZ)==0) 00082 ob->loc[2]= ob->dloc[2]= 0.0f; 00083 } 00084 00085 /* clear rotation of object */ 00086 static void object_clear_rot(Object *ob) 00087 { 00088 /* clear rotations that aren't locked */ 00089 if (ob->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) { 00090 if (ob->protectflag & OB_LOCK_ROT4D) { 00091 /* perform clamping on a component by component basis */ 00092 if (ob->rotmode == ROT_MODE_AXISANGLE) { 00093 if ((ob->protectflag & OB_LOCK_ROTW) == 0) 00094 ob->rotAngle= ob->drotAngle= 0.0f; 00095 if ((ob->protectflag & OB_LOCK_ROTX) == 0) 00096 ob->rotAxis[0]= ob->drotAxis[0]= 0.0f; 00097 if ((ob->protectflag & OB_LOCK_ROTY) == 0) 00098 ob->rotAxis[1]= ob->drotAxis[1]= 0.0f; 00099 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) 00100 ob->rotAxis[2]= ob->drotAxis[2]= 0.0f; 00101 00102 /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */ 00103 if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2])) 00104 ob->rotAxis[1] = 1.0f; 00105 if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2])) 00106 ob->drotAxis[1]= 1.0f; 00107 } 00108 else if (ob->rotmode == ROT_MODE_QUAT) { 00109 if ((ob->protectflag & OB_LOCK_ROTW) == 0) 00110 ob->quat[0]= ob->dquat[0]= 1.0f; 00111 if ((ob->protectflag & OB_LOCK_ROTX) == 0) 00112 ob->quat[1]= ob->dquat[1]= 0.0f; 00113 if ((ob->protectflag & OB_LOCK_ROTY) == 0) 00114 ob->quat[2]= ob->dquat[2]= 0.0f; 00115 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) 00116 ob->quat[3]= ob->dquat[3]= 0.0f; 00117 00118 // TODO: does this quat need normalising now? 00119 } 00120 else { 00121 /* the flag may have been set for the other modes, so just ignore the extra flag... */ 00122 if ((ob->protectflag & OB_LOCK_ROTX) == 0) 00123 ob->rot[0]= ob->drot[0]= 0.0f; 00124 if ((ob->protectflag & OB_LOCK_ROTY) == 0) 00125 ob->rot[1]= ob->drot[1]= 0.0f; 00126 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) 00127 ob->rot[2]= ob->drot[2]= 0.0f; 00128 } 00129 } 00130 else { 00131 /* perform clamping using euler form (3-components) */ 00132 // FIXME: deltas are not handled for these cases yet... 00133 float eul[3], oldeul[3], quat1[4] = {0}; 00134 00135 if (ob->rotmode == ROT_MODE_QUAT) { 00136 copy_qt_qt(quat1, ob->quat); 00137 quat_to_eul(oldeul, ob->quat); 00138 } 00139 else if (ob->rotmode == ROT_MODE_AXISANGLE) { 00140 axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle); 00141 } 00142 else { 00143 copy_v3_v3(oldeul, ob->rot); 00144 } 00145 00146 eul[0]= eul[1]= eul[2]= 0.0f; 00147 00148 if (ob->protectflag & OB_LOCK_ROTX) 00149 eul[0]= oldeul[0]; 00150 if (ob->protectflag & OB_LOCK_ROTY) 00151 eul[1]= oldeul[1]; 00152 if (ob->protectflag & OB_LOCK_ROTZ) 00153 eul[2]= oldeul[2]; 00154 00155 if (ob->rotmode == ROT_MODE_QUAT) { 00156 eul_to_quat(ob->quat, eul); 00157 /* quaternions flip w sign to accumulate rotations correctly */ 00158 if ((quat1[0]<0.0f && ob->quat[0]>0.0f) || (quat1[0]>0.0f && ob->quat[0]<0.0f)) { 00159 mul_qt_fl(ob->quat, -1.0f); 00160 } 00161 } 00162 else if (ob->rotmode == ROT_MODE_AXISANGLE) { 00163 eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle,eul, EULER_ORDER_DEFAULT); 00164 } 00165 else { 00166 copy_v3_v3(ob->rot, eul); 00167 } 00168 } 00169 } // Duplicated in source/blender/editors/armature/editarmature.c 00170 else { 00171 if (ob->rotmode == ROT_MODE_QUAT) { 00172 unit_qt(ob->quat); 00173 unit_qt(ob->dquat); 00174 } 00175 else if (ob->rotmode == ROT_MODE_AXISANGLE) { 00176 unit_axis_angle(ob->rotAxis, &ob->rotAngle); 00177 unit_axis_angle(ob->drotAxis, &ob->drotAngle); 00178 } 00179 else { 00180 zero_v3(ob->rot); 00181 zero_v3(ob->drot); 00182 } 00183 } 00184 } 00185 00186 /* clear scale of object */ 00187 static void object_clear_scale(Object *ob) 00188 { 00189 /* clear scale factors which are not locked */ 00190 if ((ob->protectflag & OB_LOCK_SCALEX)==0) { 00191 ob->dscale[0]= 1.0f; 00192 ob->size[0]= 1.0f; 00193 } 00194 if ((ob->protectflag & OB_LOCK_SCALEY)==0) { 00195 ob->dscale[1]= 1.0f; 00196 ob->size[1]= 1.0f; 00197 } 00198 if ((ob->protectflag & OB_LOCK_SCALEZ)==0) { 00199 ob->dscale[2]= 1.0f; 00200 ob->size[2]= 1.0f; 00201 } 00202 } 00203 00204 /* --------------- */ 00205 00206 /* generic exec for clear-transform operators */ 00207 static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, 00208 void (*clear_func)(Object*), const char default_ksName[]) 00209 { 00210 Main *bmain = CTX_data_main(C); 00211 Scene *scene= CTX_data_scene(C); 00212 KeyingSet *ks; 00213 00214 /* sanity checks */ 00215 if ELEM(NULL, clear_func, default_ksName) { 00216 BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform func or Keying Set Name"); 00217 return OPERATOR_CANCELLED; 00218 } 00219 00220 /* get KeyingSet to use */ 00221 ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName); 00222 00223 /* operate on selected objects only if they aren't in weight-paint mode 00224 * (so that object-transform clearing won't be applied at same time as bone-clearing) 00225 */ 00226 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 00227 { 00228 if (!(ob->mode & OB_MODE_WEIGHT_PAINT)) { 00229 /* run provided clearing function */ 00230 clear_func(ob); 00231 00232 ED_autokeyframe_object(C, scene, ob, ks); 00233 00234 /* tag for updates */ 00235 DAG_id_tag_update(&ob->id, OB_RECALC_OB); 00236 } 00237 } 00238 CTX_DATA_END; 00239 00240 /* this is needed so children are also updated */ 00241 DAG_ids_flush_update(bmain, 0); 00242 00243 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); 00244 00245 return OPERATOR_FINISHED; 00246 } 00247 00248 /* --------------- */ 00249 00250 00251 static int object_location_clear_exec(bContext *C, wmOperator *op) 00252 { 00253 return object_clear_transform_generic_exec(C, op, object_clear_loc, ANIM_KS_LOCATION_ID); 00254 } 00255 00256 void OBJECT_OT_location_clear(wmOperatorType *ot) 00257 { 00258 /* identifiers */ 00259 ot->name= "Clear Location"; 00260 ot->description = "Clear the object's location"; 00261 ot->idname= "OBJECT_OT_location_clear"; 00262 00263 /* api callbacks */ 00264 ot->exec= object_location_clear_exec; 00265 ot->poll= ED_operator_scene_editable; 00266 00267 /* flags */ 00268 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00269 } 00270 00271 static int object_rotation_clear_exec(bContext *C, wmOperator *op) 00272 { 00273 return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID); 00274 } 00275 00276 void OBJECT_OT_rotation_clear(wmOperatorType *ot) 00277 { 00278 /* identifiers */ 00279 ot->name= "Clear Rotation"; 00280 ot->description = "Clear the object's rotation"; 00281 ot->idname= "OBJECT_OT_rotation_clear"; 00282 00283 /* api callbacks */ 00284 ot->exec= object_rotation_clear_exec; 00285 ot->poll= ED_operator_scene_editable; 00286 00287 /* flags */ 00288 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00289 } 00290 00291 static int object_scale_clear_exec(bContext *C, wmOperator *op) 00292 { 00293 return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID); 00294 } 00295 00296 void OBJECT_OT_scale_clear(wmOperatorType *ot) 00297 { 00298 /* identifiers */ 00299 ot->name= "Clear Scale"; 00300 ot->description = "Clear the object's scale"; 00301 ot->idname= "OBJECT_OT_scale_clear"; 00302 00303 /* api callbacks */ 00304 ot->exec= object_scale_clear_exec; 00305 ot->poll= ED_operator_scene_editable; 00306 00307 /* flags */ 00308 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00309 } 00310 00311 /* --------------- */ 00312 00313 static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op)) 00314 { 00315 Main *bmain= CTX_data_main(C); 00316 float *v1, *v3; 00317 float mat[3][3]; 00318 00319 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 00320 { 00321 if (ob->parent) { 00322 /* vectors pointed to by v1 and v3 will get modified */ 00323 v1= ob->loc; 00324 v3= ob->parentinv[3]; 00325 00326 copy_m3_m4(mat, ob->parentinv); 00327 negate_v3_v3(v3, v1); 00328 mul_m3_v3(mat, v3); 00329 } 00330 00331 DAG_id_tag_update(&ob->id, OB_RECALC_OB); 00332 } 00333 CTX_DATA_END; 00334 00335 DAG_ids_flush_update(bmain, 0); 00336 00337 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); 00338 00339 return OPERATOR_FINISHED; 00340 } 00341 00342 void OBJECT_OT_origin_clear(wmOperatorType *ot) 00343 { 00344 /* identifiers */ 00345 ot->name= "Clear Origin"; 00346 ot->description = "Clear the object's origin"; 00347 ot->idname= "OBJECT_OT_origin_clear"; 00348 00349 /* api callbacks */ 00350 ot->exec= object_origin_clear_exec; 00351 ot->poll= ED_operator_scene_editable; 00352 00353 /* flags */ 00354 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00355 } 00356 00357 /*************************** Apply Transformation ****************************/ 00358 00359 /* use this when the loc/size/rot of the parent has changed but the children 00360 * should stay in the same place, e.g. for apply-size-rot or object center */ 00361 static void ignore_parent_tx(Main *bmain, Scene *scene, Object *ob ) 00362 { 00363 Object workob; 00364 Object *ob_child; 00365 00366 /* a change was made, adjust the children to compensate */ 00367 for(ob_child=bmain->object.first; ob_child; ob_child=ob_child->id.next) { 00368 if(ob_child->parent == ob) { 00369 object_apply_mat4(ob_child, ob_child->obmat, TRUE, FALSE); 00370 what_does_parent(scene, ob_child, &workob); 00371 invert_m4_m4(ob_child->parentinv, workob.obmat); 00372 } 00373 } 00374 } 00375 00376 static int apply_objects_internal(bContext *C, ReportList *reports, int apply_loc, int apply_rot, int apply_scale) 00377 { 00378 Main *bmain= CTX_data_main(C); 00379 Scene *scene= CTX_data_scene(C); 00380 float rsmat[3][3], tmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale; 00381 int a, change = 0; 00382 00383 /* first check if we can execute */ 00384 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) { 00385 00386 if(ob->type==OB_MESH) { 00387 if(ID_REAL_USERS(ob->data) > 1) { 00388 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user mesh, doing nothing"); 00389 return OPERATOR_CANCELLED; 00390 } 00391 } 00392 else if(ob->type==OB_ARMATURE) { 00393 if(ID_REAL_USERS(ob->data) > 1) { 00394 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user armature, doing nothing"); 00395 return OPERATOR_CANCELLED; 00396 } 00397 } 00398 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) { 00399 Curve *cu; 00400 00401 if(ID_REAL_USERS(ob->data) > 1) { 00402 BKE_report(reports, RPT_ERROR, "Can't apply to a multi user curve, doing nothing"); 00403 return OPERATOR_CANCELLED; 00404 } 00405 00406 cu= ob->data; 00407 00408 if(!(cu->flag & CU_3D) && (apply_rot || apply_loc)) { 00409 BKE_report(reports, RPT_ERROR, "Neither rotation nor location could be applied to a 2d curve, doing nothing"); 00410 return OPERATOR_CANCELLED; 00411 } 00412 if(cu->key) { 00413 BKE_report(reports, RPT_ERROR, "Can't apply to a curve with vertex keys, doing nothing"); 00414 return OPERATOR_CANCELLED; 00415 } 00416 } 00417 } 00418 CTX_DATA_END; 00419 00420 /* now execute */ 00421 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) { 00422 00423 /* calculate rotation/scale matrix */ 00424 if(apply_scale && apply_rot) 00425 object_to_mat3(ob, rsmat); 00426 else if(apply_scale) 00427 object_scale_to_mat3(ob, rsmat); 00428 else if(apply_rot) { 00429 float tmat[3][3], timat[3][3]; 00430 00431 /* simple rotation matrix */ 00432 object_rot_to_mat3(ob, rsmat); 00433 00434 /* correct for scale, note mul_m3_m3m3 has swapped args! */ 00435 object_scale_to_mat3(ob, tmat); 00436 invert_m3_m3(timat, tmat); 00437 mul_m3_m3m3(rsmat, timat, rsmat); 00438 mul_m3_m3m3(rsmat, rsmat, tmat); 00439 } 00440 else 00441 unit_m3(rsmat); 00442 00443 copy_m4_m3(mat, rsmat); 00444 00445 /* calculate translation */ 00446 if(apply_loc) { 00447 copy_v3_v3(mat[3], ob->loc); 00448 00449 if(!(apply_scale && apply_rot)) { 00450 /* correct for scale and rotation that is still applied */ 00451 object_to_mat3(ob, obmat); 00452 invert_m3_m3(iobmat, obmat); 00453 mul_m3_m3m3(tmat, rsmat, iobmat); 00454 mul_m3_v3(tmat, mat[3]); 00455 } 00456 } 00457 00458 /* apply to object data */ 00459 if(ob->type==OB_MESH) { 00460 Mesh *me= ob->data; 00461 MVert *mvert; 00462 00463 multiresModifier_scale_disp(scene, ob); 00464 00465 /* adjust data */ 00466 mvert= me->mvert; 00467 for(a=0; a<me->totvert; a++, mvert++) 00468 mul_m4_v3(mat, mvert->co); 00469 00470 if(me->key) { 00471 KeyBlock *kb; 00472 00473 for(kb=me->key->block.first; kb; kb=kb->next) { 00474 float *fp= kb->data; 00475 00476 for(a=0; a<kb->totelem; a++, fp+=3) 00477 mul_m4_v3(mat, fp); 00478 } 00479 } 00480 00481 /* update normals */ 00482 mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); 00483 } 00484 else if (ob->type==OB_ARMATURE) { 00485 ED_armature_apply_transform(ob, mat); 00486 } 00487 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) { 00488 Curve *cu= ob->data; 00489 00490 Nurb *nu; 00491 BPoint *bp; 00492 BezTriple *bezt; 00493 00494 scale = mat3_to_scale(rsmat); 00495 00496 for(nu=cu->nurb.first; nu; nu=nu->next) { 00497 if(nu->type == CU_BEZIER) { 00498 a= nu->pntsu; 00499 for(bezt= nu->bezt; a--; bezt++) { 00500 mul_m4_v3(mat, bezt->vec[0]); 00501 mul_m4_v3(mat, bezt->vec[1]); 00502 mul_m4_v3(mat, bezt->vec[2]); 00503 bezt->radius *= scale; 00504 } 00505 calchandlesNurb(nu); 00506 } 00507 else { 00508 a= nu->pntsu*nu->pntsv; 00509 for(bp= nu->bp; a--; bp++) 00510 mul_m4_v3(mat, bp->vec); 00511 } 00512 } 00513 } 00514 else 00515 continue; 00516 00517 if(apply_loc) 00518 zero_v3(ob->loc); 00519 if(apply_scale) 00520 ob->size[0]= ob->size[1]= ob->size[2]= 1.0f; 00521 if(apply_rot) { 00522 zero_v3(ob->rot); 00523 unit_qt(ob->quat); 00524 unit_axis_angle(ob->rotAxis, &ob->rotAngle); 00525 } 00526 00527 where_is_object(scene, ob); 00528 if(ob->type==OB_ARMATURE) { 00529 where_is_pose(scene, ob); /* needed for bone parents */ 00530 } 00531 00532 ignore_parent_tx(bmain, scene, ob); 00533 00534 DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA); 00535 00536 change = 1; 00537 } 00538 CTX_DATA_END; 00539 00540 if(!change) 00541 return OPERATOR_CANCELLED; 00542 00543 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); 00544 return OPERATOR_FINISHED; 00545 } 00546 00547 static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) 00548 { 00549 Scene *scene= CTX_data_scene(C); 00550 int change = 0; 00551 00552 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) { 00553 where_is_object(scene, ob); 00554 object_apply_mat4(ob, ob->obmat, TRUE, TRUE); 00555 where_is_object(scene, ob); 00556 00557 /* update for any children that may get moved */ 00558 DAG_id_tag_update(&ob->id, OB_RECALC_OB); 00559 00560 change = 1; 00561 } 00562 CTX_DATA_END; 00563 00564 if(!change) 00565 return OPERATOR_CANCELLED; 00566 00567 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); 00568 return OPERATOR_FINISHED; 00569 } 00570 00571 void OBJECT_OT_visual_transform_apply(wmOperatorType *ot) 00572 { 00573 /* identifiers */ 00574 ot->name= "Apply Visual Transform"; 00575 ot->description = "Apply the object's visual transformation to its data"; 00576 ot->idname= "OBJECT_OT_visual_transform_apply"; 00577 00578 /* api callbacks */ 00579 ot->exec= visual_transform_apply_exec; 00580 ot->poll= ED_operator_scene_editable; 00581 00582 /* flags */ 00583 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00584 } 00585 00586 static int object_transform_apply_exec(bContext *C, wmOperator *op) 00587 { 00588 const int loc= RNA_boolean_get(op->ptr, "location"); 00589 const int rot= RNA_boolean_get(op->ptr, "rotation"); 00590 const int sca= RNA_boolean_get(op->ptr, "scale"); 00591 00592 if(loc || rot || sca) { 00593 return apply_objects_internal(C, op->reports, loc, rot, sca); 00594 } 00595 else { 00596 return OPERATOR_CANCELLED; 00597 } 00598 } 00599 00600 void OBJECT_OT_transform_apply(wmOperatorType *ot) 00601 { 00602 /* identifiers */ 00603 ot->name= "Apply Object Transform"; 00604 ot->description = "Apply the object's transformation to its data"; 00605 ot->idname= "OBJECT_OT_transform_apply"; 00606 00607 /* api callbacks */ 00608 ot->exec= object_transform_apply_exec; 00609 ot->poll= ED_operator_objectmode; 00610 00611 /* flags */ 00612 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00613 00614 RNA_def_boolean(ot->srna, "location", 0, "Location", ""); 00615 RNA_def_boolean(ot->srna, "rotation", 0, "Rotation", ""); 00616 RNA_def_boolean(ot->srna, "scale", 0, "Scale", ""); 00617 } 00618 00619 /********************* Set Object Center ************************/ 00620 00621 enum { 00622 GEOMETRY_TO_ORIGIN=0, 00623 ORIGIN_TO_GEOMETRY, 00624 ORIGIN_TO_CURSOR 00625 }; 00626 00627 static int object_origin_set_exec(bContext *C, wmOperator *op) 00628 { 00629 Main *bmain= CTX_data_main(C); 00630 Scene *scene= CTX_data_scene(C); 00631 Object *obedit= CTX_data_edit_object(C); 00632 Object *tob; 00633 float cursor[3], cent[3], cent_neg[3], centn[3], min[3], max[3]; 00634 int centermode = RNA_enum_get(op->ptr, "type"); 00635 int around = RNA_enum_get(op->ptr, "center"); /* initialized from v3d->around */ 00636 00637 /* keep track of what is changed */ 00638 int tot_change=0, tot_lib_error=0, tot_multiuser_arm_error=0; 00639 00640 if (obedit && centermode != GEOMETRY_TO_ORIGIN) { 00641 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode"); 00642 return OPERATOR_CANCELLED; 00643 } 00644 else { 00645 /* get the view settings if 'around' isnt set and the view is available */ 00646 View3D *v3d= CTX_wm_view3d(C); 00647 copy_v3_v3(cursor, give_cursor(scene, v3d)); 00648 if(v3d && !RNA_struct_property_is_set(op->ptr, "center")) 00649 around= v3d->around; 00650 } 00651 00652 zero_v3(cent); 00653 00654 if(obedit) { 00655 INIT_MINMAX(min, max); 00656 00657 if(obedit->type==OB_MESH) { 00658 Mesh *me= obedit->data; 00659 EditMesh *em = BKE_mesh_get_editmesh(me); 00660 EditVert *eve; 00661 00662 if(around==V3D_CENTROID) { 00663 int total= 0; 00664 for(eve= em->verts.first; eve; eve= eve->next) { 00665 total++; 00666 add_v3_v3(cent, eve->co); 00667 } 00668 if(total) { 00669 mul_v3_fl(cent, 1.0f/(float)total); 00670 } 00671 } 00672 else { 00673 for(eve= em->verts.first; eve; eve= eve->next) { 00674 DO_MINMAX(eve->co, min, max); 00675 } 00676 mid_v3_v3v3(cent, min, max); 00677 } 00678 00679 if(!is_zero_v3(cent)) { 00680 for(eve= em->verts.first; eve; eve= eve->next) { 00681 sub_v3_v3(eve->co, cent); 00682 } 00683 00684 recalc_editnormals(em); 00685 tot_change++; 00686 DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); 00687 } 00688 BKE_mesh_end_editmesh(me, em); 00689 } 00690 } 00691 00692 /* reset flags */ 00693 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) { 00694 ob->flag &= ~OB_DONE; 00695 } 00696 CTX_DATA_END; 00697 00698 for (tob= bmain->object.first; tob; tob= tob->id.next) { 00699 if(tob->data) 00700 ((ID *)tob->data)->flag &= ~LIB_DOIT; 00701 if(tob->dup_group) 00702 ((ID *)tob->dup_group)->flag &= ~LIB_DOIT; 00703 } 00704 00705 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) { 00706 if((ob->flag & OB_DONE)==0) { 00707 int do_inverse_offset = FALSE; 00708 ob->flag |= OB_DONE; 00709 00710 if(centermode == ORIGIN_TO_CURSOR) { 00711 copy_v3_v3(cent, cursor); 00712 invert_m4_m4(ob->imat, ob->obmat); 00713 mul_m4_v3(ob->imat, cent); 00714 } 00715 00716 if(ob->data == NULL) { 00717 /* special support for dupligroups */ 00718 if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group && (ob->dup_group->id.flag & LIB_DOIT)==0) { 00719 if(ob->dup_group->id.lib) { 00720 tot_lib_error++; 00721 } 00722 else { 00723 if(centermode == ORIGIN_TO_CURSOR) { /* done */ } 00724 else { 00725 /* only bounds support */ 00726 INIT_MINMAX(min, max); 00727 minmax_object_duplis(scene, ob, min, max); 00728 mid_v3_v3v3(cent, min, max); 00729 invert_m4_m4(ob->imat, ob->obmat); 00730 mul_m4_v3(ob->imat, cent); 00731 } 00732 00733 add_v3_v3(ob->dup_group->dupli_ofs, cent); 00734 00735 tot_change++; 00736 ob->dup_group->id.flag |= LIB_DOIT; 00737 do_inverse_offset= TRUE; 00738 } 00739 } 00740 } 00741 else if (((ID *)ob->data)->lib) { 00742 tot_lib_error++; 00743 } 00744 00745 if(obedit==NULL && ob->type==OB_MESH) { 00746 Mesh *me= ob->data; 00747 00748 if(centermode == ORIGIN_TO_CURSOR) { /* done */ } 00749 else if(around==V3D_CENTROID) { mesh_center_median(me, cent); } 00750 else { mesh_center_bounds(me, cent); } 00751 00752 negate_v3_v3(cent_neg, cent); 00753 mesh_translate(me, cent_neg, 1); 00754 00755 tot_change++; 00756 me->id.flag |= LIB_DOIT; 00757 do_inverse_offset= TRUE; 00758 } 00759 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { 00760 Curve *cu= ob->data; 00761 00762 if(centermode == ORIGIN_TO_CURSOR) { /* done */ } 00763 else if(around==V3D_CENTROID) { curve_center_median(cu, cent); } 00764 else { curve_center_bounds(cu, cent); } 00765 00766 /* don't allow Z change if curve is 2D */ 00767 if((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) 00768 cent[2] = 0.0; 00769 00770 negate_v3_v3(cent_neg, cent); 00771 curve_translate(cu, cent_neg, 1); 00772 00773 tot_change++; 00774 cu->id.flag |= LIB_DOIT; 00775 do_inverse_offset= TRUE; 00776 00777 if(obedit) { 00778 if (centermode == GEOMETRY_TO_ORIGIN) { 00779 DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); 00780 } 00781 break; 00782 } 00783 } 00784 else if(ob->type==OB_FONT) { 00785 /* get from bb */ 00786 00787 Curve *cu= ob->data; 00788 00789 if(cu->bb==NULL && (centermode != ORIGIN_TO_CURSOR)) { 00790 /* do nothing*/ 00791 } 00792 else { 00793 if(centermode == ORIGIN_TO_CURSOR) { 00794 /* done */ 00795 } 00796 else { 00797 cent[0]= 0.5f * ( cu->bb->vec[4][0] + cu->bb->vec[0][0]); 00798 cent[1]= 0.5f * ( cu->bb->vec[0][1] + cu->bb->vec[2][1]) - 0.5f; /* extra 0.5 is the height o above line */ 00799 } 00800 00801 cent[2]= 0.0f; 00802 00803 cu->xof= cu->xof - (cent[0] / cu->fsize); 00804 cu->yof= cu->yof - (cent[1] / cu->fsize); 00805 00806 tot_change++; 00807 cu->id.flag |= LIB_DOIT; 00808 do_inverse_offset= TRUE; 00809 } 00810 } 00811 else if(ob->type==OB_ARMATURE) { 00812 bArmature *arm = ob->data; 00813 00814 if(ID_REAL_USERS(arm) > 1) { 00815 /*BKE_report(op->reports, RPT_ERROR, "Can't apply to a multi user armature"); 00816 return;*/ 00817 tot_multiuser_arm_error++; 00818 } 00819 else { 00820 /* Function to recenter armatures in editarmature.c 00821 * Bone + object locations are handled there. 00822 */ 00823 docenter_armature(scene, ob, cursor, centermode, around); 00824 00825 tot_change++; 00826 arm->id.flag |= LIB_DOIT; 00827 /* do_inverse_offset= TRUE; */ /* docenter_armature() handles this */ 00828 00829 where_is_object(scene, ob); 00830 where_is_pose(scene, ob); /* needed for bone parents */ 00831 00832 ignore_parent_tx(bmain, scene, ob); 00833 00834 if(obedit) 00835 break; 00836 } 00837 } 00838 00839 /* offset other selected objects */ 00840 if(do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) { 00841 /* was the object data modified 00842 * note: the functions above must set 'cent' */ 00843 copy_v3_v3(centn, cent); 00844 mul_mat3_m4_v3(ob->obmat, centn); /* ommit translation part */ 00845 add_v3_v3(ob->loc, centn); 00846 00847 where_is_object(scene, ob); 00848 if(ob->type==OB_ARMATURE) { 00849 where_is_pose(scene, ob); /* needed for bone parents */ 00850 } 00851 00852 ignore_parent_tx(bmain, scene, ob); 00853 00854 /* other users? */ 00855 CTX_DATA_BEGIN(C, Object*, ob_other, selected_editable_objects) { 00856 if( (ob_other->flag & OB_DONE)==0 && 00857 ( (ob->data && (ob->data == ob_other->data)) || 00858 (ob->dup_group==ob_other->dup_group && (ob->transflag|ob_other->transflag) & OB_DUPLIGROUP) ) 00859 ) { 00860 ob_other->flag |= OB_DONE; 00861 DAG_id_tag_update(&ob_other->id, OB_RECALC_OB|OB_RECALC_DATA); 00862 00863 copy_v3_v3(centn, cent); 00864 mul_mat3_m4_v3(ob_other->obmat, centn); /* ommit translation part */ 00865 add_v3_v3(ob_other->loc, centn); 00866 00867 where_is_object(scene, ob_other); 00868 if(ob_other->type==OB_ARMATURE) { 00869 where_is_pose(scene, ob_other); /* needed for bone parents */ 00870 } 00871 ignore_parent_tx(bmain, scene, ob_other); 00872 } 00873 } 00874 CTX_DATA_END; 00875 } 00876 } 00877 } 00878 CTX_DATA_END; 00879 00880 for (tob= bmain->object.first; tob; tob= tob->id.next) 00881 if(tob->data && (((ID *)tob->data)->flag & LIB_DOIT)) 00882 DAG_id_tag_update(&tob->id, OB_RECALC_OB|OB_RECALC_DATA); 00883 00884 if (tot_change) { 00885 DAG_ids_flush_update(bmain, 0); 00886 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); 00887 } 00888 00889 /* Warn if any errors occurred */ 00890 if (tot_lib_error+tot_multiuser_arm_error) { 00891 BKE_reportf(op->reports, RPT_WARNING, "%i Object(s) Not Centered, %i Changed:",tot_lib_error+tot_multiuser_arm_error, tot_change); 00892 if (tot_lib_error) 00893 BKE_reportf(op->reports, RPT_WARNING, "|%i linked library objects",tot_lib_error); 00894 if (tot_multiuser_arm_error) 00895 BKE_reportf(op->reports, RPT_WARNING, "|%i multiuser armature object(s)",tot_multiuser_arm_error); 00896 } 00897 00898 return OPERATOR_FINISHED; 00899 } 00900 00901 void OBJECT_OT_origin_set(wmOperatorType *ot) 00902 { 00903 static EnumPropertyItem prop_set_center_types[] = { 00904 {GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"}, 00905 {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry", "Move object origin to center of object geometry"}, 00906 {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor", "Move object origin to position of the 3d cursor"}, 00907 {0, NULL, 0, NULL, NULL} 00908 }; 00909 00910 static EnumPropertyItem prop_set_bounds_types[] = { 00911 {V3D_CENTROID, "MEDIAN", 0, "Median Center", ""}, 00912 {V3D_CENTER, "BOUNDS", 0, "Bounds Center", ""}, 00913 {0, NULL, 0, NULL, NULL} 00914 }; 00915 00916 /* identifiers */ 00917 ot->name= "Set Origin"; 00918 ot->description = "Set the object's origin, by either moving the data, or set to center of data, or use 3d cursor"; 00919 ot->idname= "OBJECT_OT_origin_set"; 00920 00921 /* api callbacks */ 00922 ot->invoke= WM_menu_invoke; 00923 ot->exec= object_origin_set_exec; 00924 00925 ot->poll= ED_operator_scene_editable; 00926 00927 /* flags */ 00928 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00929 00930 ot->prop= RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", ""); 00931 RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_CENTROID, "Center", ""); 00932 } 00933