custom_shelf initial commit
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
info = {
|
||||
'icon' : 'COPYDOWN',
|
||||
'description' : 'Go in render node mode waiting for jobs in watchfolder',
|
||||
'checkfiles' : False,
|
||||
'stamp' : False,
|
||||
'cmds' : ''
|
||||
}
|
||||
import os
|
||||
from os import listdir
|
||||
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
|
||||
import re
|
||||
from time import sleep
|
||||
import time
|
||||
import datetime
|
||||
## Blender
|
||||
import bpy
|
||||
from mathutils import Vector, Matrix
|
||||
C = bpy.context
|
||||
D = bpy.data
|
||||
scn = scene = C.scene
|
||||
|
||||
|
||||
def submit_to_watchfolder(checkfiles=False):
|
||||
'''submitter (with or without file_copy)'''
|
||||
|
||||
if D.is_dirty or not D.is_saved:
|
||||
print('!!! Not submitted : File must be saved first')
|
||||
return
|
||||
|
||||
totalframes = scn.frame_end - scn.frame_start
|
||||
if not overwrite:
|
||||
#check if output path exists and have file
|
||||
out = scn.render.filepath
|
||||
outfolder = dirname(out)
|
||||
if exists(outfolder):
|
||||
outname = basename(out)
|
||||
refile = re.compile(outname.rstrip('#') + r'\d{4}')
|
||||
outlist = [f for f in listdir(outfolder) if refile.match(f)]
|
||||
if outlist:
|
||||
print(f'!!! Abort submission : Overwrite is False and {len(outlist)} files already exists ({totalframes} wanted)')
|
||||
return
|
||||
|
||||
print(f'{totalframes} frames to render')
|
||||
watchfolder = '/z/___SERIE/WIND-UPS/episodes/00/watchfolder'
|
||||
if not exists(watchfolder):
|
||||
print(f'watchfolder not found at {watchfolder}')
|
||||
watchfolder = '/mnt/admserveur/prod/___SERIE/WIND-UPS/episodes/00/watchfolder'
|
||||
if not exists(watchfolder):
|
||||
print(f'ABORT : watchfolder not found at {watchfolder}')
|
||||
return 1
|
||||
|
||||
#save a copy to the file ?
|
||||
|
||||
the_file = D.filepath
|
||||
finalname = basename(D.filepath)
|
||||
|
||||
'''
|
||||
if use_copy:
|
||||
#save a copy
|
||||
head, tail = os.path.split(D.filepath)
|
||||
name, ext = splitext(tail)
|
||||
uid = datetime.datetime.now().strftime('_rdtemp%Y%m%d%H%M%S')
|
||||
finalname = name + uid + ext
|
||||
the_file = join(head, finalname)
|
||||
bpy.ops.wm.save_as_mainfile(filepath=the_file, copy=True)
|
||||
|
||||
link = join(watchfolder, finalname)
|
||||
print(f'Create symlink:\n src: {finalname}\n dest: {link}')#the_file, complete path to finalname
|
||||
os.symlink(the_file, link)#impossible to create symlink... so fuck-it.
|
||||
'''
|
||||
|
||||
noext = splitext(finalname)[0]
|
||||
|
||||
stby = join(watchfolder, 'stby--' + noext)# + '.txt'
|
||||
todo = join(watchfolder, 'todo--' + noext)# + '.txt'
|
||||
running = join(watchfolder, 'runn--' + noext)# + '.txt'
|
||||
done = join(watchfolder, 'done--' + noext)# + '.txt'
|
||||
|
||||
bad = 0
|
||||
statelist = []
|
||||
if exists(stby):
|
||||
statelist.append(basename(stby))
|
||||
if exists(todo):
|
||||
statelist.append(basename(todo))
|
||||
if exists(running):
|
||||
statelist.append(basename(running))
|
||||
if exists(done):
|
||||
statelist.append(basename(done))
|
||||
|
||||
for f in os.listdir(watchfolder):
|
||||
if splitext(f)[0][len('stby--'):] == noext:
|
||||
print('Something already exists')
|
||||
|
||||
|
||||
if exists(todo):
|
||||
bad = 1
|
||||
print(f'{noext}: Job already submitted')
|
||||
|
||||
if len(statelist) > 1:
|
||||
print('problem : job exists in multiple states')
|
||||
for state in statelist:
|
||||
print(state)
|
||||
bad = 1
|
||||
|
||||
if bad:
|
||||
print('skip')
|
||||
return
|
||||
|
||||
with open(todo, 'w') as fd:
|
||||
fd.write(the_file+'\n')
|
||||
if info['stamp']:
|
||||
fd.write('stamp\n')
|
||||
if info['cmds']:
|
||||
fd.write(info['cmds'])
|
||||
|
||||
print(f'Created job {todo}')
|
||||
|
||||
print(f'Submit {basename(D.filepath)}')
|
||||
submit_to_watchfolder(checkfiles=info['checkfiles'])
|
||||
@@ -0,0 +1,215 @@
|
||||
info = {
|
||||
'icon' : 'RENDER_RESULT',
|
||||
'description' : 'Pass in render node watchmode (freeze and get job from watchfolder when a todo is available)',
|
||||
}
|
||||
|
||||
import os
|
||||
from os import listdir
|
||||
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
|
||||
import re, fnmatch, glob
|
||||
from math import radians, degrees
|
||||
from time import sleep
|
||||
import datetime
|
||||
import time
|
||||
import platform
|
||||
|
||||
# Blender
|
||||
import bpy
|
||||
from mathutils import Vector, Matrix
|
||||
C = bpy.context
|
||||
D = bpy.data
|
||||
scene = C.scene
|
||||
|
||||
## General timer to disable ?
|
||||
## How to push a key to stop the mega-loop ? (or barbaric ctrl-C in cmd)
|
||||
|
||||
def logit(message):
|
||||
try:
|
||||
print(message)
|
||||
with open(log, 'a') as fd:
|
||||
if not message.endswith('\n'):
|
||||
message += '\n'
|
||||
fd.write(message)#add trailing new line
|
||||
except Exception as e:
|
||||
print('Log failed', e)
|
||||
|
||||
def set_stamp(active_note=False):
|
||||
rd = bpy.context.scene.render
|
||||
rd.use_stamp = True
|
||||
|
||||
## Enable
|
||||
rd.use_stamp_filename = True
|
||||
rd.use_stamp_frame = True
|
||||
rd.use_stamp_render_time = True
|
||||
rd.use_stamp_time = True
|
||||
rd.use_stamp_date = True
|
||||
|
||||
## Disable
|
||||
rd.use_stamp_sequencer_strip = False
|
||||
rd.use_stamp_marker = False
|
||||
rd.use_stamp_scene = False
|
||||
rd.use_stamp_lens = False
|
||||
rd.use_stamp_camera = False
|
||||
rd.use_stamp_hostname = False
|
||||
rd.use_stamp_memory = False
|
||||
rd.use_stamp_frame_range = False
|
||||
|
||||
## Notes
|
||||
rd.use_stamp_note = active_note
|
||||
|
||||
if rd.use_stamp_note:
|
||||
info = D.texts.get('info')
|
||||
txt = ''
|
||||
if info:
|
||||
for l in info.lines[:2]:
|
||||
if 'Created from' in l.body:
|
||||
txt = l.body
|
||||
if txt:
|
||||
rd.stamp_note_text = txt
|
||||
else:#disable notes
|
||||
rd.use_stamp_note = False
|
||||
|
||||
def run(fp):
|
||||
running = fp.replace('todo--', 'runn--')
|
||||
|
||||
stamp = False
|
||||
warn = []
|
||||
# Check if a running job already exists
|
||||
if exists(running):
|
||||
logit(f'Problem ! job already exists : {running}')
|
||||
return 1
|
||||
|
||||
# Get blend path
|
||||
with open(fp, 'r') as fd:
|
||||
# blend = fd.read().strip()
|
||||
lines = fd.readlines()
|
||||
blend = lines[0].strip()
|
||||
stamp = 'stamp' in lines
|
||||
for l in lines[1:]:#skip filepath
|
||||
if '=' in l:#skip simple keyword qand focus on assignation
|
||||
try:
|
||||
exec(l)
|
||||
except Exception as e:
|
||||
print(f'could not exec {l}:\n->{e}')
|
||||
warn.append(f'could not exec {l}:\n->{e}')
|
||||
|
||||
if not blend:
|
||||
logit(f'Problem reading {fp}')
|
||||
return 1
|
||||
|
||||
# check path
|
||||
logit(f'Target blend : {blend}')
|
||||
if not exists(blend):
|
||||
logit(f'ERROR ! job {basename(running)} give an invalid filepath')
|
||||
#delete/rename running job
|
||||
os.rename(running, running.replace('runn--', 'error-'))
|
||||
return 1
|
||||
|
||||
# Pass on job mode
|
||||
try:
|
||||
os.rename(fp, running)
|
||||
except Exception as e:
|
||||
logit(f'Could not rename job to running mode : {fp} ')
|
||||
return 1
|
||||
|
||||
|
||||
# write the timestamp and launch the job
|
||||
with open(running, 'a') as fd:
|
||||
startmess = f'starting : {str(datetime.datetime.now())}\n'
|
||||
logit(startmess)
|
||||
fd.write(startmess)
|
||||
|
||||
# Blender time ! open, check output and render the job
|
||||
|
||||
start_time = time.time()# get start time
|
||||
bpy.ops.wm.open_mainfile(filepath=blend)
|
||||
scn = bpy.context.scene
|
||||
#here change Ao/filepath/stuff if needed
|
||||
if stamp:
|
||||
set_stamp(active_note=True)
|
||||
else:
|
||||
bpy.context.scene.render.use_stamp = False
|
||||
|
||||
bpy.ops.render.render(animation=True)#anim render
|
||||
print('Rendering done, launching make_video in 2 sec...')
|
||||
## log end time and exit
|
||||
elapsed_time = time.time() - start_time# seconds
|
||||
full_time = str(datetime.timedelta(seconds=elapsed_time))# hh:mm:ss format
|
||||
timecode = datetime.datetime.now().strftime('%m%d%H%M')#timecode format '02041139' month+day+hour+minutes
|
||||
sleep(2)
|
||||
|
||||
#no disable auto folder opening after auto video making
|
||||
if hasattr(scn, 'MVopen'):
|
||||
scn.MVopen = False
|
||||
|
||||
bpy.ops.render.make_video()
|
||||
|
||||
with open(running, 'a') as fd:
|
||||
endmess = f'ended : {str(datetime.datetime.now())}\nrender time: {full_time}\n'
|
||||
logit(endmess)
|
||||
fd.write(endmess)
|
||||
if warn:
|
||||
fd.write('\n'.join(warn)+'\n')
|
||||
|
||||
# rename and move into done folder
|
||||
donename = basename(running).replace('runn--', 'done--') + f'__{timecode}'#.replace('.txt', f'__{timecode}.txt')
|
||||
done = join(donefolder, donename)
|
||||
|
||||
try:
|
||||
os.rename(running, done)
|
||||
except Exception as e:
|
||||
logit(f'Could not move/rename run job to done : {done} (from {running}) ')
|
||||
return
|
||||
|
||||
print(f'Finished job {basename(running)}, Continue in 5 seconds')
|
||||
sleep(5)
|
||||
return 0
|
||||
|
||||
###================
|
||||
|
||||
def watchmode():
|
||||
if not bpy.data.is_saved or bpy.data.is_dirty:
|
||||
print('You need to start from a saved blender file (preferably empty)')
|
||||
return
|
||||
|
||||
if not exists(watchfolder):
|
||||
print(f'!!!! Abort, watchfolder ({watchfolder}) not found')
|
||||
return
|
||||
|
||||
if not exists(logfolder):
|
||||
os.mkdir(logfolder)
|
||||
print('log folder created')
|
||||
|
||||
while True:#infinite loop
|
||||
job_status = 1
|
||||
|
||||
todolist = [f for f in os.listdir(watchfolder) if f.startswith('todo--')]
|
||||
if todolist:
|
||||
first = todolist[0]
|
||||
print(f'{len(todolist)} todo, starting: {first}')
|
||||
fp = join(watchfolder, first)
|
||||
job_status = run(fp)
|
||||
print('job_status: ', job_status)
|
||||
#reopen folder
|
||||
bpy.ops.wm.open_mainfile(filepath=org_blend)
|
||||
|
||||
sleep(300)#5min wait before looping
|
||||
|
||||
|
||||
org_blend = bpy.data.filepath
|
||||
machine = platform.node().split('.')[0]
|
||||
if machine:
|
||||
machine = 'node_' + machine + '.txt'
|
||||
if not machine:
|
||||
print('Cannot find machine name')
|
||||
machine = 'nodes.txt'
|
||||
|
||||
print(f'use machine name : {machine}')
|
||||
|
||||
watchfolder = '/z/___SERIE/WIND-UPS/episodes/00/watchfolder'
|
||||
donefolder = join(watchfolder, 'done')
|
||||
logfolder = join(watchfolder, 'logs')
|
||||
log = join(logfolder, machine)
|
||||
|
||||
watchmode()
|
||||
print('End of batch.\nEOF')
|
||||
Reference in New Issue
Block a user