Cleanup: Use std::string for some RNA function return values

This significantly simplifies memory management, mostly by avoiding
the need to free the memory manually. It may also improve performance,
since std::string has an inline buffer that can prevent heap
allocations and it stores the size.

Pull Request: https://projects.blender.org/blender/blender/pulls/117695
This commit is contained in:
Hans Goudey 2024-01-31 17:08:09 +01:00 committed by Hans Goudey
parent c180486c83
commit f04bc75f8c
37 changed files with 591 additions and 739 deletions

View File

@ -948,19 +948,18 @@ void insert_key_rna(PointerRNA *rna_pointer,
rna_path.c_str());
continue;
}
char *rna_path_id_to_prop = RNA_path_from_ID_to_property(&ptr, prop);
const std::optional<std::string> rna_path_id_to_prop = RNA_path_from_ID_to_property(&ptr,
prop);
Vector<float> rna_values = get_keyframe_values(&ptr, prop, visual_keyframing);
insert_key_count += insert_key_action(bmain,
action,
rna_pointer,
rna_path_id_to_prop,
rna_path_id_to_prop->c_str(),
nla_frame,
rna_values.as_span(),
insert_key_flags,
key_type);
MEM_freeN(rna_path_id_to_prop);
}
if (insert_key_count == 0) {

View File

@ -353,7 +353,7 @@ bool autokeyframe_property(bContext *C,
ReportList *reports = CTX_wm_reports(C);
ToolSettings *ts = scene->toolsettings;
const eInsertKeyFlags flag = get_autokey_flags(scene);
char *path = RNA_path_from_ID_to_property(ptr, prop);
const std::optional<std::string> path = RNA_path_from_ID_to_property(ptr, prop);
if (only_if_property_keyed) {
/* NOTE: We use rnaindex instead of fcu->array_index,
@ -366,14 +366,12 @@ bool autokeyframe_property(bContext *C,
id,
action,
(fcu && fcu->grp) ? fcu->grp->name : nullptr,
fcu ? fcu->rna_path : path,
fcu ? fcu->rna_path : (path ? path->c_str() : nullptr),
rnaindex,
&anim_eval_context,
eBezTriple_KeyframeType(ts->keyframe_type),
flag) != 0;
if (path) {
MEM_freeN(path);
}
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, nullptr);
}
}

View File

@ -3,6 +3,9 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <optional>
#include <string>
/** \file
* \ingroup bke
*/
@ -101,7 +104,7 @@ void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src);
* Get RNA-Path for 'value' setting of the given shape-key.
* \note the user needs to free the returned string once they're finished with it.
*/
char *BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb);
std::optional<std::string> BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb);
/* conversion functions */
/* NOTE: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */

View File

@ -1480,7 +1480,6 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act,
ListBase *curves)
{
PointerRNA ptr;
char *basePath = nullptr;
short flags = 0;
/* build PointerRNA from provided data to obtain the paths to use */
@ -1495,8 +1494,8 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act,
}
/* get the basic path to the properties of interest */
basePath = RNA_path_from_ID_to_struct(&ptr);
if (basePath == nullptr) {
const std::optional<std::string> basePath = RNA_path_from_ID_to_struct(&ptr);
if (!basePath) {
return eAction_TransformFlags(0);
}
@ -1518,13 +1517,13 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act,
}
/* step 1: check for matching base path */
bPtr = strstr(fcu->rna_path, basePath);
bPtr = strstr(fcu->rna_path, basePath->c_str());
if (bPtr) {
/* we must add len(basePath) bytes to the match so that we are at the end of the
* base path so that we don't get false positives with these strings in the names
*/
bPtr += strlen(basePath);
bPtr += strlen(basePath->c_str());
/* step 2: check for some property with transforms
* - to speed things up, only check for the ones not yet found
@ -1597,9 +1596,6 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act,
}
}
/* free basePath */
MEM_freeN(basePath);
/* return flags found */
return eAction_TransformFlags(flags);
}

View File

@ -238,15 +238,16 @@ FCurve *id_data_find_fcurve(
return nullptr;
}
char *path = RNA_path_from_ID_to_property(&ptr, prop);
if (path == nullptr) {
const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop);
if (!path) {
return nullptr;
}
/* FIXME: The way drivers are handled here (always nullptr-ifying `fcu`) is very weird, this
* needs to be re-checked I think?. */
bool is_driven = false;
FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(adt, path, index, nullptr, &is_driven);
FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(
adt, path->c_str(), index, nullptr, &is_driven);
if (is_driven) {
if (r_driven != nullptr) {
*r_driven = is_driven;
@ -254,8 +255,6 @@ FCurve *id_data_find_fcurve(
fcu = nullptr;
}
MEM_freeN(path);
return fcu;
}
@ -454,19 +453,19 @@ FCurve *BKE_fcurve_find_by_rna_context_ui(bContext * /*C*/,
}
/* XXX This function call can become a performance bottleneck. */
char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
if (rna_path == nullptr) {
const std::optional<std::string> rna_path = RNA_path_from_ID_to_property(ptr, prop);
if (!rna_path) {
return nullptr;
}
/* Standard F-Curve from animdata - Animation (Action) or Drivers. */
FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(adt, rna_path, rnaindex, r_action, r_driven);
FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(
adt, rna_path->c_str(), rnaindex, r_action, r_driven);
if (fcu != nullptr && r_animdata != nullptr) {
*r_animdata = adt;
}
MEM_freeN(rna_path);
return fcu;
}

View File

@ -1946,21 +1946,13 @@ void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src)
kb_dst->slidermax = kb_src->slidermax;
}
char *BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb)
std::optional<std::string> BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb)
{
PropertyRNA *prop;
/* sanity checks */
if (ELEM(nullptr, key, kb)) {
return nullptr;
}
/* create the RNA pointer */
PointerRNA ptr = RNA_pointer_create((ID *)&key->id, &RNA_ShapeKey, (KeyBlock *)kb);
/* get pointer to the property too */
prop = RNA_struct_find_property(&ptr, "value");
/* return the path */
PropertyRNA *prop = RNA_struct_find_property(&ptr, "value");
return RNA_path_from_ID_to_property(&ptr, prop);
}

View File

