def addNamespace(self, node=None, ns='', hier=False):
        ''' adds a namespace
			Params:
				node: node to add to
				ns: namespace to add
				hier: process hierarchy or not
			Returns: True/False
		'''
        if not node:
            moBuLogger.error("No node passed.")
        if not ns:
            moBuLogger.error("No namespace passed.")

        # skip if namespace already there
        if ns in node.LongName:
            moBuLogger.debug("'%s' already in object: '%s'" %
                             (ns, node.LongName))
            return False

        try:
            if hier:
                node.ProcessNamespaceHierarchy(
                    FBNamespaceAction.kFBConcatNamespace, ns, None, False)
            else:
                node.ProcessObjectNamespace(
                    FBNamespaceAction.kFBConcatNamespace, ns, None, False)
        except:
            return False
        return True
Пример #2
0
	def localRotationAxisToggle(self, pModel='', size=25):
		modelList = []
		#work on everything selected
		selected = self.getSelected()
		if selected:
			modelList = selected 
		else:
			modelList = [pModel]
		if len(modelList) == 1 and modelList[0] == '':
			moBuLogger.info("Nothing selected or passed to function localRotationAxisToggle()")
			return
		
		for pModel in modelList:
#			pModel = self.validate(pModel, FBModelSkeleton)
			if not self.validate(pModel, FBModelSkeleton):
				moBuLogger.error("'%s' is not type FBModelSkeleton" % pModel)
			pModel = self.getObject(pModel, pyMB=True)
			if pModel:
				vis = True
				if pModel.GetPropertyValue('Show Rotation Axis'):
					vis = False
				
				pModel.SetPropertyValue('Show Rotation Axis', vis)
				pModel.SetPropertyValue('Pivot Visibility', 2)
				pModel.SetPropertyValue('Pivot Size', size)
		
		# for unitTests
		return True
Пример #3
0
    def openFileDialog(self, openSave="open", startPath=""):
        """ opens dialog box to select a file
		Params:
			openSave: open or save file type
			startPath: start in path
		Returns: path and fileName/False
		"""
        lFp = FBFilePopup()
        lFp.Caption = "Select a file"
        if openSave == "open":
            lFp.Style = FBFilePopupStyle.kFBFilePopupOpen
        elif openSave == "save":
            lFp.Style = FBFilePopupStyle.kFBFilePopupSave
        else:
            moBuLogger.error("Illegal arg passed. openSave=%s" % openSave)

            # BUG: If we do not set the filter, we will have an exception.
        lFp.Filter = "*"

        if not startPath:
            if not self.sceneName == "Untitled":
                lFp.Path = str(self.sceneName.parent)
            else:
                lFp.Path = str(schemaObj.artRoot.replace("/", "\\"))
        else:
            lFp.Path = str(Path(startPath).makePretty(lastSlash=False, backward=True))

            # open window
        lRes = lFp.Execute()

        if lRes:
            return lFp.FullFilename
        else:
            return False
	def addNamespace(self, node=None, ns='', hier=False):
		''' adds a namespace
			Params:
				node: node to add to
				ns: namespace to add
				hier: process hierarchy or not
			Returns: True/False
		'''
		if not node:
			moBuLogger.error("No node passed.")
		if not ns:
			moBuLogger.error("No namespace passed.")
		
		# skip if namespace already there
		if ns in node.LongName:
			moBuLogger.debug("'%s' already in object: '%s'" % (ns, node.LongName))
			return False
		
		try:
			if hier:
				node.ProcessNamespaceHierarchy(FBNamespaceAction.kFBConcatNamespace, ns, None, False)
			else:
				node.ProcessObjectNamespace(FBNamespaceAction.kFBConcatNamespace, ns, None, False)
		except:
			return False
		return True 
Пример #5
0
	def isInSet(self, pObject='', pSet=''):
		''' see if object is in set
			Params:
				pObject: object to look for
				pSet: set to look in
			Returns: True/False
		'''			
		if not isinstance(pSet, FBSet):
			moBuLogger.error("'%s' is not of type(set)" % pSet)
			return False
		if not pObject:
			moBuLogger.error("No pObject passed.")
		
		# check if pObject is str
		if isinstance(pObject, str):
			#check directly
			for item in pSet.Items:
				if item.Name == pObject:
					moBuLogger.info("Found '%s' in '%s'" % (item.Name, pSet.Name))
					return True
		else:
			#check directly
			for item in pSet.Items:
				if item == pObject:
					moBuLogger.info("Found '%s' in '%s'" % (item.Name, pSet.Name))
					return True 
		
		# not found
		if isinstance(pObject, str):
			pObjectName = pObject
		else:
			pObjectName = pObject.LongName
		moBuLogger.info("Did not find '%s' in '%s'" % (pObjectName, pSet.Name))
		return False
