static PointerRNA rna_KeyingSet_typeinfo_get(PointerRNA *ptr) { KeyingSet *ks = (KeyingSet *)ptr->data; KeyingSetInfo *ksi = NULL; /* keying set info is only for builtin Keying Sets */ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) ksi = ANIM_keyingset_info_find_name(ks->typeinfo); return rna_pointer_inherit_refine(ptr, &RNA_KeyingSetInfo, ksi); }
static StructRNA *rna_KeyingSetInfo_register(Main *bmain, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) { KeyingSetInfo dummyksi = {NULL}; KeyingSetInfo *ksi; PointerRNA dummyptr = {{NULL}}; int have_function[3]; /* setup dummy type info to store static properties in */ /* TODO: perhaps we want to get users to register as if they're using 'KeyingSet' directly instead? */ RNA_pointer_create(NULL, &RNA_KeyingSetInfo, &dummyksi, &dummyptr); /* validate the python class */ if (validate(&dummyptr, data, have_function) != 0) return NULL; if (strlen(identifier) >= sizeof(dummyksi.idname)) { BKE_reportf(reports, RPT_ERROR, "Registering keying set info class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummyksi.idname)); return NULL; } /* check if we have registered this info before, and remove it */ ksi = ANIM_keyingset_info_find_name(dummyksi.idname); if (ksi && ksi->ext.srna) rna_KeyingSetInfo_unregister(bmain, ksi->ext.srna); /* create a new KeyingSetInfo type */ ksi = MEM_callocN(sizeof(KeyingSetInfo), "python keying set info"); memcpy(ksi, &dummyksi, sizeof(KeyingSetInfo)); /* set RNA-extensions info */ ksi->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ksi->idname, &RNA_KeyingSetInfo); ksi->ext.data = data; ksi->ext.call = call; ksi->ext.free = free; RNA_struct_blender_type_set(ksi->ext.srna, ksi); /* set callbacks */ /* NOTE: we really should have all of these... */ ksi->poll = (have_function[0]) ? RKS_POLL_rna_internal : NULL; ksi->iter = (have_function[1]) ? RKS_ITER_rna_internal : NULL; ksi->generate = (have_function[2]) ? RKS_GEN_rna_internal : NULL; /* add and register with other info as needed */ ANIM_keyingset_info_register(ksi); WM_main_add_notifier(NC_WINDOW, NULL); /* return the struct-rna added */ return ksi->ext.srna; }
/* Check if KeyingSet can be used in the current context */ short ANIM_keyingset_context_ok_poll(bContext *C, KeyingSet *ks) { if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) { KeyingSetInfo *ksi = ANIM_keyingset_info_find_name(ks->typeinfo); /* get the associated 'type info' for this KeyingSet */ if (ksi == NULL) return 0; /* TODO: check for missing callbacks! */ /* check if it can be used in the current context */ return (ksi->poll(ksi, C)); } return 1; }
/* Given a KeyingSet and context info, validate Keying Set's paths. * This is only really necessary with relative/built-in KeyingSets * where their list of paths is dynamically generated based on the * current context info. * * Returns 0 if succeeded, otherwise an error code: eModifyKey_Returns */ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks) { /* sanity check */ if (ks == NULL) return 0; /* if relative Keying Sets, poll and build up the paths */ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) { KeyingSetInfo *ksi = ANIM_keyingset_info_find_name(ks->typeinfo); /* clear all existing paths * NOTE: BKE_keyingset_free() frees all of the paths for the KeyingSet, but not the set itself */ BKE_keyingset_free(ks); /* get the associated 'type info' for this KeyingSet */ if (ksi == NULL) return MODIFYKEY_MISSING_TYPEINFO; /* TODO: check for missing callbacks! */ /* check if it can be used in the current context */ if (ksi->poll(ksi, C)) { /* if a list of data sources are provided, run a special iterator over them, * otherwise, just continue per normal */ if (dsources) RKS_ITER_overrides_list(ksi, C, ks, dsources); else ksi->iter(ksi, C, ks); /* if we don't have any paths now, then this still qualifies as invalid context */ // FIXME: we need some error conditions (to be retrieved from the iterator why this failed!) if (ks->paths.first == NULL) return MODIFYKEY_INVALID_CONTEXT; } else { /* poll callback tells us that KeyingSet is useless in current context */ // FIXME: the poll callback needs to give us more info why return MODIFYKEY_INVALID_CONTEXT; } } /* succeeded; return 0 to tag error free */ return 0; }