@ -254,15 +254,14 @@ void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph,
* given the COW ID pointer as the new lookup point */
/* TODO: Find a faster alternative, or implement support for other
* common types too above (e.g. modifiers) */
char *path = RNA_path_from_ID_to_struct(ptr);
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_struct(ptr)) {
PointerRNA cow_id_ptr = RNA_id_pointer_create(cow_id);
if (!RNA_path_resolve(&cow_id_ptr, path, r_ptr_eval, nullptr)) {
if (!RNA_path_resolve(&cow_id_ptr, path->c_str(), r_ptr_eval, nullptr)) {
/* Couldn't find COW copy of data */
fprintf(stderr,
"%s: Couldn't resolve RNA path ('%s') relative to COW ID (%p) for '%s'\n",
__func__,
path,
path->c_str(),
(void *)cow_id,
orig_id->name);
}

View File

@ -5080,7 +5080,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
Main *bmain = CTX_data_main(C);
Key *key = (Key *)key_poin;
KeyBlock *kb = (KeyBlock *)kb_poin;
char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
std::optional<std::string> rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
ReportList *reports = CTX_wm_reports(C);
Scene *scene = CTX_data_scene(C);
@ -5109,11 +5109,12 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
flag = ANIM_get_keyframing_flags(scene);
/* try to resolve the path stored in the F-Curve */
if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) {
if (RNA_path_resolve_property(&id_ptr, rna_path ? rna_path->c_str() : nullptr, &ptr, &prop)) {
/* find or create new F-Curve */
/* XXX is the group name for this ok? */
bAction *act = blender::animrig::id_action_ensure(bmain, (ID *)key);
FCurve *fcu = blender::animrig::action_fcurve_ensure(bmain, act, nullptr, &ptr, rna_path, 0);
FCurve *fcu = blender::animrig::action_fcurve_ensure(
bmain, act, nullptr, &ptr, rna_path->c_str(), 0);
/* set the special 'replace' flag if on a keyframe */
if (fcurve_frame_has_keyframe(fcu, remapped_frame)) {
@ -5137,11 +5138,6 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
}
}
/* free the path */
if (rna_path) {
MEM_freeN(rna_path);
}
BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
}
@ -5478,8 +5474,11 @@ static void draw_grease_pencil_layer_widgets(bAnimListElem *ale,
UI_block_emboss_set(block, UI_EMBOSS_NONE);
PropertyRNA *onion_skinning_prop = RNA_struct_find_property(&ptr, "use_onion_skinning");
char *onion_skinning_rna_path = RNA_path_from_ID_to_property(&ptr, onion_skinning_prop);
if (RNA_path_resolve_property(&id_ptr, onion_skinning_rna_path, &ptr, &onion_skinning_prop)) {
const std::optional<std::string> onion_skinning_rna_path = RNA_path_from_ID_to_property(
&ptr, onion_skinning_prop);
if (RNA_path_resolve_property(
&id_ptr, onion_skinning_rna_path->c_str(), &ptr, &onion_skinning_prop))
{
const int icon = layer->use_onion_skinning() ? ICON_ONIONSKIN_ON : ICON_ONIONSKIN_OFF;
uiDefAutoButR(block,
&ptr,
@ -5492,15 +5491,15 @@ static void draw_grease_pencil_layer_widgets(bAnimListElem *ale,
ICON_WIDTH,
channel_height);
}
MEM_freeN(onion_skinning_rna_path);
/* Layer opacity. */
const short width = SLIDER_WIDTH * 0.6;
offset -= width;
UI_block_emboss_set(block, UI_EMBOSS);
PropertyRNA *opacity_prop = RNA_struct_find_property(&ptr, "opacity");
char *opacity_rna_path = RNA_path_from_ID_to_property(&ptr, opacity_prop);
if (RNA_path_resolve_property(&id_ptr, opacity_rna_path, &ptr, &opacity_prop)) {
const std::optional<std::string> opacity_rna_path = RNA_path_from_ID_to_property(&ptr,
opacity_prop);
if (RNA_path_resolve_property(&id_ptr, opacity_rna_path->c_str(), &ptr, &opacity_prop)) {
uiDefAutoButR(block,
&ptr,
opacity_prop,
@ -5512,7 +5511,6 @@ static void draw_grease_pencil_layer_widgets(bAnimListElem *ale,
width,
channel_height);
}
MEM_freeN(opacity_rna_path);
}
#endif
@ -5836,9 +5834,8 @@ void ANIM_channel_draw_widgets(const bContext *C,
else if (ale->id) { /* Slider using RNA Access --------------- */
PointerRNA ptr;
PropertyRNA *prop;
char *rna_path = nullptr;
std::optional<std::string> rna_path;
int array_index = 0;
short free_path = 0;
/* get destination info */
if (ale->type == ANIMTYPE_FCURVE) {
@ -5852,7 +5849,6 @@ void ANIM_channel_draw_widgets(const bContext *C,
Key *key = (Key *)ale->id;
rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
free_path = 1;
}
/* Special for Grease Pencil Layer. */
else if (ale->type == ANIMTYPE_GPLAYER) {
@ -5861,7 +5857,6 @@ void ANIM_channel_draw_widgets(const bContext *C,
/* Reset slider offset, in order to add special gp icons. */
offset += SLIDER_WIDTH;
char *gp_rna_path = nullptr;
bGPDlayer *gpl = (bGPDlayer *)ale->data;
/* Create the RNA pointers. */
@ -5873,67 +5868,73 @@ void ANIM_channel_draw_widgets(const bContext *C,
offset -= ICON_WIDTH;
UI_block_emboss_set(block, UI_EMBOSS_NONE);
prop = RNA_struct_find_property(&ptr, "use_onion_skinning");
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
icon = (gpl->onion_flag & GP_LAYER_ONIONSKIN) ? ICON_ONIONSKIN_ON :
ICON_ONIONSKIN_OFF;
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
icon,
offset,
rect->ymin,
ICON_WIDTH,
channel_height);
if (const std::optional<std::string> gp_rna_path = RNA_path_from_ID_to_property(&ptr,
prop))
{
if (RNA_path_resolve_property(&id_ptr, gp_rna_path->c_str(), &ptr, &prop)) {
icon = (gpl->onion_flag & GP_LAYER_ONIONSKIN) ? ICON_ONIONSKIN_ON :
ICON_ONIONSKIN_OFF;
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
icon,
offset,
rect->ymin,
ICON_WIDTH,
channel_height);
}
}
MEM_freeN(gp_rna_path);
/* Mask Layer. */
offset -= ICON_WIDTH;
UI_block_emboss_set(block, UI_EMBOSS_NONE);
prop = RNA_struct_find_property(&ptr, "use_mask_layer");
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
if (gpl->flag & GP_LAYER_USE_MASK) {
icon = ICON_MOD_MASK;
if (const std::optional<std::string> gp_rna_path = RNA_path_from_ID_to_property(&ptr,
prop))
{
if (RNA_path_resolve_property(&id_ptr, gp_rna_path->c_str(), &ptr, &prop)) {
if (gpl->flag & GP_LAYER_USE_MASK) {
icon = ICON_MOD_MASK;
}
else {
icon = ICON_LAYER_ACTIVE;
}
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
icon,
offset,
rect->ymin,
ICON_WIDTH,
channel_height);
}
else {
icon = ICON_LAYER_ACTIVE;
}
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
icon,
offset,
rect->ymin,
ICON_WIDTH,
channel_height);
}
MEM_freeN(gp_rna_path);
/* Layer opacity. */
const short width = SLIDER_WIDTH * 0.6;
offset -= width;
UI_block_emboss_set(block, UI_EMBOSS);
prop = RNA_struct_find_property(&ptr, "opacity");
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
ICON_NONE,
offset,
rect->ymin,
width,
channel_height);
if (const std::optional<std::string> gp_rna_path = RNA_path_from_ID_to_property(&ptr,
prop))
{
if (RNA_path_resolve_property(&id_ptr, gp_rna_path->c_str(), &ptr, &prop)) {
uiDefAutoButR(block,
&ptr,
prop,
array_index,
"",
ICON_NONE,
offset,
rect->ymin,
width,
channel_height);
}
}
MEM_freeN(gp_rna_path);
}
}
#ifdef WITH_GREASE_PENCIL_V3
@ -5948,7 +5949,9 @@ void ANIM_channel_draw_widgets(const bContext *C,
PointerRNA id_ptr = RNA_id_pointer_create(ale->id);
/* try to resolve the path */
if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) {
if (RNA_path_resolve_property(
&id_ptr, rna_path ? rna_path->c_str() : nullptr, &ptr, &prop))
{
uiBut *but;
/* Create the slider button,
@ -5972,11 +5975,6 @@ void ANIM_channel_draw_widgets(const bContext *C,
UI_but_func_set(but, achannel_setting_slider_cb, ale->id, ale->data);
}
}
/* free the path if necessary */
if (free_path) {
MEM_freeN(rna_path);
}
}
}
else { /* Special Slider for stuff without RNA Access ---------- */

View File

@ -4533,7 +4533,7 @@ static rctf calculate_selection_fcurve_bounds_and_unhide(
bContext *C,
ListBase /* CollectionPointerLink */ *selection,
PropertyRNA *prop,
char *id_to_prop_path,
const blender::StringRefNull id_to_prop_path,
const int index,
const bool whole_array)
{
@ -4560,9 +4560,9 @@ static rctf calculate_selection_fcurve_bounds_and_unhide(
}
PointerRNA resolved_ptr;
PropertyRNA *resolved_prop;
if (id_to_prop_path != nullptr) {
if (!id_to_prop_path.is_empty()) {
const bool resolved = RNA_path_resolve_property(
&selected->ptr, id_to_prop_path, &resolved_ptr, &resolved_prop);
&selected->ptr, id_to_prop_path.c_str(), &resolved_ptr, &resolved_prop);
if (!resolved) {
continue;
}
@ -4571,7 +4571,8 @@ static rctf calculate_selection_fcurve_bounds_and_unhide(
resolved_ptr = selected->ptr;
resolved_prop = prop;
}
char *path = RNA_path_from_ID_to_property(&resolved_ptr, resolved_prop);
const std::optional<std::string> path = RNA_path_from_ID_to_property(&resolved_ptr,
resolved_prop);
AnimData *anim_data = BKE_animdata_from_id(selected_id);
blender::Vector<FCurve *> fcurves;
@ -4579,7 +4580,7 @@ static rctf calculate_selection_fcurve_bounds_and_unhide(
const int length = RNA_property_array_length(&selected->ptr, prop);
for (int i = 0; i < length; i++) {
FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path(
anim_data, path, i, nullptr, nullptr);
anim_data, path->c_str(), i, nullptr, nullptr);
if (fcurve != nullptr) {
fcurves.append(fcurve);
}
@ -4587,14 +4588,12 @@ static rctf calculate_selection_fcurve_bounds_and_unhide(
}
else {
FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path(
anim_data, path, index, nullptr, nullptr);
anim_data, path->c_str(), index, nullptr, nullptr);
if (fcurve != nullptr) {
fcurves.append(fcurve);
}
}
MEM_freeN(path);
for (FCurve *fcurve : fcurves) {
fcurve->flag |= (FCURVE_SELECTED | FCURVE_VISIBLE);
rctf fcu_bounds;
@ -4633,7 +4632,7 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
ListBase selection = {nullptr, nullptr};
bool path_from_id;
char *id_to_prop_path;
std::optional<std::string> id_to_prop_path;
const bool selected_list_success = UI_context_copy_to_selected_list(
C, &ptr, prop, &selection, &path_from_id, &id_to_prop_path);
@ -4663,14 +4662,10 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
const bool whole_array = RNA_boolean_get(op->ptr, "all");
rctf bounds = calculate_selection_fcurve_bounds_and_unhide(
C, &selection, prop, id_to_prop_path, index, whole_array);
C, &selection, prop, id_to_prop_path.value_or(""), index, whole_array);
BLI_freelistN(&selection);
if (id_to_prop_path != nullptr) {
MEM_freeN(id_to_prop_path);
}
if (!BLI_rctf_is_valid(&bounds)) {
WM_report(RPT_ERROR, "F-Curves have no valid size");
return OPERATOR_CANCELLED;

View File

@ -942,14 +942,9 @@ static bAnimListElem *make_new_animlistelem(void *data,
/* the corresponding keyframes are from the animdata */
if (ale->adt && ale->adt->action) {
bAction *act = ale->adt->action;
char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
/* try to find the F-Curve which corresponds to this exactly,
* then free the MEM_alloc'd string
*/
if (rna_path) {
ale->key_data = (void *)BKE_fcurve_find(&act->curves, rna_path, 0);
MEM_freeN(rna_path);
/* Try to find the F-Curve which corresponds to this exactly. */
if (std::optional<std::string> rna_path = BKE_keyblock_curval_rnapath_get(key, kb)) {
ale->key_data = (void *)BKE_fcurve_find(&act->curves, rna_path->c_str(), 0);
}
}
ale->datatype = (ale->key_data) ? ALE_FCURVE : ALE_NONE;

View File

@ -953,13 +953,11 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ
}
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
char *path = RNA_path_from_ID_to_property(&ptr, prop);
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
success += ANIM_add_driver(
op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON);
MEM_freeN(path);
op->reports, ptr.owner_id, path->c_str(), index, flags, DRIVER_TYPE_PYTHON);
}
}
@ -1047,14 +1045,13 @@ static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
/* 1) Create a new "empty" driver for this property */
char *path = RNA_path_from_ID_to_property(&ptr, prop);
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
bool changed = false;
if (path) {
changed |= (ANIM_add_driver(
op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON) != 0);
MEM_freeN(path);
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
changed |=
(ANIM_add_driver(
op->reports, ptr.owner_id, path->c_str(), index, flags, DRIVER_TYPE_PYTHON) != 0);
}
if (changed) {
@ -1106,12 +1103,8 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op)
}
if (ptr.owner_id && ptr.data && prop) {
char *path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
changed = ANIM_remove_driver(op->reports, ptr.owner_id, path, index, 0);
MEM_freeN(path);
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
changed = ANIM_remove_driver(op->reports, ptr.owner_id, path->c_str(), index, 0);
}
}
@ -1189,15 +1182,11 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op)
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
char *path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
/* only copy the driver for the button that this was involved for */
changed = ANIM_copy_driver(op->reports, ptr.owner_id, path, index, 0);
changed = ANIM_copy_driver(op->reports, ptr.owner_id, path->c_str(), index, 0);
UI_context_update_anim_flag(C);
MEM_freeN(path);
}
}
@ -1232,11 +1221,9 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
char *path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
/* only copy the driver for the button that this was involved for */
changed = ANIM_paste_driver(op->reports, ptr.owner_id, path, index, 0);
changed = ANIM_paste_driver(op->reports, ptr.owner_id, path->c_str(), index, 0);
UI_context_update_anim_flag(C);
@ -1245,8 +1232,6 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(ptr.owner_id, ID_RECALC_ANIMATION);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, nullptr); /* XXX */
MEM_freeN(path);
}
}

View File

@ -870,7 +870,6 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
ToolSettings *ts = scene->toolsettings;
PointerRNA ptr = {nullptr};
PropertyRNA *prop = nullptr;
char *path;
uiBut *but;
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
CTX_data_depsgraph_pointer(C), BKE_scene_frame_get(scene));
@ -938,9 +937,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
}
else {
/* standard properties */
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
const char *identifier = RNA_property_identifier(prop);
const char *group = nullptr;
@ -975,13 +972,11 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
ptr.owner_id,
nullptr,
group,
path,
path->c_str(),
index,
&anim_eval_context,
eBezTriple_KeyframeType(ts->keyframe_type),
flag) != 0);
MEM_freeN(path);
}
else {
BKE_report(op->reports,
@ -1052,7 +1047,6 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
PointerRNA ptr = {nullptr};
PropertyRNA *prop = nullptr;
Main *bmain = CTX_data_main(C);
char *path;
const float cfra = BKE_scene_frame_get(scene);
bool changed = false;
int index;
@ -1104,17 +1098,14 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
}
else {
/* standard properties */
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
if (all) {
/* -1 indicates operating on the entire array (or the property itself otherwise) */
index = -1;
}
changed = blender::animrig::delete_keyframe(
bmain, op->reports, ptr.owner_id, nullptr, path, index, cfra) != 0;
MEM_freeN(path);
bmain, op->reports, ptr.owner_id, nullptr, path->c_str(), index, cfra) != 0;
}
else if (G.debug & G_DEBUG) {
printf("Button Delete-Key: no path to property\n");
@ -1161,7 +1152,6 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
PointerRNA ptr = {nullptr};
PropertyRNA *prop = nullptr;
Main *bmain = CTX_data_main(C);
char *path;
bool changed = false;
int index;
const bool all = RNA_boolean_get(op->ptr, "all");
@ -1172,18 +1162,19 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
}
if (ptr.owner_id && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
if (all) {
/* -1 indicates operating on the entire array (or the property itself otherwise) */
index = -1;
}
changed |=
(blender::animrig::clear_keyframe(
bmain, op->reports, ptr.owner_id, nullptr, path, index, eInsertKeyFlags(0)) != 0);
MEM_freeN(path);
changed |= (blender::animrig::clear_keyframe(bmain,
op->reports,
ptr.owner_id,
nullptr,
path->c_str(),
index,
eInsertKeyFlags(0)) != 0);
}
else if (G.debug & G_DEBUG) {
printf("Button Clear-Key: no path to property\n");

View File

@ -304,12 +304,9 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
/* Check if property is able to be added. */
const bool all = RNA_boolean_get(op->ptr, "all");
char *path = nullptr;
bool changed = false;
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
if (all) {
pflag |= KSP_FLAG_WHOLE_ARRAY;
@ -322,11 +319,9 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
/* Add path to this setting. */
BKE_keyingset_add_path(
keyingset, ptr.owner_id, nullptr, path, index, pflag, KSP_GROUP_KSNAME);
keyingset, ptr.owner_id, nullptr, path->c_str(), index, pflag, KSP_GROUP_KSNAME);
keyingset->active_path = BLI_listbase_count(&keyingset->paths);
changed = true;
MEM_freeN(path);
}
}
@ -390,21 +385,16 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1));
bool changed = false;
char *path = nullptr;
if (ptr.owner_id && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
/* Try to find a path matching this description. */
KS_Path *keyingset_path = BKE_keyingset_find_path(
keyingset, ptr.owner_id, keyingset->name, path, index, KSP_GROUP_KSNAME);
keyingset, ptr.owner_id, keyingset->name, path->c_str(), index, KSP_GROUP_KSNAME);
if (keyingset_path) {
BKE_keyingset_free_path(keyingset, keyingset_path);
changed = true;
}
MEM_freeN(path);
}
}

View File

@ -76,7 +76,7 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks,
/* get the RNA path to this pchan - this needs to be freed! */
PointerRNA ptr = RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan);
pfl->pchan_path = RNA_path_from_ID_to_struct(&ptr);
pfl->pchan_path = BLI_strdup(RNA_path_from_ID_to_struct(&ptr).value_or("").c_str());
/* add linkage data to operator data */
BLI_addtail(pfLinks, pfl);

View File