Пример #6
0
	def zeroTimeline(self, character=None):
		''' moves timeline to zero with character animation
			Params:
				character: FBcharacterNode
			Returns: True/False
		'''
		
		# find start of current take
		currentTake = FBSystem().CurrentTake
		currentTimeSpan = currentTake.LocalTimeSpan
		currentTakeStartTimeInt = int(currentTimeSpan.GetStart().GetTimeString())
		
		# check timeline
		if currentTakeStartTimeInt == 0:
			# abort
			moBuLogger.warning("No need to run zeroTimeline, first frame is already 0.")
			return False
		
		# find stop and offset
		currentTakeStopTimeInt = int(currentTimeSpan.GetStop().GetTimeString())
		offset = FBTime(0, 0, 0, -1 * currentTakeStartTimeInt)
		
		# create track
		lTrackContainer = FBStoryTrack(FBStoryTrackType.kFBStoryTrackCharacter)
#		lTrackContainer = FBStoryTrack(FBStoryTrackType.kFBStoryTrackAnimation)

		# find character		
		if not character:
			character = MoBuSceneCore().getCharacter(hipsJoint='')
		if not character:
			moBuLogger.error("Failed to find character.")
		
		# plot to control rig		
		if not character.GetCurrentControlSet():
			character.CreateControlRig(True) 
		character.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, self.SetPlotOptions())
		
		# assign character to track
		lTrackContainer.Character = character
		
		# create clip, and offset it
		lTrackContainer.CopyTakeIntoTrack(currentTimeSpan, currentTake, offset)
		
		# move timeline
		newTimeSpan = FBTimeSpan()
		newTimeSpan.Set(FBTime(0, 0, 0, 0), FBTime(0, 0, 0, currentTakeStopTimeInt - currentTakeStartTimeInt))
		currentTake.LocalTimeSpan = newTimeSpan
		
		# plot back down
		self.plotCharacter(character=character, nSpace='', quiet=True)
		
		# nuke story track
		lTrackContainer.FBDelete()
		
		moBuLogger.info("Zeroed-out timeline.")
		
		return True
Пример #7
0
    def loadPCSoptions(self, pathFile=None, quiet=False, pOptions=None):
        """ saves with customFBFbxOptions
		Params:
			pathFile: complete file path to save
			quiet: suppress messages
			pOptions: pre-made options
		Returns: True/False
		"""

        # pick file if not passed
        if not pathFile:
            pathFile = self.openFileDialog(openSave="open")

        # 		# Check for binary
        # 		lFbp = FBProgress()
        # 		lFbp.ProgressBegin()
        # 		lFbp.Caption = "Checking binary on %s" % pathFile.basename
        # 		lFbp.Percent = 50
        # 		if Path(pathFile).isbin:
        # 			moBuLogger.warning("Skipping file '%s' because detected binary" % pathFile)
        # 			lFbp.ProgressDone()
        # 			return False
        # 		moBuLogger.debug("Checked '%s' for binary, passed." % pathFile)
        #
        # 		lFbp.ProgressDone()

        # check for cancel
        if not pathFile:
            moBuLogger.info("Cancelled open via loadPCSoptions()")
            return False

        if not pOptions:
            pOptions = self.customFBFbxOptions(pLoad=True)

            # by default, load all takes
        success = self.app.FileOpen(
            str(pathFile), 1 - quiet, self.customFBFbxOptions(pLoad=1, saveAllTakes=1, allElements=1)
        )
        if success:
            moBuLogger.info("Success opening '%s'" % pathFile)
        else:
            moBuLogger.error("Failed to open '%s'" % pathFile)

        # 		# check for hips
        # 		ref = self.getObject("Reference")
        # 		if ref:
        # 			if len(ref.Children) > 0:
        # 				if not ref.Children[0].Name == 'Hips':
        # 					moBuLogger.infoDialog("WARNING: No Hips found in scene. Check your joint names.", "Joints Missing")

        return success
Пример #8
0
	def listTakeNamesFromFile(self, targetFilePath):
		''' prints and returns list of all Takes from a file
		Params:
			targetFilePath: file to get take names from 
		Returns: [list] of take names
		'''
		takeNames = []
		if not os.path.exists(targetFilePath):
			moBuLogger.error("'%s' does not exist")
		pFbxOptionsLoad = FBFbxOptions(1, targetFilePath)
		for idx in range(0, pFbxOptionsLoad.GetTakeCount()):
			moBuLogger.info(pFbxOptionsLoad.GetTakeName(idx))
			takeNames.append(pFbxOptionsLoad.GetTakeName(idx))
		return takeNames
