2026-02-16

This commit is contained in:
2026-03-17 15:25:32 -06:00
parent d5dd373de0
commit 60100fbab2
560 changed files with 33397 additions and 20776 deletions
@@ -0,0 +1,23 @@
"""
UI modules for SheepIt Project Submitter addon.
"""
from . import output_panel
from . import preferences_ui
__all__ = ["output_panel", "preferences_ui"]
def register():
"""Register all UI classes."""
# Register preferences first so we can access variables in config.py
preferences_ui.register()
# Register other UI components
output_panel.register()
def unregister():
"""Unregister all UI classes."""
output_panel.unregister()
preferences_ui.unregister()
@@ -0,0 +1,90 @@
"""
Output panel UI for SheepIt Project Submitter.
Located in the Output tab, similar to Flamenco addon.
"""
import bpy
from bpy.types import Panel
from ..utils import compat
class SHEEPIT_PT_output_panel(Panel):
"""SheepIt submission panel in Output properties."""
bl_label = "SheepIt Render Farm"
bl_idname = "SHEEPIT_PT_output_panel"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "output"
def draw(self, context):
layout = self.layout
scene = context.scene
submit_settings = scene.sheepit_submit
# Do not write to scene in draw(); operators fall back to prefs.default_output_path when output_path is empty.
# Animation Setup Section
box = layout.box()
box.label(text="Animation Setup:", icon='ACTION')
col = box.column()
col.operator("sheepit.enable_nla", text="Disable Animation Layers", icon='ACTION')
layout.separator()
# Frame Range Section
box = layout.box()
box.label(text="Frame Range:", icon='RENDER_ANIMATION')
row = box.row()
row.prop(submit_settings, "frame_range_mode", expand=True)
if submit_settings.frame_range_mode == 'CUSTOM':
col = box.column(align=True)
col.prop(submit_settings, "frame_start")
col.prop(submit_settings, "frame_end")
col.prop(submit_settings, "frame_step")
else:
# Show current scene frame range
row = box.row()
row.label(text=f"Scene Range: {scene.frame_start} - {scene.frame_end} (Step: {scene.frame_step})")
layout.separator()
# Progress Bar Section (when submitting)
if submit_settings.is_submitting:
box = layout.box()
box.label(text=submit_settings.submit_status_message, icon='TIME')
box.prop(submit_settings, "submit_progress", text="Progress", slider=True)
layout.separator()
# Packing Buttons
col = layout.column()
col.scale_y = 1.5
# Pack Current Blend button (first)
op = col.operator("sheepit.submit_current", text="Pack Current Blend", icon='EXPORT')
op = col.operator("sheepit.pack_zip", text="Pack as ZIP (for scenes with caches)", icon='PACKAGE')
row = layout.row()
row.prop(submit_settings, "exclude_video_from_zip", text="Exclude video/audio from ZIP")
# Pack as Blend button
op = col.operator("sheepit.pack_blend", text="Pack as Blend", icon='FILE_BLEND')
layout.separator()
# Output Path Section
box = layout.box()
box.label(text="Output Path:", icon='FILE_FOLDER')
row = box.row()
row.prop(submit_settings, "output_path", text="")
row = box.row()
row.prop(submit_settings, "project_size_limit_gb", text="Size limit (GB)")
def register():
"""Register panel."""
compat.safe_register_class(SHEEPIT_PT_output_panel)
def unregister():
"""Unregister panel."""
compat.safe_unregister_class(SHEEPIT_PT_output_panel)
@@ -0,0 +1,106 @@
"""
Preferences UI for SheepIt Project Submitter.
"""
import sys
import bpy
from bpy.types import AddonPreferences
from bpy.props import StringProperty
from .. import config
# Get the root module name dynamically
def _get_addon_module_name():
"""Get the root addon module name for bl_idname."""
# In Blender 5.0 extensions loaded via VSCode, the module name is the full path
# e.g., "bl_ext.vscode_development.sheepit_project_submitter"
# We need to get it from the parent package (sheepit_project_submitter)
try:
# Get parent package name from __package__ (remove .ui suffix)
if __package__:
parent_pkg = __package__.rsplit('.', 1)[0] if '.' in __package__ else __package__
# Get the actual module from sys.modules to get its __name__
parent_module = sys.modules.get(parent_pkg)
if parent_module and hasattr(parent_module, '__name__'):
module_name = parent_module.__name__
config.debug_print(f"[SheepIt Debug] Using parent module __name__ as bl_idname: {module_name}")
return module_name
else:
# Use the package name directly
config.debug_print(f"[SheepIt Debug] Using parent package name as bl_idname: {parent_pkg}")
return parent_pkg
except Exception as e:
config.debug_print(f"[SheepIt Debug] Could not get parent module name: {e}")
# Last fallback
module_name = config.ADDON_ID
config.debug_print(f"[SheepIt Debug] Using fallback bl_idname: {module_name}")
return module_name
class SHEEPIT_AddonPreferences(AddonPreferences):
"""Addon preferences for SheepIt Project Submitter."""
# bl_idname must match the add-on's module name exactly
# Get it dynamically to ensure it matches what Blender registered
bl_idname = _get_addon_module_name()
default_output_path: StringProperty(
name="Default Output Path",
description="Default directory path where packed files will be saved",
default="",
subtype='DIR_PATH',
update=lambda self, context: _sync_default_output_path(self, context),
)
def draw(self, context):
layout = self.layout
# Output path settings
box = layout.box()
box.label(text="Output Settings:", icon='FILE_FOLDER')
box.prop(self, "default_output_path")
layout.separator()
# Info box
box = layout.box()
box.label(text="About:", icon='INFO')
box.label(text="This addon packs your Blender projects for manual upload to SheepIt.")
box.label(text="You must manually upload and configure projects on the SheepIt website.")
def _sync_default_output_path(prefs, context):
"""Sync default output path to all scenes' output_path if they're empty."""
if not prefs.default_output_path:
return
# Update all scenes' output_path if they're empty
for scene in bpy.data.scenes:
if hasattr(scene, 'sheepit_submit') and scene.sheepit_submit:
if not scene.sheepit_submit.output_path:
scene.sheepit_submit.output_path = prefs.default_output_path
reg_list = [SHEEPIT_AddonPreferences]
def register():
"""Register preferences."""
# Register preferences class
for cls in reg_list:
try:
from bpy.utils import register_class
register_class(cls)
config.debug_print(f"[SheepIt Debug] Registered preferences class: {cls.__name__} with bl_idname: {cls.bl_idname}")
except Exception as e:
print(f"[SheepIt Error] Failed to register preferences class {cls.__name__}: {e}")
import traceback
traceback.print_exc()
def unregister():
"""Unregister preferences."""
# Unregister preferences class
from ..utils import compat
for cls in reg_list:
compat.safe_unregister_class(cls)