/r/blenderpython

Photograph via snooOG

A community to discuss Blender's built-in Python functionality, as well as to share your Blender/Python related work.

Welcome to Blender Python! There aren't too many rules, but please stick to them.

  • Make sure your post is related to Python within Blender
  • Never steal someone's work and always credit your source
  • No blatant self- promotion- always post with inspiration in mind!
  • Always be constructive and play nice!

Webpages:

Discord:

Blender Discord

Subreddits:

/r/learnpython
/r/blender
/r/BlenderGameEngine
/r/coding
/r/gamedev
/r/opengl

Books:

/r/blenderpython

1,705 Subscribers

2

I made a universal(?) Multi-File Add-On self-bootstrapping __init.py__

I spent way too much time on making this __init,py__ file for use in add-on development... instead of actually working on the add-on I want to make

It scans it's directory for all sub-modules (.py files) and imports and/or reloads them. It is a very, very greedy approach and it's likely to load / reload the same file multiple times (because it got imported in an already loaded file)

Also the script that you run inside of Blender to load in the add-on is different than what I've seen around (included in the code as a text block).

Do whatever you want with this code, I donate it to the public domain as much as I can and whatnot.

bl_info = {
    # your add-on info here
}

"""
### Dev Loader Script ###
# Run from Blender's Text Editor

import sys
import importlib
import importlib.util

# https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly

module_name = "module_name"
file_path = "C:/blah/module_name/__init__.py"

if module_name in sys.modules:
    try:
        sys.modules[module_name].unregister()
    except Exception as err:
        print(err)

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)

module.register()
"""

# bootstrapping code based on: https://b3d.interplanety.org/en/creating-multifile-add-on-for-blender/
import importlib
import sys
from glob import glob

child_modules = {mod_name: f'{__name__}.{mod_name}' for mod_name in (
    p.replace('\\', '.').replace('/', '.').removesuffix('.py')
    for p in glob("**/[!_]*.py", root_dir=__path__[0], recursive=True)
)}

for mod_name, full_name in child_modules.items():
    if full_name in sys.modules:
        print('Reload', full_name)
        importlib.reload(sys.modules[full_name])
    else:
        print('Initial load', full_name)
        parent, name = mod_name.rsplit('.', 1)
        exec(f'from .{parent} import {name}')

del mod_name, full_name

def register():
    for full_name in child_modules.values():
        if full_name in sys.modules and hasattr(sys.modules[full_name], 'register'):
            sys.modules[full_name].register()


def unregister():
    for full_name in child_modules.values():
        if full_name in sys.modules and hasattr(sys.modules[full_name], 'unregister'):
            sys.modules[full_name].unregister()
0 Comments
2024/04/28
05:29 UTC

1

Split mesh but connect split vertices?

I’m working on a project where I’ve got a mesh that I want to split into chunks. The splitting part is easy. I’m using bmesh so I can just use split_edges to break it up and that works great.

So now it’s split into chunks and all the vertices on the boundary of each chunk has a matching vertex on the other chunk it was split from. I want to join those matching vertices on the different chunks with an edge, but there doesn’t seem to be an easy way to do that. I could loop through all the boundary points until I find all matching pairs and then call a function to connect them with edges one at a time but that seems ridiculous. Any suggestions?

0 Comments
2024/04/20
02:50 UTC

1

Alternative to draw function in gpu Module?

I want to use the blender gpu Module. In the examples they say that the draw function is only there to make the code short. The problem is that I want to remove (or update) the lines without restarting blender. How would that be possible?

Example: https://docs.blender.org/api/current/gpu.html#d-lines-with-single-color

Thank you

2 Comments
2024/04/13
13:02 UTC

1

New BPY user trying to define a problem about managing rig & animation data for a game project im working on.

Building a fighting game, here's the system I'd like to build: a shared human rig, using other blends to import corresponding meshes of characters so that there arent a ton of unneeded characters sitting in the file. animation groups so that I can specify which animations are shared between characters and which are unique to a particular character for export. Does this sound possible? And if anyone has any guidance about implementation or other words of wisdom I'd really appreciate it.
edit: oh and do people use this or the Blender Artists: Python Support Forum thats linked in the docs? wheres the place 2 be basically ;p

0 Comments
2024/03/23
01:29 UTC

1

How to create a bool type socket input for shader node groups in Blender 4.0

Hi there, I'm not very experienced with python but I used:

import bpy bpy.data.node_groups['MyGroupName'].inputs.new('NodeSocketbool', 'SocketName')

to create custom boolean socket inputs for shaders. This used to work in 3.5 but doesn't in 4.0 anymore. I tried to understand the documentation on what changed but I don't really find the solution but that might be due to my inexpience with python.

It says there's not inputs attribute anymore. Can someone help?

7 Comments
2024/03/21
08:59 UTC

