Пример #1
0
    def _do_maya_post_publish(self, work_template, progress_cb):
        """
        Do any Maya post-publish work
        """
        import maya.cmds as cmds
        progress_cb(0, "Post Checking scene now...")

        ## Now turn back on all the model editors
        cleanup.turnOnModelEditors()
        if cmds.objExists('OCEAN_hrc'):
            ## Now set the scenes Ocean settings back to normal
            cmds.setAttr('OCEAN_hrc.visibility', 1)
            cmds.setAttr('oceanPreviewPlane_prv.visibility', 1)
            cmds.setAttr('animPreviewPlane_prv.visibility', 0)
            try:
                cmds.setAttr('OCEAN_hrc.oceanCalcOnOff', 1)
                cmds.setAttr('OCEAN_hrc.oceanRes', 50)
            except:
                pass

            ## Convert the NURBS ocean to polyplane and assign the surfaceShader
            ## NOTE this will prob need a smooth node applied as well. Can you look into that for me.
            # fluidsLib._convertOceanToPolys()

            ## Setup the hardware renderglobals ready for submission to the render farm
            settings._setHWRenderGlobals()

            ## now bring up the renderfarm submission tool
            # mel.eval('source "T:/installer/SubmitMayaToDeadline.mel";')
            # mel.eval("SubmitJobToDeadline;")

        progress_cb(100, "Post complete...")
    def _do_maya_post_publish(self, work_template, progress_cb):
        """
        Do any Maya post-publish work
        """        
        import maya.cmds as cmds
        progress_cb(0, "Post Checking scene now...")

        ## Now turn back on all the model editors
        cleanup.turnOnModelEditors()
        if cmds.objExists('OCEAN_hrc'):
            ## Now set the scenes Ocean settings back to normal
            cmds.setAttr('OCEAN_hrc.visibility', 1)
            cmds.setAttr('oceanPreviewPlane_prv.visibility', 1)
            cmds.setAttr('animPreviewPlane_prv.visibility', 1)
            if cmds.objExists('OCEAN_hrc.oceanCalcOnOff'):
                cmds.setAttr('OCEAN_hrc.oceanCalcOnOff', 0)
            cmds.setAttr('OCEAN_hrc.oceanRes', 50)

        if cmds.objExists('BAKE_CAM_hrc'):
            try:    cmds.delete('BAKE_CAM_hrc')
            except: pass

        ## Gin's add-on set model panel to show back to ALL after publish
        modelPanels = cmds.getPanel(type = 'modelPanel')
        if modelPanels:
            [cmds.modelEditor(mp, edit = True, allObjects = True) for mp in modelPanels]
                            
        cmds.select(clear = True)
        cmds.file(save = True, force = True)
        progress_cb(100,"Post complete...")
    def _do_maya_post_publish(self, work_template, progress_cb):
        """
        Do any Maya post-publish work
        """
        import maya.cmds as cmds
        progress_cb(0, "Post Checking scene now...")

        ## Now turn back on all the model editors
        cleanup.turnOnModelEditors()
        if cmds.objExists('OCEAN_hrc'):
            ## Now set the scenes Ocean settings back to normal
            cmds.setAttr('OCEAN_hrc.visibility', 1)
            cmds.setAttr('oceanPreviewPlane_prv.visibility', 1)
            cmds.setAttr('animPreviewPlane_prv.visibility', 1)
            if cmds.objExists('OCEAN_hrc.oceanCalcOnOff'):
                cmds.setAttr('OCEAN_hrc.oceanCalcOnOff', 0)
            cmds.setAttr('OCEAN_hrc.oceanRes', 50)

        if cmds.objExists('BAKE_CAM_hrc'):
            try:
                cmds.delete('BAKE_CAM_hrc')
            except:
                pass

        ## Gin's add-on set model panel to show back to ALL after publish
        modelPanels = cmds.getPanel(type='modelPanel')
        if modelPanels:
            [
                cmds.modelEditor(mp, edit=True, allObjects=True)
                for mp in modelPanels
            ]

        cmds.select(clear=True)
        cmds.file(save=True, force=True)
        progress_cb(100, "Post complete...")
    def execute(self, **kwargs):
        """
        Main hook entry point
        :returns:       A list of any items that were found to be published.  
                        Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            type:   String
                                    This should match a scene_item_type defined in
                                    one of the outputs in the configuration and is 
                                    used to determine the outputs that should be 
                                    published for the item
                                    
                            name:   String
                                    Name to use for the item in the UI
                            
                            description:    String
                                            Description of the item to use in the UI
                                            
                            selected:       Bool
                                            Initial selected state of item in the UI.  
                                            Items are selected by default.
                                            
                            required:       Bool
                                            Required state of item in the UI.  If True then
                                            item will not be deselectable.  Items are not
                                            required by default.
                                            
                            other_params:   Dictionary
                                            Optional dictionary that will be passed to the
                                            pre-publish and publish hooks
                        }
        """

        items = []

        # get the main scene:
        scene_name = cmds.file(query=True, sn=True)
        if not scene_name:
            raise TankError("Please Save your file before Publishing")

        scene_path = os.path.abspath(scene_name)
        name = os.path.basename(scene_path)

        # create the primary item - this will match the primary output 'scene_item_type':
        items.append({"type": "work_file", "name": name})

        ## ANIM CURVES
        ## If shot step is animation only not layout
        if 'Anm' in scene_name.split('/'):
            ## ATOM
            items.append({"type": "anim_atom", "name": "Animation Curves"})

            ## CREASE XML
            items.append({"type": "crease_xml", "name": "Crease XML"})

        ## Delete any stack .type hrc children of those roots that already have .type
        caches_type = [
            each for each in cmds.ls(type='transform')
            if cmds.objExists('%s.type' % each)
            if 'anim' in str(cmds.getAttr('%s.type' % each))
            or 'static' in str(cmds.getAttr('%s.type' % each))
        ]
        for each in caches_type:
            descendents_hrc = cmds.listRelatives(each,
                                                 allDescendents=True,
                                                 type='transform',
                                                 fullPath=True)
            stack = [
                x for x in descendents_hrc if cmds.objExists('%s.type' % x)
                if 'anim' in str(cmds.getAttr('%s.type' % x))
                or 'static' in str(cmds.getAttr('%s.type' % x))
            ] if descendents_hrc else None
            [cmds.deleteAttr('%s.type' % hrc)
             for hrc in stack] if stack else None

        ## Make sure all definitions necessary are at FULL RES for alembic exporting!
        for each in cmds.ls(transforms=True):
            myType = ''
            if cmds.nodeType(each) == 'assemblyReference':
                ## FIRST Check to see what the active state is of the assembly reference node
                ## If it is still on GPU add this for gpu rendering
                ## Else look for what type of building it is for the alembic caching

                ## GPU CACHES
                if cmds.assembly(each, query=True, active=True) == 'gpuCache':
                    if 'Anm' in scene_name.split('/'):
                        cmds.assembly(each, edit=True, active='full')
                        if cmds.getAttr('%s.type' % cmds.listRelatives(
                                each, children=True,
                                fullPath=True)[0]) == 'animBLD':
                            items.append({"type": "anim_caches", "name": each})
                        else:
                            items.append({
                                "type": "static_caches",
                                "name": each
                            })
                else:
                    ## FULL GEO RIGGED OR STATIC
                    ## Check what type is its. Static or Animated
                    try:
                        for eachChild in cmds.listRelatives(each,
                                                            children=True):
                            try:
                                myType = cmds.getAttr('%s.type' % eachChild)
                            except ValueError:
                                print '%s is not set to a valid assemblyReference type to query for export...' % eachChild
                                pass
                            ## RIGGED BLD -- Now get the rigged buildings
                            if myType == 'animBLD':
                                ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({
                                    "type": "anim_caches",
                                    "name": each
                                })
                            ## STATIC BLD -- Now get the static buildings
                            elif myType == 'staticBLD':
                                ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({
                                    "type": "static_caches",
                                    "name": each
                                })
                            elif myType == 'staticLND':
                                ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({
                                    "type": "static_caches",
                                    "name": each
                                })
                            else:
                                pass
                    except:
                        pass
            else:
                try:
                    myType = cmds.getAttr('%s.type' % each)
                    ## FLUIDS -- Now get the fluid containers
                    ## caches = [CONST.FOAM_FLUID_SHAPENODE, CONST.WAKE_FLUID_SHAPENODE, CONST.INTERACTIVE_WAKE_FLUID_SHAPENODE, CONST.INTERACTIVE_FOAM_FLUID_SHAPENODE]
                    if 'oceanWakeFoamTexture' in myType or 'oceanWakeTexture' in myType:
                        items.append({
                            "type": "fluid_caches",
                            "name": '%sShape' % each
                        })
                    if myType == 'fx':
                        items.append({"type": "fx_caches", "name": each})
                    ## CAMERA -- Now get the camera
                    elif myType == 'shotCam' or myType == 'shotcam':
                        items.append({"type": "camera", "name": each})
                    ## REFERENCES -- Now process the references to get their types
                    elif myType == 'animCHAR' or myType == 'char':
                        items.append({"type": "anim_caches", "name": each})
                    elif myType == 'animPROP':
                        items.append({"type": "anim_caches", "name": each})
                    elif myType == 'animBLD' and '_ADef_' not in each:
                        items.append({"type": "anim_caches", "name": each})
                    elif myType == 'staticPROP':
                        items.append({"type": "static_caches", "name": each})
                    elif myType == 'staticCHAR':
                        items.append({"type": "static_caches", "name": each})
                    else:
                        pass
                except:
                    pass

        ## Check if the ocean exists..if it does do some work...
        if cmds.objExists('OCEAN_hrc'):
            ## Hide the preview planes
            cmds.setAttr('oceanPreviewPlane_prv.visibility', 1)
            cmds.setAttr('animPreviewPlane_prv.visibility', 0)
            ## Now make sure the wakes are calculating
            #cmds.setAttr('OCEAN_hrc.oceanCalcOnOff', 0)
            ## Now set the ocean preview plane res to something very low and fast to calc
            cmds.setAttr('OCEAN_hrc.oceanRes', 1)
        else:
            raise TankError(
                "MAYA OCEAN IS MISSING FROM YOUR SHOT!!! YOU SHOULD FIX THIS BEFORE PUBLISHING TO LIGHTING!!!!!!"
            )
            cleanup.turnOnModelEditors()

        ## Now delete any groups from the parenting tool
        for each in cmds.ls(transforms=True):
            if 'tmXML' in each:
                cmds.delete(each)

        ## NOW ADD THE TAGS FOR CREASES TO BE EXPORTED CORRECTLY
        ## NEED TO DO THIS LONG WAY IN CASE THE ATTR ALREADY EXISTS AND FAILS>.
        for each in cmds.ls(type='mesh', l=True):
            if not cmds.objExists('%s.SubDivisionMesh' % each):
                try:
                    cmds.addAttr('%s' % each, ln='SubDivisionMesh', at='bool')
                    cmds.setAttr("%s.SubDivisionMesh" % each, 1)
                except:
                    pass

        ## Check if cacheFiles exist and if yes, delete all of those.
        [cmds.delete(cache) for cache in cmds.ls(type='cacheFile')]
        [cmds.delete(cache) for cache in cmds.ls(type='cacheBlend')]

        ## remove unknown nodes from scene
        cleanup.cleanupUnknown()

        ## NOW MOVE ON TO PUBLISHING STEPS
        check_static_caches = [
            each['name'] for each in items if each['type'] == 'static_caches'
        ]
        if not check_static_caches:
            return items
        else:
            setName = 'static_caches_set'
            cmds.delete(setName) if cmds.objExists(
                setName) else None  ## Delete sets first
            cmds.sets(
                check_static_caches, name=setName
            ) if check_static_caches else None  ## Attach statics into newly created set

            cmds.confirmDialog(
                title='STATIC CACHES DETECTED!',
                message=
                'All the statics are stored inside the "%s" set inside the outliner.\n\n1. Use the BBB Tool "CleanOut Static ENV"\n2. Check if animated building is tagged wrongly as static\n\nIf 2, scene breakdown or ask rigger to republish!'
                % setName,
                button='OK!',
                backgroundColor=[1, 0.3, 0.3])
