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:
+34
-10
@@ -148,18 +148,27 @@ class VSETB_OT_load_projects(Operator):
|
||||
episode_datas = tracker.get_episodes(project_data)
|
||||
for episode_data in episode_datas:
|
||||
episode = project.episodes.get(episode_data['name'])
|
||||
|
||||
|
||||
if not episode:
|
||||
episode = project.episodes.add()
|
||||
|
||||
episode.name = episode_data['name']
|
||||
episode.id = episode_data['id']
|
||||
|
||||
|
||||
# Clear deleted episodes
|
||||
ep_names = [e['name'] for e in episode_datas]
|
||||
for ep in reversed(project.episodes):
|
||||
if ep.name not in ep_names:
|
||||
project.episodes.remove(list(project.episodes).index(ep))
|
||||
|
||||
# Load sequences for first episode so they're available immediately
|
||||
if project.episodes:
|
||||
first_episode = project.episodes[0]
|
||||
project.sequences.clear()
|
||||
for seq in tracker.get_sequences(project_data, episode=first_episode.id):
|
||||
sequence = project.sequences.add()
|
||||
sequence.name = seq['name']
|
||||
sequence.id = seq['id']
|
||||
else:
|
||||
# Add sequences
|
||||
sequences_data = tracker.get_sequences(project_data)
|
||||
@@ -257,15 +266,24 @@ class VSETB_OT_new_episode(Operator):
|
||||
settings = get_scene_settings()
|
||||
prefs = get_addon_prefs()
|
||||
tracker = prefs.tracker
|
||||
project = settings.active_project
|
||||
|
||||
episode_name = settings.episode_template.format(index=int(self.episode_name))
|
||||
episode = tracker.get_episode(episode_name)
|
||||
if episode:
|
||||
if not project:
|
||||
self.report({'ERROR'}, 'No active project')
|
||||
return {"CANCELLED"}
|
||||
|
||||
episode_name = project.episode_template.format(index=int(self.episode_name))
|
||||
episode_data = tracker.get_episode(episode_name, project=project.id)
|
||||
if episode_data:
|
||||
self.report({'ERROR'}, f'Episode {episode_name} already exists')
|
||||
return {"CANCELLED"}
|
||||
|
||||
tracker.new_episode(episode_name)
|
||||
tracker.update_project()
|
||||
|
||||
episode_data = tracker.new_episode(episode_name, project=project.id)
|
||||
|
||||
# Add to local episode collection
|
||||
episode = project.episodes.add()
|
||||
episode.name = episode_data['name']
|
||||
episode.id = episode_data['id']
|
||||
|
||||
self.report({'INFO'}, f'Episode {episode_name} successfully created')
|
||||
|
||||
@@ -355,6 +373,9 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||
context.window_manager.progress_update(i)
|
||||
strip_settings = strip.vsetb_strip_settings
|
||||
sequence_name = get_strip_sequence_name(strip)
|
||||
if sequence_name == 'NoSequence':
|
||||
self.report({'WARNING'}, f"Strip '{strip.name}' has no sequence — skipped")
|
||||
continue
|
||||
shot_name = strip.name
|
||||
sequence = tracker.get_sequence(sequence_name, episode=episode)
|
||||
metadata = strip_settings.metadata.to_dict(use_name=False)
|
||||
@@ -401,6 +422,7 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||
preview = None
|
||||
|
||||
comment_data = None
|
||||
preview_data = None
|
||||
if status or upload_to_tracker.comment or preview:
|
||||
comment_data = tracker.new_comment(task, comment=upload_to_tracker.comment, status=status)
|
||||
if preview:
|
||||
@@ -410,7 +432,7 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||
comment=comment_data,
|
||||
preview=preview)
|
||||
|
||||
if upload_to_tracker.set_main_preview:
|
||||
if upload_to_tracker.set_main_preview and preview_data:
|
||||
bpy.app.timers.register(partial(tracker.set_main_preview, preview_data), first_interval=10)
|
||||
|
||||
params = {}
|
||||
@@ -434,7 +456,9 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||
task = getattr(strip_settings.tasks, norm_name(task_type.name))
|
||||
tracker_task = tracker.get_task(task_type.name, entity=shot)
|
||||
|
||||
if task.comment and tracker_task.get('last_comment') != task.comment:
|
||||
last_comment = tracker_task.get('last_comment')
|
||||
last_comment_text = last_comment.get('text', '') if isinstance(last_comment, dict) else str(last_comment or '')
|
||||
if task.comment and last_comment_text != task.comment:
|
||||
tracker.new_comment(tracker_task, comment=task.comment)
|
||||
|
||||
context.window_manager.progress_end()
|
||||
|
||||
Reference in New Issue
Block a user