First off, I'm very much a novice Blender user. I use Blender mainly for building mock-ups of PCBs that I design for customers to see how the designs will look when finished. (Yes, most professional PCB packages will do this for you, but I am an open-source nut and my chosen PCB design package doesn't, so I choose Blender. Also the results from Blender are far superior to what PCB packages make).

However, putting together a new PCB design in Blender is a time consuming thing, and I would love to automate it.

I have plenty of component models in blender files, all nicely textured and looking all spangly. Making the actual PCB substrate is simple enough - import an SVG of the outline and texture it with PNG exports from the PCB package. That side of things is all fine and I am happy doing that manually.

What I'd like to automate, though, is the importing of all the components from their respective blender files and positioning them within the scene. I have a CSV file with the ID, name, and location of each component, and currently I manually clone each component from a base model and type in the location details into Blender. Which works fine, it's just very slow.

Here's an example of the end result (I am still laying out some of the components on this one):

enter image description here

So I know that Blender can do fancy things with plugins written in Python. I am not a Python programmer, I do 99% of my programming in C and C++. That's not to say I can't program in Python, just that I don't, and as a result I don't know the finer points of Python crafting, but that will come as I learn.

As a result I'd like to write a plugin which can load this CSV file (specified at run time by me - preferably with a file browser window), parse it for components, find the right blender files (or the right models in a single large blender file, I am not fussy which), clone the models along with their textures, etc, and set the location of each one.

First off: is this something that is possible in Python in Blender, or am I asking too much of it with the automated file loading / model finding, etc?

Secondly: Where on earth would I start writing a plugin like this? I have absolutely no knowledge of how the internals of Blender work (which really helps things ;) ). Yes, I have the blender python API reference, but to use that I really need some idea of what I am looking for in it.

So I could do with a couple of things:

  • Some pointers to friendly plugin writing tutorials to kick-start my effort,
  • A clue as to which parts of the API would be of most interest to a plugin like this,
  • What would be the best way to store the component models:
    • A single file with all components in it, each named properly,
    • A file per component named after the component with the component named properly, or
    • A file per component named after the component with the component having a common name (such as "component")
  • Procedurally, what steps would need to occur for the plugin to do what I need of it (how I would put the different concepts from the API together to make it work).
  • I could probably do this for you. – cmomoney Dec 27 '16 at 17:29
  • @cmomoney I'm sure you could, but how would I learn then? ;) – Majenko Dec 27 '16 at 17:53
  • Just thought I would offer since you're using this for your business. – cmomoney Dec 27 '16 at 18:05
  • @cmomoney The offer is appreciated, but I like to do things myself and learn as I go. TBH I'm not that bothered by the end result, it's how I get there that is the interesting part. – Majenko Dec 27 '16 at 18:08
  • Understood. If you go by the last sentence of my answer, like steps, you can find your way. Most of the answers will be here(on stackexchange), and you can look at the templates in Blender's text editor. Good luck. :) – cmomoney Dec 27 '16 at 18:29
up vote 3 down vote accepted

This might get you started


import bpy
import csv

file_csv = ".../layout.csv"
file_components = ".../components.blend"

with open(file_csv, newline='') as fobj:
    reader = csv.reader(fobj)
    layout_table = list(reader)

required = set(col[1] for col in layout_table)

with bpy.data.libraries.load(file_components, link=True) as (data_from, data_to):
    available = set(data_from.meshes)
    missing = required - available
    data_to.meshes = list(required & available)

if missing:
    txt = bpy.data.texts.new("missing_components.txt")
    for comp in missing:
        txt.write(comp + "\n")

objects_data  = bpy.data.objects
objects_scene = bpy.context.scene.objects
name_to_index = {mesh.name: index for index, mesh in enumerate(data_to.meshes)}

def create_dupli(id, name, location):
    try:
        mesh = data_to.meshes[name_to_index[name]]
    except KeyError:
        return

    dupli = objects_data.new(id, mesh)
    dupli.location = location
    objects_scene.link(dupli)

for id, name, x, y, z in layout_table:
    loc = tuple(float(val) for val in (x, y, z))
    create_dupli(id, name, loc)
  • Nice. I like the use of bpy.data.texts for reporting missing components - very elegant. I need to brush up on my python though to understand some bits of it, especially the layout_table handling. I'd like to add a GUI at some point for selecting the files, too, but that can come later. This is a great start. Thanks. – Majenko Dec 28 '16 at 13:31
  • Just getting to grips with this now. One question: it looks like you are looking for meshes to import. I need to import finished objects (including their materials, textures, etc). Is it simple to modify this script to do that? – Majenko Dec 30 '16 at 23:25
  • Actually, it looks like you are looking for meshes by name then importing the full object. I guess I just need to change it to look for the objects by name, not the meshes? How would I change it to do that? – Majenko Dec 30 '16 at 23:32
  • I have it working nicely now (I am now naming all my meshes the same as the object for simplicity until I work out how all the relationships between things works in blender). It even finds and replaces existing objects with the same ID, which is nice. Working well. Thanks for your assistance and pointers. – Majenko Jan 1 '17 at 21:46

This is very possible and not really that hard. Your needs are pretty specific, so finding a tutorial that would help would be the hardest part. It might be easier to find a addon that does something close to what you want and look at the code. The part of the API to look into really depends on how you want it to work. All of the ways you're considering are possible and have no real advantage over one another. Basically, you'd open a file using the browser, read it for the name and position of the object, find the object in tje master file(s), then link or append the object at it designated position.

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.