/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
static void data_transfer_exec_preprocess_objects(
        bContext *C, wmOperator *op, Object *ob_src, ListBase *ctx_objects, const bool reverse_transfer)
{
	CollectionPointerLink *ctx_ob;
	CTX_data_selected_editable_objects(C, ctx_objects);

	if (reverse_transfer) {
		return;  /* Nothing else to do in this case... */
	}

	for (ctx_ob = ctx_objects->first; ctx_ob; ctx_ob = ctx_ob->next) {
		Object *ob = ctx_ob->ptr.data;
		Mesh *me;
		if ((ob == ob_src) || (ob->type != OB_MESH)) {
			continue;
		}

		me = ob->data;
		if (me->id.lib) {
			/* Do not transfer to linked data, not supported. */
			BKE_reportf(op->reports, RPT_WARNING, "Skipping object '%s', linked data '%s' cannot be modified",
			            ob->id.name + 2, me->id.name + 2);
			me->id.tag &= ~LIB_TAG_DOIT;
			continue;
		}

		me->id.tag |= LIB_TAG_DOIT;
	}
}
Example #2
0
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
	Scene *scene = CTX_data_scene(C);
	Object *obedit = CTX_data_edit_object(C);
	Object *obact = CTX_data_active_object(C);
	View3D *v3d = CTX_wm_view3d(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float imat[3][3], bmat[3][3];
	float center_global[3];
	float offset_global[3];
	int a;

	if (use_offset) {
		if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
		    snap_calc_active_center(C, true, center_global))
		{
			/* pass */
		}
		else {
			snap_curs_to_sel_ex(C, center_global);
		}
		sub_v3_v3v3(offset_global, snap_target_global, center_global);
	}

	if (obedit) {
		float snap_target_local[3];
		
		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, 0);
		if (tvs.transverts_tot == 0)
			return OPERATOR_CANCELLED;

		copy_m3_m4(bmat, obedit->obmat);
		invert_m3_m3(imat, bmat);
		
		/* get the cursor in object space */
		sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
		mul_m3_v3(imat, snap_target_local);

		if (use_offset) {
			float offset_local[3];

			mul_v3_m3v3(offset_local, imat, offset_global);

			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				add_v3_v3(tv->loc, offset_local);
			}
		}
		else {
			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				copy_v3_v3(tv->loc, snap_target_local);
			}
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else if (obact && (obact->mode & OB_MODE_POSE)) {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		bPoseChannel *pchan;
		bArmature *arm = obact->data;
		float snap_target_local[3];

		invert_m4_m4(obact->imat, obact->obmat);
		mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global);

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_SELECTED) &&
			    (PBONE_VISIBLE(arm, pchan->bone)) &&
			    /* if the bone has a parent and is connected to the parent,
			     * don't do anything - will break chain unless we do auto-ik.
			     */
			    (pchan->bone->flag & BONE_CONNECTED) == 0)
			{
				pchan->bone->flag |= BONE_TRANSFORM;
			}
			else {
				pchan->bone->flag &= ~BONE_TRANSFORM;
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_TRANSFORM) &&
			    /* check that our parents not transformed (if we have one) */
			    ((pchan->bone->parent &&
			      BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
			{
				/* Get position in pchan (pose) space. */
				float cursor_pose[3];

				if (use_offset) {
					mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]);
					add_v3_v3(cursor_pose, offset_global);

					mul_m4_v3(obact->imat, cursor_pose);
					BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
				}
				else {
					BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
				}

				/* copy new position */
				if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
					pchan->loc[0] = cursor_pose[0];
				if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
					pchan->loc[1] = cursor_pose[1];
				if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
					pchan->loc[2] = cursor_pose[2];

				/* auto-keyframing */
				ED_autokeyframe_pchan(C, scene, obact, pchan, ks);
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			pchan->bone->flag &= ~BONE_TRANSFORM;
		}

		obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);

		DAG_id_tag_update(&obact->id, OB_RECALC_DATA);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
		Main *bmain = CTX_data_main(C);

		ListBase ctx_data_list;
		CollectionPointerLink *ctx_ob;
		Object *ob;

		CTX_data_selected_editable_objects(C, &ctx_data_list);

		/* reset flags */
		for (ob = bmain->object.first; ob; ob = ob->id.next) {
			ob->flag &= ~OB_DONE;
		}

		/* tag objects we're transforming */
		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;
			ob->flag |= OB_DONE;
		}

		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;

			if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {

				float cursor_parent[3];  /* parent-relative */

				if (use_offset) {
					add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
				}
				else {
					copy_v3_v3(cursor_parent, snap_target_global);
				}

				sub_v3_v3(cursor_parent, ob->obmat[3]);

				if (ob->parent) {
					float originmat[3][3];
					BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);

					invert_m3_m3(imat, originmat);
					mul_m3_v3(imat, cursor_parent);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += cursor_parent[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += cursor_parent[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += cursor_parent[2];

				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}

		BLI_freelistN(&ctx_data_list);
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}