@ -3102,7 +3102,7 @@ bool UI_context_copy_to_selected_list(bContext *C,
PropertyRNA *prop,
ListBase *r_lb,
bool *r_use_path_from_id,
char **r_path);
std::optional<std::string> *r_path);
bool UI_context_copy_to_selected_check(PointerRNA *ptr,
PointerRNA *ptr_link,
PropertyRNA *prop,

View File

@ -91,19 +91,20 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve
PropertyRNA *target_prop = but->rnaprop;
const int target_index = but->rnaindex;
char *target_path = RNA_path_from_ID_to_property(target_ptr, target_prop);
const std::optional<std::string> target_path = RNA_path_from_ID_to_property(target_ptr,
target_prop);
/* Get paths for the destination. */
char *dst_path = RNA_path_from_ID_to_property(&ddr->ptr, ddr->prop);
const std::optional<std::string> dst_path = RNA_path_from_ID_to_property(&ddr->ptr, ddr->prop);
/* Now create driver(s) */
if (target_path && dst_path) {
int success = ANIM_add_driver_with_target(op->reports,
ddr->ptr.owner_id,
dst_path,
dst_path->c_str(),
ddr->index,
target_ptr->owner_id,
target_path,
target_path->c_str(),
target_index,
flag,
DRIVER_TYPE_PYTHON,
@ -117,14 +118,6 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, nullptr); /* XXX */
}
}
/* cleanup */
if (target_path) {
MEM_freeN(target_path);
}
if (dst_path) {
MEM_freeN(dst_path);
}
}
static void driverdropper_cancel(bContext *C, wmOperator *op)

View File

@ -237,7 +237,6 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
bContext *C = static_cast<bContext *>(but->block->evil_C);
ID *id;
FCurve *fcu;
char *path;
bool ok = false;
/* button must have RNA-pointer to a numeric-capable property */
@ -269,13 +268,14 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
}
/* get path */
path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
if (path == nullptr) {
const std::optional<std::string> path = RNA_path_from_ID_to_property(&but->rnapoin,
but->rnaprop);
if (!path) {
return false;
}
/* create driver */
fcu = verify_driver_fcurve(id, path, but->rnaindex, DRIVER_FCURVE_KEYFRAMES);
fcu = verify_driver_fcurve(id, path->c_str(), but->rnaindex, DRIVER_FCURVE_KEYFRAMES);
if (fcu) {
ChannelDriver *driver = fcu->driver;
@ -295,8 +295,6 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
}
}
MEM_freeN(path);
return ok;
}

View File

@ -354,11 +354,11 @@ static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *
return nullptr;
}
/* Ignore the actual array index [pass -1] since the index is handled separately. */
const char *prop_id = RNA_property_is_idprop(but->rnaprop) ?
RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) :
RNA_property_identifier(but->rnaprop);
const std::string prop_id = RNA_property_is_idprop(but->rnaprop) ?
RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) :
RNA_property_identifier(but->rnaprop);
bUserMenuItem *umi = (bUserMenuItem *)ED_screen_user_menu_item_find_prop(
&um->items, member_id_data_path.value().c_str(), prop_id, but->rnaindex);
&um->items, member_id_data_path->c_str(), prop_id.c_str(), but->rnaindex);
return umi;
}
@ -436,12 +436,12 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
}
else {
/* Ignore the actual array index [pass -1] since the index is handled separately. */
const char *prop_id = RNA_property_is_idprop(but->rnaprop) ?
RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) :
RNA_property_identifier(but->rnaprop);
const std::string prop_id = RNA_property_is_idprop(but->rnaprop) ?
RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) :
RNA_property_identifier(but->rnaprop);
/* NOTE: ignore 'drawstr', use property idname always. */
ED_screen_user_menu_item_add_prop(
&um->items, "", member_id_data_path.value().c_str(), prop_id, but->rnaindex);
&um->items, "", member_id_data_path->c_str(), prop_id.c_str(), but->rnaindex);
}
}
else if ((mt = UI_but_menutype_get(but))) {

View File

@ -1824,7 +1824,6 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore
PropertyRNA *lprop;
bool success = false;
char *path = nullptr;
ListBase lb = {nullptr};
PointerRNA ptr = but->rnapoin;
@ -1844,6 +1843,7 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore
const bool is_array = RNA_property_array_check(prop);
const int rna_type = RNA_property_type(prop);
std::optional<std::string> path;
if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
!BLI_listbase_is_empty(&lb))
{
@ -1856,8 +1856,13 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore
break;
}
if (!UI_context_copy_to_selected_check(
&ptr, &link->ptr, prop, path, use_path_from_id, &lptr, &lprop))
if (!UI_context_copy_to_selected_check(&ptr,
&link->ptr,
prop,
path.has_value() ? path->c_str() : nullptr,
use_path_from_id,
&lptr,
&lprop))
{
selctx_data->elems_len -= 1;
i -= 1;
@ -1906,7 +1911,6 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore
MEM_SAFE_FREE(selctx_data->elems);
}
MEM_SAFE_FREE(path);
BLI_freelistN(&lb);
/* caller can clear */

View File