3

Python code to Shader Nodes

I think the python API is pretty cumbersome for creating materials, so I've made a decorator that converts more typical python to materials/node groups. Check it out https://github.com/JamesPickersgill/python-shader-nodes, although note this is a just a proof of concept so lots is missing. If anyone else thinks this is useful I can spend some more time fleshing it out.

Code Input

Node Output

2 Comments
2024/02/22
21:45 UTC

1

Waiting for compositor to finish before saving image to file. Tips on asynchronous processes?

I'm trying to write a script that will tweak some settings in the compositor, then save the resulting image.

However, The resulting image is NOT receiving the changes that are being made in the compositor. I suspect that blender is not, "waiting for the compositor to finish" before saving the image.

I've tried using Application handlers, but I don't really understand how to use them in this case.

Any help? Here's the code in question, without attempting to use application handlers:

    #get the render result
    render = bpy.data.images["Render Result"]
    
    #set the value of a compositor node to 0
    bpy.data.scenes["Scene"].node_tree.nodes["color vs. depth"].inputs[0].default_value = 0
    #change the colorspace to filmic
    bpy.context.scene.view_settings.view_transform = 'Filmic'
    
    #save the image
    render.save_render(filepath = tool.my_path + tool.my_string + " COLOR.png")
2 Comments
2024/02/21
07:18 UTC

4

MatLayer 2.0.4 Release - A free, open-source, fully-featured material editing add-on for Blender!

I'm really proud to release yet another version of MatLayer, my free, open-source material editing add-on for Blender!

This update brings improved importing for texture sets, improved support for custom group nodes, support for using alternative UV maps for projection and exporting, and the inclusion of an ambient occlusion material channel.

You can get this release here:

https://github.com/LoganFairbairn/MatLayer/releases/tag/2.0.4

Happy Blending fellow artists!

Made for Blender version: 4.0.0

Not backwards compatible with previous MatLayer materials.

New Features:

- Added the ability to define a UV map for a specified layer when using UV layer projection.

- Added the ability to bake textures when exporting to a specified UV map. This makes custom texture atlasing possible.

- Made texture properties from custom group nodes show in the user interface.

- The import texture set operator can now import some images using commonly used naming conventions for channel packed textures.

- The import texture set operator correctly imports texture sets using names such as 'metallic'.

- The import texture set operator now imports textures using the naming convention that starts with 'T_', the standard naming convention for game engine textures.

- Added ambient occlusion material channel.

Tweaks:

- Changed the default bake padding from 32px to 14px.

User Interface:

- Small UI tweaks to some layer projection settings.

- Moved the import texture set button next to the layer operator buttons.

Bug Fixes, Clean up:

- Fixed custom group nodes not connecting to layer projection.

- Fixed material channels not relinking for custom node groups.

- Added git ignores for pycache files, and removed existing pycache files from remote repo.

- Removed conversion mix nodes that were automatically added to the MatLayer BSDF group node for Blender 4.0.

0 Comments
2024/02/19
14:36 UTC

3

Animation Visualization

Hey, I am kinda new to blender programming and I want to create a crowd simulator.

I am currently looking through the blender source code to understand it better but does anyone know if there is a blender animation API where I can for example insert animation and bone data into my script.
Like in the photo attached you can see the arrows showing where the character was and will go, is there a way to visualize the animation vectors of bones. Is there any library for arrows or other graphics.

https://preview.redd.it/i0m8b0kzbkic1.jpg?width=1260&format=pjpg&auto=webp&s=241e6c6efa75639be5d3d7c91d20353de948cb11

This is the link to the video: https://www.youtube.com/watch?v=wAbLsRymXe4
Thanks

0 Comments
2024/02/14
14:42 UTC

5

My first blender script

Just started learning scripting in blender. I don't know if I'll do anything more with this, but the idea was some sort of procedural building. Needs an interior and a lot more details to actually be considered a building but I thought I'd share. [edit] Added window holes and interior floors

import bpy
import random

cubes = []
interior = []
wall_thickness = .2

for tt in range(4):
    # Create the first cube and store the object in the list
    tr_scale = (random.random() * 3+2 , random.random() * 3+2 , random.random() * 3+2 )
    bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(tr_scale))
    cube = bpy.context.active_object
    z_min = min([v[2] for v in cube.bound_box])
    cube.location.z-=z_min
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
    bpy.ops.object.transform_apply(scale=True)
    cubes.append(bpy.context.active_object)
    
    #create interior cube of 
    bpy.ops.object.duplicate(linked=False)
    dup = bpy.context.active_object
    sx = 1-(wall_thickness/tr_scale[0])
    sy = 1-(wall_thickness/tr_scale[1])
    sz = 1-(wall_thickness/tr_scale[2])/2
    bpy.ops.transform.resize(value=(sx,sy,sz), orient_type='GLOBAL', constraint_axis=(False,False,False))
    interior.append(dup)
   