Пример #9
0
	def cleanTakes(self, takeNames=['Take 001'], pTakeToKeep=''):
		''' will remove standard non-needed takes 'Take 001', 'Characterization'
		Params:
			takeNames: [list] of takes to remove
			pTakeToKeep: take object/name to keep, delete others
		Returns: [list] take names deleted
		'''
		deletedTakeNames = []
		pTakes = []
		takesToDelete = []
		
		# check takeNames are for list
		if not isinstance(takeNames, list):
			moBuLogger.error("mbCore.cleanTakes() expects 'list' type arg for 'takeNames'")

		if pTakeToKeep:
			takeNames[0] = 'all'
			# check for str
			if isinstance(pTakeToKeep, str):
				pTakeToKeep = self.getTakeFromName(pTakeToKeep)
		
		# get all takes
		if takeNames[0] == 'all':
			pTakes = FBSystem().Scene.Takes
		else:
			for takeName in takeNames:
				if isinstance(takeName, str):
					# convert to FBPropertyListTake
					pTakes.append(self.getTakeFromName(takeName))
				else:
					# just in case FBTake objects were passed
					pTakes.append(takeName)
		# clean takeNames
		del(takeNames)
			
		# delete takes added to list
		if pTakes:
			for pTake in pTakes:
				if not pTake == pTakeToKeep:
					takesToDelete.append(pTake)
			# perform deletion
			for takeToDelete in takesToDelete:
				deletedTakeName = self.deleteTake(takeToDelete)
				if deletedTakeName:
					deletedTakeNames.append(deletedTakeName)
				
		return deletedTakeNames
Пример #10
0
	def clearAnimCurve(self, pAnimNode):
		''' Clears curves from passed FBAnimationNode
		Params:
			pAnimNode: FBAnimationNode to clear curves with
		Returns: True/False
		'''
		if not isinstance(pAnimNode, FBAnimationNode):
			moBuLogger.error("Was not passed FBAnimationNode object: '%s'" % pAnimNode)
		if not len(pAnimNode.Nodes) == 3:
			moBuLogger.warning("No subAnimNodes found on: '%s'" % pAnimNode)
		else:
			pAnimNode.Nodes[0].FCurve.EditClear()
			pAnimNode.Nodes[1].FCurve.EditClear()
			pAnimNode.Nodes[2].FCurve.EditClear()
			return True
		
		return False
	def removeAllNamespaces(self, node=None, hier=False):
		''' removes all namespaces
			Params:
				node: node to remove from
				hier: process hierarchy or not
			Returns: True/False
		'''
		if not node:
			moBuLogger.error("No node passed.")
		try:
			if hier:
				node.ProcessNamespaceHierarchy(FBNamespaceAction.kFBRemoveAllNamespace, "")
			else:
				node.ProcessObjectNamespace(FBNamespaceAction.kFBRemoveAllNamespace, "")
		except:
			return False
		return True
