[Bf-taskforce25] AutoLayout and RNA API
vekoon
vekoon at gmail.com
Thu Jan 29 20:00:58 CET 2009
Hi,
I've started implementing autolayout for collections and I stumbled upon
a couple of issues (note that I gave the name "AutoLayout" to the
automatic ui system so I can refer to it more easily). Note also that
this is just a demo implementation or proof of concept that is, to show
how groups could be used to automatize UI and the entire implementation
code for AutoLayout is probably below 500 lines of code and thus can be
easily tweaked or even entirely rewritten.
A first problem of the current system is that it is assumed that every
group is uniquely laid out, which means that you can't display the same
group more than once without having some weirdness. This makes sense
generally (why would you lay out Object -> Transform twice, for
instance?) but in more specific contexts it actually is a limitation and
these contexts are collection properties where the same type/struct can
be used more than once and thus its properties will be displayed more
than once (and so the groups for those properties).
This is actually a good thing as this will force me to clean up the code
and separate right from the beginning the caching part which keeps track
of groups/properties and the part that instead keeps track of local
space settings (like which groups are expanded or collapsed etc.) which
means it should be easier then to move the caching part to a more global
location (like WM) so that it can be reused across all the editors.
Now, an issue here is that when you keep these local space settings you
kind of need to release them at a certain point when the context changes
but this could be annoying for the user if done the wrong way. For
instance let's say you have Cube selected and you collapse its subsurf
modifier group settings, now you select Cube.001; in this case you can
easily check if Cube.001 has a subsurf modifier group as well and in
that case you keep it at a collapsed state. Now consider that you
collapse the group for the array modifier on Cube.001 then select back
Cube and Cube has 2 array modifiers, what to do? Collapse both of them?
Just the first one? Or none? And in the latter case what happens if you
select Cube.001 back? Of course you can't keep these settings
per-object, so you need to decide arbitrarily when to get rid of or keep
them. I know modifiers in this case have an RNA property, "expanded",
that is used to keep track of expansion state in the UI, but I think
this is a really dirty trick as it keeps RNA data UI-aware which should
be always avoided in my opinion, especially in this circumstance where
it is not needed thanks to groups. Also using properties for this type
of UI information would make it not possible to manage automatically
because you can't really base automation on properties name, can you?
Another issue is: when you iterate over properties for a certain struct
it always returns automatically the properties for the base struct it
inherits from. For instance again with the example for modifiers, when
you iterate over SubsurfModifier you get also "name", "type" ecc that
belong to "Modifier" which is good in most cases but sometimes you have
to distinguish between own and inherited properties. For instance when I
create the cache I was talking of before, I list all the properties in
their relative connection to groups. Now, in order for this list to be
consistent I need to list only those properties that strictly belong to
a certain struct (and thus to a certain root group), but as of now I
don't think there's a way for doing so. I think this should be added to
the API and this would solve a couple issues that as of now makes
AutoLayout work bad for collections.
Let me know what you think about this.
Also, something I'd like to clarify for my own good (and not just mine)
is if there are the bases for groups to likely be integrated into
current RNA system. Although the code for AutoLayout is definitively not
ready for inclusion or even review the API for RNA groups is pretty much
clean and I think ready for review and possible inclusion.
The reason I'm asking this is simply practical. If groups become
"official" people could start export them for all the properties. I
could also do this myself but the problem is that being it just my own
code every time I update if any minimal changes has been made to rna_*.c
files my code breaks and I have to solve all the conflicts which not
only is boring and time consuming but can also cause errors by
distraction if I mistakenly move one line above another and I cannot
avoid svn updates considering how much the code is changing at this
time. Also, if others can export groups not only it will be done faster
of course but also better if users with more 3D and application overall
usage experience than me would do it. Having more groups exported and
not having to solve conflicts every time I update would make my
implementation of AutoLayout faster in addition to providing more
meaningful test cases.
Exporting groups is very easy and if in doubt of what group type a
certain group could be, the group type can just be set to GROUP_NONE so
that a more experienced person can then grep for it in rna_*.c files and
choose the right type. So the question really comes down to determining
whether groups are really of some use and are worth the effort. I think
they are (of course), but I'm accepting negative opinions as well
(possibly motivated). I'll paste below an example of group definition
API so that you can have a more clear idea (I indented the part that is
group specific).
group= RNA_def_grouprna(brna, "Object");
RNA_def_grouprna_type(group, GROUP_ROOT);
RNA_def_grouprna_ui_text(group, "Object", "Object Properties");
group1= RNA_def_grouprna(brna, "ObjectLayers");
RNA_def_grouprna_parent(group1, group);
RNA_def_grouprna_type(group1, GROUP_FLAGS);
RNA_def_grouprna_ui_text(group1, "Layers", "DOC_BROKEN");
prop= RNA_def_property(srna, "layers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "lay", 1);
RNA_def_property_grouprna(prop, group1);
RNA_def_property_array(prop, 20);
RNA_def_property_ui_text(prop, "Layers", "Layers the object is on.");
RNA_def_property_boolean_funcs(prop, NULL, "rna_Object_layer_set");
group1= RNA_def_grouprna(brna, "ObjectTransform");
RNA_def_grouprna_parent(group1, group);
RNA_def_grouprna_ui_text(group1, "Transform", "DOC_BROKEN");
group2= RNA_def_grouprna(brna, "ObjectTransformNormal");
RNA_def_grouprna_parent(group2, group1);
RNA_def_grouprna_type(group2, GROUP_TRIPLET);
RNA_def_grouprna_ui_text(group2, "Normal", "DOC_BROKEN");
prop= RNA_def_property(srna, "location", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_float_sdna(prop, NULL, "loc");
RNA_def_property_grouprna(prop, group2);
RNA_def_property_ui_text(prop, "Location", "Location of the object.");
RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM,
"rna_Object_update");
prop= RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ROTATION);
RNA_def_property_float_sdna(prop, NULL, "rot");
RNA_def_property_grouprna(prop, group2);
RNA_def_property_ui_text(prop, "Rotation", "Rotation of the object.");
RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM,
"rna_Object_update");
prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_float_sdna(prop, NULL, "size");
RNA_def_property_grouprna(prop, group2);
RNA_def_property_ui_text(prop, "Scale", "Scaling of the object.");
RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM,
"rna_Object_update");
If you're wondering why I used grouprna in the names instead of simply
group this is because RNA_def_group is already being used currently by
object groups/instancing. So renamed one, I had to rename them all. Of
course this can be changed later by renaming the function for object groups.
Finally this is a small preview on the just started implementation of
collections plus some tweaking of other layout elements (I suggest you
also watch the video I linked in a previous e-mail to have a better
overall view): http://img145.imageshack.us/img145/1055/83042703wn7.jpg
More information about the Bf-taskforce25
mailing list