Renumbering for already exported sequences
0.2.1 - feat: renumbering with keep existing valuesmain
parent
191f667b75
commit
07e5046bef
|
@ -9,6 +9,10 @@ OR always duplicate (safe but heavy scenes...)
|
||||||
if duplicate, need to "connect" with namespace ('_duprender') or something
|
if duplicate, need to "connect" with namespace ('_duprender') or something
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
0.2.1
|
||||||
|
|
||||||
|
- feat: renumbering with keep existing values
|
||||||
|
|
||||||
0.2.0
|
0.2.0
|
||||||
|
|
||||||
- feat: merge selected viewlayer
|
- feat: merge selected viewlayer
|
||||||
|
|
|
@ -36,7 +36,8 @@ class GPEXP_OT_number_outputs(bpy.types.Operator):
|
||||||
if self.ctrl:
|
if self.ctrl:
|
||||||
fn.delete_numbering(fo)
|
fn.delete_numbering(fo)
|
||||||
else:
|
else:
|
||||||
fn.renumber(fo)
|
fn.renumber_keep_existing(fo)
|
||||||
|
# fn.renumber(fo)
|
||||||
|
|
||||||
txt = 'de-numbered' if self.ctrl else 're-numbered'
|
txt = 'de-numbered' if self.ctrl else 're-numbered'
|
||||||
if ct:
|
if ct:
|
||||||
|
|
|
@ -2,7 +2,7 @@ bl_info = {
|
||||||
"name": "GP exporter",
|
"name": "GP exporter",
|
||||||
"description": "Organise export of gp layers through compositor output",
|
"description": "Organise export of gp layers through compositor output",
|
||||||
"author": "Samuel Bernou",
|
"author": "Samuel Bernou",
|
||||||
"version": (0, 2, 0),
|
"version": (0, 2, 1),
|
||||||
"blender": (2, 93, 0),
|
"blender": (2, 93, 0),
|
||||||
"location": "View3D",
|
"location": "View3D",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
|
255
fn.py
255
fn.py
|
@ -279,7 +279,6 @@ def connect_to_group_input(n):
|
||||||
return val
|
return val
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def clear_nodegroup_content_if_disconnected(ngroup):
|
def clear_nodegroup_content_if_disconnected(ngroup):
|
||||||
'''Get a nodegroup.node_tree
|
'''Get a nodegroup.node_tree
|
||||||
delete orphan nodes that are not connected from group input node
|
delete orphan nodes that are not connected from group input node
|
||||||
|
@ -306,115 +305,6 @@ def random_color(alpha=False):
|
||||||
return (random.uniform(0,1), random.uniform(0,1), random.uniform(0,1), 1)
|
return (random.uniform(0,1), random.uniform(0,1), random.uniform(0,1), 1)
|
||||||
return (random.uniform(0,1), random.uniform(0,1), random.uniform(0,1))
|
return (random.uniform(0,1), random.uniform(0,1), random.uniform(0,1))
|
||||||
|
|
||||||
|
|
||||||
def get_numbered_output(out, slot_name):
|
|
||||||
'''Return output slot name without looking for numbering ???_
|
|
||||||
'''
|
|
||||||
pattern = r'^(?:\d{3}_)?' # optional non capture group of 3 digits + _
|
|
||||||
pattern = f'{pattern}{slot_name}'
|
|
||||||
for inp in out.inputs:
|
|
||||||
if re.match(pattern, inp.name):
|
|
||||||
return inp
|
|
||||||
|
|
||||||
|
|
||||||
def add_fileslot_number(fs, number):
|
|
||||||
elems = fs.path.split('/')
|
|
||||||
for i, e in enumerate(elems):
|
|
||||||
if re.match(r'^\d{3}_', e):
|
|
||||||
elems[i] = re.sub(r'^(\d{3})', lambda x: str(number).zfill(3), e)
|
|
||||||
else:
|
|
||||||
elems[i] = f'{str(number).zfill(3)}_{e}'
|
|
||||||
new = '/'.join(elems)
|
|
||||||
fs.path = new
|
|
||||||
return new
|
|
||||||
|
|
||||||
def renumber(fo, offset=10):
|
|
||||||
'''Force renumber all the slots with a 3'''
|
|
||||||
|
|
||||||
if fo.type != 'OUTPUT_FILE': return
|
|
||||||
ct = 0
|
|
||||||
for fs in fo.file_slots:
|
|
||||||
add_fileslot_number(fs, ct)
|
|
||||||
ct += offset
|
|
||||||
|
|
||||||
def get_num(string):
|
|
||||||
num = re.search(r'^(\d{3})_', string)
|
|
||||||
if num:
|
|
||||||
return int(num.group(1))
|
|
||||||
"""
|
|
||||||
def renumber_keep(fo, offset=10):
|
|
||||||
'''Force renumber all the slots with a 3'''
|
|
||||||
|
|
||||||
if fo.type != 'OUTPUT_FILE': return
|
|
||||||
|
|
||||||
renum = re.compile(r'^(\d{3})_')
|
|
||||||
ct = 0
|
|
||||||
|
|
||||||
last_idx = len(fo.file_slots) -1
|
|
||||||
prev = None
|
|
||||||
prev_num = None
|
|
||||||
for idx, fs in enumerate(fo.file_slots):
|
|
||||||
# if idx!=last_idx:
|
|
||||||
# fs_next = fo.file_slots[idx+1]
|
|
||||||
if idx == last_idx: # handle last
|
|
||||||
if idx > 0:
|
|
||||||
prev = fo.file_slots[idx-1]
|
|
||||||
num = renum.search(prev)
|
|
||||||
if not num:
|
|
||||||
add_fileslot_number(fs, ct)
|
|
||||||
else:
|
|
||||||
add_fileslot_number(fs, int(num.group(1)) + offset)
|
|
||||||
else:
|
|
||||||
add_fileslot_number(fs, 0) # there is only one slot (maybe don't number ?)
|
|
||||||
break
|
|
||||||
|
|
||||||
# update the ct with the current taken number if any
|
|
||||||
number = renum.search(fs.path)
|
|
||||||
if number:
|
|
||||||
prev = fs
|
|
||||||
ct = number + offset
|
|
||||||
continue # skip already numbered
|
|
||||||
|
|
||||||
# analyse all next slots until there is numbered
|
|
||||||
divider = None
|
|
||||||
for i in range(idx + 1, len(fo.file_slots) - idx):
|
|
||||||
next_num = renum.search(fo.file_slots[idx + i])
|
|
||||||
if next_num:
|
|
||||||
divider = i-1
|
|
||||||
break
|
|
||||||
|
|
||||||
if idx == 0:
|
|
||||||
prev_num = 0
|
|
||||||
prev = None
|
|
||||||
else:
|
|
||||||
prev = fo.file_slots[idx-1]
|
|
||||||
prev_num = renum.search(prev.path)
|
|
||||||
if prev_num:
|
|
||||||
prev_num = prev_num.group(1)
|
|
||||||
|
|
||||||
if not divider: # just use prev and next if prev
|
|
||||||
if not prev:
|
|
||||||
add_fileslot_number(fs, ct)
|
|
||||||
|
|
||||||
# first check if it has a number (if not bas)
|
|
||||||
prev = fs
|
|
||||||
ct += offset
|
|
||||||
"""
|
|
||||||
|
|
||||||
def delete_numbering(fo): # padding=3
|
|
||||||
'''Delete prefix numbering on all slots on passed file output'''
|
|
||||||
|
|
||||||
if fo.type != 'OUTPUT_FILE': return
|
|
||||||
for fs in fo.file_slots:
|
|
||||||
elems = fs.path.split('/')
|
|
||||||
for i, e in enumerate(elems):
|
|
||||||
elems[i] = re.sub(r'^\d{3}_', '', e)
|
|
||||||
|
|
||||||
new = '/'.join(elems)
|
|
||||||
fs.path = new
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def nodegroup_merge_inputs(ngroup):
|
def nodegroup_merge_inputs(ngroup):
|
||||||
'''Get a nodegroup
|
'''Get a nodegroup
|
||||||
merge every group inputs with alpha over
|
merge every group inputs with alpha over
|
||||||
|
@ -452,4 +342,147 @@ def nodegroup_merge_inputs(ngroup):
|
||||||
|
|
||||||
# create one input and link
|
# create one input and link
|
||||||
out = ngroup.outputs.new('NodeSocketColor', ngroup.inputs[0].name)
|
out = ngroup.outputs.new('NodeSocketColor', ngroup.inputs[0].name)
|
||||||
ngroup.links.new(aa.outputs[0], ng_out.inputs[0])
|
ngroup.links.new(aa.outputs[0], ng_out.inputs[0])
|
||||||
|
|
||||||
|
## --- renumbering funcs ---
|
||||||
|
|
||||||
|
def get_numbered_output(out, slot_name):
|
||||||
|
'''Return output slot name without looking for numbering ???_
|
||||||
|
'''
|
||||||
|
pattern = r'^(?:\d{3}_)?' # optional non capture group of 3 digits + _
|
||||||
|
pattern = f'{pattern}{slot_name}'
|
||||||
|
for inp in out.inputs:
|
||||||
|
if re.match(pattern, inp.name):
|
||||||
|
return inp
|
||||||
|
|
||||||
|
|
||||||
|
def add_fileslot_number(fs, number):
|
||||||
|
elems = fs.path.split('/')
|
||||||
|
for i, e in enumerate(elems):
|
||||||
|
if re.match(r'^\d{3}_', e):
|
||||||
|
elems[i] = re.sub(r'^(\d{3})', lambda x: str(number).zfill(3), e)
|
||||||
|
else:
|
||||||
|
elems[i] = f'{str(number).zfill(3)}_{e}'
|
||||||
|
new = '/'.join(elems)
|
||||||
|
fs.path = new
|
||||||
|
return new
|
||||||
|
|
||||||
|
def renumber(fo, offset=10):
|
||||||
|
'''Force renumber all the slots with a 3'''
|
||||||
|
if fo.type != 'OUTPUT_FILE': return
|
||||||
|
ct = 10 # start at 10
|
||||||
|
for fs in fo.file_slots:
|
||||||
|
add_fileslot_number(fs, ct)
|
||||||
|
ct += offset
|
||||||
|
|
||||||
|
def get_num(string) -> int:
|
||||||
|
'''get a tring or a file_slot object
|
||||||
|
return leading number or None
|
||||||
|
'''
|
||||||
|
if not isinstance(string, str):
|
||||||
|
string = string.path
|
||||||
|
num = re.search(r'^(\d{3})_', string)
|
||||||
|
if num:
|
||||||
|
return int(num.group(1))
|
||||||
|
|
||||||
|
def delete_numbering(fo): # padding=3
|
||||||
|
'''Delete prefix numbering on all slots on passed file output'''
|
||||||
|
|
||||||
|
if fo.type != 'OUTPUT_FILE': return
|
||||||
|
for fs in fo.file_slots:
|
||||||
|
elems = fs.path.split('/')
|
||||||
|
for i, e in enumerate(elems):
|
||||||
|
elems[i] = re.sub(r'^\d{3}_', '', e)
|
||||||
|
|
||||||
|
new = '/'.join(elems)
|
||||||
|
fs.path = new
|
||||||
|
|
||||||
|
def renumber_keep_existing(fo, offset=10):
|
||||||
|
'''Renumber by keeping existing numbers and inserting new one whenever possible
|
||||||
|
Big and ugly function that do the trick nonetheless...
|
||||||
|
'''
|
||||||
|
|
||||||
|
if fo.type != 'OUTPUT_FILE': return
|
||||||
|
ct = 10
|
||||||
|
|
||||||
|
fsl = fo.file_slots
|
||||||
|
|
||||||
|
last_idx = len(fsl) - 1
|
||||||
|
prev = None
|
||||||
|
prev_num = None
|
||||||
|
for idx, fs in enumerate(fsl):
|
||||||
|
print('-->', idx, fs.path)
|
||||||
|
|
||||||
|
if idx == last_idx: # handle last
|
||||||
|
if idx > 0:
|
||||||
|
prev = fsl[idx-1]
|
||||||
|
num = get_num(prev)
|
||||||
|
if num is not None:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
add_fileslot_number(fs, ct)
|
||||||
|
else:
|
||||||
|
add_fileslot_number(fs, 10) # there is only one slot (maybe don't number ?)
|
||||||
|
break
|
||||||
|
|
||||||
|
# update the ct with the current taken number if any
|
||||||
|
number = get_num(fs)
|
||||||
|
if number is not None:
|
||||||
|
prev = fs
|
||||||
|
ct = number + offset
|
||||||
|
continue # skip already numbered
|
||||||
|
|
||||||
|
# analyse all next slots until there is numbered
|
||||||
|
divider = 0
|
||||||
|
print(f'range(1, {len(fsl) - idx}')
|
||||||
|
for i in range(1, len(fsl) - idx):
|
||||||
|
print('i >> idx + i', i, idx + i)
|
||||||
|
next_num = get_num(fsl[idx + i])
|
||||||
|
print('next_num: ', next_num)
|
||||||
|
if next_num is not None:
|
||||||
|
divider = i+1
|
||||||
|
break
|
||||||
|
|
||||||
|
if idx == 0: # handle first
|
||||||
|
prev_num = 0
|
||||||
|
prev = None
|
||||||
|
if next_num is None:
|
||||||
|
add_fileslot_number(fs, 0)
|
||||||
|
elif next_num == 0:
|
||||||
|
print(f'Cannot insert value before 0 to {fsl.path}')
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
add_fileslot_number(fs, int(next_num / 2))
|
||||||
|
else:
|
||||||
|
prev = fsl[idx-1]
|
||||||
|
test_prev = get_num(prev)
|
||||||
|
if test_prev is not None:
|
||||||
|
prev_num = test_prev
|
||||||
|
|
||||||
|
if not divider:
|
||||||
|
if prev_num is not None:
|
||||||
|
add_fileslot_number(fs, prev_num + offset)
|
||||||
|
else:
|
||||||
|
add_fileslot_number(fs, ct)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print('divider: ', divider)
|
||||||
|
if prev_num is not None:
|
||||||
|
print('in updater')
|
||||||
|
# iterate rename
|
||||||
|
gap_inc = int((next_num - prev_num) / divider)
|
||||||
|
print('gap_inc: ', gap_inc)
|
||||||
|
if gap_inc < 1: # same values !
|
||||||
|
print(f'cannot insert a median value at {fs.path} between {prev_num} and {next_num}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
ct = prev_num
|
||||||
|
for temp_id in range(idx, idx+i):
|
||||||
|
ct += gap_inc
|
||||||
|
add_fileslot_number(fsl[temp_id], ct)
|
||||||
|
else:
|
||||||
|
print("what's going on ?\n")
|
||||||
|
|
||||||
|
# first check if it has a number (if not bas)
|
||||||
|
prev = fs
|
||||||
|
ct += offset
|
3
ui.py
3
ui.py
|
@ -44,9 +44,8 @@ class GPEXP_PT_gp_node_ui(Panel):
|
||||||
col.operator('gp.clean_compo_tree', icon='BRUSHES_ALL', text='Clean Nodes') # NODE_CORNER
|
col.operator('gp.clean_compo_tree', icon='BRUSHES_ALL', text='Clean Nodes') # NODE_CORNER
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
col.operator('gp.number_outputs', icon='LINENUMBERS_ON', text='Renumber outputs')
|
|
||||||
## maybe get only this one...
|
|
||||||
col.operator('gp.number_outputs', icon='LINENUMBERS_ON', text='Renumber Selected outputs').mode = 'SELECTED'
|
col.operator('gp.number_outputs', icon='LINENUMBERS_ON', text='Renumber Selected outputs').mode = 'SELECTED'
|
||||||
|
# col.operator('gp.number_outputs', icon='LINENUMBERS_ON', text='Renumber outputs').mode = 'ALL'
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue