Пример #1
0
static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	bArmature *arm = (bArmature *)ob->data;
	bPoseChannel *pchan, *parent;

	/* Determine if there is an active bone */
	pchan = CTX_data_active_pose_bone(C);
	if (pchan) {
		parent = pchan->parent;
		if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
			parent->bone->flag |= BONE_SELECTED;
			arm->act_bone = parent->bone;
		}
		else {
			return OPERATOR_CANCELLED;
		}
	}
	else {
		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;
}
Пример #2
0
/* Returns total selected vgroups,
 * wpi.defbase_sel is assumed malloc'd, all values are set */
bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
{
	bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
	bDeformGroup *defgroup;
	unsigned int i;
	Object *armob = BKE_object_pose_armature_get(ob);
	(*r_dg_flags_sel_tot) = 0;

	if (armob) {
		bPose *pose = armob->pose;
		for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
			bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
			if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
				dg_selection[i] = TRUE;
				(*r_dg_flags_sel_tot) += 1;
			}
			else {
				dg_selection[i] = FALSE;
			}
		}
	}
	else {
		memset(dg_selection, FALSE, sizeof(*dg_selection) * defbase_tot);
	}

	return dg_selection;
}
Пример #3
0
static int poselib_rename_exec(bContext *C, wmOperator *op)
{
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	bAction *act = (ob) ? ob->poselib : NULL;
	TimeMarker *marker;
	char newname[64];
	
	/* check if valid poselib */
	if (act == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
		return OPERATOR_CANCELLED;
	}
	
	/* get index (and pointer) of pose to remove */
	marker = BLI_findlink(&act->markers, RNA_enum_get(op->ptr, "pose"));
	if (marker == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
		return OPERATOR_CANCELLED;
	}
	
	/* get new name */
	RNA_string_get(op->ptr, "name", newname);
	
	/* copy name and validate it */
	BLI_strncpy(marker->name, newname, sizeof(marker->name));
	BLI_uniquename(&act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
	
	/* send notifiers for this - using keyframe editing notifiers, since action 
	 * may be being shown in anim editors as active action 
	 */
	WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
	
	/* done */
	return OPERATOR_FINISHED;
}
Пример #4
0
/* set the current pose as the restpose */
static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object

	/* don't check if editmode (should be done by caller) */
	if (ob->type != OB_ARMATURE)
		return OPERATOR_CANCELLED;

	/* loop over all selected pchans
	 *
	 * TODO, loop over children before parents if multiple bones
	 * at once are to be predictable*/
	CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
	{
		float delta_mat[4][4];
		
		/* chan_mat already contains the delta transform from rest pose to pose-mode pose
		 * as that is baked into there so that B-Bones will work. Once we've set this as the
		 * new raw-transform components, don't recalc the poses yet, otherwise IK result will 
		 * change, thus changing the result we may be trying to record.
		 */
		/* XXX For some reason, we can't use pchan->chan_mat here, gives odd rotation/offset (see T38251).
		 *     Using pchan->pose_mat and bringing it back in bone space seems to work as expected!
		 */
		BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, delta_mat);
		
		BKE_pchan_apply_mat4(pchan, delta_mat, true);
	}
Пример #5
0
/* For the object with pose/action: create path curves for selected bones 
 * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
 */