@ -8,6 +8,8 @@
#include <cstring>
#include <fmt/format.h>
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
@ -105,16 +107,12 @@ static bool copy_data_path_button_poll(bContext *C)
{
PointerRNA ptr;
PropertyRNA *prop;
char *path;
int index;
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.owner_id && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
MEM_freeN(path);
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
return true;
}
}
@ -127,7 +125,6 @@ static int copy_data_path_button_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
PointerRNA ptr;
PropertyRNA *prop;
char *path;
int index;
ID *id;
@ -136,6 +133,7 @@ static int copy_data_path_button_exec(bContext *C, wmOperator *op)
/* try to create driver using property retrieved from UI */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
std::optional<std::string> path;
if (ptr.owner_id != nullptr) {
if (full_path) {
if (prop) {
@ -155,8 +153,7 @@ static int copy_data_path_button_exec(bContext *C, wmOperator *op)
}
if (path) {
WM_clipboard_text_set(path, false);
MEM_freeN(path);
WM_clipboard_text_set(path->c_str(), false);
return OPERATOR_FINISHED;
}
}
@ -195,7 +192,6 @@ static bool copy_as_driver_button_poll(bContext *C)
{
PointerRNA ptr;
PropertyRNA *prop;
char *path;
int index;
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
@ -204,10 +200,7 @@ static bool copy_as_driver_button_poll(bContext *C)
ELEM(RNA_property_type(prop), PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM) &&
(index >= 0 || !RNA_property_array_check(prop)))
{
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
MEM_freeN(path);
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
return true;
}
}
@ -228,11 +221,10 @@ static int copy_as_driver_button_exec(bContext *C, wmOperator *op)
if (ptr.owner_id && ptr.data && prop) {
ID *id;
const int dim = RNA_property_array_dimension(&ptr, prop, nullptr);
char *path = RNA_path_from_real_ID_to_property_index(bmain, &ptr, prop, dim, index, &id);
if (path) {
ANIM_copy_as_driver(id, path, RNA_property_identifier(prop));
MEM_freeN(path);
if (const std::optional<std::string> path = RNA_path_from_real_ID_to_property_index(
bmain, &ptr, prop, dim, index, &id))
{
ANIM_copy_as_driver(id, path->c_str(), RNA_property_identifier(prop));
return OPERATOR_FINISHED;
}
@ -1077,12 +1069,11 @@ bool UI_context_copy_to_selected_list(bContext *C,
PropertyRNA *prop,
ListBase *r_lb,
bool *r_use_path_from_id,
char **r_path)
std::optional<std::string> *r_path)
{
*r_use_path_from_id = false;
*r_path = nullptr;
*r_path = std::nullopt;
/* special case for bone constraints */
char *path_from_bone = nullptr;
const bool is_rna = !RNA_property_is_idprop(prop);
/* Remove links from the collection list which don't contain 'prop'. */
bool ensure_list_items_contain_prop = false;
@ -1097,34 +1088,34 @@ bool UI_context_copy_to_selected_list(bContext *C,
*/
if (is_rna && RNA_struct_is_a(ptr->type, &RNA_PropertyGroup)) {
PointerRNA owner_ptr;
char *idpath = nullptr;
std::optional<std::string> idpath;
/* First, check the active PoseBone and PoseBone->Bone. */
if (NOT_RNA_NULL(owner_ptr = CTX_data_pointer_get_type(C, "active_pose_bone", &RNA_PoseBone)))
{
if (NOT_NULL(idpath = RNA_path_from_struct_to_idproperty(
&owner_ptr, static_cast<const IDProperty *>(ptr->data))))
{
idpath = RNA_path_from_struct_to_idproperty(&owner_ptr,
static_cast<const IDProperty *>(ptr->data));
if (idpath) {
*r_lb = CTX_data_collection_get(C, "selected_pose_bones");
}
else {
bPoseChannel *pchan = static_cast<bPoseChannel *>(owner_ptr.data);
owner_ptr = RNA_pointer_create(owner_ptr.owner_id, &RNA_Bone, pchan->bone);
if (NOT_NULL(idpath = RNA_path_from_struct_to_idproperty(
&owner_ptr, static_cast<const IDProperty *>(ptr->data))))
{
idpath = RNA_path_from_struct_to_idproperty(&owner_ptr,
static_cast<const IDProperty *>(ptr->data));
if (idpath) {
ui_context_selected_bones_via_pose(C, r_lb);
}
}
}
if (idpath == nullptr) {
if (!idpath) {
/* Check the active EditBone if in edit mode. */
idpath = RNA_path_from_struct_to_idproperty(&owner_ptr,
static_cast<const IDProperty *>(ptr->data));
if (NOT_RNA_NULL(
owner_ptr = CTX_data_pointer_get_type_silent(C, "active_bone", &RNA_EditBone)) &&
NOT_NULL(idpath = RNA_path_from_struct_to_idproperty(
&owner_ptr, static_cast<const IDProperty *>(ptr->data))))
idpath)
{
*r_lb = CTX_data_collection_get(C, "selected_editable_bones");
}
@ -1133,8 +1124,7 @@ bool UI_context_copy_to_selected_list(bContext *C,
}
if (idpath) {
*r_path = BLI_sprintfN("%s.%s", idpath, RNA_property_identifier(prop));
MEM_freeN(idpath);
*r_path = fmt::format("{}.{}", *idpath, RNA_property_identifier(prop));
return true;
}
}
@ -1221,16 +1211,16 @@ bool UI_context_copy_to_selected_list(bContext *C,
else if (RNA_struct_is_a(ptr->type, &RNA_MovieTrackingTrack)) {
*r_lb = CTX_data_collection_get(C, "selected_movieclip_tracks");
}
else if (RNA_struct_is_a(ptr->type, &RNA_Constraint) &&
(path_from_bone = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_PoseBone)) !=
nullptr)
else if (const std::optional<std::string> path_from_bone =
RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_PoseBone);
RNA_struct_is_a(ptr->type, &RNA_Constraint) && path_from_bone)
{
*r_lb = CTX_data_collection_get(C, "selected_pose_bones");
*r_path = path_from_bone;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Node) || RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
ListBase lb = {nullptr, nullptr};
char *path = nullptr;
std::optional<std::string> path;
bNode *node = nullptr;
/* Get the node we're editing */
@ -1238,7 +1228,8 @@ bool UI_context_copy_to_selected_list(bContext *C,
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = static_cast<bNodeSocket *>(ptr->data);
if (nodeFindNodeTry(ntree, sock, &node, nullptr)) {
if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != nullptr) {
path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node);
if (path) {
/* we're good! */
}
else {
@ -1279,7 +1270,7 @@ bool UI_context_copy_to_selected_list(bContext *C,
/* check we're using the active object */
const short id_code = GS(id->name);
ListBase lb = CTX_data_collection_get(C, "selected_editable_objects");
char *path = RNA_path_from_ID_to_property(ptr, prop);
const std::optional<std::string> path = RNA_path_from_ID_to_property(ptr, prop);
/* de-duplicate obdata */
if (!BLI_listbase_is_empty(&lb)) {
@ -1319,8 +1310,8 @@ bool UI_context_copy_to_selected_list(bContext *C,
/* Sequencer's ID is scene :/ */
/* Try to recursively find an RNA_Sequence ancestor,
* to handle situations like #41062... */
if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != nullptr)
{
*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence);
if (r_path->has_value()) {
/* Special case when we do this for 'Sequence.lock'.
* (if the sequence is locked, it won't be in "selected_editable_sequences"). */
const char *prop_id = RNA_property_identifier(prop);
@ -1337,14 +1328,14 @@ bool UI_context_copy_to_selected_list(bContext *C,
}
}
}
return (*r_path != nullptr);
return r_path->has_value();
}
else {
return false;
}
if (RNA_property_is_idprop(prop)) {
if (*r_path == nullptr) {
if (!r_path->has_value()) {
*r_path = RNA_path_from_ptr_to_property_index(ptr, prop, 0, -1);
BLI_assert(*r_path);
}
@ -1371,7 +1362,8 @@ bool UI_context_copy_to_selected_list(bContext *C,
LISTBASE_FOREACH_MUTABLE (CollectionPointerLink *, link, r_lb) {
PointerRNA lptr;
PropertyRNA *lprop = nullptr;
RNA_path_resolve_property(&link->ptr, *r_path, &lptr, &lprop);
RNA_path_resolve_property(
&link->ptr, r_path->has_value() ? r_path->value().c_str() : nullptr, &lptr, &lprop);
bool remove = false;
if (lprop == nullptr) {
@ -1517,7 +1509,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
}
bool success = false;
char *path = nullptr;
std::optional<std::string> path;
bool use_path_from_id;
ListBase lb = {nullptr};
@ -1527,8 +1519,13 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
continue;
}
if (!UI_context_copy_to_selected_check(
&ptr, &link->ptr, prop, path, use_path_from_id, &lptr, &lprop))
if (!UI_context_copy_to_selected_check(&ptr,
&link->ptr,
prop,
path.has_value() ? path->c_str() : nullptr,
use_path_from_id,
&lptr,
&lprop))
{
continue;
}
@ -1544,7 +1541,6 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
}
}
MEM_SAFE_FREE(path);
BLI_freelistN(&lb);
return success;

View File

@ -1042,11 +1042,10 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
}
if (but->rnapoin.owner_id) {
char *str = rnaprop ?
RNA_path_full_property_py_ex(&but->rnapoin, rnaprop, but->rnaindex, true) :
RNA_path_full_struct_py(&but->rnapoin);
UI_tooltip_text_field_add(data, str, {}, UI_TIP_STYLE_MONO, UI_TIP_LC_PYTHON);
MEM_freeN(str);
std::optional<std::string> str = rnaprop ? RNA_path_full_property_py_ex(
&but->rnapoin, rnaprop, but->rnaindex, true) :
RNA_path_full_struct_py(&but->rnapoin);
UI_tooltip_text_field_add(data, str.value_or(""), {}, UI_TIP_STYLE_MONO, UI_TIP_LC_PYTHON);
}
}

View File

@ -1089,28 +1089,22 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op)
else {
/* animate constraint's "fixed offset" */
PropertyRNA *prop;
char *path;
/* get RNA pointer to constraint's "offset_factor" property - to build RNA path */
PointerRNA ptr = RNA_pointer_create(&ob->id, &RNA_FollowPathConstraint, con);
prop = RNA_struct_find_property(&ptr, "offset_factor");
path = RNA_path_from_ID_to_property(&ptr, prop);
const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop);
/* create F-Curve for constraint */
act = blender::animrig::id_action_ensure(bmain, &ob->id);
fcu = blender::animrig::action_fcurve_ensure(bmain, act, nullptr, nullptr, path, 0);
fcu = blender::animrig::action_fcurve_ensure(bmain, act, nullptr, nullptr, path->c_str(), 0);
/* standard vertical range - 0.0 to 1.0 */
standardRange = 1.0f;
/* enable "Use Fixed Position" so that animating this has effect */
data->followflag |= FOLLOWPATH_STATIC;
/* path needs to be freed */
if (path) {
MEM_freeN(path);
}
}
/* setup dummy 'generator' modifier here to get 1-1 correspondence still working

View File

@ -161,9 +161,8 @@ static void id_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
ID *id = WM_drag_get_local_ID(drag, 0);
/* copy drag path to properties */
char *text = RNA_path_full_ID_py(id);
RNA_string_set(drop->ptr, "text", text);
MEM_freeN(text);
std::string text = RNA_path_full_ID_py(id);
RNA_string_set(drop->ptr, "text", text.c_str());
}
static bool path_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)

View File

@ -221,13 +221,13 @@ void NODE_OT_group_edit(wmOperatorType *ot)
* The given paths will be owned by the returned instance.
* Both pointers are allowed to point to the same string.
*/
static AnimationBasePathChange *animation_basepath_change_new(const char *src_basepath,
const char *dst_basepath)
static AnimationBasePathChange *animation_basepath_change_new(const StringRef src_basepath,
const StringRef dst_basepath)
{
AnimationBasePathChange *basepath_change = (AnimationBasePathChange *)MEM_callocN(
sizeof(*basepath_change), AT);
basepath_change->src_basepath = src_basepath;
basepath_change->dst_basepath = dst_basepath;
basepath_change->src_basepath = BLI_strdupn(src_basepath.data(), src_basepath.size());
basepath_change->dst_basepath = BLI_strdupn(dst_basepath.data(), dst_basepath.size());
return basepath_change;
}
@ -295,7 +295,7 @@ static void node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
/* Keep track of this node's RNA "base" path (the part of the path identifying the node)
* if the old node-tree has animation data which potentially covers this node. */
const char *old_animation_basepath = nullptr;
std::optional<std::string> old_animation_basepath;
if (wgroup->adt) {
PointerRNA ptr = RNA_pointer_create(&wgroup->id, &RNA_Node, node);
old_animation_basepath = RNA_path_from_ID_to_struct(&ptr);
@ -313,9 +313,9 @@ static void node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
if (wgroup->adt) {
PointerRNA ptr = RNA_pointer_create(&ntree->id, &RNA_Node, node);
const char *new_animation_basepath = RNA_path_from_ID_to_struct(&ptr);
const std::optional<std::string> new_animation_basepath = RNA_path_from_ID_to_struct(&ptr);
BLI_addtail(&anim_basepaths,
animation_basepath_change_new(old_animation_basepath, new_animation_basepath));
animation_basepath_change_new(*old_animation_basepath, *new_animation_basepath));
}
if (!node->parent) {
@ -538,13 +538,9 @@ static bool node_group_separate_selected(
/* Keep track of this node's RNA "base" path (the part of the path identifying the node)
* if the old node-tree has animation data which potentially covers this node. */
if (ngroup.adt) {
char *path;
PointerRNA ptr = RNA_pointer_create(&ngroup.id, &RNA_Node, newnode);
path = RNA_path_from_ID_to_struct(&ptr);
if (path) {
BLI_addtail(&anim_basepaths, animation_basepath_change_new(path, path));
if (const std::optional<std::string> path = RNA_path_from_ID_to_struct(&ptr)) {
BLI_addtail(&anim_basepaths, animation_basepath_change_new(*path, *path));
}
}
@ -1088,8 +1084,8 @@ static void node_group_make_insert_selected(const bContext &C,
ListBase anim_basepaths = {nullptr, nullptr};
for (bNode *node : nodes_to_move) {
PointerRNA ptr = RNA_pointer_create(&ntree.id, &RNA_Node, node);
if (char *path = RNA_path_from_ID_to_struct(&ptr)) {
BLI_addtail(&anim_basepaths, animation_basepath_change_new(path, path));
if (const std::optional<std::string> path = RNA_path_from_ID_to_struct(&ptr)) {
BLI_addtail(&anim_basepaths, animation_basepath_change_new(*path, *path));
}
}
BKE_animdata_transfer_by_basepath(bmain, &ntree.id, &group.id, &anim_basepaths);

View File

@ -327,13 +327,11 @@ static bool text_drop_paste_poll(bContext * /*C*/, wmDrag *drag, const wmEvent *
static void text_drop_paste(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
{
char *text;
ID *id = WM_drag_get_local_ID(drag, 0);
/* copy drag path to properties */
text = RNA_path_full_ID_py(id);
RNA_string_set(drop->ptr, "text", text);
MEM_freeN(text);
std::string text = RNA_path_full_ID_py(id);
RNA_string_set(drop->ptr, "text", text.c_str());
}
/* this region dropbox definition */

View File

@ -10,7 +10,9 @@
* \ingroup RNA
*/
#include <optional>
#include <stdarg.h>
#include <string>
#include "RNA_types.hh"
@ -636,34 +638,34 @@ void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier);
/**
* Python compatible string representation of this property, (must be freed!).
*/
char *RNA_property_as_string(
std::string RNA_property_as_string(
bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length);
/**
* String representation of a property, Python compatible but can be used for display too.
* \param C: can be NULL.
*/
char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr);
char *RNA_pointer_as_string(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop_ptr,
PointerRNA *ptr_prop);
std::string RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr);
std::optional<std::string> RNA_pointer_as_string(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop_ptr,
PointerRNA *ptr_prop);
/**
* \param C: can be NULL.
*/
char *RNA_pointer_as_string_keywords_ex(bContext *C,
PointerRNA *ptr,
bool as_function,
bool all_args,
bool nested_args,
int max_prop_length,
PropertyRNA *iterprop);
char *RNA_pointer_as_string_keywords(bContext *C,
PointerRNA *ptr,
bool as_function,
bool all_args,
bool nested_args,
int max_prop_length);
char *RNA_function_as_string_keywords(
std::string RNA_pointer_as_string_keywords_ex(bContext *C,
PointerRNA *ptr,
bool as_function,
bool all_args,
bool nested_args,
int max_prop_length,
PropertyRNA *iterprop);
std::string RNA_pointer_as_string_keywords(bContext *C,
PointerRNA *ptr,
bool as_function,
bool all_args,
bool nested_args,
int max_prop_length);
std::string RNA_function_as_string_keywords(
bContext *C, FunctionRNA *func, bool as_function, bool all_args, int max_prop_length);
/* Function */

View File

@ -15,6 +15,9 @@
* UI code or Actions, though efficiency is a concern.
*/
#include <optional>
#include <string>
#include "RNA_types.hh"
struct ListBase;
@ -177,7 +180,8 @@ bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, ListBase *r_el
* \param needle: Custom property object to find.
* \return Relative path or NULL.
*/
char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, const IDProperty *needle);
std::optional<std::string> RNA_path_from_struct_to_idproperty(PointerRNA *ptr,
const IDProperty *needle);
/**
* Find the actual ID pointer and path from it to the given ID.
@ -188,67 +192,73 @@ char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, const IDProperty *need
*/
ID *RNA_find_real_ID_and_path(ID *id, const char **r_path);
char *RNA_path_from_ID_to_struct(const PointerRNA *ptr);
std::optional<std::string> RNA_path_from_ID_to_struct(const PointerRNA *ptr);
char *RNA_path_from_real_ID_to_struct(Main *bmain, const PointerRNA *ptr, ID **r_real);
std::optional<std::string> RNA_path_from_real_ID_to_struct(Main *bmain,
const PointerRNA *ptr,
ID **r_real);
char *RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop);
std::optional<std::string> RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop);
char *RNA_path_from_ptr_to_property_index(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index);
std::string RNA_path_from_ptr_to_property_index(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index);
/**
* \param index_dim: The dimension to show, 0 disables. 1 for 1d array, 2 for 2d. etc.
* \param index: The *flattened* index to use when \a `index_dim > 0`,
* this is expanded when used with multi-dimensional arrays.
*/
char *RNA_path_from_ID_to_property_index(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index);
std::optional<std::string> RNA_path_from_ID_to_property_index(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index);
char *RNA_path_from_real_ID_to_property_index(Main *bmain,
const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index,
ID **r_real_id);
std::optional<std::string> RNA_path_from_real_ID_to_property_index(Main *bmain,
const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index,
ID **r_real_id);
/**
* \return the path to given ptr/prop from the closest ancestor of given type,
* if any (else return NULL).
*/
char *RNA_path_resolve_from_type_to_property(const PointerRNA *ptr,
PropertyRNA *prop,
const StructRNA *type);
std::optional<std::string> RNA_path_resolve_from_type_to_property(const PointerRNA *ptr,
PropertyRNA *prop,
const StructRNA *type);
/**
* Get the ID as a python representation, eg:
* bpy.data.foo["bar"]
*/
char *RNA_path_full_ID_py(ID *id);
std::string RNA_path_full_ID_py(ID *id);
/**
* Get the ID.struct as a python representation, eg:
* bpy.data.foo["bar"].some_struct
*/
char *RNA_path_full_struct_py(const PointerRNA *ptr);
std::optional<std::string> RNA_path_full_struct_py(const PointerRNA *ptr);
/**
* Get the ID.struct.property as a python representation, eg:
* bpy.data.foo["bar"].some_struct.some_prop[10]
*/
char *RNA_path_full_property_py_ex(const PointerRNA *ptr,
PropertyRNA *prop,
int index,
bool use_fallback);
char *RNA_path_full_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index);
std::optional<std::string> RNA_path_full_property_py_ex(const PointerRNA *ptr,
PropertyRNA *prop,
int index,
bool use_fallback);
std::optional<std::string> RNA_path_full_property_py(const PointerRNA *ptr,
PropertyRNA *prop,
int index);
/**
* Get the struct.property as a python representation, eg:
* some_struct.some_prop[10]
*/
char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index);
std::optional<std::string> RNA_path_struct_property_py(PointerRNA *ptr,
PropertyRNA *prop,
int index);
/**
* Get the struct.property as a python representation, eg:
* some_prop[10]
*/
char *RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index);
std::string RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index);

View File

@ -257,6 +257,7 @@ set(INC
../../render
../../../../intern/clog
../../../../intern/cycles/blender
../../../../extern/fmtlib/include
../../../../intern/memutil
../../../../intern/mantaflow/extern
@ -487,6 +488,7 @@ set(SRC
set(LIB
PRIVATE bf::animrig
PRIVATE bf::dna
PRIVATE extern_fmtlib
bf_editor_space_api
bf_editor_animation

View File

@ -10,6 +10,9 @@
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <fmt/format.h>
#include "MEM_guardedalloc.h"
@ -2217,7 +2220,7 @@ bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
}
bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
{
char *path = RNA_path_from_ID_to_property(ptr, prop);
const std::optional<std::string> path = RNA_path_from_ID_to_property(ptr, prop);
bool ret = false;
if (path) {
@ -2225,10 +2228,9 @@ bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA *r_prop;
PointerRNA id_ptr = RNA_id_pointer_create(ptr->owner_id);
if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) {
if (RNA_path_resolve(&id_ptr, path->c_str(), &r_ptr, &r_prop) == true) {
ret = (prop == r_prop);
}
MEM_freeN(path);
}
return ret;
@ -5713,15 +5715,14 @@ bool RNA_property_is_unlink(PropertyRNA *prop)
return (flag & (PROP_NEVER_UNLINK | PROP_NEVER_NULL)) == 0;
}
char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
std::string RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
{
DynStr *dynstr = BLI_dynstr_new();
char *cstring;
std::stringstream ss;
const char *propname;
int first_time = 1;
BLI_dynstr_append(dynstr, "{");
ss << '{';
RNA_STRUCT_BEGIN (ptr, prop) {
propname = RNA_property_identifier(prop);
@ -5731,27 +5732,24 @@ char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
}
if (first_time == 0) {
BLI_dynstr_append(dynstr, ", ");
ss << ", ";
}
first_time = 0;
cstring = RNA_property_as_string(C, ptr, prop, -1, INT_MAX);
BLI_dynstr_appendf(dynstr, "\"%s\":%s", propname, cstring);
MEM_freeN(cstring);
const std::string str = RNA_property_as_string(C, ptr, prop, -1, INT_MAX);
ss << fmt::format("\"{}\":{}", propname, str);
}
RNA_STRUCT_END;
BLI_dynstr_append(dynstr, "}");
ss << '}';
cstring = BLI_dynstr_get_cstring(dynstr);
BLI_dynstr_free(dynstr);
return cstring;
return ss.str();
}
static char *rna_pointer_as_string__bldata(PointerRNA *ptr)
static std::optional<std::string> rna_pointer_as_string__bldata(PointerRNA *ptr)
{
if (ptr->type == nullptr || ptr->owner_id == nullptr) {
return BLI_strdup("None");
return "None";
}
if (RNA_struct_is_ID(ptr->type)) {
return RNA_path_full_ID_py(ptr->owner_id);
@ -5759,14 +5757,14 @@ static char *rna_pointer_as_string__bldata(PointerRNA *ptr)
return RNA_path_full_struct_py(ptr);
}
char *RNA_pointer_as_string(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop_ptr,
PointerRNA *ptr_prop)
std::optional<std::string> RNA_pointer_as_string(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop_ptr,
PointerRNA *ptr_prop)
{
IDProperty *prop;
if (ptr_prop->data == nullptr) {
return BLI_strdup("None");
return "None";
}
if ((prop = rna_idproperty_check(&prop_ptr, ptr)) && prop->type != IDP_ID) {
return RNA_pointer_as_string_id(C, ptr_prop);
@ -5774,20 +5772,20 @@ char *RNA_pointer_as_string(bContext *C,
return rna_pointer_as_string__bldata(ptr_prop);
}
char *RNA_pointer_as_string_keywords_ex(bContext *C,
PointerRNA *ptr,
const bool as_function,
const bool all_args,
const bool nested_args,
const int max_prop_length,
PropertyRNA *iterprop)
std::string RNA_pointer_as_string_keywords_ex(bContext *C,
PointerRNA *ptr,
const bool as_function,
const bool all_args,
const bool nested_args,
const int max_prop_length,
PropertyRNA *iterprop)
{
const char *arg_name = nullptr;
PropertyRNA *prop;
DynStr *dynstr = BLI_dynstr_new();
char *cstring, *buf;
std::stringstream ss;
bool first_iter = true;
int flag, flag_parameter;
@ -5813,7 +5811,7 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C,
if (as_function && (prop->flag_parameter & PARM_REQUIRED)) {
/* required args don't have useful defaults */
BLI_dynstr_appendf(dynstr, first_iter ? "%s" : ", %s", arg_name);
ss << fmt::format(first_iter ? "{}" : ", {}", arg_name);
first_iter = false;
}
else {
@ -5827,39 +5825,37 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C,
}
if (ok) {
std::string buf;
if (as_function && RNA_property_type(prop) == PROP_POINTER) {
/* don't expand pointers for functions */
if (flag & PROP_NEVER_NULL) {
/* we can't really do the right thing here. arg=arg?, hrmf! */
buf = BLI_strdup(arg_name);
buf = arg_name;
}
else {
buf = BLI_strdup("None");
buf = "None";
}
}
else {
buf = RNA_property_as_string(C, ptr, prop, -1, max_prop_length);
}
BLI_dynstr_appendf(dynstr, first_iter ? "%s=%s" : ", %s=%s", arg_name, buf);
ss << fmt::format(first_iter ? "{}={}" : ", {}={}", arg_name, buf);
first_iter = false;
MEM_freeN(buf);
}
}
}
RNA_PROP_END;
cstring = BLI_dynstr_get_cstring(dynstr);
BLI_dynstr_free(dynstr);
return cstring;
return ss.str();
}
char *RNA_pointer_as_string_keywords(bContext *C,
PointerRNA *ptr,
const bool as_function,
const bool all_args,
const bool nested_args,
const int max_prop_length)
std::string RNA_pointer_as_string_keywords(bContext *C,
PointerRNA *ptr,
const bool as_function,
const bool all_args,
const bool nested_args,
const int max_prop_length)
{
PropertyRNA *iterprop;
@ -5869,17 +5865,15 @@ char *RNA_pointer_as_string_keywords(bContext *C,
C, ptr, as_function, all_args, nested_args, max_prop_length, iterprop);
}
char *RNA_function_as_string_keywords(bContext *C,
FunctionRNA *func,
const bool as_function,
const bool all_args,
const int max_prop_length)
std::string RNA_function_as_string_keywords(bContext *C,
FunctionRNA *func,
const bool as_function,
const bool all_args,
const int max_prop_length)
{
PropertyRNA *iterprop;
PointerRNA funcptr = RNA_pointer_create(nullptr, &RNA_Function, func);
iterprop = RNA_struct_find_property(&funcptr, "parameters");
PropertyRNA *iterprop = RNA_struct_find_property(&funcptr, "parameters");
RNA_struct_iterator_property(funcptr.type);
@ -5920,7 +5914,7 @@ static void *rna_array_as_string_alloc(
}
}
static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dynstr)
static void rna_array_as_string_elem(int type, void **buf_p, int len, std::stringstream &ss)
{
/* This will print a comma separated string of the array elements from
* buf start to len. We will add a comma if len == 1 to preserve tuples. */
@ -5929,7 +5923,7 @@ static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dy
case PROP_BOOLEAN: {
bool *buf = static_cast<bool *>(*buf_p);
for (int i = 0; i < len; i++, buf++) {
BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%s, " : "%s", bool_as_py_string(*buf));
ss << fmt::format((i < end || !end) ? "{}, " : "{}", bool_as_py_string(*buf));
}
*buf_p = buf;
break;
@ -5937,7 +5931,7 @@ static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dy
case PROP_INT: {
int *buf = static_cast<int *>(*buf_p);
for (int i = 0; i < len; i++, buf++) {
BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%d, " : "%d", *buf);
ss << fmt::format((i < end || !end) ? "{}, " : "{}", *buf);
}
*buf_p = buf;
break;
@ -5945,7 +5939,7 @@ static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dy
case PROP_FLOAT: {
float *buf = static_cast<float *>(*buf_p);
for (int i = 0; i < len; i++, buf++) {
BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%g, " : "%g", *buf);
ss << fmt::format((i < end || !end) ? "%g, " : "%g", *buf);
}
*buf_p = buf;
break;
@ -5956,27 +5950,27 @@ static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dy
}
static void rna_array_as_string_recursive(
int type, void **buf_p, int totdim, const int *dim_size, DynStr *dynstr)
int type, void **buf_p, int totdim, const int *dim_size, std::stringstream &ss)
{
BLI_dynstr_append(dynstr, "(");
ss << '(';
if (totdim > 1) {
totdim--;
const int end = dim_size[totdim] - 1;
for (int i = 0; i <= end; i++) {
rna_array_as_string_recursive(type, buf_p, totdim, dim_size, dynstr);
rna_array_as_string_recursive(type, buf_p, totdim, dim_size, ss);
if (i < end || !end) {
BLI_dynstr_append(dynstr, ", ");
ss << ", ";
}
}
}
else {
rna_array_as_string_elem(type, buf_p, dim_size[0], dynstr);
rna_array_as_string_elem(type, buf_p, dim_size[0], ss);
}
BLI_dynstr_append(dynstr, ")");
ss << ')';
}
static void rna_array_as_string(
int type, int len, PointerRNA *ptr, PropertyRNA *prop, DynStr *dynstr)
int type, int len, PointerRNA *ptr, PropertyRNA *prop, std::stringstream &ss)
{
void *buf_end;
void *buf = rna_array_as_string_alloc(type, len, ptr, prop, &buf_end);
@ -5985,59 +5979,57 @@ static void rna_array_as_string(
totdim = RNA_property_array_dimension(ptr, prop, dim_size);
rna_array_as_string_recursive(type, &buf_step, totdim, dim_size, dynstr);
rna_array_as_string_recursive(type, &buf_step, totdim, dim_size, ss);
BLI_assert(buf_step == buf_end);
MEM_freeN(buf);
}
char *RNA_property_as_string(
std::string RNA_property_as_string(
bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length)
{
int type = RNA_property_type(prop);
int len = RNA_property_array_length(ptr, prop);
DynStr *dynstr = BLI_dynstr_new();
char *cstring;
std::stringstream ss;
/* see if we can coerce into a python type - PropertyType */
switch (type) {
case PROP_BOOLEAN:
if (len == 0) {
BLI_dynstr_append(dynstr, bool_as_py_string(RNA_property_boolean_get(ptr, prop)));
ss << bool_as_py_string(RNA_property_boolean_get(ptr, prop));
}
else {
if (index != -1) {
BLI_dynstr_append(dynstr,
bool_as_py_string(RNA_property_boolean_get_index(ptr, prop, index)));
ss << bool_as_py_string(RNA_property_boolean_get_index(ptr, prop, index));
}
else {
rna_array_as_string(type, len, ptr, prop, dynstr);
rna_array_as_string(type, len, ptr, prop, ss);
}
}
break;
case PROP_INT:
if (len == 0) {
BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get(ptr, prop));
ss << RNA_property_int_get(ptr, prop);
}
else {
if (index != -1) {
BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get_index(ptr, prop, index));
ss << RNA_property_int_get_index(ptr, prop, index);
}
else {
rna_array_as_string(type, len, ptr, prop, dynstr);
rna_array_as_string(type, len, ptr, prop, ss);
}
}
break;
case PROP_FLOAT:
if (len == 0) {
BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get(ptr, prop));
ss << fmt::format("{:g}", RNA_property_float_get(ptr, prop));
}
else {
if (index != -1) {
BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get_index(ptr, prop, index));
ss << fmt::format("{:g}", RNA_property_float_get_index(ptr, prop, index));
}
else {
rna_array_as_string(type, len, ptr, prop, dynstr);
rna_array_as_string(type, len, ptr, prop, ss);
}
}
break;
@ -6054,7 +6046,7 @@ char *RNA_property_as_string(
RNA_property_string_get(ptr, prop, buf);
BLI_str_escape(buf_esc, buf, length * 2 + 1);
MEM_freeN(buf);
BLI_dynstr_appendf(dynstr, "\"%s\"", buf_esc);
ss << fmt::format("\"{}\"", buf_esc);
MEM_freeN(buf_esc);
break;
}
@ -6069,7 +6061,7 @@ char *RNA_property_as_string(
const EnumPropertyItem *item_array;
bool free;
BLI_dynstr_append(dynstr, "{");
ss << "{";
RNA_property_enum_items(C, ptr, prop, &item_array, nullptr, &free);
if (item_array) {
@ -6077,7 +6069,7 @@ char *RNA_property_as_string(
bool is_first = true;
for (; item->identifier; item++) {
if (item->identifier[0] && item->value & val) {
BLI_dynstr_appendf(dynstr, is_first ? "'%s'" : ", '%s'", item->identifier);
ss << fmt::format(is_first ? "'%s'" : ", '%s'", item->identifier);
is_first = false;
}
}
@ -6087,32 +6079,30 @@ char *RNA_property_as_string(
}
}
BLI_dynstr_append(dynstr, "}");
ss << "}";
}
else {
/* annoying exception, don't confuse with dictionary syntax above: {} */
BLI_dynstr_append(dynstr, "set()");
ss << "set()";
}
}
else if (RNA_property_enum_identifier(C, ptr, prop, val, &identifier)) {
BLI_dynstr_appendf(dynstr, "'%s'", identifier);
ss << fmt::format("'{}'", identifier);
}
else {
BLI_dynstr_append(dynstr, "'<UNKNOWN ENUM>'");
return "'<UNKNOWN ENUM>'";
}
break;
}
case PROP_POINTER: {
PointerRNA tptr = RNA_property_pointer_get(ptr, prop);
cstring = RNA_pointer_as_string(C, ptr, prop, &tptr);
BLI_dynstr_append(dynstr, cstring);
MEM_freeN(cstring);
ss << RNA_pointer_as_string(C, ptr, prop, &tptr).value_or("");
break;
}
case PROP_COLLECTION: {
int i = 0;
CollectionPropertyIterator collect_iter;
BLI_dynstr_append(dynstr, "[");
ss << "[";
for (RNA_property_collection_begin(ptr, prop, &collect_iter);
(i < max_prop_length) && collect_iter.valid;
@ -6121,27 +6111,22 @@ char *RNA_property_as_string(
PointerRNA itemptr = collect_iter.ptr;
if (i != 0) {
BLI_dynstr_append(dynstr, ", ");
ss << ", ";
}
/* now get every prop of the collection */
cstring = RNA_pointer_as_string(C, ptr, prop, &itemptr);
BLI_dynstr_append(dynstr, cstring);
MEM_freeN(cstring);
ss << RNA_pointer_as_string(C, ptr, prop, &itemptr).value_or("");
}
RNA_property_collection_end(&collect_iter);
BLI_dynstr_append(dynstr, "]");
ss << "]";
break;
}
default:
BLI_dynstr_append(dynstr, "'<UNKNOWN TYPE>'"); /* TODO */
break;
return "'<UNKNOWN TYPE>'"; /* TODO */
}
cstring = BLI_dynstr_get_cstring(dynstr);
BLI_dynstr_free(dynstr);
return cstring;
return ss.str();
}
/* Function */

View File

@ -101,12 +101,10 @@ static ID *rna_property_override_property_real_id_owner(Main * /*bmain*/,
return owner_id;
}
char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
if (rna_path) {
*r_rna_path = rna_path;
if (const std::optional<std::string> rna_path = RNA_path_from_ID_to_property(ptr, prop)) {
*r_rna_path = BLI_strdup(rna_path->c_str());
if (rna_path_prefix != nullptr) {
*r_rna_path = BLI_sprintfN("%s%s", rna_path_prefix, rna_path);
MEM_freeN(rna_path);
*r_rna_path = BLI_sprintfN("%s%s", rna_path_prefix, rna_path->c_str());
}
return owner_id;
@ -191,14 +189,15 @@ bool RNA_property_overridable_library_set(PointerRNA * /*ptr*/,
bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop)
{
char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
const std::optional<std::string> rna_path = RNA_path_from_ID_to_property(ptr, prop);
ID *id = ptr->owner_id;
if (rna_path == nullptr || id == nullptr || !ID_IS_OVERRIDE_LIBRARY(id)) {
if (!rna_path || id == nullptr || !ID_IS_OVERRIDE_LIBRARY(id)) {
return false;
}
return (BKE_lib_override_library_property_find(id->override_library, rna_path) != nullptr);
return (BKE_lib_override_library_property_find(id->override_library, rna_path->c_str()) !=
nullptr);
}
bool RNA_property_comparable(PointerRNA * /*ptr*/, PropertyRNA *prop)
@ -725,8 +724,7 @@ bool RNA_struct_override_matches(Main *bmain,
#define RNA_PATH_BUFFSIZE 8192
char rna_path_buffer[RNA_PATH_BUFFSIZE];
char *rna_path = rna_path_buffer;
std::optional<std::string> rna_path;
size_t rna_path_len = 0;
/* XXX TODO: this will have to be refined to handle collections insertions, and array items. */
@ -736,6 +734,9 @@ bool RNA_struct_override_matches(Main *bmain,
const char *prop_name = prop_local.identifier;
const size_t prop_name_len = strlen(prop_name);
char rna_path_buffer[RNA_PATH_BUFFSIZE];
char *rna_path_c = rna_path_buffer;
/* Inlined building (significantly more efficient). */
if (!prop_local.is_idprop) {
rna_path_len = root_path_len + 1 + prop_name_len;
@ -743,46 +744,46 @@ bool RNA_struct_override_matches(Main *bmain,
rna_path = static_cast<char *>(MEM_mallocN(rna_path_len + 1, __func__));
}
memcpy(rna_path, root_path, root_path_len);
rna_path[root_path_len] = '.';
memcpy(rna_path + root_path_len + 1, prop_name, prop_name_len);
rna_path[rna_path_len] = '\0';
memcpy(rna_path_c, root_path, root_path_len);
rna_path_c[root_path_len] = '.';
memcpy(rna_path_c + root_path_len + 1, prop_name, prop_name_len);
rna_path_c[rna_path_len] = '\0';
}
else {
rna_path_len = root_path_len + 2 + prop_name_len + 2;
if (rna_path_len >= RNA_PATH_BUFFSIZE) {
rna_path = static_cast<char *>(MEM_mallocN(rna_path_len + 1, __func__));
rna_path_c = static_cast<char *>(MEM_mallocN(rna_path_len + 1, __func__));
}
memcpy(rna_path, root_path, root_path_len);
rna_path[root_path_len] = '[';
rna_path[root_path_len + 1] = '"';
memcpy(rna_path + root_path_len + 2, prop_name, prop_name_len);
rna_path[root_path_len + 2 + prop_name_len] = '"';
rna_path[root_path_len + 2 + prop_name_len + 1] = ']';
rna_path[rna_path_len] = '\0';
memcpy(rna_path_c, root_path, root_path_len);
rna_path_c[root_path_len] = '[';
rna_path_c[root_path_len + 1] = '"';
memcpy(rna_path_c + root_path_len + 2, prop_name, prop_name_len);
rna_path_c[root_path_len + 2 + prop_name_len] = '"';
rna_path_c[root_path_len + 2 + prop_name_len + 1] = ']';
rna_path_c[rna_path_len] = '\0';
}
rna_path.emplace(rna_path_c);
}
else {
/* This is rather slow, but is not much called, so not really worth optimizing. */
rna_path = RNA_path_from_ID_to_property(ptr_local, rawprop);
if (rna_path != nullptr) {
rna_path_len = strlen(rna_path);
if (rna_path) {
rna_path_len = rna_path->size();
}
}
if (rna_path == nullptr) {
if (!rna_path) {
continue;
}
CLOG_INFO(&LOG, 5, "Override Checking %s", rna_path);
CLOG_INFO(&LOG, 5, "Override Checking %s", rna_path->c_str());
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_find(liboverride, rna_path);
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_find(liboverride,
rna_path->c_str());
if (ignore_overridden && op != nullptr) {
BKE_lib_override_library_operations_tag(op, LIBOVERRIDE_PROP_OP_TAG_UNUSED, false);
if (rna_path != rna_path_buffer) {
MEM_freeN(rna_path);
}
continue;
}
@ -796,7 +797,7 @@ bool RNA_struct_override_matches(Main *bmain,
const int diff = rna_property_override_diff(bmain,
&prop_local,
&prop_reference,
rna_path,
rna_path->c_str(),
rna_path_len,
RNA_EQ_STRICT,
liboverride,
@ -818,7 +819,7 @@ bool RNA_struct_override_matches(Main *bmain,
if (diff != 0) {
/* XXX TODO: refine this for per-item overriding of arrays... */
op = BKE_lib_override_library_property_find(liboverride, rna_path);
op = BKE_lib_override_library_property_find(liboverride, rna_path->c_str());
IDOverrideLibraryPropertyOperation *opop = static_cast<IDOverrideLibraryPropertyOperation *>(
op ? op->operations.first : nullptr);
@ -868,14 +869,15 @@ bool RNA_struct_override_matches(Main *bmain,
CLOG_INFO(&LOG,
2,
"Failed to restore forbidden liboverride `%s` for override data '%s'",
rna_path,
rna_path->c_str(),
ptr_local->owner_id->name);
}
}
else {
if (op == nullptr) {
/* An override property is needed, create a temp one if necessary. */
op = BKE_lib_override_library_property_get(liboverride, rna_path, nullptr);
op = BKE_lib_override_library_property_get(
liboverride, rna_path->c_str(), nullptr);
BKE_lib_override_library_operations_tag(op, LIBOVERRIDE_PROP_OP_TAG_UNUSED, true);
}
IDOverrideLibraryPropertyOperation *opop_restore =
@ -918,18 +920,11 @@ bool RNA_struct_override_matches(Main *bmain,
/* This property is not overridden, and differs from reference, so we have no match. */
matching = false;
if (!(do_create || do_restore || do_tag_for_restore)) {
/* Since we have no 'changing' action allowed, we can break here. */
if (rna_path != rna_path_buffer) {
MEM_freeN(rna_path);
}
break;
}
}
}
if (rna_path != rna_path_buffer) {
MEM_freeN(rna_path);
}
#undef RNA_PATH_BUFFSIZE
}
RNA_property_collection_end(&iter);

View File

@ -181,7 +181,6 @@ static char *rna_ColorRamp_path(const PointerRNA *ptr)
case ID_NT: {
bNodeTree *ntree = (bNodeTree *)id;
bNode *node;
char *node_path;
for (node = static_cast<bNode *>(ntree->nodes.first); node; node = node->next) {
if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
@ -190,9 +189,8 @@ static char *rna_ColorRamp_path(const PointerRNA *ptr)
* prepend path from ID to the node
*/
PointerRNA node_ptr = RNA_pointer_create(id, &RNA_Node, node);
node_path = RNA_path_from_ID_to_struct(&node_ptr);
path = BLI_sprintfN("%s.color_ramp", node_path);
MEM_freeN(node_path);
std::string node_path = RNA_path_from_ID_to_struct(&node_ptr).value_or("");
path = BLI_sprintfN("%s.color_ramp", node_path.c_str());
}
}
}

View File

@ -9,10 +9,13 @@
#include <cstdlib>
#include <cstring>
#include <fmt/format.h>
#include "BLI_alloca.h"
#include "BLI_dynstr.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_ref.hh"
#include "BLI_utildefines.h"
#include "BKE_idprop.h"
@ -894,17 +897,18 @@ static char *rna_idp_path(PointerRNA *ptr,
return path;
}
char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, const IDProperty *needle)
std::optional<std::string> RNA_path_from_struct_to_idproperty(PointerRNA *ptr,
const IDProperty *needle)
{
const IDProperty *haystack = RNA_struct_idprops(ptr, false);
if (haystack) { /* can fail when called on bones */
return rna_idp_path(ptr, haystack, needle, nullptr);
}
return nullptr;
return std::nullopt;
}
static char *rna_path_from_ID_to_idpgroup(const PointerRNA *ptr)
static std::optional<std::string> rna_path_from_ID_to_idpgroup(const PointerRNA *ptr)
{
BLI_assert(ptr->owner_id != nullptr);
@ -947,7 +951,10 @@ ID *RNA_find_real_ID_and_path(ID *id, const char **r_path)
return (owner_id != nullptr) ? owner_id : id;
}
static char *rna_prepend_real_ID_path(Main * /*bmain*/, ID *id, char *path, ID **r_real_id)
static std::optional<std::string> rna_prepend_real_ID_path(Main * /*bmain*/,
ID *id,
const blender::StringRef path,
ID **r_real_id)
{
if (r_real_id != nullptr) {
*r_real_id = nullptr;
@ -960,36 +967,36 @@ static char *rna_prepend_real_ID_path(Main * /*bmain*/, ID *id, char *path, ID *
*r_real_id = real_id;
}
if (path != nullptr) {
char *new_path = nullptr;
if (!path.is_empty()) {
if (real_id) {
if (prefix[0]) {
new_path = BLI_sprintfN("%s%s%s", prefix, path[0] == '[' ? "" : ".", path);
}
else {
return path;
return fmt::format("{}{}{}", prefix, path[0] == '[' ? "" : ".", std::string_view(path));
}
return path;
}
MEM_freeN(path);
return new_path;
}
return prefix[0] != '\0' ? BLI_strdup(prefix) : nullptr;
if (prefix[0] == '\0') {
return std::nullopt;
}
return prefix;
}
char *RNA_path_from_ID_to_struct(const PointerRNA *ptr)
std::optional<std::string> RNA_path_from_ID_to_struct(const PointerRNA *ptr)
{
char *ptrpath = nullptr;
std::optional<std::string> ptrpath;
if (!ptr->owner_id || !ptr->data) {
return nullptr;
return std::nullopt;
}
if (!RNA_struct_is_ID(ptr->type)) {
if (ptr->type->path) {
/* if type has a path to some ID, use it */
ptrpath = ptr->type->path((PointerRNA *)ptr);
char *path_cstr = ptr->type->path((PointerRNA *)ptr);
ptrpath = path_cstr;
MEM_freeN(path_cstr);
}
else if (ptr->type->nested && RNA_struct_is_ID(ptr->type->nested)) {
PropertyRNA *userprop;
@ -1001,10 +1008,11 @@ char *RNA_path_from_ID_to_struct(const PointerRNA *ptr)
userprop = rna_struct_find_nested(&parentptr, ptr->type);
if (userprop) {
ptrpath = BLI_strdup(RNA_property_identifier(userprop));
ptrpath = RNA_property_identifier(userprop);
}
else {
return nullptr; /* can't do anything about this case yet... */
/* can't do anything about this case yet... */
return std::nullopt;
}
}
else if (RNA_struct_is_a(ptr->type, &RNA_PropertyGroup)) {
@ -1012,19 +1020,21 @@ char *RNA_path_from_ID_to_struct(const PointerRNA *ptr)
return rna_path_from_ID_to_idpgroup(ptr);
}
else {
return nullptr;
return std::nullopt;
}
}
return ptrpath;
}
char *RNA_path_from_real_ID_to_struct(Main *bmain, const PointerRNA *ptr, ID **r_real)
std::optional<std::string> RNA_path_from_real_ID_to_struct(Main *bmain,
const PointerRNA *ptr,
ID **r_real)
{
char *path = RNA_path_from_ID_to_struct(ptr);
const std::optional<std::string> path = RNA_path_from_ID_to_struct(ptr);
/* Null path is valid in that case, when given struct is an ID one. */
return rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real);
return rna_prepend_real_ID_path(bmain, ptr->owner_id, path.value_or(""), r_real);
}
static void rna_path_array_multi_from_flat_index(const int dimsize[RNA_MAX_ARRAY_LENGTH],
@ -1067,14 +1077,15 @@ static void rna_path_array_multi_string_from_flat_index(const PointerRNA *ptr,
}
}
static char *rna_path_from_ptr_to_property_index_ex(
const PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, const char *path_prefix)
static std::string rna_path_from_ptr_to_property_index_ex(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index,
const blender::StringRef path_prefix)
{
const bool is_rna = (prop->magic == RNA_MAGIC);
const char *propname;
char *path;
propname = RNA_property_identifier(prop);
const char *propname = RNA_property_identifier(prop);
/* support indexing w/ multi-dimensional arrays */
char index_str[RNA_MAX_ARRAY_LENGTH * 12 + 1];
@ -1086,107 +1097,98 @@ static char *rna_path_from_ptr_to_property_index_ex(
ptr, prop, index_dim, index, index_str, sizeof(index_str));
}
if (path_prefix) {
if (!path_prefix.is_empty()) {
if (is_rna) {
path = BLI_sprintfN("%s.%s%s", path_prefix, propname, index_str);
}
else {
char propname_esc[MAX_IDPROP_NAME * 2];
BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
path = BLI_sprintfN("%s[\"%s\"]%s", path_prefix, propname_esc, index_str);
}
}
else {
if (is_rna) {
if (index_dim == 0) {
/* Use direct duplication instead of #BLI_sprintfN because it's faster. */
path = BLI_strdup(propname);
}
else {
path = BLI_sprintfN("%s%s", propname, index_str);
}
}
else {
char propname_esc[MAX_IDPROP_NAME * 2];
BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
path = BLI_sprintfN("[\"%s\"]%s", propname_esc, index_str);
return fmt::format("{}.{}{}", std::string_view(path_prefix), propname, index_str);
}
char propname_esc[MAX_IDPROP_NAME * 2];
BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
return fmt::format("{}[\"{}\"]{}", std::string_view(path_prefix), propname_esc, index_str);
}
return path;
if (is_rna) {
if (index_dim == 0) {
/* Use direct duplication instead of #fmt::format because it's faster. */
return propname;
}
return fmt::format("{}{}", propname, index_str);
}
char propname_esc[MAX_IDPROP_NAME * 2];
BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
return fmt::format("[\"{}\"]{}", propname_esc, index_str);
}
char *RNA_path_from_ptr_to_property_index(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index)
std::string RNA_path_from_ptr_to_property_index(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index)
{
return rna_path_from_ptr_to_property_index_ex(ptr, prop, index_dim, index, nullptr);
return rna_path_from_ptr_to_property_index_ex(ptr, prop, index_dim, index, "");
}
char *RNA_path_from_ID_to_property_index(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index)
std::optional<std::string> RNA_path_from_ID_to_property_index(const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index)
{
if (!ptr->owner_id || !ptr->data) {
return nullptr;
return std::nullopt;
}
/* Path from ID to the struct holding this property. */
char *ptrpath = RNA_path_from_ID_to_struct(ptr);
std::optional<std::string> ptrpath = RNA_path_from_ID_to_struct(ptr);
/* When there is no path and this is not an ID, there is no path to the ID. */
char *path = ((ptrpath == nullptr) && !RNA_struct_is_ID(ptr->type)) ?
nullptr :
rna_path_from_ptr_to_property_index_ex(ptr, prop, index_dim, index, ptrpath);
if (ptrpath != nullptr) {
MEM_freeN(ptrpath);
if (!ptrpath && !RNA_struct_is_ID(ptr->type)) {
return std::nullopt;
}
return path;
return rna_path_from_ptr_to_property_index_ex(ptr, prop, index_dim, index, ptrpath.value_or(""));
}
char *RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
std::optional<std::string> RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
{
return RNA_path_from_ID_to_property_index(ptr, prop, 0, -1);
}
char *RNA_path_from_real_ID_to_property_index(Main *bmain,
const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index,
ID **r_real_id)
std::optional<std::string> RNA_path_from_real_ID_to_property_index(Main *bmain,
const PointerRNA *ptr,
PropertyRNA *prop,
int index_dim,
int index,
ID **r_real_id)
{
char *path = RNA_path_from_ID_to_property_index(ptr, prop, index_dim, index);
const std::optional<std::string> path = RNA_path_from_ID_to_property_index(
ptr, prop, index_dim, index);
if (!path) {
return std::nullopt;
}
/* Null path is always an error here, in that case do not return the 'fake ID from real ID' part
* of the path either. */
return path != nullptr ? rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real_id) :
nullptr;
return rna_prepend_real_ID_path(bmain, ptr->owner_id, path->c_str(), r_real_id);
}
char *RNA_path_resolve_from_type_to_property(const PointerRNA *ptr,
PropertyRNA *prop,
const StructRNA *type)
std::optional<std::string> RNA_path_resolve_from_type_to_property(const PointerRNA *ptr,
PropertyRNA *prop,
const StructRNA *type)
{
/* Try to recursively find an "type"'d ancestor,
* to handle situations where path from ID is not enough. */
ListBase path_elems = {nullptr};
char *path = nullptr;
char *full_path = RNA_path_from_ID_to_property(ptr, prop);
if (full_path == nullptr) {
return nullptr;
const std::optional<std::string> full_path = RNA_path_from_ID_to_property(ptr, prop);
if (!full_path) {
return std::nullopt;
}
PointerRNA idptr = RNA_id_pointer_create(ptr->owner_id);
if (RNA_path_resolve_elements(&idptr, full_path, &path_elems)) {
std::optional<std::string> path;
if (RNA_path_resolve_elements(&idptr, full_path->c_str(), &path_elems)) {
LISTBASE_FOREACH_BACKWARD (PropertyElemRNA *, prop_elem, &path_elems) {
if (RNA_struct_is_a(prop_elem->ptr.type, type)) {
char *ref_path = RNA_path_from_ID_to_struct(&prop_elem->ptr);
if (ref_path) {
path = BLI_strdup(full_path + strlen(ref_path) + 1); /* +1 for the linking '.' */
MEM_freeN(ref_path);
if (const std::optional<std::string> ref_path = RNA_path_from_ID_to_struct(
&prop_elem->ptr))
{
path = blender::StringRef(*full_path).drop_prefix(ref_path->size() + 1);
}
break;
}
@ -1195,11 +1197,10 @@ char *RNA_path_resolve_from_type_to_property(const PointerRNA *ptr,
BLI_freelistN(&path_elems);
}
MEM_freeN(full_path);
return path;
}
char *RNA_path_full_ID_py(ID *id)
std::string RNA_path_full_ID_py(ID *id)
{
const char *path;
ID *id_real = RNA_find_real_ID_and_path(id, &path);
@ -1226,65 +1227,47 @@ char *RNA_path_full_ID_py(ID *id)
char id_esc[(sizeof(id->name) - 2) * 2];
BLI_str_escape(id_esc, id->name + 2, sizeof(id_esc));
return BLI_sprintfN("bpy.data.%s[\"%s\"%s]%s%s",
BKE_idtype_idcode_to_name_plural(GS(id->name)),
id_esc,
lib_filepath_esc,
path[0] ? "." : "",
path);
return fmt::format("bpy.data.{}[\"{}\"{}]{}{}",
BKE_idtype_idcode_to_name_plural(GS(id->name)),
id_esc,
lib_filepath_esc,
path[0] ? "." : "",
path);
}
char *RNA_path_full_struct_py(const PointerRNA *ptr)
std::optional<std::string> RNA_path_full_struct_py(const PointerRNA *ptr)
{
char *id_path;
char *data_path;
char *ret;
if (!ptr->owner_id) {
return nullptr;
return std::nullopt;
}
/* never fails */
id_path = RNA_path_full_ID_py(ptr->owner_id);
std::string id_path = RNA_path_full_ID_py(ptr->owner_id);
data_path = RNA_path_from_ID_to_struct(ptr);
std::optional<std::string> data_path = RNA_path_from_ID_to_struct(ptr);
/* XXX data_path may be null (see #36788),
* do we want to get the 'bpy.data.foo["bar"].(null)' stuff? */
ret = BLI_sprintfN("%s.%s", id_path, data_path);
if (data_path) {
MEM_freeN(data_path);
}
MEM_freeN(id_path);
return ret;
return fmt::format("{}.{}", id_path, data_path.value_or(""));
}
char *RNA_path_full_property_py_ex(const PointerRNA *ptr,
PropertyRNA *prop,
int index,
bool use_fallback)
std::optional<std::string> RNA_path_full_property_py_ex(const PointerRNA *ptr,
PropertyRNA *prop,
int index,
bool use_fallback)
{
char *id_path;
const char *data_delim;
const char *data_path;
bool data_path_free;
char *ret;
if (!ptr->owner_id) {
return nullptr;
return std::nullopt;
}
/* never fails */
id_path = RNA_path_full_ID_py(ptr->owner_id);
std::string id_path = RNA_path_full_ID_py(ptr->owner_id);
data_path = RNA_path_from_ID_to_property(ptr, prop);
std::optional<std::string> data_path = RNA_path_from_ID_to_property(ptr, prop);
if (data_path) {
data_delim = (data_path[0] == '[') ? "" : ".";
data_path_free = true;
data_delim = ((*data_path)[0] == '[') ? "" : ".";
}
else {
if (use_fallback) {
@ -1295,66 +1278,49 @@ char *RNA_path_full_property_py_ex(const PointerRNA *ptr,
else {
data_delim = ".";
}
data_path_free = false;
}
if ((index == -1) || (RNA_property_array_check(prop) == false)) {
ret = BLI_sprintfN("%s%s%s", id_path, data_delim, data_path);
return fmt::format("{}{}{}", id_path, data_delim, data_path.value_or(""));
}
else {
ret = BLI_sprintfN("%s%s%s[%d]", id_path, data_delim, data_path, index);
}
MEM_freeN(id_path);
if (data_path_free) {
MEM_freeN((void *)data_path);
}
return ret;
return fmt::format("{}{}{}[{}]", id_path, data_delim, data_path.value_or(""), index);
}
char *RNA_path_full_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index)
std::optional<std::string> RNA_path_full_property_py(const PointerRNA *ptr,
PropertyRNA *prop,
int index)
{
return RNA_path_full_property_py_ex(ptr, prop, index, false);
}
char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
std::optional<std::string> RNA_path_struct_property_py(PointerRNA *ptr,
PropertyRNA *prop,
int index)
{
char *data_path;
char *ret;
if (!ptr->owner_id) {
return nullptr;
return std::nullopt;
}
data_path = RNA_path_from_ID_to_property(ptr, prop);
std::optional<std::string> data_path = RNA_path_from_ID_to_property(ptr, prop);
if (data_path == nullptr) {
if (!data_path) {
/* This may not be an ID at all, check for simple when pointer owns property.
* TODO: more complex nested case. */
if (!RNA_struct_is_ID(ptr->type)) {
const char *prop_identifier = RNA_property_identifier(prop);
if (RNA_struct_find_property(ptr, prop_identifier) == prop) {
data_path = BLI_strdup(prop_identifier);
data_path = prop_identifier;
}
}
}
if ((index == -1) || (RNA_property_array_check(prop) == false)) {
ret = BLI_strdup(data_path);
return *data_path;
}
else {
ret = BLI_sprintfN("%s[%d]", data_path, index);
}
if (data_path) {
MEM_freeN(data_path);
}
return ret;
return fmt::format("{}[{}]", data_path.value_or(""), index);
}
char *RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index)
std::string RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index)
{
if (RNA_property_array_check(prop) == false) {
index = -1;

View File

@ -924,10 +924,10 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
"bpy.data.%s[%R]", BKE_idtype_idcode_to_name_plural(GS(id->name)), tmp_str);
}
else {
const char *path;
ID *real_id = nullptr;
path = RNA_path_from_real_ID_to_struct(G_MAIN, &self->ptr, &real_id);
if (path != nullptr) {
const std::optional<std::string> path = RNA_path_from_real_ID_to_struct(
G_MAIN, &self->ptr, &real_id);
if (path) {
/* 'real_id' may be nullptr in some cases, although the only valid one is evaluated data,
* which should have already been caught above.
* So assert, but handle it without crashing for release builds. */
@ -939,7 +939,7 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
ret = PyUnicode_FromFormat("bpy.data.%s[%R].%s",
BKE_idtype_idcode_to_name_plural(GS(real_id->name)),
tmp_str,
path);
path->c_str());
}
else {
/* Can't find the path, print something useful as a fallback. */
@ -948,7 +948,6 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
tmp_str,
RNA_struct_identifier(self->ptr.type));
}
MEM_freeN((void *)path);
}
else {
/* Can't find the path, print something useful as a fallback. */
@ -1038,7 +1037,6 @@ static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim,
ID *id = self->ptr.owner_id;
PyObject *tmp_str;
PyObject *ret;
const char *path;
PYRNA_PROP_CHECK_OBJ(self);
@ -1052,7 +1050,7 @@ static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim,
/* Note that using G_MAIN is absolutely not ideal, but we have no access to actual Main DB from
* here. */
ID *real_id = nullptr;
path = RNA_path_from_real_ID_to_property_index(
const std::optional<std::string> path = RNA_path_from_real_ID_to_property_index(
G_MAIN, &self->ptr, self->prop, index_dim, index, &real_id);
if (path) {
@ -1060,14 +1058,12 @@ static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim,
Py_DECREF(tmp_str);
tmp_str = PyUnicode_FromString(real_id->name + 2);
}
const char *data_delim = (path[0] == '[') ? "" : ".";
const char *data_delim = ((*path)[0] == '[') ? "" : ".";
ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s",
BKE_idtype_idcode_to_name_plural(GS(real_id->name)),
tmp_str,
data_delim,
path);
MEM_freeN((void *)path);
path->c_str());
}
else {
/* Can't find the path, print something useful as a fallback. */
@ -3892,7 +3888,6 @@ PyDoc_STRVAR(
static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args)
{
const char *name = nullptr;
const char *path;
PropertyRNA *prop;
PyObject *ret;
@ -3902,6 +3897,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args)
return nullptr;
}
std::optional<std::string> path;
if (name) {
prop = RNA_struct_find_property(&self->ptr, name);
if (prop == nullptr) {
@ -3918,7 +3914,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args)
path = RNA_path_from_ID_to_struct(&self->ptr);
}
if (path == nullptr) {
if (!path) {
if (name) {
PyErr_Format(PyExc_ValueError,
"%.200s.path_from_id(\"%s\") found, but does not support path creation",
@ -3933,8 +3929,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args)
return nullptr;
}
ret = PyUnicode_FromString(path);
MEM_freeN((void *)path);
ret = PyUnicode_FromString(path->c_str());
return ret;
}
@ -3950,13 +3945,12 @@ PyDoc_STRVAR(
" :rtype: str\n");
static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self)
{
const char *path;
PropertyRNA *prop = self->prop;
PyObject *ret;
path = RNA_path_from_ID_to_property(&self->ptr, self->prop);
const std::optional<std::string> path = RNA_path_from_ID_to_property(&self->ptr, self->prop);
if (path == nullptr) {
if (!path) {
PyErr_Format(PyExc_ValueError,
"%.200s.%.200s.path_from_id() does not support path creation for this type",
RNA_struct_identifier(self->ptr.type),
@ -3964,8 +3958,7 @@ static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self)
return nullptr;
}
ret = PyUnicode_FromString(path);
MEM_freeN((void *)path);
ret = PyUnicode_FromString(path->c_str());
return ret;
}
@ -4469,7 +4462,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
PointerRNA idptr;
PointerRNA *base_ptr;
char *path_str;
std::optional<std::string> path_str;
if (newptr.owner_id) {
idptr = RNA_id_pointer_create(newptr.owner_id);
@ -4485,10 +4478,8 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
ret = PyTuple_New(3);
PyTuple_SET_ITEMS(ret,
pyrna_struct_CreatePyObject(base_ptr),
PyUnicode_FromString(path_str),
PyUnicode_FromString(path_str->c_str()),
PyLong_FromLong(newindex));
MEM_freeN(path_str);
}
else {
ret = Py_None;
@ -6783,18 +6774,15 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void * /*closure*/)
{
PyObject *ret;
char *args;
args = RNA_function_as_string_keywords(nullptr, self->func, true, true, INT_MAX);
std::string args = RNA_function_as_string_keywords(nullptr, self->func, true, true, INT_MAX);
ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s",
RNA_struct_identifier(self->ptr.type),
RNA_function_identifier(self->func),
args,
args.c_str(),
RNA_function_ui_description(self->func));
MEM_freeN(args);
return ret;
}

View File

@ -142,7 +142,8 @@ static int pyrna_struct_anim_args_parse_ex(PointerRNA *ptr,
*r_path_full = BLI_strdup(path);
}
else {
*r_path_full = RNA_path_from_ID_to_property(&r_ptr, prop);
const std::optional<std::string> path_full = RNA_path_from_ID_to_property(&r_ptr, prop);
*r_path_full = path_full ? BLI_strdup(path_full->c_str()) : nullptr;
if (*r_path_full == nullptr) {
PyErr_Format(PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path);
@ -176,8 +177,8 @@ static int pyrna_struct_anim_args_parse_no_resolve(PointerRNA *ptr,
return 0;
}
char *path_prefix = RNA_path_from_ID_to_struct(ptr);
if (path_prefix == nullptr) {
const std::optional<std::string> path_prefix = RNA_path_from_ID_to_struct(ptr);
if (!path_prefix) {
PyErr_Format(PyExc_TypeError,
"%.200s could not make path for type %s",
error_prefix,
@ -186,12 +187,11 @@ static int pyrna_struct_anim_args_parse_no_resolve(PointerRNA *ptr,
}
if (*path == '[') {
*r_path_full = BLI_string_joinN(path_prefix, path);
*r_path_full = BLI_string_joinN(path_prefix->c_str(), path);
}
else {
*r_path_full = BLI_string_join_by_sep_charN('.', path_prefix, path);
*r_path_full = BLI_string_join_by_sep_charN('.', path_prefix->c_str(), path);
}
MEM_freeN(path_prefix);
return 0;
}

View File

@ -2930,7 +2930,7 @@ static const char *keymap_handler_log_kmi_op_str(bContext *C,
size_t buf_maxncpy)
{
/* The key-map item properties can further help distinguish this item from others. */
char *kmi_props = nullptr;
std::optional<std::string> kmi_props;
if (kmi->properties != nullptr) {
wmOperatorType *ot = WM_operatortype_find(kmi->idname, false);
if (ot) {
@ -2940,10 +2940,7 @@ static const char *keymap_handler_log_kmi_op_str(bContext *C,
kmi_props = IDP_reprN(kmi->properties, nullptr);
}
}
BLI_snprintf(buf, buf_maxncpy, "%s(%s)", kmi->idname, kmi_props ? kmi_props : "");
if (kmi_props != nullptr) {
MEM_freeN(kmi_props);
}
BLI_snprintf(buf, buf_maxncpy, "%s(%s)", kmi->idname, kmi_props.value_or("").c_str());
return buf;
}

View File

@ -246,15 +246,14 @@ std::string WM_operator_pystring_ex(bContext *C,
opmptr = &opmptr_default;
}
char *cstring_args = RNA_pointer_as_string_id(C, opmptr);
std::string string_args = RNA_pointer_as_string_id(C, opmptr);
if (first_op) {
ss << opm->type->idname << '=' << cstring_args;
ss << opm->type->idname << '=' << string_args;
first_op = false;
}
else {
ss << ", " << opm->type->idname << '=' << cstring_args;
ss << ", " << opm->type->idname << '=' << string_args;
}
MEM_freeN(cstring_args);
if (opmptr == &opmptr_default) {
WM_operator_properties_free(&opmptr_default);
@ -271,10 +270,8 @@ std::string WM_operator_pystring_ex(bContext *C,
opptr = &opptr_default;
}
char *cstring_args = RNA_pointer_as_string_keywords(
ss << RNA_pointer_as_string_keywords(
C, opptr, false, all_args, macro_args_test, max_prop_length);
ss << cstring_args;
MEM_freeN(cstring_args);
if (opptr == &opptr_default) {
WM_operator_properties_free(&opptr_default);
@ -608,34 +605,31 @@ std::optional<std::string> WM_context_path_resolve_property_full(const bContext
}
std::string member_id_data_path;
if (is_id && !RNA_struct_is_ID(ptr->type)) {
char *data_path = RNA_path_from_ID_to_struct(ptr);
if (data_path != nullptr) {
std::optional<std::string> data_path = RNA_path_from_ID_to_struct(ptr);
if (data_path) {
if (prop != nullptr) {
char *prop_str = RNA_path_property_py(ptr, prop, index);
std::string prop_str = RNA_path_property_py(ptr, prop, index);
if (prop_str[0] == '[') {
member_id_data_path = fmt::format("{}.{}", data_path, prop_str);
member_id_data_path = fmt::format("{}.{}", *data_path, prop_str);
}
else {
member_id_data_path = fmt::format("{}.{}.{}", member_id, data_path, prop_str);
member_id_data_path = fmt::format("{}.{}.{}", member_id, *data_path, prop_str);
}
MEM_freeN(prop_str);
}
else {
member_id_data_path = fmt::format("{}.{}", member_id, data_path);
member_id_data_path = fmt::format("{}.{}", member_id, *data_path);
}
MEM_freeN(data_path);
}
}
else {
if (prop != nullptr) {
char *prop_str = RNA_path_property_py(ptr, prop, index);
std::string prop_str = RNA_path_property_py(ptr, prop, index);
if (prop_str[0] == '[') {
member_id_data_path = fmt::format("{}{}", member_id, prop_str);
}
else {
member_id_data_path = fmt::format("{}.{}", member_id, prop_str);
}
MEM_freeN(prop_str);
}
else {
member_id_data_path = member_id;
@ -673,22 +667,17 @@ std::optional<std::string> WM_prop_pystring_assign(bContext *C,
if (!lhs.has_value()) {
/* Fallback to `bpy.data.foo[id]` if we don't find in the context. */
if (char *lhs_cstr = RNA_path_full_property_py(ptr, prop, index)) {
lhs = lhs_cstr;
MEM_freeN(lhs_cstr);
if (std::optional<std::string> lhs_str = RNA_path_full_property_py(ptr, prop, index)) {
lhs = lhs_str;
}
else {
return std::nullopt;
}
}
char *rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX);
if (!rhs) {
return std::nullopt;
}
std::string rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX);
std::string ret = fmt::format("{} = {}", lhs.value(), rhs);
MEM_freeN(rhs);
return ret;
}
@ -1523,12 +1512,12 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
BLF_width(style->widget.uifont_id, data->title.c_str(), BLF_DRAW_STR_DUMMY_MAX));
/* Break Message into multiple lines. */
std::vector<std::string> message_lines;
blender::Vector<std::string> message_lines;
blender::StringRef messaged_trimmed = blender::StringRef(data->message).trim();
std::istringstream message_stream(messaged_trimmed);
std::string line;
while (std::getline(message_stream, line)) {
message_lines.push_back(line);
message_lines.append(line);
text_width = std::max(
text_width, int(BLF_width(style->widget.uifont_id, line.c_str(), BLF_DRAW_STR_DUMMY_MAX)));
}

View File

@ -15,6 +15,7 @@
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "WM_message.hh"
@ -316,7 +317,9 @@ void WM_msg_subscribe_rna_params(wmMsgBus *mbus,
if (msg_key->msg.params.data_path == nullptr) {
if (msg_key->msg.params.ptr.data != msg_key->msg.params.ptr.owner_id) {
/* We assume prop type can't change. */
msg_key->msg.params.data_path = RNA_path_from_ID_to_struct(&msg_key->msg.params.ptr);
const std::optional<std::string> str = RNA_path_from_ID_to_struct(
&msg_key->msg.params.ptr);
msg_key->msg.params.data_path = str ? BLI_strdupn(str->c_str(), str->size()) : nullptr;
}
}
}