PyDoc: use complete sentences in comments for templates & examples
This commit is contained in:
@@ -8,15 +8,15 @@ This script shows how to use the classes: :class:`Device`, :class:`Sound` and
|
||||
import aud
|
||||
|
||||
device = aud.Device()
|
||||
# load sound file (it can be a video file with audio)
|
||||
# Load sound file (it can be a video file with audio).
|
||||
sound = aud.Sound('music.ogg')
|
||||
|
||||
# play the audio, this return a handle to control play/pause
|
||||
# Play the audio, this return a handle to control play/pause.
|
||||
handle = device.play(sound)
|
||||
# if the audio is not too big and will be used often you can buffer it
|
||||
# If the audio is not too big and will be used often you can buffer it.
|
||||
sound_buffered = aud.Sound.cache(sound)
|
||||
handle_buffered = device.play(sound_buffered)
|
||||
|
||||
# stop the sounds (otherwise they play until their ends)
|
||||
# Stop the sounds (otherwise they play until their ends).
|
||||
handle.stop()
|
||||
handle_buffered.stop()
|
||||
|
||||
@@ -5,7 +5,7 @@ Hello World Text Example
|
||||
Example of using the blf module. For this module to work we
|
||||
need to use the GPU module :mod:`gpu` as well.
|
||||
"""
|
||||
# import stand alone modules
|
||||
# Import stand alone modules.
|
||||
import blf
|
||||
import bpy
|
||||
|
||||
@@ -20,21 +20,21 @@ def init():
|
||||
import os
|
||||
# Create a new font object, use external TTF file.
|
||||
font_path = bpy.path.abspath('//Zeyada.ttf')
|
||||
# Store the font indice - to use later.
|
||||
# Store the font index - to use later.
|
||||
if os.path.exists(font_path):
|
||||
font_info["font_id"] = blf.load(font_path)
|
||||
else:
|
||||
# Default font.
|
||||
font_info["font_id"] = 0
|
||||
|
||||
# set the font drawing routine to run every frame
|
||||
# Set the font drawing routine to run every frame.
|
||||
font_info["handler"] = bpy.types.SpaceView3D.draw_handler_add(
|
||||
draw_callback_px, (None, None), 'WINDOW', 'POST_PIXEL')
|
||||
|
||||
|
||||
def draw_callback_px(self, context):
|
||||
"""Draw on the viewports"""
|
||||
# BLF drawing routine
|
||||
# BLF drawing routine.
|
||||
font_id = font_info["font_id"]
|
||||
blf.position(font_id, 2, 80, 0)
|
||||
blf.size(font_id, 50.0)
|
||||
|
||||
@@ -14,7 +14,7 @@ Below is an example of a mesh that is altered from a handler:
|
||||
|
||||
|
||||
def frame_change_pre(scene):
|
||||
# A triangle that shifts in the z direction
|
||||
# A triangle that shifts in the z direction.
|
||||
zshift = scene.frame_current * 0.1
|
||||
vertices = [(-1, -1, zshift), (1, -1, zshift), (0, 1, zshift)]
|
||||
triangles = [(0, 1, 2)]
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import bpy
|
||||
|
||||
|
||||
# print all objects
|
||||
# Print all objects.
|
||||
for obj in bpy.data.objects:
|
||||
print(obj.name)
|
||||
|
||||
|
||||
# print all scene names in a list
|
||||
# Print all scene names in a list.
|
||||
print(bpy.data.scenes.keys())
|
||||
|
||||
|
||||
# remove mesh Cube
|
||||
# Remove mesh Cube.
|
||||
if "Cube" in bpy.data.meshes:
|
||||
mesh = bpy.data.meshes["Cube"]
|
||||
print("removing mesh", mesh)
|
||||
bpy.data.meshes.remove(mesh)
|
||||
|
||||
|
||||
# write images into a file next to the blend
|
||||
# Write images into a file next to the blend.
|
||||
import os
|
||||
with open(os.path.splitext(bpy.data.filepath)[0] + ".txt", 'w') as fs:
|
||||
for image in bpy.data.images:
|
||||
|
||||
@@ -29,6 +29,6 @@ The execution context is one of:
|
||||
- ``EXEC_SCREEN``
|
||||
"""
|
||||
|
||||
# collection add popup
|
||||
# Collection add popup.
|
||||
import bpy
|
||||
bpy.ops.object.collection_instance_add('INVOKE_DEFAULT')
|
||||
|
||||
@@ -45,10 +45,10 @@ Each of these arguments is optional, but must be given in the order above.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
# calling an operator
|
||||
# Calling an operator.
|
||||
bpy.ops.mesh.subdivide(number_cuts=3, smoothness=0.5)
|
||||
|
||||
|
||||
# check poll() to avoid exception.
|
||||
# Check poll() to avoid exception.
|
||||
if bpy.ops.object.mode_set.poll():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
@@ -19,7 +19,7 @@ bpy.utils.register_class(MaterialSettings)
|
||||
|
||||
bpy.types.Material.my_settings = bpy.props.PointerProperty(type=MaterialSettings)
|
||||
|
||||
# test the new settings work
|
||||
# Test the new settings work.
|
||||
material = bpy.data.materials[0]
|
||||
|
||||
material.my_settings.my_int = 5
|
||||
|
||||
@@ -28,7 +28,7 @@ def set_float(self, value):
|
||||
bpy.types.Scene.test_float = bpy.props.FloatProperty(get=get_float, set=set_float)
|
||||
|
||||
|
||||
# Read-only string property, returns the current date
|
||||
# Read-only string property, returns the current date.
|
||||
def get_date(self):
|
||||
import datetime
|
||||
return str(datetime.datetime.now())
|
||||
@@ -37,9 +37,10 @@ def get_date(self):
|
||||
bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date)
|
||||
|
||||
|
||||
# Boolean array. Set function stores a single boolean value, returned as the second component.
|
||||
# Array getters must return a list or tuple
|
||||
# Array size must match the property vector size exactly
|
||||
# Boolean array.
|
||||
# - Set function stores a single boolean value, returned as the second component.
|
||||
# - Array getters must return a list or tuple.
|
||||
# - Array size must match the property vector size exactly.
|
||||
def get_array(self):
|
||||
return (True, self["somebool"])
|
||||
|
||||
@@ -82,7 +83,7 @@ print('test_float:', scene.test_float)
|
||||
scene.test_array = (True, False)
|
||||
print('test_array:', tuple(scene.test_array))
|
||||
|
||||
# scene.test_date = "blah" # this would fail, property is read-only
|
||||
# scene.test_date = "blah" # This would fail, property is read-only.
|
||||
print('test_date:', scene.test_date)
|
||||
|
||||
scene.test_enum = 'BLUE'
|
||||
|
||||
@@ -2,33 +2,33 @@ import bpy
|
||||
|
||||
filepath = "//link_library.blend"
|
||||
|
||||
# load a single scene we know the name of.
|
||||
# Load a single scene we know the name of.
|
||||
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
||||
data_to.scenes = ["Scene"]
|
||||
|
||||
|
||||
# load all meshes
|
||||
# Load all meshes.
|
||||
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
||||
data_to.meshes = data_from.meshes
|
||||
|
||||
|
||||
# link all objects starting with 'A'
|
||||
# Link all objects starting with "A".
|
||||
with bpy.data.libraries.load(filepath, link=True) as (data_from, data_to):
|
||||
data_to.objects = [name for name in data_from.objects if name.startswith("A")]
|
||||
|
||||
|
||||
# append everything
|
||||
# Append everything.
|
||||
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
||||
for attr in dir(data_to):
|
||||
setattr(data_to, attr, getattr(data_from, attr))
|
||||
|
||||
|
||||
# the loaded objects can be accessed from 'data_to' outside of the context
|
||||
# since loading the data replaces the strings for the datablocks or None
|
||||
# if the datablock could not be loaded.
|
||||
# The loaded objects can be accessed from 'data_to' outside of the context
|
||||
# since loading the data replaces the strings for the data-blocks or None
|
||||
# if the data-block could not be loaded.
|
||||
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
||||
data_to.meshes = data_from.meshes
|
||||
# now operate directly on the loaded data
|
||||
# Now operate directly on the loaded data.
|
||||
for mesh in data_to.meshes:
|
||||
if mesh is not None:
|
||||
print(mesh.name)
|
||||
|
||||
@@ -2,17 +2,17 @@ import bpy
|
||||
|
||||
filepath = "//new_library.blend"
|
||||
|
||||
# write selected objects and their data to a blend file
|
||||
# Write selected objects and their data to a blend file.
|
||||
data_blocks = set(bpy.context.selected_objects)
|
||||
bpy.data.libraries.write(filepath, data_blocks)
|
||||
|
||||
|
||||
# write all meshes starting with a capital letter and
|
||||
# set them with fake-user enabled so they aren't lost on re-saving
|
||||
# Write all meshes starting with a capital letter and
|
||||
# set them with fake-user enabled so they aren't lost on re-saving.
|
||||
data_blocks = {mesh for mesh in bpy.data.meshes if mesh.name[:1].isupper()}
|
||||
bpy.data.libraries.write(filepath, data_blocks, fake_user=True)
|
||||
|
||||
|
||||
# write all materials, textures and node groups to a library
|
||||
# Write all materials, textures and node groups to a library.
|
||||
data_blocks = {*bpy.data.materials, *bpy.data.textures, *bpy.data.node_groups}
|
||||
bpy.data.libraries.write(filepath, data_blocks)
|
||||
|
||||
@@ -16,7 +16,7 @@ def set_pose_matrices(obj, matrix_map):
|
||||
# pbone.matrix = matrix
|
||||
# bpy.context.view_layer.update()
|
||||
|
||||
# Compute and assign local matrix, using the new parent matrix
|
||||
# Compute and assign local matrix, using the new parent matrix.
|
||||
if pbone.parent:
|
||||
pbone.matrix_basis = pbone.bone.convert_local_to_pose(
|
||||
matrix,
|
||||
@@ -32,7 +32,7 @@ def set_pose_matrices(obj, matrix_map):
|
||||
invert=True
|
||||
)
|
||||
else:
|
||||
# Compute the updated pose matrix from local and new parent matrix
|
||||
# Compute the updated pose matrix from local and new parent matrix.
|
||||
if pbone.parent:
|
||||
matrix = pbone.bone.convert_local_to_pose(
|
||||
pbone.matrix_basis,
|
||||
@@ -46,11 +46,11 @@ def set_pose_matrices(obj, matrix_map):
|
||||
pbone.bone.matrix_local,
|
||||
)
|
||||
|
||||
# Recursively process children, passing the new matrix through
|
||||
# Recursively process children, passing the new matrix through.
|
||||
for child in pbone.children:
|
||||
rec(child, matrix)
|
||||
|
||||
# Scan all bone trees from their roots
|
||||
# Scan all bone trees from their roots.
|
||||
for pbone in obj.pose.bones:
|
||||
if not pbone.parent:
|
||||
rec(pbone, None)
|
||||
|
||||
@@ -19,7 +19,7 @@ class OBJECT_OT_simple_exporter(bpy.types.Operator):
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
for object_instance in depsgraph.object_instances:
|
||||
if not self.is_object_instance_from_selected(object_instance):
|
||||
# We only export selected objects
|
||||
# We only export selected objects.
|
||||
continue
|
||||
# NOTE: This will create a mesh for every instance, which is not ideal at all. In
|
||||
# reality destination format will support some sort of instancing mechanism, so the
|
||||
|
||||
@@ -64,7 +64,7 @@ class ShaderScriptImport(bpy.types.Operator, ImportHelper):
|
||||
text_node.filepath = filepath
|
||||
text_node.location = Vector((x, y))
|
||||
|
||||
# Set the node's title to the file name
|
||||
# Set the node's title to the file name.
|
||||
if self.set_label:
|
||||
text_node.label = file.name
|
||||
|
||||
|
||||
@@ -41,14 +41,14 @@ class CustomHydraRenderEngine(bpy.types.HydraRenderEngine):
|
||||
# by implementing the methods like this.
|
||||
def update(self, data, depsgraph):
|
||||
super().update(data, depsgraph)
|
||||
# Do extra work here
|
||||
# Do extra work here.
|
||||
|
||||
def update_render_passes(self, scene, render_layer):
|
||||
if render_layer.use_pass_z:
|
||||
self.register_pass(scene, render_layer, 'Depth', 1, 'Z', 'VALUE')
|
||||
|
||||
|
||||
# Registration
|
||||
# Registration.
|
||||
def register():
|
||||
bpy.utils.register_class(CustomHydraRenderEngine)
|
||||
|
||||
|
||||
@@ -6,12 +6,11 @@ count is used to prevent data being removed when it is used.
|
||||
# This example shows what _not_ to do, and will crash Blender.
|
||||
import bpy
|
||||
|
||||
# object which is in the scene.
|
||||
# Object which is in the scene.
|
||||
obj = bpy.data.objects["Cube"]
|
||||
|
||||
# without this, removal would raise an error.
|
||||
# Without this, removal would raise an error.
|
||||
obj.user_clear()
|
||||
|
||||
# runs without an exception
|
||||
# but will crash on redraw.
|
||||
# Runs without an exception but will crash on redraw.
|
||||
bpy.data.objects.remove(obj)
|
||||
|
||||
@@ -34,5 +34,5 @@ class SubMenu(bpy.types.Menu):
|
||||
|
||||
bpy.utils.register_class(SubMenu)
|
||||
|
||||
# test call to display immediately.
|
||||
# Test call to display immediately.
|
||||
bpy.ops.wm.call_menu(name="OBJECT_MT_select_submenu")
|
||||
|
||||
@@ -29,12 +29,12 @@ class AddPresetObjectDisplay(AddPresetBase, Operator):
|
||||
bl_label = "Add Object Display Preset"
|
||||
preset_menu = "OBJECT_MT_display_presets"
|
||||
|
||||
# variable used for all preset values
|
||||
# Variable used for all preset values.
|
||||
preset_defines = [
|
||||
"obj = bpy.context.object"
|
||||
]
|
||||
|
||||
# properties to store in the preset
|
||||
# Properties to store in the preset.
|
||||
preset_values = [
|
||||
"obj.display_type",
|
||||
"obj.show_bounds",
|
||||
@@ -44,11 +44,11 @@ class AddPresetObjectDisplay(AddPresetBase, Operator):
|
||||
"obj.show_wire",
|
||||
]
|
||||
|
||||
# where to store the preset
|
||||
# Where to store the preset.
|
||||
preset_subdir = "object/display"
|
||||
|
||||
|
||||
# Display into an existing panel
|
||||
# Display into an existing panel.
|
||||
def panel_func(self, context):
|
||||
layout = self.layout
|
||||
|
||||
|
||||
@@ -38,5 +38,5 @@ class BasicMenu(bpy.types.Menu):
|
||||
|
||||
bpy.utils.register_class(BasicMenu)
|
||||
|
||||
# test call to display immediately.
|
||||
# Test call to display immediately.
|
||||
bpy.ops.wm.call_menu(name="OBJECT_MT_select_test")
|
||||
|
||||
@@ -34,7 +34,7 @@ uv_layer = me.uv_layers.active.data
|
||||
for poly in me.polygons:
|
||||
print("Polygon index: {:d}, length: {:d}".format(poly.index, poly.loop_total))
|
||||
|
||||
# range is used here to show how the polygons reference loops,
|
||||
# Range is used here to show how the polygons reference loops,
|
||||
# for convenience 'poly.loop_indices' can be used instead.
|
||||
for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
|
||||
print(" Vertex: {:d}".format(me.loops[loop_index].vertex_index))
|
||||
|
||||
@@ -10,10 +10,10 @@ import bpy
|
||||
|
||||
view_layer = bpy.context.view_layer
|
||||
|
||||
# Create new light datablock.
|
||||
# Create new light data-block.
|
||||
light_data = bpy.data.lights.new(name="New Light", type='POINT')
|
||||
|
||||
# Create new object with our light datablock.
|
||||
# Create new object with our light data-block.
|
||||
light_object = bpy.data.objects.new(name="New Light", object_data=light_data)
|
||||
|
||||
# Link light object to the active collection of current view layer,
|
||||
|
||||
@@ -39,8 +39,8 @@ class SimpleMouseOperator(bpy.types.Operator):
|
||||
y: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
# rather than printing, use the report function,
|
||||
# this way the message appears in the header,
|
||||
# Rather than printing, use the report function,
|
||||
# this way the message appears in the header.
|
||||
self.report({'INFO'}, "Mouse coords are {:d} {:d}".format(self.x, self.y))
|
||||
return {'FINISHED'}
|
||||
|
||||
@@ -55,13 +55,13 @@ def menu_func(self, context):
|
||||
self.layout.operator(SimpleMouseOperator.bl_idname, text="Simple Mouse Operator")
|
||||
|
||||
|
||||
# Register and add to the view menu (required to also use F3 search "Simple Mouse Operator" for quick access)
|
||||
# Register and add to the view menu (required to also use F3 search "Simple Mouse Operator" for quick access).
|
||||
bpy.utils.register_class(SimpleMouseOperator)
|
||||
bpy.types.VIEW3D_MT_view.append(menu_func)
|
||||
|
||||
# Test call to the newly defined operator.
|
||||
# Here we call the operator and invoke it, meaning that the settings are taken
|
||||
# from the mouse.
|
||||
# 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.
|
||||
|
||||
@@ -43,10 +43,10 @@ def menu_func(self, context):
|
||||
self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")
|
||||
|
||||
|
||||
# Register and add to the file selector (required to also use F3 search "Text Export Operator" for quick access)
|
||||
# Register and add to the file selector (required to also use F3 search "Text Export Operator" for quick access).
|
||||
bpy.utils.register_class(ExportSomeData)
|
||||
bpy.types.TOPBAR_MT_file_export.append(menu_func)
|
||||
|
||||
|
||||
# test call
|
||||
# Test call.
|
||||
bpy.ops.export.some_data('INVOKE_DEFAULT')
|
||||
|
||||
@@ -32,7 +32,7 @@ def menu_func(self, context):
|
||||
self.layout.operator(DialogOperator.bl_idname, text="Dialog Operator")
|
||||
|
||||
|
||||
# Register and add to the object menu (required to also use F3 search "Dialog Operator" for quick access)
|
||||
# Register and add to the object menu (required to also use F3 search "Dialog Operator" for quick access).
|
||||
bpy.utils.register_class(DialogOperator)
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
||||
|
||||
@@ -51,5 +51,5 @@ def menu_func(self, context):
|
||||
bpy.utils.register_class(CustomDrawOperator)
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
||||
# test call
|
||||
# Test call.
|
||||
bpy.ops.object.custom_draw('INVOKE_DEFAULT')
|
||||
|
||||
@@ -43,12 +43,12 @@ class ModalOperator(bpy.types.Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
def modal(self, context, event):
|
||||
if event.type == 'MOUSEMOVE': # Apply
|
||||
if event.type == 'MOUSEMOVE': # Apply.
|
||||
self.value = event.mouse_x
|
||||
self.execute(context)
|
||||
elif event.type == 'LEFTMOUSE': # Confirm
|
||||
elif event.type == 'LEFTMOUSE': # Confirm.
|
||||
return {'FINISHED'}
|
||||
elif event.type in {'RIGHTMOUSE', 'ESC'}: # Cancel
|
||||
elif event.type in {'RIGHTMOUSE', 'ESC'}: # Cancel.
|
||||
# Revert all changes that have been made
|
||||
context.object.location.x = self.init_loc_x
|
||||
return {'CANCELLED'}
|
||||
@@ -73,5 +73,5 @@ def menu_func(self, context):
|
||||
bpy.utils.register_class(ModalOperator)
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
||||
# test call
|
||||
# Test call.
|
||||
bpy.ops.object.modal_operator('INVOKE_DEFAULT')
|
||||
|
||||
@@ -37,9 +37,9 @@ def menu_func(self, context):
|
||||
self.layout.operator(SearchEnumOperator.bl_idname, text="Search Enum Operator")
|
||||
|
||||
|
||||
# Register and add to the object menu (required to also use F3 search "Search Enum Operator" for quick access)
|
||||
# Register and add to the object menu (required to also use F3 search "Search Enum Operator" for quick access).
|
||||
bpy.utils.register_class(SearchEnumOperator)
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
||||
# test call
|
||||
# Test call.
|
||||
bpy.ops.object.search_enum_operator('INVOKE_DEFAULT')
|
||||
|
||||
@@ -12,7 +12,7 @@ def bbone_deform_matrix(pose_bone, point):
|
||||
pose1 = pose_bone.bbone_segment_matrix(index, rest=False)
|
||||
deform1 = pose1 @ rest1.inverted()
|
||||
|
||||
# bbone_segment_index ensures that index + 1 is always valid
|
||||
# `bbone_segment_index` ensures that index + 1 is always valid
|
||||
rest2 = pose_bone.bbone_segment_matrix(index + 1, rest=True)
|
||||
pose2 = pose_bone.bbone_segment_matrix(index + 1, rest=False)
|
||||
deform2 = pose2 @ rest2.inverted()
|
||||
|
||||
@@ -37,5 +37,5 @@ bpy.utils.register_class(MyPropertyGroup)
|
||||
bpy.types.Object.my_prop_grp = bpy.props.PointerProperty(type=MyPropertyGroup)
|
||||
|
||||
|
||||
# test this worked
|
||||
# Test this worked.
|
||||
bpy.data.objects[0].my_prop_grp.custom_1 = 22.0
|
||||
|
||||
@@ -125,14 +125,14 @@ class CustomDrawData:
|
||||
def __init__(self, dimensions):
|
||||
import gpu
|
||||
|
||||
# Generate dummy float image buffer
|
||||
# Generate dummy float image buffer.
|
||||
self.dimensions = dimensions
|
||||
width, height = dimensions
|
||||
|
||||
pixels = width * height * array.array('f', [0.1, 0.2, 0.1, 1.0])
|
||||
pixels = gpu.types.Buffer('FLOAT', width * height * 4, pixels)
|
||||
|
||||
# Generate texture
|
||||
# Generate texture.
|
||||
self.texture = gpu.types.GPUTexture((width, height), format='RGBA16F', data=pixels)
|
||||
|
||||
# Note: This is just a didactic example.
|
||||
@@ -167,7 +167,7 @@ def get_panels():
|
||||
|
||||
|
||||
def register():
|
||||
# Register the RenderEngine
|
||||
# Register the RenderEngine.
|
||||
bpy.utils.register_class(CustomRenderEngine)
|
||||
|
||||
for panel in get_panels():
|
||||
|
||||
@@ -60,7 +60,7 @@ class UIListPanelExample1(bpy.types.Panel):
|
||||
|
||||
obj = context.object
|
||||
|
||||
# template_list now takes two new args.
|
||||
# `template_list` now takes two new arguments.
|
||||
# The first one is the identifier of the registered UIList to use (if you want only the default list,
|
||||
# with no custom draw code, use "UI_UL_list").
|
||||
layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
|
||||
|
||||
@@ -10,11 +10,11 @@ import bpy
|
||||
|
||||
|
||||
class MESH_UL_vgroups_slow(bpy.types.UIList):
|
||||
# Constants (flags)
|
||||
# Constants (flags).
|
||||
# Be careful not to shadow FILTER_ITEM!
|
||||
VGROUP_EMPTY = 1 << 0
|
||||
|
||||
# Custom properties, saved with .blend file.
|
||||
# Custom properties, saved with `.blend` file.
|
||||
use_filter_empty: bpy.props.BoolProperty(
|
||||
name="Filter Empty",
|
||||
default=False,
|
||||
@@ -151,10 +151,10 @@ class MESH_UL_vgroups_slow(bpy.types.UIList):
|
||||
flt_flags = []
|
||||
flt_neworder = []
|
||||
|
||||
# Pre-compute of vgroups data, CPU-intensive. :/
|
||||
# Pre-compute of vertex-groups data, unfortunately this is CPU-intensive.
|
||||
vgroups_empty = self.filter_items_empty_vgroups(context, vgroups)
|
||||
|
||||
# Filtering by name
|
||||
# Filtering by name.
|
||||
if self.filter_name:
|
||||
flt_flags = helper_funcs.filter_items_by_name(self.filter_name, self.bitflag_filter_item, vgroups, "name",
|
||||
reverse=self.use_filter_name_reverse)
|
||||
@@ -193,7 +193,7 @@ class UIListPanelExample2(bpy.types.Panel):
|
||||
layout = self.layout
|
||||
obj = context.object
|
||||
|
||||
# template_list now takes two new args.
|
||||
# `template_list` now takes two new arguments.
|
||||
# The first one is the identifier of the registered UIList to use (if you want only the default list,
|
||||
# with no custom draw code, use "UI_UL_list").
|
||||
layout.template_list("MESH_UL_vgroups_slow", "", obj, "vertex_groups", obj.vertex_groups, "active_index")
|
||||
|
||||
@@ -5,6 +5,6 @@ Multi-dimensional arrays (like array of vectors) will be flattened into seq.
|
||||
|
||||
collection.foreach_get(attr, some_seq)
|
||||
|
||||
# Python equivalent
|
||||
# Python equivalent.
|
||||
for i in range(len(seq)):
|
||||
some_seq[i] = getattr(collection[i], attr)
|
||||
|
||||
@@ -5,6 +5,6 @@ seq must be uni-dimensional, multi-dimensional arrays (like array of vectors) wi
|
||||
|
||||
collection.foreach_set(attr, some_seq)
|
||||
|
||||
# Python equivalent
|
||||
# Python equivalent.
|
||||
for i in range(len(some_seq)):
|
||||
setattr(collection[i], attr, some_seq[i])
|
||||
|
||||
@@ -6,6 +6,6 @@ import bpy
|
||||
|
||||
obj = bpy.context.object
|
||||
|
||||
# set the keyframe at frame 1
|
||||
# Set the keyframe at frame 1.
|
||||
obj.location = (3.0, 4.0, 10.0)
|
||||
obj.keyframe_insert(data_path="location", frame=1)
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
Custom compute shader (using image store) and vertex/fragment shader
|
||||
--------------------------------------------------------------------
|
||||
|
||||
This is an example of how to use a custom compute shader to write to a texture and then use that texture in a vertex/fragment shader.
|
||||
The expected result is a 2x2 plane (size of the default cube), which changes color from a green-black gradient to a green-red gradient,
|
||||
This is an example of how to use a custom compute shader
|
||||
to write to a texture and then use that texture in a vertex/fragment shader.
|
||||
The expected result is a 2x2 plane (size of the default cube),
|
||||
which changes color from a green-black gradient to a green-red gradient,
|
||||
based on current time.
|
||||
"""
|
||||
import bpy
|
||||
@@ -17,7 +19,7 @@ start_time = time.time()
|
||||
size = 128
|
||||
texture = gpu.types.GPUTexture((size, size), format='RGBA32F')
|
||||
|
||||
# Create the compute shader to write to the texture
|
||||
# Create the compute shader to write to the texture.
|
||||
compute_shader_info = gpu.types.GPUShaderCreateInfo()
|
||||
compute_shader_info.image(0, 'RGBA32F', "FLOAT_2D", "img_output", qualifiers={"WRITE"})
|
||||
compute_shader_info.compute_source('''
|
||||
@@ -35,7 +37,7 @@ compute_shader_info.push_constant('FLOAT', "time")
|
||||
compute_shader_info.local_group_size(1, 1)
|
||||
compute_shader = gpu.shader.create_from_info(compute_shader_info)
|
||||
|
||||
# Create the shader to draw the texture
|
||||
# Create the shader to draw the texture.
|
||||
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
|
||||
vert_out.smooth('VEC2', "uvInterp")
|
||||
shader_info = gpu.types.GPUShaderCreateInfo()
|
||||
|
||||
@@ -22,7 +22,7 @@ with offscreen.bind():
|
||||
fb = gpu.state.active_framebuffer_get()
|
||||
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
||||
with gpu.matrix.push_pop():
|
||||
# reset matrices -> use normalized device coordinates [-1, 1]
|
||||
# Reset matrices -> use normalized device coordinates [-1, 1].
|
||||
gpu.matrix.load_matrix(Matrix.Identity(4))
|
||||
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ with offscreen.bind():
|
||||
fb = gpu.state.active_framebuffer_get()
|
||||
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
||||
with gpu.matrix.push_pop():
|
||||
# reset matrices -> use normalized device coordinates [-1, 1]
|
||||
# Reset matrices -> use normalized device coordinates [-1, 1].
|
||||
gpu.matrix.load_matrix(Matrix.Identity(4))
|
||||
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
||||
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import mathutils
|
||||
|
||||
# color values are represented as RGB values from 0 - 1, this is blue
|
||||
# Color values are represented as RGB values from 0 - 1, this is blue.
|
||||
col = mathutils.Color((0.0, 0.0, 1.0))
|
||||
|
||||
# as well as r/g/b attribute access you can adjust them by h/s/v
|
||||
# As well as r/g/b attribute access you can adjust them by h/s/v.
|
||||
col.s *= 0.5
|
||||
|
||||
# you can access its components by attribute or index
|
||||
# You can access its components by attribute or index.
|
||||
print("Color R:", col.r)
|
||||
print("Color G:", col[1])
|
||||
print("Color B:", col[-1])
|
||||
print("Color HSV: {:.2f}, {:.2f}, {:.2f}".format(*col))
|
||||
|
||||
|
||||
# components of an existing color can be set
|
||||
# Components of an existing color can be set.
|
||||
col[:] = 0.0, 0.5, 1.0
|
||||
|
||||
# components of an existing color can use slice notation to get a tuple
|
||||
# Components of an existing color can use slice notation to get a tuple.
|
||||
print("Values: {:f}, {:f}, {:f}".format(*col))
|
||||
|
||||
# colors can be added and subtracted
|
||||
# Colors can be added and subtracted.
|
||||
col += mathutils.Color((0.25, 0.0, 0.0))
|
||||
|
||||
# Color can be multiplied, in this example color is scaled to 0-255
|
||||
# can printed as integers
|
||||
# can printed as integers.
|
||||
print("Color: {:d}, {:d}, {:d}".format(*(int(c) for c in (col * 255.0))))
|
||||
|
||||
# This example prints the color as hexadecimal
|
||||
# This example prints the color as hexadecimal.
|
||||
print("Hexadecimal: {:02x}{:02x}{:02x}".format(int(col.r * 255), int(col.g * 255), int(col.b * 255)))
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
import mathutils
|
||||
import math
|
||||
|
||||
# create a new euler with default axis rotation order
|
||||
# Create a new euler with default axis rotation order.
|
||||
eul = mathutils.Euler((0.0, math.radians(45.0), 0.0), 'XYZ')
|
||||
|
||||
# rotate the euler
|
||||
# Rotate the euler.
|
||||
eul.rotate_axis('Z', math.radians(10.0))
|
||||
|
||||
# you can access its components by attribute or index
|
||||
# You can access its components by attribute or index.
|
||||
print("Euler X", eul.x)
|
||||
print("Euler Y", eul[1])
|
||||
print("Euler Z", eul[-1])
|
||||
|
||||
# components of an existing euler can be set
|
||||
# Components of an existing euler can be set.
|
||||
eul[:] = 1.0, 2.0, 3.0
|
||||
|
||||
# components of an existing euler can use slice notation to get a tuple
|
||||
# Components of an existing euler can use slice notation to get a tuple.
|
||||
print("Values: {:f}, {:f}, {:f}".format(*eul))
|
||||
|
||||
# the order can be set at any time too
|
||||
# The order can be set at any time too.
|
||||
eul.order = 'ZYX'
|
||||
|
||||
# eulers can be used to rotate vectors
|
||||
# Eulers can be used to rotate vectors.
|
||||
vec = mathutils.Vector((0.0, 0.0, 1.0))
|
||||
vec.rotate(eul)
|
||||
|
||||
# often its useful to convert the euler into a matrix so it can be used as
|
||||
# transformations with more flexibility
|
||||
# Often its useful to convert the euler into a matrix so it can be used as
|
||||
# transformations with more flexibility.
|
||||
mat_rot = eul.to_matrix()
|
||||
mat_loc = mathutils.Matrix.Translation((2.0, 3.0, 4.0))
|
||||
mat = mat_loc @ mat_rot.to_4x4()
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import mathutils
|
||||
import math
|
||||
|
||||
# a new rotation 90 degrees about the Y axis
|
||||
# A new rotation 90 degrees about the Y axis.
|
||||
quat_a = mathutils.Quaternion((0.7071068, 0.0, 0.7071068, 0.0))
|
||||
|
||||
# passing values to Quaternion's directly can be confusing so axis, angle
|
||||
# is supported for initializing too
|
||||
# Passing values to Quaternion's directly can be confusing so axis, angle
|
||||
# is supported for initializing too.
|
||||
quat_b = mathutils.Quaternion((0.0, 1.0, 0.0), math.radians(90.0))
|
||||
|
||||
print("Check quaternions match", quat_a == quat_b)
|
||||
|
||||
# like matrices, quaternions can be multiplied to accumulate rotational values
|
||||
# Like matrices, quaternions can be multiplied to accumulate rotational values.
|
||||
quat_a = mathutils.Quaternion((0.0, 1.0, 0.0), math.radians(90.0))
|
||||
quat_b = mathutils.Quaternion((0.0, 0.0, 1.0), math.radians(45.0))
|
||||
quat_out = quat_a @ quat_b
|
||||
|
||||
# print the quat, euler degrees for mere mortals and (axis, angle)
|
||||
# Print the quaternion, euler degrees for mere mortals and (axis, angle).
|
||||
print("Final Rotation:")
|
||||
print(quat_out)
|
||||
print("{:.2f}, {:.2f}, {:.2f}".format(*(math.degrees(a) for a in quat_out.to_euler())))
|
||||
print("({:.2f}, {:.2f}, {:.2f}), {:.2f}".format(*quat_out.axis, math.degrees(quat_out.angle)))
|
||||
|
||||
# multiple rotations can be interpolated using the exponential map
|
||||
# Multiple rotations can be interpolated using the exponential map.
|
||||
quat_c = mathutils.Quaternion((1.0, 0.0, 0.0), math.radians(15.0))
|
||||
exp_avg = (quat_a.to_exponential_map() +
|
||||
quat_b.to_exponential_map() +
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import mathutils
|
||||
|
||||
# zero length vector
|
||||
# Zero length vector.
|
||||
vec = mathutils.Vector((0.0, 0.0, 1.0))
|
||||
|
||||
# unit length vector
|
||||
# Unit length vector.
|
||||
vec_a = vec.normalized()
|
||||
|
||||
vec_b = mathutils.Vector((0.0, 1.0, 2.0))
|
||||
@@ -29,7 +29,7 @@ vec_a < vec_b
|
||||
vec_a <= vec_b
|
||||
|
||||
|
||||
# Math can be performed on Vector classes
|
||||
# Math can be performed on Vector classes.
|
||||
vec_a + vec_b
|
||||
vec_a - vec_b
|
||||
vec_a @ vec_b
|
||||
@@ -39,7 +39,7 @@ quat @ vec_a
|
||||
-vec_a
|
||||
|
||||
|
||||
# You can access a vector object like a sequence
|
||||
# You can access a vector object like a sequence.
|
||||
x = vec_a[0]
|
||||
len(vec)
|
||||
vec_a[:] = vec_b
|
||||
@@ -47,7 +47,7 @@ vec_a[:] = 1.0, 2.0, 3.0
|
||||
vec2d[:] = vec3d[:2]
|
||||
|
||||
|
||||
# Vectors support 'swizzle' operations
|
||||
# Vectors support 'swizzle' operations.
|
||||
# See https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)
|
||||
vec.xyz = vec.zyx
|
||||
vec.xy = vec4d.zw
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import mathutils
|
||||
|
||||
# create a kd-tree from a mesh
|
||||
# Create a KD-tree from a mesh.
|
||||
from bpy import context
|
||||
obj = context.object
|
||||
|
||||
@@ -14,21 +14,21 @@ for i, v in enumerate(mesh.vertices):
|
||||
kd.balance()
|
||||
|
||||
|
||||
# Find the closest point to the center
|
||||
# Find the closest point to the center.
|
||||
co_find = (0.0, 0.0, 0.0)
|
||||
co, index, dist = kd.find(co_find)
|
||||
print("Close to center:", co, index, dist)
|
||||
|
||||
# 3d cursor relative to the object data
|
||||
# 3D cursor relative to the object data.
|
||||
co_find = obj.matrix_world.inverted() @ context.scene.cursor.location
|
||||
|
||||
# Find the closest 10 points to the 3d cursor
|
||||
# Find the closest 10 points to the 3D cursor.
|
||||
print("Close 10 points")
|
||||
for (co, index, dist) in kd.find_n(co_find, 10):
|
||||
print(" ", co, index, dist)
|
||||
|
||||
|
||||
# Find points within a radius of the 3d cursor
|
||||
# Find points within a radius of the 3D cursor.
|
||||
print("Close points within 0.5 distance")
|
||||
for (co, index, dist) in kd.find_range(co_find, 0.5):
|
||||
print(" ", co, index, dist)
|
||||
|
||||
@@ -902,12 +902,12 @@ including advanced features.
|
||||
|
||||
import bgl
|
||||
xval, yval= 100, 40
|
||||
# Get the scale of the view matrix
|
||||
# Get the scale of the view matrix.
|
||||
view_matrix = bgl.Buffer(bgl.GL_FLOAT, 16)
|
||||
bgl.glGetFloatv(bgl.GL_MODELVIEW_MATRIX, view_matrix)
|
||||
f = 1.0 / view_matrix[0]
|
||||
|
||||
# Instead of the usual glRasterPos2i(xval, yval)
|
||||
# Instead of the usual `glRasterPos2i(xval, yval)`.
|
||||
bgl.glRasterPos2f(xval * f, yval * f)
|
||||
|
||||
|
||||
|
||||
@@ -104,11 +104,11 @@ Here are some examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# in this example the active vertex group index is used,
|
||||
# this is stored in the object, not the BMesh
|
||||
# In this example the active vertex group index is used,
|
||||
# this is stored in the object, not the `BMesh`.
|
||||
group_index = obj.vertex_groups.active_index
|
||||
|
||||
# only ever one deform weight layer
|
||||
# Only ever one deform weight layer.
|
||||
dvert_lay = bm.verts.layers.deform.active
|
||||
|
||||
for vert in bm.verts:
|
||||
|
||||
@@ -149,13 +149,13 @@ Rather than:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
polygons = mesh.polygons[:] # make a list copy of the meshes polygons
|
||||
p_idx = len(polygons) # Loop backwards
|
||||
while p_idx: # while the value is not 0
|
||||
polygons = mesh.polygons[:] # Make a list copy of the meshes polygons.
|
||||
p_idx = len(polygons) # Loop backwards
|
||||
while p_idx: # While the value is not 0.
|
||||
p_idx -= 1
|
||||
|
||||
if len(polygons[p_idx].vertices) == 3:
|
||||
polygons.pop(p_idx) # remove the triangle
|
||||
polygons.pop(p_idx) # Remove the triangle.
|
||||
|
||||
|
||||
It's faster to build a new list with list comprehension:
|
||||
@@ -227,10 +227,10 @@ This works by swapping two list items, so the item you remove is always last:
|
||||
|
||||
pop_index = 5
|
||||
|
||||
# swap so the pop_index is last.
|
||||
# Swap so the pop_index is last.
|
||||
my_list[-1], my_list[pop_index] = my_list[pop_index], my_list[-1]
|
||||
|
||||
# remove last item (pop_index)
|
||||
# Remove last item (pop_index).
|
||||
my_list.pop()
|
||||
|
||||
|
||||
@@ -357,6 +357,6 @@ While developing a script it is good to time it to be aware of any changes in pe
|
||||
import time
|
||||
time_start = time.time()
|
||||
|
||||
# do something...
|
||||
# Do something...
|
||||
|
||||
print("My Script Finished: %.4f sec" % (time.time() - time_start))
|
||||
|
||||
@@ -67,10 +67,10 @@ Examples using :class:`bpy.types.PoseBone` in Object or Pose-Mode:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Gets the name of the first constraint (if it exists)
|
||||
# Gets the name of the first constraint (if it exists).
|
||||
bpy.context.object.pose.bones["Bone"].constraints[0].name
|
||||
|
||||
# Gets the last selected pose bone (Pose-Mode only)
|
||||
# Gets the last selected pose bone (Pose-Mode only).
|
||||
bpy.context.active_pose_bone
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ Here is an example of threading supported by Blender:
|
||||
def prod():
|
||||
print(threading.current_thread().name, "Starting")
|
||||
|
||||
# do something vaguely useful
|
||||
# Do something vaguely useful.
|
||||
import bpy
|
||||
from mathutils import Vector
|
||||
from random import random
|
||||
@@ -28,7 +28,7 @@ Here is an example of threading supported by Blender:
|
||||
print("Prodding", prod_vec)
|
||||
bpy.data.objects["Cube"].location += prod_vec
|
||||
time.sleep(random() + 1.0)
|
||||
# finish
|
||||
# Finish.
|
||||
|
||||
print(threading.current_thread().name, "Exiting")
|
||||
|
||||
@@ -256,7 +256,7 @@ Only the reference to the data itself can be re-accessed, the following example
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
# this will crash
|
||||
# This will crash!
|
||||
print(polygons)
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ the following example shows how to avoid the crash above.
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
# polygons have been re-allocated
|
||||
# Polygons have been re-allocated.
|
||||
polygons = mesh.polygons
|
||||
print(polygons)
|
||||
|
||||
@@ -291,7 +291,7 @@ internally the array which stores this data is re-allocated.
|
||||
point = bpy.context.object.data.splines[0].bezier_points[0]
|
||||
bpy.context.object.data.splines[0].bezier_points.add()
|
||||
|
||||
# this will crash!
|
||||
# This will crash!
|
||||
point.co = 1.0, 2.0, 3.0
|
||||
|
||||
This can be avoided by re-assigning the point variables after adding the new one or by storing
|
||||
@@ -315,9 +315,9 @@ The following example shows how this precaution works:
|
||||
.. code-block:: python
|
||||
|
||||
mesh = bpy.data.meshes.new(name="MyMesh")
|
||||
# normally the script would use the mesh here...
|
||||
# Normally the script would use the mesh here.
|
||||
bpy.data.meshes.remove(mesh)
|
||||
print(mesh.name) # <- give an exception rather than crashing:
|
||||
print(mesh.name) # <- Give an exception rather than crashing:
|
||||
|
||||
# ReferenceError: StructRNA of type Mesh has been removed
|
||||
|
||||
@@ -330,7 +330,7 @@ the next example will still crash:
|
||||
mesh = bpy.data.meshes.new(name="MyMesh")
|
||||
vertices = mesh.vertices
|
||||
bpy.data.meshes.remove(mesh)
|
||||
print(vertices) # <- this may crash
|
||||
print(vertices) # <- This may crash.
|
||||
|
||||
|
||||
Unfortunate Corner Cases
|
||||
|
||||
@@ -42,7 +42,7 @@ This can cause bugs when you add data (normally imported) then reference it late
|
||||
|
||||
bpy.data.meshes.new(name=meshid)
|
||||
|
||||
# normally some code, function calls...
|
||||
# Normally some code, function calls, etc.
|
||||
bpy.data.meshes[meshid]
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ Or with name assignment:
|
||||
|
||||
obj.name = objname
|
||||
|
||||
# normally some code, function calls...
|
||||
# Normally some code, function calls, etc.
|
||||
obj = bpy.data.meshes[objname]
|
||||
|
||||
|
||||
@@ -69,15 +69,15 @@ this way you don't run this risk of referencing existing data from the blend-fil
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# typically declared in the main body of the function.
|
||||
# Typically declared in the main body of the function.
|
||||
mesh_name_mapping = {}
|
||||
|
||||
mesh = bpy.data.meshes.new(name=meshid)
|
||||
mesh_name_mapping[meshid] = mesh
|
||||
|
||||
# normally some code, or function calls...
|
||||
# Normally some code, or function calls, etc.
|
||||
|
||||
# use own dictionary rather than bpy.data
|
||||
# Use own dictionary rather than `bpy.data`.
|
||||
mesh = mesh_name_mapping[meshid]
|
||||
|
||||
|
||||
@@ -96,18 +96,18 @@ If you need to select between local and library data, there is a feature in ``bp
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# typical name lookup, could be local or library.
|
||||
# Typical name lookup, could be local or library.
|
||||
obj = bpy.data.objects["my_obj"]
|
||||
|
||||
# library object name look up using a pair
|
||||
# where the second argument is the library path matching bpy.types.Library.filepath
|
||||
# Library object name lookup using a pair,
|
||||
# where the second argument is the library path matching bpy.types.Library.filepath.
|
||||
obj = bpy.data.objects["my_obj", "//my_lib.blend"]
|
||||
|
||||
# local object name look up using a pair
|
||||
# Local object name look up using a pair,
|
||||
# where the second argument excludes library data from being returned.
|
||||
obj = bpy.data.objects["my_obj", None]
|
||||
|
||||
# both the examples above also works for 'get'
|
||||
# Both the examples above also works for `get`.
|
||||
obj = bpy.data.objects.get(("my_obj", None))
|
||||
|
||||
|
||||
|
||||
@@ -362,7 +362,7 @@ For example, if you want to store material settings for a custom engine:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Create new property
|
||||
# Create new property:
|
||||
# bpy.data.materials[0].my_custom_props.my_float
|
||||
import bpy
|
||||
|
||||
@@ -389,7 +389,7 @@ For example, if you want to store material settings for a custom engine:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Create new property group with a sub property
|
||||
# Create new property group with a sub property:
|
||||
# bpy.data.materials[0].my_custom_props.sub_group.my_float
|
||||
import bpy
|
||||
|
||||
@@ -428,9 +428,9 @@ For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# add a new property to an existing type
|
||||
# Add a new property to an existing type.
|
||||
bpy.types.Object.my_float: bpy.props.FloatProperty()
|
||||
# remove
|
||||
# Remove it.
|
||||
del bpy.types.Object.my_float
|
||||
|
||||
This works just as well for ``PropertyGroup`` subclasses you define yourself.
|
||||
|
||||
@@ -182,7 +182,7 @@ This data is saved with the blend-file and copied with objects, for example:
|
||||
# which can have a fallback value.
|
||||
value = bpy.data.scenes["Scene"].get("test_prop", "fallback value")
|
||||
|
||||
# dictionaries can be assigned as long as they only use basic types.
|
||||
# Dictionaries can be assigned as long as they only use basic types.
|
||||
collection = bpy.data.collections.new("MyTestCollection")
|
||||
collection["MySettings"] = {"foo": 10, "bar": "spam", "baz": {}}
|
||||
|
||||
@@ -363,10 +363,10 @@ so these are accessed as normal Python types.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# setting multiple snap targets
|
||||
# Setting multiple snap targets.
|
||||
bpy.context.scene.tool_settings.snap_elements_base = {'VERTEX', 'EDGE'}
|
||||
|
||||
# passing as an operator argument for report types
|
||||
# Passing as an operator argument for report types.
|
||||
self.report({'WARNING', 'INFO'}, "Some message!")
|
||||
|
||||
|
||||
@@ -411,10 +411,10 @@ Example of a matrix, vector multiplication:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# modifies the Z axis in place.
|
||||
# Modifies the Z axis in place.
|
||||
bpy.context.object.location.z += 2.0
|
||||
|
||||
# location variable holds a reference to the object too.
|
||||
# Location variable holds a reference to the object too.
|
||||
location = bpy.context.object.location
|
||||
location *= 2.0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user