Create a new collection
collection = bpy.data.collections.get(collectionName)
if collection is None:
collection = bpy.data.collections.new(collectionName)
bpy.context.scene.collection.children.link(collection)
# make it the active collection
bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection.children[collection.name]
Add object to active collection
bpy.context.view_layer.active_layer_collection.collection.objects.link(obj)
I had crashes while scripting the CUDA devices selection (b3d v2.83 + 4x GTX 2080 GPU).
The original code was :
preferences = bpy.context.preferences
cycles_preferences = preferences.addons["cycles"].preferences
cuda_devices, opencl_devices = cycles_preferences.get_devices()
...
After reading a comment in blender source code :
/* Lazy initialize devices. On some platforms OpenCL or CUDA drivers can
* be broken and cause crashes when only trying to get device info, so
* we don't want to do any initialization until the user chooses to. */
Changed code to the following, seems to prevent (most?) crashes :
...
devices = cycles_preferences.get_devices_for_type('CUDA')
...
import bpy
def remove_object_linked_material_slots():
"""
2020/10/21 - In Blender 2.80-2.90+, Cycles do *not* instance objects sharing the same
mesh datablock when they have materials linked to 'Object' in their material_slots.
"""
all_objs = dict()
for obj in bpy.data.objects:
if obj.type != 'MESH':
continue
mesh = obj.data
mtls = tuple( [ slot.material for slot in obj.material_slots ] )
key = ( mesh, mtls )
all_objs.setdefault(key, []).append(obj)
print("*" * 60)
for key in all_objs:
objs = all_objs[key]
if len(objs) > 1:
mesh, mtls = key
newmesh = mesh.copy()
for obj in objs:
obj.data = newmesh
for i, mtl in enumerate(mtls):
mtl_slot = obj.material_slots[i]
mtl_slot.link = 'DATA'
mtl_slot.material = mtl
- Material slots :
bpy.ops.object.material_slot_add({'object':obj})
bpy.ops.object.material_slot_remove({'object': obj})
- Could not a find a way to get material preview images from a script, browsing the source code, they seem to be generated in an async way only in the related UI components
To export ambient occlusion textures, one have to use a glTF Settings
node group, which can be created by script :
import bpy
# create a group
gltfSettings_group = bpy.data.node_groups.new('glTF Settings', 'ShaderNodeTree')
# create group inputs
group_inputs = gltfSettings_group.nodes.new('NodeGroupInput')
group_inputs.location = (-100,0)
gltfSettings_group.inputs.new('NodeSocketFloat','Occlusion')
# create group outputs
group_outputs = gltfSettings_group.nodes.new('NodeGroupOutput')
group_outputs.location = (100,0)
class RenderEngine(bpy.types.RenderEngine):
bl_idname = "MY_CUSTOM_RENDER_ENGINE"
bl_label = "Custom Render Engine"
bl_use_preview = False # doesn't supports being used for rendering previews of materials, lights and worlds
bl_use_shading_nodes_custom = False # Use Cycles and Eevee material nodes
def __init__(self):
print("RenderEngine.__init__")
def __del__(self):
"""
If no reference on 'self' is kept :
* '__del__' is called immediately
* 'self' is valid and usable
In some other cases, the call is delayed :
* 'self' is 'invalid', weakref to 'self' is not None
* accessing 'self.some_attribute' will raise 'ReferenceError: StructRNA of type RenderEngine has been removed'
* after that, weakref to 'self' becomes None
"""
print("RenderEngine.__del__", self)
def render(self, depsgraph):
return
def view_update(self, context, depsgraph):
return
def view_draw(self, context, depsgraph):
return