Added regex fitlering to the PSA sequence list
This commit is contained in:
@@ -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}')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,15 +279,24 @@ 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
|
||||
for i, sequence in enumerate(sequences):
|
||||
if not fnmatch.fnmatch(sequence.action_name, f'*{pg.sequence_filter_name}*'):
|
||||
flt_flags[i] &= ~bitflag_filter_item
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user