static wmKeyMapItem *wm_keymap_item_find( const bContext *C, const char *opname, int opcontext, IDProperty *properties, const short hotkey, const bool strict, wmKeyMap **keymap_r) { wmKeyMapItem *found = wm_keymap_item_find_props(C, opname, opcontext, properties, strict, hotkey, keymap_r); if (!found && properties) { wmOperatorType *ot = WM_operatortype_find(opname, TRUE); if (ot) { /* make a copy of the properties and set any unset props * to their default values, so the ID property compare function succeeds */ PointerRNA opptr; IDProperty *properties_default = IDP_CopyProperty(properties); RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); if (WM_operator_properties_default(&opptr, true) || (!strict && ot->prop && RNA_property_is_set(&opptr, ot->prop))) { /* for operator that has enum menu, unset it so it always matches */ if (!strict && ot->prop) { RNA_property_unset(&opptr, ot->prop); } found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, false, hotkey, keymap_r); } IDP_FreeProperty(properties_default); MEM_freeN(properties_default); } } return found; }
static void fcm_python_copy(FModifier *fcm, FModifier *src) { FMod_Python *pymod = (FMod_Python *)fcm->data; FMod_Python *opymod = (FMod_Python *)src->data; pymod->prop = IDP_CopyProperty(opymod->prop); }
/* used everywhere in blenkernel and text.c */ void *copy_libblock(void *rt) { ID *idn, *id; ListBase *lb; char *cp, *cpn; int idn_len; id= rt; lb= wich_libbase(G.main, GS(id->name)); idn= alloc_libblock(lb, GS(id->name), id->name+2); if(idn==NULL) { printf("ERROR: Illegal ID name for %s (Crashing now)\n", id->name); } idn_len= MEM_allocN_len(idn); if(idn_len - sizeof(ID) > 0) { cp= (char *)id; cpn= (char *)idn; memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID)); } id->newid= idn; idn->flag |= LIB_NEW; if (id->properties) idn->properties = IDP_CopyProperty(id->properties); /* the duplicate should get a copy of the animdata */ id_copy_animdata(idn); return idn; }
/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */ static void poselib_backup_posecopy (tPoseLib_PreviewData *pld) { bActionGroup *agrp; bPoseChannel *pchan; /* for each posechannel that has an actionchannel in */ for (agrp= pld->act->groups.first; agrp; agrp= agrp->next) { /* try to find posechannel */ pchan= get_pose_channel(pld->pose, agrp->name); /* backup data if available */ if (pchan) { tPoseLib_Backup *plb; /* store backup */ plb= MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup"); plb->pchan= pchan; memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel)); if (pchan->prop) plb->oldprops= IDP_CopyProperty(pchan->prop); BLI_addtail(&pld->backups, plb); /* mark as being affected */ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) pld->selcount++; pld->totcount++; } } }
void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb) { BLI_assert(dimb != simb); if (simb->metadata) { IMB_metadata_free(dimb->metadata); dimb->metadata = IDP_CopyProperty(simb->metadata); } }
/* material nodes use this since they are not treated as libdata */ void copy_libblock_data(ID *id, const ID *id_from, const short do_action) { if (id_from->properties) id->properties = IDP_CopyProperty(id_from->properties); /* the duplicate should get a copy of the animdata */ id_copy_animdata(id, do_action); }
void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi) { wmWindowManager *wm = CTX_wm_manager(C); wmKeyMap *defaultmap, *addonmap; wmKeyMapItem *orig; if(!keymap) return; /* construct default keymap from preset + addons */ defaultmap= wm_keymap_preset(wm, keymap); addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); if(addonmap) { defaultmap = wm_keymap_copy(defaultmap); wm_keymap_addon_add(defaultmap, addonmap); } /* find original item */ orig = WM_keymap_item_find_id(defaultmap, kmi->id); if(orig) { /* restore to original */ if(strcmp(orig->idname, kmi->idname) != 0) { BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname)); WM_keymap_properties_reset(kmi, NULL); } if (orig->properties) { if(kmi->properties) { IDP_FreeProperty(kmi->properties); MEM_freeN(kmi->properties); kmi->properties= NULL; } kmi->properties= IDP_CopyProperty(orig->properties); kmi->ptr->data= kmi->properties; } kmi->propvalue = orig->propvalue; kmi->type = orig->type; kmi->val = orig->val; kmi->shift = orig->shift; kmi->ctrl = orig->ctrl; kmi->alt = orig->alt; kmi->oskey = orig->oskey; kmi->keymodifier = orig->keymodifier; kmi->maptype = orig->maptype; WM_keyconfig_update_tag(keymap, kmi); } /* free temporary keymap */ if(addonmap) { WM_keymap_free(defaultmap); MEM_freeN(defaultmap); } }
/* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan) { ListBase curves = {NULL, NULL}; int transFlags = action_get_item_transforms(act, ob, pchan, &curves); pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE); /* check if any transforms found... */ if (transFlags) { /* make new linkage data */ tPChanFCurveLink *pfl = MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink"); PointerRNA ptr; pfl->fcurves = curves; pfl->pchan = pchan; /* get the RNA path to this pchan - this needs to be freed! */ RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr); pfl->pchan_path = RNA_path_from_ID_to_struct(&ptr); /* add linkage data to operator data */ BLI_addtail(pfLinks, pfl); /* set pchan's transform flags */ if (transFlags & ACT_TRANS_LOC) pchan->flag |= POSE_LOC; if (transFlags & ACT_TRANS_ROT) pchan->flag |= POSE_ROT; if (transFlags & ACT_TRANS_SCALE) pchan->flag |= POSE_SIZE; if (transFlags & ACT_TRANS_BBONE) pchan->flag |= POSE_BBONE_SHAPE; /* store current transforms */ copy_v3_v3(pfl->oldloc, pchan->loc); copy_v3_v3(pfl->oldrot, pchan->eul); copy_v3_v3(pfl->oldscale, pchan->size); copy_qt_qt(pfl->oldquat, pchan->quat); copy_v3_v3(pfl->oldaxis, pchan->rotAxis); pfl->oldangle = pchan->rotAngle; /* store current bbone values */ pfl->roll1 = pchan->roll1; pfl->roll2 = pchan->roll2; pfl->curveInX = pchan->curveInX; pfl->curveInY = pchan->curveInY; pfl->curveOutX = pchan->curveOutX; pfl->curveOutY = pchan->curveOutY; pfl->ease1 = pchan->ease1; pfl->ease2 = pchan->ease2; pfl->scaleIn = pchan->scaleIn; pfl->scaleOut = pchan->scaleOut; /* make copy of custom properties */ if (pchan->prop && (transFlags & ACT_TRANS_PROP)) pfl->oldprops = IDP_CopyProperty(pchan->prop); } }
static void node_copy_script(bNode *orig_node, bNode *new_node) { NodeShaderScript *orig_nss = orig_node->storage; NodeShaderScript *new_nss = MEM_dupallocN(orig_nss); if (orig_nss->bytecode) new_nss->bytecode = MEM_dupallocN(orig_nss->bytecode); if (orig_nss->prop) new_nss->prop = IDP_CopyProperty(orig_nss->prop); new_node->storage = new_nss; }
/** * Allocate a new pose on the heap, and copy the src pose and it's channels * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL. * * \param dst Should be freed already, makes entire duplicate. */ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints) { bPose *outPose; bPoseChannel *pchan; ListBase listb; if (!src) { *dst = NULL; return; } outPose = MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); outPose->iksolver = src->iksolver; outPose->ikdata = NULL; outPose->ikparam = MEM_dupallocN(src->ikparam); outPose->avs = src->avs; for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->custom) { id_us_plus(&pchan->custom->id); } /* warning, O(n2) here, but it's a rarely used feature. */ if (pchan->custom_tx) { pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name); } if (copy_constraints) { BKE_constraints_copy(&listb, &pchan->constraints, true); // BKE_constraints_copy NULLs listb pchan->constraints = listb; pchan->mpath = NULL; /* motion paths should not get copied yet... */ } if (pchan->prop) { pchan->prop = IDP_CopyProperty(pchan->prop); } } /* for now, duplicate Bone Groups too when doing this */ if (copy_constraints) { BLI_duplicatelist(&outPose->agroups, &src->agroups); } *dst = outPose; }
/** * Copy the internal members of each pose channel including constraints * and ID-Props, used when duplicating bones in editmode. * (unlike copy_pose_channel_data which only does posing-related stuff). * * \note use when copying bones in editmode (on returned value from #BKE_pose_channel_verify) */ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_from) { /* copy transform locks */ pchan->protectflag = pchan_from->protectflag; /* copy rotation mode */ pchan->rotmode = pchan_from->rotmode; /* copy bone group */ pchan->agrp_index = pchan_from->agrp_index; /* ik (dof) settings */ pchan->ikflag = pchan_from->ikflag; copy_v3_v3(pchan->limitmin, pchan_from->limitmin); copy_v3_v3(pchan->limitmax, pchan_from->limitmax); copy_v3_v3(pchan->stiffness, pchan_from->stiffness); pchan->ikstretch = pchan_from->ikstretch; pchan->ikrotweight = pchan_from->ikrotweight; pchan->iklinweight = pchan_from->iklinweight; /* bbone settings (typically not animated) */ pchan->bboneflag = pchan_from->bboneflag; pchan->bbone_next = pchan_from->bbone_next; pchan->bbone_prev = pchan_from->bbone_prev; /* constraints */ BKE_constraints_copy(&pchan->constraints, &pchan_from->constraints, true); /* id-properties */ if (pchan->prop) { /* unlikely but possible it exists */ IDP_FreeProperty(pchan->prop); MEM_freeN(pchan->prop); pchan->prop = NULL; } if (pchan_from->prop) { pchan->prop = IDP_CopyProperty(pchan_from->prop); } /* custom shape */ pchan->custom = pchan_from->custom; if (pchan->custom) { id_us_plus(&pchan->custom->id); } pchan->custom_scale = pchan_from->custom_scale; }
static wmKeyMapItem *wm_keymap_item_copy(wmKeyMapItem *kmi) { wmKeyMapItem *kmin = MEM_dupallocN(kmi); kmin->prev= kmin->next= NULL; kmin->flag &= ~KMI_UPDATE; if(kmin->properties) { kmin->ptr= MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr"); WM_operator_properties_create(kmin->ptr, kmin->idname); kmin->properties= IDP_CopyProperty(kmin->properties); kmin->ptr->data= kmin->properties; } return kmin; }
/* dst should be freed already, makes entire duplicate */ void copy_pose (bPose **dst, bPose *src, int copycon) { bPose *outPose; bPoseChannel *pchan; ListBase listb; if (!src) { *dst=NULL; return; } if (*dst==src) { printf("copy_pose source and target are the same\n"); *dst=NULL; return; } outPose= MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); outPose->iksolver = src->iksolver; outPose->ikdata = NULL; outPose->ikparam = MEM_dupallocN(src->ikparam); for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) { // TODO: rename this argument... if (copycon) { copy_constraints(&listb, &pchan->constraints, TRUE); // copy_constraints NULLs listb pchan->constraints= listb; pchan->path= NULL; // XXX remove this line when the new motionpaths are ready... (depreceated code) pchan->mpath= NULL; /* motion paths should not get copied yet... */ } if(pchan->prop) { pchan->prop= IDP_CopyProperty(pchan->prop); } } /* for now, duplicate Bone Groups too when doing this */ if (copycon) BLI_duplicatelist(&outPose->agroups, &src->agroups); *dst=outPose; }
EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase *editbones, Object *src_ob, Object *dst_ob) { EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone"); /* Copy data from old bone to new bone */ memcpy(eBone, curBone, sizeof(EditBone)); curBone->temp.ebone = eBone; eBone->temp.ebone = curBone; if (name != NULL) { BLI_strncpy(eBone->name, name, sizeof(eBone->name)); } unique_editbone_name(editbones, eBone->name, NULL); BLI_addtail(editbones, eBone); /* copy the ID property */ if (curBone->prop) eBone->prop = IDP_CopyProperty(curBone->prop); /* Lets duplicate the list of constraints that the * current bone has. */ if (src_ob->pose) { bPoseChannel *chanold, *channew; chanold = BKE_pose_channel_verify(src_ob->pose, curBone->name); if (chanold) { /* WARNING: this creates a new posechannel, but there will not be an attached bone * yet as the new bones created here are still 'EditBones' not 'Bones'. */ channew = BKE_pose_channel_verify(dst_ob->pose, eBone->name); if (channew) { BKE_pose_channel_copy_data(channew, chanold); } } } return eBone; }
/* dst should be freed already, makes entire duplicate */ void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon) { bPose *outPose; bPoseChannel *pchan; ListBase listb; if (!src) { *dst = NULL; return; } outPose = MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); outPose->iksolver = src->iksolver; outPose->ikdata = NULL; outPose->ikparam = MEM_dupallocN(src->ikparam); outPose->avs = src->avs; for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { /* TODO: rename this argument... */ if (copycon) { BKE_copy_constraints(&listb, &pchan->constraints, TRUE); // BKE_copy_constraints NULLs listb pchan->constraints = listb; pchan->mpath = NULL; /* motion paths should not get copied yet... */ } if (pchan->prop) { pchan->prop = IDP_CopyProperty(pchan->prop); } } /* for now, duplicate Bone Groups too when doing this */ if (copycon) BLI_duplicatelist(&outPose->agroups, &src->agroups); *dst = outPose; }
void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src) { EditBone *ebone_src; EditBone *ebone_dst; BLI_assert(BLI_listbase_is_empty(lb_dst)); for (ebone_src = lb_src->first; ebone_src; ebone_src = ebone_src->next) { ebone_dst = MEM_dupallocN(ebone_src); if (ebone_dst->prop) { ebone_dst->prop = IDP_CopyProperty(ebone_dst->prop); } ebone_src->temp.ebone = ebone_dst; BLI_addtail(lb_dst, ebone_dst); } /* set pointers */ for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) { if (ebone_dst->parent) { ebone_dst->parent = ebone_dst->parent->temp.ebone; } } }
/* makes copies of internal data, unlike copy_pose_channel_data which only * copies the pose state. * hint: use when copying bones in editmode (on returned value from verify_pose_channel) */ void duplicate_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *pchan_from) { /* copy transform locks */ pchan->protectflag = pchan_from->protectflag; /* copy rotation mode */ pchan->rotmode = pchan_from->rotmode; /* copy bone group */ pchan->agrp_index= pchan_from->agrp_index; /* ik (dof) settings */ pchan->ikflag = pchan_from->ikflag; VECCOPY(pchan->limitmin, pchan_from->limitmin); VECCOPY(pchan->limitmax, pchan_from->limitmax); VECCOPY(pchan->stiffness, pchan_from->stiffness); pchan->ikstretch= pchan_from->ikstretch; pchan->ikrotweight= pchan_from->ikrotweight; pchan->iklinweight= pchan_from->iklinweight; /* constraints */ copy_constraints(&pchan->constraints, &pchan_from->constraints, TRUE); /* id-properties */ if(pchan->prop) { /* unlikely but possible it exists */ IDP_FreeProperty(pchan->prop); MEM_freeN(pchan->prop); pchan->prop= NULL; } if(pchan_from->prop) { pchan->prop= IDP_CopyProperty(pchan_from->prop); } /* custom shape */ pchan->custom= pchan_from->custom; }
/* put EditMode back in Object */ void ED_armature_from_edit(bArmature *arm) { EditBone *eBone, *neBone; Bone *newBone; Object *obt; /* armature bones */ BKE_armature_bonelist_free(&arm->bonebase); arm->act_bone = NULL; /* remove zero sized bones, this gives unstable restposes */ for (eBone = arm->edbo->first; eBone; eBone = neBone) { float len = len_v3v3(eBone->head, eBone->tail); neBone = eBone->next; if (len <= 0.000001f) { /* FLT_EPSILON is too large? */ EditBone *fBone; /* Find any bones that refer to this bone */ for (fBone = arm->edbo->first; fBone; fBone = fBone->next) { if (fBone->parent == eBone) fBone->parent = eBone->parent; } if (G.debug & G_DEBUG) printf("Warning: removed zero sized bone: %s\n", eBone->name); bone_free(arm, eBone); } } /* Copy the bones from the editData into the armature */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = MEM_callocN(sizeof(Bone), "bone"); eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */ BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name)); copy_v3_v3(newBone->arm_head, eBone->head); copy_v3_v3(newBone->arm_tail, eBone->tail); newBone->arm_roll = eBone->roll; newBone->flag = eBone->flag; if (eBone == arm->act_edbone) { /* don't change active selection, this messes up separate which uses * editmode toggle and can separate active bone which is de-selected originally */ /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */ arm->act_bone = newBone; } newBone->roll = 0.0f; newBone->weight = eBone->weight; newBone->dist = eBone->dist; newBone->xwidth = eBone->xwidth; newBone->zwidth = eBone->zwidth; newBone->ease1 = eBone->ease1; newBone->ease2 = eBone->ease2; newBone->rad_head = eBone->rad_head; newBone->rad_tail = eBone->rad_tail; newBone->segments = eBone->segments; newBone->layer = eBone->layer; if (eBone->prop) newBone->prop = IDP_CopyProperty(eBone->prop); } /* Fix parenting in a separate pass to ensure ebone->bone connections * are valid at this point */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = eBone->temp.bone; if (eBone->parent) { newBone->parent = eBone->parent->temp.bone; BLI_addtail(&newBone->parent->childbase, newBone); { float M_parentRest[3][3]; float iM_parentRest[3][3]; /* Get the parent's matrix (rotation only) */ ED_armature_ebone_to_mat3(eBone->parent, M_parentRest); /* Invert the parent matrix */ invert_m3_m3(iM_parentRest, M_parentRest); /* Get the new head and tail */ sub_v3_v3v3(newBone->head, eBone->head, eBone->parent->tail); sub_v3_v3v3(newBone->tail, eBone->tail, eBone->parent->tail); mul_m3_v3(iM_parentRest, newBone->head); mul_m3_v3(iM_parentRest, newBone->tail); } } /* ...otherwise add this bone to the armature's bonebase */ else { copy_v3_v3(newBone->head, eBone->head); copy_v3_v3(newBone->tail, eBone->tail); BLI_addtail(&arm->bonebase, newBone); } } /* Make a pass through the new armature to fix rolling */ /* also builds restposition again (like BKE_armature_where_is) */ fix_bonelist_roll(&arm->bonebase, arm->edbo); /* so all users of this armature should get rebuilt */ for (obt = G.main->object.first; obt; obt = obt->id.next) { if (obt->data == arm) BKE_pose_rebuild(obt, arm); } DAG_id_tag_update(&arm->id, 0); }
/** * Move here pose function for game engine so that we can mix with GE objects * Principle is as follow: * Use Blender structures so that BKE_pose_where_is can be used unchanged * Copy the constraint so that they can be enabled/disabled/added/removed at runtime * Don't copy the constraints for the pose used by the Action actuator, it does not need them. * Scan the constraint structures so that the KX equivalent of target objects are identified and * stored in separate list. * When it is about to evaluate the pose, set the KX object position in the obmat of the corresponding * Blender objects and restore after the evaluation. */ static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint) { bPose *out; bPoseChannel *pchan, *outpchan; GHash *ghash; /* the game engine copies the current armature pose and then swaps * the object pose pointer. this makes it possible to change poses * without affecting the original blender data. */ if (!src) { *dst=NULL; return; } else if (*dst==src) { printf("game_copy_pose source and target are the same\n"); *dst=NULL; return; } out= (bPose*)MEM_dupallocN(src); out->chanhash = NULL; out->agroups.first= out->agroups.last= NULL; out->ikdata = NULL; out->ikparam = MEM_dupallocN(src->ikparam); out->flag |= POSE_GAME_ENGINE; BLI_duplicatelist(&out->chanbase, &src->chanbase); /* remap pointers */ ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "game_copy_pose gh"); pchan= (bPoseChannel *)src->chanbase.first; outpchan= (bPoseChannel *)out->chanbase.first; for (; pchan; pchan=pchan->next, outpchan=outpchan->next) BLI_ghash_insert(ghash, pchan, outpchan); for (pchan = (bPoseChannel *)out->chanbase.first; pchan; pchan = pchan->next) { pchan->parent= (bPoseChannel *)BLI_ghash_lookup(ghash, pchan->parent); pchan->child= (bPoseChannel *)BLI_ghash_lookup(ghash, pchan->child); if (copy_constraint) { ListBase listb; // copy all constraint for backward compatibility // BKE_constraints_copy NULLs listb, no need to make extern for this operation. BKE_constraints_copy(&listb, &pchan->constraints, false); pchan->constraints= listb; } else { BLI_listbase_clear(&pchan->constraints); } if (pchan->custom) { id_us_plus(&pchan->custom->id); } // fails to link, props are not used in the BGE yet. #if 0 if (pchan->prop) pchan->prop= IDP_CopyProperty(pchan->prop); #endif pchan->prop= NULL; } BLI_ghash_free(ghash, NULL, NULL); // set acceleration structure for channel lookup BKE_pose_channels_hash_make(out); *dst=out; }
Scene *BKE_scene_copy(Scene *sce, int type) { Scene *scen; ToolSettings *ts; Base *base, *obase; if (type == SCE_COPY_EMPTY) { ListBase lb; /* XXX. main should become an arg */ scen = BKE_scene_add(G.main, sce->id.name + 2); lb = scen->r.layers; scen->r = sce->r; scen->r.layers = lb; scen->unit = sce->unit; scen->physics_settings = sce->physics_settings; scen->gm = sce->gm; scen->audio = sce->audio; MEM_freeN(scen->toolsettings); } else { scen = BKE_libblock_copy(&sce->id); BLI_duplicatelist(&(scen->base), &(sce->base)); clear_id_newpoins(); id_us_plus((ID *)scen->world); id_us_plus((ID *)scen->set); id_us_plus((ID *)scen->gm.dome.warptext); scen->ed = NULL; scen->theDag = NULL; scen->obedit = NULL; scen->stats = NULL; scen->fps_info = NULL; BLI_duplicatelist(&(scen->markers), &(sce->markers)); BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces)); BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers)); BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); if (sce->nodetree) { /* ID's are managed on both copy and switch */ scen->nodetree = ntreeCopyTree(sce->nodetree); ntreeSwitchID(scen->nodetree, &sce->id, &scen->id); } obase = sce->base.first; base = scen->base.first; while (base) { id_us_plus(&base->object->id); if (obase == sce->basact) scen->basact = base; obase = obase->next; base = base->next; } /* copy color management settings */ BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings); BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings); BKE_color_managed_view_settings_copy(&scen->r.im_format.view_settings, &sce->r.im_format.view_settings); BLI_strncpy(scen->sequencer_colorspace_settings.name, sce->sequencer_colorspace_settings.name, sizeof(scen->sequencer_colorspace_settings.name)); /* remove animation used by sequencer */ if (type != SCE_COPY_FULL) remove_sequencer_fcurves(scen); } /* tool settings */ scen->toolsettings = MEM_dupallocN(sce->toolsettings); ts = scen->toolsettings; if (ts) { if (ts->vpaint) { ts->vpaint = MEM_dupallocN(ts->vpaint); ts->vpaint->paintcursor = NULL; ts->vpaint->vpaint_prev = NULL; ts->vpaint->wpaint_prev = NULL; BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint); } if (ts->wpaint) { ts->wpaint = MEM_dupallocN(ts->wpaint); ts->wpaint->paintcursor = NULL; ts->wpaint->vpaint_prev = NULL; ts->wpaint->wpaint_prev = NULL; BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint); } if (ts->sculpt) { ts->sculpt = MEM_dupallocN(ts->sculpt); BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint); } BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint); ts->imapaint.paintcursor = NULL; ts->particle.paintcursor = NULL; } /* make a private copy of the avicodecdata */ if (sce->r.avicodecdata) { scen->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata); scen->r.avicodecdata->lpFormat = MEM_dupallocN(scen->r.avicodecdata->lpFormat); scen->r.avicodecdata->lpParms = MEM_dupallocN(scen->r.avicodecdata->lpParms); } /* make a private copy of the qtcodecdata */ if (sce->r.qtcodecdata) { scen->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata); scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms); } if (sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */ scen->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties); } /* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations * are done outside of blenkernel with ED_objects_single_users! */ /* camera */ if (type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) { ID_NEW(scen->camera); } /* before scene copy */ sound_create_scene(scen); /* world */ if (type == SCE_COPY_FULL) { BKE_copy_animdata_id_action((ID *)scen); if (scen->world) { id_us_plus((ID *)scen->world); scen->world = BKE_world_copy(scen->world); BKE_copy_animdata_id_action((ID *)scen->world); } if (sce->ed) { scen->ed = MEM_callocN(sizeof(Editing), "addseq"); scen->ed->seqbasep = &scen->ed->seqbase; BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL); } } return scen; }
/* converts Bones to EditBone list, used for tools as well */ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone) { EditBone *eBone; EditBone *eBoneAct = NULL; EditBone *eBoneTest = NULL; Bone *curBone; for (curBone = bones->first; curBone; curBone = curBone->next) { eBone = MEM_callocN(sizeof(EditBone), "make_editbone"); /* Copy relevant data from bone to eBone */ eBone->parent = parent; BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name)); eBone->flag = curBone->flag; /* fix selection flags */ if (eBone->flag & BONE_SELECTED) { /* if the bone is selected the copy its root selection to the parents tip */ eBone->flag |= BONE_TIPSEL; if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { eBone->parent->flag |= BONE_TIPSEL; eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */ } else { eBone->flag |= BONE_ROOTSEL; } } else { /* if the bone is not selected, but connected to its parent * always use the parents tip selection state */ if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { eBone->flag &= ~BONE_ROOTSEL; } } copy_v3_v3(eBone->head, curBone->arm_head); copy_v3_v3(eBone->tail, curBone->arm_tail); eBone->roll = curBone->arm_roll; /* rest of stuff copy */ eBone->length = curBone->length; eBone->dist = curBone->dist; eBone->weight = curBone->weight; eBone->xwidth = curBone->xwidth; eBone->zwidth = curBone->zwidth; eBone->ease1 = curBone->ease1; eBone->ease2 = curBone->ease2; eBone->rad_head = curBone->rad_head; eBone->rad_tail = curBone->rad_tail; eBone->segments = curBone->segments; eBone->layer = curBone->layer; if (curBone->prop) eBone->prop = IDP_CopyProperty(curBone->prop); BLI_addtail(edbo, eBone); /* Add children if necessary */ if (curBone->childbase.first) { eBoneTest = make_boneList(edbo, &curBone->childbase, eBone, actBone); if (eBoneTest) eBoneAct = eBoneTest; } if (curBone == actBone) eBoneAct = eBone; } return eBoneAct; }
/* converts Bones to EditBone list, used for tools as well */ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone) { EditBone *eBone; EditBone *eBoneAct = NULL; EditBone *eBoneTest = NULL; Bone *curBone; for (curBone = bones->first; curBone; curBone = curBone->next) { eBone = MEM_callocN(sizeof(EditBone), "make_editbone"); /* Copy relevant data from bone to eBone * Keep selection logic in sync with ED_armature_sync_selection. */ eBone->parent = parent; BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name)); eBone->flag = curBone->flag; /* fix selection flags */ if (eBone->flag & BONE_SELECTED) { /* if the bone is selected the copy its root selection to the parents tip */ eBone->flag |= BONE_TIPSEL; if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { eBone->parent->flag |= BONE_TIPSEL; } /* For connected bones, take care when changing the selection when we have a connected parent, * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */ eBone->flag |= BONE_ROOTSEL; } else { /* if the bone is not selected, but connected to its parent * always use the parents tip selection state */ if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { eBone->flag &= ~BONE_ROOTSEL; } } copy_v3_v3(eBone->head, curBone->arm_head); copy_v3_v3(eBone->tail, curBone->arm_tail); eBone->roll = curBone->arm_roll; /* rest of stuff copy */ eBone->length = curBone->length; eBone->dist = curBone->dist; eBone->weight = curBone->weight; eBone->xwidth = curBone->xwidth; eBone->zwidth = curBone->zwidth; eBone->rad_head = curBone->rad_head; eBone->rad_tail = curBone->rad_tail; eBone->segments = curBone->segments; eBone->layer = curBone->layer; /* Bendy-Bone parameters */ eBone->roll1 = curBone->roll1; eBone->roll2 = curBone->roll2; eBone->curveInX = curBone->curveInX; eBone->curveInY = curBone->curveInY; eBone->curveOutX = curBone->curveOutX; eBone->curveOutY = curBone->curveOutY; eBone->ease1 = curBone->ease1; eBone->ease2 = curBone->ease2; eBone->scaleIn = curBone->scaleIn; eBone->scaleOut = curBone->scaleOut; if (curBone->prop) eBone->prop = IDP_CopyProperty(curBone->prop); BLI_addtail(edbo, eBone); /* Add children if necessary */ if (curBone->childbase.first) { eBoneTest = make_boneList(edbo, &curBone->childbase, eBone, actBone); if (eBoneTest) eBoneAct = eBoneTest; } if (curBone == actBone) eBoneAct = eBone; } return eBoneAct; }
/** * Allocate a new pose on the heap, and copy the src pose and it's channels * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL. * * \param dst Should be freed already, makes entire duplicate. */ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints) { bPose *outPose; bPoseChannel *pchan; ListBase listb; if (!src) { *dst = NULL; return; } outPose = MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); /* Rebuild ghash here too, so that name lookups below won't be too bad... * BUT this will have the penalty that the ghash will be built twice * if BKE_pose_rebuild() gets called after this... */ if (outPose->chanbase.first != outPose->chanbase.last) { outPose->chanhash = NULL; BKE_pose_channels_hash_make(outPose); } outPose->iksolver = src->iksolver; outPose->ikdata = NULL; outPose->ikparam = MEM_dupallocN(src->ikparam); outPose->avs = src->avs; for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->custom) { id_us_plus(&pchan->custom->id); } /* warning, O(n2) here, if done without the hash, but these are rarely used features. */ if (pchan->custom_tx) { pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name); } if (pchan->bbone_prev) { pchan->bbone_prev = BKE_pose_channel_find_name(outPose, pchan->bbone_prev->name); } if (pchan->bbone_next) { pchan->bbone_next = BKE_pose_channel_find_name(outPose, pchan->bbone_next->name); } if (copy_constraints) { BKE_constraints_copy(&listb, &pchan->constraints, true); // BKE_constraints_copy NULLs listb pchan->constraints = listb; pchan->mpath = NULL; /* motion paths should not get copied yet... */ } if (pchan->prop) { pchan->prop = IDP_CopyProperty(pchan->prop); } } /* for now, duplicate Bone Groups too when doing this */ if (copy_constraints) { BLI_duplicatelist(&outPose->agroups, &src->agroups); } *dst = outPose; }
/* put EditMode back in Object */ void ED_armature_from_edit(bArmature *arm) { EditBone *eBone, *neBone; Bone *newBone; Object *obt; /* armature bones */ BKE_armature_bonelist_free(&arm->bonebase); arm->act_bone = NULL; /* remove zero sized bones, this gives unstable restposes */ for (eBone = arm->edbo->first; eBone; eBone = neBone) { float len_sq = len_squared_v3v3(eBone->head, eBone->tail); neBone = eBone->next; if (len_sq <= SQUARE(0.000001f)) { /* FLT_EPSILON is too large? */ EditBone *fBone; /* Find any bones that refer to this bone */ for (fBone = arm->edbo->first; fBone; fBone = fBone->next) { if (fBone->parent == eBone) fBone->parent = eBone->parent; } if (G.debug & G_DEBUG) printf("Warning: removed zero sized bone: %s\n", eBone->name); bone_free(arm, eBone); } } /* Copy the bones from the editData into the armature */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = MEM_callocN(sizeof(Bone), "bone"); eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */ BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name)); copy_v3_v3(newBone->arm_head, eBone->head); copy_v3_v3(newBone->arm_tail, eBone->tail); newBone->arm_roll = eBone->roll; newBone->flag = eBone->flag; if (eBone == arm->act_edbone) { /* don't change active selection, this messes up separate which uses * editmode toggle and can separate active bone which is de-selected originally */ /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */ arm->act_bone = newBone; } newBone->roll = 0.0f; newBone->weight = eBone->weight; newBone->dist = eBone->dist; newBone->xwidth = eBone->xwidth; newBone->zwidth = eBone->zwidth; newBone->rad_head = eBone->rad_head; newBone->rad_tail = eBone->rad_tail; newBone->segments = eBone->segments; newBone->layer = eBone->layer; /* Bendy-Bone parameters */ newBone->roll1 = eBone->roll1; newBone->roll2 = eBone->roll2; newBone->curveInX = eBone->curveInX; newBone->curveInY = eBone->curveInY; newBone->curveOutX = eBone->curveOutX; newBone->curveOutY = eBone->curveOutY; newBone->ease1 = eBone->ease1; newBone->ease2 = eBone->ease2; newBone->scaleIn = eBone->scaleIn; newBone->scaleOut = eBone->scaleOut; if (eBone->prop) newBone->prop = IDP_CopyProperty(eBone->prop); } /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point. * Do not set bone->head/tail here anymore, using EditBone data for that is not OK since our later fiddling * with parent's arm_mat (for roll conversion) may have some small but visible impact on locations (T46010). */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = eBone->temp.bone; if (eBone->parent) { newBone->parent = eBone->parent->temp.bone; BLI_addtail(&newBone->parent->childbase, newBone); } /* ...otherwise add this bone to the armature's bonebase */ else { BLI_addtail(&arm->bonebase, newBone); } } /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */ armature_finalize_restpose(&arm->bonebase, arm->edbo); /* so all users of this armature should get rebuilt */ for (obt = G.main->object.first; obt; obt = obt->id.next) { if (obt->data == arm) { BKE_pose_rebuild(obt, arm); } } DAG_id_tag_update(&arm->id, 0); }