UI: Allow passing named strings via context

Sometimes it is necessary to pass additional data through generic UI entities,
to specific implementations. For example to pass additional options to panel
polling & drawing when instantiating a panel through its panel type. Or storing
additional data in a button, without hardcoding it in the button struct/class.

Passing data via context is a simple solution to this, however so far this only
works using hardcoded context queries or RNA pointers. For passing arbitrary
strings we've used workarounds like creating an RNA type to wrap it already.
For example `RNA_AssetCatalogPath`, which is used to dynamically populate menu
items based on an asset catalog path, via a generic menu type.
type instantiation. This makes it possible to invoke specific asset shelves as
popover panels.

Idea is simply to let `bContextStore` entries hold copies of the string (as
`std::string`), avoiding lifetime issues. Context APIs are extended to support
setting/querying strings via a context member name.

Pull Request: https://projects.blender.org/blender/blender/pulls/122113
This commit is contained in:
Julian Eisel
2024-05-27 18:46:19 +02:00
committed by Julian Eisel
parent cdf960ecec
commit 2fbf206491
7 changed files with 111 additions and 21 deletions

View File

@@ -4438,6 +4438,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
blender::Vector<PointerRNA> newlb;
PropertyRNA *newprop;
int newindex;
blender::StringRef newstr;
short newtype;
/* An empty string is used to implement #CTX_data_dir_get,
@@ -4445,7 +4446,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
eContextResult done;
if (name[0]) {
done = eContextResult(
CTX_data_get(C, name, &newptr, &newlb, &newprop, &newindex, &newtype));
CTX_data_get(C, name, &newptr, &newlb, &newprop, &newindex, &newstr, &newtype));
}
else {
/* Fall through to built-in `getattr`. */
@@ -4463,6 +4464,16 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
ret = pyrna_struct_CreatePyObject(&newptr);
}
break;
case CTX_DATA_TYPE_STRING: {
if (newstr.is_empty()) {
ret = Py_None;
Py_INCREF(ret);
}
else {
ret = PyUnicode_FromStringAndSize(newstr.data(), newstr.size());
}
break;
}
case CTX_DATA_TYPE_COLLECTION: {
ret = PyList_New(0);
for (PointerRNA &ptr : newlb) {
@@ -4702,10 +4713,11 @@ static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject
blender::Vector<PointerRNA> newlb;
PropertyRNA *newprop;
int newindex;
blender::StringRef newstr;
short newtype;
const eContextResult done = eContextResult(
CTX_data_get(C, name, &newptr, &newlb, &newprop, &newindex, &newtype));
CTX_data_get(C, name, &newptr, &newlb, &newprop, &newindex, &newstr, &newtype));
if (done == CTX_RESULT_OK) {
PyErr_Format(