base = cubes[0]
for cube in cubes[1:]:
     # Add a boolean modifier to the base object
    bool = base.modifiers.new(name="Bool", type='BOOLEAN')
    bool.object = cube
    bool.operation = 'UNION'

    # Apply the boolean modifier
    bpy.context.view_layer.objects.active = base
    bpy.ops.object.modifier_apply(modifier="Bool")

    # Delete the cube from the scene
    bpy.data.objects.remove(cube, do_unlink=True)
    #cube.hide_set(True)

cubes.clear()
cubes.append(base)

obj = base
x_min = min([v[0] for v in obj.bound_box])
x_max = max([v[0] for v in obj.bound_box])
y_min = min([v[1] for v in obj.bound_box])
y_max = max([v[1] for v in obj.bound_box])
for tt in range(4):
    x = random.uniform(-x_min, -x_max)
    y = random.uniform(-y_min, -y_max)
    # Create the first cube and store the object in the list
    tr_scale = (random.random() * 3+2 , random.random() * 3+2 , random.random() * 3+2 )
    bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(tr_scale))
    cube = bpy.context.active_object
    z_min = min([v[2] for v in cube.bound_box])
    cube.location.z-=z_min
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
    bpy.ops.object.transform_apply(scale=True)
    cube.location = (x,y,0)
    cubes.append(bpy.context.active_object)
    
    #create interior cube of 
    bpy.ops.object.duplicate(linked=False)
    dup = bpy.context.active_object
    sx = 1-(wall_thickness/tr_scale[0])
    sy = 1-(wall_thickness/tr_scale[1])
    sz = 1-(wall_thickness/tr_scale[2])/2
    bpy.ops.transform.resize(value=(sx,sy,sz), orient_type='GLOBAL', constraint_axis=(False,False,False))
    interior.append(dup)

for cube in cubes[1:]:
     # Add a boolean modifier to the base object
    bool = base.modifiers.new(name="Bool", type='BOOLEAN')
    bool.object = cube
    bool.operation = 'UNION'

    # Apply the boolean modifier
    bpy.context.view_layer.objects.active = base
    bpy.ops.object.modifier_apply(modifier="Bool")

    # Delete the cube from the scene
    bpy.data.objects.remove(cube, do_unlink=True)
    #cube.hide_set(True)

#Add interiorFloors before interior is cut out
for z in [0,3,6]:
    bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=(0, 0, z), scale=(13,13,.23))
    floor_plane = bpy.context.active_object
    bool = floor_plane.modifiers.new(name="FloorIntersect", type='BOOLEAN')
    bool.object = base
    bool.solver = 'FAST'
    bool.operation = 'INTERSECT'
    bpy.ops.object.modifier_apply(modifier="FloorIntersect")
    bpy.ops.transform.resize(value=(.98,.98,1), orient_type='GLOBAL', constraint_axis=(False,False,False))
    floor_plane.name = "Floor"

for cube in interior:
     # Add a boolean modifier to the base object
    bool = base.modifiers.new(name="Bool", type='BOOLEAN')
    bool.object = cube
    bool.operation = 'DIFFERENCE'

    # Apply the boolean modifier
    bpy.context.view_layer.objects.active = base
    bpy.ops.object.modifier_apply(modifier="Bool")

    # Delete the cube from the scene
    bpy.data.objects.remove(cube, do_unlink=True)
    
def create_windows(obj, window_size, height, probability, amount):
  for _ in range(amount):
    if random.random() < probability:
        #
      radius = 20      
       # Use random angle to place within boundary circle
      angle = random.uniform(0, 2*math.pi)
      x = obj.location.x + radius * math.cos(angle)
      y = obj.location.y + radius * math.sin(angle)      
      z = height#random.uniform(height_min, height_max)

      # Cast ray around perimeter
      ray_origin = (x, y,z)
      ray_direction = (obj.location.x - x,obj.location.y - y, 0)
      
      depsgraph = bpy.context.evaluated_depsgraph_get()
      bvhtree = BVHTree.FromObject(obj, depsgraph)
      
      location, normal, index, dist = bvhtree.ray_cast(ray_origin, ray_direction)

      # If ray hits the object, create a window using Boolean with a cube
      if location:
        bpy.ops.mesh.primitive_cube_add(size=window_size, enter_editmode=False, align='WORLD', location=location)
        window_cube = bpy.context.active_object
        bpy.ops.transform.resize(value=(sx,sy,sz*1.5), orient_type='GLOBAL', constraint_axis=(False,False,False))
        bool = obj.modifiers.new(name="WindowBool", type='BOOLEAN')
        bool.object = window_cube
        bool.operation = 'DIFFERENCE'
        bpy.context.view_layer.objects.active = obj
        bpy.ops.object.modifier_apply(modifier="WindowBool")
        bpy.data.objects.remove(window_cube, do_unlink=True)
        

create_windows(base, 1.5,.7, 0.6,3) 

create_windows(base, .8 ,1.2, 0.8, 10)
create_windows(base, .8 ,4.2, 0.8, 10) 
create_windows(base, .8 ,7.2, 0.8, 10) 

1 Comment
2024/02/06
03:16 UTC

1

rationale for changes in bpy 4.0

Hi, I was wondering why bpy.ops.export_scene.obj is no longer in version 4.0 ? Any links that would explain the changes ?

2 Comments
2024/02/01
16:23 UTC

1

identifiers for BezierCurve points

I'm working on an addon that creates a smooth surface bazed on Bezier curves wireframe. I want to give to the user an ability to manually adjust the surface, and for this ideally that they
- selects a Bezier segment
- adjusts the values in the pop-up menu or drags the specific handle that apparates for this purpose
- the value is stored linked to this segment when the user edits the curve: drags points and creates/deletes segments.

I'm new in Blender scripting (nearly all my experience is writing the part that actually generates surface mesh) and my plan for now is this:
- generate an id for each point and store it in weight_softbody attribute (I don't like this part because the user may want to actually do the softbody simulation, but I didn't found better way)
- in my code, create a mapping of these ids and my custom surface parameters for the segments on the right and on the left of this point, and also ids of neighbour points on the right and on the left
- when the user selects for example right handle, they can summon a menu with input fields (or maybe I can create a temporary segment that can be used as a handle)
- my code verifies that the id on the right is what is enregistred. If yes, we edit segment to the right property, if no, the user has changed segment direction and we edit segment that is enregistred as to the left
- After this, the surface is updated, the value is stored in my code and all values are saved in Curve custom property as dictionnary.

Is there a way to do this without using a built-in attribute?

Sorry for giving such a lot of context, but maybe there is a way to achieve what I want completely differently.

0 Comments
2024/01/28
12:50 UTC

1

Can anyone help me make this addon compatible with 4.0?

Report: Error igme Froxy owap vjun. Python: Traceback (most recent call last): File "C:\Users\censored\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\FZRandomizer_3_0_3.py", line 3039, in execute multiOBJ(context) File "C:\Users\censored\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\FZRandomizer_3_0_3.py", line 1114, in multiOBJ buildChars(name, generations, genCodesList, proxyParametersList) File "C:\Users\censored\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\FZRandomizer_3_0_3.py", line 1186, in buildChars ng= buildHostProxy(genCodesList) File "C:\Users\censored\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\FZRandomizer_3_0_3.py", line 1493, in buildHostProxy ng= make_hostcollgroup(host, proxy, genCodesList) File "C:\Users\censored\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\FZRandomizer_3_0_3.py", line 646, in make_hostcolLgroup hostcoll_group.inputs.new("NodeSocketGeometry", "Input") AttributeError: 'GeometryNodeTree' object has no attribute 'inputs'

3 Comments
2023/12/13
09:25 UTC

1

Script Update 4.0 Component Space

Hello,
I have this script from blender 3.3 that I would like to use in 4.0. Select a face and the script will move the orientation to the face.

3.6

import bpy

class ComponentSpace(bpy.types.Operator):

bl_label = 'Component Space'

bl_idname = 'wm.setcomponentspace'

def execute(self, context):

for area in bpy.context.screen.areas:

if area.type == 'VIEW_3D':

ctx = bpy.context.copy()

ctx['area'] = area

ctx['region'] = area.regions[-1]

orientName = 'tempOrientation'

bpy.ops.transform.create_orientation(name=orientName)

bpy.context.scene.transform_orientation_slots[0].type = orientName

bpy.ops.object.editmode_toggle()

bpy.context.scene.tool_settings.use_transform_data_origin = True

matrix = bpy.context.scene.transform_orientation_slots[0].custom_orientation.matrix

bpy.ops.transform.transform(mode='ALIGN', orient_matrix=matrix)

bpy.ops.object.editmode_toggle()

bpy.ops.view3d.snap_cursor_to_selected(ctx)

bpy.ops.object.editmode_toggle()

bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')

bpy.context.scene.tool_settings.use_transform_data_origin = False

bpy.ops.transform.delete_orientation()

bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL'

break

return {'FINISHED'}

addonKeymaps = []

def register():

bpy.utils.register_class(ComponentSpace)

windowManager = bpy.context.window_manager

keyConfig = windowManager.keyconfigs.addon

if keyConfig:

keymap = keyConfig.keymaps.new(name='3D View', space_type='VIEW_3D')

keymapitem = keymap.keymap_items.new('wm.setcomponentspace', type='F', shift=True, value='PRESS')

addonKeymaps.append((keymap, keymapitem))

