Reputation: 403
I am writing a script for Luxology modo (3D and VFX application), which is using python as scripting language. Somewhere in my script i am reading text file outputted from other app, and creating materials and image maps from the lines of this text file. one of the things i am doing there is creating a dictionary of the channel names from this text file, and mapping each channel name to the modo's internal channel name, so modo could understand what to do with this channels. This is a snippet that doing it:
# this is a dictionary of the channel names in the textures.txt file
# mapped to modo's internal channel names
channels = {'color':'diffColor', 'specular':'specAmount', 'normalmap':'normal'}
for channel in channels:
if channel in materials[mat].keys():
============AND SO ON==============
Everything works as expected, but there is one more channel - displacement. And the problem is that it's not just a string as other channels, but a string followed by a float number, which is a scale factor for displacement, like this: displacement 19.378531
For now i want just to create displacement image map in modo, as i am already doing with other maps (color, normals, specular), without using this 'scale factor' number in any way. It seems easy enough, and i have tried to use Regular Expression to match string "displacement" followed by random float number, but it does not works (or, i do not use it properly)!
How can i tell python to do instead of
channels = {'color':'diffColor', 'specular':'specAmount', 'normalmap':'normal', 'displacement':'displace'}
to do this:
channels = {'color':'diffColor', 'specular':'specAmount', 'normalmap':'normal', 'displacement' + 'ANY_FLOAT_NUMBER':'displace'}
Upvotes: 1
Views: 373
Reputation: 2196
Based on your pastebin, I believe this should work for you:
# ...
infile.close()
channels = {'color':'diffColor', 'specular':'specAmount', 'normalmap':'normal'}
re_dis = re.compile(r'displacement\s[-+]?[0-9]*\.?[0-9]+')
for material, values in materials.items():
lx.eval('select.item {Matr: %s} set textureLayer' % material)
uvmap = materials[material]['uvmap']
for v in values:
m = re_dis.match(v)
if m or v in channels.keys():
lx.eval('shader.create constant')
lx.eval('item.setType imageMap textureLayer')
imagepath = materials[material][v]
imagename = os.path.splitext(os.path.basename(imagepath))[0]
lx.eval('clip.addStill {%s}' % imagepath)
lx.eval('texture.setIMap {%s}' % imagename)
if m:
# we can't auto map to the channels dict
lx.eval('shader.setEffect %s' % 'displace')
else:
lx.eval('shader.setEffect %s' % channels[v])
Also don't forget to add import re
to the top of your script.
Upvotes: 0
Reputation: 14258
You can do this using standard string methods to strip the coefficient from the string if it begins with 'displacement':
for material in materials[mat].keys():
if material.startswith('displacement'):
# coefficient = float(material.split('displacement')[1])
material = material.rstrip('0123456789.')
if material in channels:
channelName = channels[material]
...
I've added commented-out instruction that you can uncomment if you later decide you want the coefficient (might be important if you start getting displacement artefacts!).
Edit after reading comments and full code.
You can't have anything programmatic or varying in a dictionary key. But if you want to keep the pattern you've already got, the simplest solution would be to ignore my suggestion above and just remove the floats at the end before you start searching with a quick loop like this:
for channel in channels:
for key in materials[mat].keys():
if "." in key:
materials[mat][key.rstrip("0123456789.")] = materials[mat].pop(key)
if channel in materials[mat].keys():
Upvotes: 1
Reputation: 610
I'm not entirely sure I understand the question, but I think you just have to do something a bit less efficient:
for material in materials:
if material in channels:
...
if 'displacement' in material:
...
Upvotes: 0