I am trying to avoid splitting my attention between Cycles and Blender Render.
Attempting to stay with Cycles knowing that I will have little use of any other…
So, here is my solution to the problem, but applied to Cycles.
'''
Create credits from CVS - file.
BOOTSTRAP:
import os,sys,bpy;sys.path.append(os.path.dirname(bpy.data.filepath))
import importlib; importlib.reload(texture_painter)
'''
import bpy, sys, os, codecs, csv
from PIL import Image, ImageDraw, ImageFont
PDIR = os.path.dirname( bpy.data.filepath )
TEXDIR = 'textures'
class Props(object):
""" Args as props utility """
def __init__(self,data=None,**kv):
self.__dict__.update(kv)
if data: self.__dict__.update(data)
def __call__(self,data=None,**kv):
clone = Props(kv,**self.__dict__)
if data: clone.__dict__.update(data)
return clone
def PPath(*args):
return os.path.join(PDIR,*args)
def TextureFactory(text, **kv):
""" Create texture file.
Arguments:
text: The text to render
Keyed arguments (default):
imgsize = (512,64)
fontsize = 32
out = 'out.png'
margin = (20,20)
"""
imgsize = kv.get( 'imgsize',(512,64) )
fontsize = kv.get( 'fontsize',32 )
outfile = PPath( kv.get('out','out.png') )
pos = kv.get( 'margin',(20,20) )
# Initiate an image (w,h)
img = Image.new( 'RGB', imgsize )
# Initiate a font (sources?)
draw = ImageDraw.Draw(img)
fnt = ImageFont.truetype( PPath('defconzero.ttf'), fontsize )
# Use the font to project on the image
draw.text( pos, text, font=fnt )
# Save the image
img.save( outfile )
return outfile
def BackerIter( cvs_fname ):
""" Iterate csv - file, skipping the header.
Yields values as Props(Name=?,Number=?,Country=?)
Accessible as obj.Name, obj.Country ...
"""
with codecs.open(PPath(cvs_fname),'r','utf-8-sig') as file:
rip = csv.reader(file)
hdr = next(rip)
for row in rip:
yield Props(zip(hdr,row))
def get_single_selected():
if 1 != len(bpy.context.selected_objects):
raise Exception('Operation only valid with one selected template!')
return bpy.context.selected_objects[0]
def CloneFactory( templ, offset ):
bpy.ops.object.select_all(action='DESELECT')
templ.select=True
bpy.ops.object.duplicate_move( TRANSFORM_OT_translate={"value":offset })
new_brick = bpy.context.selected_objects[0]
new_brick.select = False
return new_brick
class Layout(Props):
""" Stateful placement tool
Keyword arguments
cols - Number of columns
xpad - Padding between 'bricks' in x
ypad - Padding between 'bricks' in y
"""
def __call__(self, idx):
row = idx // self.cols
col = idx % self.cols
return ( col * (2 + self.xpad), row * (1 + self.ypad), 0 )
def BrickFactory( templ, backer, idx ):
""" Create brick
"""
text = ', '.join( (backer.Name, backer.Country) )
fname = PPath(TEXDIR,'%d.png'%idx)
texture_file = TextureFactory(text, fontsize=42, out=fname, margin=(10,9))
placer = Layout(cols=3,xpad=.1,ypad=.1)
if idx:
new_brick = CloneFactory(templ=templ, offset=placer(idx))
else:
new_brick = templ
new_mat = templ.material_slots[0].material.copy()
new_mat.name = 'GeneratedMaterial%d'%idx
new_img = bpy.data.images.load(texture_file)
new_mat.node_tree.nodes.get('Image Texture').image = new_img
new_brick.material_slots[0].material = new_mat
def go():
templ = get_single_selected()
for idx, backer in enumerate(BackerIter('backers_10.csv')):
BrickFactory( templ, backer, idx )
Hopefully this is useful further on…