Update .gitignore to include log files and database journal files. Modify go.mod to update dependencies for go-sqlite3 and cloud.google.com/go/compute/metadata. Enhance Makefile to include logging options for manager and runner commands. Introduce new job token handling in auth package and implement database migration scripts. Refactor manager and runner components to improve job processing and metadata extraction. Add support for video preview in frontend components and enhance WebSocket management for channel subscriptions.
This commit is contained in:
@@ -339,12 +339,8 @@ object_count = len(scene.objects)
|
||||
material_count = len(bpy.data.materials)
|
||||
|
||||
# Extract Blender version info
|
||||
# bpy.app.version gives the current running Blender version
|
||||
# For the file's saved version, we check bpy.data.version (version the file was saved with)
|
||||
blender_version = {
|
||||
"current": bpy.app.version_string, # Version of Blender running this script
|
||||
"file_saved_with": ".".join(map(str, bpy.data.version)) if hasattr(bpy.data, 'version') else None, # Version file was saved with
|
||||
}
|
||||
# bpy.data.version gives the version the file was saved with
|
||||
blender_version = ".".join(map(str, bpy.data.version)) if hasattr(bpy.data, 'version') else bpy.app.version_string
|
||||
|
||||
# Build metadata dictionary
|
||||
metadata = {
|
||||
|
||||
@@ -12,6 +12,52 @@ try:
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not make paths relative: {e}")
|
||||
|
||||
# Auto-enable addons from blender_addons folder in context
|
||||
# Supports .zip files (installed via Blender API) and already-extracted addons
|
||||
blend_dir = os.path.dirname(bpy.data.filepath) if bpy.data.filepath else os.getcwd()
|
||||
addons_dir = os.path.join(blend_dir, "blender_addons")
|
||||
|
||||
if os.path.isdir(addons_dir):
|
||||
print(f"Found blender_addons folder: {addons_dir}")
|
||||
|
||||
for item in os.listdir(addons_dir):
|
||||
item_path = os.path.join(addons_dir, item)
|
||||
|
||||
try:
|
||||
if item.endswith('.zip'):
|
||||
# Install and enable zip addon using Blender's API
|
||||
bpy.ops.preferences.addon_install(filepath=item_path)
|
||||
# Get module name from zip (usually the folder name inside)
|
||||
import zipfile
|
||||
with zipfile.ZipFile(item_path, 'r') as zf:
|
||||
# Find the top-level module name
|
||||
names = zf.namelist()
|
||||
if names:
|
||||
module_name = names[0].split('/')[0]
|
||||
if module_name.endswith('.py'):
|
||||
module_name = module_name[:-3]
|
||||
bpy.ops.preferences.addon_enable(module=module_name)
|
||||
print(f" Installed and enabled addon: {module_name}")
|
||||
|
||||
elif item.endswith('.py') and not item.startswith('__'):
|
||||
# Single-file addon
|
||||
bpy.ops.preferences.addon_install(filepath=item_path)
|
||||
module_name = item[:-3]
|
||||
bpy.ops.preferences.addon_enable(module=module_name)
|
||||
print(f" Installed and enabled addon: {module_name}")
|
||||
|
||||
elif os.path.isdir(item_path) and os.path.exists(os.path.join(item_path, '__init__.py')):
|
||||
# Multi-file addon directory - add to path and enable
|
||||
if addons_dir not in sys.path:
|
||||
sys.path.insert(0, addons_dir)
|
||||
bpy.ops.preferences.addon_enable(module=item)
|
||||
print(f" Enabled addon: {item}")
|
||||
|
||||
except Exception as e:
|
||||
print(f" Error with addon {item}: {e}")
|
||||
else:
|
||||
print(f"No blender_addons folder found at: {addons_dir}")
|
||||
|
||||
{{UNHIDE_CODE}}
|
||||
# Read output format from file (created by Go code)
|
||||
format_file_path = {{FORMAT_FILE_PATH}}
|
||||
@@ -53,10 +99,10 @@ print(f"Blend file output format: {current_output_format}")
|
||||
if output_format_override:
|
||||
print(f"Overriding output format from '{current_output_format}' to '{output_format_override}'")
|
||||
# Map common format names to Blender's format constants
|
||||
# For video formats (EXR_264_MP4, EXR_AV1_MP4), we render as EXR frames first
|
||||
# For video formats, we render as appropriate frame format first
|
||||
format_to_use = output_format_override.upper()
|
||||
if format_to_use in ['EXR_264_MP4', 'EXR_AV1_MP4']:
|
||||
format_to_use = 'EXR' # Render as EXR for video formats
|
||||
if format_to_use in ['EXR_264_MP4', 'EXR_AV1_MP4', 'EXR_VP9_WEBM']:
|
||||
format_to_use = 'EXR' # Render as EXR for EXR video formats
|
||||
|
||||
format_map = {
|
||||
'PNG': 'PNG',
|
||||
|
||||
@@ -32,22 +32,20 @@ const (
|
||||
|
||||
// Job represents a render job
|
||||
type Job struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
JobType JobType `json:"job_type"` // "render"
|
||||
Name string `json:"name"`
|
||||
Status JobStatus `json:"status"`
|
||||
Progress float64 `json:"progress"` // 0.0 to 100.0
|
||||
FrameStart *int `json:"frame_start,omitempty"` // Only for render jobs
|
||||
FrameEnd *int `json:"frame_end,omitempty"` // Only for render jobs
|
||||
OutputFormat *string `json:"output_format,omitempty"` // Only for render jobs - PNG, JPEG, EXR, etc.
|
||||
AllowParallelRunners *bool `json:"allow_parallel_runners,omitempty"` // Only for render jobs
|
||||
TimeoutSeconds int `json:"timeout_seconds"` // Job-level timeout (24 hours default)
|
||||
BlendMetadata *BlendMetadata `json:"blend_metadata,omitempty"` // Extracted metadata from blend file
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
StartedAt *time.Time `json:"started_at,omitempty"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||
ErrorMessage string `json:"error_message,omitempty"`
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
JobType JobType `json:"job_type"` // "render"
|
||||
Name string `json:"name"`
|
||||
Status JobStatus `json:"status"`
|
||||
Progress float64 `json:"progress"` // 0.0 to 100.0
|
||||
FrameStart *int `json:"frame_start,omitempty"` // Only for render jobs
|
||||
FrameEnd *int `json:"frame_end,omitempty"` // Only for render jobs
|
||||
OutputFormat *string `json:"output_format,omitempty"` // Only for render jobs - PNG, JPEG, EXR, etc.
|
||||
BlendMetadata *BlendMetadata `json:"blend_metadata,omitempty"` // Extracted metadata from blend file
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
StartedAt *time.Time `json:"started_at,omitempty"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||
ErrorMessage string `json:"error_message,omitempty"`
|
||||
}
|
||||
|
||||
// RunnerStatus represents the status of a runner
|
||||
@@ -86,9 +84,8 @@ const (
|
||||
type TaskType string
|
||||
|
||||
const (
|
||||
TaskTypeRender TaskType = "render"
|
||||
TaskTypeMetadata TaskType = "metadata"
|
||||
TaskTypeVideoGeneration TaskType = "video_generation"
|
||||
TaskTypeRender TaskType = "render"
|
||||
TaskTypeEncode TaskType = "encode"
|
||||
)
|
||||
|
||||
// Task represents a render task assigned to a runner
|
||||
@@ -96,8 +93,7 @@ type Task struct {
|
||||
ID int64 `json:"id"`
|
||||
JobID int64 `json:"job_id"`
|
||||
RunnerID *int64 `json:"runner_id,omitempty"`
|
||||
FrameStart int `json:"frame_start"`
|
||||
FrameEnd int `json:"frame_end"`
|
||||
Frame int `json:"frame"`
|
||||
TaskType TaskType `json:"task_type"`
|
||||
Status TaskStatus `json:"status"`
|
||||
CurrentStep string `json:"current_step,omitempty"`
|
||||
@@ -132,16 +128,18 @@ type JobFile struct {
|
||||
|
||||
// CreateJobRequest represents a request to create a new job
|
||||
type CreateJobRequest struct {
|
||||
JobType JobType `json:"job_type"` // "render"
|
||||
Name string `json:"name"`
|
||||
FrameStart *int `json:"frame_start,omitempty"` // Required for render jobs
|
||||
FrameEnd *int `json:"frame_end,omitempty"` // Required for render jobs
|
||||
OutputFormat *string `json:"output_format,omitempty"` // Required for render jobs
|
||||
AllowParallelRunners *bool `json:"allow_parallel_runners,omitempty"` // Optional for render jobs, defaults to true
|
||||
RenderSettings *RenderSettings `json:"render_settings,omitempty"` // Optional: Override blend file render settings
|
||||
UploadSessionID *string `json:"upload_session_id,omitempty"` // Optional: Session ID from file upload
|
||||
UnhideObjects *bool `json:"unhide_objects,omitempty"` // Optional: Enable unhide tweaks for objects/collections
|
||||
EnableExecution *bool `json:"enable_execution,omitempty"` // Optional: Enable auto-execution in Blender (adds --enable-autoexec flag, defaults to false)
|
||||
JobType JobType `json:"job_type"` // "render"
|
||||
Name string `json:"name"`
|
||||
FrameStart *int `json:"frame_start,omitempty"` // Required for render jobs
|
||||
FrameEnd *int `json:"frame_end,omitempty"` // Required for render jobs
|
||||
OutputFormat *string `json:"output_format,omitempty"` // Required for render jobs
|
||||
RenderSettings *RenderSettings `json:"render_settings,omitempty"` // Optional: Override blend file render settings
|
||||
UploadSessionID *string `json:"upload_session_id,omitempty"` // Optional: Session ID from file upload
|
||||
UnhideObjects *bool `json:"unhide_objects,omitempty"` // Optional: Enable unhide tweaks for objects/collections
|
||||
EnableExecution *bool `json:"enable_execution,omitempty"` // Optional: Enable auto-execution in Blender (adds --enable-autoexec flag, defaults to false)
|
||||
BlenderVersion *string `json:"blender_version,omitempty"` // Optional: Override Blender version (e.g., "4.2" or "4.2.3")
|
||||
PreserveHDR *bool `json:"preserve_hdr,omitempty"` // Optional: Preserve HDR range for EXR encoding (uses HLG with bt709 primaries)
|
||||
PreserveAlpha *bool `json:"preserve_alpha,omitempty"` // Optional: Preserve alpha channel for EXR encoding (requires AV1 or VP9 codec)
|
||||
}
|
||||
|
||||
// UpdateJobProgressRequest represents a request to update job progress
|
||||
@@ -227,23 +225,26 @@ type TaskLogEntry struct {
|
||||
|
||||
// BlendMetadata represents extracted metadata from a blend file
|
||||
type BlendMetadata struct {
|
||||
FrameStart int `json:"frame_start"`
|
||||
FrameEnd int `json:"frame_end"`
|
||||
HasNegativeFrames bool `json:"has_negative_frames"` // True if blend file has negative frame numbers (not supported)
|
||||
RenderSettings RenderSettings `json:"render_settings"`
|
||||
SceneInfo SceneInfo `json:"scene_info"`
|
||||
FrameStart int `json:"frame_start"`
|
||||
FrameEnd int `json:"frame_end"`
|
||||
HasNegativeFrames bool `json:"has_negative_frames"` // True if blend file has negative frame numbers (not supported)
|
||||
RenderSettings RenderSettings `json:"render_settings"`
|
||||
SceneInfo SceneInfo `json:"scene_info"`
|
||||
MissingFilesInfo *MissingFilesInfo `json:"missing_files_info,omitempty"`
|
||||
UnhideObjects *bool `json:"unhide_objects,omitempty"` // Enable unhide tweaks for objects/collections
|
||||
EnableExecution *bool `json:"enable_execution,omitempty"` // Enable auto-execution in Blender (adds --enable-autoexec flag, defaults to false)
|
||||
UnhideObjects *bool `json:"unhide_objects,omitempty"` // Enable unhide tweaks for objects/collections
|
||||
EnableExecution *bool `json:"enable_execution,omitempty"` // Enable auto-execution in Blender (adds --enable-autoexec flag, defaults to false)
|
||||
BlenderVersion string `json:"blender_version,omitempty"` // Detected or overridden Blender version (e.g., "4.2" or "4.2.3")
|
||||
PreserveHDR *bool `json:"preserve_hdr,omitempty"` // Preserve HDR range for EXR encoding (uses HLG with bt709 primaries)
|
||||
PreserveAlpha *bool `json:"preserve_alpha,omitempty"` // Preserve alpha channel for EXR encoding (requires AV1 or VP9 codec)
|
||||
}
|
||||
|
||||
// MissingFilesInfo represents information about missing files/addons
|
||||
type MissingFilesInfo struct {
|
||||
Checked bool `json:"checked"`
|
||||
HasMissing bool `json:"has_missing"`
|
||||
MissingFiles []string `json:"missing_files,omitempty"`
|
||||
Checked bool `json:"checked"`
|
||||
HasMissing bool `json:"has_missing"`
|
||||
MissingFiles []string `json:"missing_files,omitempty"`
|
||||
MissingAddons []string `json:"missing_addons,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// RenderSettings represents render settings from a blend file
|
||||
|
||||
Reference in New Issue
Block a user