/* helper call for armature_bone_rename */ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, const char *oldname, const char *newname) { bConstraint *curcon; bConstraintTarget *ct; for (curcon = conlist->first; curcon; curcon = curcon->next) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); ListBase targets = {NULL, NULL}; /* constraint targets */ if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(curcon, &targets); for (ct = targets.first; ct; ct = ct->next) { if (ct->tar == ob) { if (STREQ(ct->subtarget, oldname)) { BLI_strncpy(ct->subtarget, newname, MAXBONENAME); } } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(curcon, &targets, 0); } /* action constraints */ if (curcon->type == CONSTRAINT_TYPE_ACTION) { bActionConstraint *actcon = (bActionConstraint *)curcon->data; BKE_action_fix_paths_rename(&ob->id, actcon->act, "pose.bones", oldname, newname, 0, 0, 1); } } }
void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames ) { ListBase *conlist = get_active_constraints(ob); if (conlist == NULL) return; bConstraint *con; for (con = (bConstraint *)conlist->first; con; con = con->next) { ListBase targets = {NULL, NULL}; bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (!validateConstraints(con)) continue; if (cti && cti->get_constraint_targets) { bConstraintTarget *ct; Object *obtar; /* get targets * - constraints should use ct->matrix, not directly accessing values * - ct->matrix members have not yet been calculated here! */ cti->get_constraint_targets(con, &targets); for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { obtar = ct->tar; if (obtar) find_frames(obtar, frames); } if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 1); } } }
void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]) { ListBase *conlist = get_active_constraints(ob); bConstraint *con; for (con = (bConstraint *)conlist->first; con; con = con->next) { ListBase targets = {NULL, NULL}; bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti && cti->get_constraint_targets) { bConstraintTarget *ct; Object *obtar; cti->get_constraint_targets(con, &targets); for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { obtar = ct->tar; if (obtar) { BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM); BKE_object_where_is_calc_time(scene, obtar, ctime); } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 1); } } BKE_object_where_is_calc_time(scene, ob, ctime); copy_m4_m4(mat, ob->obmat); }
static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat[4][4]) { bool found = false; for (bConstraint *con = ob->constraints.first; con != NULL; con = con->next) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti == NULL) { continue; } if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) { bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data; if (!found) { Object *cam = data->camera ? data->camera : scene->camera; BKE_object_where_is_calc_mat4(cam, invmat); } mul_m4_m4m4(invmat, invmat, data->invmat); found = true; } } if (found) { invert_m4(invmat); } else { unit_m4(invmat); } }
static void joined_armature_fix_links_constraints( Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone, ListBase *lb) { bConstraint *con; for (con = lb->first; con; con = con->next) { bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; /* constraint targets */ if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); for (ct = targets.first; ct; ct = ct->next) { if (ct->tar == srcArm) { if (ct->subtarget[0] == '\0') { ct->tar = tarArm; } else if (STREQ(ct->subtarget, pchan->name)) { ct->tar = tarArm; BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget)); } } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 0); } /* action constraint? (pose constraints only) */ if (con->type == CONSTRAINT_TYPE_ACTION) { bActionConstraint *data = con->data; // XXX old animation system bAction *act; bActionChannel *achan; if (data->act) { act = data->act; for (achan = act->chanbase.first; achan; achan = achan->next) { if (STREQ(achan->name, pchan->name)) { BLI_strncpy(achan->name, curbone->name, sizeof(achan->name)); } } } } } }
bool AnimationExporter::validateConstraints(bConstraint *con) { bool valid = true; bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); /* these we can skip completely (invalid constraints...) */ if (cti == NULL) valid = false; if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false; /* these constraints can't be evaluated anyway */ if (cti->evaluate_constraint == NULL) valid = false; /* influence == 0 should be ignored */ if (con->enforce == 0.0f) valid = false; return valid; }
static Object *object_solver_camera(Scene *scene, Object *ob) { for (bConstraint *con = ob->constraints.first; con != NULL; con = con->next) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti == NULL) { continue; } if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) { bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data; return (data->camera != NULL) ? data->camera : scene->camera; } } return NULL; }
static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bArmature *arm = (bArmature *)ob->data; bConstraint *con; int found = 0; CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) { if (pchan->bone->flag & BONE_SELECTED) { for (con = pchan->constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); for (ct = targets.first; ct; ct = ct->next) { if ((ct->tar == ob) && (ct->subtarget[0])) { bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget); if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) { pchanc->bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL; found = 1; } } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 1); } } } } CTX_DATA_END; if (!found) return OPERATOR_CANCELLED; /* updates */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } return OPERATOR_FINISHED; }
/* * Note: When duplicating cross objects, editbones here is the list of bones * from the SOURCE object but ob is the DESTINATION object * */ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Object *src_ob, Object *dst_ob) { /* If an edit bone has been duplicated, lets * update it's constraints if the subtarget * they point to has also been duplicated */ EditBone *oldtarget, *newtarget; bPoseChannel *pchan; bConstraint *curcon; ListBase *conlist; if ((pchan = BKE_pose_channel_verify(dst_ob->pose, dupBone->name))) { if ((conlist = &pchan->constraints)) { for (curcon = conlist->first; curcon; curcon = curcon->next) { /* does this constraint have a subtarget in * this armature? */ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(curcon, &targets); for (ct = targets.first; ct; ct = ct->next) { if ((ct->tar == src_ob) && (ct->subtarget[0])) { ct->tar = dst_ob; /* update target */ oldtarget = get_named_editbone(editbones, ct->subtarget); if (oldtarget) { /* was the subtarget bone duplicated too? If * so, update the constraint to point at the * duplicate of the old subtarget. */ if (oldtarget->temp.ebone) { newtarget = oldtarget->temp.ebone; BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget)); } } } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(curcon, &targets, 0); } } } } }
void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter) { // first delete any existing constraint (should not have any) while (!m_controlledConstraints.Empty()) { BL_ArmatureConstraint* constraint = m_controlledConstraints.Remove(); delete constraint; } m_constraintNumber = 0; // list all the constraint and convert them to BL_ArmatureConstraint // get the persistent pose structure bPoseChannel* pchan; bConstraint* pcon; const bConstraintTypeInfo* cti; Object* blendtarget; KX_GameObject* gametarget; KX_GameObject* gamesubtarget; // and locate the constraint for (pchan = (bPoseChannel *)m_pose->chanbase.first; pchan; pchan = pchan->next) { for (pcon = (bConstraint *)pchan->constraints.first; pcon; pcon = pcon->next) { if (pcon->flag & CONSTRAINT_DISABLE) continue; // which constraint should we support? switch (pcon->type) { case CONSTRAINT_TYPE_TRACKTO: case CONSTRAINT_TYPE_DAMPTRACK: case CONSTRAINT_TYPE_KINEMATIC: case CONSTRAINT_TYPE_ROTLIKE: case CONSTRAINT_TYPE_LOCLIKE: case CONSTRAINT_TYPE_MINMAX: case CONSTRAINT_TYPE_SIZELIKE: case CONSTRAINT_TYPE_LOCKTRACK: case CONSTRAINT_TYPE_STRETCHTO: case CONSTRAINT_TYPE_CLAMPTO: case CONSTRAINT_TYPE_TRANSFORM: case CONSTRAINT_TYPE_DISTLIMIT: case CONSTRAINT_TYPE_TRANSLIKE: cti = BKE_constraint_typeinfo_get(pcon); gametarget = gamesubtarget = NULL; if (cti && cti->get_constraint_targets) { ListBase listb = { NULL, NULL }; cti->get_constraint_targets(pcon, &listb); if (listb.first) { bConstraintTarget* target = (bConstraintTarget*)listb.first; if (target->tar && target->tar != m_objArma) { // only remember external objects, self target is handled automatically blendtarget = target->tar; gametarget = converter->FindGameObject(blendtarget); } if (target->next != NULL) { // secondary target target = target->next; if (target->tar && target->tar != m_objArma) { // only track external object blendtarget = target->tar; gamesubtarget = converter->FindGameObject(blendtarget); } } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(pcon, &listb, 1); } BL_ArmatureConstraint* constraint = new BL_ArmatureConstraint(this, pchan, pcon, gametarget, gamesubtarget); m_controlledConstraints.AddBack(constraint); m_constraintNumber++; } } } // If we have constraints, make sure we get treated as an "animated" object if (m_constraintNumber > 0) GetActionManager(); }
/** * Selectively remove pose channels. */ void BKE_pose_channels_remove( Object *ob, bool (*filter_fn)(const char *bone_name, void *user_data), void *user_data) { /* Erase any associated pose channel, along with any references to them */ if (ob->pose) { bPoseChannel *pchan, *pchan_next; bConstraint *con; for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan_next) { pchan_next = pchan->next; if (filter_fn(pchan->name, user_data)) { /* Bone itself is being removed */ BKE_pose_channel_free(pchan); if (ob->pose->chanhash) { BLI_ghash_remove(ob->pose->chanhash, pchan->name, NULL, NULL); } BLI_freelinkN(&ob->pose->chanbase, pchan); } else { /* Maybe something the bone references is being removed instead? */ for (con = pchan->constraints.first; con; con = con->next) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); for (ct = targets.first; ct; ct = ct->next) { if (ct->tar == ob) { if (ct->subtarget[0]) { if (filter_fn(ct->subtarget, user_data)) { con->flag |= CONSTRAINT_DISABLE; ct->subtarget[0] = 0; } } } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 0); } } if (pchan->bbone_prev) { if (filter_fn(pchan->bbone_prev->name, user_data)) pchan->bbone_prev = NULL; } if (pchan->bbone_next) { if (filter_fn(pchan->bbone_next->name, user_data)) pchan->bbone_next = NULL; } if (pchan->custom_tx) { if (filter_fn(pchan->custom_tx->name, user_data)) pchan->custom_tx = NULL; } } } } }
/* Helper function for armature separating - link fixing */ static void separated_armature_fix_links(Object *origArm, Object *newArm) { Object *ob; bPoseChannel *pchan; bConstraint *con; ListBase *opchans, *npchans; /* get reference to list of bones in original and new armatures */ opchans = &origArm->pose->chanbase; npchans = &newArm->pose->chanbase; /* let's go through all objects in database */ for (ob = G.main->object.first; ob; ob = ob->id.next) { /* do some object-type specific things */ if (ob->type == OB_ARMATURE) { for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; /* constraint targets */ if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); for (ct = targets.first; ct; ct = ct->next) { /* any targets which point to original armature are redirected to the new one only if: * - the target isn't origArm/newArm itself * - the target is one that can be found in newArm/origArm */ if (ct->subtarget[0] != 0) { if (ct->tar == origArm) { if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) { ct->tar = newArm; } } else if (ct->tar == newArm) { if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) { ct->tar = origArm; } } } } if (cti->flush_constraint_targets) { cti->flush_constraint_targets(con, &targets, 0); } } } } } /* fix object-level constraints */ if (ob != origArm) { for (con = ob->constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; /* constraint targets */ if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); for (ct = targets.first; ct; ct = ct->next) { /* any targets which point to original armature are redirected to the new one only if: * - the target isn't origArm/newArm itself * - the target is one that can be found in newArm/origArm */ if (ct->subtarget[0] != '\0') { if (ct->tar == origArm) { if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) { ct->tar = newArm; } } else if (ct->tar == newArm) { if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) { ct->tar = origArm; } } } } if (cti->flush_constraint_targets) { cti->flush_constraint_targets(con, &targets, 0); } } } } /* See if an object is parented to this armature */ if (ob->parent && (ob->parent == origArm)) { /* Is object parented to a bone of this src armature? */ if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) { if (BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) { ob->parent = newArm; } } } } }
void SceneExporter::writeNodes(Object *ob, Scene *sce) { // Add associated armature first if available bool armature_exported = false; Object *ob_arm = bc_get_assigned_armature(ob); if (ob_arm != NULL) { armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm); if (armature_exported && bc_is_marked(ob_arm)) { bc_remove_mark(ob_arm); writeNodes(ob_arm, sce); armature_exported = true; } } COLLADASW::Node colladaNode(mSW); colladaNode.setNodeId(translate_id(id_name(ob))); colladaNode.setNodeName(translate_id(id_name(ob))); colladaNode.setType(COLLADASW::Node::NODE); colladaNode.start(); std::list<Object *> child_objects; // list child objects LinkNode *node; for (node=this->export_settings->export_set; node; node=node->next) { // cob - child object Object *cob = (Object *)node->link; if (cob->parent == ob) { switch (cob->type) { case OB_MESH: case OB_CAMERA: case OB_LAMP: case OB_EMPTY: case OB_ARMATURE: if (bc_is_marked(cob)) child_objects.push_back(cob); break; } } } if (ob->type == OB_MESH && armature_exported) // for skinned mesh we write obmat in <bind_shape_matrix> TransformWriter::add_node_transform_identity(colladaNode); else { TransformWriter::add_node_transform_ob(colladaNode, ob, this->transformation_type); } // <instance_geometry> if (ob->type == OB_MESH) { bool instance_controller_created = false; if (armature_exported) { instance_controller_created = arm_exporter->add_instance_controller(ob); } if (!instance_controller_created) { COLLADASW::InstanceGeometry instGeom(mSW); instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation))); instGeom.setName(translate_id(id_name(ob))); InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only); instGeom.add(); } } // <instance_controller> else if (ob->type == OB_ARMATURE) { arm_exporter->add_armature_bones(ob, sce, this, child_objects); } // <instance_camera> else if (ob->type == OB_CAMERA) { COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob))); instCam.add(); } // <instance_light> else if (ob->type == OB_LAMP) { COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob))); instLa.add(); } // empty object else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLIGROUP if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) { GroupObject *go = NULL; Group *gr = ob->dup_group; /* printf("group detected '%s'\n", gr->id.name + 2); */ for (go = (GroupObject *)(gr->gobject.first); go; go = go->next) { printf("\t%s\n", go->ob->id.name); } } } if (ob->type == OB_ARMATURE) { colladaNode.end(); } if (BLI_listbase_is_empty(&ob->constraints) == false) { bConstraint *con = (bConstraint *) ob->constraints.first; while (con) { std::string con_name(translate_id(con->name)); std::string con_tag = con_name + "_constraint"; printf("%s\n", con_name.c_str()); printf("%s\n\n", con_tag.c_str()); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"type",con->type); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"enforce",con->enforce); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"flag",con->flag); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"headtail",con->headtail); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"own_space",con->ownspace); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"rot_error",con->rot_error); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"tar_space",con->tarspace); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error); //not ideal: add the target object name as another parameter. //No real mapping in the .dae //Need support for multiple target objects also. const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; if (cti && cti->get_constraint_targets) { bConstraintTarget *ct; Object *obtar; cti->get_constraint_targets(con, &targets); for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) { obtar = ct->tar; std::string tar_id((obtar) ? id_name(obtar) : ""); colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"target_id",tar_id); } if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 1); } con = con->next; } } for (std::list<Object *>::iterator i = child_objects.begin(); i != child_objects.end(); ++i) { if (bc_is_marked(*i)) { bc_remove_mark(*i); writeNodes(*i, sce); } } if (ob->type != OB_ARMATURE) colladaNode.end(); }