Пример #5
0
    def add_file_to_maya(self, file_path, shotgun_data):
        """
        Load file into Maya.
        
        This implementation creates a standard maya reference file for any item.
        """
        
        import pymel.core as pm
        import maya.cmds as cmds
        
        # get the slashes right
        file_path = file_path.replace(os.path.sep, "/")
        debug(app = None, method = 'add_file_to_maya', message = 'file_path: %s' % file_path, verbose = False)
        #file_path: I:/lsapipeline/episodes/eptst/eptst_sh2000/Anm/publish/maya/eptstsh2000.v002.mb
        
                
        file_version = int(file_path.split('.')[1].split('v')[-1])
        debug(app = None, method = 'add_file_to_maya', message = 'file_version: %s' % file_version, verbose = False)
        
        (path, ext) = os.path.splitext(file_path)
              
        if ext in [".ma", ".mb"]:
            ## Open the blocking file
            cmds.file(file_path, o = True, f = True)
            
            ## Cleanup unknown nodes to make sure we can save from mb back to ma
            for each in cmds.ls():
                if cmds.nodeType(each) == 'unknown':
                    cmds.delete(each)
                    
            ## Build the script node for the FX app.py to use as the current version number of the oceanPreset
            if not cmds.objExists('fxNugget'):
                cmds.scriptNode(n ='fxNugget')
                cmds.addAttr('fxNugget', ln = 'animVersion', at = 'long')
                cmds.setAttr('fxNugget.animVersion', file_version)
            ## Save the animation file as the next working file in the FX folder
            tk = sgtk.sgtk_from_path("T:/software/bubblebathbay")
            getEntity = shotgun_data['entity']
            shotName = getEntity['name']
            work_template = tk.templates['shot_work_area_maya']
            pathToWorking = r'%s' % tk.paths_from_template(work_template, {"Shot" : shotName, "Step":'FX'})[0]
            pathToWorking.replace('\\\\', '\\')
            debug(app = None, method = 'add_file_to_maya', message = 'pathToWorking: %s' % pathToWorking, verbose = False)
            ## Scan the folder and find the highest version number
            fileShotName = "".join(shotName.split('_'))
            padding = ''
            versionNumber = ''
            
            if os.path.exists(pathToWorking):
               getfiles = os.listdir(pathToWorking)

               ## Remove the stupid Keyboard folder if it exists.. thx autodesk.. not
               if 'Keyboard' in getfiles:
                   getfiles.remove('Keyboard')
               
               ## Process a clean list now.. trying to remove from the current list is giving me grief and I'm too fn tired to care...
               finalFiles = []
               for each in getfiles:
                   if each.split('.')[0] == fileShotName:
                       finalFiles.append(each)
                   else:
                       pass

               if finalFiles:
                   highestVersFile = max(finalFiles)
                   versionNumber  = int(highestVersFile.split('.')[1].split('v')[1]) + 1
               else:
                   versionNumber  = 1
            
               ## Now pad the version number
               if versionNumber < 10:
                   padding = '00'
               elif versionNumber < 100:
                   padding = '0'
               else:
                   padding = ''
               
            ## Rename the file
            #print 'FinalFilePath: %s\%s.v%s%s' % (pathToWorking, fileShotName, padding, versionNumber)  
            renameTo = '%s\%s.v%s%s' % (pathToWorking, fileShotName, padding, versionNumber)
            ## Now rename the file
            cmds.file(rename = renameTo)
            ## Now save this as a working version in the animation working folder
            cmds.file(save = True, force = True, type = 'mayaAscii')
            cmds.workspace(pathToWorking, openWorkspace = True)
            cleanup.turnOnModelEditors()
            
            
        else:
            self.parent.log_error("Unsupported file extension for %s! Nothing will be loaded." % file_path)
