I start with adding a custom property editor panel to realize my plan stated in the previous post.
The patch file for a sample property editor can be found here.
- Task statements
- Overview of our approach
- Define a new panel
- Draw button on header
- Draw panels
- Some extra notes
There are several predefined property editors in Blender’s properties view, such as Render, Render Layers, Scene, World, Object, etc.
Sometimes I want to add new features for an element in Blender and provide user interfaces for user to edit its properties.
One approach is to write Python scripts to create custom property panels. But these custom panels are confined in predefined property editors.
For consistency and clarity, we want to group logically related panels in a separate property editor.
We call this new property editor “Simulation”. Here is a screenshot of it:
For simplicity I use
ICON_ANIM as its icon.
Overview of our approach
Firstly we will define a new property editor named Simulation in Blender system. Then we register it to UI system in order to make its button appear on the header of properties view. Finally we draw the body of Simulation panel when it is activated.
Define a new panel
A new item of
eSpaceButtons_Context1 should be defined:
Also some meta information(description text, icon, etc) should be provided in
Draw button on header
The source code for properties view are located in the folder
After a brief search inside this folder
we can locate the area(or region) definition function
in the file
For buttons rendering we focus on the header area.
We can see the actual header rendering is registered as function
ED_region_header function performs the UI rendering.
But what does function
Let me distill the essential parts of function
SpaceButs structure records the state of each property editors.
pathcontains the current available components(such as mesh data, particle systems, etc) of an object. It gets its name since a serial hierarchy from the root scene to the corresponding component will be rendered later. It looks like .
mainbis the index of current property editor(or context in the source code). It has the same integer value of corresponding item in
mainbuseris the index of desired property editor from user.
pathflagis a bit fields indicating which property editor is available for current object.
Now we can understand what
it loops through all property editors and records available ones to the
We simply turn on the corresponding bit in
pathflag to mark our new property editor available for header rendering:
However you still cannot see our new button now.
This problem took me some time in my first try since the panel rendering process is rather complicated: it gets issued in C++ side, then goes into Python script, and finally calls back to C++ side for OpenGL rendering. It is really hard to trace the execution due to the discontinuous call stack.
But remember that the
pathflag indicates which editor is available?
I conjecture that any rendering code may refer to the variable
pathflag for available editors.
Through a search of
pathflag I finally find the solution.
An enum item should be added for each available editor.
So I should add this in function
Let us have a look at its stack trace. It is hard to trace through that Python part:
blender-app.exe!rna_SpaceProperties_context_itemf blender-app.exe!RNA_property_enum_items blender-app.exe!RNA_property_enum_items_gettexted blender-app.exe!ui_item_enum_expand blender-app.exe!uiItemFullR blender-app.exe!rna_uiItemR blender-app.exe!UILayout_prop_call blender-app.exe!RNA_function_call blender-app.exe!pyrna_func_call python34_d.dll!56c7de81 [Frames below may be incorrect and/or missing, no symbols loaded for python34_d.dll] python34_d.dll!56d99f5c python34_d.dll!56d999ed python34_d.dll!56d9742d python34_d.dll!56d92f31 python34_d.dll!56cc1dc5 python34_d.dll!56c7de81 blender-app.exe!bpy_class_call blender-app.exe!header_draw blender-app.exe!ED_region_header blender-app.exe!buttons_header_area_draw blender-app.exe!ED_region_do_draw blender-app.exe!wm_method_draw_triple blender-app.exe!wm_draw_update blender-app.exe!ghost_event_proc blender-app.exe!GHOST_CallbackEventConsumer::processEvent blender-app.exe!GHOST_EventManager::dispatchEvent blender-app.exe!GHOST_EventManager::dispatchEvent blender-app.exe!GHOST_EventManager::dispatchEvents blender-app.exe!GHOST_System::dispatchEvents blender-app.exe!GHOST_DispatchEvents blender-app.exe!wm_window_process_events blender-app.exe!WM_main blender-app.exe!main
Now the new property editor button appears on the header of property view. We move on to render panels inside it.
The panel user interface is defined in Python.
You can refer to scripts in
release/scripts/startup/bl_ui for examples.
Mine is here:
Note that I use
This tells Blender we want to put this panel under the Simulation context.
The C++ side of Blender also have to use this string to dispatch UI rendering to Python.
Therefore we add following code in the function
Some extra notes
In this post we just turn on a bit of
pathflag to force our custom panel appear in the user interface.
In a real life situation a data block should be defined and a valid path to that block reveals the corresponding bit of
I leave this for future works.