Пример #12
0
	def getAllByType(self, _type='all'):
		''' return list[] of everything in scene of specific type
		Params:
			#_type: passed FBobject type
			_type: passed FBObject type as a str
			found: [list] of objects of type
		'''
		# check for str(_type)
		if not isinstance(_type, str):
			moBuLogger.error("_type arg must be type(str) now.")
			
		allComps = FBSystem().Scene.Components
		pObjects = []
		for comp in allComps:
			if _type == 'all':
				
				# skip __SYSTEM objects
				if '__SYSTEM' in comp.LongName:
					continue
				
				# skip animationLayers
				if comp.ClassName() == 'FBBox':
					if "Anim" in comp.Name:
						continue
				
				# skip if type(FBBox), BaseAnimation
				if isinstance(comp, FBBox) and ('BaseAnimation' in comp.Name or 'AnimLayer1' in comp.LongName):
					continue
				
				# skip if type(FBModel), 'ActorBodyBone' and 'ActorBodyMesh'
				if isinstance(comp, FBModel) and ('ActorBodyBone' in comp.LongName or 'ActorBodyMesh' in comp.LongName):
					continue
				
				# skip if type(FBModel), 'Motion Blend Result'
				if isinstance(comp, FBModel) and 'Motion Blend Result' in comp.Name:
					continue
				
				pObjects.append(comp)
				
				
			elif _type == comp.ClassName():
				pObjects.append(comp)
			moBuLogger.debug("Adding %s  <---type	 %s  <--LongName" % (comp.ClassName(), comp.LongName))
			
		return pObjects
    def getNamespace(self, node=None):
        ''' returns namespaces on node
			Params:
				node: node to remove from
				hier: process hierarchy or not
			Returns: list of namespaces /False
		'''
        if not node:
            moBuLogger.error("No node passed.")

        nameSpaces = []
        splitByColon = node.LongName.split(':')
        for i in range(len(splitByColon) - 1):
            nameSpaces.append(splitByColon[i])

        if not nameSpaces:
            return False

        return nameSpaces
	def getNamespace(self, node=None):
		''' returns namespaces on node
			Params:
				node: node to remove from
				hier: process hierarchy or not
			Returns: list of namespaces /False
		'''
		if not node:
			moBuLogger.error("No node passed.")

		nameSpaces = []			
		splitByColon = node.LongName.split(':')
		for i in range(len(splitByColon) - 1):
			nameSpaces.append(splitByColon[i])
			
		if not nameSpaces:
			return False
		
		return nameSpaces
    def removeAllNamespaces(self, node=None, hier=False):
        ''' removes all namespaces
			Params:
				node: node to remove from
				hier: process hierarchy or not
			Returns: True/False
		'''
        if not node:
            moBuLogger.error("No node passed.")
        try:
            if hier:
                node.ProcessNamespaceHierarchy(
                    FBNamespaceAction.kFBRemoveAllNamespace, "")
            else:
                node.ProcessObjectNamespace(
                    FBNamespaceAction.kFBRemoveAllNamespace, "")
        except:
            return False
        return True
    def replaceNamespace(self, node=None, nsOrig='', nsReplace='', hier=False):
        ''' replaces all namespaces
			Params:
				node: node to replace
				nsOrig: namespace to replace
				nsReplace: new namespace
				hier: process hierarchy or not
			Returns: True/False
		'''
        if not node:
            moBuLogger.error("No node passed.")
        if not nsOrig:
            moBuLogger.error("No namespace passed.")
        if not nsReplace:
            moBuLogger.error("No namespace passed.")
        try:
            if hier:
                node.ProcessNamespaceHierarchy(
                    FBNamespaceAction.kFBReplaceNamespace, nsOrig, nsReplace,
                    False)
            else:
                node.ProcessObjectNamespace(
                    FBNamespaceAction.kFBReplaceNamespace, nsOrig, nsReplace,
                    False)
        except:
            return False
        return True
Пример #17
0
	def deleteNote(self, nameOrFBNote=''):
		''' delete FBNote
		Params:
			nameOrFBNote: name of note OR FBNote object
		Returns: True/False
		'''
		if isinstance(nameOrFBNote, FBNote):
			ourNote = nameOrFBNote
		else:
			ourNote = self.getObjectFromWildcardName(pattern=nameOrFBNote, byName=True, returnLongNames=False, byType=FBNote)
			if not ourNote:
				moBuLogger.error("Could not find FBNote: '%s'" % nameOrFBNote)
				return False
		
		try:
			# detach?
			#ourNode.Detach()
			ourNote.FBDelete()
			return True
		except:
			moBuLogger.error("Failed to delete FBNote: '%s'" % nameOrFBNote)
			return False
Пример #18
0
    def cleanDirs(self, folderPath="", dirExtension=".fbm"):
        """ Cleans viral .bck/.fbm folders from given folderPath
			Params:
				folderPath: director to clean
				dirExtension: extension to look for on end of dir
			Returns: True if cleaned any
			"""
        deleted = False
        if not folderPath:
            moBuLogger.error("No folderPath arg passed.")
            return False

        for root, dirs, unused in os.walk(folderPath):
            for _dir in dirs:
                dirPath = os.path.join(root, _dir)
                if Path(dirPath).isdir:
                    if re.search(dirExtension, dirPath):
                        try:
                            shutil.rmtree(dirPath)
                            deleted = True
                        except WindowsError:
                            moBuLogger.info("Failed to remove '%s'" % dirPath)
        return deleted
