From BlenderWiki

Jump to: navigation, search

Adding a new Context entry

This checklist documents how to add a new entry in the global "Context" object (i.e. via bContext *C in C, and bpy.context in Python). Examples of these properties include bpy.context.active_object, bpy.context.active_gpencil_layer, bpy.context.tool_settings, bpy.context.area and more.


Checklist - Single Item

This assumes that we are adding a property my_prop of type PropType (commonly referred to as pro in the code). See the next section/checklist for what to do if you want to add a set of thing instead.

Furthermore, we assume that this property refers to some "data" (e.g. a datablock, or an entity like a bone/keyingset/driver/node/etc., or similiar) as opposed to something window-management ("wm") related such as active area/region/etc.

When properly defined, you should be able to do:

   #include "BKE_context.h"
   ...
   void some_func(bContext *C, ...)
   {
       PropType *pro = CTX_data_my_prop(C);
       ... do something with "prop" ...
   }


blenkernel

  • BKE_context.h - Add one of the following lines somewhere near another conceptually similar one:

   PropType *CTX_data_my_prop(const bContext *C);

  • context.c - Add a function corresponding to the one below (and in a similar location in the file, grouping-wise):

   PropType *CTX_data_my_prop(const bContext *C)
   {
       return ctx_data_pointer_get(C, "my_prop");
   }

editors/screen/screen_context.c

  • screen_context_dir[] - Add a string entry for your property
  • ed_screen_context() - Add an else if block for setting your prop in Context. For example:

   else if (CTX_data_equals(member, "my_prop")) {
       PropType *pro = ...
       ... Do some magic to get the property, and to test that should be made available at this time (as appropriate) ...
       
       CTX_data_id_pointer_set(result, pro);
       return 1;
   }

doc/python_api/sphinx_doc_gen.py

  • context_type_map - Add an entry for my_prop, following the examples for other properties. These are arranged in alphabetical order.


---


Checklist - Collection/Set

We still need to add code to the same places as before. This assuming that the context entry is now called my_things.

This collection can then be used via:

   CTX_DATA_BEGIN(C, PropType *, pro, my_things)
   {
       ... do something with pro ...
   }
   CTX_DATA_END;


blenkernel

  • BKE_context.h - Add the following line instead:

   int CTX_data_my_things(const bContext *C, ListBase *list);

  • context.c - Add the following code instead:

   int CTX_data_my_things(const bContext *C, ListBase *list)
   {
       return ctx_data_collection_get(C, "my_things", list);
   }

editors/screen/screen_context.c

  • screen_context_dir[] - (Same as before) Add a string entry for your collection
  • ed_screen_context() - Add an else if block for setting your prop in Context. For example:

   else if (CTX_data_equals(member, "my_prop")) {
       for (...) {
           PropType *pro = ...
           
           if (...)
               CTX_data_id_list_add(result, pro);
       }
       
       CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
       return 1;
   }

doc/python_api/sphinx_doc_gen.py

  • context_type_map - Add an entry for my_prop, following the examples for other properties. These are arranged in alphabetical order.


---

Precautions

  • When doing the ed_screen_context() logic, it is not advised to try and use CTX_* stuff to get hold of pointers to data you need. Instead use the local vars declared at the start of that function instead.
    • For more details, see the comments in the gpencil_data case
  • Try to keep any logic needed here simple - especially if the property is likely to be looked up in Operator.poll() callbacks. If necessary, consider revising or improving your data structures to make these lookups simpler.