Пример #6
0
def _cacheWake(cachepath = '', oceanFluidTextures = [], fluids = []):
	"""
	Internal used by _publish_fx_caches_for_item
	"""

	cleanup.turnOffModelEditors()

	debug(None, method = 'fluidCaches._cacheWake', message = 'cachepath: %s' % cachepath, verbose = False)
	debug(None, method = 'fluidCaches._cacheWake', message = 'oceanFluidTextures: %s' % oceanFluidTextures, verbose = False)
	debug(None, method = 'fluidCaches._cacheWake', message = 'fluids: %s' % fluids, verbose = False)

	## Setup various vars
	output = r'%s' % cachepath
	debug(None, method = 'fluidCaches._cacheWake', message = 'output: %s' % output, verbose = False)

	## Start/end = 0 / Render settings = 1 / Time slider = 2
	time_range_mode        = 2

	start_frame            = cmds.playbackOptions(min = 1, q = 1)
	end_frame              = cmds.playbackOptions(max = 1, q = 1)

	debug(None, method = 'fluidCaches._cacheWake', message = 'start_frame: %s' % start_frame, verbose = False)
	debug(None, method = 'fluidCaches._cacheWake', message = 'end_frame: %s' % end_frame, verbose = False)

	### OneFilePerFrame / OneFile
	file_Distribution      = "OneFilePerFrame"

	refresh_during_caching = 1
	directory              = output.replace('\\', '/')
	# One file per object
	cache_per_geometry     = 1
	cache_name             = "" # We're not specifying any fluid name here as we enabled "One File Per Object" which automatically set the name on selected fluids
	cache_name_as_prefix   = 0

	## add / replace / merge / mergeDelete
	cache_method           = "replace"

	force_save             = 0
	evaluation             = 1
	evaluation_multiplier  = 1
	inherit_modification   = 0
	store_double_as_floats = 1
	caching_format         = "mcc"
	cache_density          = 1
	cache_velocity         = 1
	cache_temperature      = 1
	cache_fuel             = 1
	cache_color            = 1
	cache_texture_coord    = 1
	cache_falloff          = 1

	if not fluids:
		## Now select the fluid for caching as this is required by maya
		cmds.select(oceanFluidTextures, r = True)
		debug(None, method = 'fluidCaches._cacheWake', message = 'cur Selection is now: %s' % cmds.ls(sl= True), verbose = False)
		selection = _filter_fluids_on_selection()
	else:
		debug(None, method = 'fluidCaches._cacheWake', message = 'Fluids True: fluids: %s' % fluids, verbose = False)
		selection = fluids

	if selection:
		# check for existing cache file and delete then select fluids for new caching
		cmds.select(selection, replace = True)
		delete_caches_on_selection()
		debug(None, method = 'fluidCaches._cacheWake', message = 'cur Selection after cache deletion is now: %s' % cmds.ls(sl= True), verbose = False)

		print 'doCreateFluidCache 5 { "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s" } ;' % (time_range_mode, start_frame, end_frame, file_Distribution, refresh_during_caching, directory,cache_per_geometry,cache_name,cache_name_as_prefix,cache_method,force_save,evaluation,evaluation_multiplier,inherit_modification,store_double_as_floats,caching_format,cache_density,cache_velocity,cache_temperature,cache_fuel,cache_color,cache_texture_coord,cache_falloff)

		# Perform some clean-up (with fluids selected)
		debug(None, method = 'fluidCaches._cacheWake', message = 'Clearing inital state', verbose = False)
		mel.eval("ClearInitialState;")
		debug(None, method = 'fluidCaches._cacheWake', message = 'performDeleteFluidsIC', verbose = False)
		mel.eval("performDeleteFluidsIC 0;")

		debug(None, method = 'fluidCaches._cacheWake', message = 'Performing fluid caching now...', verbose = False)
		mel.eval('doCreateFluidCache 5 { "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s" } ;'
		%(  time_range_mode,
			start_frame,
			end_frame,
			file_Distribution,
			refresh_during_caching,
			directory,
			cache_per_geometry,
			cache_name,
			cache_name_as_prefix,
			cache_method,
			force_save,
			evaluation,
			evaluation_multiplier,
			inherit_modification,
			store_double_as_floats,
			caching_format,
			cache_density,
			cache_velocity,
			cache_temperature,
			cache_fuel,
			cache_color,
			cache_texture_coord,
			cache_falloff
		))

	else:
		debug(None, method = 'fluidCaches._cacheWake', message = 'FAILED: No fluids in selection!', verbose = False)
		mel.eval(r'print "Fluid(s) not in selection...\n";')

	cleanup.turnOnModelEditors()
