vse_toolbox/ui/preferences.py
Joseph HENRY d2d64dc8a8 Blender 5.0 compat + STB XML import + sequence/stamps improvements
- Fix Blender 5.0 API: active_sequence_strip → active_strip, bracket
  property access on AddonPreferences, _RestrictContext during register()
- Fix new_effect() frame_end → length for Blender 5.0
- Fix OTIO adapter kwargs (rate/ignore_timecode_mismatch only for cmx_3600)
- Fix OTIO global_start_time RationalTime → int conversion
- Add Import STB XML operator with movie strip import and XML patching
  for Storyboard Pro transitions missing <alignment>
- Add Create Sequence Strip operator (select shots → create sequence)
- Improve Set Stamps: channel at top, no conflict with existing strips,
  use raw strip names in templates
- TVSHOW episode fixes: sequence loading, episode creation
- Kitsu: new_asset, new_episode, admin_connect fix, gazu version pin
- Fix escape warnings in file_utils regex patterns
- Guard handler registration against duplicates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 16:09:03 +01:00

171 lines
4.5 KiB
Python

# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
import inspect
import os
from bpy.props import (
BoolProperty,
EnumProperty,
FloatProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import (
AddonPreferences,
PropertyGroup,
)
from vse_toolbox.bl_utils import get_addon_prefs, get_scene_settings
from vse_toolbox.constants import (
TRACKERS,
TRACKERS_DIR,
)
from vse_toolbox.file_utils import (
import_module_from_path,
norm_str,
read_file,
)
from vse_toolbox.resources.trackers.kitsu import Kitsu
def load_trackers():
from vse_toolbox.resources.trackers.tracker import Tracker
TRACKERS.clear()
tracker_files = list(TRACKERS_DIR.glob('*.py'))
for tracker_file in tracker_files:
if tracker_file.stem.startswith('_'):
continue
mod = import_module_from_path(tracker_file)
for name, obj in inspect.getmembers(mod):
if not inspect.isclass(obj):
continue
if not Tracker in obj.__mro__:
continue
if obj is Tracker or name in (a.__name__ for a in TRACKERS):
continue
try:
print(f'Register Tracker {name}')
bpy.utils.register_class(obj)
#obj.register()
setattr(Trackers, norm_str(name), PointerProperty(type=obj))
TRACKERS.append(obj)
except Exception as e:
print(f'Could not register Tracker {name}')
print(e)
def load_prefs():
prefs = get_addon_prefs()
prefs_config_file = prefs.config_path
if not prefs_config_file:
return
prefs_datas = read_file(os.path.expandvars(prefs_config_file))
if not prefs_datas:
return
for tracker_data in prefs_datas['trackers']:
tracker_name = norm_str(tracker_data['name'])
if not hasattr(prefs.trackers, tracker_name):
continue
tracker_pref = getattr(prefs.trackers, tracker_name)
if not tracker_pref:
continue
for k, v in tracker_data.items():
if k in ('name',):
continue
setattr(tracker_pref, k, os.path.expandvars(v))
try:
settings = get_scene_settings()
settings.tracker_name = prefs_datas['tracker_name']
except AttributeError:
pass # Scene not available yet during register()
class Trackers(PropertyGroup):
def __iter__(self):
return (getattr(self, p) for p in self.bl_rna.properties.keys() if p not in ('rna_type', 'name'))
class VSETB_Prefs(AddonPreferences):
bl_idname = 'vse_toolbox'
trackers : PointerProperty(type=Trackers)
expand_settings: BoolProperty(default=False)
config_path : StringProperty(subtype='FILE_PATH')
sort_metadata_items : BoolProperty(default=True)
@property
def tracker(self):
return getattr(self.trackers, norm_str(get_scene_settings().tracker_name))
def draw(self, context):
prefs = get_addon_prefs()
settings = get_scene_settings()
layout = self.layout
row = layout.row(align=True)
row.prop(self, 'config_path', text='Config Path')
row.operator("vse_toolbox.load_settings", icon="CHECKMARK", text='')
layout.prop(self, "sort_metadata_items", text='Sort Metadata Items')
col = layout.column(align=True)
box = col.box()
row = box.row(align=True)
icon = "DISCLOSURE_TRI_DOWN" if self.expand_settings else "DISCLOSURE_TRI_RIGHT"
row.prop(self, 'expand_settings', icon=icon, emboss=False, text='')
row.label(icon='PREFERENCES')
row.label(text='Tracker')
subrow = row.row()
subrow.alignment = 'RIGHT'
subrow.operator("vse_toolbox.reload_addon", text='Reload Addon')
if self.expand_settings:
box.prop(settings, 'tracker_name', text='Tracker')
self.tracker.draw_prefs(box)
#row = box.row()
box.operator("vse_toolbox.tracker_connect", text='Connect')
classes = [
Trackers,
VSETB_Prefs,
]
def register():
for cls in classes:
bpy.utils.register_class(cls)
load_trackers()
prefs = get_addon_prefs()
config_path = os.getenv('VSE_TOOLBOX_CONFIG')
if config_path:
prefs.config_path = os.path.expandvars(config_path)
load_prefs()
def unregister():
for cls in reversed(classes + TRACKERS):
bpy.utils.unregister_class(cls)
TRACKERS.clear()