From 07e5046befb9efe3a95e93d3569d8a0d76221d39 Mon Sep 17 00:00:00 2001 From: Pullusb Date: Fri, 10 Sep 2021 22:59:52 +0200 Subject: [PATCH] Renumbering for already exported sequences 0.2.1 - feat: renumbering with keep existing values --- CHANGELOG.md | 4 + OP_number_outputs.py | 3 +- __init__.py | 2 +- fn.py | 255 ++++++++++++++++++++++++------------------- ui.py | 3 +- 5 files changed, 152 insertions(+), 115 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5517d38..33709cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ OR always duplicate (safe but heavy scenes...) if duplicate, need to "connect" with namespace ('_duprender') or something --> +0.2.1 + +- feat: renumbering with keep existing values + 0.2.0 - feat: merge selected viewlayer diff --git a/OP_number_outputs.py b/OP_number_outputs.py index df05adc..89f215b 100644 --- a/OP_number_outputs.py +++ b/OP_number_outputs.py @@ -36,7 +36,8 @@ class GPEXP_OT_number_outputs(bpy.types.Operator): if self.ctrl: fn.delete_numbering(fo) else: - fn.renumber(fo) + fn.renumber_keep_existing(fo) + # fn.renumber(fo) txt = 'de-numbered' if self.ctrl else 're-numbered' if ct: diff --git a/__init__.py b/__init__.py index dcef863..0f003a2 100644 --- a/__init__.py +++ b/__init__.py @@ -2,7 +2,7 @@ bl_info = { "name": "GP exporter", "description": "Organise export of gp layers through compositor output", "author": "Samuel Bernou", - "version": (0, 2, 0), + "version": (0, 2, 1), "blender": (2, 93, 0), "location": "View3D", "warning": "", diff --git a/fn.py b/fn.py index 3470092..a6d4e1a 100644 --- a/fn.py +++ b/fn.py @@ -279,7 +279,6 @@ def connect_to_group_input(n): return val return False - def clear_nodegroup_content_if_disconnected(ngroup): '''Get a nodegroup.node_tree 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)) - -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): '''Get a nodegroup merge every group inputs with alpha over @@ -452,4 +342,147 @@ def nodegroup_merge_inputs(ngroup): # create one input and link out = ngroup.outputs.new('NodeSocketColor', ngroup.inputs[0].name) - ngroup.links.new(aa.outputs[0], ng_out.inputs[0]) \ No newline at end of file + 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 \ No newline at end of file diff --git a/ui.py b/ui.py index ff912e7..677afd5 100644 --- a/ui.py +++ b/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.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 outputs').mode = 'ALL' layout.separator()