Пример #19
0
    def mergePCSoptions(self, pathFile="", quiet=True, pOptions=None):
        """ merges with customFBFbxOptions
		Params:
			pathFile: complete file path to merge
			quiet: suppress messages
			pOptions: pre-made options
		Returns: True/False
		"""
        if not pathFile:
            pathFile = self.openFileDialog()

        if not pOptions:
            pOptions = self.customFBFbxOptions(pLoad=True, saveAllTakes=True, allElements=True)

            # by default, do NOT merge takes
        if self.app.FileMerge(str(pathFile), 1 - quiet, pOptions):
            # report
            if not quiet:
                moBuLogger.info("Merged %s with PCSoptions" % pathFile)
            return True
        else:
            moBuLogger.error("Failed to merge '%s'" % pathFile)
            return False
Пример #20
0
    def isInSet(self, pObject='', pSet=''):
        ''' see if object is in set
			Params:
				pObject: object to look for
				pSet: set to look in
			Returns: True/False
		'''
        if not isinstance(pSet, FBSet):
            moBuLogger.error("'%s' is not of type(set)" % pSet)
            return False
        if not pObject:
            moBuLogger.error("No pObject passed.")

        # check if pObject is str
        if isinstance(pObject, str):
            #check directly
            for item in pSet.Items:
                if item.Name == pObject:
                    moBuLogger.info("Found '%s' in '%s'" %
                                    (item.Name, pSet.Name))
                    return True
        else:
            #check directly
            for item in pSet.Items:
                if item == pObject:
                    moBuLogger.info("Found '%s' in '%s'" %
                                    (item.Name, pSet.Name))
                    return True

        # not found
        if isinstance(pObject, str):
            pObjectName = pObject
        else:
            pObjectName = pObject.LongName
        moBuLogger.info("Did not find '%s' in '%s'" % (pObjectName, pSet.Name))
        return False
	def replaceNamespace(self, node=None, nsOrig='', nsReplace='', hier=False):	
		''' replaces all namespaces
			Params:
				node: node to replace
				nsOrig: namespace to replace
				nsReplace: new namespace
				hier: process hierarchy or not
			Returns: True/False
		'''
		if not node:
			moBuLogger.error("No node passed.")
		if not nsOrig:
			moBuLogger.error("No namespace passed.")
		if not nsReplace:
			moBuLogger.error("No namespace passed.")
		try:
			if hier:
				node.ProcessNamespaceHierarchy(FBNamespaceAction.kFBReplaceNamespace, nsOrig, nsReplace, False)
			else:
				node.ProcessObjectNamespace(FBNamespaceAction.kFBReplaceNamespace, nsOrig, nsReplace, False)
		except:
			return False
		return True
_VERSION = 1.05

# Load additions dependent on MoBu version
if mbCore.mobuVer == 2010:
	from pyfbsdk_additions import CreateUniqueTool as FBCreateUniqueTool #@UnresolvedImport @UnusedImport
	from pyfbsdk_additions import HBoxLayout as FBHBoxLayout #@UnusedImport @UnresolvedImport
	from pyfbsdk_additions import TabControl as FBTabControl #@UnusedImport @UnresolvedImport
	from pyfbsdk_additions import GridLayout as FBGridLayout #@UnusedImport @UnresolvedImport
elif mbCore.mobuVer == 2012:
	from pyfbsdk_additions import FBCreateUniqueTool, FBHBoxLayout, FBTabControl, FBGridLayout #@Reimport @UnresolvedImport @UnusedImport
	fileMenuName = "&File"
elif mbCore.mobuVer == 2013 or mbCore.mobuVer == 2014:
	from pyfbsdk_additions import FBCreateUniqueTool, FBHBoxLayout, FBTabControl, FBGridLayout #@Reimport @UnresolvedImport @UnusedImport
	fileMenuName = "File"
else:
	moBuLogger.error("Failed to find proper MoBu version: '%s'" % mbCore.mobuVer)

class MoBuToolsMenu(object):
	'''
	Super class of MotionBuilder Tool Delivery Menu. 
	Methods to manage the delivery system.
	'''

	def __init__(self):
		""" MoBuToolsMenu.__init__():  set initial parameters """
		super(MoBuToolsMenu, self).__init__()
		
		# Set who is running for metrics
		self.userName = getpass.getuser()
		
		# run metrics
