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
|
import aud
|
||||||
|
|
||||||
device = aud.Device()
|
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')
|
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)
|
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)
|
sound_buffered = aud.Sound.cache(sound)
|
||||||
handle_buffered = device.play(sound_buffered)
|
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.stop()
|
||||||
handle_buffered.stop()
|
handle_buffered.stop()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Hello World Text Example
|
|||||||
Example of using the blf module. For this module to work we
|
Example of using the blf module. For this module to work we
|
||||||
need to use the GPU module :mod:`gpu` as well.
|
need to use the GPU module :mod:`gpu` as well.
|
||||||
"""
|
"""
|
||||||
# import stand alone modules
|
# Import stand alone modules.
|
||||||
import blf
|
import blf
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
@@ -20,21 +20,21 @@ def init():
|
|||||||
import os
|
import os
|
||||||
# Create a new font object, use external TTF file.
|
# Create a new font object, use external TTF file.
|
||||||
font_path = bpy.path.abspath('//Zeyada.ttf')
|
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):
|
if os.path.exists(font_path):
|
||||||
font_info["font_id"] = blf.load(font_path)
|
font_info["font_id"] = blf.load(font_path)
|
||||||
else:
|
else:
|
||||||
# Default font.
|
# Default font.
|
||||||
font_info["font_id"] = 0
|
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(
|
font_info["handler"] = bpy.types.SpaceView3D.draw_handler_add(
|
||||||
draw_callback_px, (None, None), 'WINDOW', 'POST_PIXEL')
|
draw_callback_px, (None, None), 'WINDOW', 'POST_PIXEL')
|
||||||
|
|
||||||
|
|
||||||
def draw_callback_px(self, context):
|
def draw_callback_px(self, context):
|
||||||
"""Draw on the viewports"""
|
"""Draw on the viewports"""
|
||||||
# BLF drawing routine
|
# BLF drawing routine.
|
||||||
font_id = font_info["font_id"]
|
font_id = font_info["font_id"]
|
||||||
blf.position(font_id, 2, 80, 0)
|
blf.position(font_id, 2, 80, 0)
|
||||||
blf.size(font_id, 50.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):
|
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
|
zshift = scene.frame_current * 0.1
|
||||||
vertices = [(-1, -1, zshift), (1, -1, zshift), (0, 1, zshift)]
|
vertices = [(-1, -1, zshift), (1, -1, zshift), (0, 1, zshift)]
|
||||||
triangles = [(0, 1, 2)]
|
triangles = [(0, 1, 2)]
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
|
|
||||||
# print all objects
|
# Print all objects.
|
||||||
for obj in bpy.data.objects:
|
for obj in bpy.data.objects:
|
||||||
print(obj.name)
|
print(obj.name)
|
||||||
|
|
||||||
|
|
||||||
# print all scene names in a list
|
# Print all scene names in a list.
|
||||||
print(bpy.data.scenes.keys())
|
print(bpy.data.scenes.keys())
|
||||||
|
|
||||||
|
|
||||||
# remove mesh Cube
|
# Remove mesh Cube.
|
||||||
if "Cube" in bpy.data.meshes:
|
if "Cube" in bpy.data.meshes:
|
||||||
mesh = bpy.data.meshes["Cube"]
|
mesh = bpy.data.meshes["Cube"]
|
||||||
print("removing mesh", mesh)
|
print("removing mesh", mesh)
|
||||||
bpy.data.meshes.remove(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
|
import os
|
||||||
with open(os.path.splitext(bpy.data.filepath)[0] + ".txt", 'w') as fs:
|
with open(os.path.splitext(bpy.data.filepath)[0] + ".txt", 'w') as fs:
|
||||||
for image in bpy.data.images:
|
for image in bpy.data.images:
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ The execution context is one of:
|
|||||||
- ``EXEC_SCREEN``
|
- ``EXEC_SCREEN``
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# collection add popup
|
# Collection add popup.
|
||||||
import bpy
|
import bpy
|
||||||
bpy.ops.object.collection_instance_add('INVOKE_DEFAULT')
|
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
|
import bpy
|
||||||
|
|
||||||
# calling an operator
|
# Calling an operator.
|
||||||
bpy.ops.mesh.subdivide(number_cuts=3, smoothness=0.5)
|
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():
|
if bpy.ops.object.mode_set.poll():
|
||||||
bpy.ops.object.mode_set(mode='EDIT')
|
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)
|
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 = bpy.data.materials[0]
|
||||||
|
|
||||||
material.my_settings.my_int = 5
|
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)
|
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):
|
def get_date(self):
|
||||||
import datetime
|
import datetime
|
||||||
return str(datetime.datetime.now())
|
return str(datetime.datetime.now())
|
||||||
@@ -37,9 +37,10 @@ def get_date(self):
|
|||||||
bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date)
|
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.
|
# Boolean array.
|
||||||
# Array getters must return a list or tuple
|
# - Set function stores a single boolean value, returned as the second component.
|
||||||
# Array size must match the property vector size exactly
|
# - Array getters must return a list or tuple.
|
||||||
|
# - Array size must match the property vector size exactly.
|
||||||
def get_array(self):
|
def get_array(self):
|
||||||
return (True, self["somebool"])
|
return (True, self["somebool"])
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ print('test_float:', scene.test_float)
|
|||||||
scene.test_array = (True, False)
|
scene.test_array = (True, False)
|
||||||
print('test_array:', tuple(scene.test_array))
|
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)
|
print('test_date:', scene.test_date)
|
||||||
|
|
||||||
scene.test_enum = 'BLUE'
|
scene.test_enum = 'BLUE'
|
||||||
|
|||||||
@@ -2,33 +2,33 @@ import bpy
|
|||||||
|
|
||||||
filepath = "//link_library.blend"
|
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):
|
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
||||||
data_to.scenes = ["Scene"]
|
data_to.scenes = ["Scene"]
|
||||||
|
|
||||||
|
|
||||||
# load all meshes
|
# Load all meshes.
|
||||||
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
||||||
data_to.meshes = data_from.meshes
|
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):
|
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")]
|
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):
|
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
||||||
for attr in dir(data_to):
|
for attr in dir(data_to):
|
||||||
setattr(data_to, attr, getattr(data_from, attr))
|
setattr(data_to, attr, getattr(data_from, attr))
|
||||||
|
|
||||||
|
|
||||||
# the loaded objects can be accessed from 'data_to' outside of the context
|
# 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
|
# since loading the data replaces the strings for the data-blocks or None
|
||||||
# if the datablock could not be loaded.
|
# if the data-block could not be loaded.
|
||||||
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
with bpy.data.libraries.load(filepath) as (data_from, data_to):
|
||||||
data_to.meshes = data_from.meshes
|
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:
|
for mesh in data_to.meshes:
|
||||||
if mesh is not None:
|
if mesh is not None:
|
||||||
print(mesh.name)
|
print(mesh.name)
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ import bpy
|
|||||||
|
|
||||||
filepath = "//new_library.blend"
|
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)
|
data_blocks = set(bpy.context.selected_objects)
|
||||||
bpy.data.libraries.write(filepath, data_blocks)
|
bpy.data.libraries.write(filepath, data_blocks)
|
||||||
|
|
||||||
|
|
||||||
# write all meshes starting with a capital letter and
|
# Write all meshes starting with a capital letter and
|
||||||
# set them with fake-user enabled so they aren't lost on re-saving
|
# 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()}
|
data_blocks = {mesh for mesh in bpy.data.meshes if mesh.name[:1].isupper()}
|
||||||
bpy.data.libraries.write(filepath, data_blocks, fake_user=True)
|
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}
|
data_blocks = {*bpy.data.materials, *bpy.data.textures, *bpy.data.node_groups}
|
||||||
bpy.data.libraries.write(filepath, data_blocks)
|
bpy.data.libraries.write(filepath, data_blocks)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ def set_pose_matrices(obj, matrix_map):
|
|||||||
# pbone.matrix = matrix
|
# pbone.matrix = matrix
|
||||||
# bpy.context.view_layer.update()
|
# 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:
|
if pbone.parent:
|
||||||
pbone.matrix_basis = pbone.bone.convert_local_to_pose(
|
pbone.matrix_basis = pbone.bone.convert_local_to_pose(
|
||||||
matrix,
|
matrix,
|
||||||
@@ -32,7 +32,7 @@ def set_pose_matrices(obj, matrix_map):
|
|||||||
invert=True
|
invert=True
|
||||||
)
|
)
|
||||||
else:
|
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:
|
if pbone.parent:
|
||||||
matrix = pbone.bone.convert_local_to_pose(
|
matrix = pbone.bone.convert_local_to_pose(
|
||||||
pbone.matrix_basis,
|
pbone.matrix_basis,
|
||||||
@@ -46,11 +46,11 @@ def set_pose_matrices(obj, matrix_map):
|
|||||||
pbone.bone.matrix_local,
|
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:
|
for child in pbone.children:
|
||||||
rec(child, matrix)
|
rec(child, matrix)
|
||||||
|
|
||||||
# Scan all bone trees from their roots
|
# Scan all bone trees from their roots.
|
||||||
for pbone in obj.pose.bones:
|
for pbone in obj.pose.bones:
|
||||||
if not pbone.parent:
|
if not pbone.parent:
|
||||||
rec(pbone, None)
|
rec(pbone, None)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class OBJECT_OT_simple_exporter(bpy.types.Operator):
|
|||||||
depsgraph = context.evaluated_depsgraph_get()
|
depsgraph = context.evaluated_depsgraph_get()
|
||||||
for object_instance in depsgraph.object_instances:
|
for object_instance in depsgraph.object_instances:
|
||||||
if not self.is_object_instance_from_selected(object_instance):
|
if not self.is_object_instance_from_selected(object_instance):
|
||||||
# We only export selected objects
|
# We only export selected objects.
|
||||||
continue
|
continue
|
||||||
# NOTE: This will create a mesh for every instance, which is not ideal at all. In
|
# 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
|
# 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.filepath = filepath
|
||||||
text_node.location = Vector((x, y))
|
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:
|
if self.set_label:
|
||||||
text_node.label = file.name
|
text_node.label = file.name
|
||||||
|
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ class CustomHydraRenderEngine(bpy.types.HydraRenderEngine):
|
|||||||
# by implementing the methods like this.
|
# by implementing the methods like this.
|
||||||
def update(self, data, depsgraph):
|
def update(self, data, depsgraph):
|
||||||
super().update(data, depsgraph)
|
super().update(data, depsgraph)
|
||||||
# Do extra work here
|
# Do extra work here.
|
||||||
|
|
||||||
def update_render_passes(self, scene, render_layer):
|
def update_render_passes(self, scene, render_layer):
|
||||||
if render_layer.use_pass_z:
|
if render_layer.use_pass_z:
|
||||||
self.register_pass(scene, render_layer, 'Depth', 1, 'Z', 'VALUE')
|
self.register_pass(scene, render_layer, 'Depth', 1, 'Z', 'VALUE')
|
||||||
|
|
||||||
|
|
||||||
# Registration
|
# Registration.
|
||||||
def register():
|
def register():
|
||||||
bpy.utils.register_class(CustomHydraRenderEngine)
|
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.
|
# This example shows what _not_ to do, and will crash Blender.
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
# object which is in the scene.
|
# Object which is in the scene.
|
||||||
obj = bpy.data.objects["Cube"]
|
obj = bpy.data.objects["Cube"]
|
||||||
|
|
||||||
# without this, removal would raise an error.
|
# Without this, removal would raise an error.
|
||||||
obj.user_clear()
|
obj.user_clear()
|
||||||
|
|
||||||
# runs without an exception
|
# Runs without an exception but will crash on redraw.
|
||||||
# but will crash on redraw.
|
|
||||||
bpy.data.objects.remove(obj)
|
bpy.data.objects.remove(obj)
|
||||||
|
|||||||
@@ -34,5 +34,5 @@ class SubMenu(bpy.types.Menu):
|
|||||||
|
|
||||||
bpy.utils.register_class(SubMenu)
|
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")
|
bpy.ops.wm.call_menu(name="OBJECT_MT_select_submenu")
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ class AddPresetObjectDisplay(AddPresetBase, Operator):
|
|||||||
bl_label = "Add Object Display Preset"
|
bl_label = "Add Object Display Preset"
|
||||||
preset_menu = "OBJECT_MT_display_presets"
|
preset_menu = "OBJECT_MT_display_presets"
|
||||||
|
|
||||||
# variable used for all preset values
|
# Variable used for all preset values.
|
||||||
preset_defines = [
|
preset_defines = [
|
||||||
"obj = bpy.context.object"
|
"obj = bpy.context.object"
|
||||||
]
|
]
|
||||||
|
|
||||||
# properties to store in the preset
|
# Properties to store in the preset.
|
||||||
preset_values = [
|
preset_values = [
|
||||||
"obj.display_type",
|
"obj.display_type",
|
||||||
"obj.show_bounds",
|
"obj.show_bounds",
|
||||||
@@ -44,11 +44,11 @@ class AddPresetObjectDisplay(AddPresetBase, Operator):
|
|||||||
"obj.show_wire",
|
"obj.show_wire",
|
||||||
]
|
]
|
||||||
|
|
||||||
# where to store the preset
|
# Where to store the preset.
|
||||||
preset_subdir = "object/display"
|
preset_subdir = "object/display"
|
||||||
|
|
||||||
|
|
||||||
# Display into an existing panel
|
# Display into an existing panel.
|
||||||
def panel_func(self, context):
|
def panel_func(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
|
|||||||
@@ -38,5 +38,5 @@ class BasicMenu(bpy.types.Menu):
|
|||||||
|
|
||||||
bpy.utils.register_class(BasicMenu)
|
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")
|
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:
|
for poly in me.polygons:
|
||||||
print("Polygon index: {:d}, length: {:d}".format(poly.index, poly.loop_total))
|
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 convenience 'poly.loop_indices' can be used instead.
|
||||||
for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
|
for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
|
||||||
print(" Vertex: {:d}".format(me.loops[loop_index].vertex_index))
|
print(" Vertex: {:d}".format(me.loops[loop_index].vertex_index))
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import bpy
|
|||||||
|
|
||||||
view_layer = bpy.context.view_layer
|
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')
|
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)
|
light_object = bpy.data.objects.new(name="New Light", object_data=light_data)
|
||||||
|
|
||||||
# Link light object to the active collection of current view layer,
|
# Link light object to the active collection of current view layer,
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ class SimpleMouseOperator(bpy.types.Operator):
|
|||||||
y: bpy.props.IntProperty()
|
y: bpy.props.IntProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
# rather than printing, use the report function,
|
# Rather than printing, use the report function,
|
||||||
# this way the message appears in the header,
|
# this way the message appears in the header.
|
||||||
self.report({'INFO'}, "Mouse coords are {:d} {:d}".format(self.x, self.y))
|
self.report({'INFO'}, "Mouse coords are {:d} {:d}".format(self.x, self.y))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@@ -55,13 +55,13 @@ def menu_func(self, context):
|
|||||||
self.layout.operator(SimpleMouseOperator.bl_idname, text="Simple Mouse Operator")
|
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.utils.register_class(SimpleMouseOperator)
|
||||||
bpy.types.VIEW3D_MT_view.append(menu_func)
|
bpy.types.VIEW3D_MT_view.append(menu_func)
|
||||||
|
|
||||||
# Test call to the newly defined operator.
|
# Test call to the newly defined operator.
|
||||||
# Here we call the operator and invoke it, meaning that the settings are taken
|
# Here we call the operator and invoke it,
|
||||||
# from the mouse.
|
# meaning that the settings are taken from the mouse.
|
||||||
bpy.ops.wm.mouse_position('INVOKE_DEFAULT')
|
bpy.ops.wm.mouse_position('INVOKE_DEFAULT')
|
||||||
|
|
||||||
# Another test call, this time call execute() directly with pre-defined settings.
|
# 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")
|
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.utils.register_class(ExportSomeData)
|
||||||
bpy.types.TOPBAR_MT_file_export.append(menu_func)
|
bpy.types.TOPBAR_MT_file_export.append(menu_func)
|
||||||
|
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.export.some_data('INVOKE_DEFAULT')
|
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")
|
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.utils.register_class(DialogOperator)
|
||||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||||
|
|
||||||
|
|||||||
@@ -51,5 +51,5 @@ def menu_func(self, context):
|
|||||||
bpy.utils.register_class(CustomDrawOperator)
|
bpy.utils.register_class(CustomDrawOperator)
|
||||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.object.custom_draw('INVOKE_DEFAULT')
|
bpy.ops.object.custom_draw('INVOKE_DEFAULT')
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ class ModalOperator(bpy.types.Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def modal(self, context, event):
|
def modal(self, context, event):
|
||||||
if event.type == 'MOUSEMOVE': # Apply
|
if event.type == 'MOUSEMOVE': # Apply.
|
||||||
self.value = event.mouse_x
|
self.value = event.mouse_x
|
||||||
self.execute(context)
|
self.execute(context)
|
||||||
elif event.type == 'LEFTMOUSE': # Confirm
|
elif event.type == 'LEFTMOUSE': # Confirm.
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
elif event.type in {'RIGHTMOUSE', 'ESC'}: # Cancel
|
elif event.type in {'RIGHTMOUSE', 'ESC'}: # Cancel.
|
||||||
# Revert all changes that have been made
|
# Revert all changes that have been made
|
||||||
context.object.location.x = self.init_loc_x
|
context.object.location.x = self.init_loc_x
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
@@ -73,5 +73,5 @@ def menu_func(self, context):
|
|||||||
bpy.utils.register_class(ModalOperator)
|
bpy.utils.register_class(ModalOperator)
|
||||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.object.modal_operator('INVOKE_DEFAULT')
|
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")
|
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.utils.register_class(SearchEnumOperator)
|
||||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.object.search_enum_operator('INVOKE_DEFAULT')
|
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)
|
pose1 = pose_bone.bbone_segment_matrix(index, rest=False)
|
||||||
deform1 = pose1 @ rest1.inverted()
|
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)
|
rest2 = pose_bone.bbone_segment_matrix(index + 1, rest=True)
|
||||||
pose2 = pose_bone.bbone_segment_matrix(index + 1, rest=False)
|
pose2 = pose_bone.bbone_segment_matrix(index + 1, rest=False)
|
||||||
deform2 = pose2 @ rest2.inverted()
|
deform2 = pose2 @ rest2.inverted()
|
||||||
|
|||||||
@@ -37,5 +37,5 @@ bpy.utils.register_class(MyPropertyGroup)
|
|||||||
bpy.types.Object.my_prop_grp = bpy.props.PointerProperty(type=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
|
bpy.data.objects[0].my_prop_grp.custom_1 = 22.0
|
||||||
|
|||||||
@@ -125,14 +125,14 @@ class CustomDrawData:
|
|||||||
def __init__(self, dimensions):
|
def __init__(self, dimensions):
|
||||||
import gpu
|
import gpu
|
||||||
|
|
||||||
# Generate dummy float image buffer
|
# Generate dummy float image buffer.
|
||||||
self.dimensions = dimensions
|
self.dimensions = dimensions
|
||||||
width, height = dimensions
|
width, height = dimensions
|
||||||
|
|
||||||
pixels = width * height * array.array('f', [0.1, 0.2, 0.1, 1.0])
|
pixels = width * height * array.array('f', [0.1, 0.2, 0.1, 1.0])
|
||||||
pixels = gpu.types.Buffer('FLOAT', width * height * 4, pixels)
|
pixels = gpu.types.Buffer('FLOAT', width * height * 4, pixels)
|
||||||
|
|
||||||
# Generate texture
|
# Generate texture.
|
||||||
self.texture = gpu.types.GPUTexture((width, height), format='RGBA16F', data=pixels)
|
self.texture = gpu.types.GPUTexture((width, height), format='RGBA16F', data=pixels)
|
||||||
|
|
||||||
# Note: This is just a didactic example.
|
# Note: This is just a didactic example.
|
||||||
@@ -167,7 +167,7 @@ def get_panels():
|
|||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
# Register the RenderEngine
|
# Register the RenderEngine.
|
||||||
bpy.utils.register_class(CustomRenderEngine)
|
bpy.utils.register_class(CustomRenderEngine)
|
||||||
|
|
||||||
for panel in get_panels():
|
for panel in get_panels():
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class UIListPanelExample1(bpy.types.Panel):
|
|||||||
|
|
||||||
obj = context.object
|
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,
|
# 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").
|
# with no custom draw code, use "UI_UL_list").
|
||||||
layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
|
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):
|
class MESH_UL_vgroups_slow(bpy.types.UIList):
|
||||||
# Constants (flags)
|
# Constants (flags).
|
||||||
# Be careful not to shadow FILTER_ITEM!
|
# Be careful not to shadow FILTER_ITEM!
|
||||||
VGROUP_EMPTY = 1 << 0
|
VGROUP_EMPTY = 1 << 0
|
||||||
|
|
||||||
# Custom properties, saved with .blend file.
|
# Custom properties, saved with `.blend` file.
|
||||||
use_filter_empty: bpy.props.BoolProperty(
|
use_filter_empty: bpy.props.BoolProperty(
|
||||||
name="Filter Empty",
|
name="Filter Empty",
|
||||||
default=False,
|
default=False,
|
||||||
@@ -151,10 +151,10 @@ class MESH_UL_vgroups_slow(bpy.types.UIList):
|
|||||||
flt_flags = []
|
flt_flags = []
|
||||||
flt_neworder = []
|
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)
|
vgroups_empty = self.filter_items_empty_vgroups(context, vgroups)
|
||||||
|
|
||||||
# Filtering by name
|
# Filtering by name.
|
||||||
if self.filter_name:
|
if self.filter_name:
|
||||||
flt_flags = helper_funcs.filter_items_by_name(self.filter_name, self.bitflag_filter_item, vgroups, "name",
|
flt_flags = helper_funcs.filter_items_by_name(self.filter_name, self.bitflag_filter_item, vgroups, "name",
|
||||||
reverse=self.use_filter_name_reverse)
|
reverse=self.use_filter_name_reverse)
|
||||||
@@ -193,7 +193,7 @@ class UIListPanelExample2(bpy.types.Panel):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
obj = context.object
|
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,
|
# 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").
|
# with no custom draw code, use "UI_UL_list").
|
||||||
layout.template_list("MESH_UL_vgroups_slow", "", obj, "vertex_groups", obj.vertex_groups, "active_index")
|
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)
|
collection.foreach_get(attr, some_seq)
|
||||||
|
|
||||||
# Python equivalent
|
# Python equivalent.
|
||||||
for i in range(len(seq)):
|
for i in range(len(seq)):
|
||||||
some_seq[i] = getattr(collection[i], attr)
|
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)
|
collection.foreach_set(attr, some_seq)
|
||||||
|
|
||||||
# Python equivalent
|
# Python equivalent.
|
||||||
for i in range(len(some_seq)):
|
for i in range(len(some_seq)):
|
||||||
setattr(collection[i], attr, some_seq[i])
|
setattr(collection[i], attr, some_seq[i])
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ import bpy
|
|||||||
|
|
||||||
obj = bpy.context.object
|
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.location = (3.0, 4.0, 10.0)
|
||||||
obj.keyframe_insert(data_path="location", frame=1)
|
obj.keyframe_insert(data_path="location", frame=1)
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
Custom compute shader (using image store) and vertex/fragment shader
|
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.
|
This is an example of how to use a custom compute 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,
|
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.
|
based on current time.
|
||||||
"""
|
"""
|
||||||
import bpy
|
import bpy
|
||||||
@@ -17,7 +19,7 @@ start_time = time.time()
|
|||||||
size = 128
|
size = 128
|
||||||
texture = gpu.types.GPUTexture((size, size), format='RGBA32F')
|
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 = gpu.types.GPUShaderCreateInfo()
|
||||||
compute_shader_info.image(0, 'RGBA32F', "FLOAT_2D", "img_output", qualifiers={"WRITE"})
|
compute_shader_info.image(0, 'RGBA32F', "FLOAT_2D", "img_output", qualifiers={"WRITE"})
|
||||||
compute_shader_info.compute_source('''
|
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_info.local_group_size(1, 1)
|
||||||
compute_shader = gpu.shader.create_from_info(compute_shader_info)
|
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 = gpu.types.GPUStageInterfaceInfo("my_interface")
|
||||||
vert_out.smooth('VEC2', "uvInterp")
|
vert_out.smooth('VEC2', "uvInterp")
|
||||||
shader_info = gpu.types.GPUShaderCreateInfo()
|
shader_info = gpu.types.GPUShaderCreateInfo()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ with offscreen.bind():
|
|||||||
fb = gpu.state.active_framebuffer_get()
|
fb = gpu.state.active_framebuffer_get()
|
||||||
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
||||||
with gpu.matrix.push_pop():
|
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_matrix(Matrix.Identity(4))
|
||||||
gpu.matrix.load_projection_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 = gpu.state.active_framebuffer_get()
|
||||||
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
||||||
with gpu.matrix.push_pop():
|
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_matrix(Matrix.Identity(4))
|
||||||
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import mathutils
|
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))
|
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
|
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 R:", col.r)
|
||||||
print("Color G:", col[1])
|
print("Color G:", col[1])
|
||||||
print("Color B:", col[-1])
|
print("Color B:", col[-1])
|
||||||
print("Color HSV: {:.2f}, {:.2f}, {:.2f}".format(*col))
|
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
|
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))
|
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))
|
col += mathutils.Color((0.25, 0.0, 0.0))
|
||||||
|
|
||||||
# Color can be multiplied, in this example color is scaled to 0-255
|
# 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))))
|
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)))
|
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 mathutils
|
||||||
import math
|
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')
|
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))
|
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 X", eul.x)
|
||||||
print("Euler Y", eul[1])
|
print("Euler Y", eul[1])
|
||||||
print("Euler Z", 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
|
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))
|
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'
|
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 = mathutils.Vector((0.0, 0.0, 1.0))
|
||||||
vec.rotate(eul)
|
vec.rotate(eul)
|
||||||
|
|
||||||
# often its useful to convert the euler into a matrix so it can be used as
|
# Often its useful to convert the euler into a matrix so it can be used as
|
||||||
# transformations with more flexibility
|
# transformations with more flexibility.
|
||||||
mat_rot = eul.to_matrix()
|
mat_rot = eul.to_matrix()
|
||||||
mat_loc = mathutils.Matrix.Translation((2.0, 3.0, 4.0))
|
mat_loc = mathutils.Matrix.Translation((2.0, 3.0, 4.0))
|
||||||
mat = mat_loc @ mat_rot.to_4x4()
|
mat = mat_loc @ mat_rot.to_4x4()
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
import mathutils
|
import mathutils
|
||||||
import math
|
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))
|
quat_a = mathutils.Quaternion((0.7071068, 0.0, 0.7071068, 0.0))
|
||||||
|
|
||||||
# passing values to Quaternion's directly can be confusing so axis, angle
|
# Passing values to Quaternion's directly can be confusing so axis, angle
|
||||||
# is supported for initializing too
|
# is supported for initializing too.
|
||||||
quat_b = mathutils.Quaternion((0.0, 1.0, 0.0), math.radians(90.0))
|
quat_b = mathutils.Quaternion((0.0, 1.0, 0.0), math.radians(90.0))
|
||||||
|
|
||||||
print("Check quaternions match", quat_a == quat_b)
|
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_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_b = mathutils.Quaternion((0.0, 0.0, 1.0), math.radians(45.0))
|
||||||
quat_out = quat_a @ quat_b
|
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("Final Rotation:")
|
||||||
print(quat_out)
|
print(quat_out)
|
||||||
print("{:.2f}, {:.2f}, {:.2f}".format(*(math.degrees(a) for a in quat_out.to_euler())))
|
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)))
|
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))
|
quat_c = mathutils.Quaternion((1.0, 0.0, 0.0), math.radians(15.0))
|
||||||
exp_avg = (quat_a.to_exponential_map() +
|
exp_avg = (quat_a.to_exponential_map() +
|
||||||
quat_b.to_exponential_map() +
|
quat_b.to_exponential_map() +
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import mathutils
|
import mathutils
|
||||||
|
|
||||||
# zero length vector
|
# Zero length vector.
|
||||||
vec = mathutils.Vector((0.0, 0.0, 1.0))
|
vec = mathutils.Vector((0.0, 0.0, 1.0))
|
||||||
|
|
||||||
# unit length vector
|
# Unit length vector.
|
||||||
vec_a = vec.normalized()
|
vec_a = vec.normalized()
|
||||||
|
|
||||||
vec_b = mathutils.Vector((0.0, 1.0, 2.0))
|
vec_b = mathutils.Vector((0.0, 1.0, 2.0))
|
||||||
@@ -29,7 +29,7 @@ vec_a < vec_b
|
|||||||
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
|
vec_a - vec_b
|
||||||
vec_a @ vec_b
|
vec_a @ vec_b
|
||||||
@@ -39,7 +39,7 @@ quat @ vec_a
|
|||||||
-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]
|
x = vec_a[0]
|
||||||
len(vec)
|
len(vec)
|
||||||
vec_a[:] = vec_b
|
vec_a[:] = vec_b
|
||||||
@@ -47,7 +47,7 @@ vec_a[:] = 1.0, 2.0, 3.0
|
|||||||
vec2d[:] = vec3d[:2]
|
vec2d[:] = vec3d[:2]
|
||||||
|
|
||||||
|
|
||||||
# Vectors support 'swizzle' operations
|
# Vectors support 'swizzle' operations.
|
||||||
# See https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)
|
# See https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)
|
||||||
vec.xyz = vec.zyx
|
vec.xyz = vec.zyx
|
||||||
vec.xy = vec4d.zw
|
vec.xy = vec4d.zw
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import mathutils
|
import mathutils
|
||||||
|
|
||||||
# create a kd-tree from a mesh
|
# Create a KD-tree from a mesh.
|
||||||
from bpy import context
|
from bpy import context
|
||||||
obj = context.object
|
obj = context.object
|
||||||
|
|
||||||
@@ -14,21 +14,21 @@ for i, v in enumerate(mesh.vertices):
|
|||||||
kd.balance()
|
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_find = (0.0, 0.0, 0.0)
|
||||||
co, index, dist = kd.find(co_find)
|
co, index, dist = kd.find(co_find)
|
||||||
print("Close to center:", co, index, dist)
|
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
|
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")
|
print("Close 10 points")
|
||||||
for (co, index, dist) in kd.find_n(co_find, 10):
|
for (co, index, dist) in kd.find_n(co_find, 10):
|
||||||
print(" ", co, index, dist)
|
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")
|
print("Close points within 0.5 distance")
|
||||||
for (co, index, dist) in kd.find_range(co_find, 0.5):
|
for (co, index, dist) in kd.find_range(co_find, 0.5):
|
||||||
print(" ", co, index, dist)
|
print(" ", co, index, dist)
|
||||||
|
|||||||
@@ -902,12 +902,12 @@ including advanced features.
|
|||||||
|
|
||||||
import bgl
|
import bgl
|
||||||
xval, yval= 100, 40
|
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)
|
view_matrix = bgl.Buffer(bgl.GL_FLOAT, 16)
|
||||||
bgl.glGetFloatv(bgl.GL_MODELVIEW_MATRIX, view_matrix)
|
bgl.glGetFloatv(bgl.GL_MODELVIEW_MATRIX, view_matrix)
|
||||||
f = 1.0 / view_matrix[0]
|
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)
|
bgl.glRasterPos2f(xval * f, yval * f)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -104,11 +104,11 @@ Here are some examples:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# in this example the active vertex group index is used,
|
# In this example the active vertex group index is used,
|
||||||
# this is stored in the object, not the BMesh
|
# this is stored in the object, not the `BMesh`.
|
||||||
group_index = obj.vertex_groups.active_index
|
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
|
dvert_lay = bm.verts.layers.deform.active
|
||||||
|
|
||||||
for vert in bm.verts:
|
for vert in bm.verts:
|
||||||
|
|||||||
@@ -149,13 +149,13 @@ Rather than:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
polygons = mesh.polygons[:] # make a list copy of the meshes polygons
|
polygons = mesh.polygons[:] # Make a list copy of the meshes polygons.
|
||||||
p_idx = len(polygons) # Loop backwards
|
p_idx = len(polygons) # Loop backwards
|
||||||
while p_idx: # while the value is not 0
|
while p_idx: # While the value is not 0.
|
||||||
p_idx -= 1
|
p_idx -= 1
|
||||||
|
|
||||||
if len(polygons[p_idx].vertices) == 3:
|
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:
|
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
|
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]
|
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()
|
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
|
import time
|
||||||
time_start = time.time()
|
time_start = time.time()
|
||||||
|
|
||||||
# do something...
|
# Do something...
|
||||||
|
|
||||||
print("My Script Finished: %.4f sec" % (time.time() - time_start))
|
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
|
.. 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
|
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
|
bpy.context.active_pose_bone
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Here is an example of threading supported by Blender:
|
|||||||
def prod():
|
def prod():
|
||||||
print(threading.current_thread().name, "Starting")
|
print(threading.current_thread().name, "Starting")
|
||||||
|
|
||||||
# do something vaguely useful
|
# Do something vaguely useful.
|
||||||
import bpy
|
import bpy
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
from random import random
|
from random import random
|
||||||
@@ -28,7 +28,7 @@ Here is an example of threading supported by Blender:
|
|||||||
print("Prodding", prod_vec)
|
print("Prodding", prod_vec)
|
||||||
bpy.data.objects["Cube"].location += prod_vec
|
bpy.data.objects["Cube"].location += prod_vec
|
||||||
time.sleep(random() + 1.0)
|
time.sleep(random() + 1.0)
|
||||||
# finish
|
# Finish.
|
||||||
|
|
||||||
print(threading.current_thread().name, "Exiting")
|
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='EDIT')
|
||||||
bpy.ops.object.mode_set(mode='OBJECT')
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
# this will crash
|
# This will crash!
|
||||||
print(polygons)
|
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='EDIT')
|
||||||
bpy.ops.object.mode_set(mode='OBJECT')
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
# polygons have been re-allocated
|
# Polygons have been re-allocated.
|
||||||
polygons = mesh.polygons
|
polygons = mesh.polygons
|
||||||
print(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]
|
point = bpy.context.object.data.splines[0].bezier_points[0]
|
||||||
bpy.context.object.data.splines[0].bezier_points.add()
|
bpy.context.object.data.splines[0].bezier_points.add()
|
||||||
|
|
||||||
# this will crash!
|
# This will crash!
|
||||||
point.co = 1.0, 2.0, 3.0
|
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
|
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
|
.. code-block:: python
|
||||||
|
|
||||||
mesh = bpy.data.meshes.new(name="MyMesh")
|
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)
|
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
|
# 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")
|
mesh = bpy.data.meshes.new(name="MyMesh")
|
||||||
vertices = mesh.vertices
|
vertices = mesh.vertices
|
||||||
bpy.data.meshes.remove(mesh)
|
bpy.data.meshes.remove(mesh)
|
||||||
print(vertices) # <- this may crash
|
print(vertices) # <- This may crash.
|
||||||
|
|
||||||
|
|
||||||
Unfortunate Corner Cases
|
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)
|
bpy.data.meshes.new(name=meshid)
|
||||||
|
|
||||||
# normally some code, function calls...
|
# Normally some code, function calls, etc.
|
||||||
bpy.data.meshes[meshid]
|
bpy.data.meshes[meshid]
|
||||||
|
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ Or with name assignment:
|
|||||||
|
|
||||||
obj.name = objname
|
obj.name = objname
|
||||||
|
|
||||||
# normally some code, function calls...
|
# Normally some code, function calls, etc.
|
||||||
obj = bpy.data.meshes[objname]
|
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
|
.. 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_name_mapping = {}
|
||||||
|
|
||||||
mesh = bpy.data.meshes.new(name=meshid)
|
mesh = bpy.data.meshes.new(name=meshid)
|
||||||
mesh_name_mapping[meshid] = mesh
|
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]
|
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
|
.. 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"]
|
obj = bpy.data.objects["my_obj"]
|
||||||
|
|
||||||
# library object name look up using a pair
|
# Library object name lookup using a pair,
|
||||||
# where the second argument is the library path matching bpy.types.Library.filepath
|
# where the second argument is the library path matching bpy.types.Library.filepath.
|
||||||
obj = bpy.data.objects["my_obj", "//my_lib.blend"]
|
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.
|
# where the second argument excludes library data from being returned.
|
||||||
obj = bpy.data.objects["my_obj", None]
|
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))
|
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
|
.. code-block:: python
|
||||||
|
|
||||||
# Create new property
|
# Create new property:
|
||||||
# bpy.data.materials[0].my_custom_props.my_float
|
# bpy.data.materials[0].my_custom_props.my_float
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
@@ -389,7 +389,7 @@ For example, if you want to store material settings for a custom engine:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. 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
|
# bpy.data.materials[0].my_custom_props.sub_group.my_float
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
@@ -428,9 +428,9 @@ For example:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. 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()
|
bpy.types.Object.my_float: bpy.props.FloatProperty()
|
||||||
# remove
|
# Remove it.
|
||||||
del bpy.types.Object.my_float
|
del bpy.types.Object.my_float
|
||||||
|
|
||||||
This works just as well for ``PropertyGroup`` subclasses you define yourself.
|
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.
|
# which can have a fallback value.
|
||||||
value = bpy.data.scenes["Scene"].get("test_prop", "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 = bpy.data.collections.new("MyTestCollection")
|
||||||
collection["MySettings"] = {"foo": 10, "bar": "spam", "baz": {}}
|
collection["MySettings"] = {"foo": 10, "bar": "spam", "baz": {}}
|
||||||
|
|
||||||
@@ -363,10 +363,10 @@ so these are accessed as normal Python types.
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# setting multiple snap targets
|
# Setting multiple snap targets.
|
||||||
bpy.context.scene.tool_settings.snap_elements_base = {'VERTEX', 'EDGE'}
|
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!")
|
self.report({'WARNING', 'INFO'}, "Some message!")
|
||||||
|
|
||||||
|
|
||||||
@@ -411,10 +411,10 @@ Example of a matrix, vector multiplication:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# modifies the Z axis in place.
|
# Modifies the Z axis in place.
|
||||||
bpy.context.object.location.z += 2.0
|
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 = bpy.context.object.location
|
||||||
location *= 2.0
|
location *= 2.0
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from bpy.types import Operator
|
|||||||
|
|
||||||
class ExportSomeData(Operator, ExportHelper):
|
class ExportSomeData(Operator, ExportHelper):
|
||||||
"""This appears in the tooltip of the operator and in the generated docs"""
|
"""This appears in the tooltip of the operator and in the generated docs"""
|
||||||
bl_idname = "export_test.some_data" # important since its how bpy.ops.import_test.some_data is constructed
|
bl_idname = "export_test.some_data" # Important since its how bpy.ops.import_test.some_data is constructed.
|
||||||
bl_label = "Export Some Data"
|
bl_label = "Export Some Data"
|
||||||
|
|
||||||
# ExportHelper mix-in class uses this.
|
# ExportHelper mix-in class uses this.
|
||||||
@@ -72,5 +72,5 @@ def unregister():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.export_test.some_data('INVOKE_DEFAULT')
|
bpy.ops.export_test.some_data('INVOKE_DEFAULT')
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ def read_some_data(context, filepath, use_some_setting):
|
|||||||
data = f.read()
|
data = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# would normally load the data here
|
# Would normally load the data here.
|
||||||
print(data)
|
print(data)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
@@ -75,5 +75,5 @@ def unregister():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.import_test.some_data('INVOKE_DEFAULT')
|
bpy.ops.import_test.some_data('INVOKE_DEFAULT')
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ def add_box(width, height, depth):
|
|||||||
(4, 0, 3, 7),
|
(4, 0, 3, 7),
|
||||||
]
|
]
|
||||||
|
|
||||||
# apply size
|
# Apply size.
|
||||||
for i, v in enumerate(verts):
|
for i, v in enumerate(verts):
|
||||||
verts[i] = v[0] * width, v[1] * depth, v[2] * height
|
verts[i] = v[0] * width, v[1] * depth, v[2] * height
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ class AddBox(bpy.types.Operator, AddObjectHelper):
|
|||||||
bm.to_mesh(mesh)
|
bm.to_mesh(mesh)
|
||||||
mesh.update()
|
mesh.update()
|
||||||
|
|
||||||
# add the mesh as an object into the scene with this utility module
|
# Add the mesh as an object into the scene with this utility module.
|
||||||
from bpy_extras import object_utils
|
from bpy_extras import object_utils
|
||||||
object_utils.object_data_add(context, mesh, operator=self)
|
object_utils.object_data_add(context, mesh, operator=self)
|
||||||
|
|
||||||
@@ -112,5 +112,5 @@ def unregister():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.mesh.primitive_box_add()
|
bpy.ops.mesh.primitive_box_add()
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ def main(context):
|
|||||||
|
|
||||||
uv_layer = bm.loops.layers.uv.verify()
|
uv_layer = bm.loops.layers.uv.verify()
|
||||||
|
|
||||||
# adjust uv coordinates
|
# Adjust UV coordinates.
|
||||||
for face in bm.faces:
|
for face in bm.faces:
|
||||||
for loop in face.loops:
|
for loop in face.loops:
|
||||||
loop_uv = loop[uv_layer]
|
loop_uv = loop[uv_layer]
|
||||||
# use xy position of the vertex as a uv coordinate
|
# Use XY position of the vertex as a uv coordinate.
|
||||||
loop_uv.uv = loop.vert.co.xy
|
loop_uv.uv = loop.vert.co.xy
|
||||||
|
|
||||||
bmesh.update_edit_mesh(me)
|
bmesh.update_edit_mesh(me)
|
||||||
@@ -52,5 +52,5 @@ def unregister():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.uv.simple_operator()
|
bpy.ops.uv.simple_operator()
|
||||||
|
|||||||
@@ -54,5 +54,5 @@ def unregister():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.object.modal_operator('INVOKE_DEFAULT')
|
bpy.ops.object.modal_operator('INVOKE_DEFAULT')
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class ModalTimerOperator(bpy.types.Operator):
|
|||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
if event.type == 'TIMER':
|
if event.type == 'TIMER':
|
||||||
# change theme color, silly!
|
# Change theme color, silly!
|
||||||
color = context.preferences.themes[0].view_3d.space.gradients.high_gradient
|
color = context.preferences.themes[0].view_3d.space.gradients.high_gradient
|
||||||
color.s = 1.0
|
color.s = 1.0
|
||||||
color.h += 0.01
|
color.h += 0.01
|
||||||
@@ -50,5 +50,5 @@ def unregister():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.wm.modal_timer_operator()
|
bpy.ops.wm.modal_timer_operator()
|
||||||
|
|||||||
@@ -38,5 +38,5 @@ def unregister():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
||||||
# test call
|
# Test call.
|
||||||
bpy.ops.object.simple_operator()
|
bpy.ops.object.simple_operator()
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class UIListPanelExample(bpy.types.Panel):
|
|||||||
|
|
||||||
obj = context.object
|
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,
|
# 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").
|
# with no custom draw code, use "UI_UL_list").
|
||||||
layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
|
layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
|
||||||
|
|||||||
Reference in New Issue
Block a user