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>
This commit is contained in:
2026-03-10 16:09:03 +01:00
co-authored by Claude Opus 4.6
parent c46d78f2ae
commit d2d64dc8a8
14 changed files with 548 additions and 122 deletions
+27 -2
View File
@@ -15,7 +15,7 @@ from vse_toolbox.file_utils import install_module, norm_str
from vse_toolbox.resources.trackers.tracker import Tracker
try:
gazu = install_module('gazu')
gazu = install_module('gazu', package_name='gazu>=1.0,<2.0')
except Exception as e:
print('Could not install gazu')
print(e)
@@ -32,10 +32,15 @@ class Kitsu(Tracker):
admin_password : StringProperty(subtype='PASSWORD')
def admin_connect(self):
url = self.url
url = expandvars(self.url)
if not url:
raise ConnectionError("No Kitsu URL configured")
if not url.endswith('/api'):
url += '/api'
gazu.client.set_host(url)
login = expandvars(self.admin_login or self.login)
password = expandvars(self.admin_password or self.password)
@@ -347,6 +352,26 @@ class Kitsu(Tracker):
status = self.get_task_status(status)
return gazu.task.new_task(entity, task_type=task_type, task_status=status)
def new_asset(self, name, asset_type_name, project=None, description="", episode=None):
project = self.get_project(project)
project_dict = {'id': self.get_id(project)}
asset_type = gazu.asset.get_asset_type_by_name(asset_type_name)
if not asset_type:
raise ValueError(f"Asset type '{asset_type_name}' not found in Kitsu")
episode_dict = {'id': self.get_id(episode)} if episode else None
return gazu.asset.new_asset(
project_dict, asset_type, name,
description=description, episode=episode_dict
)
def new_episode(self, name, project=None):
project = self.get_project(project)
return gazu.shot.new_episode({'id': self.get_id(project)}, name)
def update_project(self, project=None):
"""Refresh project data — no-op for now, caller should reload via load_projects."""
pass
def new_sequence(self, sequence, episode=None, project=None):
project = self.get_project(project)