[Bf-taskforce25] RNA and API wrap-up

Elia Sarti vekoon at gmail.com
Mon Jun 29 15:33:13 CEST 2009


Hey Brecht,

Brecht Van Lommel wrote, on 06/29/2009 03:02 PM:
> Hi Elia,
>
> On Mon, 2009-06-29 at 14:06 +0200, Elia Sarti wrote:
>   
>> Operators are more or less defined/complete at least C side. API side 
>> though we still have things undefined or problematic. For instance an 
>> issue is unique naming. Although the current naming convention fits 
>> perfectly and it's cohesive on our core application side it presents 
>> some limitations for extensibility as we cannot really control how many 
>> pyoperators will be written and handle collisions between these. A way 
>> could be simply to always prepend pyops with PY_ (or tell py devs to use 
>> this convention). We could tell devs to prepend their pyoperators with 
>> their own names/ids of choice. Or we could use python own module/package 
>> system to combine the final operator name. As of now I don't seem to see 
>> any check on operator names? We could allow a 
>> module.OBJECT_OT_do_something() type of name syntax which could be 
>> translated automatically from py? Not sure if this conflicts with something.
>>     
>
> I think a convention for prefixes would be best here, don't think a
> more advanced solution is needed.
>   
Well the idea of more complicate names would be just python/plugin 
related, that would not change for core operators of course. The idea is 
just to *allow* dot-prefixed names.
Imagine this situation where I've found 2 scripts, both of them do the 
same tool, let's say "vortex tool", they're likely to be named the same 
e.g. MESH_OT_vortex but one works better in some situations and the 
second in others. What happens if I load them both?
We could make that the dot-prefix is optional for lookups unless there's 
another operator with the same non-dot-prefixed name so you can use both 
but still defaults to one. For instance I have abc.MESH_OT_vortex and 
xyz.MESH_OT_vortex if I search for MESH_OT_vortex I get the first but I 
can search for xyz.MESH_OT_vortex to have the specific one I want (also 
for macros). This would actually be useful also to filter tools while 
searching if someone releases like a "tool pack" by typing in only the 
prefix (the name of the company/product/release).

>> Another issue for operators in general is context constraints. For 
>> instance as of now as Ton mentioned in IRC add_object operator works in 
>> node editor. Is this fine? Can it be expected by the user? From my point 
>> of view being able to run operators from contexts you wouldn't expect is 
>> totally acceptable architecture-wise as running constraints are defined 
>> in terms of "needs" and if requirements are respected I see no reason 
>> why the operator should not run. They should just be hidden from the 
>> user in order not to create confusion. I think we could do this with 
>> some type of "flag" both on operators and space types defining the 
>> constraints of context. Something like CTX_HANDLE_OBJECT, 
>> CTX_HANDLE_NODE etc. On the operator this is the same as represented by 
>> the prefix of its idname so we could actually use this on spaces 
>> although string comparison would introduce some issues but would be more 
>> solid e.g. for py/plugin spaces which brings me back to pyops naming as 
>> using this method would leave module/package approach as the only usable 
>> naming convention.
>> You might wonder why not to put the space check directly on the 
>> operator's poll? Well the reason for this is that as I said poll() 
>> should just check requirements and not interface issues which is instead 
>> something spaces take care of. This is not just a design choice but also 
>> has some practical examples. For instance, the same example I made on 
>> IRC, suppose at some point Outliner space gets capacity of 
>> listing/handling nodes. To support node tools in outliner you would have 
>> to go and change every single node operator to add additional check on 
>> space type while with the former approach you just update outliner space 
>> to accept NODE_* operators. This of course is even more clear for 
>> python/plugin spaces.
>>     
>
> I think this is what keymaps are already for. If it is useful to share
> some set of operators between spaces, they can be added in a keymap and
> both spaces can add that keymap in.
>
>   
Yes I was referring more to the "search" features for tools and I'm not 
sure it'd be a good idea to filter out all tools that are not key-mapped.
>> Type registration
>>
>> This is less important and more of a personal question than general issue.
>> Types can get registered for adding customization like it happens for 
>> Panels or Menus. If I'm not mistaken this is how current architecture works:
>>
>> script.py -> class SomePanel(Panel): [...] bpy.types.register(SomePanel) ->
>>
>>     RNA: Panel.register() -> register the type in some custom way -> 
>> (ARegionType.paneltypes)
>>         
>>         ARegionType.draw() ->
>>         
>>             ED_region_panels("context") ->
>>             
>>                 foreach (panel in paneltypes) if (panel.context == 
>> "context") draw(panel)
>>                 
>>
>> How it should work in my opinion:
>>
>> script.py -> class SomePanel(Panel): [...] bpy.types.register(SomePanel) ->
>>
>>     [RNA: insert SomePanel in optimized lookup list]
>>         
>>         ARegionType.init() ->
>>             
>>             retrieve all Panel-inherited RNA types and register -> 
>> (ARegionType.autopaneltypes)
>>         
>>         ARegionType.draw() ->
>>         
>>             ED_region_panels("context") ->
>>             
>>                 foreach (panel in paneltypes) draw(panel)
>>                 foreach (panel in autopaneltypes) if (panel.context == 
>> "context") draw(panel)
>>     
>
> The reason I do it in the first way is because then there is no
> distinction between paneltypes and autopaneltypes, for the panel drawing
> code it's all the same. For panels this is not a big problem because
> they are only looped over in one place, but I think it is important that
> from the C code using them, they look 100% identical.
>
>   
>> Advantages of this kind of architecture are that it keeps RNA more 
>> consistent and self-contained, no messing around (i.e. no real logics) 
>> with interface. By consequence it also keeps interface stuff more 
>> self-contained by letting it handle its own supported custom types.
>>     
>
> I don't understand this argument, if the interface code needs to be kept
> together more, it's just a matter of making the register function in RNA
> call some function in the interface code.
>
>   
>> The apparent disadvantage is low performance, having to do lookups at 
>> every init. I understand this could be why the first method was adopted 
>> but to me this doesn't seem a valid reason. To solve this problem 
>> instead we could create a coexistent fast-to-access list of registered 
>> types. This could be ordered like some type of tree to optimize access 
>> based on type hierarchy lookup. I know caches are bad but still I think 
>> they're better than code fragmentation. Once we have this type of cache 
>> we could further optimize for instance like (in pseudo-code):
>>
>> if type_tree.is_hierarchy_changed_for(Panel):
>>     re-init ARegionType.autopaneltypes
>>
>> This could simply be a flag on the cache-stored type updated by the 
>> cache itself. This way we would re-do the lookup only when some new 
>> specific type gets registered/unregistered.
>>     
>
> I didn't choose this method for performance, it just seemed to be the
> simplest way to do it.
>
> I don't understand how introducing autopaneltypes helps, it only makes
> it more complicated in my opinion. The register function needs to check
> validness, override existing panels with the same idname, etc. That way
> it can throw an error to python immediately. Splitting up validation and
> actual registration means you split up the code in two parts.
>
> But there is another problem, when you want to register a spacetype,
> with regions in that spacetype, and panels in those regions. Then you
> can't delay re-init for spacetypes and regions immediately anyway.
>
> Generally I think it's more predictable and easier to debug doing
> things immediately instead of delayed.
>
>   
Yes I think you're right about this. Also this part is not as important 
because we can change it as we like in that it doesn't influence things 
API side.

>> I think I mentioned the main issues that must be either solved, decided 
>> upon or simply settled, if you think I forgot something feel free to add it.
>> I'm also thinking about writing some more detailed docs on RNA and its 
>> internals in order not to turn it into a black box that only a few 
>> understand. This of course with the assistance of Brecht.
>>     
>
> Yes, we definitely need more docs.
>
> Brecht.
>   
I started writing down all the internal mechanisms that are more 
important to be made clear, especially I think the makesrna part is what 
people could find more obscure because of its auto-generating behavior.

> _______________________________________________
> Bf-taskforce25 mailing list
> Bf-taskforce25 at blender.org
> http://lists.blender.org/mailman/listinfo/bf-taskforce25
>
>   


More information about the Bf-taskforce25 mailing list