Added regex fitlering to the PSA sequence list

This commit is contained in:
Colin Basnett
2022-04-17 17:31:52 -07:00
parent ab52b1520e
commit e8e8d6ce8b
3 changed files with 46 additions and 33 deletions

View File

@@ -30,6 +30,26 @@ class PsaBuilder(object):
def __init__(self):
pass
def get_sequence_fps(self, context, options: PsaBuilderOptions, actions: Iterable[Action]) -> float:
if options.fps_source == 'SCENE':
return context.scene.render.fps
if options.fps_source == 'CUSTOM':
return options.fps_custom
elif options.fps_source == 'ACTION_METADATA':
# Get the minimum value of action metadata FPS values.
psa_fps_list = []
for action in filter(lambda x: 'psa_fps' in x, actions):
psa_fps = action['psa_fps']
if type(psa_fps) == int or type(psa_fps) == float:
psa_fps_list.append(psa_fps)
if len(psa_fps_list) > 0:
return min(psa_fps_list)
else:
# No valid action metadata to use, fallback to scene FPS
return context.scene.render.fps
else:
raise RuntimeError(f'Invalid FPS source "{options.fps_source}"')
def build(self, context, options: PsaBuilderOptions) -> Psa:
performance = PsaBuilderPerformance()
active_object = context.view_layer.objects.active
@@ -124,26 +144,6 @@ class PsaBuilder(object):
export_sequences = []
def get_sequence_fps(context, options: PsaBuilderOptions, actions: Iterable[Action]) -> float:
if options.fps_source == 'SCENE':
return context.scene.render.fps
if options.fps_source == 'CUSTOM':
return options.fps_custom
elif options.fps_source == 'ACTION_METADATA':
# Get the minimum value of action metadata FPS values.
psa_fps_list = []
for action in filter(lambda x: 'psa_fps' in x, actions):
psa_fps = action['psa_fps']
if type(psa_fps) == int or type(psa_fps) == float:
psa_fps_list.append(psa_fps)
if len(psa_fps_list) > 0:
return min(psa_fps_list)
else:
# No valid action metadata to use, fallback to scene FPS
return context.scene.render.fps
else:
raise RuntimeError(f'Invalid FPS source "{options.fps_source}"')
if options.sequence_source == 'ACTIONS':
for action in options.actions:
if len(action.fcurves) == 0:
@@ -154,7 +154,7 @@ class PsaBuilder(object):
frame_min, frame_max = [int(x) for x in action.frame_range]
export_sequence.nla_state.frame_min = frame_min
export_sequence.nla_state.frame_max = frame_max
export_sequence.fps = get_sequence_fps(context, options, [action])
export_sequence.fps = self.get_sequence_fps(context, options, [action])
export_sequences.append(export_sequence)
pass
elif options.sequence_source == 'TIMELINE_MARKERS':
@@ -167,7 +167,7 @@ class PsaBuilder(object):
export_sequence.nla_state.frame_min = frame_min
export_sequence.nla_state.frame_max = frame_max
nla_strips_actions = set(map(lambda x: x.action, get_nla_strips_in_timeframe(active_object, frame_min, frame_max)))
export_sequence.fps = get_sequence_fps(context, options, nla_strips_actions)
export_sequence.fps = self.get_sequence_fps(context, options, nla_strips_actions)
export_sequences.append(export_sequence)
else:
raise ValueError(f'Unhandled sequence source: {options.sequence_source}')

View File