def unregister():

for keymap, keymapitem in addonKeymaps:

keymap.keymap_items.remove(keymapitem)

addonKeymaps.clear()

bpy.utils.unregister_class(ComponentSpace)

if __name__ == '__main__':

register()

3 Comments
2023/12/11
16:34 UTC

3

MatLayer 2.0.2 is out! (free, layer based PBR material editing add-on)

https://github.com/LoganFairbairn/matlayer/releases

Feel free to fiddle with the code!

This release fixes some major bugs with mesh map baking, toggling material channels on / off and implements better options for managing external textures.

Change Log:

- Removed the icon from the load export template menu because it wasn't required and was identical to the icon used in the save export template operator.

- Fixed many issues with toggling on / off material channels in the texture set settings.

- Fixed mesh maps saving in the wrong resolution when using upscaling.

- Changed baked mesh maps to save in uncompressed png format, instead of open exr. This also fixes the bug where images were saving as png files with an exr extension.

- Changed baked mesh maps to save in their own folder.

- Made all folder properties store in the blend file, instead of in add-on preferences. This means users can have unique folder paths per blend which is much more useful.

- Made it possible to define custom paths for custom folders for all images MatLayer saves externally.

- Added the ability to mark debug log messages as errors or warnings.

- Removed auto snapping adjustments when selecting layers. This auto snapping adjustment feature implemented to make it easier to move decal layer objects was more annoying and confusing for users than it was helpful.

- Updated the MatLayer BSDF to be more compatible with Blender 4.0. This improved performance slightly, but makes Blender 3.6 materials no longer compatible.

0 Comments
2023/11/27
19:19 UTC

2

Use a scipt to control an object by acceleration or velocity in real time

Hi, I'm trying to use Blender to simulate a vehicle to test the autonomous navigation I'm working on. To be able to do this you would need to be able to give, preferably, an acceleration setpoint to the vehicle, or a speed setpoint, to be able to move the vehicle through the simulation in real time. Do you know if there is any way to do it? or any addon that makes it easier?

2 Comments
2023/11/26
20:20 UTC

3

I am trying to get Blender to show 9 horizontal buttons on the bottom of the viewport, the GUI is not showing, please help.

Question Asked:
Can you write me a very simple template add-on for Blender that displays 9 horizontal buttons on the bottom of the viewport?
The button 1 is labeled "Draw" that when clicked will simulateclicking the Draw brush in Blender's sculpt mode.
The button 2 is labeled "Draw Sharp" that when clicked will simulate clicking the Draw Sharp brush in Blender's sculpt mode.
The button 3 is labeled "Smooth" that when clicked will simulate clicking the Smooth brush in Blender's sculpt mode.
The button 4 is labeled "Scrape" that when clicked will simulate clicking the Scrape brush in Blender's sculpt mode.
The button 5 is labeled "Grab" that when clicked will simulate clicking the Grab brush in Blender's sculpt mode.
The button 6 is labeled "Mask" that when clicked will simulate clicking the Mask brush in Blender's sculpt mode.
The button 7 is labeled "Box Mask" that when clicked will simulate clicking the Box Mask brush in Blender's sculpt mode.
The button 8 is labeled "Line Project" that when clicked will simulate clicking the Line Project brush in Blender's sculpt mode.
The button 9 is labeled "Mesh Filter" that when clicked will simulate clicking the Mesh Filter brush in Blender's sculpt mode.
Each of them when clicked plays a sound.

 

This is the script:
import bpy

# Define button functions
def draw_brush():
    # Simulate clicking the Draw brush in sculpt mode
    pass


def sharp_draw_brush():
    # Simulate clicking the Draw Sharp brush in sculpt mode
    pass


def smooth_brush():
    # Simulate clicking the Smooth brush in sculpt mode
    pass


def scrape_brush():
    # Simulate clicking the Scrape brush in sculpt mode
    pass


def grab_brush():
    # Simulate clicking the Grab brush in sculpt mode
    pass


def mask_brush():
    # Simulate clicking the Mask brush in sculpt mode
    pass


def box_mask_brush():
    # Simulate clicking the Box Mask brush in sculpt mode
    pass


def line_project_brush():
    # Simulate clicking the Line Project brush in sculpt mode
    pass


def mesh_filter_brush():
    # Simulate clicking the Mesh Filter brush in sculpt mode
    pass


# Define button labels and functions
buttons = [
    ("Draw", draw_brush),
    ("Draw Sharp", sharp_draw_brush),
    ("Smooth", smooth_brush),
    ("Scrape", scrape_brush),
    ("Grab", grab_brush),
    ("Mask", mask_brush),
    ("Box Mask", box_mask_brush),
    ("Line Project", line_project_brush),
    ("Mesh Filter", mesh_filter_brush),
]

