void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C, wmGizmo *gz, Base **r_base, BMElem **r_ele) { ViewLayer *view_layer = CTX_data_view_layer(C); const int object_index = RNA_int_get(gz->ptr, "object_index"); /* weak, allocate an array just to access the index. */ Base *base = NULL; Object *obedit = NULL; { uint bases_len; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( view_layer, CTX_wm_view3d(C), &bases_len); if (object_index < bases_len) { base = bases[object_index]; obedit = base->object; } MEM_freeN(bases); } *r_base = base; *r_ele = NULL; if (obedit) { BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; PropertyRNA *prop; /* Ring select only defines edge, check properties exist first. */ prop = RNA_struct_find_property(gz->ptr, "vert_index"); const int vert_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; prop = RNA_struct_find_property(gz->ptr, "edge_index"); const int edge_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; prop = RNA_struct_find_property(gz->ptr, "face_index"); const int face_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; if (vert_index != -1) { *r_ele = (BMElem *)BM_vert_at_index_find(bm, vert_index); } else if (edge_index != -1) { *r_ele = (BMElem *)BM_edge_at_index_find(bm, edge_index); } else if (face_index != -1) { *r_ele = (BMElem *)BM_face_at_index_find(bm, face_index); } } }
/* helper for apply() - perform sliding for custom properties */ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl) { PointerRNA ptr = {{NULL}}; LinkData *ld; int len = strlen(pfl->pchan_path); /* setup pointer RNA for resolving paths */ RNA_pointer_create(NULL, &RNA_PoseBone, pfl->pchan, &ptr); /* custom properties are just denoted using ["..."][etc.] after the end of the base path, * so just check for opening pair after the end of the path */ for (ld = pfl->fcurves.first; ld; ld = ld->next) { FCurve *fcu = (FCurve *)ld->data; char *bPtr, *pPtr; if (fcu->rna_path == NULL) continue; /* do we have a match? * - bPtr is the RNA Path with the standard part chopped off * - pPtr is the chunk of the path which is left over */ bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len; pPtr = strstr(bPtr, "[\""); /* dummy " for texteditor bugs */ if (pPtr) { /* use RNA to try and get a handle on this property, then, assuming that it is just * numerical, try and grab the value as a float for temp editing before setting back */ PropertyRNA *prop = RNA_struct_find_property(&ptr, pPtr); if (prop) { switch (RNA_property_type(prop)) { case PROP_FLOAT: { float tval = RNA_property_float_get(&ptr, prop); pose_slide_apply_val(pso, fcu, &tval); RNA_property_float_set(&ptr, prop, tval); break; } case PROP_BOOLEAN: case PROP_ENUM: case PROP_INT: { float tval = (float)RNA_property_int_get(&ptr, prop); pose_slide_apply_val(pso, fcu, &tval); RNA_property_int_set(&ptr, prop, (int)tval); break; } default: /* cannot handle */ //printf("Cannot Pose Slide non-numerical property\n"); break; } } } } }
/* invoke callback which presents a list of bone-groups for the user to choose from */ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = ED_pose_object_from_context(C); bPose *pose; PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type"); uiPopupMenu *pup; uiLayout *layout; bActionGroup *grp; int i; /* only continue if there's an object, and a pose there too */ if (ELEM(NULL, ob, ob->pose)) return OPERATOR_CANCELLED; pose = ob->pose; /* If group index is set, try to use it! */ if (RNA_property_is_set(op->ptr, prop)) { const int num_groups = BLI_listbase_count(&pose->agroups); const int group = RNA_property_int_get(op->ptr, prop); /* just use the active group index, and call the exec callback for the calling operator */ if (group > 0 && group <= num_groups) { return op->type->exec(C, op); } } /* if there's no active group (or active is invalid), create a new menu to find it */ if (pose->active_group <= 0) { /* create a new menu, and start populating it with group names */ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE); layout = UI_popup_menu_layout(pup); /* special entry - allow to create new group, then use that * (not to be used for removing though) */ if (strstr(op->idname, "assign")) { uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0); uiItemS(layout); } /* add entries for each group */ for (grp = pose->agroups.first, i = 1; grp; grp = grp->next, i++) uiItemIntO(layout, grp->name, ICON_NONE, op->idname, "type", i); /* finish building the menu, and process it (should result in calling self again) */ UI_popup_menu_end(C, pup); return OPERATOR_INTERFACE; } else { /* just use the active group index, and call the exec callback for the calling operator */ RNA_int_set(op->ptr, "type", pose->active_group); return op->type->exec(C, op); } }
/* get reference value from F-Curve using RNA */ static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value) { PointerRNA id_ptr, ptr; PropertyRNA *prop; bool found = false; /* base pointer is always the object -> id_ptr */ RNA_id_pointer_create(&ob->id, &id_ptr); /* resolve the property... */ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) { if (RNA_property_array_check(prop)) { /* array */ if (fcu->array_index < RNA_property_array_length(&ptr, prop)) { found = true; switch (RNA_property_type(prop)) { case PROP_BOOLEAN: *value = (float)RNA_property_boolean_get_index(&ptr, prop, fcu->array_index); break; case PROP_INT: *value = (float)RNA_property_int_get_index(&ptr, prop, fcu->array_index); break; case PROP_FLOAT: *value = RNA_property_float_get_index(&ptr, prop, fcu->array_index); break; default: found = false; break; } } } else { /* not an array */ found = true; switch (RNA_property_type(prop)) { case PROP_BOOLEAN: *value = (float)RNA_property_boolean_get(&ptr, prop); break; case PROP_INT: *value = (float)RNA_property_int_get(&ptr, prop); break; case PROP_ENUM: *value = (float)RNA_property_enum_get(&ptr, prop); break; case PROP_FLOAT: *value = RNA_property_float_get(&ptr, prop); break; default: found = false; break; } } } return found; }
/** * \note RNA_struct_property_is_set_ex is used here because we want * the previously used settings to be used here rather then overriding them */ short ED_fileselect_set_params(SpaceFile *sfile) { FileSelectParams *params; wmOperator *op = sfile->op; /* create new parameters if necessary */ if (!sfile->params) { sfile->params = MEM_callocN(sizeof(FileSelectParams), "fileselparams"); /* set path to most recently opened .blend */ BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); sfile->params->filter_glob[0] = '\0'; /* set the default thumbnails size */ sfile->params->thumbnail_size = 128; } params = sfile->params; /* set the parameters from the operator, if it exists */ if (op) { PropertyRNA *prop; const bool is_files = (RNA_struct_find_property(op->ptr, "files") != NULL); const bool is_filepath = (RNA_struct_find_property(op->ptr, "filepath") != NULL); const bool is_filename = (RNA_struct_find_property(op->ptr, "filename") != NULL); const bool is_directory = (RNA_struct_find_property(op->ptr, "directory") != NULL); const bool is_relative_path = (RNA_struct_find_property(op->ptr, "relative_path") != NULL); BLI_strncpy_utf8(params->title, RNA_struct_ui_name(op->type->srna), sizeof(params->title)); if ((prop = RNA_struct_find_property(op->ptr, "filemode"))) { params->type = RNA_property_int_get(op->ptr, prop); } else { params->type = FILE_SPECIAL; } if (is_filepath && RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { char name[FILE_MAX]; RNA_string_get(op->ptr, "filepath", name); if (params->type == FILE_LOADLIB) { BLI_strncpy(params->dir, name, sizeof(params->dir)); sfile->params->file[0] = '\0'; } else { BLI_split_dirfile(name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); } } else { if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", false)) { RNA_string_get(op->ptr, "directory", params->dir); sfile->params->file[0] = '\0'; } if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", false)) { RNA_string_get(op->ptr, "filename", params->file); } } if (params->dir[0]) { BLI_cleanup_dir(G.main->name, params->dir); BLI_path_abs(params->dir, G.main->name); } if (is_directory == true && is_filename == false && is_filepath == false && is_files == false) { params->flag |= FILE_DIRSEL_ONLY; } else { params->flag &= ~FILE_DIRSEL_ONLY; } params->filter = 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_blender"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_backup"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER_BACKUP : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_image"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_IMAGE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_movie"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_MOVIE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_python"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_PYSCRIPT : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_font"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FTFONT : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_sound"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_SOUND : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_text"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_TEXT : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_folder"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_FOLDER : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_btx"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_collada"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) { RNA_property_string_get(op->ptr, prop, params->filter_glob); params->filter |= (FILE_TYPE_OPERATOR | FILE_TYPE_FOLDER); } else { params->filter_glob[0] = '\0'; } if (params->filter != 0) { if (U.uiflag & USER_FILTERFILEEXTS) { params->flag |= FILE_FILTER; } else { params->flag &= ~FILE_FILTER; } } if (U.uiflag & USER_HIDE_DOT) { params->flag |= FILE_HIDE_DOT; } else { params->flag &= ~FILE_HIDE_DOT; } if (params->type == FILE_LOADLIB) { params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0; params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0; params->flag |= RNA_boolean_get(op->ptr, "active_layer") ? FILE_ACTIVELAY : 0; } if ((prop = RNA_struct_find_property(op->ptr, "display_type"))) { params->display = RNA_property_enum_get(op->ptr, prop); } if (params->display == FILE_DEFAULTDISPLAY) { if (U.uiflag & USER_SHOW_THUMBNAILS) { if (params->filter & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE)) params->display = FILE_IMGDISPLAY; else params->display = FILE_SHORTDISPLAY; } else { params->display = FILE_SHORTDISPLAY; } } if (is_relative_path) { if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) { if (!RNA_property_is_set_ex(op->ptr, prop, false)) { RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_RELPATHS) != 0); } } } } else { /* default values, if no operator */ params->type = FILE_UNIX; params->flag |= FILE_HIDE_DOT; params->flag &= ~FILE_DIRSEL_ONLY; params->display = FILE_SHORTDISPLAY; params->filter = 0; params->filter_glob[0] = '\0'; } /* operator has no setting for this */ params->sort = FILE_SORT_ALPHA; params->active_file = -1; /* initialize the list with previous folders */ if (!sfile->folders_prev) sfile->folders_prev = folderlist_new(); if (!sfile->params->dir[0]) { if (G.main->name[0]) { BLI_split_dir_part(G.main->name, sfile->params->dir, sizeof(sfile->params->dir)); } else { const char *doc_path = BKE_appdir_folder_default(); if (doc_path) { BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir)); } } } folderlist_pushdir(sfile->folders_prev, sfile->params->dir); /* switching thumbnails needs to recalc layout [#28809] */ if (sfile->layout) { sfile->layout->dirty = true; } return 1; }
/* Main Driver Management API calls: * Add a new driver for the specified property on the given ID block */ int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type) { PointerRNA id_ptr, ptr; PropertyRNA *prop; FCurve *fcu; int array_index_max; int done_tot = 0; /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) { BKE_reportf(reports, RPT_ERROR, "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", id->name, rna_path); return 0; } /* key entire array convenience method */ if (array_index == -1) { array_index_max = RNA_property_array_length(&ptr, prop); array_index = 0; } else array_index_max = array_index; /* maximum index should be greater than the start index */ if (array_index == array_index_max) array_index_max += 1; /* will only loop once unless the array index was -1 */ for (; array_index < array_index_max; array_index++) { short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1; /* create F-Curve with Driver */ fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode); if (fcu && fcu->driver) { ChannelDriver *driver = fcu->driver; /* set the type of the driver */ driver->type = type; /* creating drivers for buttons will create the driver(s) with type * "scripted expression" so that their values won't be lost immediately, * so here we copy those values over to the driver's expression */ if (type == DRIVER_TYPE_PYTHON) { PropertyType proptype = RNA_property_type(prop); int array = RNA_property_array_length(&ptr, prop); char *expression = driver->expression; int val, maxlen = sizeof(driver->expression); float fval; if (proptype == PROP_BOOLEAN) { if (!array) val = RNA_property_boolean_get(&ptr, prop); else val = RNA_property_boolean_get_index(&ptr, prop, array_index); BLI_strncpy(expression, (val) ? "True" : "False", maxlen); } else if (proptype == PROP_INT) { if (!array) val = RNA_property_int_get(&ptr, prop); else val = RNA_property_int_get_index(&ptr, prop, array_index); BLI_snprintf(expression, maxlen, "%d", val); } else if (proptype == PROP_FLOAT) { if (!array) fval = RNA_property_float_get(&ptr, prop); else fval = RNA_property_float_get_index(&ptr, prop, array_index); BLI_snprintf(expression, maxlen, "%.3f", fval); } } /* for easier setup of drivers from UI, a driver variable should be * added if flag is set (UI calls only) */ if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { /* assume that users will mostly want this to be of type "Transform Channel" too, * since this allows the easiest setting up of common rig components */ DriverVar *dvar = driver_add_new_variable(driver); driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); } } /* set the done status */ done_tot += (fcu != NULL); } /* done */ return done_tot; }
/* helper for apply() - perform sliding for custom properties or bbone properties */ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, const char prop_prefix[]) { PointerRNA ptr = {{NULL}}; LinkData *ld; int len = strlen(pfl->pchan_path); /* setup pointer RNA for resolving paths */ RNA_pointer_create(NULL, &RNA_PoseBone, pfl->pchan, &ptr); /* - custom properties are just denoted using ["..."][etc.] after the end of the base path, * so just check for opening pair after the end of the path * - bbone properties are similar, but they always start with a prefix "bbone_*", * so a similar method should work here for those too */ for (ld = pfl->fcurves.first; ld; ld = ld->next) { FCurve *fcu = (FCurve *)ld->data; const char *bPtr, *pPtr; if (fcu->rna_path == NULL) continue; /* do we have a match? * - bPtr is the RNA Path with the standard part chopped off * - pPtr is the chunk of the path which is left over */ bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len; pPtr = strstr(bPtr, prop_prefix); if (pPtr) { /* use RNA to try and get a handle on this property, then, assuming that it is just * numerical, try and grab the value as a float for temp editing before setting back */ PropertyRNA *prop = RNA_struct_find_property(&ptr, pPtr); if (prop) { switch (RNA_property_type(prop)) { /* continuous values that can be smoothly interpolated... */ case PROP_FLOAT: { float tval = RNA_property_float_get(&ptr, prop); pose_slide_apply_val(pso, fcu, &tval); RNA_property_float_set(&ptr, prop, tval); break; } case PROP_INT: { float tval = (float)RNA_property_int_get(&ptr, prop); pose_slide_apply_val(pso, fcu, &tval); RNA_property_int_set(&ptr, prop, (int)tval); break; } /* values which can only take discrete values */ case PROP_BOOLEAN: { float tval = (float)RNA_property_boolean_get(&ptr, prop); pose_slide_apply_val(pso, fcu, &tval); RNA_property_boolean_set(&ptr, prop, (int)tval); // XXX: do we need threshold clamping here? break; } case PROP_ENUM: { /* don't handle this case - these don't usually represent interchangeable * set of values which should be interpolated between */ break; } default: /* cannot handle */ //printf("Cannot Pose Slide non-numerical property\n"); break; } } } } }