Пример #7
0
    def _publish_nukeCamera_for_item(self, item, output, work_template, primary_publish_path, sg_task, comment, thumbnail_path, progress_cb):
        """
        Export an xml file for the specified item and publish it to Shotgun.
        """        
        debug(app = None, method = '_publish_nukeCamera_for_item', message = 'item["name"]: %s' % item["name"], verbose = False)
        
        tank_type = output["tank_type"]
        debug(app = None, method = '_publish_nukeCamera_for_item', message = 'tank_type: %s' % tank_type, verbose = False)
        
        publish_template = output["publish_template"]
        debug(app = None, method = '_publish_nukeCamera_for_item', message = 'publish_template: %s' % publish_template, verbose = False)

        # get the current scene path and extract fields from it
        # using the work template:
        scene_path = os.path.abspath(cmds.file(query=True, sn= True))
        fields = work_template.get_fields(scene_path)
        publish_version = fields["version"]
        
        ## create the publish path by applying the fields 
        ## with the publish template:            
        try:
            print '====================='
            print 'Exporting the nukeCamera'
            startFrame = cmds.playbackOptions(query =True, animationStartTime = True) 
            debug(app = None, method = '_publish_nukeCamera_for_item', message = 'startFrame: %s' % startFrame, verbose = False)

            endFrame = cmds.playbackOptions(query =True, animationEndTime= True)
            debug(app = None, method = '_publish_nukeCamera_for_item', message = 'endFrame: %s' % endFrame, verbose = False)
            
            cleanup.turnOffModelEditors()
            
            shotCams = []
            for eachCamera in cmds.listRelatives(item["name"], children = True):
                if cmds.getAttr('%s.type' % eachCamera) == 'shotCam':
                    debug(app = None, method = '_publish_nukeCamera_for_item', message = 'eachCamera: %s' % eachCamera, verbose = False)
                    shotCams.extend([eachCamera])
            debug(app = None, method = '_publish_nukeCamera_for_item', message = 'shotCams: %s' % shotCams, verbose = False)
            
            debug(app = None, method = '_publish_nukeCamera_for_item', message = 'len(shotCams): %s' % len(shotCams), verbose = False)
            group_name = ''
            if len(shotCams) == 1:
                # update fields with the group name:
                group_name = '%s_NUKECAM' % shotCams[0]
                fields["grp_name"] = group_name
                debug(app = None, method = '_publish_nukeCamera_for_item', message = 'grp_name: %s' % group_name, verbose = False)
                
                fields["cam_name"] = shotCams[0]
                debug(app = None, method = '_publish_nukeCamera_for_item', message = 'cam_name: %s' % shotCams[0], verbose = False)
    
                publish_path = publish_template.apply_fields(fields)                 
                debug(app = None, method = '_publish_nukeCamera_for_item', message = 'FINAL publish_path: %s' % publish_path, verbose = False)
                
                ## Make the directory now...
                if not os.path.isdir(os.path.dirname(publish_path)):
                    debug(app = None, method = '_publish_nukeCamera_for_item', message = 'Building dir: %s' % os.path.dirname(publish_path), verbose = False)
                    os.mkdir(os.path.dirname(publish_path))

                frame_start = cmds.playbackOptions(query = True, animationStartTime = True)
                frame_end = cmds.playbackOptions(query = True, animationEndTime = True)
    
                cmds.select(shotCams[0], r = True)
                #Switching to alembic output for camera.
                rootList = ''
                for eachRoot in cmds.ls(sl= True):
                    rootList = '-root %s %s' % (str(cmds.ls(eachRoot, l = True)[0]), rootList)
                
                debug(app = None, method = '_publish_nukeCamera_for_item', message = 'rootList: %s' % rootList, verbose = False)
                abc_export_cmd = "preRollStartFrame -15 -ro -attr SubDivisionMesh -attr smoothed -attr mcAssArchive -wholeFrameGeo -worldSpace -writeVisibility -uvWrite -fr %d %d %s -file %s" % (frame_start, frame_end, rootList, publish_path)
                cmds.AbcExport(verbose = False, j = abc_export_cmd)
                ##fm2n.FromMaya2Nuke(exportPath = os.path.dirname(publish_path), nukePath = 'C:\\"Program Files\"\Nuke7.0v6\\', nukeExec = 'Nuke7.0.exe', scriptName = '%s' % shotCams[0], startFrame = startFrame, endFrame = endFrame, camera = shotCams[0])
                #fm2n.FromMaya2Nuke(exportPath = os.path.dirname(publish_path), nukePath = '', nukeExec = '', scriptName = '%s' % shotCams[0], startFrame = startFrame, endFrame = endFrame)
                debug(app = None, method = '_publish_nukeCamera_for_item', message = 'Export Complete...', verbose = False)

                ## Now register publish with shotgun
                self._register_publish(publish_path,
                                      group_name,
                                      sg_task,
                                      publish_version, 
                                      tank_type,
                                      comment,
                                      thumbnail_path,
                                      [primary_publish_path])
                debug(app = None, method = '_publish_nukeCamera_for_item', message = '_register_publish complete for %s...' % shotCams[0], verbose = False)

                print 'Finished camera export for %s...' % shotCams[0]
                print '====================='
                cleanup.turnOnModelEditors()
            else:
                cmds.warning('Found more than one shotCam, using the first in the list only!!')
                pass
        except Exception, e:
            raise TankError("Failed to export NukeCamera")
Пример #8
0
    def execute(self, **kwargs):
        """
        Main hook entry point
        :returns:       A list of any items that were found to be published.  
                        Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            type:   String
                                    This should match a scene_item_type defined in
                                    one of the outputs in the configuration and is 
                                    used to determine the outputs that should be 
                                    published for the item
                                    
                            name:   String
                                    Name to use for the item in the UI
                            
                            description:    String
                                            Description of the item to use in the UI
                                            
                            selected:       Bool
                                            Initial selected state of item in the UI.  
                                            Items are selected by default.
                                            
                            required:       Bool
                                            Required state of item in the UI.  If True then
                                            item will not be deselectable.  Items are not
                                            required by default.
                                            
                            other_params:   Dictionary
                                            Optional dictionary that will be passed to the
                                            pre-publish and publish hooks
                        }
        """   
                
        items = []
        
        # get the main scene:
        scene_name = cmds.file(query=True, sn= True)
        if not scene_name:
            raise TankError("Please Save your file before Publishing")
      
        scene_path = os.path.abspath(scene_name)
        name = os.path.basename(scene_path)

        # create the primary item - this will match the primary output 'scene_item_type':            
        items.append({"type": "work_file", "name": name})
      
        ## Make sure all definitions are at FULL RES for alembic exporting.
        for each in cmds.ls(transforms = True):
            myType = ''
            if cmds.nodeType(each) == 'assemblyReference':         
                ## FIRST Check to see what the active state is of the assembly reference node
                ## If it is still on GPU add this for gpu rendering
                ## Else look for what type of building it is for the alembic caching
                
                ## GPU CACHES
                if cmds.assembly(each, query = True, active = True) == 'gpuCache':
                    items.append({"type":"gpu_caches", "name":each})
                else:
                    ## FULL GEO RIGGED OR STATIC
                    ## Check what type is its. Static or Animated
                    try:
                        for eachChild in cmds.listRelatives(each, children = True):
                            try:
                                myType = cmds.getAttr('%s.type' % eachChild)
                            except ValueError:
                                print '%s is not set to a valid assemblyReference type to query for export...' % eachChild
                                pass
                            ## RIGGED BLD -- Now get the rigged buildings
                            if myType == 'animBLD':
                                ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({"type":"anim_caches", "name":each})
                            ## STATIC BLD -- Now get the static buildings
                            elif myType == 'staticBLD':
                                 ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({"type":"static_caches", "name":each})
                            elif myType == 'staticLND':
                                 ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({"type":"static_caches", "name":each})
                            else:
                                pass
                    except:
                        pass
            else:
                try:
                    myType = cmds.getAttr('%s.type' % each)
                    ## FLUIDS -- Now get the fluid containers