Пример #23
0
    def customFBFbxOptions(self, pLoad=False, saveAllTakes=True, allElements=True, selection=False, **kwargs):
        """ create save/load options
		Params:
			pLoad: True if loading, False if saving
			saveAllTakes: Set to False if save current take only
			allElements: Set to False and pass kwargs to save/load/merge specific elements
			selection: True to save selected only
		Returns: FBFbxOptions object
		"""
        if self.mobuVer == 2010:
            moBuLogger.warning("FBFbxOptions are not valid for 2010")
            return None

        elif self.mobuVer == 2012 or self.mobuVer == 2013 or self.mobuVer == 2014:
            # create object
            pFbxOptions = FBFbxOptions(pLoad)

            if not allElements:
                # set all ElementActions and Base properties to false
                pFbxOptions.SetAll(FBElementAction.kFBElementActionDiscard, False)
                baseProperties = [
                    "BaseCameras",
                    "CameraSwitcher",
                    "CameraSwitcherSettings",
                    "CurrentCamera",
                    "CurrentCameraSettings",
                    "GlobalLighting",
                    "GlobalLightingSettings",
                    "Transport",
                    "TransportSettings",
                    "EmbedMedia",
                    "SaveSelectedModelsOnly",
                ]
                for bProperty in baseProperties:
                    exec ("pFbxOptions.%s=False" % bProperty)

                    # process kwargs
                for key in kwargs:
                    # check for non-strings passed in
                    if not isinstance(kwargs[key], str):
                        moBuLogger.error("A non-string type arg was passed in: '%s'" % kwargs[key])
                    if "kFBElementAction" in kwargs[key]:
                        # FBPropertyElementAction
                        exec ("pFbxOptions.%s = FBElementAction.%s" % (key, kwargs[key]))
                    else:
                        # FBPropertyBase
                        exec ("pFbxOptions.%s=%s" % (key, kwargs[key]))

                        # save selected for saves
            if not pLoad and selection:
                pFbxOptions.SaveSelectedModelsOnly = True

                # skip takes
            if not saveAllTakes:
                currentTake = self.system.CurrentTake

                pTakeIndex = 0
                for take in self.scene.Takes:
                    # save current take only
                    if not pLoad:
                        if not take.Name == currentTake.Name:
                            pFbxOptions.SetTakeSelect(pTakeIndex, False)
                            # merge no takes
                    else:
                        pFbxOptions.SetTakeSelect(pTakeIndex, False)
                    pTakeIndex += 1

                    # save ASCII
            pFbxOptions.UseASCIIFormat = True

            return pFbxOptions
        else:
            moBuLogger.error("Wrong version of MotionBuilder '%s'" % self.mobuVer)