static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
{
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	Scene *scene = CTX_data_scene(C);
	
	if (ELEM(NULL, ob, ob->pose))
		return OPERATOR_CANCELLED;
	
	/* grab baking settings from operator settings */
	{
		bAnimVizSettings *avs = &ob->pose->avs;
		PointerRNA avs_ptr;
		
		avs->path_sf = RNA_int_get(op->ptr, "start_frame");
		avs->path_ef = RNA_int_get(op->ptr, "end_frame");
		
		RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
		RNA_enum_set(&avs_ptr, "bake_location", RNA_enum_get(op->ptr, "bake_location"));
	}
	
	/* set up path data for bones being calculated */
	CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
	{
		/* verify makes sure that the selected bone has a bone with the appropriate settings */
		animviz_verify_motionpaths(op->reports, scene, ob, pchan);
	}
Пример #6
0
/* operator init */
static int pose_slide_init(bContext *C, wmOperator *op, short mode)
{
	tPoseSlideOp *pso;
	bAction *act = NULL;
	
	/* init slide-op data */
	pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp");
	
	/* get info from context */
	pso->scene = CTX_data_scene(C);
	pso->ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	pso->arm = (pso->ob) ? pso->ob->data : NULL;
	pso->sa = CTX_wm_area(C); /* only really needed when doing modal() */
	pso->ar = CTX_wm_region(C); /* only really needed when doing modal() */
	
	pso->cframe = pso->scene->r.cfra;
	pso->mode = mode;
	
	/* set range info from property values - these may get overridden for the invoke() */
	pso->percentage = RNA_float_get(op->ptr, "percentage");
	pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
	pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
	
	/* check the settings from the context */
	if (ELEM(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
		return 0;
	else
		act = pso->ob->adt->action;
	
	/* for each Pose-Channel which gets affected, get the F-Curves for that channel 
	 * and set the relevant transform flags...
	 */
	poseAnim_mapping_get(C, &pso->pfLinks, pso->ob, act);
	
	/* set depsgraph flags */
	/* make sure the lock is set OK, unlock can be accidentally saved? */
	pso->ob->pose->flag |= POSE_LOCKED;
	pso->ob->pose->flag &= ~POSE_DO_UNLOCK;
	
	/* do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up 
	 * to the caller of this (usually only invoke() will do it, to make things more efficient).
	 */
	BLI_dlrbTree_init(&pso->keys);
	
	/* initialise numeric input */
	initNumInput(&pso->num);
	pso->num.idx_max = 0; /* one axis */
	pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
	pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */
	
	/* return status is whether we've got all the data we were requested to get */
	return 1;
}
Пример #7
0
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_get_typeinfo(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;
}
Пример #8
0
/* previously known as "selectconnected_posearmature" */
static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	bArmature *arm = (bArmature *)ob->data;
	Bone *bone, *curBone, *next = NULL;
	const bool extend = RNA_boolean_get(op->ptr, "extend");

	view3d_operator_needs_opengl(C);
	
	if (extend)
		bone = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
	else
		bone = get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
	
	if (!bone)
		return OPERATOR_CANCELLED;
	
	/* Select parents */
	for (curBone = bone; curBone; curBone = next) {
		/* ignore bone if cannot be selected */
		if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
			if (extend)
				curBone->flag &= ~BONE_SELECTED;
			else
				curBone->flag |= BONE_SELECTED;
			
			if (curBone->flag & BONE_CONNECTED)
				next = curBone->parent;
			else
				next = NULL;
		}
		else
			next = NULL;
	}
	
	/* Select children */
	for (curBone = bone->childbase.first; curBone; curBone = next)
		selectconnected_posebonechildren(ob, curBone, extend);
	
	/* 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;
}
Пример #9
0
/* XXX C can be zero */
static Object *get_poselib_object(bContext *C)
{
	ScrArea *sa;
	
	/* sanity check */
	if (C == NULL)
		return NULL;
	
	sa = CTX_wm_area(C);
	
	if (sa && (sa->spacetype == SPACE_BUTS)) 
		return ED_object_context(C);
	else
		return BKE_object_pose_armature_get(CTX_data_active_object(C));
}
Пример #10
0
/* matches logic with ED_operator_posemode_context() */
Object *ED_pose_object_from_context(bContext *C)
{
	ScrArea *sa = CTX_wm_area(C);
	Object *ob;

	/* since this call may also be used from the buttons window, we need to check for where to get the object */
	if (sa && sa->spacetype == SPACE_BUTS) {
		ob = ED_object_context(C);
	}
	else {
		ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	}

	return ob;
}
Пример #11
0
/* show popup to determine settings */
static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{	
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	
	if (ELEM(NULL, ob, ob->pose))
		return OPERATOR_CANCELLED;
	
	/* set default settings from existing/stored settings */
	{
		bAnimVizSettings *avs = &ob->pose->avs;
		PointerRNA avs_ptr;
		
		RNA_int_set(op->ptr, "start_frame", avs->path_sf);
		RNA_int_set(op->ptr, "end_frame", avs->path_ef);
		
		RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
		RNA_enum_set(op->ptr, "bake_location", RNA_enum_get(&avs_ptr, "bake_location"));
	}
	
	/* show popup dialog to allow editing of range... */
	// FIXME: hardcoded dimensions here are just arbitrary
	return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 10 * UI_UNIT_Y);
}
Пример #12
0
static bool is_cursor_visible(const DRWContextState *draw_ctx, Scene *scene, ViewLayer *view_layer)
{
  View3D *v3d = draw_ctx->v3d;
  if ((v3d->flag2 & V3D_HIDE_OVERLAYS) || (v3d->overlay.flag & V3D_OVERLAY_HIDE_CURSOR)) {
    return false;
  }

  /* don't draw cursor in paint modes, but with a few exceptions */
  if (draw_ctx->object_mode & OB_MODE_ALL_PAINT) {
    /* exception: object is in weight paint and has deforming armature in pose mode */
    if (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) {
      if (BKE_object_pose_armature_get(draw_ctx->obact) != NULL) {
        return true;
      }
    }
    /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
    else if (draw_ctx->object_mode & OB_MODE_TEXTURE_PAINT) {
      const Paint *p = BKE_paint_get_active(scene, view_layer);

      if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
        if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
          return true;
        }
      }
    }

    /* no exception met? then don't draw cursor! */
    return false;
  }
  else if (draw_ctx->object_mode & OB_MODE_WEIGHT_GPENCIL) {
    /* grease pencil hide always in some modes */
    return false;
  }

  return true;
}
Пример #13
0
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
{
	bScreen *sc = CTX_wm_screen(C);
	Scene *scene = sc->scene;
	Base *base;
	unsigned int lay = scene->lay;

#if 0  /* Using the context breaks adding objects in the UI. Need to find out why - campbell */
	Object *obact = CTX_data_active_object(C);
	Object *obedit = CTX_data_edit_object(C);
	base = CTX_data_active_base(C);
#else
	Object *obedit = scene->obedit;
	Object *obact = OBACT;
	base = BASACT;
#endif

	if (CTX_data_dir(member)) {
		CTX_data_dir_set(result, screen_context_dir);
		return 1;
	}
	else if (CTX_data_equals(member, "scene")) {
		CTX_data_id_pointer_set(result, &scene->id);
		return 1;
	}
	else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
		int visible_objects = CTX_data_equals(member, "visible_objects");

		for (base = scene->base.first; base; base = base->next) {
			if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & scene->lay)) {
				if (visible_objects)
					CTX_data_id_list_add(result, &base->object->id);
				else
					CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
		int selectable_objects = CTX_data_equals(member, "selectable_objects");

		for (base = scene->base.first; base; base = base->next) {
			if (base->lay & lay) {
				if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) {
					if (selectable_objects)
						CTX_data_id_list_add(result, &base->object->id);
					else
						CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
				}
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
		int selected_objects = CTX_data_equals(member, "selected_objects");

		for (base = scene->base.first; base; base = base->next) {
			if ((base->flag & SELECT) && (base->lay & scene->lay)) {
				if (selected_objects)
					CTX_data_id_list_add(result, &base->object->id);
				else
					CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
		int selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");

		for (base = scene->base.first; base; base = base->next) {
			if ((base->flag & SELECT) && (base->lay & scene->lay)) {
				if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
					if (0 == BKE_object_is_libdata(base->object)) {
						if (selected_editable_objects)
							CTX_data_id_list_add(result, &base->object->id);
						else
							CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
					}
				}
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "visible_bones") || CTX_data_equals(member, "editable_bones")) {
		bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
		EditBone *ebone, *flipbone = NULL;
		int editable_bones = CTX_data_equals(member, "editable_bones");
		
		if (arm && arm->edbo) {
			/* Attention: X-Axis Mirroring is also handled here... */
			for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
				/* first and foremost, bone must be visible and selected */
				if (EBONE_VISIBLE(arm, ebone)) {
					/* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
					 * so that most users of this data don't need to explicitly check for it themselves.
					 * 
					 * We need to make sure that these mirrored copies are not selected, otherwise some
					 * bones will be operated on twice.
					 */
					if (arm->flag & ARM_MIRROR_EDIT)
						flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
					
					/* if we're filtering for editable too, use the check for that instead, as it has selection check too */
					if (editable_bones) {
						/* only selected + editable */
						if (EBONE_EDITABLE(ebone)) {
							CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
						
							if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
								CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
						}
					}
					else {
						/* only include bones if visible */
						CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
						
						if ((flipbone) && EBONE_VISIBLE(arm, flipbone) == 0)
							CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
					}
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "selected_bones") || CTX_data_equals(member, "selected_editable_bones")) {
		bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
		EditBone *ebone, *flipbone = NULL;
		int selected_editable_bones = CTX_data_equals(member, "selected_editable_bones");
		
		if (arm && arm->edbo) {
			/* Attention: X-Axis Mirroring is also handled here... */
			for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
				/* first and foremost, bone must be visible and selected */
				if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_SELECTED)) {
					/* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
					 * so that most users of this data don't need to explicitly check for it themselves.
					 * 
					 * We need to make sure that these mirrored copies are not selected, otherwise some
					 * bones will be operated on twice.
					 */
					if (arm->flag & ARM_MIRROR_EDIT)
						flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
					
					/* if we're filtering for editable too, use the check for that instead, as it has selection check too */
					if (selected_editable_bones) {
						/* only selected + editable */
						if (EBONE_EDITABLE(ebone)) {
							CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
						
							if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
								CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
						}
					}
					else {
						/* only include bones if selected */
						CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
						
						if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
							CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
					}
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "visible_pose_bones")) {
		Object *obpose = BKE_object_pose_armature_get(obact);
		bArmature *arm = (obpose) ? obpose->data : NULL;
		bPoseChannel *pchan;
		
		if (obpose && obpose->pose && arm) {
			for (pchan = obpose->pose->chanbase.first; pchan; pchan = pchan->next) {
				/* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
				if (PBONE_VISIBLE(arm, pchan->bone)) {
					CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "selected_pose_bones")) {
		Object *obpose = BKE_object_pose_armature_get(obact);
		bArmature *arm = (obpose) ? obpose->data : NULL;
		bPoseChannel *pchan;
		
		if (obpose && obpose->pose && arm) {
			for (pchan = obpose->pose->chanbase.first; pchan; pchan = pchan->next) {
				/* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
				if (PBONE_VISIBLE(arm, pchan->bone)) {
					if (pchan->bone->flag & BONE_SELECTED)
						CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "active_bone")) {
		if (obact && obact->type == OB_ARMATURE) {
			bArmature *arm = obact->data;
			if (arm->edbo) {
				if (arm->act_edbone) {
					CTX_data_pointer_set(result, &arm->id, &RNA_EditBone, arm->act_edbone);
					return 1;
				}
			}
			else {
				if (arm->act_bone) {
					CTX_data_pointer_set(result, &arm->id, &RNA_Bone, arm->act_bone);
					return 1;
				}
			}
		}
	}
	else if (CTX_data_equals(member, "active_pose_bone")) {
		bPoseChannel *pchan;
		Object *obpose = BKE_object_pose_armature_get(obact);
		
		pchan = BKE_pose_channel_active(obpose);
		if (pchan) {
			CTX_data_pointer_set(result, &obpose->id, &RNA_PoseBone, pchan);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "active_base")) {
		if (base)
			CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, base);

		return 1;
	}
	else if (CTX_data_equals(member, "active_object")) {
		if (obact)
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "object")) {
		if (obact)
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "edit_object")) {
		/* convenience for now, 1 object per scene in editmode */
		if (obedit)
			CTX_data_id_pointer_set(result, &obedit->id);
		
		return 1;
	}
	else if (CTX_data_equals(member, "sculpt_object")) {
		if (obact && (obact->mode & OB_MODE_SCULPT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "vertex_paint_object")) {
		if (obact && (obact->mode & OB_MODE_VERTEX_PAINT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "weight_paint_object")) {
		if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "image_paint_object")) {
		if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "particle_edit_object")) {
		if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "sequences")) {
		Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
		if (ed) {
			Sequence *seq;
			for (seq = ed->seqbasep->first; seq; seq = seq->next) {
				CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "selected_sequences")) {
		Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
		if (ed) {
			Sequence *seq;
			for (seq = ed->seqbasep->first; seq; seq = seq->next) {
				if (seq->flag & SELECT) {
					CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "selected_editable_sequences")) {
		Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
		if (ed) {
			Sequence *seq;
			for (seq = ed->seqbasep->first; seq; seq = seq->next) {
				if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) {
					CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "active_operator")) {
		wmOperator *op = NULL;

		SpaceFile *sfile = CTX_wm_space_file(C);
		if (sfile) {
			op = sfile->op;
		}
		else if ((op = uiContextActiveOperator(C))) {
			/* do nothign */
		}
		else {
			/* note, this checks poll, could be a problem, but this also
			 * happens for the toolbar */
			op = WM_operator_last_redo(C);
		}
		/* TODO, get the operator from popup's */

		if (op && op->ptr) {
			CTX_data_pointer_set(result, NULL, &RNA_Operator, op);
			return 1;
		}
	}
	else {
		return 0; /* not found */
	}

	return -1; /* found but not available */
}
Пример #14
0
static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
{
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	bArmature *arm = ob->data;
	Bone *curbone, *pabone, *chbone;
	int direction = RNA_enum_get(op->ptr, "direction");
	const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
	bool found = false;
	
	CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
	{
		curbone = pchan->bone;
		
		if ((curbone->flag & BONE_UNSELECTABLE) == 0) {
			if (curbone == arm->act_bone) {
				if (direction == BONE_SELECT_PARENT) {
					if (pchan->parent == NULL) continue;
					else pabone = pchan->parent->bone;
					
					if (PBONE_SELECTABLE(arm, pabone)) {
						if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
						pabone->flag |= BONE_SELECTED;
						arm->act_bone = pabone;
						
						found = 1;
						break;
					}
				}
				else { /* direction == BONE_SELECT_CHILD */
					/* the child member is only assigned to connected bones, see [#30340] */
#if 0
					if (pchan->child == NULL) continue;
					else chbone = pchan->child->bone;
#else
					/* instead. find _any_ visible child bone, using the first one is a little arbitrary  - campbell */
					chbone = pchan->child ? pchan->child->bone : NULL;
					if (chbone == NULL) {
						bPoseChannel *pchan_child;

						for (pchan_child = ob->pose->chanbase.first; pchan_child; pchan_child = pchan_child->next) {
							/* possible we have multiple children, some invisible */
							if (PBONE_SELECTABLE(arm, pchan_child->bone)) {
								if (pchan_child->parent == pchan) {
									chbone = pchan_child->bone;
									break;
								}
							}
						}
					}

					if (chbone == NULL) continue;
#endif
					
					if (PBONE_SELECTABLE(arm, chbone)) {
						if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
						chbone->flag |= BONE_SELECTED;
						arm->act_bone = chbone;
						
						found = 1;
						break;
					}
				}
			}
		}
	}
Пример #15
0
static int pose_propagate_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	bAction *act = (ob && ob->adt) ? ob->adt->action : NULL;
	
	ListBase pflinks = {NULL, NULL};
	tPChanFCurveLink *pfl;
	
	tPosePropagate_ModeData modeData;
	const int mode = RNA_enum_get(op->ptr, "mode");
	
	/* sanity checks */
	if (ob == NULL) {
		BKE_report(op->reports, RPT_ERROR, "No object to propagate poses for");
		return OPERATOR_CANCELLED;
	}
	if (act == NULL) {
		BKE_report(op->reports, RPT_ERROR, "No keyframed poses to propagate to");
		return OPERATOR_CANCELLED;
	}
	
	/* isolate F-Curves related to the selected bones */
	poseAnim_mapping_get(C, &pflinks, ob, act);
	
	/* mode-specific data preprocessing (requiring no access to curves) */
	if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
		/* get a list of selected markers */
		ED_markers_make_cfra_list(&scene->markers, &modeData.sel_markers, SELECT);
	}
	else {
		/* assume everything else wants endFrame */
		modeData.end_frame = RNA_float_get(op->ptr, "end_frame");
	}
	
	/* for each bone, perform the copying required */
	for (pfl = pflinks.first; pfl; pfl = pfl->next) {
		LinkData *ld;
		
		/* mode-specific data preprocessing (requiring access to all curves) */
		if (mode == POSE_PROPAGATE_SMART_HOLDS) {
			/* we store in endFrame the end frame of the "long keyframe" (i.e. a held value) starting
			 * from the keyframe that occurs after the current frame
			 */
			modeData.end_frame = pose_propagate_get_boneHoldEndFrame(ob, pfl, (float)CFRA);
		}
		
		/* go through propagating pose to keyframes, curve by curve */
		for (ld = pfl->fcurves.first; ld; ld = ld->next)
			pose_propagate_fcurve(op, ob, (FCurve *)ld->data, (float)CFRA, modeData);
	}
	
	/* free temp data */
	poseAnim_mapping_free(&pflinks);
	
	if (mode == POSE_PROPAGATE_SELECTED_MARKERS)
		BLI_freelistN(&modeData.sel_markers);
	
	/* updates + notifiers */
	poseAnim_mapping_refresh(C, scene, ob);
	
	return OPERATOR_FINISHED;
}
Пример #16
0
/* set the current pose as the restpose */
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
	bArmature *arm = BKE_armature_from_object(ob);
	bPose *pose;
	bPoseChannel *pchan;
	EditBone *curbone;
	
	/* don't check if editmode (should be done by caller) */
	if (ob->type != OB_ARMATURE)
		return OPERATOR_CANCELLED;
	if (BKE_object_obdata_is_libdata(ob)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); /* error_libdata(); */
		return OPERATOR_CANCELLED;
	}

	/* helpful warnings... */
	/* TODO: add warnings to be careful about actions, applying deforms first, etc. */
	if (ob->adt && ob->adt->action)
		BKE_report(op->reports, RPT_WARNING,
		           "Actions on this armature will be destroyed by this new rest pose as the "
		           "transforms stored are relative to the old rest pose");

	/* Get editbones of active armature to alter */
	ED_armature_to_edit(arm);
	
	/* get pose of active object and move it out of posemode */
	pose = ob->pose;
	
	for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
		curbone = ED_armature_bone_find_name(arm->edbo, pchan->name);
		
		/* simply copy the head/tail values from pchan over to curbone */
		copy_v3_v3(curbone->head, pchan->pose_head);
		copy_v3_v3(curbone->tail, pchan->pose_tail);
		
		/* fix roll:
		 *	1. find auto-calculated roll value for this bone now
		 *	2. remove this from the 'visual' y-rotation
		 */
		{
			float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
			float delta[3], eul[3];
			
			/* obtain new auto y-rotation */
			sub_v3_v3v3(delta, curbone->tail, curbone->head);
			vec_roll_to_mat3(delta, 0.0f, premat);
			invert_m3_m3(imat, premat);
			
			/* get pchan 'visual' matrix */
			copy_m3_m4(pmat, pchan->pose_mat);
			
			/* remove auto from visual and get euler rotation */
			mul_m3_m3m3(tmat, imat, pmat);
			mat3_to_eul(eul, tmat);
			
			/* just use this euler-y as new roll value */
			curbone->roll = eul[1];
		}
		
		/* clear transform values for pchan */
		zero_v3(pchan->loc);
		zero_v3(pchan->eul);
		unit_qt(pchan->quat);
		unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
		pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
		
		/* set anim lock */
		curbone->flag |= BONE_UNKEYED;
	}
	
	/* convert editbones back to bones, and then free the edit-data */
	ED_armature_from_edit(arm);
	ED_armature_edit_free(arm);
	
	/* flush positions of posebones */
	BKE_pose_where_is(scene, ob);
	
	/* fix parenting of objects which are bone-parented */
	applyarmature_fix_boneparents(scene, ob);
	
	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
	
	return OPERATOR_FINISHED;
}
Пример #17
0
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
{
	bScreen *sc = CTX_wm_screen(C);
	ScrArea *sa = CTX_wm_area(C);
	Scene *scene = sc->scene;
	Base *base;

#if 0  /* Using the context breaks adding objects in the UI. Need to find out why - campbell */
	Object *obact = CTX_data_active_object(C);
	Object *obedit = CTX_data_edit_object(C);
	base = CTX_data_active_base(C);
#else
	Object *obedit = scene->obedit;
	Object *obact = OBACT;
	base = BASACT;
#endif

	if (CTX_data_dir(member)) {
		CTX_data_dir_set(result, screen_context_dir);
		return 1;
	}
	else if (CTX_data_equals(member, "scene")) {
		CTX_data_id_pointer_set(result, &scene->id);
		return 1;
	}
	else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
		const unsigned int lay = context_layers(sc, scene, sa);
		int visible_objects = CTX_data_equals(member, "visible_objects");

		for (base = scene->base.first; base; base = base->next) {
			if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) {
				if (visible_objects)
					CTX_data_id_list_add(result, &base->object->id);
				else
					CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
		const unsigned int lay = context_layers(sc, scene, sa);
		int selectable_objects = CTX_data_equals(member, "selectable_objects");

		for (base = scene->base.first; base; base = base->next) {
			if (base->lay & lay) {
				if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) {
					if (selectable_objects)
						CTX_data_id_list_add(result, &base->object->id);
					else
						CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
				}
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
		const unsigned int lay = context_layers(sc, scene, sa);
		int selected_objects = CTX_data_equals(member, "selected_objects");

		for (base = scene->base.first; base; base = base->next) {
			if ((base->flag & SELECT) && (base->lay & lay)) {
				if (selected_objects)
					CTX_data_id_list_add(result, &base->object->id);
				else
					CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
		const unsigned int lay = context_layers(sc, scene, sa);
		int selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");

		for (base = scene->base.first; base; base = base->next) {
			if ((base->flag & SELECT) && (base->lay & lay)) {
				if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
					if (0 == BKE_object_is_libdata(base->object)) {
						if (selected_editable_objects)
							CTX_data_id_list_add(result, &base->object->id);
						else
							CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
					}
				}
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "editable_objects") || CTX_data_equals(member, "editable_bases")) {
		const unsigned int lay = context_layers(sc, scene, sa);
		int editable_objects = CTX_data_equals(member, "editable_objects");
		
		/* Visible + Editable, but not necessarily selected */
		for (base = scene->base.first; base; base = base->next) {
			if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) {
				if (0 == BKE_object_is_libdata(base->object)) {
					if (editable_objects)
						CTX_data_id_list_add(result, &base->object->id);
					else
						CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
				}
			}
		}
		CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
		return 1;
	}
	else if (CTX_data_equals(member, "visible_bones") || CTX_data_equals(member, "editable_bones")) {
		bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
		EditBone *ebone, *flipbone = NULL;
		int editable_bones = CTX_data_equals(member, "editable_bones");
		
		if (arm && arm->edbo) {
			/* Attention: X-Axis Mirroring is also handled here... */
			for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
				/* first and foremost, bone must be visible and selected */
				if (EBONE_VISIBLE(arm, ebone)) {
					/* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
					 * so that most users of this data don't need to explicitly check for it themselves.
					 * 
					 * We need to make sure that these mirrored copies are not selected, otherwise some
					 * bones will be operated on twice.
					 */
					if (arm->flag & ARM_MIRROR_EDIT)
						flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
					
					/* if we're filtering for editable too, use the check for that instead, as it has selection check too */
					if (editable_bones) {
						/* only selected + editable */
						if (EBONE_EDITABLE(ebone)) {
							CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
						
							if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
								CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
						}
					}
					else {
						/* only include bones if visible */
						CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
						
						if ((flipbone) && EBONE_VISIBLE(arm, flipbone) == 0)
							CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
					}
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "selected_bones") || CTX_data_equals(member, "selected_editable_bones")) {
		bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
		EditBone *ebone, *flipbone = NULL;
		int selected_editable_bones = CTX_data_equals(member, "selected_editable_bones");
		
		if (arm && arm->edbo) {
			/* Attention: X-Axis Mirroring is also handled here... */
			for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
				/* first and foremost, bone must be visible and selected */
				if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_SELECTED)) {
					/* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
					 * so that most users of this data don't need to explicitly check for it themselves.
					 * 
					 * We need to make sure that these mirrored copies are not selected, otherwise some
					 * bones will be operated on twice.
					 */
					if (arm->flag & ARM_MIRROR_EDIT)
						flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
					
					/* if we're filtering for editable too, use the check for that instead, as it has selection check too */
					if (selected_editable_bones) {
						/* only selected + editable */
						if (EBONE_EDITABLE(ebone)) {
							CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
						
							if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
								CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
						}
					}
					else {
						/* only include bones if selected */
						CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
						
						if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
							CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
					}
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "visible_pose_bones")) {
		Object *obpose = BKE_object_pose_armature_get(obact);
		bArmature *arm = (obpose) ? obpose->data : NULL;
		bPoseChannel *pchan;
		
		if (obpose && obpose->pose && arm) {
			for (pchan = obpose->pose->chanbase.first; pchan; pchan = pchan->next) {
				/* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
				if (PBONE_VISIBLE(arm, pchan->bone)) {
					CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "selected_pose_bones")) {
		Object *obpose = BKE_object_pose_armature_get(obact);
		bArmature *arm = (obpose) ? obpose->data : NULL;
		bPoseChannel *pchan;
		
		if (obpose && obpose->pose && arm) {
			for (pchan = obpose->pose->chanbase.first; pchan; pchan = pchan->next) {
				/* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
				if (PBONE_VISIBLE(arm, pchan->bone)) {
					if (pchan->bone->flag & BONE_SELECTED)
						CTX_data_list_add(result, &obpose->id, &RNA_PoseBone, pchan);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "active_bone")) {
		if (obact && obact->type == OB_ARMATURE) {
			bArmature *arm = obact->data;
			if (arm->edbo) {
				if (arm->act_edbone) {
					CTX_data_pointer_set(result, &arm->id, &RNA_EditBone, arm->act_edbone);
					return 1;
				}
			}
			else {
				if (arm->act_bone) {
					CTX_data_pointer_set(result, &arm->id, &RNA_Bone, arm->act_bone);
					return 1;
				}
			}
		}
	}
	else if (CTX_data_equals(member, "active_pose_bone")) {
		bPoseChannel *pchan;
		Object *obpose = BKE_object_pose_armature_get(obact);
		
		pchan = BKE_pose_channel_active(obpose);
		if (pchan) {
			CTX_data_pointer_set(result, &obpose->id, &RNA_PoseBone, pchan);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "active_base")) {
		if (base)
			CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, base);

		return 1;
	}
	else if (CTX_data_equals(member, "active_object")) {
		if (obact)
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "object")) {
		if (obact)
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "edit_object")) {
		/* convenience for now, 1 object per scene in editmode */
		if (obedit)
			CTX_data_id_pointer_set(result, &obedit->id);
		
		return 1;
	}
	else if (CTX_data_equals(member, "sculpt_object")) {
		if (obact && (obact->mode & OB_MODE_SCULPT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "vertex_paint_object")) {
		if (obact && (obact->mode & OB_MODE_VERTEX_PAINT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "weight_paint_object")) {
		if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "image_paint_object")) {
		if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "particle_edit_object")) {
		if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT))
			CTX_data_id_pointer_set(result, &obact->id);

		return 1;
	}
	else if (CTX_data_equals(member, "sequences")) {
		Editing *ed = BKE_sequencer_editing_get(scene, false);
		if (ed) {
			Sequence *seq;
			for (seq = ed->seqbasep->first; seq; seq = seq->next) {
				CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "selected_sequences")) {
		Editing *ed = BKE_sequencer_editing_get(scene, false);
		if (ed) {
			Sequence *seq;
			for (seq = ed->seqbasep->first; seq; seq = seq->next) {
				if (seq->flag & SELECT) {
					CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "selected_editable_sequences")) {
		Editing *ed = BKE_sequencer_editing_get(scene, false);
		if (ed) {
			Sequence *seq;
			for (seq = ed->seqbasep->first; seq; seq = seq->next) {
				if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) {
					CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "gpencil_data")) {
		/* FIXME: for some reason, CTX_data_active_object(C) returns NULL when called from these situations
		 * (as outlined above - see Campbell's #ifdefs). That causes the get_active function to fail when 
		 * called from context. For that reason, we end up using an alternative where we pass everything in!
		 */
		bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
		
		if (gpd) {
			CTX_data_id_pointer_set(result, &gpd->id);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "gpencil_data_owner")) {
		/* pointer to which data/datablock owns the reference to the Grease Pencil data being used (as gpencil_data)
		 * XXX: see comment for gpencil_data case... 
		 */
		bGPdata **gpd_ptr = NULL;
		PointerRNA ptr;
		
		/* get pointer to Grease Pencil Data */
		gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, scene, sa, obact, &ptr);
		
		if (gpd_ptr) {
			CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "active_gpencil_layer")) {
		/* XXX: see comment for gpencil_data case... */
		bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
		
		if (gpd) {
			bGPDlayer *gpl = gpencil_layer_getactive(gpd);
			
			if (gpl) {
				CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
				return 1;
			}
		}
	}
	else if (CTX_data_equals(member, "active_gpencil_frame")) {
		/* XXX: see comment for gpencil_data case... */
		bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
		
		if (gpd) {
			bGPDlayer *gpl = gpencil_layer_getactive(gpd);
			
			if (gpl) {
				CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe);
				return 1;
			}
		}
	}
	else if (CTX_data_equals(member, "visible_gpencil_layers")) {
		/* XXX: see comment for gpencil_data case... */
		bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
		
		if (gpd) {
			bGPDlayer *gpl;
			
			for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
				if ((gpl->flag & GP_LAYER_HIDE) == 0) {
					CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "editable_gpencil_layers")) {
		/* XXX: see comment for gpencil_data case... */
		bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
		
		if (gpd) {
			bGPDlayer *gpl;
			
			for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
				if (gpencil_layer_is_editable(gpl)) {
					CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "editable_gpencil_strokes")) {
		/* XXX: see comment for gpencil_data case... */
		bGPdata *gpd = ED_gpencil_data_get_active_direct((ID *)sc, scene, sa, obact);
		
		if (gpd) {
			bGPDlayer *gpl;
			
			for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
				if (gpencil_layer_is_editable(gpl) && (gpl->actframe)) {
					bGPDframe *gpf = gpl->actframe;
					bGPDstroke *gps;
					
					for (gps = gpf->strokes.first; gps; gps = gps->next) {
						if (ED_gpencil_stroke_can_use_direct(sa, gps)) {
							CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
						}
					}
				}
			}
			CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "active_operator")) {
		wmOperator *op = NULL;

		SpaceFile *sfile = CTX_wm_space_file(C);
		if (sfile) {
			op = sfile->op;
		}
		else if ((op = UI_context_active_operator_get(C))) {
			/* do nothing */
		}
		else {
			/* note, this checks poll, could be a problem, but this also
			 * happens for the toolbar */
			op = WM_operator_last_redo(C);
		}
		/* TODO, get the operator from popup's */

		if (op && op->ptr) {
			CTX_data_pointer_set(result, NULL, &RNA_Operator, op);
			return 1;
		}
	}
	else {
		return 0; /* not found */
	}

	return -1; /* found but not available */
}
/* Note: rna_enum_dt_layers_select_src_items enum is from rna_modifier.c */
static EnumPropertyItem *dt_layers_select_src_itemf(
        bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
	EnumPropertyItem *item = NULL, tmp_item = {0};
	int totitem = 0;

	const int data_type = RNA_enum_get(ptr, "data_type");

	if (!C) {  /* needed for docs and i18n tools */
		return rna_enum_dt_layers_select_src_items;
	}

	RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC);
	RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC);

	if (data_type == DT_TYPE_MDEFORMVERT) {
		Object *ob_src = CTX_data_active_object(C);

		if (BKE_object_pose_armature_get(ob_src)) {
			RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
			RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
		}

		if (ob_src) {
			bDeformGroup *dg;
			int i;

			RNA_enum_item_add_separator(&item, &totitem);

			for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
				tmp_item.value = i;
				tmp_item.identifier = tmp_item.name = dg->name;
				RNA_enum_item_add(&item, &totitem, &tmp_item);
			}
		}
	}
	else if (data_type == DT_TYPE_SHAPEKEY) {
		/* TODO */
	}
	else if (data_type == DT_TYPE_UV) {
		Object *ob_src = CTX_data_active_object(C);
		Scene *scene = CTX_data_scene(C);

		if (ob_src) {
			DerivedMesh *dm_src;
			CustomData *pdata;
			int num_data, i;

			/* XXX Is this OK? */
			dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MTEXPOLY);
			pdata = dm_src->getPolyDataLayout(dm_src);
			num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);

			RNA_enum_item_add_separator(&item, &totitem);

			for (i = 0; i < num_data; i++) {
				tmp_item.value = i;
				tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
				RNA_enum_item_add(&item, &totitem, &tmp_item);
			}
		}
	}
	else if (data_type == DT_TYPE_VCOL) {
		Object *ob_src = CTX_data_active_object(C);
		Scene *scene = CTX_data_scene(C);

		if (ob_src) {
			DerivedMesh *dm_src;
			CustomData *ldata;
			int num_data, i;

			/* XXX Is this OK? */
			dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
			ldata = dm_src->getLoopDataLayout(dm_src);
			num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);

			RNA_enum_item_add_separator(&item, &totitem);

			for (i = 0; i < num_data; i++) {
				tmp_item.value = i;
				tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i);
				RNA_enum_item_add(&item, &totitem, &tmp_item);
			}
		}
	}

	RNA_enum_item_end(&item, &totitem);
	*r_free = true;

	return item;
}