Floor board generator, using a floor plan

I have started on the support for a floor plan, i.e. restricting the generated planks to some outline. This feature is very much a work in progress but it is already useable:
It works by adding and applying a boolean modifier to the generated floorboards.

The current [updated] workflow is like this:
  • select your floor plan, make sure it is flat, has a number of faces selected and the face normals pointing up:

  • position the 3D cursor just outside the bottom left corner of the floor plan
  • choose Add -> Mesh -> Add floor board mesh
  • adjust the number of planks and their length (in the modifier tab!)

    • select 'use floorplan' and select your floor plan mesh

      What is left to automate is probably to make sure the floor board is position at the lower left corner of the floor plan because that is easy to forget. You can change the position of the generated floor board but then you have to tweak some attribute (like the number of planks for example) to make it calculate a new floor board, which is ugly.

      For those who find a video easier to understand, here's a short screencast of the workflow:

      Code availability

      You can download version 0.0.15 form GitHub to try out this new functionality. If you already installed a previous version don't forget to remove the old version before installing the new one. (You can remove an old version by deleting the file planks.py from your Blender addons directory (on Windows typically in C:\Users\<your user name>\AppData\Roaming\Blender Foundation\Blender\2.71\scripts\addons )

      Known issues

      The sides of the planks are currently not properly uv mapped, something that may show when large gaps are used.

      Previous articles on the floor board addon

      The development and use of this addon is documented in several earlier articles:

      Part I initial version
      Part II random uv-coordinates
      Part III random vertex colors
      Part IV additional options
      Part V randomization
      Part VI small enhancements

      It is also extensively discussed in this BlenderArtists thread.

      EnumProperty callback problems - a better workaround

      A frequent use case of EnumProperties in Blender addons is to display a dropdown with a choice of scene objects. Of course which objects are available in a scene is only known when invoking the addon so a fixed list of choices is of no use here. For this scenario a callback option is provided. The callback can be any function that returns a list of choices. Unfortunately there are a number of severe bugs associated with using a callback: if your python code doesn't keep a reference to the items in the list it returns, Blender may crash. This bug is documented and a workaround suggested but this doesn't solve the problem completely. Have a look at the code below:
      import bpy
      from bpy.props import EnumProperty
      available_objects = []
      def availableObjects(self, context):
       for ob in bpy.data.objects:
        name = ob.name
        available_objects.append((name, name, name))
       return available_objects
      class TestCase(bpy.types.Operator):
       bl_idname = "object.testcase"
       bl_label = "TestCase"
       bl_options = {'REGISTER', 'UNDO'}
       objects = EnumProperty(name="Objects", items = availableObjects)
      if we hover the mouse over the second or third option we see that the description shows garbage, i.e. the description part of another item!
      The really annoying part is that even if we make a full copy of the object's name (with ob.name[:]) the problem isn't solved. So probably the internal callback code trashes memory even outside its own allocated memory.
      def availableObjects(self, context):
       for ob in bpy.data.objects:
        name = ob.name[:] # a copy, not just a reference
        available_objects.append((name, name, name))
       return available_objects
      A way around this is to let the callback just return a list that is filled with values outside the callback code, for example in the code thst is executed when the user clicks on the menu item that selects the addon:
      available_objects = []
      def availableObjectsInit(self, context):
       for ob in bpy.data.objects:
        name = ob.name[:] # a copy, not just a reference
        available_objects.append((name, name, name))
       return available_objects
      class TestCase(bpy.types.Operator):
              ... stuff omitted ... 
       objects = EnumProperty(name="Objects",
                          items = lambda self,context: available_objects)
      def menu_func(self, context):
       availableObjectsInit(self, context)
      def register():
      This is usable even if the addon changes the number of objects. The only downside is that the code isn't reentrant because in its present form does not guard thread access to the global variable but as far as I know the Blender UI runs as part of a single Python interpreter so there's only one thread, which renders this point moot. The other issue is that it looks ugly, but as long as it works that's a minor issue :-) Note: you might wonder why we need the lambda here but that's because if we would point to just the list here, the list would be empty at the point where the EnumProperty was defined and apparently it makes a copy of that list so it would stay empty.

      WeightLifter - My first BlenderMarket addon

      I am quite proud to announce my first addon that's available on BlenderMarket!

      The addon combines a lot functionality in a single comprehensive addon. There's a tutorial online as well, demoing the most eyecatching features and I hope it will be useful to not just ArchViz people!

      Update: there is now an update available that fixes a crash that could happen when assiging random weights to groups of connected vertices in large meshes.