# Add buttons to Blender's UI
layout = bpy.context.window_manager.popup_menu(title="Sculpt Mode Brushes")
for i, button in enumerate(buttons):
    layout.operator("sculpt.brush", text=button[0]).type = button[1]._name_
3 Comments
2023/11/25
10:46 UTC

1

MatLayer 2

Hi everyone,

I’ve been working for the past 5 months, putting roughly 6 – 10 hours a day (in addition to some of my heart and soul) to create the next version of my Blender add-on.

I’m very proud to announce the release of MatLayer 2!

For those who are not familiar, MatLayer is a 100% free Blender add-on that wraps the material nodes with a layer based user interface. This allows instant mixing of full PBR materials, emulation of industry leading material creation workflow, and implementation of many essential features for a fast and efficient material editing workflow.

Some of the main features of this add-on currently includes:

- A one-click mesh map baker for baking ambient occlusion, curvature, thickness, world space normals, and high to low poly normal maps, all heavily optimized to bake mesh maps as fast as possible.

- Fast, full PBR material layering, with lots of control, and built-in filters like blurring.

- Fast, optimized masking and multi-masking for materials.

- A toggle for true tri-planar projection (with corrected normals)!

- Auto-corrections for normal map projections.

- Decal layers for non-destructive projection of text / stickers.

- Basic support for merging materials.

- Fast effects for edge wear and dirt.

- Fast importing of full PBR texture sets.

- One-click exporting for texture sets with automatic channel packing for commonly used software applications and formats.

- An exporting options for baking multiple material slots to a single texture set.

The main focus of this release was initially better performance, bug fixes and stability, but I’ve implemented some massive improvements to workflow, quality and many new features!

To get MatLayer 2, and to see a full list of features and new changes in this version you can check out the latest release on the Github - https://github.com/LoganFairbairn/matlayer/releases

I plan on creating a new tutorial series, within the near future to help explain workflow and features available in the software.

Although MatLayer is still not a perfect software, I really hope you enjoy this add-on, I’ve put many long days and nights into this. I’m hoping this gives users the freedom to create some new amazing materials for their 3D models within Blender.

This add-on is my personal thank you to the Blender developers for making such an amazing software, and to the community for keeping it charged.

Cheers, and happy blending!

0 Comments
2023/11/22
14:30 UTC

1

Getting text data from geometry nodes

I've created a modifier that creates shapes using the bounding box data of an object. I now need to write the parameters (size, rotation, etc) of those shapes to a text file. I figured the best way to do that would be to grab the data from the node outputs but I'm having trouble with that. I can't seem to get anything to print using python.

For instance I have the X length of the bounding box using a "Separate XYZ" node which is a float. When I enter "bpy.data.node_groups["Modifier"].nodes["Separate XYZ.001"].outputs[0].default_value[1]" I get "'float' object is not subscriptable". When I try to convert it to a string in the text editor using "str()" I just get the same error. When I use the convert float to string node and try to print that the value is empty. I just get " ".

Any thoughts on how I can write the outputs of nodes to text?

0 Comments
2023/11/14
22:04 UTC

1

Interjecting a python script within the "render" path.

When you click "render" or "render animation" (or use the command line -f or -a) is there a way you can hook into those using python? I have multiple cameras with different rendering resolution for X and Y. So I need to mess with bpy.data.scenes["Scene"].render.resolution_y and bpy.data.scenes["Scene"].render.resolution_x before the render.

I can write a script to mimic -a or -f via the command line, but it would be nicer to hook into the existing UI buttons and CLI options.

2 Comments
2023/10/29
05:20 UTC

1

Blender App Template Examples | hello world | music visualizer | grapher

Hello friends! I have a few blender app templates to show off, I think the app template feature is pretty cool and has a lot of dope uses, I have a few of samples if anyone is interested in the types of things it can do, and also a couple questions is anyone knows.

These are not polished, bug-free apps but are samples that show how to setup a dev environment and get going with these.

This template turns blender into a music player with a sound synchronized visualizer made w geo nodes: https://github.com/b-rad-c/bl-music-player

This is a stripped down hello world example: https://github.com/b-rad-c/bl-hello-donut

This is a basic app for graphing data: https://github.com/b-rad-c/bl-app-grapher

Again they don't have tons of features but are enough to see what is possible w app templates.
Two questions I have:

  1. I'm looking to get a completely blank window so I can start from scratch, if you look at the bl-app-grapher, I'm using the property area to get user input, I'd like to get rid of the pin button and the icon, but I couldn't figure out how. Not sure if it's possible to create an area from scratch or to remove these two items.
  2. Best practices for including pip dependencies? The bl-app-grapher relies on matplotlib, everything works when I run the app from source but when I package it into a zip to distribute I realized the dependencies weren't getting copied in. I tried running pip with the --target flag to install the dips into the folder that I ended up zipping but that didn't work. Not sure if there is a better method, should I call pip dynamically during the app install process?

