112 lines
5.3 KiB
Python
112 lines
5.3 KiB
Python
# Copyright Epic Games, Inc. All Rights Reserved.
|
|
from collections import OrderedDict
|
|
|
|
from maya import cmds
|
|
|
|
from epic_pose_wrangler.log import LOG
|
|
from epic_pose_wrangler.model import exceptions
|
|
|
|
|
|
class PluginManager:
|
|
"""
|
|
Class for loading latest available plugin and managing pose_wrangler versions
|
|
"""
|
|
# The name of the recommended solver
|
|
RECOMMENDED_SOLVER = "UERBFSolverNode"
|
|
# Empty list to keep track of the loaded solver nodes
|
|
LOADED_NODES = []
|
|
# Generate an ordered manifest of known plugin name variants with the newest plugins
|
|
__PLUGIN_VERSIONS = OrderedDict(
|
|
{
|
|
"MayaUERBFPlugin_{}".format(cmds.about(version=True)): "UERBFSolverNode",
|
|
"MayaUERBFPlugin{}".format(cmds.about(version=True)): "UERBFSolverNode",
|
|
"MayaUERBFPlugin": "UERBFSolverNode",
|
|
"MayaUE4RBFPlugin_{}".format(cmds.about(version=True)): "UE4RBFSolverNode",
|
|
"MayaUE4RBFPlugin{}".format(cmds.about(version=True)): "UE4RBFSolverNode",
|
|
"MayaUE4RBFPlugin": "UE4RBFSolverNode"}
|
|
)
|
|
|
|
@staticmethod
|
|
def load_plugin():
|
|
"""
|
|
Load any valid RBF plugins
|
|
:return :type list: node names loaded
|
|
"""
|
|
|
|
PluginManager.LOADED_NODES = []
|
|
# Iterate through all of the valid plugin versions and attempt to load
|
|
for plugin_name, solver_name in PluginManager.__PLUGIN_VERSIONS.items():
|
|
# If the plugin is already loaded, add the solver name to the list of loaded nodes
|
|
if cmds.pluginInfo(plugin_name, q=True, loaded=True) and solver_name not in PluginManager.LOADED_NODES:
|
|
PluginManager.LOADED_NODES.append(solver_name)
|
|
else:
|
|
try:
|
|
# Attempt to load the plugin
|
|
cmds.loadPlugin(plugin_name)
|
|
# If the solver name is not already in the list, add it
|
|
if solver_name not in PluginManager.LOADED_NODES:
|
|
PluginManager.LOADED_NODES.append(solver_name)
|
|
# Ignore errors
|
|
except RuntimeError as e:
|
|
pass
|
|
# If we have no loaded nodes no plugin loaded correctly
|
|
if not PluginManager.LOADED_NODES:
|
|
raise exceptions.InvalidPoseWranglerPlugin("Unable to load valid RBF plugin version.")
|
|
|
|
return PluginManager.LOADED_NODES
|
|
|
|
@staticmethod
|
|
def is_scene_using_recommended_solver():
|
|
"""
|
|
Scan the current scene to find which version of the solver is being used
|
|
:return :type bool: is the recommended solver being used for all RBF nodes
|
|
"""
|
|
solvers = []
|
|
# Get a list of the solver names
|
|
for solver_node_name in list(PluginManager.__PLUGIN_VERSIONS.values()):
|
|
if solver_node_name not in solvers:
|
|
solvers.append(solver_node_name)
|
|
# Iterate through the solver names
|
|
for solver_node_name in solvers:
|
|
# Check if any solvers exist in the scene of the specified type and check if the solver name is the
|
|
# recommended name. If we have old solvers in the scene, we aren't using the latest version.
|
|
if cmds.ls(type=solver_node_name) and solver_node_name != PluginManager.RECOMMENDED_SOLVER:
|
|
return False
|
|
return True
|
|
|
|
@staticmethod
|
|
def get_pose_wrangler(view=True, parent=None, file_path=None):
|
|
"""
|
|
Get the correct version of the pose wrangler tool depending on the available plugins and nodes in the scene
|
|
:param view :type bool: Should we be displaying a UI to the user?
|
|
:param parent :type main.PoseWrangler: reference to the main entry point for the tool, used for
|
|
restarting/upgrading the tool
|
|
:param file_path :type str: (optional) path to a json file containing serialized solver data
|
|
:return :type object: reference to the currently loaded version of pose wrangler
|
|
"""
|
|
# Load the RBF plugin
|
|
loaded_nodes = PluginManager.load_plugin()
|
|
# If the recommended solver is not loaded, fall back to the original pose wrangler implementation
|
|
if PluginManager.RECOMMENDED_SOLVER not in loaded_nodes:
|
|
LOG.warning("You are currently using an outdated plugin. Certain functionality may be limited.")
|
|
from epic_pose_wrangler.v1 import main
|
|
return main.UE4RBFAPI(view=view, parent=parent)
|
|
# Bool to keep track of importing the newest api version
|
|
import_failed = False
|
|
# Check if the scene uses the latest solver
|
|
if PluginManager.is_scene_using_recommended_solver():
|
|
# Try and import the latest tool version
|
|
try:
|
|
from epic_pose_wrangler.v2 import main
|
|
return main.UERBFAPI(view=view, parent=parent, file_path=file_path)
|
|
except ImportError as e:
|
|
LOG.error("Unable to import API v2, falling back to API v1 - {exception}".format(exception=e))
|
|
import_failed = True
|
|
# Fall back to API v1
|
|
from epic_pose_wrangler.v1 import main
|
|
# If the recommended solver is available but finds old nodes in the scene and imports correctly, provide
|
|
# the option to upgrade to the latest version
|
|
if not import_failed:
|
|
main.UE4RBFAPI.UPGRADE_AVAILABLE = True
|
|
return main.UE4RBFAPI(view=view, parent=parent)
|