''' Module for accessing configuration and settings. Provides access to the current Project, User, Environment( Motionbuilder ) and installed Tools. Author: Jason Hayes Author: Ross George ''' import platform import os WINDOWS_CONST = "Windows" class AppConfig(object): FFMPEG = "2_7_0" class VirtualProduction(object): ''' Provides access to Virtual Production Paths etc. ''' def __init__(self): class Path(object): ''' Paths for the main Virtual Production folders ''' def __init__(self): self._root = os.path.join('x:\\', 'virtualproduction') self._previz = os.path.join(self._root, 'previz') @property def Root(self): ''' Build root path ''' return self._root @property def Previz(self): ''' Build previz path ''' return self._previz self._path = Path() @property def Path(self): ''' Paths related to Virtual Production ''' return self._path # Overwrite the VirtualProduction class definition with a single instance VirtualProduction = VirtualProduction() if platform.system() == WINDOWS_CONST: import clr import sys import os import inspect import RS.Core.Metadata clr.AddReference("RSG.Base.Configuration") from RSG.Base.Configuration import ConfigFactory # Create our .NET config object which we will extract all configuration settings from _Config = ConfigFactory.CreateConfig() class Branch(object): '''Represents a branch within a project.''' def __init__(self, in_CLRBranch): self._Name = in_CLRBranch.Name self._IsDefault = (in_CLRBranch.Project.DefaultBranchName == self._Name) class Path: '''Nested singleton which contains all paths related to the branch.''' def __init__(self): self._Common = str(in_CLRBranch.Common) self._Build = str(in_CLRBranch.Build) self._Audio = str(in_CLRBranch.Audio) self._Code = str(in_CLRBranch.Code) @property def Common(self): '''Common root path.''' return self._Common @property def Build(self): '''Build root path.''' return self._Build @property def Audio(self): '''Audio root path.''' return self._Audio @property def Code(self): '''Code root path.''' return self._Code self._Path = Path() @property def Name(self): '''Name of the branch.''' return self._Name @property def IsDefault(self): '''Indicates if the branch is the default branch.''' return self._IsDefault @property def Path(self): '''Paths related to the branch''' return self._Path class Project(object): '''Provides access to project specific settings and configuration.''' def __init__(self, _project, _isCore=False): class Path(object): '''Nested singleton which contains all root level paths for the project.''' def __init__(self): self._Cache = str(_project.Cache) self._Root = str(_project.Root) self._Art = str(_project.DefaultBranch.Art) self._Anim = str(_project.DefaultBranch.Anim) self._Assets = str(_project.DefaultBranch.Assets) self._Processed = str(_project.DefaultBranch.Processed) self._Export = str(_project.DefaultBranch.Export) self._Metadata = str(_project.DefaultBranch.Metadata) if _project.Name.upper() == "RDR3": self._MocapRoot = "X:\\projects\\bob" elif _project.Name.upper() == "GTA5": self._MocapRoot = "X:\\projects\\paradise" elif _project.Name.upper() == "GTA5_DLC": self._MocapRoot = "X:\\projects\\paradise_dlc" else: self._MocapRoot = "unknown project" @property def Cache(self): '''Project export cache root path.''' return self._Cache @property def Root(self): '''Project root path.''' return self._Root @property def MocapRoot(self): '''Project mocap root path.''' return self._MocapRoot @property def Art(self): '''Project art source root path.''' return self._Art @property def Anim(self): '''Project anim source root path.''' return self._Anim @property def Assets(self): '''Project assets root path.''' return self._Assets @property def Processed(self): '''Project processed root path.''' return self._Processed @property def Export(self): '''Project export root path.''' return self._Export @property def Metadata(self): '''Project metadata root path.''' return self._Metadata self._Name = _project.Name self._FriendlyName = _project.FriendlyName self._Path = Path() self._isCore = _isCore self._DefaultBranch = None self._Branches = list() for CLRBranch in _project.Branches: CurrentBranch = Branch(CLRBranch.Value) self._Branches.append(CurrentBranch) if(CurrentBranch.Name == _project.DefaultBranch.Name): self._DefaultBranch = CurrentBranch self._DefaultBranch._IsDefault = True @property def IsCore(self): '''Is the core (main) project i.e. GTA5 or RDR3.''' return self._isCore @property def Name(self): '''Name of the project.''' # Lots of places are testing for the core project name in CAPITALS so have to put this check in if(self.IsCore): return self._Name.upper() else: return self._Name @property def FriendlyName(self): '''Name of the project.''' return self._FriendlyName @property def Codename(self): '''Codeame of the project.''' if self._Name == "RDR3": return str("bob") elif self._Name == "GTA5": return str("paradise") elif self._Name == "GTA5_DLC": return str("paradise_dlc") @property def Path(self): '''Paths related to the project''' return self._Path @property def Branches(self): '''Branches for the current project''' return self._Branches @property def DefaultBranch(self): '''The default branch for the project''' return self._DefaultBranch class User(object): '''Provides access to properties and settings related to the current user.''' def __init__(self): self._Name = str(_Config.Username) # IConfig has changed so altered script logic to take this into account withour try: self._Domain = str(_Config.Domain) except: if _Config.Studios.ThisStudio: self._Domain = str(_Config.Studios.ThisStudio.Domain) else: self._Domain = None if _Config.Studios.ThisStudio: self._Studio = str(_Config.Studios.ThisStudio.FriendlyName) else: self._Studio = None if _Config.EmailAddress: self._Email = _Config.EmailAddress.lower() else: self._Email = None self._IsExternal = True if self._Studio != None and 'R*' in self._Studio: self._IsExternal = False self._Type = None self._Types = [] # Determine user type. for userType in _Config.Usertypes: if userType.Flags == _Config.Usertype: self._Type = str(userType.FriendlyName) self._Types.append(str(userType.FriendlyName)) self._Types.sort() if self._Studio: self._ExchangeServer = str(_Config.Studios.ThisStudio.ExchangeServer) else: self._ExchangeServer = None @property def Name(self): '''Name of the user.''' return self._Name @property def Domain(self): '''Domain the user belongs to.''' return self._Domain @property def Studio(self): '''Studio the user belongs to.''' return self._Studio @property def Email(self): '''Email address of the user''' return self._Email @property def IsExternal(self): '''Indicates whether the user is external (outsourcer) or not''' return self._IsExternal @property def IsInternal(self): '''Indicates whether the user is internal (Rockstar) or not''' return not self.IsExternal @property def Type(self): '''Type of user (e.g. Animator, Artist, Tools Developer)''' return self._Type @property def Types(self): return self._Types @property def ExchangeServer(self): '''Users exhange server''' return self._ExchangeServer class Tool(object): '''Provides access to information and settings about the tools currently installed.''' def __init__(self): class Path(object): '''Nested singleton which contains relevant paths for tools.''' def __init__(self): self._Library = str(_Config.ToolsLib) self._Bin = str(_Config.ToolsBin) self._Logs = str(_Config.ToolsLogs) self._Root = str(_Config.ToolsRoot) self._Config = str(_Config.ToolsConfig) self._Drive = str(_Config.ToolsDrive) self._Temp = str(_Config.ToolsTemp) self._TechArt = '{0}\\techart'.format(self._Root) currentFile = str(os.path.abspath(inspect.getfile(inspect.currentframe()))).lower() if 'x:\\wildwest' in currentFile: self._TechArt = 'x:\\wildwest' @property def TechArt(self): '''Tech Art directory root path.''' return self._TechArt @property def Library(self): '''Tools root library path.''' return self._Library @property def Bin(self): '''Tools root bin path.''' return self._Bin @property def Logs(self): '''Tools log path.''' return self._Logs @property def Root(self): '''Tools root path.''' return self._Root @property def Config(self): '''Tools configuration path.''' return self._Config @property def Drive(self): '''Tools root drive.''' return self._Drive @property def Temp(self): '''Tools temporary path.''' return self._Temp class Executable(object): '''Nested singleton which contains relevant executable paths for tools.''' def __init__(self): self._LogViewer = '{0}\\bin\\UniversalLogViewer\\UniversalLogViewer.exe'.format(_Config.ToolsLib) @property def LogViewer(self): '''Log viewer .exe path.''' return self._LogViewer self._Version = _Config.Version.InstalledVersion.LabelName self._Path = Path() self._Executable = Executable() @property def Version(self): '''Currently install of tools version.''' return self._Version @property def Path(self): '''Useful paths related to tools.''' return self._Path @property def Executable(self): '''Useful executable paths (mainly from the bin directory).''' return self._Executable class Script(object): '''Provides access to information about the python script framework for this session of Motionbuilder.''' def __init__(self): class Path(object): '''Nested singleton which contains relevant paths for scripts.''' def __init__(self): currentFile = str(os.path.abspath(inspect.getfile(inspect.currentframe()))).lower() self._Root = os.path.abspath('{0}/../../python'.format(os.path.dirname(currentFile))) self._RockstarRoot = '{0}\\RS'.format(self._Root) self._ExternalRoot = '{0}\\External'.format(self._Root) self._ToolImages = '{0}\\..\\images'.format(self._Root) self._SetupConfig = '{0}\\setup.config'.format(self._Root) self._MenuConfig = '{0}\\menu.config'.format(self._Root) @property def Root(self): '''Script root path.''' return self._Root @property def RockstarRoot(self): '''Rockstar script root path.''' return self._RockstarRoot @property def ExternalRoot(self): '''External script root path.''' return self._ExternalRoot @property def SetupConfig(self): '''Setup configuration file path.''' return self._SetupConfig @property def MenuConfig(self): '''Menu configuration file path.''' return self._MenuConfig @property def ToolImages(self): '''Path for images used in tools.''' return self._ToolImages self._Path = Path() ConfigMetafile = RS.Core.Metadata.ParseMetaFile(self._Path._SetupConfig) self._DevelopmentMode = ConfigMetafile.DevelopmentMode self._TargetBuild = ConfigMetafile.TargetBuild self._TargetBuildVersion = ConfigMetafile.TargetBuildVersion self._TargetBuildTitle = ConfigMetafile.TargetBuildTitle self._DependencyPathList = list() for DependencyPath in ConfigMetafile.DependencyPathList: # ToDo - Need to expand {projRoot} properly self._DependencyPathList.append(DependencyPath) @property def Path(self): '''Useful paths related to script.''' return self._Path @property def DevelopmentMode(self): '''Indicates if the session of MotionBuilder is in development mode.''' return self._DevelopmentMode @property def TargetBuildVersion(self): '''The build version of MotionBuilder the scripts are designed to work with.''' return self._TargetBuildVersion @property def TargetBuild(self): '''The Application Handle name, this is used for pathing so migrates to newer versions of MB is easier to update. ''' return self._TargetBuild @property def TargetBuildTitle(self): '''Human friendly name for the TargetBuildVersion.''' return self._TargetBuildTitle @property def DependencyPathList(self): '''Paths to files and directories that MotionBuilder is dependant on.''' return self._DependencyPathList # Overwrite the Project class definition with a single instance of Project # Collect all the DLC projects and add to an dictionary DLCProjects = {} for _dlcproject in _Config.DLCProjects: dlcProject = Project(_dlcproject.Value) DLCProjects[_dlcproject.Key] = dlcProject # Pass in our Core project. Project = Project(_Config.CoreProject, True) # Overwrite the User class definition with a single instance of User User = User() # Overwrite the Tool class definition with a single instance of User Tool = Tool() # Overwrite the Environment class definition with a single instance of User Script = Script()