#                     if myType == 'oceanWakeFoamTexture' or myType == 'oceanWakeTexture':
#                         items.append({"type":"fx_caches", "name":'%sShape' % each})
                    if myType == 'fx':
                        items.append({"type":"fx_caches", "name":each})
                    ## CAMERA -- Now get the camera
                    elif myType == 'shotCam' or myType == 'shotcam':
                        items.append({"type":"camera", "name":each})
                    ## REFERENCES -- Now process the references to get their types
                    elif myType == 'animCHAR' or myType == 'char':
                        items.append({"type":"anim_caches", "name":each})
                    elif myType == 'animPROP':
                        items.append({"type":"anim_caches", "name":each})
                    elif myType == 'staticPROP':
                        items.append({"type":"static_caches", "name":each})
                    elif myType == 'staticCHAR':
                        items.append({"type":"static_caches", "name":each})
                    else:
                        pass
                except:
                    pass

        ## NPARTICLES
        for eachNpart in cmds.ls(type = 'nParticle'):
            ## Now put the fx nodes to be cached into items, remember the type is set to match the shot_step.yml secondary output type!
            items.append({"type":"nparticle_caches", "name":eachNpart})
        
        ## Now turn off all the modelEditors to speed up exporting
        ## cleanup.turnOffModelEditors()

        ## Check if the ocean exists..if it does do some work...
        if cmds.objExists('OCEAN_hrc'):
            ## Hide the preview planes
            cmds.setAttr('oceanPreviewPlane_prv.visibility', 0)
            cmds.setAttr('animPreviewPlane_prv.visibility', 0)       
            ## Now make sure the wakes are calculating
            #cmds.setAttr('OCEAN_hrc.oceanCalcOnOff', 0)
            ## Now set the ocean preview plane res to something very low and fast to calc
            cmds.setAttr('OCEAN_hrc.oceanRes', 1)
        else:
            raise TankError("MAYA OCEAN IS MISSING FROM YOUR SHOT!!! YOU SHOULD FIX THIS BEFORE PUBLISHING TO LIGHTING!!!!!!")
            cleanup.turnOnModelEditors()

        ## Cleanup panels so nParticles don't keep crashing on export.
