170 lines
6.1 KiB
Python
170 lines
6.1 KiB
Python
import maya.OpenMaya as om
|
|
import maya.OpenMayaMPx as ompx
|
|
import maya.cmds as cmds
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
# Global variable to store the scriptJob ID
|
|
playblast_job_id = None
|
|
original_playblast = cmds.playblast
|
|
|
|
def get_plugin_directory():
|
|
# Get the path of the currently loaded plugin
|
|
plugin_name = "tinyblast"
|
|
plugin_path = cmds.pluginInfo(plugin_name, query=True, path=True)
|
|
return os.path.dirname(plugin_path)
|
|
|
|
def custom_playblast(*args, **kwargs):
|
|
print("Running playblast...")
|
|
|
|
kwargs['format'] = 'avi'
|
|
kwargs['percent'] = 100
|
|
kwargs['quality'] = 100
|
|
kwargs['widthHeight'] = (1920, 1080)
|
|
|
|
result = original_playblast(*args, **kwargs)
|
|
print(f"{result}")
|
|
|
|
if result:
|
|
try:
|
|
ffmpeg_path = os.path.join(get_plugin_directory(), 'ffmpeg.exe')
|
|
print(f"ffmpeg path: {ffmpeg_path}")
|
|
if not os.path.exists(ffmpeg_path):
|
|
raise FileNotFoundError(f"FFmpeg binary not found at {ffmpeg_path}")
|
|
|
|
input_file = result # The file output by playblast
|
|
#output_directory = os.path.dirname(result) # Get the directory path
|
|
output_directory = os.path.dirname(cmds.file(query=True, sceneName=True))
|
|
input_filename = os.path.basename(result) # Get the filename with extension
|
|
|
|
# Change the extension to .mp4
|
|
output_filename = os.path.splitext(input_filename)[0] + ".mp4"
|
|
|
|
# Define the full path for the converted output file
|
|
output_file = os.path.join(output_directory, output_filename)
|
|
|
|
# Run FFmpeg conversion
|
|
subprocess.run([ffmpeg_path,
|
|
'-i', input_file,
|
|
'-vcodec', 'libx264',
|
|
'-pix_fmt', 'yuv420p',
|
|
'-strict', 'experimental',
|
|
'-b:v', '1m',
|
|
output_file,
|
|
'-y'], check=True, shell=True)
|
|
print(f"Video conversion to {output_file} successful!")
|
|
# os.remove(input_file) # Running into permission issues trying to delete from AppData
|
|
# print(f"Original playblast deleted: {input_file}")
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error during FFmpeg conversion: {e}")
|
|
|
|
class WindowWatcher:
|
|
""" A class to watch for a particular window in Maya """
|
|
|
|
def __init__(self, window_title, on_open_callback, on_close_callback=None):
|
|
self.window_title = window_title
|
|
self.on_open_callback = on_open_callback
|
|
self.on_close_callback = on_close_callback
|
|
self.window_opened = False
|
|
|
|
def check_for_window_open(self):
|
|
if not self.window_opened:
|
|
window = self.get_window_by_title(self.window_title)
|
|
if window:
|
|
self.on_open_callback()
|
|
self.window_opened = True
|
|
else:
|
|
window = self.get_window_by_title(self.window_title)
|
|
if not window:
|
|
self.window_opened = False
|
|
if self.on_close_callback:
|
|
self.on_close_callback()
|
|
|
|
def get_window_by_title(self, title):
|
|
# Check all open windows and return the one that matches the title
|
|
windows = cmds.lsUI(windows=True)
|
|
for window in windows:
|
|
if cmds.window(window, query=True, title=True) == title:
|
|
return window
|
|
return None
|
|
|
|
|
|
def add_custom_button_to_playblast():
|
|
# Get the Playblast Options window
|
|
window = get_playblast_options_window()
|
|
|
|
if window:
|
|
# Find the layout of the Playblast Options window
|
|
layout = cmds.columnLayout(adjustableColumn=True)
|
|
if layout:
|
|
# Add a custom button below existing UI
|
|
cmds.setParent(layout) # Set the parent to the top-level layout
|
|
cmds.columnLayout(adjustableColumn=True)
|
|
cmds.button(label="Tinyblast", command=custom_button_action)
|
|
else:
|
|
print("Couldn't find the layout for the Playblast Options window.")
|
|
else:
|
|
print("Playblast Options window not found.")
|
|
|
|
|
|
def custom_button_action(*args):
|
|
cmds.playblast()
|
|
|
|
|
|
def get_playblast_options_window():
|
|
# Check if the Playblast Options window is open
|
|
windows = cmds.lsUI(windows=True)
|
|
for window in windows:
|
|
if cmds.window(window, query=True, title=True) == "Playblast Options": # Exact title match
|
|
return window
|
|
return None
|
|
|
|
def setup_script_job():
|
|
global playblast_job_id
|
|
|
|
# Kill any previously running scriptJob
|
|
if playblast_job_id is not None and cmds.scriptJob(exists=playblast_job_id):
|
|
cmds.scriptJob(kill=playblast_job_id, force=True)
|
|
print(f"Killed previous scriptJob with ID: {playblast_job_id}")
|
|
|
|
# Watch for the Playblast Options window by title
|
|
playblast_watcher = WindowWatcher(
|
|
window_title="Playblast Options", # Exact window title to look for
|
|
on_open_callback=add_custom_button_to_playblast
|
|
)
|
|
|
|
# Set up a new scriptJob
|
|
playblast_job_id = cmds.scriptJob(event=["idle", playblast_watcher.check_for_window_open])
|
|
|
|
class Tinyblast(ompx.MPxCommand):
|
|
def __init__(self):
|
|
ompx.MPxCommand.__init__(self)
|
|
|
|
def doIt(selfself, args):
|
|
print("Executing custom playblast command.")
|
|
cmds.playblast()
|
|
|
|
@staticmethod
|
|
def cmdCreator():
|
|
return ompx.asMPxPtr(Tinyblast())
|
|
|
|
def initializePlugin(mobject):
|
|
try:
|
|
mplugin = ompx.MFnPlugin(mobject, "Jack Christensen", "1.0.0", "Any")
|
|
mplugin.registerCommand("tinyblast", Tinyblast.cmdCreator)
|
|
om.MGlobal.displayInfo("Tinyblast plugin loaded.")
|
|
setup_script_job()
|
|
cmds.playblast = custom_playblast
|
|
except Exception as e:
|
|
om.MGlobal.displayError(f"Failed to initialize plugin: {str(e)}")
|
|
raise
|
|
|
|
def uninitializePlugin(mobject):
|
|
try:
|
|
mplugin = ompx.MFnPlugin(mobject)
|
|
mplugin.deregisterCommand("tinyblast")
|
|
om.MGlobal.displayInfo("Tinyblast plugin unloaded.")
|
|
except Exception as e:
|
|
om.MGlobal.displayError(f"Failed to uninitialize plugin: {str(e)}")
|
|
raise |