Пример #24
0
    def savePCSoptions(self, pathFile=None, quiet=True, pOptions=None, p4=True):
        """ saves with customFBFbxOptions
		Params:
			pathFile: complete file path to save
			quiet: suppress messages
			pOptions: pre-made options
			p4: markForAdd/checkout or not
		Returns: True/False
		"""

        text = "Saved with PCSoptions"

        # pick file if not passed
        if not pathFile:
            if not quiet:
                pathFile = self.openFileDialog(openSave="save")
            else:
                moBuLogger.error("No pathFile passed and quiet=True")
                return False
        if not pathFile:
            moBuLogger.info("Cancelled")
            return False

            # add extension if they didn't type it
        if not Path(pathFile).ext:
            pathFile = "%s.fbx" % pathFile

        # 		# checkout from perforce
        # 		if p4:
        # 			if self.pcsParseObj.isp4Active:
        # 				self.p4.fileName = pathFile
        # 				if self.p4.isP4Connected:
        # 					try:
        # 						self.p4.p4CheckOut(desc=text)
        ##					except P4.P4Exception:
        # 					except:
        # 						moBuLogger.warning("Failed to checkout: '%s'" % pathFile)
        # 			else:
        # 				if not quiet:
        # 					moBuLogger.warning('P4Active setting FALSE, not checking out.')
        # 		else:
        # 			if not quiet:
        # 				moBuLogger.warning("p4 arg passed as False, not checking out for file: '%s'." % pathFile)

        if not pOptions:
            pOptions = self.customFBFbxOptions(pLoad=False, saveAllTakes=True)

            # 2010 save process
        currentTakeObject = FBSystem().CurrentTake
        if self.mobuVer == 2010:
            lMgr = FBFbxManager()  # @UndefinedVariable
            lMgr.SaveBegin(str(pathFile))
            lMgr.Selected = True
            for strEach in lMgr.Takes:
                if strEach.Name != currentTakeObject.Name:
                    strEach.Import = False
            lMgr.EmbedMedia = False
            lMgr.BaseCameras = False
            lMgr.CameraSwitcherSettings = False
            lMgr.CurrentCameraSettings = False
            lMgr.GlobalLightingSettings = False
            lMgr.TransportSettings = False
            if not lMgr.Save():
                moBuLogger.errorDialog("There is a problem saving the file", "Cannot Save")
            if not lMgr.SaveEnd():
                moBuLogger.errorDialog("There is a problem saving the file", "Cannot Save")

                # 2012 save process
        elif self.mobuVer == 2012 or self.mobuVer == 2013 or self.mobuVer == 2014:
            alreadyExists = False
            if Path(pathFile).exists():
                alreadyExists = True
            if not self.app.FileSave(str(pathFile), pOptions):
                # cancelled?
                moBuLogger.warning("Cancelled")
                return False
            if not alreadyExists:
                # check to see if new file is there
                res = os.path.exists(str(pathFile))
                if res:
                    if not quiet:
                        moBuLogger.info("%s, '%s'" % (text, str(pathFile)))
                    return True
                else:
                    moBuLogger.errorDialog("Failed to save '%s'" % str(pathFile))
                    return False
            else:
                # TODO: check to see if different?
                if not quiet:
                    moBuLogger.info("%s, '%s'" % (text, str(pathFile)))
                return True
    def replaceNamespaceOnChar(self, nSpace='', quiet=False):
        ''' replace namespace on character or add if none
			Params:
				nSpace: namespace to add/replace with
				quiet: suppress message
			Returns: True/False
		'''

        success = True

        # get selected reference or find it
        selected = self.getSelected(_type='all', found=True)
        if not selected:
            # try to select
            selected = self.getReference(namespace='', pyMB=False)
            if not selected:
                # run again
                if not quiet:
                    moBuLogger.errorDialog("Select a node from the character")
                else:
                    moBuLogger.error("Select a node from the character")
                return False

        # get the FBSet associated with the character
        if isinstance(selected, FBSet):
            charSet = selected
        else:
            charSet = mbSets.findSetFromObject(pObject=selected, quiet=quiet)
        if not charSet:
            return False

        # iterate through all items in set
        for item in charSet.Items:
            # check if already has namespaces
            currentNS = None
            if mbNamespace.getNamespace(node=item):
                for ns in mbNamespace.getNamespace(node=item):
                    # do NOT replace '*_Template' Namespaces
                    if not '_Template' in ns:
                        currentNS = ns

                        # check for replace or add
                        if not mbNamespace.replaceNamespace(node=item,
                                                            nsOrig=currentNS,
                                                            nsReplace=nSpace,
                                                            hier=False):
                            moBuLogger.debug(
                                "Failed to replaceNamespace on: '%s'" %
                                item.LongName)
                            success = False
                    else:  #_Template Namespace
                        # check for existence of new nSpace
                        if not nSpace in mbNamespace.getNamespace(node=item):
                            # add
                            if not mbNamespace.addNamespace(
                                    node=item, ns=nSpace, hier=False):
                                moBuLogger.debug(
                                    "Failed to addNamespace on: '%s'" %
                                    item.LongName)
                                success = False
            else:
                if not mbNamespace.addNamespace(
                        node=item, ns=nSpace, hier=False):
                    moBuLogger.debug("Failed to addNamespace on: '%s'" %
                                     item.LongName)
                    success = False

        # add nameSpace to set as well
        if not mbNamespace.addNamespace(node=charSet, ns=nSpace, hier=False):
            moBuLogger.debug("Failed to addNamespace on: '%s'" %
                             charSet.LongName)
            # no need to report False, already getting added

        return success
        #--------------------------------------------
        # start debugging
        import common.diagnostic.wingdbstub  #@UnusedImport

        #--------------------------------------------
        from common.diagnostic.pcsLogger import moBuLogger
        # do main import loop
        try:
            from moBu.core.sysGlobalMenu import MoBuToolsMenu
        except:
            moBuLogger.info(sys.exc_info())
            moBuLogger.errorDialog("Failed to import moBu and start ArtMonkey")
            print "Failed to import moBu. Error: "
            print sys.exc_info()

        #--------------------------------------------
        # start ArtMonkey Global menu
        try:
            MoBuToolsMenu().createTool()
        except:
            moBuLogger.error("Failed to create Art Monkey menu")

        #--------------------------------------------
        # report run from location
        def tempFunc():
            pass

        fileLocation = os.path.dirname(inspect.getsourcefile(tempFunc))
        moBuLogger.info("Ran pcsGlobalSetup.py from '%s'" % fileLocation)
	def replaceNamespaceOnChar(self, nSpace='', quiet=False):
		''' replace namespace on character or add if none
			Params:
				nSpace: namespace to add/replace with
				quiet: suppress message
			Returns: True/False
		'''
		
		success = True
		
		# get selected reference or find it
		selected = self.getSelected(_type='all', found=True)
		if not selected:
			# try to select
			selected = self.getReference(namespace='', pyMB=False)
			if not selected:
				# run again
				if not quiet:
					moBuLogger.errorDialog("Select a node from the character")
				else:
					moBuLogger.error("Select a node from the character")
				return False
		
		# get the FBSet associated with the character
		if isinstance(selected, FBSet):
			charSet = selected
		else:
			charSet = mbSets.findSetFromObject(pObject=selected, quiet=quiet)
		if not charSet:
			return False
	
		# iterate through all items in set		
		for item in charSet.Items:
			# check if already has namespaces
			currentNS = None
			if mbNamespace.getNamespace(node=item):
				for ns in mbNamespace.getNamespace(node=item):
					# do NOT replace '*_Template' Namespaces
					if not '_Template' in ns:
						currentNS = ns
						
						# check for replace or add
						if not mbNamespace.replaceNamespace(node=item, nsOrig=currentNS, nsReplace=nSpace, hier=False):
							moBuLogger.debug("Failed to replaceNamespace on: '%s'" % item.LongName)
							success = False
					else:	#_Template Namespace
						# check for existence of new nSpace
						if not nSpace in mbNamespace.getNamespace(node=item):
							# add
							if not mbNamespace.addNamespace(node=item, ns=nSpace, hier=False):
								moBuLogger.debug("Failed to addNamespace on: '%s'" % item.LongName)
								success = False
			else:
				if not mbNamespace.addNamespace(node=item, ns=nSpace, hier=False):
					moBuLogger.debug("Failed to addNamespace on: '%s'" % item.LongName)
					success = False
			
		# add nameSpace to set as well
		if not mbNamespace.addNamespace(node=charSet, ns=nSpace, hier=False):
			moBuLogger.debug("Failed to addNamespace on: '%s'" % charSet.LongName)
			# no need to report False, already getting added
		
		return success
		sys.path.append('%s/python/moBu/site-packages/%s' % (gv.toolsLocation, pyMoBuVer))
				
		#--------------------------------------------
		# start debugging
		import common.diagnostic.wingdbstub #@UnusedImport
		
		#--------------------------------------------
		from common.diagnostic.pcsLogger import moBuLogger
		# do main import loop
		try:
			from moBu.core.sysGlobalMenu import MoBuToolsMenu
		except:
			moBuLogger.info(sys.exc_info())
			moBuLogger.errorDialog("Failed to import moBu and start ArtMonkey")
			print "Failed to import moBu. Error: "
			print sys.exc_info()
		
		#--------------------------------------------
		# start ArtMonkey Global menu
		try:
			MoBuToolsMenu().createTool()
		except:
			moBuLogger.error("Failed to create Art Monkey menu")
		
		#--------------------------------------------
		# report run from location
		def tempFunc():
			pass
		fileLocation = os.path.dirname(inspect.getsourcefile(tempFunc))
		moBuLogger.info("Ran pcsGlobalSetup.py from '%s'" % fileLocation)
