Aurore DELAUNAY
Lead TD
+33 (0)7 70 16 38 93
PROJECTS
Arcane 2018-2024
Problem solving, Python, Management
Python, Guerilla, Maya, Nuke, Mari, Photoshop, After Effects, Deadline, Shotgun
Living Universe 2018
Set-dress, lighting, rendering and scripts
3ds Max, VRay, Nuke, Maxscript, Python
Legends Never Die 2017
Compositing
Nuke
Pipas & Douglas 2016
Look-dev, lighting, rendering and compositing
Guerilla, Nuke
Mishimasaiko 2014-2015
Look-dev, lighting, rendering, compositing and scripts
Maya, VRay, Nuke, Mudbox, Mari, Photoshop, Python, mel, C++
The Red Herring 2013
Rigging, skinning and scripts
Softimage, Maxwell, Python
Coors 2012
Character rigging, skinning and scripts
3DS Max, RPM, Maxscript
Trois Petits Chats 2012
Co-direction, modeling, skinning, props rigging, look-dev, lighting, rendering, compositing, scripts
3DS Max, VRay, Nuke, Photoshop, Maxscript
Egaro 2011
Rigging, skinning, look-dev, lighting, rendering, compositing and scripts
3DS Max, mental ray, Nuke, Maxscript
No Brain 2010
Fractal sequence (1:40-2:04) concept, look-dev, modeling, animation, rendering and compositing
Maya, mental ray, Mudbox, Photoshop, After Effects
La Belette Entrée dans un Grenier 2010
Modeling, animation, look-dev, rendering and compositing
3DS Max, mental ray, After Effects, Photoshop
EXPERIENCE
Lead TD Fortiche in France (2019-current) Problem solving, Python, Management Arcane
Technical Director Fortiche in France (2018-2019) Problem solving, Python Arcane
Nuke TD FIX Studio, Remote 3 months (2018) Nuke gizmo, Python
3D Generalist Fauns in France 6 months (2017-2018) Living Universe
Nuke Artist Passion Pictures in England 1 month (2017) Legends Never Die
3D Generalist Studio AKA in England 3 weeks (2017) Layout, look-dev, lighting, rendering, compositing
3D Generalist 17 MARS in France 2 weeks (2017) Modeling, look-dev, lighting, rendering
Look dev, Lighting & Compositing Supervisor Studio Hari in France 2 months (2016) Pipas & Douglas
Director of Photography Lardux Films in France 2 years (2014-2015) Mishimasaiko
Rigging Ink & Light in Ireland 8 weeks (2013) The Red Herring
Nuke artist DesignStudio in England 6 weeks (2013) Compositing
3D Generalist MFP in France 2 weeks (2013) Props, animation, lighting, rendering, compositing
3D Generalist ThreeDee in France 7 months (2013) Modeling, shading, VFX, lighting, compositing
3D Generalist Cube in France 5 weeks (2013) Shading, VFX, Maxscript
Rigging Nexus Productions in England 3 weeks (2012) Coors
3D Generalist Mazedia in France 6 weeks (2012) Modeling, shading
Student Volunteer Siggraph Los Angeles (2012)
Student Volunteer Siggraph Vancouver (2011)
3D Generalist Mathematic Studio in France 2 months (2010) No Brain
STUDIES
Formation: Studio Lighting INA in France 1 week (2016) Photography, portrait, still life
Supinfocom Valenciennes 5 years (2007-2012) Graphic arts, live action, 2D animation, Trois Petits Chats, Egaro, La Belette
Graphic arts course Sépia 1 year (2007) Drawing, painting, ink
Baccalauréat science with honors 2 years early (2006)
SKILLS & SOFTWARES
Good communication, problem solving, knowledge of every step of the 3D pipeline, able to work in a team and independently, good stress and pressure management, multitasking and attention to detail.
Maya, 3ds Max, Softimage, Mari, Mudbox, Topogun
VRay, Guerilla, Arnold, Mental ray
Nuke, Combustion
Python, basics of C++, git, shotgun, Nuke gizmos, Maxscript, Mel, HTML, CSS and JS
Photoshop, Illustrator, Final Cut, Avid, Lightworks
Windows and Mac OS, slowly learning Unix
Fluent English, native French, notions of German, Irish and Chinese
Passion for ski and sport in general, board and video games, Hitchcock, hitchhiking, photography and food.
A 9 x 35 minutes serie in the League of Legends universe
A 4 x 52 minutes documentary about space with tons of CGI. I came in to do a lot of lighting, rendering, pipeline and some set-dress and comp. There were a few challenges, namely working with Maya and Max on the same project, having close-ups in scenes a million km wide, working with 50 million polys and huge textures in 3ds Max.
A 13' short film directed by Aude Danset.
I was in charge of the look dev, lighting, rendering, compositing, outlines and most of the pipeline. Finding a good 2D/3D compromise and achieving the final look was tough. The outlines required flexibility and as such, were made in post-production, allowing us to have full control over visibility, size and colour until the very last minute. It relies on quite a lot of expressions, heavy scripting and huge Nuke gizmos but could be applied to any project. I also had the opportunity to manage two lighting / compositing interns for a few months. The visual style, pre-production drawings, backgrounds and quite a few static outlines were done by Minchi.
A two month collaboration with the great Frédéric Lafay to make the first three episodes. I learnt Guerilla and was in charge of the shading, lighting, rendering and compositing. I worked closely with Frédéric on two lookdev options : a flat version and this one. The directors picked their favorite, then I set up the details, finished the assets, optimized the scenes and fitted everything in the studio pipeline. Texturing was handled by another artist. The first episode is available online.
My graduation short-film, co-directed and produced with Maïwenn le Borgne, Albane Hertault Lacoste and Alexia Provoost. I was in charge of the pipeline, half the characters modeling, props rigging, characters skinning, shading, lighting, rendering, compositing and scripting. I developped a small render pass manager to suit our needs, a tool to import, export, merge and update materials and a few scripts to drastically improve the texturing and matte painting process. The boy and mood boards drawings included here were made by Maiwenn, along with all the design, visual research, color boards, textures, etc.
A 6' short film directed by Leevi Lemmetty produced at Ink & Light in Dublin, Ireland. I learnt Softimage then did the Characters, props and machines rigging. I also spent some time working on the stop-motion feeling, with baked and animated procedural displacement.
A 5' short-film co-directed with Maïwenn le Borgne, Anaëlle Moreau, Alexia Provoost and Simon Taroni. Based on a story and graphic universe by Bruno Salamone. I was in charge of the pipeline, shading, lighting, rendering, compositing and some scripting to make life easier.
No Brain by Étienne de Crécy. I made the fractal part, including camera animation, from 1:40 to 2:04.
Coors advertising, I did some character rigging and skinning.
Ink, paper and a lot of patience.
Illustrator Mesh Tool.
CheckIO is an online game for Python and JavaScript coders. Most of my solutions are on their website and on GitHub.
# Pawn Brotherhood | |
# You are given a set of square coordinates | |
# where we have placed white pawns. | |
# You should count how many pawns are safe. | |
# safe_pawns({"b4", "d4", "f4", "c3", "e3", "g5", "d2"}) == 6 | |
def safe_pawns(pawns): | |
safe = 0 | |
for col, row in pawns: | |
defense_row = str(int(row) - 1) | |
defense_left = chr(ord(col) - 1) + defense_row | |
defense_right = chr(ord(col) + 1) + defense_row | |
if defense_left in pawns or defense_right in pawns: | |
safe += 1 | |
return safe |
# Ghosts age | |
# Help Nicola write a function which will determine the age of a ghost based on | |
# its opacity. You are given opacity measurements as a number ranging from 0 to | |
# 10000 inclusively. The ghosts cannot be older than 5000 years as they simply | |
# disappear after such a long time (really!). | |
# This is a Halloween task so you should try and write a "magic" or "scary" | |
# solution. Please, do not write "regular" solution. | |
# checkio(9990) == 5 | |
def checkio(B00): | |
BO0, B0O, BOO = 1, 1, 0 | |
while B00 != 10000: | |
BOO += 1 | |
if BOO == B0O: | |
B00 += B0O | |
BO0, B0O = B0O, BO0 + B0O | |
else: | |
B00 -= 1 | |
return BOO |
# Golden Pyramid | |
# Consider a tuple of tuples in which the first tuple has one integer and each | |
# consecutive tuple has one more integer then the last. Such a tuple of tuples | |
# would look like a triangle. You should write a program that will help Stephan | |
# find the highest possible sum on the most profitable route down the pyramid. | |
# All routes down the pyramid involve stepping down and to the left or down and | |
# to the right. | |
# count_gold(((9,), | |
# (2, 2), | |
# (3, 3, 3), | |
# (4, 4, 4, 4) | |
# )) == 18 | |
def count_gold(pyramid): | |
# start at the bottom | |
sums = list(pyramid[-1]) | |
# go up | |
for row in pyramid[-2::-1]: | |
for i, gold in enumerate(row): | |
# check left and right descendants, keep max sum | |
sums[i] = max(sums[i] + gold, sums[i + 1] + gold) | |
sums.pop() | |
return sums[0] |
CodinGame is a challenge-based training platform for programmers where you can improve your coding skills with fun exercises. I am going through the Hard ones in Python and Medium ones in C++.
I took part in the 2016 and 2017 editions, qualification and round 1. My solutions are on GitHub.
import os | |
import sys | |
script = __file__ | |
scriptPath = os.path.dirname(script) | |
scriptFile = os.path.basename(script)[0] | |
files = [f for f in os.listdir(scriptPath) if scriptFile in f and '.in' in f] | |
if '{}-large'.format(scriptFile) in str(files): | |
size = 'large' | |
elif '{}-small'.format(scriptFile) in str(files): | |
size = 'small' | |
elif '{}-test'.format(scriptFile) in str(files): | |
size = 'test' | |
else: | |
print('{}-test not found'.format(scriptFile)) | |
sys.exit() | |
latest = sorted(f for f in files if size in f)[-1][:-3] | |
f = '{}/{}'.format(scriptPath, latest) | |
i = open(f + '.in', 'r') | |
o = open(f + '.out', 'w') | |
print(f) | |
T = int(i.readline()) | |
# https://code.google.com/codejam/contest/4304486/dashboard#s=p0 | |
# Problem A. The Last Word | |
for x in range(T): | |
S = list(i.readline().rstrip()) | |
y = S[0] | |
for s in S[1:]: | |
y = max(y + s, s + y) | |
o.write('{}Case #{}: {}'.format(['', '\n'][x > 0], x + 1, y)) | |
i.close() | |
o.close() |
import os | |
import sys | |
script = __file__ | |
scriptPath = os.path.dirname(script) | |
scriptFile = os.path.basename(script)[0] | |
files = [f for f in os.listdir(scriptPath) if scriptFile in f and '.in' in f] | |
if '{}-large'.format(scriptFile) in str(files): | |
size = 'large' | |
elif '{}-small'.format(scriptFile) in str(files): | |
size = 'small' | |
elif '{}-test'.format(scriptFile) in str(files): | |
size = 'test' | |
else: | |
print('{}-test not found'.format(scriptFile)) | |
sys.exit() | |
latest = sorted(f for f in files if size in f)[-1][:-3] | |
f = '{}/{}'.format(scriptPath, latest) | |
i = open(f + '.in', 'r') | |
o = open(f + '.out', 'w') | |
print(f) | |
T = int(i.readline()) | |
# https://code.google.com/codejam/contest/4304486/dashboard#s=p1 | |
# Problem B. Rank and File | |
for x in range(T): | |
N = int(i.readline()) | |
S = [int(s) for l in range(2 * N - 1) for s in i.readline().rstrip().split()] | |
y = ' '.join(str(t) for t in sorted(set(s for s in S if S.count(s) % 2))) | |
o.write('{}Case #{}: {}'.format(['', '\n'][x > 0], x + 1, y)) | |
i.close() | |
o.close() |
import os | |
import sys | |
script = __file__ | |
scriptPath = os.path.dirname(script) | |
scriptFile = os.path.basename(script)[0] | |
files = [f for f in os.listdir(scriptPath) if scriptFile in f and '.in' in f] | |
if '{}-large'.format(scriptFile) in str(files): | |
size = 'large' | |
elif '{}-small'.format(scriptFile) in str(files): | |
size = 'small' | |
elif '{}-test'.format(scriptFile) in str(files): | |
size = 'test' | |
else: | |
print('{}-test not found'.format(scriptFile)) | |
sys.exit() | |
latest = sorted(f for f in files if size in f)[0][:-3] | |
f = '{}/{}'.format(scriptPath, latest) | |
i = open(f + '.in', 'r') | |
o = open(f + '.out', 'w') | |
print(f) | |
T = int(i.readline()) | |
# https://code.google.com/codejam/contest/6254486/dashboard#s=p2 | |
# Problem C. Coin Jam | |
from itertools import * | |
import numpy | |
def primesfrom2to(n): | |
sieve = numpy.ones(n // 3 + (n % 6 == 2), dtype=numpy.bool) | |
sieve[0] = False | |
for i in range(int(n ** 0.5) // 3 + 1): | |
if sieve[i]: | |
k = 3 * i + 1 | 1 | |
sieve[(k * k) // 3::2 * k] = False | |
sieve[(k * k + 4 * k - 2 * k * (i & 1)) // 3::2 * k] = False | |
return numpy.r_[2, 3, (3 * numpy.nonzero(sieve)[0] + 1) | 1] | |
primes = primesfrom2to(100) | |
for x in range(T): | |
o.write('Case #{}:'.format(x + 1)) | |
N, J = map(int, i.readline().split()) | |
for j in product('01', repeat=int(N) - 2): | |
y = '1{}1'.format(''.join(j)) | |
divs = [] | |
for base in range(2, 11): | |
for d in primes: | |
if not int(y, base) % d: | |
divs.append(str(d)) | |
break | |
else: | |
break | |
else: | |
J -= 1 | |
o.write('\n{} {}'.format(y, ' '.join(divs))) | |
if J == 0: | |
break | |
i.close() | |
o.close() |
Currently at Problem 27. My solutions are on GitHub.
Mishimasaiko required a lot of scripting. Things like unfolding hundreds of thousands of UVs, handling a lot of different render passes and layers, recreating complex scenes on the fly and many more. Here are a few simple ones.
Show Maya AffinityAssign n % of your cores to maya.
import sys | |
# psutil cannot be used from inside maya. | |
# Install python then psutil | |
try: | |
import psutil | |
except: | |
pass | |
# Assigns n% of your cores to maya | |
# n should be between 0 and 100. | |
def affinity(n): | |
total = psutil.cpu_count() | |
assigned = int(total * max(0, min(1, n / 100))) | |
for p in psutil.process_iter(): | |
proc = p.as_dict(attrs=['pid', 'name']) | |
if proc['name'] in ['mayabatch.exe', 'maya.exe']: | |
p.cpu_affinity(range(total - assigned, total)) | |
if __name__ == "__main__": | |
affinity(float(sys.argv[1])) |
Show Export UVsExport UVs as PNG to sourceimages/edits folder.
import maya.cmds as mc | |
import os | |
# Export UVs as PNG to sourceimages/edits folder | |
def exportuvs(): | |
filePath = mc.file(sn=1, q=1).split('/') | |
place = filePath[:-1] | |
superPath = '/'.join(place) + '/sourceimages/edits/' | |
if not os.path.isdir(superPath): | |
os.makedirs(superPath) | |
for i in mc.ls(sl=1): | |
mc.uvSnapshot(i, o=1, n='{0}UVs_{1}.png'.format(superPath, i.split(':')[-1]), xr=4096, yr=4096, aa=1, ff='png') |
Show Export OBJAdd a smooth (1 iteration) then export each selected mesh an an OBJ.
import maya.cmds as mc | |
import os | |
import re | |
# export obj to obj folder in shading directory | |
def exportobj(d="M:/Assets/OBJ/"): | |
if not mc.pluginInfo('objExport', q=1, l=1): | |
mc.loadPlugin('objExport', quiet=1) | |
mc.pluginInfo('objExport', e=1, a=1) | |
if not os.path.isdir(d): | |
os.makedirs(d) | |
sel = mc.ls(sl=1) | |
actualSel = set(mc.ls(sel, type='transform')) | |
for s in sel: | |
if mc.nodeType(s) != 'transform': | |
mc.select(s) | |
out = mc.listConnections(s + '.outColor') | |
if out and mc.nodeType(out) != 'shadingEngine': | |
mc.select(out) | |
mc.hyperShade(objects='') | |
actualSel |= set([mc.listRelatives(j, parent=1)[0] for j in mc.ls(sl=1)]) | |
sortedSel = {} | |
for s in actualSel: | |
oldAttr = mc.getAttr(s + '.vrayUserAttributes') | |
oname = re.findall('(?<=oname=)[^;]*', oldAttr) | |
if oname and 'contour=1' in oldAttr: | |
if oname[0] not in sortedSel.keys(): | |
sortedSel[oname[0]] = [s] | |
else: | |
sortedSel[oname[0]] += [s] | |
else: | |
print('check this one - ' + s) | |
for key, val in sortedSel.iteritems(): | |
mc.select(val) | |
for mesh in val: | |
mc.polySmooth(mesh, keepBorder=0, divisions=1, keepTessellation=0, | |
mth=0, bnr=1, kmb=0, suv=1, sl=1, dpe=1, ps=.1, ro=1, | |
ch=0) | |
mc.file(d + key, f=1, typ='OBJexport', es=1, | |
options='groups=1;ptgroups=1;materials=0;smoothing=1;normals=1') | |
print(d) |
Show Duplicate LightDuplicate a light, keeping the same light and shadow-linking.
import maya.cmds as mc | |
# Duplicate a light keeping the same light and shadow-linking. | |
def duplights(): | |
allShapes = set(mc.ls(ni=1, type=('mesh', 'nurbsSurface', 'subdiv'))) | |
sel = mc.ls(sl=1) | |
for old in sel: | |
new = mc.duplicate(old, rr=1) | |
lightLinkInclude = mc.ls(mc.lightlink(q=1, l=old), typ='shape') | |
lightLinkExclude = allShapes - set(lightLinkInclude) | |
excludeList = [mc.listRelatives(j, type='transform', p=1)[0] for j in lightLinkExclude] | |
mc.lightlink(b=True, light=new, object=excludeList) | |
shadowLinkInclude = mc.ls(mc.lightlink(q=1, l=old, shadow=1), typ='shape') | |
shadowLinkExclude = allShapes - set(shadowLinkInclude) | |
excludeList = [mc.listRelatives(j, type='transform', p=1)[0] for j in shadowLinkExclude] | |
mc.lightlink(b=True, light=new, object=excludeList, shadow=1) |
Show VRay User AttributesCheck, set or overwrite a transform's VRayUserAttribute.
import maya.cmds as mc | |
import maya.mel as mel | |
import loadvray | |
# If the vrayUserAttribute doesn't exist, create it. If it does, overwrite it's value. | |
def setAttrVray(attr, value): | |
loadvray.loadvray() | |
trans, attr = attr.split('.') | |
mc.vray('addAttributesFromGroup', trans, 'vray_user_attributes', 1) | |
mel.eval('vrayAddAttr {0} "vrayUserAttributes"'.format(trans)) | |
oldValue = mc.getAttr(trans + '.vrayUserAttributes').replace(';;', ';').strip(';') | |
if oldValue: | |
ExtraAttrs = dict(s.split('=') for s in oldValue.split(';')) | |
else: | |
ExtraAttrs = {} | |
ExtraAttrs[attr] = value | |
newValue = ';'.join('{0}={1}'.format(k, v) for k, v in ExtraAttrs.items() if v != '') | |
mc.setAttr(trans + '.vrayUserAttributes', newValue, type='string') | |
# Check for a vray user attribute | |
# Example: hasAttrVray(pSphere1.objID) | |
def hasAttrVray(attr): | |
trans, attr = attr.split('.') | |
try: | |
return attr in mc.getAttr(trans + '.vrayUserAttributes') | |
except: | |
return False |
Show VRayMtl on SelectionAssign a vrayMtl, a file and a 2dTexCoordinates to each selected transform.
import maya.cmds as mc | |
import maya.mel as mel | |
# assign a vrayMtl, a file and a 2dTexCoordinates to each selected object | |
def mtlstd(): | |
shadersList, filesList = [], [] | |
sel = mc.ls(sl=1) | |
if not sel: | |
print('no selection'), | |
for i in sel: | |
superShader = mc.shadingNode('VRayMtl', asShader=1, name='sh' + i[1:]) | |
superFile = mc.shadingNode('file', asTexture=1) | |
mc.vray('addAttributesFromGroup', superFile, 'vray_file_gamma', 1) | |
for attr in ['vrayFileGammaEnable', 'vrayFileColorSpace', 'vrayFileGammaValue']: | |
mel.eval('vrayAddAttr {0} "{1}"'.format(superFile, attr)) | |
mc.setAttr(superFile + '.vrayFileGammaValue', 1) | |
mc.setAttr(superFile + '.filterType', 3) | |
mc.vray('addAttributesFromGroup', superFile, 'vray_texture_filter', 1) | |
for attr in ['vrayOverrideTextureFilter', 'vrayTextureFilter', 'vrayTextureSmoothType']: | |
mel.eval('vrayAddAttr {0} "{1}"'.format(superFile, attr)) | |
mc.setAttr(superFile + '.vrayTextureFilter', 1) | |
mc.setAttr(superFile + '.vrayTextureSmoothType', 1) | |
filesList.append(superFile) | |
superSG = mc.sets(renderable=1, noSurfaceShader=1, empty=1) | |
p2DT = mc.shadingNode('place2dTexture', asUtility=1) | |
shadersList.append(superShader) | |
connections = ['.coverage', '.translateFrame', '.rotateFrame', '.mirrorU', | |
'.mirrorV', '.stagger', '.wrapU', '.wrapV', '.repeatUV', | |
'.offset', '.rotateUV', '.noiseUV', '.vertexUvOne', | |
'.vertexUvTwo', '.vertexUvThree', '.vertexCameraOne'] | |
for c in connections: | |
mc.connectAttr(p2DT + c, superFile + c, f=1) | |
mc.connectAttr(p2DT + '.outUV', superFile + '.uv', f=1) | |
mc.connectAttr(p2DT + '.outUvFilterSize', superFile + '.uvFilterSize', f=1) | |
mc.connectAttr(superShader + '.outColor', superSG + '.surfaceShader', f=1) | |
mc.connectAttr(superFile + '.outColor', superShader + '.color', f=1) | |
mc.select(i) | |
mc.hyperShade(a=superShader) | |
mc.select(shadersList) | |
mc.HypershadeWindow() | |
panel = mel.eval('hyperShadePanelName()') | |
mel.eval('hyperShadePanelGraphCommand("{0}", "showUpstream")'.format(panel)) | |
mc.select(filesList) |
Show Fix VRay VFBBring back your VRayVFB when it won't open at all, despite many clicks.
import maya.cmds as mc | |
import re | |
# useful when your vray VFB window won't open at all | |
def fixvfb(): | |
file_path = mc.file(q=1, sn=1) | |
if mc.confirmDialog(m='you sure you just saved ?', b=['Yes', 'No'], db='Yes', cb='No', ds='No') == 'Yes': | |
mc.file(f=1, new=1) | |
with open(file_path, 'r+') as f: | |
read_data = f.read() | |
write_data = re.sub('\n\tsetAttr ".vfbSA[^;]*;', '', read_data) | |
with open(file_path, 'w+') as f: | |
f.write(write_data) | |
mc.file(file_path, o=1, iv=1) |
These scrips are for 3ds max 2012 and are not guaranteed to work on more recent versions. Some heavier scripting included a render pass manager, bits of autorig, an assets manager, a LAN messaging service and a materials manager with import, export, merge and replace features.
Show Super Incremental SaveMake a copy of your file, move it to a "_OLD" subfolder and increment it, then save in place.
macroScript Super_Incremental_Save | |
category:"Pouf" | |
toolTip:"Super Incremental Save" ( | |
-- if max file has not been saved yet, display save dialog | |
if maxFileName == "" do checkForSave() | |
if maxFileName != "" do ( | |
d = maxFilePath + "_OLD\\" | |
base = d + getFilenameFile maxfilename + "_" | |
ext = getFilenameType maxfilename | |
-- create "_OLD" directory in the max file directory if it does not exist | |
makeDir (d) | |
-- arbitrary, half the average number of versions for a single file. | |
-- Preferably 2^something. Very important, it has to be a float number (with a . ) | |
j = 32. | |
-- 4 is the number of digits, like "_0069.max". | |
while doesFileExist (base + (FormattedPrint j format:"04.f") + ext) do j *= 2 | |
-- as soon as we are over the number of saves, use any approximation algo | |
i = j / 2 | |
while (j - i) > .5 do ( | |
if doesFileExist (base + (FormattedPrint i format:"04.f") + ext) then ( | |
i += (j - i) / 2 | |
) else ( | |
temp = i | |
i -= (j - i) / 2 | |
j = temp | |
) | |
) | |
-- copy old file with increment to the _OLD directory | |
copyFile (maxFilePath + maxFileName) (base + (FormattedPrint i format:"04.f") + ext) | |
-- save normally | |
max file save | |
) | |
) -- bendelaunay.com |
Show Super MaskRender a white on black mask of each selected object or the entire selection. Great for cam maps.
macroScript Super_Mask | |
category:"Pouf" | |
tooltip: "Super Mask" | |
icon:#("PFSubObjectIcons",1) ( | |
try destroyDialog SuperMask catch() | |
rollout SuperMask "Super Mask" width:240 ( | |
button each "Single" width:60 across:2 offset:[20,5] | |
button all "Multi" width:60 offset:[-20,5] | |
checkbox remove "Hide everything else" align:#center | |
label lbla "Single : one mask for the whole selection" offset:[0,10] | |
label lblb "Multi : one mask for each selected geometry" | |
label lblc "Masks will be saved in your " offset:[0,10] | |
label lbld "max file directory, subfolder _MASKS" | |
on each pressed do ( | |
o = getcurrentselection() | |
oc = o.count | |
b = bitmap 1920 1080 | |
if oc > 0 then ( | |
makedir (maxfilepath + "_MASKS") | |
for i in o do ( | |
useEnvironmentmap = off | |
backgroundColor = color 0 0 0 | |
renderers.current = Default_Scanline_Renderer() | |
i.material = standardMaterial diffusecolor:[255,255,255] selfIllumAmount:100 | |
select i | |
max select invert | |
if remove.state then hide $ else $.material = standardMaterial diffusecolor:[0,0,0] selfIllumAmount:100 | |
render outputSize:[1920,1080] to:b vfb:off | |
b.filename = maxfilepath + "_MASKS\\" + i.name + ".jpg" | |
save b | |
max undo | |
) | |
) else messagebox "Selection is empty" title"Super Mask" | |
) | |
on all pressed do ( | |
o = getcurrentselection() | |
oc = o.count | |
b = bitmap 1920 1080 | |
if oc > 0 then ( | |
makedir (maxfilepath + "_MASKS") | |
useEnvironmentmap = off | |
backgroundColor = color 0 0 0 | |
renderers.current = Default_Scanline_Renderer() | |
o.material = standardMaterial diffusecolor:[255,255,255] selfIllumAmount:100 | |
max select invert | |
if remove.state then hide $ else $.material = standardMaterial diffusecolor:[0,0,0] selfIllumAmount:100 | |
render outputSize:[1920,1080] to:b vfb:off | |
b.filename = (maxfilepath + "_MASKS\\" + (timestamp() as string) + ".jpg") | |
save b | |
max undo | |
) else messagebox "Selection is empty" title"Super Mask" | |
) | |
) | |
createDialog SuperMask style:#(#style_toolwindow, #style_sysmenu) | |
) -- bendelaunay.com |
Show Super IDAssign Object and Mat ID, Select by ID.
macroScript Super_ID | |
category:"Pouf" | |
toolTip:"Super ID" | |
icon:#("UVWUnwrapSelection",28) ( | |
try DestroyDialog Super_ID catch() | |
rollout Super_ID " Easy ID" width:120 ( | |
spinner MatID "Material ID " width:70 align:#center type:#integer range:[0,15,0] offset:[15,0] | |
button assignMat "Assign (selection)" width:100 align:#center | |
button selectMat "Select (scene)" width:100 align:#center | |
spinner ObjID "Object ID " width:90 align:#center type:#integer range:[0,65535,0] offset:[5,10] | |
button assignObj "Assign (selection)" width:100 align:#center | |
button selectObj "Select (scene)" width:100 align:#center | |
on assignMat pressed do ( | |
o = getcurrentselection() | |
for i in o where i.material != undefined do i.material.effectsChannel = MatID.value | |
) | |
on selectMat pressed do ( | |
GotIt = #() | |
for i in $* where i.material != undefined do if i.material.effectsChannel == MatID.value do append GotIt i | |
select GotIt | |
) | |
on assignObj pressed do ( | |
o = getcurrentselection() | |
for i in o do i.gbufferChannel = ObjID.value | |
) | |
on selectObj pressed do ( | |
GotIt = for i in $* where i.gbufferChannel == ObjID.value collect i | |
select GotIt | |
) | |
) | |
createDialog super_ID style:#(#style_toolwindow, #style_sysmenu) | |
) -- bendelaunay.com |
Show Super OBJ ExporterExport each mesh as an OBJ in a subfolder.
macroScript Super_OBJ_Exporter | |
category:"Pouf" | |
toolTip:"Super OBJ Exporter" | |
icon:#("Containers",4) ( | |
if maxfilepath == "" then messagebox "Please save your file first" | |
else ( | |
messagebox "OBJs will be saved in the \"_OBJ\" directory in your max file directory.\rYou will be asked for the export settings once." title:"Export each mesh as obj" | |
SuperPath = maxfilepath + "\\_OBJ" | |
MakeDir SuperPath | |
pouf = getcurrentselection() | |
if pouf.count > 0 do for i in pouf do ( | |
select i | |
-- disable any kind of smooth | |
try i.modifiers[#TurboSmooth].enabled = on catch() | |
try i.modifiers[#MeshSmooth].enabled = on catch() | |
-- the first time, display export settings | |
if i == 1 then exportFile (SuperPath + i.name + ".obj") selectedOnly:on | |
else exportFile (SuperPath + i.name + ".obj") #noPrompt selectedOnly:on | |
) | |
select pouf | |
) | |
) -- bendelaunay.com |
Show Super UV ManagerQuickly unfold basic UVs, save UV templates, move UVs precisely by 1 square.
macroScript Super_UV_Manager | |
category:"Pouf" | |
toolTip:"Super Fast Unwrap" | |
icon:#("UVWUnwrapOption", 3) ( | |
try DestroyDialog SuperFastUnwrap catch() | |
-- GUI | |
rollout SuperFastUnwrap " Super UV Manager" width:180 ( | |
button addmod "Add Unwrap mod. (selection)" width:160 align:#center | |
-- radio box, sphere, plane, cylinder, pelt, flatten (angle) | |
button FastUV "Box Unwrap (selection)" width:160 align:#center | |
-- on radio buttons change, update texte, try to update unwraps | |
button saveUV "Save UV templates (selection)" width:160 align:#center offset:[0,20] | |
label lbla "move UVs (selection)" align:#center offset:[0,20] | |
--scroller offset, default 1, error message no UVs selected | |
button top "^" width:16 height:16 align:#center offset:[0,5] | |
button left "<" width:16 height:16 across:3 align:#center offset:[30,0] | |
button bottom " v " width:16 height:16 align:#center offset:[1,0] | |
button right ">" width:16 height:16 align:#center offset:[-30,0] | |
on addMod pressed do ( | |
o = getcurrentselection() | |
-- if object has modifiers | |
for i in o do if i.modifiers.count > 0 then ( | |
-- but no unwrap | |
if i[4][#unwrap_uvw] == undefined do ( | |
l = 0 | |
-- list of modifiers to keep on top of the unwrap | |
topModifiers = #(MeshSmooth, TurboSmooth, Skin, Skin_Morph, Skin_Wrap, Morphers) | |
for j in i.modifiers.count to 1 by -1 where findItem topModifiers (classof i[4][j]) != 0 do l = j | |
-- add the unwrap beneath the top smooth | |
addmodifier i (unwrap_uvw()) before:l | |
) | |
-- if object does not have any modifier | |
) else addmodifier i (unwrap_uvw()) | |
) | |
on SaveUV pressed do ( | |
SuperPath = "Q:\\03_BDD\\01_MAPS\\_UVS\\" | |
if not doesFileExist SuperPath do ( | |
makeDir SuperPath all:on | |
for i in selection ( | |
if i.modifiers[#Unwrap_uvw] != undefined do ( | |
pouf = i.modifiers[#unwrap_uvw] | |
pouf.renderuv_width = 4096 | |
pouf.renderuv_height = 4096 | |
pouf.renderUV (SuperPath + "UVTEMPLATE_" + i.name + ".jpg") | |
) else messagebox format ((i as string) + "doesn't have an Unwrap modifier.") title:"wtf ? Oo" | |
) | |
) | |
) | |
on top pressed do $[4][#unwrap_uvw].unwrap2.MoveSelected [0,1,0] | |
on left pressed do $[4][#unwrap_uvw].unwrap2.MoveSelected [-1,0,0] | |
on bottom pressed do $[4][#unwrap_uvw].unwrap2.MoveSelected [0,-1,0] | |
on right pressed do $[4][#unwrap_uvw].unwrap2.MoveSelected [1,0,0] | |
) | |
createDialog SuperFastUnwrap style:#(#style_toolwindow, #style_sysmenu) | |
) -- bendelaunay.com |
Show Super Instances SelectSelect every other instance of your selection
macroScript Super_Instances_Select | |
category:"Pouf" | |
toolTip:"Super Instances Select" | |
icon:#("SubObjectIcons", 20) ( | |
o = getcurrentselection () | |
f = #() | |
for i in o do ( | |
InstanceMgr.GetInstances i &gro | |
for j in gro do append f j | |
) | |
select f | |
) -- bendelaunay.com |
Show Super Instances MakerTransform meshes into instances of another mesh
macroScript Super_Instances_Maker | |
category:"Pouf" | |
toolTip:"Super Instances Maker" | |
icon:#("UVWUnwrapModes",19) ( | |
source = selectByName title:"Select a source mesh" single:true | |
targets = selectByName title:"Select every soon-to-be-instances" | |
for i in targets do instanceReplace i source | |
) |
Show Super Ressources ManagementQuickly toggle anim modifiers, smooth and maps in viewport.
macroScript Super_Ressources_Management | |
category:"Pouf" | |
toolTip:"Super Ressources Management" | |
icon:#("Helpers",3) ( | |
global buttonswidth = 140 | |
try destroyDialog Ressources catch() | |
rollout Ressources "Ressources Management" width:(buttonswidth + 30) ( | |
group "Anim" ( | |
label lbla "Toggle the following :" align:#left | |
label lblb "MeshSmooth, Skin, Skin Morph" align:#left | |
radiobuttons anim_type labels:#("scene", "selection") columns:2 default:2 | |
button animToggle "ON / OFF (scene)" width:buttonswidth | |
on animToggle pressed do ( | |
o = case anim_type.state of ( | |
1: $* | |
2: GetCurrentSelection() | |
) | |
hasSkin = for i in o where i.modifiers[#Skin] != undefined collect i | |
hasMorph = for i in o where i.modifiers[#Skin_Morph] != undefined collect i | |
hasMesh = for i in o where i.modifiers[#MeshSmooth] != undefined collect i | |
if ((hasSkin.count > 0 and hasSkin[1].modifiers[#Skin].enabled) or (hasMorph.count > 0 and hasMorph[1].modifiers[#Skin_Morph].enabled) or (hasMesh.count > 0 and hasMesh[1].modifiers[#MeshSmooth].enabled)) then ( | |
if hasSkin.count > 0 do for i in hasSkin do i.modifiers[#Skin].enabled = off | |
if hasMorph.count > 0 do for i in hasMorph do i.modifiers[#Skin_Morph].enabled = off | |
if hasMesh.count > 0 do for i in hasMesh do i.modifiers[#MeshSmooth].enabled = off | |
) else ( | |
if hasSkin.count > 0 do for i in hasSkin do i.modifiers[#Skin].enabled = on | |
if hasMorph.count > 0 do for i in hasMorph do i.modifiers[#Skin_Morph].enabled = on | |
if hasMesh.count > 0 do for i in hasMesh do i.modifiers[#MeshSmooth].enabled = on | |
) | |
) | |
) | |
group "Smooth in Viewport" ( | |
radiobuttons smooth_type labels:#("scene", "selection") columns:2 default:2 | |
button smoothToggle "ON / OFF" width:buttonswidth | |
on smoothToggle pressed do ( | |
o = case smooth_type.state of ( | |
1: $* | |
2: GetCurrentSelection() | |
) | |
signal = 0 | |
TurboSel = for i in o where i[4][#TurboSmooth] != undefined collect i | |
MeshSel = for i in o where i[4][#MeshSmooth] != undefined collect i | |
if TurboSel.count > 0 do ( | |
if TurboSel[1].modifiers[#TurboSmooth].iterations == 0 then signal = 2 else signal = 1 | |
for i in TurboSel do ( | |
Tur = i.modifiers[#TurboSmooth] | |
Tur.enabled = on | |
Tur.useRenderIterations = on | |
if Tur.Iterations > Tur.Render_Iterations do Tur.Render_Iterations = Tur.Iterations | |
if signal == 2 then Tur.Iterations = Tur.Render_Iterations else Tur.Iterations = 0 | |
) | |
) | |
if MeshSel.count > 0 do ( | |
if signal == 0 do ( | |
if MeshSel[1].modifiers[#MeshSmooth].iterations == 0 then signal = 2 else signal = 1 | |
) | |
for i in MeshSel do ( | |
Mes = i.modifiers[#MeshSmooth] | |
Mes.enabled = on | |
Mes.useRenderIterations = on | |
if Mes.Iterations > Mes.Render_Iterations do Mes.Render_Iterations = Mes.Iterations | |
if signal == 2 then Mes.Iterations = Mes.Render_Iterations else Mes.Iterations = 0 | |
) | |
) | |
) | |
) -- smooth end | |
group "Maps in Viewport" ( | |
radiobuttons tex_type labels:#("scene", "selection") columns:2 default:2 | |
button TexSoft "Software" width:buttonswidth | |
button TexHard "Hardware" width:buttonswidth | |
button TexOff "OFF" width:buttonswidth | |
on TexSoft pressed do ( | |
Actual = #() | |
o = case tex_type.state of ( | |
1: $* | |
2: GetCurrentSelection() | |
) | |
for i in o where i.material != undefined do appendIfUnique Actual i.material | |
for m in Actual do ( | |
try showHWTextureMap m off catch() | |
try m.ShowInViewport = on catch() | |
) | |
) | |
on TexHard pressed do for m in scenematerials do ( | |
Actual = #() | |
o = case tex_type.state of ( | |
1: $* | |
2: GetCurrentSelection() | |
) | |
for i in o where i.material != undefined do appendIfUnique Actual i.material | |
for m in Actual do ( | |
try m.ShowInViewport = off catch() | |
try enableHardwareMaterial m on catch() | |
try showHWTextureMap m on catch() | |
) | |
) | |
on TexOff pressed do for m in sceneMaterials do ( | |
Actual = #() | |
o = case tex_type.state of ( | |
1: $* | |
2: GetCurrentSelection() | |
) | |
for i in o where i.material != undefined do appendIfUnique Actual i.material | |
for m in Actual do ( | |
try m.ShowInViewport = off catch() | |
try showTextureMap m m.diffusemap off catch() | |
try showHWTextureMap m off catch() | |
) | |
) | |
) -- textures end | |
-- group "Self Illu (Scene)" ( | |
-- label lblc "Careful. You will lose" | |
-- label lbld "all your self-illu; values." | |
-- button SelfToggle "ON / OFF (scene)" width:buttonswidth | |
-- on SelfToggle pressed do ( | |
-- if sceneMaterials[1].selfIllumAmount == 0 then for m in sceneMaterials do try m.selfIllumAmount = 100 catch() | |
-- else for m in sceneMaterials do try m.selfIllumAmount = 0 catch() | |
-- ) | |
-- ) -- self illu end | |
) -- rollout end | |
createDialog Ressources | |
) -- bendelaunay.com |
Show Super Skin ReloadSometimes bugs happen, and reloading your Skin data works.
macroScript Super_Skin_Reload | |
category:"Pouf" | |
toolTip:"Super Skin Reload" | |
icon:#("Maintoolbar", 23) ( | |
undo off ( | |
Sel = getcurrentselection() | |
if Sel.count > 1 then messagebox "un seul objet a la fois !" | |
else if $.modifiers[#Skin] != undefined do with redraw off ( | |
SuperSkin = skin filter_vertices:on | |
bonesList = #() | |
SuperPath = maxfilepath + $.name + ".env" | |
i = 1 | |
while classof $.modifiers[i] != Skin do i += 1 | |
oldSkin = $.modifiers[#Skin] | |
bonesCount = skinOps.GetNumberBones oldSkin | |
bonesList = for j in 1 to bonesCount collect skinOps.GetBoneName oldSkin j 0 | |
skinOps.saveenvelope oldSkin SuperPath | |
deletemodifier $ i | |
addmodifier $ SuperSkin before:(i - 1) | |
newSkin = $.modifiers[#Skin] | |
for k in 1 to bonesCount do skinOps.addbone newSkin (getnodebyname bonesList[k] exact:true ignoreCase:true) -1 | |
skinOps.loadenvelope newSkin SuperPath | |
) | |
) | |
) -- bendelaunay.com |
Show Super lolAssign a random colour to every element of the 3ds max UI. Fun !
macroScript Super_lol | |
category:"Pouf" | |
toolTip:"Super lol" | |
icon:#("BodyObjects", 4) ( | |
-- this script saves your current color scheme in the 3ds max UI directory. name : ColorsBackup.clr | |
-- to load your previous color scheme, go to customize > customize user interface... > colors > Load (bottom left button) | |
-- or execute this code : colorMan.loadColorFile "ColorsBackup.clr" | |
-- for a classy white gizmo, execute this code : setUIcolor 71 [1, 1, 1]; colorMan.repaintUI #repaintAll | |
undo off ( | |
if querybox "sure ?" title:"lol" do ( | |
max create mode | |
if not doesfileexist (getDir #ui + "ColorsBackup.clr") do colorMan.saveColorFile (getDir #ui + "ColorsBackup.clr") | |
pourissage = #(#background, #text, #activeCommand, #hilight, \ | |
#shadow, #window, #activeCaption, #toolTipBackground, \ | |
#toolTipText, #hilightText, #windowText, #itemHilight, \ | |
#subObjectColor, #3dDarkShadow, #3dLight, #appWorkspace, \ | |
#trackbarBg, #trackbarBgSel, #trackbarText, #trackbarTicks, \ | |
#trackbarKeys, #trackbarSelKeys, #trackbarCursor, #pressedButton, \ | |
#timeSliderBg, #viewportBorder, #activeViewportBorder, #rollupTitleFace, \ | |
#rollupTitleText, #rollupTitleHilight, #rollupTitleShadow, #selectionRubberBand, #stackViewSelection) | |
for i in pourissage do try colorMan.setColor i [random .1 .5, random .1 .5, random .1 .5] catch() | |
for i = 1 to 103 do try setUIcolor i [random .1 .5, random .1 .5, random .1 .5] catch() | |
colorMan.repaintUI #repaintAll | |
max motion mode | |
) | |
) | |
) -- bendelaunay.com |
Show Super RepathChange multiple shots' path root, go back and forth between local and network files.
import nuke | |
import os | |
from shutil import copy | |
def compare(a, b): | |
for i, ai, bi in zip(xrange(len(a)), a, b): | |
if ai != bi: | |
return a[:i] | |
def ChangePath(): | |
allPaths, allReads = [], [] | |
for n in nuke.allNodes(): | |
if n.Class() == "Read": | |
allReads.append(n) | |
allPaths.append(n['file'].value()) | |
sortedPaths = sorted(allPaths, key=len) | |
shortest, temp = sortedPaths[0], '' | |
for i in sortedPaths[1:]: | |
temp = compare(shortest, i) | |
while temp[-1:].isalnum(): | |
temp = temp[:-1] | |
newPath = nuke.getInput('Replace common path: {0}'.format(temp), temp) | |
if newPath: | |
if newPath[-1:] != temp[-1:]: | |
newPath += temp[-1:] | |
for i in xrange(len(allReads)): | |
allReads[i]['file'].setValue(allPaths[i].replace(temp, newPath, 1)) | |
# to Local | |
def toLocal(): | |
for n in nuke.allNodes('Read'): | |
path = n['file'].value() | |
t = '{0:04d}'.format(nuke.frame()) | |
spath = path.replace('%04d.', t + '.').replace('####.', t + '.') | |
d = '/'.join(spath.split('/')[:-1]) + '/' | |
newD = 'D' + d[1:] | |
try: | |
copy(spath, newD) | |
n['file'].setValue('D' + path[1:]) | |
except: | |
pass | |
# to Server | |
def toServer(): | |
for n in nuke.allNodes('Read'): | |
n['file'].setValue('M' + n['file'].value()[1:]) | |
# change shot | |
def changeShot(): | |
allN = nuke.allNodes('Read') | |
k = nuke.selectedNode() | |
fpath = k['file'].value() | |
fshot = fpath.split('/')[2] | |
fver = fpath.split('/')[4] | |
if '%04d' in fpath or '###' in fpath: | |
first = k['first'].value() | |
last = k['last'].value() | |
else: | |
first = last = fpath[-8:-4].lstrip('0') | |
nuke.root()['first_frame'].setValue(float(first)) | |
nuke.root()['last_frame'].setValue(float(last)) | |
targets = [n for n in allN if 'SuperRead' in n['name'].value()] | |
for n in targets: | |
n['first'].setValue(int(first)) | |
n['origfirst'].setValue(int(first)) | |
n['last'].setValue(int(last)) | |
n['origlast'].setValue(int(last)) | |
oldPath = n['file'].value().split('/') | |
oldPath[2] = fshot | |
oldPath[4] = fver | |
n['file'].setValue('/'.join(oldPath)) | |
# switch from generate to scrips | |
def updateAssets(): | |
for n in nuke.allNodes(): | |
if n.Class() == 'Read': | |
Path = n['file'].value() | |
if '014_PRECOMP/Shot' in Path: | |
if n.width() == 2048 and n.height() == 1080: | |
newPath = Path.split('/') | |
shotN = newPath[4].split('_')[-1] | |
newPath[5] = shotN + '_assets' | |
newPath = '/'.join(newPath) | |
if os.path.isfile(newPath): | |
n['file'].setValue(newPath) | |
else: | |
print('NOT FOUND - ' + Path) | |
else: | |
print('DIFFERENT WIDTH/HEIGHT - ' + Path) |
Show Premiere to NukeConvert a Premiere editing file to a Nuke scene. Might need some customization.
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import xml.etree.ElementTree | |
import re | |
import os | |
import nuke | |
def Premiere2Nuke(): | |
xmlFile = nuke.getFilename('Where is the XML file', '*.xml') | |
root = xml.etree.ElementTree.parse(xmlFile).getroot() | |
nodes = [] | |
for clipitem in root.getiterator('clipitem'): | |
file = clipitem.find('file') | |
if file is not None: | |
pathurl = file.find('pathurl') | |
if pathurl is not None: | |
clipPath = pathurl.text | |
if 'Compositing' in clipPath or 'Generiques' in clipPath or 'GENERIQUES' in clipPath: | |
clipPath = clipPath.replace('file://localhost/M%3a/', 'M:/') | |
clipPath = clipPath.replace('file://?/M%3a', 'M:/') | |
clipIn = clipitem.find('in') | |
clipOut = clipitem.find('out') | |
clipStart = clipitem.find('start') | |
if None not in [clipIn, clipOut, clipStart]: | |
nodes.append([clipPath, clipIn.text, clipOut.text, clipStart.text]) | |
nodes.sort(key=lambda n: int(n[3])) | |
endOfTime = len(nodes) - 1 | |
final = '2048 1080 final' | |
nuke.addFormat(final) | |
nuke.root()['format'].setValue('final') | |
nuke.root()['first_frame'].setValue(1) | |
B = nuke.nodes.Constant(channels='rgba') | |
for i, n in enumerate(nodes): | |
clipPath, clipIn, clipOut, clipStart = n | |
clipStart = str(int(clipStart) + 1) | |
d = n[0].split('/') | |
tail = d.pop() | |
d = '/'.join(d) | |
if not os.path.isdir(d): | |
d = d.replace('sortieNuke', 'sortiesNuke') | |
clipPath = clipPath.replace('sortieNuke', 'sortiesNuke') | |
if not os.path.isfile(clipPath): | |
content = re.findall('\d{4}', str(os.listdir(d))) | |
if content: | |
clipPath = re.sub('\d{4}', content[0], clipPath) | |
if not os.path.isfile(clipPath): | |
clipPath = '{0}/{1}_avecContour_v01.{2}.exr'.format(d, tail.split('_')[0], tail[-8:-4]) | |
if not os.path.isfile(clipPath): | |
clipPath = '{0}/{1}_compo_{2}.exr'.format(d, tail.split('_')[0], tail[-8:-4]) | |
if os.path.isfile(clipPath): | |
num = re.findall('\d{4}', clipPath) | |
if num: | |
clipPath = clipPath.replace(num[-1], '####') | |
read = nuke.nodes.Read(file=clipPath, | |
frame_mode='start at', | |
frame=clipStart, | |
before='hold', | |
after='hold') | |
merge = nuke.nodes.Merge2(operation='copy') | |
merge.setInput(0, B) | |
merge.setInput(1, read) | |
if num: | |
content = re.findall('\d{4}', str(os.listdir(d))) | |
firstFound = int(min(content)) | |
first = firstFound + int(clipIn) | |
last = firstFound + int(clipOut) - 1 | |
read['first'].setExpression(str(first)) | |
read['last'].setExpression(str(last)) | |
clipEnd = int(clipStart) + last - first | |
merge['disable'].setExpression('1 - (t >= {0}) * (t <= {1})'.format(clipStart, clipEnd)) | |
if i == endOfTime: | |
nuke.root()['last_frame'].setValue(clipEnd) | |
B = merge | |
else: | |
print('j\'ai pas trouvé ce plan : {0}'.format(clipPath)) |
Show No Dialog ExportExport every flattened channel of every mesh as a tif
def NoDialogExport(): | |
mari.history.startMacro("Export Every Damn Channel No Questions") | |
path = 'M:/Assets/Guns/Cock/Mari/$ENTITY_$CHANNEL_$UDIM.tif' | |
mari.history.stopMacro() | |
save_options = 0|2|1 | |
objList = mari.geo.list() | |
chanList = [c for o in objList for c in o.channelList() if 'out' in c.name() or 'color' in c.name()] | |
msg = 'Fini !' | |
for c in chanList: | |
geo = c.geoEntity() | |
all_layers = c.layerList() | |
patch_list = geo.patchList() | |
uv_index_list = [patch.uvIndex() for patch in patch_list] | |
try: | |
c.exportImagesFlattened(path, save_options, uv_index_list) | |
except Exception, e: | |
msg += '\nFailed to export {0}'.format(geo) | |
mari.utils.message(msg) | |
mari.menus.addAction(mari.actions.create('Export', 'NoDialogExport()'), 'MainWindow/Pouf') |
Show Super Generate PNGAn alternative to Photoshop's Generate feature to save layers as 16bpc PNG.
var doc = app.activeDocument; | |
var Dir = doc.path.fsName + '\\'; | |
var Name = doc.name; | |
var shotN = Name.split('_')[1] | |
var Assets = Dir + shotN + '_assets\\'; | |
var f = new Folder(Assets); | |
if (!f.exists) | |
f.create(); | |
var startLoop = Number(!hasBackground()); | |
var endLoop = getNumberOfLayer(); | |
for(var l = startLoop; l <= endLoop; l++) { | |
while(!isValidActiveLayer(l)) { | |
l++; | |
} | |
Show(l); | |
} | |
for(var l = startLoop; l <= endLoop; l++) { | |
while(!isValidActiveLayer(l)) { | |
l++; | |
} | |
superLayer = getLayerNameByIndex(l) | |
if(superLayer.match(/\.png/i) != null) { | |
toogleVis(l) | |
saveFile = File(Assets + getLayerNameByIndex(l)); | |
if(saveFile.exists) saveFile.remove(); | |
SavePNG(saveFile); | |
toogleVis(l); | |
} | |
} | |
alert('J\'ai fini.'); | |
function SavePNG(saveFile){ | |
pngSaveOptions = new PNGSaveOptions(); | |
pngSaveOptions.compression=9 | |
activeDocument.saveAs(saveFile, pngSaveOptions, true, Extension.LOWERCASE); | |
} | |
function Show(idx) { | |
var desc = new ActionDescriptor(); | |
var list = new ActionList(); | |
var ref = new ActionReference(); | |
ref.putIndex(charIDToTypeID("Lyr "), idx); | |
list.putReference(ref); | |
desc.putList(charIDToTypeID("null"), list); | |
executeAction(charIDToTypeID("Shw "), desc, DialogModes.NO); | |
}; | |
function toogleVis(idx) { | |
var desc = new ActionDescriptor(); | |
var list = new ActionList(); | |
var ref = new ActionReference(); | |
ref.putIndex(charIDToTypeID('Lyr '), idx); | |
list.putReference(ref); | |
desc.putList(charIDToTypeID('null'), list); | |
desc.putBoolean(charIDToTypeID('TglO'), true); | |
executeAction(charIDToTypeID('Shw '), desc, DialogModes.NO); | |
}; | |
function isValidActiveLayer(idx) { | |
var propName = stringIDToTypeID('layerSection'); | |
var ref = new ActionReference(); | |
ref.putProperty(1349677170 , propName); | |
ref.putIndex(1283027488, idx); | |
var desc = executeActionGet(ref); | |
var type = desc.getEnumerationValue(propName); | |
var res = typeIDToStringID(type); | |
return res == 'layerSectionEnd' ? false:true; | |
}; | |
function hasBackground() { | |
var res = undefined; | |
try { | |
var ref = new ActionReference(); | |
ref.putProperty(1349677170 , 1315774496); | |
ref.putIndex(1283027488, 0); | |
executeActionGet(ref).getString(1315774496);; | |
res = true; | |
}catch(e){ res = false} | |
return res; | |
}; | |
function getNumberOfLayer() { | |
var ref = new ActionReference(); | |
ref.putEnumerated(charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt')); | |
var desc = executeActionGet(ref); | |
var numberOfLayer = desc.getInteger(charIDToTypeID('NmbL')); | |
return numberOfLayer; | |
}; | |
function getLayerNameByIndex(idx) { | |
var ref = new ActionReference(); | |
ref.putProperty(charIDToTypeID('Prpr') , charIDToTypeID('Nm ')); | |
ref.putIndex(charIDToTypeID('Lyr '), idx); | |
return executeActionGet(ref).getString(charIDToTypeID('Nm '));; | |
}; |