Cleanup: Use std::string for WM API function return values

This commit is contained in:
Hans Goudey
2024-01-29 16:33:06 -05:00
parent 4fa780d334
commit 61fb2b17c8
10 changed files with 174 additions and 204 deletions

View File

@@ -1359,6 +1359,7 @@ static bool ui_but_event_property_operator_string(const bContext *C,
char *buf,
const size_t buf_maxncpy)
{
using namespace blender;
/* Context toggle operator names to check. */
/* NOTE(@ideasman42): This function could use a refactor to generalize button type to operator
@@ -1448,18 +1449,17 @@ static bool ui_but_event_property_operator_string(const bContext *C,
/* There may be multiple data-paths to the same properties,
* support different variations so key bindings are properly detected no matter which are used.
*/
char *data_path_variations[2] = {nullptr};
int data_path_variations_num = 0;
Vector<std::string, 2> data_path_variations;
{
char *data_path = WM_context_path_resolve_property_full(C, ptr, prop, prop_index);
std::string data_path = WM_context_path_resolve_property_full(C, ptr, prop, prop_index);
/* Always iterate once, even if data-path isn't set. */
data_path_variations[data_path_variations_num++] = data_path;
data_path_variations.append(data_path);
if (data_path) {
if (STRPREFIX(data_path, "scene.tool_settings.")) {
data_path_variations[data_path_variations_num++] = BLI_strdup(data_path + 6);
if (!data_path.empty()) {
if (StringRef(data_path).startswith("scene.tool_settings.")) {
data_path_variations.append(StringRef(data_path).drop_known_prefix("scene."));
}
}
}
@@ -1467,18 +1467,18 @@ static bool ui_but_event_property_operator_string(const bContext *C,
/* We have a data-path! */
bool found = false;
for (int data_path_index = 0; data_path_index < data_path_variations_num && (found == false);
for (int data_path_index = 0; data_path_index < data_path_variations.size() && (found == false);
data_path_index++)
{
const char *data_path = data_path_variations[data_path_index];
if (data_path || (prop_enum_value_ok && prop_enum_value_id)) {
const StringRefNull data_path = data_path_variations[data_path_index];
if (!data_path.is_empty() || (prop_enum_value_ok && prop_enum_value_id)) {
/* Create a property to host the "data_path" property we're sending to the operators. */
IDProperty *prop_path;
const IDPropertyTemplate group_val = {0};
prop_path = IDP_New(IDP_GROUP, &group_val, __func__);
if (data_path) {
IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path"));
if (!data_path.is_empty()) {
IDP_AddToGroup(prop_path, IDP_NewString(data_path.c_str(), "data_path"));
}
if (prop_enum_value_ok) {
const EnumPropertyItem *item;
@@ -1522,12 +1522,6 @@ static bool ui_but_event_property_operator_string(const bContext *C,
}
}
for (int data_path_index = 0; data_path_index < data_path_variations_num; data_path_index++) {
char *data_path = data_path_variations[data_path_index];
if (data_path) {
MEM_freeN(data_path);
}
}
return found;
}

View File

@@ -61,18 +61,16 @@ static IDProperty *shortcut_property_from_rna(bContext *C, uiBut *but)
/* If this returns null, we won't be able to bind shortcuts to these RNA properties.
* Support can be added at #wm_context_member_from_ptr. */
char *final_data_path = WM_context_path_resolve_property_full(
std::string final_data_path = WM_context_path_resolve_property_full(
C, &but->rnapoin, but->rnaprop, but->rnaindex);
if (final_data_path == nullptr) {
if (final_data_path.empty()) {
return nullptr;
}
/* Create ID property of data path, to pass to the operator. */
const IDPropertyTemplate val = {0};
IDProperty *prop = IDP_New(IDP_GROUP, &val, __func__);
IDP_AddToGroup(prop, IDP_NewString(final_data_path, "data_path"));
MEM_freeN((void *)final_data_path);
IDP_AddToGroup(prop, IDP_NewString(final_data_path.c_str(), "data_path"));
return prop;
}
@@ -321,9 +319,8 @@ static bool ui_but_is_user_menu_compatible(bContext *C, uiBut *but)
}
else if (but->rnaprop) {
if (RNA_property_type(but->rnaprop) == PROP_BOOLEAN) {
char *data_path = WM_context_path_resolve_full(C, &but->rnapoin);
if (data_path != nullptr) {
MEM_freeN(data_path);
std::string data_path = WM_context_path_resolve_full(C, &but->rnapoin);
if (!data_path.empty()) {
result = true;
}
}
@@ -346,14 +343,13 @@ static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *
&um->items, but->optype, prop, "", but->opcontext);
}
if (but->rnaprop) {
char *member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
std::string member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
/* 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);
bUserMenuItem *umi = (bUserMenuItem *)ED_screen_user_menu_item_find_prop(
&um->items, member_id_data_path, prop_id, but->rnaindex);
MEM_freeN(member_id_data_path);
&um->items, member_id_data_path.c_str(), prop_id, but->rnaindex);
return umi;
}
@@ -423,14 +419,14 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
}
else if (but->rnaprop) {
/* NOTE: 'member_id' may be a path. */
char *member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
std::string member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
/* 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);
/* NOTE: ignore 'drawstr', use property idname always. */
ED_screen_user_menu_item_add_prop(&um->items, "", member_id_data_path, prop_id, but->rnaindex);
MEM_freeN(member_id_data_path);
ED_screen_user_menu_item_add_prop(
&um->items, "", member_id_data_path.c_str(), prop_id, but->rnaindex);
}
else if ((mt = UI_but_menutype_get(but))) {
ED_screen_user_menu_item_add_menu(&um->items, drawstr.c_str(), mt);

View File

@@ -1001,13 +1001,12 @@ static void ui_apply_but_autokey(bContext *C, uiBut *but)
}
/* make a little report about what we've done! */
char *buf = WM_prop_pystring_assign(C, &but->rnapoin, but->rnaprop, but->rnaindex);
if (buf) {
BKE_report(CTX_wm_reports(C), RPT_PROPERTY, buf);
MEM_freeN(buf);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, nullptr);
const std::string str = WM_prop_pystring_assign(C, &but->rnapoin, but->rnaprop, but->rnaindex);
if (str.empty()) {
return;
}
BKE_report(CTX_wm_reports(C), RPT_PROPERTY, str.c_str());
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, nullptr);
}
static void ui_apply_but_funcs_after(bContext *C)
@@ -2736,10 +2735,8 @@ static void ui_but_copy_operator(bContext *C, uiBut *but, char *output, int outp
{
PointerRNA *opptr = UI_but_operator_ptr_ensure(but);
char *str;
str = WM_operator_pystring_ex(C, nullptr, false, true, but->optype, opptr);
BLI_strncpy(output, str, output_maxncpy);
MEM_freeN(str);
std::string str = WM_operator_pystring_ex(C, nullptr, false, true, but->optype, opptr);
BLI_strncpy(output, str.c_str(), output_maxncpy);
}
static bool ui_but_copy_menu(uiBut *but, char *output, int output_maxncpy)

View File

@@ -6287,25 +6287,23 @@ static void ui_layout_introspect_button(DynStr *ds, uiButtonItem *bitem)
BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : "");
if (but->optype) {
char *opstr = WM_operator_pystring_ex(static_cast<bContext *>(but->block->evil_C),
nullptr,
false,
true,
but->optype,
but->opptr);
BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
MEM_freeN(opstr);
std::string opstr = WM_operator_pystring_ex(static_cast<bContext *>(but->block->evil_C),
nullptr,
false,
true,
but->optype,
but->opptr);
BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr.c_str());
}
{
PropertyRNA *prop = nullptr;
wmOperatorType *ot = UI_but_operatortype_get_from_enum_menu(but, &prop);
if (ot) {
char *opstr = WM_operator_pystring_ex(
std::string opstr = WM_operator_pystring_ex(
static_cast<bContext *>(but->block->evil_C), nullptr, false, true, ot, nullptr);
BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr.c_str());
BLI_dynstr_appendf(ds, "'property':'''%s''', ", prop ? RNA_property_identifier(prop) : "");
MEM_freeN(opstr);
}
}

View File

@@ -283,15 +283,12 @@ static int copy_python_command_button_exec(bContext *C, wmOperator * /*op*/)
uiBut *but = UI_context_active_but_get(C);
if (but && (but->optype != nullptr)) {
PointerRNA *opptr;
char *str;
opptr = UI_but_operator_ptr_ensure(but); /* allocated when needed, the button owns it */
/* allocated when needed, the button owns it */
PointerRNA *opptr = UI_but_operator_ptr_ensure(but);
str = WM_operator_pystring_ex(C, nullptr, false, true, but->optype, opptr);
std::string str = WM_operator_pystring_ex(C, nullptr, false, true, but->optype, opptr);
WM_clipboard_text_set(str, false);
MEM_freeN(str);
WM_clipboard_text_set(str.c_str(), false);
return OPERATOR_FINISHED;
}

View File

@@ -347,14 +347,14 @@ static void ui_tooltip_region_free_cb(ARegion *region)
/** \name ToolTip Creation Utility Functions
* \{ */
static char *ui_tooltip_text_python_from_op(bContext *C, wmOperatorType *ot, PointerRNA *opptr)
static std::string ui_tooltip_text_python_from_op(bContext *C,
wmOperatorType *ot,
PointerRNA *opptr)
{
char *str = WM_operator_pystring_ex(C, nullptr, false, false, ot, opptr);
std::string str = WM_operator_pystring_ex(C, nullptr, false, false, ot, opptr);
/* Avoid overly verbose tips (eg, arrays of 20 layers), exact limit is arbitrary. */
WM_operator_pystring_abbreviate(str, 32);
return str;
return WM_operator_pystring_abbreviate(std::move(str), 32);
}
/** \} */
@@ -397,10 +397,9 @@ static bool ui_tooltip_data_append_from_keymap(bContext *C, uiTooltipData *data,
/* Python. */
if (U.flag & USER_TOOLTIPS_PYTHON) {
char *str = ui_tooltip_text_python_from_op(C, ot, kmi->ptr);
std::string str = ui_tooltip_text_python_from_op(C, ot, kmi->ptr);
UI_tooltip_text_field_add(
data, fmt::format(TIP_("Python: {}"), str), {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_PYTHON);
MEM_freeN(str);
}
}
}
@@ -744,14 +743,13 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
/* Python */
if ((is_label == false) && (U.flag & USER_TOOLTIPS_PYTHON)) {
char *str = ui_tooltip_text_python_from_op(C, but->optype, but->opptr);
std::string str = ui_tooltip_text_python_from_op(C, but->optype, but->opptr);
UI_tooltip_text_field_add(data,
fmt::format(TIP_("Python: {}"), str),
{},
UI_TIP_STYLE_NORMAL,
UI_TIP_LC_PYTHON,
true);
MEM_freeN(str);
}
/* Keymap */
@@ -985,7 +983,7 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
/* So the context is passed to field functions (some Python field functions use it). */
WM_operator_properties_sanitize(opptr, false);
char *str = ui_tooltip_text_python_from_op(C, optype, opptr);
std::string str = ui_tooltip_text_python_from_op(C, optype, opptr);
/* Operator info. */
if (U.flag & USER_TOOLTIPS_PYTHON) {
@@ -996,8 +994,6 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
UI_TIP_LC_PYTHON,
true);
}
MEM_freeN(str);
}
/* Button is disabled, we may be able to tell user why. */

View File

@@ -313,7 +313,6 @@ static PyObject *pyop_as_string(PyObject * /*self*/, PyObject *args)
bool macro_args = true;
int error_val = 0;
char *buf = nullptr;
PyObject *pybuf;
bContext *C = BPY_context_get();
@@ -370,8 +369,9 @@ static PyObject *pyop_as_string(PyObject * /*self*/, PyObject *args)
&ptr, kw, false, "Converting py args to operator properties: ");
}
std::string op_string;
if (error_val == 0) {
buf = WM_operator_pystring_ex(C, nullptr, all_args, macro_args, ot, &ptr);
op_string = WM_operator_pystring_ex(C, nullptr, all_args, macro_args, ot, &ptr);
}
WM_operator_properties_free(&ptr);
@@ -380,9 +380,8 @@ static PyObject *pyop_as_string(PyObject * /*self*/, PyObject *args)
return nullptr;
}
if (buf) {
pybuf = PyUnicode_FromString(buf);
MEM_freeN(buf);
if (!op_string.empty()) {
pybuf = PyUnicode_FromString(op_string.c_str());
}
else {
pybuf = PyUnicode_FromString("");

View File

@@ -14,6 +14,8 @@
* \todo document
*/
#include <string>
#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h"
#include "DNA_windowmanager_types.h"
@@ -1045,9 +1047,9 @@ bool WM_operator_properties_checker_interval_test(const CheckerIntervalParams *o
int depth);
/**
* Operator as a Python command (resulting string must be freed).
* Operator as a Python command.
*
* Print a string representation of the operator,
* Return a string representation of the operator,
* with the arguments that it runs so Python can run it again.
*
* When calling from an existing #wmOperator, better to use simple version:
@@ -1055,18 +1057,17 @@ bool WM_operator_properties_checker_interval_test(const CheckerIntervalParams *o
*
* \note Both \a op and \a opptr may be `NULL` (\a op is only used for macro operators).
*/
char *WM_operator_pystring_ex(bContext *C,
wmOperator *op,
bool all_args,
bool macro_args,
wmOperatorType *ot,
PointerRNA *opptr);
char *WM_operator_pystring(bContext *C, wmOperator *op, bool all_args, bool macro_args);
/**
* \return true if the string was shortened.
*/
bool WM_operator_pystring_abbreviate(char *str, int str_len_max);
char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index);
std::string WM_operator_pystring_ex(bContext *C,
wmOperator *op,
bool all_args,
bool macro_args,
wmOperatorType *ot,
PointerRNA *opptr);
std::string WM_operator_pystring(bContext *C, wmOperator *op, bool all_args, bool macro_args);
std::string WM_operator_pystring_abbreviate(std::string str, int str_len_max);
std::string WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index);
/**
* Convert: `some.op` -> `SOME_OT_op` or leave as-is.
* \return the length of `dst`.
@@ -1087,11 +1088,11 @@ bool WM_operator_py_idname_ok_or_report(ReportList *reports,
/**
* Calculate the path to `ptr` from context `C`, or return NULL if it can't be calculated.
*/
char *WM_context_path_resolve_property_full(const bContext *C,
const PointerRNA *ptr,
PropertyRNA *prop,
int index);
char *WM_context_path_resolve_full(bContext *C, const PointerRNA *ptr);
std::string WM_context_path_resolve_property_full(const bContext *C,
const PointerRNA *ptr,
PropertyRNA *prop,
int index);
std::string WM_context_path_resolve_full(bContext *C, const PointerRNA *ptr);
/* `wm_operator_type.cc` */

