RNA: Add 'self as RNA' flag for RNA functions.

This allows such functions' callbacks to receive the 'self' data as a
PointerRNA, instead of a pointer of the relevant DNA type.

This commit also adds some validation of flags when defining them for
a FunctionRNA.

Part of !135807.
This commit is contained in:
Bastien Montagne
2025-06-23 16:06:42 +02:00
parent ef3e30c8fe
commit 13068b2e9c
3 changed files with 36 additions and 4 deletions

View File

@@ -791,9 +791,21 @@ enum FunctionFlag {
*/
FUNC_USE_SELF_ID = (1 << 11),
/**
* Pass 'self' data as a PointerRNA (by value), rather than as a pointer of the relevant DNA
* type.
*
* Mutually exclusive with #FUNC_NO_SELF and #FUNC_USE_SELF_TYPE.
*
* Useful for functions that need to access `self` as RNA data, not as DNA data (e.g. when doing
* 'generic', type-agnostic processing).
*/
FUNC_SELF_AS_RNA = (1 << 13),
/**
* Do not pass the object (DNA struct pointer) from which it is called,
* used to define static or class functions.
*
* Mutually exclusive with #FUNC_SELF_AS_RNA.
*/
FUNC_NO_SELF = (1 << 0),
/** Pass RNA type, used to define class functions, only valid when #FUNC_NO_SELF is set. */

View File

@@ -2916,7 +2916,10 @@ static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, Func
if ((func->flag & FUNC_NO_SELF) == 0) {
WRITE_COMMA;
if (dsrna->dnafromprop) {
if ((func->flag & FUNC_SELF_AS_RNA) != 0) {
fprintf(f, "this->ptr");
}
else if (dsrna->dnafromprop) {
fprintf(f, "(::%s *) this->ptr.data", dsrna->dnafromname);
}
else if (dsrna->dnaname) {
@@ -3170,7 +3173,10 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
}
if ((func->flag & FUNC_NO_SELF) == 0) {
if (dsrna->dnafromprop) {
if ((func->flag & FUNC_SELF_AS_RNA) != 0) {
fprintf(f, "\tstruct PointerRNA _self;\n");
}
else if (dsrna->dnafromprop) {
fprintf(f, "\tstruct %s *_self;\n", dsrna->dnafromname);
}
else if (dsrna->dnaname) {
@@ -3251,7 +3257,10 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
}
if ((func->flag & FUNC_NO_SELF) == 0) {
if (dsrna->dnafromprop) {
if ((func->flag & FUNC_SELF_AS_RNA) != 0) {
fprintf(f, "\t_self = *_ptr;\n");
}
else if (dsrna->dnafromprop) {
fprintf(f, "\t_self = (struct %s *)_ptr->data;\n", dsrna->dnafromname);
}
else if (dsrna->dnaname) {
@@ -3904,7 +3913,10 @@ static void rna_generate_static_parameter_prototypes(FILE *f,
if (!first) {
fprintf(f, ", ");
}
if (dsrna->dnafromprop) {
if ((func->flag & FUNC_SELF_AS_RNA) != 0) {
fprintf(f, "struct PointerRNA _self");
}
else if (dsrna->dnafromprop) {
fprintf(f, "struct %s *_self", dsrna->dnafromname);
}
else if (dsrna->dnaname) {

View File

@@ -4691,6 +4691,14 @@ void RNA_def_function_output(FunctionRNA * /*func*/, PropertyRNA *ret)
void RNA_def_function_flag(FunctionRNA *func, int flag)
{
func->flag |= flag;
if (func->flag & FUNC_USE_SELF_TYPE) {
BLI_assert_msg((func->flag & FUNC_NO_SELF) != 0, "FUNC_USE_SELF_TYPE requires FUNC_NO_SELF");
}
if (func->flag & FUNC_SELF_AS_RNA) {
BLI_assert_msg((func->flag & FUNC_NO_SELF) == 0,
"FUNC_SELF_AS_RNA and FUNC_NO_SELF are mutually exclusive");
}
}
void RNA_def_function_ui_description(FunctionRNA *func, const char *description)