#         for each in cmds.lsUI(panels = True):
#             if 'outlinerPanel' in each or 'nodeEditorPanel' in each:
#                 cmds.deleteUI(each, panel = True)
        
        cleanup.cleanupUnknown()
        ## NOW MOVE ON TO PUBLISHING STEPS
        return items
    def execute(self, **kwargs):
        """
        Main hook entry point
        :returns:       A list of any items that were found to be published.  
                        Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            type:   String
                                    This should match a scene_item_type defined in
                                    one of the outputs in the configuration and is 
                                    used to determine the outputs that should be 
                                    published for the item
                                    
                            name:   String
                                    Name to use for the item in the UI
                            
                            description:    String
                                            Description of the item to use in the UI
                                            
                            selected:       Bool
                                            Initial selected state of item in the UI.  
                                            Items are selected by default.
                                            
                            required:       Bool
                                            Required state of item in the UI.  If True then
                                            item will not be deselectable.  Items are not
                                            required by default.
                                            
                            other_params:   Dictionary
                                            Optional dictionary that will be passed to the
                                            pre-publish and publish hooks
                        }
        """   
                
        items = []
        
        # get the main scene:
        scene_name = cmds.file(query=True, sn= True)
        if not scene_name:
            raise TankError("Please Save your file before Publishing")
      
        scene_path = os.path.abspath(scene_name)
        name = os.path.basename(scene_path)

        # create the primary item - this will match the primary output 'scene_item_type':            
        items.append({"type": "work_file", "name": name})
        
        ## Now find the fx stuff to export as secondary
        ## Make sure the groups are visible and good for calculating
        grps = ['Shot_FX_hrc', 'OCEAN_hrc', 'fluids_hrc', 'FLUID_EMITTERS_hrc']
        for eachGrp in grps:
            if cmds.objExists(eachGrp):
                cmds.setAttr('%s.visibility' % eachGrp, 1)
        
        ## FLUIDS
        for each in cmds.ls(transforms = True):
            myType = ''
            try:
                myType = cmds.getAttr('%s.type' % each)
            except:
                pass
            #debug(app = None, method = 'shotFX_ScanSceneHook', message = 'myType: %s' % myType, verbose = False)
            if myType:
                ## FLUIDS -- Now get the fluid containers
                if myType == 'oceanWakeFoamTexture' or myType == 'oceanWakeTexture':
                    debug(app = None, method = 'shotFX_ScanSceneHook', message = 'fx_caches: %s' % each, verbose = False)
                    items.append({"type":"fx_caches", "name":'%sShape' % each})
                    ## Otherwise grab the fluids group
                elif myType == 'fx':
                    if each != 'ocean_srf':
                        debug(app = None, method = 'shotFX_ScanSceneHook', message = 'fx_caches: %s' % each, verbose = False)
                        items.append({"type":"fx_caches", "name":'%s' % each})
                else:
                    pass

        ## NPARTICLES
        getNParticles = cmds.ls(type = 'nParticle')
        if getNParticles:
            for eachNpart in cmds.ls(type = 'nParticle'):
                ## Now put the fx nodes to be cached into items, remember the type is set to match the shot_step.yml secondary output type!
                debug(app = None, method = 'shotFX_ScanSceneHook', message = 'nparticle_caches: %s' % eachNpart, verbose = False)
                cmds.setAttr('%s.visibility' % eachNpart, 1)
                items.append({"type":"nparticle_caches", "name":eachNpart})

        ## FX RENDERS
        nParticleShapes = [nPart for nPart in cmds.ls(type = 'nParticle')]
        if nParticleShapes:
            items.append({"type":"fx_renders", "name":"Render Final"})

        ## Check if the ocean exists..if it does do some work...
        if cmds.objExists('OCEAN_hrc'):
            ## Hide the preview planes
            cmds.setAttr('oceanPreviewPlane_prv.visibility', 0)
            cmds.setAttr('animPreviewPlane_prv.visibility', 0)       
            ## Now set the ocean preview plane res to something very low and fast to calc
            cmds.setAttr('OCEAN_hrc.oceanRes', 1)
            ## Now make sure the wakes are calculating
            try:
                cmds.setAttr('OCEAN_hrc.oceanCalcOnOff', 1)
            except RuntimeError:
                pass
        else:
            raise TankError("MAYA OCEAN IS MISSING FROM YOUR SHOT!!! YOU SHOULD FIX THIS BEFORE PUBLISHING TO LIGHTING!!!!!!")
            cleanup.turnOnModelEditors()

        ## Check if cacheFiles exist and if yes, delete all of those.
        [cmds.delete(cache) for cache in cmds.ls(type = 'cacheFile')]
        [cmds.delete(cache) for cache in cmds.ls(type = 'cacheBlend')]

        ## Cleanup panels so nParticles don't keep crashing on export.
        for each in cmds.lsUI(panels = True):
            if 'outlinerPanel' in each or 'nodeEditorPanel' in each:
                cmds.deleteUI(each, panel = True)
        debug(app = None, method = 'shotFX_ScanSceneHook', message = 'FINISHED...', verbose = False)
        ## NOW MOVE ON TO PUBLISHING STEPS
        return items
    def execute(self, **kwargs):
        """
        Main hook entry point
        :returns:       A list of any items that were found to be published.  
                        Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            type:   String
                                    This should match a scene_item_type defined in
                                    one of the outputs in the configuration and is 
                                    used to determine the outputs that should be 
                                    published for the item
                                    
                            name:   String
                                    Name to use for the item in the UI
                            
                            description:    String
                                            Description of the item to use in the UI
                                            
                            selected:       Bool
                                            Initial selected state of item in the UI.  
                                            Items are selected by default.
                                            
                            required:       Bool
                                            Required state of item in the UI.  If True then
                                            item will not be deselectable.  Items are not
                                            required by default.
                                            
                            other_params:   Dictionary
                                            Optional dictionary that will be passed to the
                                            pre-publish and publish hooks
                        }
        """   
                
        items = []
        
        # get the main scene:
        scene_name = cmds.file(query=True, sn= True)
        if not scene_name:
            raise TankError("Please Save your file before Publishing")
      
        scene_path = os.path.abspath(scene_name)
        name = os.path.basename(scene_path)

        # create the primary item - this will match the primary output 'scene_item_type':            
        items.append({"type": "work_file", "name": name})

        ## ANIM CURVES
        ## If shot step is animation only not layout
        if 'Anm' in scene_name.split('/'):
            ## ATOM
            items.append({"type":"anim_atom", "name":"Animation Curves"})

            ## CREASE XML
            items.append({"type":"crease_xml", "name":"Crease XML"})

        ## Delete any stack .type hrc children of those roots that already have .type
        caches_type = [each for each in cmds.ls(type = 'transform') if cmds.objExists('%s.type' % each) if 'anim' in str(cmds.getAttr('%s.type' % each)) or 'static' in str(cmds.getAttr('%s.type' % each))]
        for each in caches_type:
            descendents_hrc = cmds.listRelatives(each, allDescendents = True, type = 'transform', fullPath = True)
            stack = [x for x in descendents_hrc if cmds.objExists('%s.type' % x) if 'anim' in str(cmds.getAttr('%s.type' % x)) or 'static' in str(cmds.getAttr('%s.type' % x))] if descendents_hrc else None
            [cmds.deleteAttr('%s.type' % hrc) for hrc in stack] if stack else None

        ## Make sure all definitions necessary are at FULL RES for alembic exporting!
        for each in cmds.ls(transforms = True):
            myType = ''
            if cmds.nodeType(each) == 'assemblyReference':         
                ## FIRST Check to see what the active state is of the assembly reference node
                ## If it is still on GPU add this for gpu rendering
                ## Else look for what type of building it is for the alembic caching

                ## GPU CACHES
                if cmds.assembly(each, query = True, active = True) == 'gpuCache':
                    if 'Anm' in scene_name.split('/'):
                        cmds.assembly(each, edit = True, active = 'full')
                        if cmds.getAttr( '%s.type' % cmds.listRelatives(each, children = True, fullPath = True)[0] ) == 'animBLD':
                            items.append( {"type":"anim_caches", "name":each} )
                        else:
                            items.append( {"type":"static_caches", "name":each} )
                else:
                    ## FULL GEO RIGGED OR STATIC
                    ## Check what type is its. Static or Animated
                    try:
                        for eachChild in cmds.listRelatives(each, children = True):
                            try:
                                myType = cmds.getAttr('%s.type' % eachChild)
                            except ValueError:
                                print '%s is not set to a valid assemblyReference type to query for export...' % eachChild
                                pass
                            ## RIGGED BLD -- Now get the rigged buildings
                            if myType == 'animBLD':
                                ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({"type":"anim_caches", "name":each})
                            ## STATIC BLD -- Now get the static buildings
                            elif myType == 'staticBLD':
                                 ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({"type":"static_caches", "name":each})
                            elif myType == 'staticLND':
                                 ## Now put the Assembly References into items, remember the type is set to match the shot_step.yml secondary output type!
                                items.append({"type":"static_caches", "name":each})
                            else:
                                pass
                    except:
                        pass
            else:
                try:
                    myType = cmds.getAttr('%s.type' % each)
                    ## FLUIDS -- Now get the fluid containers
                    ## caches = [CONST.FOAM_FLUID_SHAPENODE, CONST.WAKE_FLUID_SHAPENODE, CONST.INTERACTIVE_WAKE_FLUID_SHAPENODE, CONST.INTERACTIVE_FOAM_FLUID_SHAPENODE]
                    if 'oceanWakeFoamTexture' in myType or 'oceanWakeTexture' in myType:
                         items.append({"type":"fluid_caches", "name":'%sShape' % each})
                    if myType == 'fx':
                        items.append({"type":"fx_caches", "name":each})
                    ## CAMERA -- Now get the camera
                    elif myType == 'shotCam' or myType == 'shotcam':
                        items.append({"type":"camera", "name":each})
                    ## REFERENCES -- Now process the references to get their types
                    elif myType == 'animCHAR' or myType == 'char':
                        items.append({"type":"anim_caches", "name":each})
                    elif myType == 'animPROP':
                        items.append({"type":"anim_caches", "name":each})
                    elif myType == 'animBLD' and '_ADef_' not in each:
                        items.append({"type":"anim_caches", "name":each})
                    elif myType == 'staticPROP':
                        items.append({"type":"static_caches", "name":each})
                    elif myType == 'staticCHAR':
                        items.append({"type":"static_caches", "name":each})
                    else:
                        pass
                except:
                    pass


        ## Check if the ocean exists..if it does do some work...
        if cmds.objExists('OCEAN_hrc'):
            ## Hide the preview planes
            cmds.setAttr('oceanPreviewPlane_prv.visibility', 1)
            cmds.setAttr('animPreviewPlane_prv.visibility', 0)
            ## Now make sure the wakes are calculating
            #cmds.setAttr('OCEAN_hrc.oceanCalcOnOff', 0)
            ## Now set the ocean preview plane res to something very low and fast to calc
            cmds.setAttr('OCEAN_hrc.oceanRes', 1)
        else:
            raise TankError("MAYA OCEAN IS MISSING FROM YOUR SHOT!!! YOU SHOULD FIX THIS BEFORE PUBLISHING TO LIGHTING!!!!!!")
            cleanup.turnOnModelEditors()
        
        ## Now delete any groups from the parenting tool
        for each in cmds.ls(transforms = True):
            if 'tmXML' in each:
                cmds.delete(each)
        
        ## NOW ADD THE TAGS FOR CREASES TO BE EXPORTED CORRECTLY
        ## NEED TO DO THIS LONG WAY IN CASE THE ATTR ALREADY EXISTS AND FAILS>.
        for each in cmds.ls(type = 'mesh', l = True):
            if not cmds.objExists('%s.SubDivisionMesh' % each):
                try:
                    cmds.addAttr('%s' % each, ln = 'SubDivisionMesh', at = 'bool')
                    cmds.setAttr("%s.SubDivisionMesh" % each, 1)
                except:
                    pass

        ## Check if cacheFiles exist and if yes, delete all of those.
        [cmds.delete(cache) for cache in cmds.ls(type = 'cacheFile')]
        [cmds.delete(cache) for cache in cmds.ls(type = 'cacheBlend')]
        
        ## remove unknown nodes from scene
        cleanup.cleanupUnknown()

        ## NOW MOVE ON TO PUBLISHING STEPS
        check_static_caches = [each['name'] for each in items if each['type'] == 'static_caches']
        if not check_static_caches:
            return items
        else:
            setName = 'static_caches_set'
            cmds.delete(setName) if cmds.objExists(setName) else None ## Delete sets first
            cmds.sets(check_static_caches, name = setName) if check_static_caches else None ## Attach statics into newly created set

            cmds.confirmDialog(title = 'STATIC CACHES DETECTED!', message = 'All the statics are stored inside the "%s" set inside the outliner.\n\n1. Use the BBB Tool "CleanOut Static ENV"\n2. Check if animated building is tagged wrongly as static\n\nIf 2, scene breakdown or ask rigger to republish!' % setName, button = 'OK!', backgroundColor = [1, 0.3, 0.3])