@@ -10,6 +10,7 @@ from ..helpers import *
from collections import Counter
import re
import sys
import fnmatch
class PsaExporter(object):
@@ -318,7 +319,6 @@ def filter_sequences(pg: PsaExportPropertyGroup, sequences: bpy.types.bpy_prop_c
if pg.sequence_filter_name is not None:
# Filter name is non-empty.
import fnmatch
for i, sequence in enumerate(sequences):
if not fnmatch.fnmatch(sequence.name, f'*{pg.sequence_filter_name}*'):
flt_flags[i] &= ~bitflag_filter_item
@@ -331,7 +331,7 @@ def filter_sequences(pg: PsaExportPropertyGroup, sequences: bpy.types.bpy_prop_c
if pg.sequence_use_filter_invert:
# Invert filter flags for all items.
for i, sequence in enumerate(sequences):
flt_flags[i] ^= ~bitflag_filter_item
flt_flags[i] ^= bitflag_filter_item
return flt_flags
@@ -377,7 +377,7 @@ class PSA_UL_ExportActionList(UIList):
class PsaExportActionsSelectAll(Operator):
bl_idname = 'psa_export.sequences_select_all'
bl_label = 'Select All'
bl_description = 'Select all sequences'
bl_description = 'Select all visible sequences'
bl_options = {'INTERNAL'}
@classmethod
@@ -408,7 +408,7 @@ class PsaExportActionsSelectAll(Operator):
class PsaExportActionsDeselectAll(Operator):
bl_idname = 'psa_export.sequences_deselect_all'
bl_label = 'Deselect All'
bl_description = 'Deselect all sequences'
bl_description = 'Deselect all visible sequences'
bl_options = {'INTERNAL'}
@classmethod

View File

@@ -1,6 +1,8 @@
import bpy
import os
import numpy as np
import re
import fnmatch
from mathutils import Vector, Quaternion, Matrix
from .data import Psa
from typing import List, AnyStr, Optional
@@ -267,6 +269,7 @@ class PsaImportPropertyGroup(PropertyGroup):
action_name_prefix: StringProperty(default='', name='Prefix', options=set())
sequence_filter_name: StringProperty(default='', options={'TEXTEDIT_UPDATE'})
sequence_use_filter_invert: BoolProperty(default=False, options=set())
sequence_use_filter_regex: BoolProperty(default=False, name='Regular Expression', description='Filter using regular expressions', options=set())
select_text: PointerProperty(type=bpy.types.Text)
@@ -276,7 +279,16 @@ def filter_sequences(pg: PsaImportPropertyGroup, sequences: bpy.types.bpy_prop_c
if pg.sequence_filter_name is not None:
# Filter name is non-empty.
import fnmatch
if pg.sequence_use_filter_regex:
# Use regular expression
try:
regex = re.compile(pg.sequence_filter_name)
for i, sequence in enumerate(sequences):
if not regex.match(sequence.action_name):
flt_flags[i] &= ~bitflag_filter_item
except re.error:
pass
else:
for i, sequence in enumerate(sequences):
if not fnmatch.fnmatch(sequence.action_name, f'*{pg.sequence_filter_name}*'):
flt_flags[i] &= ~bitflag_filter_item
@@ -284,7 +296,7 @@ def filter_sequences(pg: PsaImportPropertyGroup, sequences: bpy.types.bpy_prop_c
if pg.sequence_use_filter_invert:
# Invert filter flags for all items.
for i, sequence in enumerate(sequences):
flt_flags[i] ^= ~bitflag_filter_item
flt_flags[i] ^= bitflag_filter_item
return flt_flags
@@ -313,6 +325,7 @@ class PSA_UL_SequenceList(UIList):
subrow = row.row(align=True)
subrow.prop(pg, 'sequence_filter_name', text="")
subrow.prop(pg, 'sequence_use_filter_invert', text="", icon='ARROW_LEFTRIGHT')
subrow.prop(pg, 'sequence_use_filter_regex', text="", icon='SORTBYEXT')
def filter_items(self, context, data, property):
pg = context.scene.psa_import
@@ -368,7 +381,7 @@ class PsaImportSequencesFromText(Operator):
class PsaImportSequencesSelectAll(Operator):
bl_idname = 'psa_import.sequences_select_all'
bl_label = 'All'
bl_description = 'Select all sequences'
bl_description = 'Select all visible sequences'
bl_options = {'INTERNAL'}
@classmethod
@@ -389,7 +402,7 @@ class PsaImportSequencesSelectAll(Operator):
class PsaImportSequencesDeselectAll(Operator):
bl_idname = 'psa_import.sequences_deselect_all'
bl_label = 'None'
bl_description = 'Deselect all sequences'
bl_description = 'Deselect all visible sequences'
bl_options = {'INTERNAL'}
@classmethod