/* Check whether there's an active GP keyframe on the current frame */ bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra) { /* just check both for now... */ // XXX: this could get confusing (e.g. if only on the object, but other places don't show this) if (scene->gpd) { bGPDlayer *gpl = gpencil_layer_getactive(scene->gpd); if (gpl) { if (gpl->actframe) { // XXX: assumes that frame has been fetched already return (gpl->actframe->framenum == cfra); } else { /* XXX: disabled as could be too much of a penalty */ /* return BKE_gpencil_layer_find_frame(gpl, cfra); */ } } } if (ob && ob->gpd) { bGPDlayer *gpl = gpencil_layer_getactive(ob->gpd); if (gpl) { if (gpl->actframe) { // XXX: assumes that frame has been fetched already return (gpl->actframe->framenum == cfra); } else { /* XXX: disabled as could be too much of a penalty */ /* return BKE_gpencil_layer_find_frame(gpl, cfra); */ } } } return false; }
/* poll callback for checking if there is an active layer */ int gp_active_layer_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); return (gpl != NULL); }
static int rna_GPencil_active_layer_index_get(PointerRNA *ptr) { bGPdata *gpd = (bGPdata *)ptr->id.data; bGPDlayer *gpl = gpencil_layer_getactive(gpd); return BLI_findindex(&gpd->layers, gpl); }
/* delete active frame - wrapper around API calls */ static int gp_actframe_delete_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); bGPdata *gpd = gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); /* if there's no existing Grease-Pencil data there, add some */ if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No grease pencil data"); return OPERATOR_CANCELLED; } if (ELEM(NULL, gpl, gpf)) { BKE_report(op->reports, RPT_ERROR, "No active frame to delete"); return OPERATOR_CANCELLED; } /* delete it... */ gpencil_layer_delframe(gpl, gpf); /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; }
static int gpencil_select_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); /* only if there's an active layer with an active frame */ return (gpl && gpl->actframe); }
static int gp_convert_poll(bContext *C) { bGPdata *gpd = gpencil_data_get_active(C); ScrArea *sa = CTX_wm_area(C); Scene *scene = CTX_data_scene(C); /* only if there's valid data, and the current view is 3D View */ return ((sa && sa->spacetype == SPACE_VIEW3D) && gpencil_layer_getactive(gpd) && (scene->obedit == NULL)); }
static int gp_convert_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = NULL; bGPDframe *gpf = NULL; ScrArea *sa = CTX_wm_area(C); Scene *scene = CTX_data_scene(C); /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!), * and if we are not in edit mode! */ return ((sa && sa->spacetype == SPACE_VIEW3D) && (gpl = gpencil_layer_getactive(gpd)) && (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) && (gpf->strokes.first) && (scene->obedit == NULL)); }
static int gp_convert_layer_exec(bContext *C, wmOperator *op) { bGPdata *gpd = gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); Scene *scene = CTX_data_scene(C); int mode = RNA_enum_get(op->ptr, "type"); /* check if there's data to work with */ if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); return OPERATOR_CANCELLED; } gp_layer_to_curve(C, gpd, gpl, mode); /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); /* done */ return OPERATOR_FINISHED; }
static int gp_convert_layer_exec(bContext *C, wmOperator *op) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); Scene *scene = CTX_data_scene(C); const int mode = RNA_enum_get(op->ptr, "type"); const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights"); const float rad_fac = RNA_float_get(op->ptr, "radius_multiplier"); const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes"); bool valid_timing; tGpTimingData gtd; /* check if there's data to work with */ if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); return OPERATOR_CANCELLED; } if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { BKE_report(op->reports, RPT_WARNING, "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!"); } valid_timing = RNA_property_boolean_get(op->ptr, prop); gtd.mode = RNA_enum_get(op->ptr, "timing_mode"); /* Check for illegal timing mode! */ if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) { gtd.mode = GP_STROKECONVERT_TIMING_LINEAR; RNA_enum_set(op->ptr, "timing_mode", gtd.mode); } if (!link_strokes) { gtd.mode = GP_STROKECONVERT_TIMING_NONE; } /* grab all relevant settings */ gtd.frame_range = RNA_int_get(op->ptr, "frame_range"); gtd.start_frame = RNA_int_get(op->ptr, "start_frame"); gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : false; gtd.end_frame = RNA_int_get(op->ptr, "end_frame"); gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration"); gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness"); gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration); gtd.seed = RNA_int_get(op->ptr, "seed"); gtd.num_points = gtd.cur_point = 0; gtd.dists = gtd.times = NULL; gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f; gtd.inittime = 0.0; gtd.offset_time = 0.0f; /* perform conversion */ gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); /* free temp memory */ if (gtd.dists) { MEM_freeN(gtd.dists); gtd.dists = NULL; } if (gtd.times) { MEM_freeN(gtd.times); gtd.times = NULL; } /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); /* done */ return OPERATOR_FINISHED; }
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 */ }