def open_save_as_dialog(self): """ Open the tk-multi-workfiles2 app's file save dialog. Fallback to using VRED save dialog UI if workfiles is not available. """ open_dialog_func = None kwargs = {} workfiles = self.apps.get("tk-multi-workfiles2", None) if workfiles: if hasattr(workfiles, "show_file_save_dlg"): open_dialog_func = workfiles.show_file_save_dlg kwargs["use_modal_dialog"] = True if open_dialog_func: open_dialog_func(**kwargs) else: # Fallback to using VRED's save dialog. Pass flag to not confirm overwrite, the # save dialog will already ask this. if vrFileIOService: filename = vrFileIOService.getFileName() else: filename = vrFileIO.getFileIOFilePath() path = vrFileDialog.getSaveFileName( caption="Save As", filename=filename, filter=["VRED Project Binary (*.vpb)"], confirmOverwrite=False, ) self.save_current_file(path, False)
def publish(self, settings, item): """ Executes the publish logic for the given item and settings. :param settings: Dictionary of Settings. The keys are strings, matching the keys returned in the settings property. The values are `Setting` instances. :param item: Item to process """ publisher = self.parent engine = publisher.engine # get the path in a normalized state. no trailing separator, separators # are appropriate for current os, no double separators, etc. session_path = vrFileIO.getFileIOFilePath() path = sgtk.util.ShotgunPath.normalize(session_path) # ensure the session is saved in its current state engine.save_current_file(path) # get the path to a versioned copy of the file. version_path = publisher.util.get_version_path(path, "v001") # save to the new version path engine.save_current_file(version_path) self.logger.info("A version number has been added to the VRED file...") self.logger.info(" VRED file path: %s" % (version_path,))
def set_render_path(self, file_path=None): """ Prepare render path when the file is selected or saved. :param file_path: the name of the file. """ render_template_settings = self.get_setting("render_template") render_template = self.get_template_by_name(render_template_settings) if not render_template: self.logger.debug( "{engine_name} failed to set render path: template not found from 'render_template' engine settings: {settings}" .format(engine_name=self.name, settings=render_template_settings)) return if file_path is None: file_path = vrFileIO.getFileIOFilePath() if file_path is None: self.logger.debug( "{engine_name} failed to set render path: current scene path not found" .format(engine_name=self.name)) return work_template = self.sgtk.template_from_path(file_path) if not work_template: self.logger.debug( "{engine_name} failed to set render path: template matching scene path '{path}' not found" .format(engine_name=self.name, path=file_path)) return # Update the template fields with the context ones to be sure to have all the required fields. template_fields = work_template.get_fields(file_path) context_fields = self.context.as_template_fields(render_template) for k in context_fields: if k not in template_fields.keys(): template_fields[k] = context_fields[k] missing_keys = render_template.missing_keys(template_fields, skip_defaults=True) if missing_keys: self.logger.debug( "{engine_name} failed to set render path: render template missing keys {keys}" .format(engine_name=self.name, keys=missing_keys)) return render_path = render_template.apply_fields(template_fields) # Be sure the render folder is created. render_folder = os.path.dirname(render_path) if not os.path.isdir(render_folder): os.makedirs(render_folder) self.logger.debug( "{engine_name} calling VRED to set render path '{path}'".format( engine_name=self.name, path=render_path)) vrRenderSettings.setRenderFilename(render_path)
def accept(self, settings, item): """ Method called by the publisher to determine if an item is of any interest to this plugin. Only items matching the filters defined via the item_filters property will be presented to this method. A publish task will be generated for each item accepted here. Returns a dictionary with the following booleans: - accepted: Indicates if the plugin is interested in this value at all. Required. - enabled: If True, the plugin will be enabled in the UI, otherwise it will be disabled. Optional, True by default. - visible: If True, the plugin will be visible in the UI, otherwise it will be hidden. Optional, True by default. - checked: If True, the plugin will be checked in the UI, otherwise it will be unchecked. Optional, True by default. :param settings: Dictionary of Settings. The keys are strings, matching the keys returned in the settings property. The values are `Setting` instances. :param item: Item to process :returns: dictionary with boolean keys accepted, required and enabled """ path = vrFileIO.getFileIOFilePath() if path: version_number = self._get_version_number(path, item) if version_number is not None: self.logger.info( "VRED '%s' plugin rejected the current session..." % (self.name,) ) self.logger.info(" There is already a version number in the file...") self.logger.info(" VRED file path: %s" % (path,)) return {"accepted": False} else: # the session has not been saved before (no path determined). # provide a save button. the session will need to be saved before # validation will succeed. self.logger.warn( "The VRED session has not been saved.", extra=sgtk.platform.current_engine().open_save_as_dialog, ) self.logger.info( "VRED '%s' plugin accepted the current session." % (self.name,), extra=_get_version_docs_action(), ) # accept the plugin, but don't force the user to add a version number # (leave it unchecked) return {"accepted": True, "checked": False}
def collect_current_vred_session(self, settings, parent_item): """ Creates an item that represents the current VRED session. :param dict settings: Configured settings for this collector :param parent_item: Root item instance :returns: Item of type vred.session """ publisher = self.parent # get the path to the current file path = vrFileIO.getFileIOFilePath() # determine the display name for the item if path: file_info = publisher.util.get_file_path_components(path) display_name = file_info["filename"] else: display_name = "Current VRED Session" # create the session item for the publish hierarchy session_item = parent_item.create_item("vred.session", "VRED Session", display_name) # get the icon path to display for this item icon_path = os.path.join(self.disk_location, os.pardir, "icons", "vred.png") session_item.set_icon_from_path(icon_path) # if a work template is defined, add it to the item properties so # that it can be used by attached publish plugins work_template_setting = settings.get("Work Template") if work_template_setting: work_template = publisher.engine.get_template_by_name( work_template_setting.value) # store the template on the item for use by publish plugins. we # can't evaluate the fields here because there's no guarantee the # current session path won't change once the item has been created. # the attached publish plugins will need to resolve the fields at # execution time. session_item.properties["work_template"] = work_template self.logger.debug("Work template defined for VRED collection.") self.logger.info("Collected current VRED scene") # Need to store the path on properties to backward compatibility # TODO: clean LMV plugin to remove the path query session_item.properties["path"] = path return session_item
def save(): """ Saves the current scene to a .vpb in the current opened file folder (saving on top of the scene if it can). If the scene hasn't been saved yet, it will prompt a save dialog. """ currentScenePath = vrFileIO.getFileIOFilePath() if len(currentScenePath) == 0: currentScenePath = vrFileDialog.getSaveFileName("Save As", "", ["vpb(*.vpb)"], True) # Force VPB extension currentScenePath = os.path.splitext(currentScenePath)[0] + '.vpb' return currentScenePath, vrFileIO.save(currentScenePath)
def accept(self, settings, item): """ Method called by the publisher to determine if an item is of any interest to this plugin. Only items matching the filters defined via the item_filters property will be presented to this method. A publish task will be generated for each item accepted here. Returns a dictionary with the following booleans: - accepted: Indicates if the plugin is interested in this value at all. Required. - enabled: If True, the plugin will be enabled in the UI, otherwise it will be disabled. Optional, True by default. - visible: If True, the plugin will be visible in the UI, otherwise it will be hidden. Optional, True by default. - checked: If True, the plugin will be checked in the UI, otherwise it will be unchecked. Optional, True by default. :param settings: Dictionary of Settings. The keys are strings, matching the keys returned in the settings property. The values are `Setting` instances. :param item: Item to process :returns: dictionary with boolean keys accepted, required and enabled """ # if a publish template is configured, disable context change. This # is a temporary measure until the publisher handles context switching # natively. if settings.get("Publish Template").value: item.context_change_allowed = False path = vrFileIO.getFileIOFilePath() if not path: # the session has not been saved before (no path determined). # provide a save button. the session will need to be saved before # validation will succeed. self.logger.warn( "The VRED session has not been saved.", extra=sgtk.platform.current_engine().open_save_as_dialog, ) self.logger.info( "VRED '%s' plugin accepted the current VRED session." % (self.name, )) return {"accepted": True, "checked": True}
def validate(self, settings, item): """ Validates the given item to check that it is ok to publish. Returns a boolean to indicate validity. :param settings: Dictionary of Settings. The keys are strings, matching the keys returned in the settings property. The values are `Setting` instances. :param item: Item to process :returns: True if item is valid, False otherwise. """ publisher = self.parent path = vrFileIO.getFileIOFilePath() if not path: # the session still requires saving. provide a save button. # validation fails error_msg = "The VRED session has not been saved." self.logger.error( error_msg, extra=sgtk.platform.current_engine().open_save_as_dialog ) raise Exception(error_msg) # NOTE: If the plugin is attached to an item, that means no version # number could be found in the path. If that's the case, the work file # template won't be much use here as it likely has a version number # field defined within it. Simply use the path info hook to inject a # version number into the current file path # get the path to a versioned copy of the file. version_path = publisher.util.get_version_path(path, "v001") if os.path.exists(version_path): error_msg = ( "A file already exists with a version number. Please " "choose another name." ) self.logger.error( error_msg, extra=sgtk.platform.current_engine().open_save_as_dialog ) raise Exception(error_msg) return True
def publish(self, settings, item): """ Executes the publish logic for the given item and settings. :param settings: Dictionary of Settings. The keys are strings, matching the keys returned in the settings property. The values are `Setting` instances. :param item: Item to process """ # get the path in a normalized state. no trailing separator, separators # are appropriate for current os, no double separators, etc. session_path = vrFileIO.getFileIOFilePath() path = sgtk.util.ShotgunPath.normalize(session_path) # ensure the session is saved self.save_file(path) # update the item with the saved session path item.properties["path"] = path # let the base class register the publish super(VREDSessionPublishPlugin, self).publish(settings, item)
def get_current_file(self): """Get the current file.""" return vrFileIO.getFileIOFilePath()
def validate(self, settings, item): """ Validates the given item to check that it is ok to publish. Returns a boolean to indicate validity. :param settings: Dictionary of Settings. The keys are strings, matching the keys returned in the settings property. The values are `Setting` instances. :param item: Item to process :returns: True if item is valid, False otherwise. """ path = vrFileIO.getFileIOFilePath() # ---- ensure the session has been saved if not path: # the session still requires saving. provide a save button. # validation fails. error_msg = "The VRED session has not been saved." self.logger.error( error_msg, extra=sgtk.platform.current_engine().open_save_as_dialog) raise Exception(error_msg) # ---- check the session against any attached work template # get the path in a normalized state. no trailing separator, # separators are appropriate for current os, no double separators, # etc. path = sgtk.util.ShotgunPath.normalize(path) # if the session item has a known work template, see if the path # matches. if not, warn the user and provide a way to save the file to # a different path work_template = item.properties.get("work_template") if work_template: if not work_template.validate(path): error_msg = "The current session does not match the configured work file template." self.logger.warning( error_msg, extra={ "action_button": { "label": "Save File", "tooltip": "Save the current VRED session to a " "different file name", "callback": sgtk.platform.current_engine().open_save_as_dialog, } }, ) raise Exception(error_msg) else: self.logger.debug( "Work template configured and matches session file.") else: self.logger.debug("No work template configured.") # ---- see if the version can be bumped post-publish # check to see if the next version of the work file already exists on # disk. if so, warn the user and provide the ability to jump to save # to that version now (next_version_path, version) = self._get_next_version_info(path, item) if next_version_path and os.path.exists(next_version_path): # determine the next available version_number. just keep asking for # the next one until we get one that doesn't exist. while os.path.exists(next_version_path): (next_version_path, version) = self._get_next_version_info( next_version_path, item) error_msg = "The next version of this file already exists on disk." self.logger.error( error_msg, extra={ "action_button": { "label": "Save to v%s" % (version, ), "tooltip": "Save to the next available version number, " "v%s" % (version, ), "callback": lambda: self.save_file(next_version_path), } }, ) raise Exception(error_msg) # ---- populate the necessary properties and call base class validation # populate the publish template on the item if found publish_template_setting = settings.get("Publish Template") publish_template = self.parent.engine.get_template_by_name( publish_template_setting.value) if publish_template: item.properties["publish_template"] = publish_template # set the session path on the item for use by the base plugin validation # step. NOTE: this path could change prior to the publish phase. item.properties["path"] = path # store the item publish version item.properties["publish_version"] = self.get_publish_version( settings, item) # run the base class validation return super(VREDSessionPublishPlugin, self).validate(settings, item)
# Loop over all variant sets in the Snapshot group. The variable snapshot no contains the name of the variant set. for snapshot in variantSetGroups["Snapshots"]: # Conveniently our variant sets are called exactly like the corresponding viewpoint # Therefore we can jump the correct viewpoint using the same name as the variant set name vrCamera.jumpViewPoint(snapshot) # Create a file name filePath = os.path.join(directory, snapshot + ".png") # start rendering vrRenderSettings.setRenderFilename(filePath) vrRenderSettings.startRenderToFile(False) else: print( "[VR][Workshop] There is no variant set group called 'Snapshots'.") # Open a directory dialog and select a directory where to store the renderings directory = vrFileDialog.getExistingDirectory("Select Snapshot Directory", vrFileIO.getFileIOFilePath()) def renderSnapshotsToDirectory(): # If the user cancels the dialog or there is no such directory the variable 'directory' will be empty # In this case we tell the user and leave the script if directory: renderSnapshots(directory) subprocess.Popen(r'explorer /select,"' + directory + '"') else: print("[VR][Workshop] No valid directory selected.")
def execute(self, operation, file_path=None, context=None, parent_action=None, file_version=None, read_only=None, **kwargs): """ Main hook entry point :param operation: String Scene operation to perform :param file_path: String File path to use if the operation requires it (e.g. open) :param context: Context The context the file operation is being performed in. :param parent_action: This is the action that this scene operation is being executed for. :param file_version: The version/revision of the file to be opened. :param read_only: Specifies if the file should be opened read-only or not :returns: Depends on operation: 'current_path' - Return the current scene file path as a String all others - True for success, else False """ self.logger.debug( "{self} executing operation '{op}' on file '{path}'".format( self=self, op=operation, path=file_path)) success = True if operation == "current_path": current_path = vrFileIO.getFileIOFilePath() return "" if current_path is None else current_path if operation == "open": vrFileIO.load( [file_path], vrScenegraph.getRootNode(), newFile=True, showImportOptions=False, ) self.parent.engine.set_render_path(file_path) elif operation == "save": if file_path is None: file_path = vrFileIO.getFileIOFilePath() self.parent.engine.save_current_file(file_path) elif operation == "save_as": self.parent.engine.save_current_file(file_path) elif operation == "reset": success = self.parent.engine.save_or_discard_changes( override_cursor=QtCore.Qt.ArrowCursor) if success: vrController.newScene() return success