_VERSION = 1.05

# Load additions dependent on MoBu version
if mbCore.mobuVer == 2010:
    from pyfbsdk_additions import CreateUniqueTool as FBCreateUniqueTool  #@UnresolvedImport @UnusedImport
    from pyfbsdk_additions import HBoxLayout as FBHBoxLayout  #@UnusedImport @UnresolvedImport
    from pyfbsdk_additions import TabControl as FBTabControl  #@UnusedImport @UnresolvedImport
    from pyfbsdk_additions import GridLayout as FBGridLayout  #@UnusedImport @UnresolvedImport
elif mbCore.mobuVer == 2012:
    from pyfbsdk_additions import FBCreateUniqueTool, FBHBoxLayout, FBTabControl, FBGridLayout  #@Reimport @UnresolvedImport @UnusedImport
    fileMenuName = "&File"
elif mbCore.mobuVer == 2013 or mbCore.mobuVer == 2014:
    from pyfbsdk_additions import FBCreateUniqueTool, FBHBoxLayout, FBTabControl, FBGridLayout  #@Reimport @UnresolvedImport @UnusedImport
    fileMenuName = "File"
else:
    moBuLogger.error("Failed to find proper MoBu version: '%s'" %
                     mbCore.mobuVer)


class MoBuToolsMenu(object):
    '''
	Super class of MotionBuilder Tool Delivery Menu. 
	Methods to manage the delivery system.
	'''
    def __init__(self):
        """ MoBuToolsMenu.__init__():  set initial parameters """
        super(MoBuToolsMenu, self).__init__()

        # Set who is running for metrics
        self.userName = getpass.getuser()

        # run metrics