Thanks! Hope you enjoy the app templates!

0 Comments
2023/10/27
03:40 UTC

1

My simple add-on won't install - traceback error

Hello, so I have a very simple add-on. If I run it in the Scripting workspace, all is well.

If I try to install the .py file as an add-on through Preferences, I receive this error. Any ideas as to what's happening here?

Thanks in advance

https://preview.redd.it/ybuezf86kfwb1.png?width=781&format=png&auto=webp&s=b6b1aa4f2abd1b965231bedce383293bba7d1f24

0 Comments
2023/10/25
23:07 UTC

2

Free Tutorial Ground Destruction with Blender Geometry Nodes

0 Comments
2023/10/13
15:39 UTC

4

How to force Context to be 'Outliner' for using 'bpy.ops.outliner.select_walk' in the 3D Viewport?

Hi, I've been trying to use the 'bpy.ops.outliner.select_walk' functionality which walks up and down the list of objects in the outliner with the arrow keys. I want to use this functionality while in the context of the 3D viewport, similar to what ZBrush and Maya do by default. By default in Blender, this functionality only works when hovering the mouse over the Outliner and pressing the up and down arrow keys on the keyboard..

Therefore, I'm trying to make a Python script to force the context to be 'Outliner', even when I'm in the 3D viewport. Is this possible?

After some research, I have found and tried to adapt some existing examples such as the 2 different approaches below, which both use 'bpy.context.temp_override()'. However, I can't get either of these code to work in the scenario of forcing Outliner context whilst in the 3d viewport context. I can only get it to work for it's original purpose of overriding the Blender text editor context with the 'VIEW_3D' context, and performing an operator such as adding primitives and overriding.

I have errors in the VS Code terminal like:

ERROR (wm.operator): C:\Users\blender\git\blender-v360\blender.git\source\blender\windowmanager\intern\wm_event_system.cc:1551 wm_operator_invoke: invalid operator call 'OUTLINER_OT_select_walk'

Approach 1:

https://preview.redd.it/sd3p20vbiusb1.png?width=871&format=png&auto=webp&s=344decf9b154a3aaedd8c911edb432a9960f5990

Approach 2:

https://preview.redd.it/ciabkrbphusb1.png?width=721&format=png&auto=webp&s=755d2b000a2ded715f45352ad48159b59c8f29b4

I must be doing something wrong, any help would be much appreciated! Many thanks.

1 Comment
2023/10/07
21:07 UTC

2

Automatic Python atlas baking gives wrong Occlusion Roughness Metallic (Blender 3.3.1 LTS)

Hi everyone!

I've been developing a tool to automatically bake texture atlases and export GLB objects. However, I've come accross a pretty strange event: the output Occlusion Roughness Metallic (ORM) atlas looks way too bright. After digging a bit deeper, I realized it was particularly the roughness that was too bright (the only difference I see in my script is thatthe roughness is baked in "Roughness" mode, whereas metallic and ambient occlusion (AO) are baked in Emit mode). What is even stranger is that I don't have this problem when baking manually.

While digging even deeper, I found out that if I apply a gamma correction of 2.2 on the ORM, it gives it the appearance it should have. So my temporary solution could be to call Pillow and add a gamma correction to the output ORM, but I would very much like to understand why my script causes that in the first place.

So that's why I decided to turn to the community's wisdom :) If anyone can help me figure out what the heck is happening, I'd be most grateful.

Just a few more info on what I tried:
- I tried fiddling with the colorspaces, I'm on "Standard" rather than Filmic, I tried turning on the 'None' option on Display Device, and the original ORM texture to be baked is in Non color mode...

- I'm using the save_render function, I'm wondering whether the problem doesn't come from there, but when trying to use 'Image.save', the filepath argument I put in is not recognized...

Thank you very much for your help :)

1 Comment
2023/09/18
09:32 UTC

2

Pass list of Objects to Operator

I often deal with large CAD imports.
Now I'm working on an add-on that links all of the objects based on their names.

So, based on a selection of objects, I'm filtering through them and construct a dict in the form of:

dict = {
    '3323-310-0094_Bolt_M12_A4': [<object_00>, <object_01>, ... , <object_67>],
    '3323-310-0103_Nut_M12_A4': [<object_512>, <object_513>, ... , <object_874>],
    ....
    }

In order to build the UI, shown in the image, I iterate through the keys of the dict.

Now, I what to call two different operators and pass the list of objects to them.
The fist should just select all of the corresponding objects in the view-port and the other should link the object data.

I really struggle to find a solution to pass the list to the operators.
I've seen suggestions of using the bpy.props.IntProperty() class or similar solutions. But they all define a global variable. So in my example below, they would all just contain the last element of the dict.

