Merged changes in the trunk up to revision 34996.
Conflicts resolved: C:\bf-blender\soc-2008-mxcurioni\doc\python_api\sphinx_doc_gen.py C:\bf-blender\soc-2008-mxcurioni\source\blender\makesrna\RNA_types.h C:\bf-blender\soc-2008-mxcurioni\source\blender\render\SConscript
This commit is contained in:
@@ -25,5 +25,3 @@ for image in bpy.data.images:
|
||||
file.write("%s %dx%d\n" % (image.filepath, image.size[0], image.size[1]))
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
Execution Context
|
||||
+++++++++++++++++
|
||||
|
||||
When calling an operator you may want to pass the execution context.
|
||||
|
||||
This determines the context thats given to the operator to run in, and weather
|
||||
invoke() is called or execute().
|
||||
|
||||
'EXEC_DEFAULT' is used by default but you may want the operator to take user
|
||||
interaction with 'INVOKE_DEFAULT'.
|
||||
|
||||
The execution context is as a non keyword, string argument in:
|
||||
('INVOKE_DEFAULT', 'INVOKE_REGION_WIN', 'INVOKE_REGION_CHANNELS',
|
||||
'INVOKE_REGION_PREVIEW', 'INVOKE_AREA', 'INVOKE_SCREEN', 'EXEC_DEFAULT',
|
||||
'EXEC_REGION_WIN', 'EXEC_REGION_CHANNELS', 'EXEC_REGION_PREVIEW', 'EXEC_AREA',
|
||||
'EXEC_SCREEN')
|
||||
"""
|
||||
|
||||
# group add popup
|
||||
import bpy
|
||||
bpy.ops.object.group_instance_add('INVOKE_DEFAULT')
|
||||
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
Calling Operators
|
||||
+++++++++++++++++
|
||||
|
||||
Provides python access to calling operators, this includes operators written in
|
||||
C, Python or Macros.
|
||||
|
||||
Only keyword arguments can be used to pass operator properties.
|
||||
|
||||
Operators don't have return values as you might expect, instead they return a
|
||||
set() which is made up of: {'RUNNING_MODAL', 'CANCELLED', 'FINISHED',
|
||||
'PASS_THROUGH'}.
|
||||
Common return values are {'FINISHED'} and {'CANCELLED'}.
|
||||
|
||||
|
||||
Calling an operator in the wrong context will raise a RuntimeError,
|
||||
there is a poll() method to avoid this problem.
|
||||
|
||||
Note that the operator ID (bl_idname) in this example is 'mesh.subdivide',
|
||||
'bpy.ops' is just the access path for python.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
# calling an operator
|
||||
bpy.ops.mesh.subdivide(number_cuts=3, smoothness=0.5)
|
||||
|
||||
|
||||
# check poll() to avoid exception.
|
||||
if bpy.ops.object.mode_set.poll():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
@@ -0,0 +1,31 @@
|
||||
"""
|
||||
Operator Example
|
||||
++++++++++++++++
|
||||
|
||||
A common use of custom properties is for python based :class:`Operator` classes.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class DialogOperator(bpy.types.Operator):
|
||||
bl_idname = "object.dialog_operator"
|
||||
bl_label = "Property Example"
|
||||
|
||||
my_float = bpy.props.FloatProperty(name="Some Floating Point")
|
||||
my_bool = bpy.props.BoolProperty(name="Toggle Option")
|
||||
my_string = bpy.props.StringProperty(name="String Value")
|
||||
|
||||
def execute(self, context):
|
||||
print("Dialog Runs")
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.window_manager
|
||||
return wm.invoke_props_dialog(self)
|
||||
|
||||
|
||||
bpy.utils.register_class(DialogOperator)
|
||||
|
||||
# test call
|
||||
bpy.ops.object.dialog_operator('INVOKE_DEFAULT')
|
||||
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
PropertyGroup Example
|
||||
+++++++++++++++++++++
|
||||
|
||||
PropertyGroups can be used for collecting custom settings into one value
|
||||
to avoid many indervidual settings mixed in together.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class MaterialSettings(bpy.types.PropertyGroup):
|
||||
my_int = bpy.props.IntProperty()
|
||||
my_float = bpy.props.FloatProperty()
|
||||
my_string = bpy.props.StringProperty()
|
||||
|
||||
bpy.utils.register_class(MaterialSettings)
|
||||
|
||||
bpy.types.Material.my_settings = \
|
||||
bpy.props.PointerProperty(type=MaterialSettings)
|
||||
|
||||
# test the new settings work
|
||||
material = bpy.data.materials[0]
|
||||
|
||||
material.my_settings.val_int = 5
|
||||
material.my_settings.val_float = 3.0
|
||||
material.my_settings.my_string = "Foo"
|
||||
@@ -0,0 +1,33 @@
|
||||
"""
|
||||
Collection Example
|
||||
++++++++++++++++++
|
||||
|
||||
Custom properties can be added to any subclass of an :class:`ID`,
|
||||
:class:`Bone` and :class:`PoseBone`.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
|
||||
# Assign a collection
|
||||
class SceneSettingItem(bpy.types.PropertyGroup):
|
||||
name = bpy.props.StringProperty(name="Test Prop", default="Unknown")
|
||||
value = bpy.props.IntProperty(name="Test Prop", default=22)
|
||||
|
||||
bpy.utils.register_class(SceneSettingItem)
|
||||
|
||||
bpy.types.Scene.my_settings = \
|
||||
bpy.props.CollectionProperty(type=SceneSettingItem)
|
||||
|
||||
# Assume an armature object selected
|
||||
print("Adding 3 values!")
|
||||
|
||||
my_item = bpy.context.scene.my_settings.add()
|
||||
my_item.name = "Spam"
|
||||
my_item.value = 1000
|
||||
|
||||
my_item = bpy.context.scene.my_settings.add()
|
||||
my_item.name = "Eggs"
|
||||
my_item.value = 30
|
||||
|
||||
for my_item in bpy.context.scene.my_settings:
|
||||
print(my_item.name, my_item.value)
|
||||
@@ -0,0 +1,18 @@
|
||||
"""
|
||||
Assigning to Existing Classes
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
Custom properties can be added to any subclass of an :class:`ID`,
|
||||
:class:`Bone` and :class:`PoseBone`.
|
||||
|
||||
These properties can be animated, accessed by the user interface and python
|
||||
like blenders existing properties.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
|
||||
# Assign a custom property to an existing type.
|
||||
bpy.types.Material.custom_float = bpy.props.FloatProperty(name="Test Prob")
|
||||
|
||||
# Test the property is there.
|
||||
bpy.data.materials[0].custom_float = 5.0
|
||||
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
Submenus
|
||||
++++++++
|
||||
This menu demonstrates some different functions.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class SubMenu(bpy.types.Menu):
|
||||
bl_idname = "OBJECT_MT_select_submenu"
|
||||
bl_label = "Select"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("object.select_all", text="Select/Deselect All")
|
||||
layout.operator("object.select_inverse", text="Inverse")
|
||||
layout.operator("object.select_random", text="Random")
|
||||
|
||||
# access this operator as a submenu
|
||||
layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
|
||||
|
||||
layout.separator()
|
||||
|
||||
# expand each operator option into this menu
|
||||
layout.operator_enum("object.lamp_add", "type")
|
||||
|
||||
layout.separator()
|
||||
|
||||
# use existing memu
|
||||
layout.menu("VIEW3D_MT_transform")
|
||||
|
||||
|
||||
bpy.utils.register_class(SubMenu)
|
||||
|
||||
# test call to display immediately.
|
||||
bpy.ops.wm.call_menu(name="OBJECT_MT_select_submenu")
|
||||
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
Extending Menus
|
||||
+++++++++++++++
|
||||
When creating menus for addons you can't reference menus in blenders default
|
||||
scripts.
|
||||
|
||||
Instead the addon can add menu items to existing menus.
|
||||
|
||||
The function menu_draw acts like Menu.draw
|
||||
"""
|
||||
import bpy
|
||||
|
||||
def menu_draw(self, context):
|
||||
self.layout.operator("wm.save_homefile")
|
||||
|
||||
bpy.types.INFO_MT_file.append(menu_draw)
|
||||
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
Basic Menu Example
|
||||
++++++++++++++++++
|
||||
This script is a simple menu, menus differ from panels in that they must
|
||||
reference from a header, panel or another menu.
|
||||
|
||||
Notice the 'CATEGORY_MT_name' :class:`Menu.bl_idname`, this is a naming
|
||||
convention for menus.
|
||||
|
||||
.. note::
|
||||
|
||||
Menu subclasses must be registered before referencing them from blender.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class BasicMenu(bpy.types.Menu):
|
||||
bl_idname = "OBJECT_MT_select_test"
|
||||
bl_label = "Select"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("object.select_all", text="Select/Deselect All")
|
||||
layout.operator("object.select_inverse", text="Inverse")
|
||||
layout.operator("object.select_random", text="Random")
|
||||
|
||||
|
||||
bpy.utils.register_class(BasicMenu)
|
||||
|
||||
# test call to display immediately.
|
||||
bpy.ops.wm.call_menu(name="OBJECT_MT_select_test")
|
||||
@@ -0,0 +1,52 @@
|
||||
"""
|
||||
Invoke Function
|
||||
+++++++++++++++
|
||||
:class:`Operator.invoke` is used to initialize the operator from the context
|
||||
at the moment the operator is called.
|
||||
invoke() is typically used to assign properties which are then used by
|
||||
execute().
|
||||
Some operators don't have an execute() function, removing the ability to be
|
||||
repeated from a script or macro.
|
||||
|
||||
This example shows how to define an operator which gets mouse input to
|
||||
execute a function and that this operator can be invoked or executed from
|
||||
the python api.
|
||||
|
||||
Also notice this operator defines its own properties, these are different
|
||||
to typical class properties because blender registers them with the
|
||||
operator, to use as arguments when called, saved for operator undo/redo and
|
||||
automatically added into the user interface.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class SimpleMouseOperator(bpy.types.Operator):
|
||||
""" This operator shows the mouse location,
|
||||
this string is used for the tooltip and API docs
|
||||
"""
|
||||
bl_idname = "wm.mouse_position"
|
||||
bl_label = "Invoke Mouse Operator"
|
||||
|
||||
x = bpy.props.IntProperty()
|
||||
y = bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
# rather then printing, use the report function,
|
||||
# this way the messag appiers in the header,
|
||||
self.report({'INFO'}, "Mouse coords are %d %d" % (self.x, self.y))
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.x = event.mouse_x
|
||||
self.y = event.mouse_y
|
||||
return self.execute(context)
|
||||
|
||||
bpy.utils.register_class(SimpleMouseOperator)
|
||||
|
||||
# Test call to the newly defined operator.
|
||||
# Here we call the operator and invoke it, meaning that the settings are taken
|
||||
# from the mouse.
|
||||
bpy.ops.wm.mouse_position('INVOKE_DEFAULT')
|
||||
|
||||
# Another test call, this time call execute() directly with pre-defined settings.
|
||||
bpy.ops.wm.mouse_position('EXEC_DEFAULT', x=20, y=66)
|
||||
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
Calling a File Selector
|
||||
+++++++++++++++++++++++
|
||||
This example shows how an operator can use the file selector.
|
||||
|
||||
Notice the invoke function calls a window manager method and returns
|
||||
RUNNING_MODAL, this means the file selector stays open and the operator does not
|
||||
exit immediately after invoke finishes.
|
||||
|
||||
The file selector runs the operator, calling :class:`Operator.execute` when the
|
||||
user confirms.
|
||||
|
||||
The :class:`Operator.poll` function is optional, used to check if the operator
|
||||
can run.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class ExportSomeData(bpy.types.Operator):
|
||||
"""Test exporter which just writes hello world"""
|
||||
bl_idname = "export.some_data"
|
||||
bl_label = "Export Some Data"
|
||||
|
||||
filepath = bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object is not None
|
||||
|
||||
def execute(self, context):
|
||||
file = open(self.filepath, 'w')
|
||||
file.write("Hello World " + context.object.name)
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
||||
# Only needed if you want to add into a dynamic menu
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")
|
||||
|
||||
# Register and add to the file selector
|
||||
bpy.utils.register_class(ExportSomeData)
|
||||
bpy.types.INFO_MT_file_export.append(menu_func)
|
||||
|
||||
|
||||
# test call
|
||||
bpy.ops.export.some_data('INVOKE_DEFAULT')
|
||||
@@ -0,0 +1,31 @@
|
||||
"""
|
||||
Dialog Box
|
||||
++++++++++
|
||||
This operator uses its :class:`Operator.invoke` function to call a popup.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class DialogOperator(bpy.types.Operator):
|
||||
bl_idname = "object.dialog_operator"
|
||||
bl_label = "Simple Dialog Operator"
|
||||
|
||||
my_float = bpy.props.FloatProperty(name="Some Floating Point")
|
||||
my_bool = bpy.props.BoolProperty(name="Toggle Option")
|
||||
my_string = bpy.props.StringProperty(name="String Value")
|
||||
|
||||
def execute(self, context):
|
||||
message = "Popup Values: %f, %d, '%s'" % \
|
||||
(self.my_float, self.my_bool, self.my_string)
|
||||
self.report({'INFO'}, message)
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.window_manager
|
||||
return wm.invoke_props_dialog(self)
|
||||
|
||||
|
||||
bpy.utils.register_class(DialogOperator)
|
||||
|
||||
# test call
|
||||
bpy.ops.object.dialog_operator('INVOKE_DEFAULT')
|
||||
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
Custom Drawing
|
||||
++++++++++++++
|
||||
By default operator properties use an automatic user interface layout.
|
||||
If you need more control you can create your own layout with a
|
||||
:class:`Operator.draw` function.
|
||||
|
||||
This works like the :class:`Panel` and :class:`Menu` draw functions, its used
|
||||
for dialogs and file selectors.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class CustomDrawOperator(bpy.types.Operator):
|
||||
bl_idname = "object.custom_draw"
|
||||
bl_label = "Simple Modal Operator"
|
||||
|
||||
filepath = bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
my_float = bpy.props.FloatProperty(name="Float")
|
||||
my_bool = bpy.props.BoolProperty(name="Toggle Option")
|
||||
my_string = bpy.props.StringProperty(name="String Value")
|
||||
|
||||
def execute(self, context):
|
||||
print()
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
col = layout.column()
|
||||
col.label(text="Custom Interface!")
|
||||
|
||||
row = col.row()
|
||||
row.prop(self, "my_float")
|
||||
row.prop(self, "my_bool")
|
||||
|
||||
col.prop(self, "my_string")
|
||||
|
||||
bpy.utils.register_class(CustomDrawOperator)
|
||||
|
||||
# test call
|
||||
bpy.ops.object.custom_draw('INVOKE_DEFAULT')
|
||||
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
Modal Execution
|
||||
+++++++++++++++
|
||||
This operator defines a :class:`Operator.modal` function which running,
|
||||
handling events until it returns {'FINISHED'} or {'CANCELLED'}.
|
||||
|
||||
Grab, Rotate, Scale and Fly-Mode are examples of modal operators.
|
||||
They are especially useful for interactive tools,
|
||||
your operator can have its own state where keys toggle options as the operator
|
||||
runs.
|
||||
|
||||
:class:`Operator.invoke` is used to initialize the operator as being by
|
||||
returning {'RUNNING_MODAL'}, initializing the modal loop.
|
||||
|
||||
Notice __init__() and __del__() are declared.
|
||||
For other operator types they are not useful but for modal operators they will
|
||||
be called before the :class:`Operator.invoke` and after the operator finishes.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class ModalOperator(bpy.types.Operator):
|
||||
bl_idname = "object.modal_operator"
|
||||
bl_label = "Simple Modal Operator"
|
||||
|
||||
def __init__(self):
|
||||
print("Start")
|
||||
|
||||
def __del__(self):
|
||||
print("End")
|
||||
|
||||
def execute(self, context):
|
||||
context.object.location.x = self.value / 100.0
|
||||
|
||||
def modal(self, context, event):
|
||||
if event.type == 'MOUSEMOVE': # Apply
|
||||
self.value = event.mouse_x
|
||||
self.execute(context)
|
||||
elif event.type == 'LEFTMOUSE': # Confirm
|
||||
return {'FINISHED'}
|
||||
elif event.type in ('RIGHTMOUSE', 'ESC'): # Cancel
|
||||
return {'CANCELLED'}
|
||||
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.value = event.mouse_x
|
||||
self.execute(context)
|
||||
|
||||
print(context.window_manager.modal_handler_add(self))
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
||||
|
||||
bpy.utils.register_class(ModalOperator)
|
||||
|
||||
# test call
|
||||
bpy.ops.object.modal_operator('INVOKE_DEFAULT')
|
||||
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
Basic Operator Example
|
||||
++++++++++++++++++++++
|
||||
This script shows simple operator which prints a message.
|
||||
|
||||
Since the operator only has an :class:`Operator.execute` function it takes no
|
||||
user input.
|
||||
|
||||
.. note::
|
||||
|
||||
Operator subclasses must be registered before accessing them from blender.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class HelloWorldOperator(bpy.types.Operator):
|
||||
bl_idname = "wm.hello_world"
|
||||
bl_label = "Minimal Operator"
|
||||
|
||||
def execute(self, context):
|
||||
print("Hello World")
|
||||
return {'FINISHED'}
|
||||
|
||||
bpy.utils.register_class(SimpleOperator)
|
||||
|
||||
# test call to the newly defined operator
|
||||
bpy.ops.wm.hello_world()
|
||||
@@ -0,0 +1,44 @@
|
||||
"""
|
||||
Simple Object Panel
|
||||
+++++++++++++++++++
|
||||
This panel has a :class:`Panel.poll` and :class:`Panel.draw_header` function,
|
||||
even though the contents is basic this closely resemples blenders panels.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class ObjectSelectPanel(bpy.types.Panel):
|
||||
bl_idname = "OBJECT_PT_select"
|
||||
bl_label = "Select"
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "object"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.object is not None)
|
||||
|
||||
def draw_header(self, context):
|
||||
layout = self.layout
|
||||
obj = context.object
|
||||
layout.prop(obj, "select", text="")
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
obj = context.object
|
||||
row = layout.row()
|
||||
row.prop(obj, "hide_select")
|
||||
row.prop(obj, "hide_render")
|
||||
|
||||
box = layout.box()
|
||||
box.label("Selection Tools")
|
||||
box.operator("object.select_all")
|
||||
row = box.row()
|
||||
row.operator("object.select_inverse")
|
||||
row.operator("object.select_random")
|
||||
|
||||
|
||||
bpy.utils.register_class(ObjectSelectPanel)
|
||||
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
Mix-in Classes
|
||||
++++++++++++++
|
||||
A mix-in parent class can be used to share common properties and
|
||||
:class:`Menu.poll` function.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
class View3DPanel():
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'TOOLS'
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.object is not None)
|
||||
|
||||
|
||||
class PanelOne(View3DPanel, bpy.types.Panel):
|
||||
bl_idname = "VIEW3D_PT_test_1"
|
||||
bl_label = "Panel One"
|
||||
|
||||
def draw(self, context):
|
||||
self.layout.label("Small Class")
|
||||
|
||||
|
||||
class PanelTwo(View3DPanel, bpy.types.Panel):
|
||||
bl_idname = "VIEW3D_PT_test_2"
|
||||
bl_label = "Panel Two"
|
||||
|
||||
def draw(self, context):
|
||||
self.layout.label("Also Small Class")
|
||||
|
||||
|
||||
bpy.utils.register_class(PanelOne)
|
||||
bpy.utils.register_class(PanelTwo)
|
||||
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
Basic Panel Example
|
||||
+++++++++++++++++++
|
||||
This script is a simple panel which will draw into the object properties
|
||||
section.
|
||||
|
||||
Notice the 'CATEGORY_PT_name' :class:`Panel.bl_idname`, this is a naming
|
||||
convention for panels.
|
||||
|
||||
.. note::
|
||||
|
||||
Panel subclasses must be registered for blender to use them.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class HelloWorldPanel(bpy.types.Panel):
|
||||
bl_idname = "OBJECT_PT_hello_world"
|
||||
bl_label = "Hello World"
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_context = "object"
|
||||
|
||||
def draw(self, context):
|
||||
self.layout.label(text="Hello World")
|
||||
|
||||
|
||||
bpy.utils.register_class(HelloWorldPanel)
|
||||
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
Custom Properties
|
||||
+++++++++++++++++
|
||||
|
||||
PropertyGroups are the base class for dynamically defined sets of properties.
|
||||
|
||||
They can be used to extend existing blender data with your own types which can
|
||||
be animated, accessed from the user interface and from python.
|
||||
|
||||
.. note::
|
||||
|
||||
The values assigned to blender data are saved to disk but the class
|
||||
definitions are not, this means whenever you load blender the class needs
|
||||
to be registered too.
|
||||
|
||||
This is best done by creating an addon which loads on startup and registers
|
||||
your properties.
|
||||
|
||||
.. note::
|
||||
|
||||
PropertyGroups must be registered before assigning them to blender data.
|
||||
|
||||
.. seealso::
|
||||
|
||||
Property types used in class declarations are all in :mod:`bpy.props`
|
||||
"""
|
||||
import bpy
|
||||
|
||||
|
||||
class MyPropertyGroup(bpy.types.PropertyGroup):
|
||||
custom_1 = bpy.props.FloatProperty(name="My Float")
|
||||
custom_2 = bpy.props.IntProperty(name="My Int")
|
||||
|
||||
bpy.utils.register_class(MyPropertyGroup)
|
||||
|
||||
bpy.types.Object.my_properties = MyPropertyGroup
|
||||
|
||||
|
||||
# test this worked
|
||||
bpy.data.objects[0].my_properties.custom_1 = 22.0
|
||||
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
Simple Render Engine
|
||||
++++++++++++++++++++
|
||||
"""
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class CustomRenderEngine(bpy.types.RenderEngine):
|
||||
# These three members are used by blender to set up the
|
||||
# RenderEngine; define its internal name, visible name and capabilities.
|
||||
bl_idname = 'custom_renderer'
|
||||
bl_label = 'Flat Color Renderer'
|
||||
bl_use_preview = True
|
||||
|
||||
# This is the only method called by blender, in this example
|
||||
# we use it to detect preview rendering and call the implementation
|
||||
# in another method.
|
||||
def render(self, scene):
|
||||
scale = scene.render.resolution_percentage / 100.0
|
||||
self.size_x = int(scene.render.resolution_x * scale)
|
||||
self.size_y = int(scene.render.resolution_y * scale)
|
||||
|
||||
if scene.name == 'preview':
|
||||
self.render_preview(scene)
|
||||
else:
|
||||
self.render_scene(scene)
|
||||
|
||||
# In this example, we fill the preview renders with a flat green color.
|
||||
def render_preview(self, scene):
|
||||
pixel_count = self.size_x * self.size_y
|
||||
|
||||
# The framebuffer is defined as a list of pixels, each pixel
|
||||
# itself being a list of R,G,B,A values
|
||||
green_rect = [[0.0, 1.0, 0.0, 1.0]] * pixel_count
|
||||
|
||||
# Here we write the pixel values to the RenderResult
|
||||
result = self.begin_result(0, 0, self.size_x, self.size_y)
|
||||
layer = result.layers[0]
|
||||
layer.rect = green_rect
|
||||
self.end_result(result)
|
||||
|
||||
# In this example, we fill the full renders with a flat blue color.
|
||||
def render_scene(self, scene):
|
||||
pixel_count = self.size_x * self.size_y
|
||||
|
||||
# The framebuffer is defined as a list of pixels, each pixel
|
||||
# itself being a list of R,G,B,A values
|
||||
blue_rect = [[0.0, 0.0, 1.0, 1.0]] * pixel_count
|
||||
|
||||
# Here we write the pixel values to the RenderResult
|
||||
result = self.begin_result(0, 0, self.size_x, self.size_y)
|
||||
layer = result.layers[0]
|
||||
layer.rect = blue_rect
|
||||
self.end_result(result)
|
||||
|
||||
# Register the RenderEngine
|
||||
bpy.utils.register_class(CustomRenderEngine)
|
||||
|
||||
# RenderEngines also need to tell UI Panels that they are compatible
|
||||
# Otherwise most of the UI will be empty when the engine is selected.
|
||||
# In this example, we need to see the main render image button and
|
||||
# the material preview panel.
|
||||
import properties_render
|
||||
properties_render.RENDER_PT_render.COMPAT_ENGINES.add('custom_renderer')
|
||||
del properties_render
|
||||
|
||||
import properties_material
|
||||
properties_material.MATERIAL_PT_preview.COMPAT_ENGINES.add('custom_renderer')
|
||||
del properties_material
|
||||
+496
-249
@@ -47,6 +47,46 @@ For PDF generation
|
||||
make
|
||||
'''
|
||||
|
||||
# Switch for quick testing
|
||||
if 1:
|
||||
# full build
|
||||
EXCLUDE_MODULES = ()
|
||||
FILTER_BPY_TYPES = None
|
||||
FILTER_BPY_OPS = None
|
||||
|
||||
else:
|
||||
# for testing so doc-builds dont take so long.
|
||||
EXCLUDE_MODULES = (
|
||||
# "bpy.context",
|
||||
"bpy.app",
|
||||
"bpy.path",
|
||||
"bpy.data",
|
||||
#"bpy.props",
|
||||
"bpy.utils",
|
||||
"bpy.context",
|
||||
# "bpy.types", # supports filtering
|
||||
"bpy.ops", # supports filtering
|
||||
"bge",
|
||||
"aud",
|
||||
"bgl",
|
||||
"blf",
|
||||
"mathutils",
|
||||
"mathutils.geometry",
|
||||
"Freestyle",
|
||||
)
|
||||
|
||||
FILTER_BPY_TYPES = ("PropertyGroup", "Panel", "Menu", "Operator", "RenderEngine") # allow
|
||||
FILTER_BPY_OPS = ("import.scene", ) # allow
|
||||
|
||||
# for quick rebuilds
|
||||
"""
|
||||
rm -rf /b/doc/python_api/sphinx-* && \
|
||||
./blender.bin --background --factory-startup --python doc/python_api/sphinx_doc_gen.py && \
|
||||
sphinx-build doc/python_api/sphinx-in doc/python_api/sphinx-out
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# import rpdb2; rpdb2.start_embedded_debugger('test')
|
||||
|
||||
import os
|
||||
@@ -72,9 +112,9 @@ def undocumented_message(module_name, type_name, identifier):
|
||||
preloadtitle = '%s.%s' % (module_name, identifier)
|
||||
else:
|
||||
preloadtitle = '%s.%s.%s' % (module_name, type_name, identifier)
|
||||
message = "Undocumented (`contribute " \
|
||||
"<http://wiki.blender.org/index.php/Dev:2.5/Py/API/Documentation/Contribute" \
|
||||
"?action=edit§ion=new&preload=Dev:2.5/Py/API/Documentation/Contribute/Howto-message" \
|
||||
message = "Undocumented (`contribute "\
|
||||
"<http://wiki.blender.org/index.php/Dev:2.5/Py/API/Documentation/Contribute"\
|
||||
"?action=edit§ion=new&preload=Dev:2.5/Py/API/Documentation/Contribute/Howto-message"\
|
||||
"&preloadtitle=%s>`_)\n\n" % preloadtitle
|
||||
return message
|
||||
|
||||
@@ -94,14 +134,61 @@ def range_str(val):
|
||||
return str(val)
|
||||
|
||||
|
||||
def example_extract_docstring(filepath):
|
||||
file = open(filepath, 'r')
|
||||
line = file.readline()
|
||||
line_no = 0
|
||||
text = []
|
||||
if line.startswith('"""'): # assume nothing here
|
||||
line_no += 1
|
||||
else:
|
||||
file.close()
|
||||
return "", 0
|
||||
|
||||
for line in file.readlines():
|
||||
line_no += 1
|
||||
if line.startswith('"""'):
|
||||
break
|
||||
else:
|
||||
text.append(line.rstrip())
|
||||
|
||||
line_no += 1
|
||||
file.close()
|
||||
return "\n".join(text), line_no
|
||||
|
||||
|
||||
def write_example_ref(ident, fw, example_id, ext="py"):
|
||||
if example_id in EXAMPLE_SET:
|
||||
fw("%s.. literalinclude:: ../examples/%s.%s\n\n" % (ident, example_id, ext))
|
||||
|
||||
# extract the comment
|
||||
filepath = "../examples/%s.%s" % (example_id, ext)
|
||||
filepath_full = os.path.join(os.path.dirname(fw.__self__.name), filepath)
|
||||
|
||||
text, line_no = example_extract_docstring(filepath_full)
|
||||
|
||||
for line in text.split("\n"):
|
||||
fw("%s\n" % (ident + line).rstrip())
|
||||
fw("\n")
|
||||
|
||||
fw("%s.. literalinclude:: %s\n" % (ident, filepath))
|
||||
if line_no > 0:
|
||||
fw("%s :lines: %d-\n" % (ident, line_no))
|
||||
fw("\n")
|
||||
EXAMPLE_SET_USED.add(example_id)
|
||||
else:
|
||||
if bpy.app.debug:
|
||||
print("\tskipping example:", example_id)
|
||||
|
||||
# Support for numbered files bpy.types.Operator -> bpy.types.Operator.1.py
|
||||
i = 1
|
||||
while True:
|
||||
example_id_num = "%s.%d" % (example_id, i)
|
||||
if example_id_num in EXAMPLE_SET:
|
||||
write_example_ref(ident, fw, example_id_num, ext)
|
||||
i += 1
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
def write_indented_lines(ident, fn, text, strip=True):
|
||||
'''
|
||||
@@ -321,224 +408,127 @@ def pymodule2sphinx(BASEPATH, module_name, module, title):
|
||||
file.close()
|
||||
|
||||
|
||||
def rna2sphinx(BASEPATH):
|
||||
def pycontext2sphinx(BASEPATH):
|
||||
# Only use once. very irregular
|
||||
|
||||
filepath = os.path.join(BASEPATH, "bpy.context.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
fw("Context Access (bpy.context)\n")
|
||||
fw("============================\n\n")
|
||||
fw(".. module:: bpy.context\n")
|
||||
fw("\n")
|
||||
fw("The context members available depend on the area of blender which is currently being accessed.\n")
|
||||
fw("\n")
|
||||
fw("Note that all context values are readonly, but may be modified through the data api or by running operators\n\n")
|
||||
|
||||
# nasty, get strings directly from blender because there is no other way to get it
|
||||
import ctypes
|
||||
|
||||
context_strings = (
|
||||
"screen_context_dir",
|
||||
"view3d_context_dir",
|
||||
"buttons_context_dir",
|
||||
"image_context_dir",
|
||||
"node_context_dir",
|
||||
"text_context_dir",
|
||||
)
|
||||
|
||||
# Changes in blender will force errors here
|
||||
type_map = {
|
||||
"active_base": ("ObjectBase", False),
|
||||
"active_bone": ("Bone", False),
|
||||
"active_object": ("Object", False),
|
||||
"active_pose_bone": ("PoseBone", False),
|
||||
"armature": ("Armature", False),
|
||||
"bone": ("Bone", False),
|
||||
"brush": ("Brush", False),
|
||||
"camera": ("Camera", False),
|
||||
"cloth": ("ClothModifier", False),
|
||||
"collision": ("CollisionModifier", False),
|
||||
"curve": ("Curve", False),
|
||||
"edit_bone": ("EditBone", False),
|
||||
"edit_image": ("Image", False),
|
||||
"edit_object": ("Object", False),
|
||||
"edit_text": ("Text", False),
|
||||
"editable_bones": ("EditBone", True),
|
||||
"fluid": ("FluidSimulationModifier", False),
|
||||
"lamp": ("Lamp", False),
|
||||
"lattice": ("Lattice", False),
|
||||
"material": ("Material", False),
|
||||
"material_slot": ("MaterialSlot", False),
|
||||
"mesh": ("Mesh", False),
|
||||
"meta_ball": ("MetaBall", False),
|
||||
"object": ("Object", False),
|
||||
"particle_edit_object": ("Object", False),
|
||||
"particle_system": ("ParticleSystem", False),
|
||||
"particle_system_editable": ("ParticleSystem", False),
|
||||
"pose_bone": ("PoseBone", False),
|
||||
"scene": ("Scene", False),
|
||||
"sculpt_object": ("Object", False),
|
||||
"selectable_bases": ("ObjectBase", True),
|
||||
"selectable_objects": ("Object", True),
|
||||
"selected_bases": ("ObjectBase", True),
|
||||
"selected_bones": ("Bone", True),
|
||||
"selected_editable_bases": ("ObjectBase", True),
|
||||
"selected_editable_bones": ("Bone", True),
|
||||
"selected_editable_objects": ("Object", True),
|
||||
"selected_editable_sequences": ("Sequence", True),
|
||||
"selected_nodes": ("Node", True),
|
||||
"selected_objects": ("Object", True),
|
||||
"selected_pose_bones": ("PoseBone", True),
|
||||
"selected_sequences": ("Sequence", True),
|
||||
"sequences": ("Sequence", True),
|
||||
"smoke": ("SmokeModifier", False),
|
||||
"soft_body": ("SoftBodyModifier", False),
|
||||
"texture": ("Texture", False),
|
||||
"texture_paint_object": ("Object", False),
|
||||
"texture_slot": ("MaterialTextureSlot", False),
|
||||
"vertex_paint_object": ("Object", False),
|
||||
"visible_bases": ("ObjectBase", True),
|
||||
"visible_bones": ("Object", True),
|
||||
"visible_objects": ("Object", True),
|
||||
"visible_pose_bones": ("PoseBone", True),
|
||||
"weight_paint_object": ("Object", False),
|
||||
"world": ("World", False),
|
||||
}
|
||||
|
||||
unique = set()
|
||||
blend_cdll = ctypes.CDLL("")
|
||||
for ctx_str in context_strings:
|
||||
subsection = "%s Context" % ctx_str.split("_")[0].title()
|
||||
fw("\n%s\n%s\n\n" % (subsection, (len(subsection) * '-')))
|
||||
|
||||
attr = ctypes.addressof(getattr(blend_cdll, ctx_str))
|
||||
c_char_p_p = ctypes.POINTER(ctypes.c_char_p)
|
||||
char_array = c_char_p_p.from_address(attr)
|
||||
i = 0
|
||||
while char_array[i] is not None:
|
||||
member = ctypes.string_at(char_array[i]).decode()
|
||||
fw(".. data:: %s\n\n" % member)
|
||||
member_type, is_seq = type_map[member]
|
||||
fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type))
|
||||
unique.add(member)
|
||||
i += 1
|
||||
|
||||
# generate typemap...
|
||||
# for member in sorted(unique):
|
||||
# print(' "%s": ("", False),' % member)
|
||||
if len(type_map) > len(unique):
|
||||
raise Exception("Some types are not used: %s" % str([member for member in type_map if member not in unique]))
|
||||
else:
|
||||
pass # will have raised an error above
|
||||
|
||||
|
||||
def pyrna2sphinx(BASEPATH):
|
||||
""" bpy.types and bpy.ops
|
||||
"""
|
||||
structs, funcs, ops, props = rna_info.BuildRNAInfo()
|
||||
if FILTER_BPY_TYPES is not None:
|
||||
structs = {k: v for k, v in structs.items() if k[1] in FILTER_BPY_TYPES}
|
||||
|
||||
try:
|
||||
os.mkdir(BASEPATH)
|
||||
except:
|
||||
pass
|
||||
|
||||
# conf.py - empty for now
|
||||
filepath = os.path.join(BASEPATH, "conf.py")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
|
||||
version_string = ".".join(str(v) for v in bpy.app.version)
|
||||
if bpy.app.build_revision != "Unknown":
|
||||
version_string = version_string + " r" + bpy.app.build_revision
|
||||
|
||||
# for use with files
|
||||
version_string_fp = "_".join(str(v) for v in bpy.app.version)
|
||||
|
||||
fw("project = 'Blender'\n")
|
||||
# fw("master_doc = 'index'\n")
|
||||
fw("copyright = u'Blender Foundation'\n")
|
||||
fw("version = '%s - UNSTABLE API'\n" % version_string)
|
||||
fw("release = '%s - UNSTABLE API'\n" % version_string)
|
||||
fw("html_theme = 'blender-org'\n")
|
||||
fw("html_theme_path = ['../']\n")
|
||||
fw("html_favicon = 'favicon.ico'\n")
|
||||
# not helpful since the source us generated, adds to upload size.
|
||||
fw("html_copy_source = False\n")
|
||||
fw("\n")
|
||||
# needed for latex, pdf gen
|
||||
fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
|
||||
fw("latex_paper_size = 'a4paper'\n")
|
||||
file.close()
|
||||
|
||||
# main page needed for sphinx (index.html)
|
||||
filepath = os.path.join(BASEPATH, "contents.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
|
||||
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
|
||||
fw(" Blender Documentation contents\n")
|
||||
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
|
||||
fw("\n")
|
||||
fw("This document is an API reference for Blender %s. built %s.\n" % (version_string, bpy.app.build_date))
|
||||
fw("\n")
|
||||
fw("An introduction to Blender and Python can be found at <http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro>\n")
|
||||
fw("\n")
|
||||
fw("`A PDF version of this document is also available <blender_python_reference_%s.pdf>`__\n" % version_string_fp)
|
||||
fw("\n")
|
||||
fw(".. warning:: The Python API in Blender is **UNSTABLE**, It should only be used for testing, any script written now may break in future releases.\n")
|
||||
fw(" \n")
|
||||
fw(" The following areas are subject to change.\n")
|
||||
fw(" * operator names and arguments\n")
|
||||
fw(" * render api\n")
|
||||
fw(" * function calls with the data api (any function calls with values accessed from bpy.data), including functions for importing and exporting meshes\n")
|
||||
fw(" * class registration (Operator, Panels, Menus, Headers)\n")
|
||||
fw(" * modules: bpy.props, blf)\n")
|
||||
fw(" * members in the bpy.context have to be reviewed\n")
|
||||
fw(" * python defined modal operators, especially drawing callbacks are highly experemental\n")
|
||||
fw(" \n")
|
||||
fw(" These parts of the API are relatively stable and are unlikely to change significantly\n")
|
||||
fw(" * data API, access to attributes of blender data such as mesh verts, material color, timeline frames and scene objects\n")
|
||||
fw(" * user interface functions for defining buttons, creation of menus, headers, panels\n")
|
||||
fw(" * modules: bgl and mathutils\n")
|
||||
fw(" * game engine modules\n")
|
||||
fw("\n")
|
||||
|
||||
fw("===================\n")
|
||||
fw("Application Modules\n")
|
||||
fw("===================\n")
|
||||
fw("\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :maxdepth: 1\n\n")
|
||||
fw(" bpy.data.rst\n\n") # note: not actually a module
|
||||
fw(" bpy.ops.rst\n\n")
|
||||
fw(" bpy.types.rst\n\n")
|
||||
|
||||
# py modules
|
||||
fw(" bpy.utils.rst\n\n")
|
||||
fw(" bpy.path.rst\n\n")
|
||||
fw(" bpy.app.rst\n\n")
|
||||
|
||||
# C modules
|
||||
fw(" bpy.props.rst\n\n")
|
||||
|
||||
fw("==================\n")
|
||||
fw("Standalone Modules\n")
|
||||
fw("==================\n")
|
||||
fw("\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :maxdepth: 1\n\n")
|
||||
|
||||
fw(" mathutils.rst\n\n")
|
||||
fw(" Freestyle.rst\n\n")
|
||||
fw(" mathutils.geometry.rst\n\n")
|
||||
# XXX TODO
|
||||
#fw(" bgl.rst\n\n")
|
||||
fw(" blf.rst\n\n")
|
||||
fw(" aud.rst\n\n")
|
||||
|
||||
# game engine
|
||||
fw("===================\n")
|
||||
fw("Game Engine Modules\n")
|
||||
fw("===================\n")
|
||||
fw("\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :maxdepth: 1\n\n")
|
||||
fw(" bge.types.rst\n\n")
|
||||
fw(" bge.logic.rst\n\n")
|
||||
fw(" bge.render.rst\n\n")
|
||||
fw(" bge.events.rst\n\n")
|
||||
|
||||
file.close()
|
||||
|
||||
# internal modules
|
||||
filepath = os.path.join(BASEPATH, "bpy.ops.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
fw("Operators (bpy.ops)\n")
|
||||
fw("===================\n\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :glob:\n\n")
|
||||
fw(" bpy.ops.*\n\n")
|
||||
file.close()
|
||||
|
||||
filepath = os.path.join(BASEPATH, "bpy.types.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
fw("Types (bpy.types)\n")
|
||||
fw("=================\n\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :glob:\n\n")
|
||||
fw(" bpy.types.*\n\n")
|
||||
file.close()
|
||||
|
||||
# not actually a module, only write this file so we
|
||||
# can reference in the TOC
|
||||
filepath = os.path.join(BASEPATH, "bpy.data.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
fw("Data Access (bpy.data)\n")
|
||||
fw("======================\n\n")
|
||||
fw(".. module:: bpy\n")
|
||||
fw("\n")
|
||||
fw("This module is used for all blender/python access.\n")
|
||||
fw("\n")
|
||||
fw(".. data:: data\n")
|
||||
fw("\n")
|
||||
fw(" Access to blenders internal data\n")
|
||||
fw("\n")
|
||||
fw(" :type: :class:`bpy.types.BlendData`\n")
|
||||
fw("\n")
|
||||
fw(".. literalinclude:: ../examples/bpy.data.py\n")
|
||||
file.close()
|
||||
|
||||
EXAMPLE_SET_USED.add("bpy.data")
|
||||
|
||||
# python modules
|
||||
from bpy import utils as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.utils", module, "Utilities (bpy.utils)")
|
||||
|
||||
from bpy import path as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.path", module, "Path Utilities (bpy.path)")
|
||||
|
||||
# C modules
|
||||
from bpy import app as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.app", module, "Application Data (bpy.app)")
|
||||
|
||||
from bpy import props as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.props", module, "Property Definitions (bpy.props)")
|
||||
|
||||
import mathutils as module
|
||||
pymodule2sphinx(BASEPATH, "mathutils", module, "Math Types & Utilities (mathutils)")
|
||||
del module
|
||||
|
||||
import mathutils.geometry as module
|
||||
pymodule2sphinx(BASEPATH, "mathutils.geometry", module, "Geometry Utilities (mathutils.geometry)")
|
||||
del module
|
||||
|
||||
import Freestyle as module
|
||||
pymodule2sphinx(BASEPATH, "Freestyle", module, "Freestyle Data Types & Operators (Freestyle)")
|
||||
del module
|
||||
|
||||
import blf as module
|
||||
pymodule2sphinx(BASEPATH, "blf", module, "Font Drawing (blf)")
|
||||
del module
|
||||
|
||||
# XXX TODO
|
||||
#import bgl as module
|
||||
#pymodule2sphinx(BASEPATH, "bgl", module, "Blender OpenGl wrapper (bgl)")
|
||||
#del module
|
||||
|
||||
import aud as module
|
||||
pymodule2sphinx(BASEPATH, "aud", module, "Audio System (aud)")
|
||||
del module
|
||||
|
||||
## game engine
|
||||
import shutil
|
||||
# copy2 keeps time/date stamps
|
||||
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.types.rst"), BASEPATH)
|
||||
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.logic.rst"), BASEPATH)
|
||||
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.render.rst"), BASEPATH)
|
||||
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.events.rst"), BASEPATH)
|
||||
|
||||
if 0:
|
||||
filepath = os.path.join(BASEPATH, "bpy.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
|
||||
fw("\n")
|
||||
|
||||
title = ":mod:`bpy` --- Blender Python Module"
|
||||
fw("%s\n%s\n\n" % (title, "=" * len(title)))
|
||||
fw(".. module:: bpy.types\n\n")
|
||||
file.close()
|
||||
if FILTER_BPY_OPS is not None:
|
||||
ops = {k: v for k, v in ops.items() if v.module_name in FILTER_BPY_OPS}
|
||||
|
||||
def write_param(ident, fw, prop, is_return=False):
|
||||
if is_return:
|
||||
@@ -583,6 +573,9 @@ def rna2sphinx(BASEPATH):
|
||||
|
||||
fw(".. module:: bpy.types\n\n")
|
||||
|
||||
# docs first?, ok
|
||||
write_example_ref("", fw, "bpy.types.%s" % struct.identifier)
|
||||
|
||||
base_ids = [base.identifier for base in struct.get_bases()]
|
||||
|
||||
if _BPY_STRUCT_FAKE:
|
||||
@@ -744,42 +737,46 @@ def rna2sphinx(BASEPATH):
|
||||
fw(" * :class:`%s`\n" % ref)
|
||||
fw("\n")
|
||||
|
||||
for struct in structs.values():
|
||||
# TODO, rna_info should filter these out!
|
||||
if "_OT_" in struct.identifier:
|
||||
continue
|
||||
write_struct(struct)
|
||||
# docs last?, disable for now
|
||||
# write_example_ref("", fw, "bpy.types.%s" % struct.identifier)
|
||||
|
||||
# special case, bpy_struct
|
||||
if _BPY_STRUCT_FAKE:
|
||||
filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % _BPY_STRUCT_FAKE)
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
if "bpy.types" not in EXCLUDE_MODULES:
|
||||
for struct in structs.values():
|
||||
# TODO, rna_info should filter these out!
|
||||
if "_OT_" in struct.identifier:
|
||||
continue
|
||||
write_struct(struct)
|
||||
|
||||
fw("%s\n" % _BPY_STRUCT_FAKE)
|
||||
fw("=" * len(_BPY_STRUCT_FAKE) + "\n")
|
||||
fw("\n")
|
||||
fw(".. module:: bpy.types\n")
|
||||
fw("\n")
|
||||
# special case, bpy_struct
|
||||
if _BPY_STRUCT_FAKE:
|
||||
filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % _BPY_STRUCT_FAKE)
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
|
||||
subclass_ids = [s.identifier for s in structs.values() if s.base is None if not rna_info.rna_id_ignore(s.identifier)]
|
||||
if subclass_ids:
|
||||
fw("subclasses --- \n" + ", ".join((":class:`%s`" % s) for s in sorted(subclass_ids)) + "\n\n")
|
||||
fw("%s\n" % _BPY_STRUCT_FAKE)
|
||||
fw("=" * len(_BPY_STRUCT_FAKE) + "\n")
|
||||
fw("\n")
|
||||
fw(".. module:: bpy.types\n")
|
||||
fw("\n")
|
||||
|
||||
fw(".. class:: %s\n\n" % _BPY_STRUCT_FAKE)
|
||||
fw(" built-in base class for all classes in bpy.types.\n\n")
|
||||
fw(" .. note::\n\n")
|
||||
fw(" Note that bpy.types.%s is not actually available from within blender, it only exists for the purpose of documentation.\n\n" % _BPY_STRUCT_FAKE)
|
||||
subclass_ids = [s.identifier for s in structs.values() if s.base is None if not rna_info.rna_id_ignore(s.identifier)]
|
||||
if subclass_ids:
|
||||
fw("subclasses --- \n" + ", ".join((":class:`%s`" % s) for s in sorted(subclass_ids)) + "\n\n")
|
||||
|
||||
descr_items = [(key, descr) for key, descr in sorted(bpy.types.Struct.__bases__[0].__dict__.items()) if not key.startswith("__")]
|
||||
fw(".. class:: %s\n\n" % _BPY_STRUCT_FAKE)
|
||||
fw(" built-in base class for all classes in bpy.types.\n\n")
|
||||
fw(" .. note::\n\n")
|
||||
fw(" Note that bpy.types.%s is not actually available from within blender, it only exists for the purpose of documentation.\n\n" % _BPY_STRUCT_FAKE)
|
||||
|
||||
for key, descr in descr_items:
|
||||
if type(descr) == MethodDescriptorType: # GetSetDescriptorType, GetSetDescriptorType's are not documented yet
|
||||
py_descr2sphinx(" ", fw, descr, "bpy.types", _BPY_STRUCT_FAKE, key)
|
||||
descr_items = [(key, descr) for key, descr in sorted(bpy.types.Struct.__bases__[0].__dict__.items()) if not key.startswith("__")]
|
||||
|
||||
for key, descr in descr_items:
|
||||
if type(descr) == GetSetDescriptorType:
|
||||
py_descr2sphinx(" ", fw, descr, "bpy.types", _BPY_STRUCT_FAKE, key)
|
||||
for key, descr in descr_items:
|
||||
if type(descr) == MethodDescriptorType: # GetSetDescriptorType, GetSetDescriptorType's are not documented yet
|
||||
py_descr2sphinx(" ", fw, descr, "bpy.types", _BPY_STRUCT_FAKE, key)
|
||||
|
||||
for key, descr in descr_items:
|
||||
if type(descr) == GetSetDescriptorType:
|
||||
py_descr2sphinx(" ", fw, descr, "bpy.types", _BPY_STRUCT_FAKE, key)
|
||||
|
||||
# operators
|
||||
def write_ops():
|
||||
@@ -821,7 +818,257 @@ def rna2sphinx(BASEPATH):
|
||||
if location != (None, None):
|
||||
fw(" :file: `%s <%s/%s>`_:%d\n\n" % (location[0], API_BASEURL, location[0], location[1]))
|
||||
|
||||
write_ops()
|
||||
if "bpy.ops" not in EXCLUDE_MODULES:
|
||||
write_ops()
|
||||
|
||||
|
||||
def rna2sphinx(BASEPATH):
|
||||
|
||||
try:
|
||||
os.mkdir(BASEPATH)
|
||||
except:
|
||||
pass
|
||||
|
||||
# conf.py - empty for now
|
||||
filepath = os.path.join(BASEPATH, "conf.py")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
|
||||
version_string = ".".join(str(v) for v in bpy.app.version)
|
||||
if bpy.app.build_revision != "Unknown":
|
||||
version_string = version_string + " r" + bpy.app.build_revision
|
||||
|
||||
# for use with files
|
||||
version_string_fp = "_".join(str(v) for v in bpy.app.version)
|
||||
|
||||
fw("project = 'Blender'\n")
|
||||
# fw("master_doc = 'index'\n")
|
||||
fw("copyright = u'Blender Foundation'\n")
|
||||
fw("version = '%s - UNSTABLE API'\n" % version_string)
|
||||
fw("release = '%s - UNSTABLE API'\n" % version_string)
|
||||
fw("html_theme = 'blender-org'\n")
|
||||
fw("html_theme_path = ['../']\n")
|
||||
fw("html_favicon = 'favicon.ico'\n")
|
||||
# not helpful since the source us generated, adds to upload size.
|
||||
fw("html_copy_source = False\n")
|
||||
fw("\n")
|
||||
# needed for latex, pdf gen
|
||||
fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
|
||||
fw("latex_paper_size = 'a4paper'\n")
|
||||
file.close()
|
||||
|
||||
# main page needed for sphinx (index.html)
|
||||
filepath = os.path.join(BASEPATH, "contents.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
|
||||
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
|
||||
fw(" Blender Documentation contents\n")
|
||||
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
|
||||
fw("\n")
|
||||
fw("This document is an API reference for Blender %s. built %s.\n" % (version_string, bpy.app.build_date))
|
||||
fw("\n")
|
||||
fw("| An introduction to Blender and Python can be found at `Quickstart Intro <http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro>`_,\n")
|
||||
fw("| For a more general explanation of blender/python see the `API Overview <http://wiki.blender.org/index.php/Dev:2.5/Py/API/Overview>`_\n")
|
||||
fw("\n")
|
||||
fw("`A PDF version of this document is also available <blender_python_reference_%s.pdf>`_\n" % version_string_fp)
|
||||
fw("\n")
|
||||
fw(".. warning:: The Python API in Blender is **UNSTABLE**, It should only be used for testing, any script written now may break in future releases.\n")
|
||||
fw(" \n")
|
||||
fw(" The following areas are subject to change.\n")
|
||||
fw(" * operator names and arguments\n")
|
||||
fw(" * render api\n")
|
||||
fw(" * function calls with the data api (any function calls with values accessed from bpy.data), including functions for importing and exporting meshes\n")
|
||||
fw(" * class registration (Operator, Panels, Menus, Headers)\n")
|
||||
fw(" * modules: bpy.props, blf)\n")
|
||||
fw(" * members in the bpy.context have to be reviewed\n")
|
||||
fw(" * python defined modal operators, especially drawing callbacks are highly experemental\n")
|
||||
fw(" \n")
|
||||
fw(" These parts of the API are relatively stable and are unlikely to change significantly\n")
|
||||
fw(" * data API, access to attributes of blender data such as mesh verts, material color, timeline frames and scene objects\n")
|
||||
fw(" * user interface functions for defining buttons, creation of menus, headers, panels\n")
|
||||
fw(" * modules: bgl and mathutils\n")
|
||||
fw(" * game engine modules\n")
|
||||
fw("\n")
|
||||
|
||||
fw("===================\n")
|
||||
fw("Application Modules\n")
|
||||
fw("===================\n")
|
||||
fw("\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :maxdepth: 1\n\n")
|
||||
if "bpy.context" not in EXCLUDE_MODULES:
|
||||
fw(" bpy.context.rst\n\n") # note: not actually a module
|
||||
if "bpy.data" not in EXCLUDE_MODULES:
|
||||
fw(" bpy.data.rst\n\n") # note: not actually a module
|
||||
if "bpy.ops" not in EXCLUDE_MODULES:
|
||||
fw(" bpy.ops.rst\n\n")
|
||||
if "bpy.types" not in EXCLUDE_MODULES:
|
||||
fw(" bpy.types.rst\n\n")
|
||||
|
||||
# py modules
|
||||
if "bpy.utils" not in EXCLUDE_MODULES:
|
||||
fw(" bpy.utils.rst\n\n")
|
||||
if "bpy.path" not in EXCLUDE_MODULES:
|
||||
fw(" bpy.path.rst\n\n")
|
||||
if "bpy.app" not in EXCLUDE_MODULES:
|
||||
fw(" bpy.app.rst\n\n")
|
||||
|
||||
# C modules
|
||||
if "bpy.props" not in EXCLUDE_MODULES:
|
||||
fw(" bpy.props.rst\n\n")
|
||||
|
||||
fw("==================\n")
|
||||
fw("Standalone Modules\n")
|
||||
fw("==================\n")
|
||||
fw("\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :maxdepth: 1\n\n")
|
||||
|
||||
if "mathutils" not in EXCLUDE_MODULES:
|
||||
fw(" mathutils.rst\n\n")
|
||||
if "mathutils.geometry" not in EXCLUDE_MODULES:
|
||||
fw(" mathutils.geometry.rst\n\n")
|
||||
if "Freestyle" not in EXCLUDE_MODULES:
|
||||
fw(" Freestyle.rst\n\n")
|
||||
# XXX TODO
|
||||
#fw(" bgl.rst\n\n")
|
||||
if "blf" not in EXCLUDE_MODULES:
|
||||
fw(" blf.rst\n\n")
|
||||
if "aud" not in EXCLUDE_MODULES:
|
||||
fw(" aud.rst\n\n")
|
||||
|
||||
# game engine
|
||||
if "bge" not in EXCLUDE_MODULES:
|
||||
fw("===================\n")
|
||||
fw("Game Engine Modules\n")
|
||||
fw("===================\n")
|
||||
fw("\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :maxdepth: 1\n\n")
|
||||
fw(" bge.types.rst\n\n")
|
||||
fw(" bge.logic.rst\n\n")
|
||||
fw(" bge.render.rst\n\n")
|
||||
fw(" bge.events.rst\n\n")
|
||||
|
||||
file.close()
|
||||
|
||||
# internal modules
|
||||
if "bpy.ops" not in EXCLUDE_MODULES:
|
||||
filepath = os.path.join(BASEPATH, "bpy.ops.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
fw("Operators (bpy.ops)\n")
|
||||
fw("===================\n\n")
|
||||
write_example_ref("", fw, "bpy.ops")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :glob:\n\n")
|
||||
fw(" bpy.ops.*\n\n")
|
||||
file.close()
|
||||
|
||||
if "bpy.types" not in EXCLUDE_MODULES:
|
||||
filepath = os.path.join(BASEPATH, "bpy.types.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
fw("Types (bpy.types)\n")
|
||||
fw("=================\n\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :glob:\n\n")
|
||||
fw(" bpy.types.*\n\n")
|
||||
file.close()
|
||||
|
||||
if "bpy.data" not in EXCLUDE_MODULES:
|
||||
# not actually a module, only write this file so we
|
||||
# can reference in the TOC
|
||||
filepath = os.path.join(BASEPATH, "bpy.data.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
fw("Data Access (bpy.data)\n")
|
||||
fw("======================\n\n")
|
||||
fw(".. module:: bpy\n")
|
||||
fw("\n")
|
||||
fw("This module is used for all blender/python access.\n")
|
||||
fw("\n")
|
||||
fw(".. data:: data\n")
|
||||
fw("\n")
|
||||
fw(" Access to blenders internal data\n")
|
||||
fw("\n")
|
||||
fw(" :type: :class:`bpy.types.BlendData`\n")
|
||||
fw("\n")
|
||||
fw(".. literalinclude:: ../examples/bpy.data.py\n")
|
||||
file.close()
|
||||
|
||||
EXAMPLE_SET_USED.add("bpy.data")
|
||||
|
||||
module = None
|
||||
|
||||
if "bpy.context" not in EXCLUDE_MODULES:
|
||||
# one of a kind, context doc (uses ctypes to extract info!)
|
||||
pycontext2sphinx(BASEPATH)
|
||||
|
||||
# python modules
|
||||
if "bpy.utils" not in EXCLUDE_MODULES:
|
||||
from bpy import utils as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.utils", module, "Utilities (bpy.utils)")
|
||||
|
||||
if "bpy.path" not in EXCLUDE_MODULES:
|
||||
from bpy import path as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.path", module, "Path Utilities (bpy.path)")
|
||||
|
||||
# C modules
|
||||
if "bpy.app" not in EXCLUDE_MODULES:
|
||||
from bpy import app as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.app", module, "Application Data (bpy.app)")
|
||||
|
||||
if "bpy.props" not in EXCLUDE_MODULES:
|
||||
from bpy import props as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.props", module, "Property Definitions (bpy.props)")
|
||||
|
||||
if "mathutils" not in EXCLUDE_MODULES:
|
||||
import mathutils as module
|
||||
pymodule2sphinx(BASEPATH, "mathutils", module, "Math Types & Utilities (mathutils)")
|
||||
|
||||
if "mathutils.geometry" not in EXCLUDE_MODULES:
|
||||
import mathutils.geometry as module
|
||||
pymodule2sphinx(BASEPATH, "mathutils.geometry", module, "Geometry Utilities (mathutils.geometry)")
|
||||
|
||||
if "mathutils.geometry" not in EXCLUDE_MODULES:
|
||||
import blf as module
|
||||
pymodule2sphinx(BASEPATH, "blf", module, "Font Drawing (blf)")
|
||||
|
||||
# XXX TODO
|
||||
#import bgl as module
|
||||
#pymodule2sphinx(BASEPATH, "bgl", module, "Blender OpenGl wrapper (bgl)")
|
||||
#del module
|
||||
|
||||
if "aud" not in EXCLUDE_MODULES:
|
||||
import aud as module
|
||||
pymodule2sphinx(BASEPATH, "aud", module, "Audio System (aud)")
|
||||
del module
|
||||
|
||||
## game engine
|
||||
import shutil
|
||||
# copy2 keeps time/date stamps
|
||||
if "bge" not in EXCLUDE_MODULES:
|
||||
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.types.rst"), BASEPATH)
|
||||
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.logic.rst"), BASEPATH)
|
||||
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.render.rst"), BASEPATH)
|
||||
shutil.copy2(os.path.join(BASEPATH, "..", "rst", "bge.events.rst"), BASEPATH)
|
||||
|
||||
if 0:
|
||||
filepath = os.path.join(BASEPATH, "bpy.rst")
|
||||
file = open(filepath, "w")
|
||||
fw = file.write
|
||||
|
||||
fw("\n")
|
||||
|
||||
title = ":mod:`bpy` --- Blender Python Module"
|
||||
fw("%s\n%s\n\n" % (title, "=" * len(title)))
|
||||
fw(".. module:: bpy.types\n\n")
|
||||
file.close()
|
||||
|
||||
# bpy.types and bpy.ops
|
||||
pyrna2sphinx(BASEPATH)
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user