Пример #11
0
    def execute(self, **kwargs):
        """
        Main hook entry point
        :returns:       A list of any items that were found to be published.  
                        Each item in the list should be a dictionary containing 
                        the following keys:
                        {
                            type:   String
                                    This should match a scene_item_type defined in
                                    one of the outputs in the configuration and is 
                                    used to determine the outputs that should be 
                                    published for the item
                                    
                            name:   String
                                    Name to use for the item in the UI
                            
                            description:    String
                                            Description of the item to use in the UI
                                            
                            selected:       Bool
                                            Initial selected state of item in the UI.  
                                            Items are selected by default.
                                            
                            required:       Bool
                                            Required state of item in the UI.  If True then
                                            item will not be deselectable.  Items are not
                                            required by default.
                                            
                            other_params:   Dictionary
                                            Optional dictionary that will be passed to the
                                            pre-publish and publish hooks
                        }
        """

        items = []

        # get the main scene:
        scene_name = cmds.file(query=True, sn=True)
        if not scene_name:
            raise TankError("Please Save your file before Publishing")

        scene_path = os.path.abspath(scene_name)
        name = os.path.basename(scene_path)

        # create the primary item - this will match the primary output 'scene_item_type':
        items.append({"type": "work_file", "name": name})

        ## Now find the fx stuff to export as secondary
        ## Make sure the groups are visible and good for calculating
        grps = ['Shot_FX_hrc', 'OCEAN_hrc', 'fluids_hrc', 'FLUID_EMITTERS_hrc']
        for eachGrp in grps:
            if cmds.objExists(eachGrp):
                cmds.setAttr('%s.visibility' % eachGrp, 1)

        ## FLUIDS
        for each in cmds.ls(transforms=True):
            myType = ''
            try:
                myType = cmds.getAttr('%s.type' % each)
            except:
                pass
            #debug(app = None, method = 'shotFX_ScanSceneHook', message = 'myType: %s' % myType, verbose = False)
            if myType:
                ## FLUIDS -- Now get the fluid containers
                if myType == 'oceanWakeFoamTexture' or myType == 'oceanWakeTexture':
                    debug(app=None,
                          method='shotFX_ScanSceneHook',
                          message='fx_caches: %s' % each,
                          verbose=False)
                    items.append({
                        "type": "fx_caches",
                        "name": '%sShape' % each
                    })
                    ## Otherwise grab the fluids group
                elif myType == 'fx':
                    if each != 'ocean_srf':
                        debug(app=None,
                              method='shotFX_ScanSceneHook',
                              message='fx_caches: %s' % each,
                              verbose=False)
                        items.append({
                            "type": "fx_caches",
                            "name": '%s' % each
                        })
                else:
                    pass

        ## NPARTICLES
        getNParticles = cmds.ls(type='nParticle')
        if getNParticles:
            for eachNpart in cmds.ls(type='nParticle'):
                ## Now put the fx nodes to be cached into items, remember the type is set to match the shot_step.yml secondary output type!
                debug(app=None,
                      method='shotFX_ScanSceneHook',
                      message='nparticle_caches: %s' % eachNpart,
                      verbose=False)
                cmds.setAttr('%s.visibility' % eachNpart, 1)
                items.append({"type": "nparticle_caches", "name": eachNpart})

        ## FX RENDERS
        nParticleShapes = [nPart for nPart in cmds.ls(type='nParticle')]
        if nParticleShapes:
            items.append({"type": "fx_renders", "name": "Render Final"})

        ## Check if the ocean exists..if it does do some work...
        if cmds.objExists('OCEAN_hrc'):
            ## Hide the preview planes
            cmds.setAttr('oceanPreviewPlane_prv.visibility', 0)
            cmds.setAttr('animPreviewPlane_prv.visibility', 0)
            ## Now set the ocean preview plane res to something very low and fast to calc
            cmds.setAttr('OCEAN_hrc.oceanRes', 1)
            ## Now make sure the wakes are calculating
            try:
                cmds.setAttr('OCEAN_hrc.oceanCalcOnOff', 1)
            except RuntimeError:
                pass
        else:
            raise TankError(
                "MAYA OCEAN IS MISSING FROM YOUR SHOT!!! YOU SHOULD FIX THIS BEFORE PUBLISHING TO LIGHTING!!!!!!"
            )
            cleanup.turnOnModelEditors()

        ## Check if cacheFiles exist and if yes, delete all of those.
        [cmds.delete(cache) for cache in cmds.ls(type='cacheFile')]
        [cmds.delete(cache) for cache in cmds.ls(type='cacheBlend')]

        ## Cleanup panels so nParticles don't keep crashing on export.
        for each in cmds.lsUI(panels=True):
            if 'outlinerPanel' in each or 'nodeEditorPanel' in each:
                cmds.deleteUI(each, panel=True)
        debug(app=None,
              method='shotFX_ScanSceneHook',
              message='FINISHED...',
              verbose=False)
        ## NOW MOVE ON TO PUBLISHING STEPS
        return items