View File

@@ -1097,7 +1097,7 @@ static void wm_operator_reports(bContext *C,
}
if (retval & OPERATOR_FINISHED) {
CLOG_STR_INFO_N(WM_LOG_OPERATORS, 1, WM_operator_pystring(C, op, false, true));
CLOG_STR_INFO_N(WM_LOG_OPERATORS, 1, WM_operator_pystring(C, op, false, true).c_str());
if (caller_owns_reports == false) {
BKE_reports_print(op->reports, RPT_DEBUG); /* Print out reports to console. */
@@ -1105,10 +1105,9 @@ static void wm_operator_reports(bContext *C,
if (op->type->flag & OPTYPE_REGISTER) {
if (G.background == 0) { /* Ends up printing these in the terminal, gets annoying. */
/* Report the python string representation of the operator. */
char *buf = WM_operator_pystring(C, op, false, true);
BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
MEM_freeN(buf);
/* Report the python string representation of the operator. */
std::string pystring = WM_operator_pystring(C, op, false, true);
BKE_report(CTX_wm_reports(C), RPT_OPERATOR, pystring.c_str());
}
}
}
@@ -1189,9 +1188,8 @@ static void wm_operator_finished(bContext *C,
if (repeat == 0) {
if (G.debug & G_DEBUG_WM) {
char *buf = WM_operator_pystring(C, op, false, true);
BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
MEM_freeN(buf);
std::string pystring = WM_operator_pystring(C, op, false, true);
BKE_report(CTX_wm_reports(C), RPT_OPERATOR, pystring.c_str());
}
if (do_register) {

View File

@@ -19,6 +19,8 @@
#include <iostream>
#include <sstream>
#include <fmt/format.h>
#ifdef WIN32
# include "GHOST_C-api.h"
#endif
@@ -40,7 +42,6 @@
#include "BLI_blenlib.h"
#include "BLI_dial_2d.h"
#include "BLI_dynstr.h" /* For #WM_operator_pystring. */
#include "BLI_math_rotation.h"
#include "BLI_math_vector_types.hh"
#include "BLI_string_utils.hh"
@@ -212,23 +213,23 @@ bool WM_operator_py_idname_ok_or_report(ReportList *reports,
return true;
}
char *WM_operator_pystring_ex(bContext *C,
wmOperator *op,
const bool all_args,
const bool macro_args,
wmOperatorType *ot,
PointerRNA *opptr)
std::string WM_operator_pystring_ex(bContext *C,
wmOperator *op,
const bool all_args,
const bool macro_args,
wmOperatorType *ot,
PointerRNA *opptr)
{
char idname_py[OP_MAX_TYPENAME];
/* for building the string */
DynStr *dynstr = BLI_dynstr_new();
std::stringstream ss;
/* arbitrary, but can get huge string with stroke painting otherwise */
int max_prop_length = 10;
WM_operator_py_idname(idname_py, ot->idname);
BLI_dynstr_appendf(dynstr, "bpy.ops.%s(", idname_py);
ss << "bpy.ops." << idname_py << "(";
if (op && op->macro.first) {
/* Special handling for macros, else we only get default values in this case... */
@@ -247,11 +248,11 @@ char *WM_operator_pystring_ex(bContext *C,
char *cstring_args = RNA_pointer_as_string_id(C, opmptr);
if (first_op) {
BLI_dynstr_appendf(dynstr, "%s=%s", opm->type->idname, cstring_args);
ss << opm->type->idname << '=' << cstring_args;
first_op = false;
}
else {
BLI_dynstr_appendf(dynstr, ", %s=%s", opm->type->idname, cstring_args);
ss << ", " << opm->type->idname << '=' << cstring_args;
}
MEM_freeN(cstring_args);
@@ -272,7 +273,7 @@ char *WM_operator_pystring_ex(bContext *C,
char *cstring_args = RNA_pointer_as_string_keywords(
C, opptr, false, all_args, macro_args_test, max_prop_length);
BLI_dynstr_append(dynstr, cstring_args);
ss << cstring_args;
MEM_freeN(cstring_args);
if (opptr == &opptr_default) {
@@ -280,53 +281,53 @@ char *WM_operator_pystring_ex(bContext *C,
}
}
BLI_dynstr_append(dynstr, ")");
ss << ')';
char *cstring = BLI_dynstr_get_cstring(dynstr);
BLI_dynstr_free(dynstr);
return cstring;
return ss.str();
}
char *WM_operator_pystring(bContext *C, wmOperator *op, const bool all_args, const bool macro_args)
std::string WM_operator_pystring(bContext *C,
wmOperator *op,
const bool all_args,
const bool macro_args)
{
return WM_operator_pystring_ex(C, op, all_args, macro_args, op->type, op->ptr);
}
bool WM_operator_pystring_abbreviate(char *str, int str_len_max)
std::string WM_operator_pystring_abbreviate(std::string str, int str_len_max)
{
const int str_len = strlen(str);
const char *parens_start = strchr(str, '(');
if (parens_start) {
const int parens_start_pos = parens_start - str;
const char *parens_end = strrchr(parens_start + 1, ')');
if (parens_end) {
const int parens_len = parens_end - parens_start;
if (parens_len > str_len_max) {
const char *comma_first = strchr(parens_start, ',');
/* Truncate after the first comma. */
if (comma_first) {
const char end_str[] = " ... )";
const int end_str_len = sizeof(end_str) - 1;
/* Leave a place for the first argument. */
const int new_str_len = (comma_first - parens_start) + 1;
if (str_len >= new_str_len + parens_start_pos + end_str_len + 1) {
/* Append " ... )" to the string after the comma. */
memcpy(str + new_str_len + parens_start_pos, end_str, end_str_len + 1);
return true;
}
}
}
}
const int str_len = str.size();
const size_t parens_start = str.find('(');
if (parens_start == std::string::npos) {
return str;
}
return false;
const size_t parens_end = str.find(parens_start + 1, ')');
if (parens_end == std::string::npos) {
return str;
}
const int parens_len = parens_end - parens_start;
if (parens_len <= str_len_max) {
return str;
}
/* Truncate after the first comma. */
const size_t comma_first = str.find(parens_start, ',');
if (comma_first == std::string::npos) {
return str;
}
const char end_str[] = " ... )";
const int end_str_len = sizeof(end_str) - 1;
/* Leave a place for the first argument. */
const int new_str_len = (comma_first - parens_start) + 1;
if (str_len < new_str_len + parens_start + end_str_len + 1) {
return str;
}
return str.substr(0, comma_first) + end_str;
}
/* return nullptr if no match is found */
@@ -595,94 +596,87 @@ static const char *wm_context_member_from_ptr(const bContext *C,
}
#endif
char *WM_context_path_resolve_property_full(const bContext *C,
const PointerRNA *ptr,
PropertyRNA *prop,
int index)
std::string WM_context_path_resolve_property_full(const bContext *C,
const PointerRNA *ptr,
PropertyRNA *prop,
int index)
{
bool is_id;
const char *member_id = wm_context_member_from_ptr(C, ptr, &is_id);
char *member_id_data_path = nullptr;
if (member_id != nullptr) {
if (is_id && !RNA_struct_is_ID(ptr->type)) {
char *data_path = RNA_path_from_ID_to_struct(ptr);
if (data_path != nullptr) {
if (prop != nullptr) {
char *prop_str = RNA_path_property_py(ptr, prop, index);
if (prop_str[0] == '[') {
member_id_data_path = BLI_string_joinN(member_id, ".", data_path, prop_str);
}
else {
member_id_data_path = BLI_string_join_by_sep_charN(
'.', member_id, data_path, prop_str);
}
MEM_freeN(prop_str);
}
else {
member_id_data_path = BLI_string_join_by_sep_charN('.', member_id, data_path);
}
MEM_freeN(data_path);
}
}
else {
if (!member_id) {
return "";
}
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) {
if (prop != nullptr) {
char *prop_str = RNA_path_property_py(ptr, prop, index);
if (prop_str[0] == '[') {
member_id_data_path = BLI_string_joinN(member_id, prop_str);
member_id_data_path = fmt::format("{}.{}", data_path, prop_str);
}
else {
member_id_data_path = BLI_string_join_by_sep_charN('.', member_id, prop_str);
member_id_data_path = fmt::format("{}.{}.{}", member_id, data_path, prop_str);
}
MEM_freeN(prop_str);
}
else {
member_id_data_path = BLI_strdup(member_id);
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);
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;
}
}
return member_id_data_path;
}
char *WM_context_path_resolve_full(bContext *C, const PointerRNA *ptr)
std::string WM_context_path_resolve_full(bContext *C, const PointerRNA *ptr)
{
return WM_context_path_resolve_property_full(C, ptr, nullptr, -1);
}
static char *wm_prop_pystring_from_context(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
int index)
static std::string wm_prop_pystring_from_context(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
int index)
{
char *member_id_data_path = WM_context_path_resolve_property_full(C, ptr, prop, index);
char *ret = nullptr;
if (member_id_data_path != nullptr) {
ret = BLI_sprintfN("bpy.context.%s", member_id_data_path);
MEM_freeN(member_id_data_path);
std::string member_id_data_path = WM_context_path_resolve_property_full(C, ptr, prop, index);
if (member_id_data_path.empty()) {
return "";
}
return ret;
return "bpy.context." + member_id_data_path;
}
char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
std::string WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
{
char *lhs = C ? wm_prop_pystring_from_context(C, ptr, prop, index) : nullptr;
std::string lhs = C ? wm_prop_pystring_from_context(C, ptr, prop, index) : "";
if (lhs == nullptr) {
if (lhs.empty()) {
/* Fallback to `bpy.data.foo[id]` if we don't find in the context. */
lhs = RNA_path_full_property_py(ptr, prop, index);
}
if (!lhs) {
return nullptr;
}
char *rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX);
if (!rhs) {
MEM_freeN(lhs);
return nullptr;
}
char *ret = BLI_sprintfN("%s = %s", lhs, rhs);
MEM_freeN(lhs);
std::string ret = fmt::format("{} = {}", lhs, rhs);
MEM_freeN(rhs);
return ret;
}