I'd be grateful for any hints or suggestions!

Also, any idea how I can create a thumbnail image of an object on the fly?

UI-Concept

2 Comments
2023/09/02
10:40 UTC

2

Help with a Street-Generator Addon

https://preview.redd.it/pxh4mxha978b1.png?width=1321&format=png&auto=webp&s=e360169f8d5f6fa5fb777ae9ed7269c01e60a66d

I am trying to create an Addon for a Street Generator and want to add Objects along a Bezier-Curve using the Array Modifier. It worked well so far except that the Objects seem to get the angle around the y-axis depending on the angle of the z-angle as in the image. The trees are instances(faces) of planes that have the array- and a curve-modifier set on the bezier curve. The planes itself are in the correct orientation. Does anyone know if this is a problem I can fix by code? As I don't give any rotation for the instanced trees and don't know how to change it or why it changes at all?!
I'm still new to the Blender Python API and am happy for any help :)

1 Comment
2023/06/25
17:34 UTC

6

Help I am a marine biologist not a programmer

I have this project I am trying to automate, but I know next to nothing about programming, especially python. This is my first time using python. The lab I am in basically runs on R which I am in the process of learning, but no one else in my lab knows any python. Basically, I am trying to automate the process so that blender imports a file, remeshes it, triangulates it, then exports it. Heres the codes I have so far that works:

import bpy

bpy.ops.object.delete(use_global=False)

bpy.ops.import_mesh.stl(filepath="C://Users//aedan//Downloads//OneDrive_1_6-22-2023//Fish_1_bladder.stl")

bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN', center='MEDIAN')

bpy.context.scene.unit_settings.length_unit = 'MILLIMETERS'

bpy.ops.object.modifier_add(type='REMESH')

bpy.context.object.modifiers["Remesh"].voxel_size = 0.00025

bpy.ops.object.modifier_add(type='TRIANGULATE')

bpy.context.space_data.overlay.show_wireframes = True

The part I am having trouble is when I go to export it. I do not know how to write the code so that it gets exported as an .stl. Also it has to be an ascii file. When I export it manually there is a little box in the right hand corner I check off to indicate that it is ascii.

Here is the code I try unsuccessfully. I am trying to export it into a file named export:

bpy.ops.export_scene.stl(filepath="C://Users//aedan//Downloads//export",export_format=.stl)

There error I usually get is invalid syntax. How would I write the code in a way that specifies the file as a .stl, specifies it as ascii, specifies the name I want for the exported file(Fish_1_swimbladder_voxel_0.25.stl) and specifies which folder i want the exported file to go into.

Any advice is greatly appreciated. Again I am not a programmer, I just like fish. I am a fish programmer. I do fish stuff. Not computer stuff. STRIICTLY fish stuff. Fish dont have computers. Why do I have to have a computer I hate computers. I love fish. Fish hate computers. I love fish. Yet, I still need to do computer fish stuff from time to time. Even if they had computers how would that work? They dont have fingers. What kind of keyboard would they use? An octopus, sure, but they arent a fish. Techinically humans are fish. I mean thats an inaccurate statement, but it wouldnt be inaccurate to say we fall under the umbrella of fish. No thats not really accurate but again not inaccurate. I mean what even is a fish, huh? You tell me mr fish man. Mr I know all about fish FUCK YOU, Mr walkway. Mr walk me to the docks to go see some fish am I right? But what is a fish? Is it just cause its in the water, NO. Because then a fucking otter would be a fish wouldnt it. DO NOT even get me started with those little greedy no good backstabbing little fucks. A poikilothermic aquatic chordate covered scales with fins for appendages and gills for respiration? Well what about Tuna, they are homeothermic. Eels dont have appendages fucko. Cyclostomes dont have scales. Lungfish can breath out water using their physostomous swimbladder. Why arent sharks considered fish? Cause they are cartilaginous? But they have gills and are chordates and are poikilotherms. They even have scales and fins! You know what else "fish" dont have, .... d e f i n i t i o n s. All they know is swim n eat. but if we are fish(kinda) then we shouldnt have comupters right? right? Or definitions. I guess we are just shitty fish. I bet other fish see us flailing about in the water and think "jeez, blub blub blub". Fuck it mammals are fish too. There are plenty of aquatic mammals, like dugongs, whales, and dolphins. I think they got their shit together. We should go back to the sea. Become the fish we were really meant to be. No definitions or god forbid computers. I think if I was a fish I would be a reallly really cool fish like Will Smith fish. God I love Will Smith fish. Will Smith fish is sooooo cool. But this is the real world. I am not that cool. I am not a fish. God I with I was a fish. I love fish.

5 Comments
2023/06/23
14:39 UTC

9

Hi, I have made a Aircraft Generator in Blender

4 Comments
2023/06/15
13:18 UTC

Back To Top