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