Пример #12
0
def buildFXOcean(editor,
                 ocean_preset_template='',
                 ocean_foam_template='',
                 ocean_wake_template='',
                 hiTide=False,
                 xRes=20,
                 zRes=20,
                 inprogressBar='',
                 pathToAnimCaches=''):
    """
    Build of the ocean for the FX Step. Check the application here for the ocean_preset_template. This should be coming from a
    published animation ocean preset from the DISPOcean in the animation scene.
    Even though we have `opened' the animation scene we are rebuilding the ocean during this step, so the rebuild should match
    the animation publish via the preset.

    @param editor:                     The current viewport editor so we can use this to stick the ocean in the right location in the shot
    @param ocean_preset_template:     The publish template leading us to the ocean preset mel file from animation
    @param ocean_foam_template:     The template to find the preset for the ocean foam fluid container
    @param ocean_wake_template:      The template to find the preset for the ocean wake fluid container
    @type editor:                     String
    @type ocean_preset_template:     A valid shotgun tempate
    @type ocean_foam_template:         A valid shotgun tempate
    @type ocean_wake_template:         A valid shotgun tempate
    """
    [cmds.currentTime(1) for x in range(2)]  ## Twice to ensure start position
    debug(None,
          method='buildFXOcean',
          message='_buildBaseOceanSetup...',
          verbose=False)
    inprogressBar.updateProgress(percent=15,
                                 doingWhat='_buildBaseOceanSetup...')

    ## Look for the master interactive boat
    masterBoatHook = [
        eachHook for eachHook in cmds.ls(type='transform')
        if cmds.objExists('%s.oceanHeightHook' % eachHook)
        and cmds.objExists('%s.interactiveMasterBoat' % eachHook)
    ]
    interactiveBoatName = ''

    ## IF there is a masterboat attr in the scene we have an interactive boat setup coming through from animation and need to handle this correctly.
    if masterBoatHook:
        ## First lets find the name of the boat
        interactiveBoatName = masterBoatHook[0].split(':')[0]
        debug(None,
              method='buildFXOcean',
              message='interactiveBoatName: %s' % interactiveBoatName,
              verbose=False)

        ## Now delete the original animation fx setup so we don't have to calc these again as we're going to use the caches from animation now.
        fluidLib.cleanupMasterBoatFluids(interactiveBoatName)

        ## Now connect the published animation caches from the highest version folder found in the animation publish fx folder.
        if pathToAnimCaches:
            if os.path.isdir(pathToAnimCaches):
                ## Find and create a list of just the xml files
                getCaches = [
                    eachFile for eachFile in os.listdir(pathToAnimCaches)
                    if eachFile.endswith('.xml')
                ]

                for eachCache in getCaches:
                    pathToXML = r'%s/%s' % (pathToAnimCaches, eachCache)
                    ## Now do the attach using the lib to handle fluid caches
                    try:
                        fluidCaches.rebuild_cache_from_xml(pathToXML)
                    except:
                        cmds.warning('Failed to connect cache: %s' % pathToXML)
                        pass

    ############################################################################################################################
    ## BUILD
    _buildBaseOceanSetup(editor,
                         ocean_preset_template=ocean_preset_template,
                         ocean_foam_template=ocean_foam_template,
                         ocean_wake_template=ocean_wake_template,
                         hiTide=hiTide)

    ## BUILD FUILD CONTAINERS NOW
    ## Now build the fluid texture containers for the wakes and foams...
    debug(None,
          method='buildFXOcean',
          message='_build_OceanWakeAndFoam_FluidContainers...',
          verbose=False)
    inprogressBar.updateProgress(
        percent=25, doingWhat='_build_OceanWakeAndFoam_FluidContainers...')
    _build_OceanWakeAndFoam_FluidContainers(editor, ocean_foam_template,
                                            ocean_wake_template)

    # ## NOW LINK THE HEIGHT LOCS
    # ## Now process all the height locators again to be connected to the ocean via their expressions
    # debug(None, method = 'buildFXOcean', message = 'connectAllWithOceanHeightAttr...', verbose = False)
    # inprogressBar.updateProgress(percent = 35, doingWhat = 'connectAllWithOceanHeightAttr...')
    # ## Since if interactive, oceanLoc is tagged and baked during ANM publish, we don't want to rebuild and preserve those to have exactly same character movement.
    # if not cmds.objExists(CONST.INTERACTIVE_FOAM_FLUID_SHAPENODE) and not cmds.objExists(CONST.INTERACTIVE_WAKE_FLUID_SHAPENODE):
    #     connOH.connectAllWithOceanHeightAttr()## Note this now factors in the new metatags for the bakeLocs and masterInteractiveBoat!

    ### NOW DO THE FLUID EMITTER BUILDS
    ### This is the new approach for the wakes and foam!
    inprogressBar.updateProgress(percent=40,
                                 doingWhat='_setupBaseBoatFXSystems...')
    if interactiveBoatName:
        bfx._setupBaseBoatFXSystems(xRes=xRes,
                                    zRes=zRes,
                                    inprogressBar=inprogressBar,
                                    fxInteractive=True,
                                    interactiveBoatName=interactiveBoatName)
    else:
        bfx._setupBaseBoatFXSystems(xRes=xRes,
                                    zRes=zRes,
                                    inprogressBar=inprogressBar)

    ## Now connect all the new emitters
    inprogressBar.updateProgress(percent=50,
                                 doingWhat='Linking all emitters...')
    fluidLib._linkWakeEmitters()

    ## APPLY PRESETS TO OCEAN TEXTURE PLANES
    ## Now apply the presets to the ocean Textures
    inprogressBar.updateProgress(percent=60,
                                 doingWhat='_setFXOceanTexurePresets...')
    fluidLib._setFXOceanTexurePresets()

    ## DELETE CACHES
    fluidLib._deleteOceanTextureCaches()

    ############################################################################################################################
    #
    #
    ############################################################################################################################
    #########################
    ## FX CLEANUP
    ############################################################################################################################
    debug(None,
          method='buildFXOcean',
          message='_cleanupOcean...',
          verbose=False)
    inprogressBar.updateProgress(percent=65, doingWhat='_cleanupOcean...')
    _cleanupOcean()

    ## Now turn on all the modelEditors to speed up mayas playback
    cleanup.turnOnModelEditors()

    ## Now remove the f*****g expression that maya refuses to evaluate because maya is a dumb shit c**t..
    cmds.delete('oceanRes_exp')

    ## Now set the defaults
    cmds.setAttr('oceanPreviewPlane_heightF.resolution', 100)
    cmds.setAttr("OCEAN_hrc.oceanRes", 50)
    cmds.setAttr("OCEAN_hrc.oceanCalcOnOff", 1)
    cmds.setAttr("%s.shadedDisplay" % CONST.FOAM_FLUID_SHAPENODE, 3)
    cmds.setAttr("%s.shadedDisplay" % CONST.WAKE_FLUID_SHAPENODE, 2)
    cmds.setAttr("oceanPreviewPlane_prv.visibility", 0)

    ## NOTE BUG WORK AROUND
    ## The new fluid textures get offset for some obscure reason just resetting these transforms now..
    cmds.setAttr(
        "%s.translateX" % CONST.FOAM_FLUID_SHAPENODE.split('Shape')[0], 0)
    cmds.setAttr(
        "%s.translateX" % CONST.WAKE_FLUID_SHAPENODE.split('Shape')[0], 0)
    cmds.setAttr(
        "%s.translateZ" % CONST.FOAM_FLUID_SHAPENODE.split('Shape')[0], 0)
    cmds.setAttr(
        "%s.translateZ" % CONST.WAKE_FLUID_SHAPENODE.split('Shape')[0], 0)

    try:
        cmds.parent('nPARTICLE_EMITTERS_hrc', 'Shot_FX_hrc')
    except:
        pass
    try:
        cmds.parent('FLUID_EMITTERS_hrc', 'Shot_FX_hrc')
    except:
        pass
    try:
        cmds.parent('nPARTICLE_PARTICLES_hrc', 'Shot_FX_hrc')
    except:
        pass

    ### Setup the nucleus preset now
    pathToPreset = CONST.FXNUCLEUSPRESETPATH

    fx_nucleus = [
        each for each in cmds.ls(type='nucleus')
        if 'fx_nucleus' in each and cmds.nodeType(each) == 'nucleus'
    ]
    if fx_nucleus:
        for each in fx_nucleus:
            mel.eval('applyPresetToNode "%s" "" "" "%s" 1;' %
                     (each, pathToPreset))
        debug(None,
              method='buildFXOcean',
              message='Mel preset applied to %s: %s' % (each, pathToPreset),
              verbose=False)

    ## Connect some of the core attributes from fluid wake/foam/nucleus to global_dynamicAnim group
    if fx_nucleus:
        connect_fluidTexture3D_to_animatable(
            foamContainer=CONST.FOAM_FLUID_SHAPENODE,
            wakeContainer=CONST.WAKE_FLUID_SHAPENODE,
            nucleus=fx_nucleus[0],
            animatable='global_dynamicAnim')
    else:
        connect_fluidTexture3D_to_animatable(
            foamContainer=CONST.FOAM_FLUID_SHAPENODE,
            wakeContainer=CONST.WAKE_FLUID_SHAPENODE,
            nucleus='',
            animatable='global_dynamicAnim')

    inprogressBar.updateProgress(percent=70, doingWhat='Cleanup Completed')