Tobi Posted December 1, 2015 Report Share Posted December 1, 2015 Hey everybody, is there a way to change the behavior of the default actions like opening Nuke from ftrack?My goal is to extend those actions so I can read out the current shot information and automatically open the latest version of the Nuke script on the server directly from ftrack. At the moment artists have to open the Nuke scripts manually after running the Ftrack Action.My current assumption is that the only way to do that is to write an own action but I'm not sure how to enable the ftrack features in Nuke then so I hope there's a easier way to achieve this.. Thank you in advance,Tobi Link to comment Share on other sites More sharing options...
tokejepsen Posted December 2, 2015 Report Share Posted December 2, 2015 Hey Tobi, Assuming you are using Ftrack Connect, you can set the environment variable "FTRACK_EVENT_PLUGIN_PATH" to point to your custom action. This is the action we are using here;# :coding: utf-8# :copyright: Copyright (c) 2015 ftrackimport getpassimport sysimport pprintimport loggingimport reimport osimport argparseimport tracebackimport subprocessimport timeimport threadingtools_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))ftrack_connect_path = os.path.join(tools_path, 'ftrack', 'ftrack-connect_package', 'windows', 'current')if __name__ == '__main__': sys.path.append(os.path.join(tools_path, 'ftrack', 'ftrack-api')) sys.path.append(os.path.join(ftrack_connect_path, 'common.zip')) os.environ['PYTHONPATH'] = os.path.join(ftrack_connect_path, 'common.zip') os.environ['PYTHONPATH'] += os.pathsep + os.path.join(tools_path, 'pyblish', 'pyblish') os.environ['PYTHONPATH'] += os.pathsep + os.path.join(tools_path, 'pyblish', 'pyblish-hiero') os.environ['PYTHONPATH'] += os.pathsep + os.path.join(tools_path, 'pyblish', 'pyblish-integration') os.environ['PYTHONPATH'] += os.pathsep + os.path.join(tools_path, 'pyblish', 'pyblish-nuke') os.environ['PYTHONPATH'] += os.pathsep + os.path.join(tools_path, 'pyblish', 'pyblish-qml') os.environ['PYTHONPATH'] += os.pathsep + os.path.join(tools_path, 'pyblish', 'pyblish-rpc') os.environ['PYTHONPATH'] += os.pathsep + os.path.join(tools_path, 'pyblish', 'python-qt5') os.environ['NUKE_PATH'] = os.pathsep + os.path.join(tools_path, 'pyblish', 'pyblish-nuke', 'pyblish_nuke', 'nuke_path') os.environ['NUKE_PATH'] += os.pathsep + os.path.join(tools_path, 'ftrack', 'ftrack-tools') os.environ['HIERO_PLUGIN_PATH'] = os.path.join(tools_path, 'pyblish', 'pyblish-hiero', 'pyblish_hiero', 'hiero_plugin_path') os.environ['PYBLISHPLUGINPATH'] = '' sys.path.append(r'C:\Users\toke.jepsen\Desktop\library')import ftrackimport ftrack_connect.applicationclass ApplicationThread(threading.Thread): def __init__(self, launcher, applicationIdentifier, context, task): self.stdout = None self.stderr = None threading.Thread.__init__(self) self.launcher = launcher self.applicationIdentifier = applicationIdentifier self.context = context self.task = task self.logger = logging.getLogger() def run(self): self.logger.info('start time log') timelog = ftrack.createTimelog(1, contextId=self.task.getId()) start_time = time.time() self.launcher.launch(self.applicationIdentifier, self.context) duration = time.time() - start_time timelog.set('duration', value=duration) self.logger.info('end time log')class LaunchApplicationAction(object): '''Discover and launch nuke.''' identifier = 'ftrack-connect-launch-nuke' def __init__(self, application_store, launcher): '''Initialise action with *applicationStore* and *launcher*. *applicationStore* should be an instance of :class:`ftrack_connect.application.ApplicationStore`. *launcher* should be an instance of :class:`ftrack_connect.application.ApplicationLauncher`. ''' super(LaunchApplicationAction, self).__init__() self.logger = logging.getLogger() self.application_store = application_store self.launcher = launcher # newer version pop-up def version_get(self, string, prefix, suffix = None): """Extract version information from filenames. Code from Foundry's nukescripts.version_get()""" if string is None: raise ValueError, "Empty version string - no match" regex = "[/_.]"+prefix+"\d+" matches = re.findall(regex, string, re.IGNORECASE) if not len(matches): msg = "No \"_"+prefix+"#\" found in \""+string+"\"" raise ValueError, msg return (matches[-1:][0][1], re.search("\d+", matches[-1:][0]).group()) def is_valid_selection(self, selection): '''Return true if the selection is valid.''' if ( len(selection) != 1 or selection[0]['entityType'] != 'task' ): return False entity = selection[0] task = ftrack.Task(entity['entityId']) if task.getObjectType() != 'Task': return False return True def register(self): '''Register discover actions on logged in user.''' ftrack.EVENT_HUB.subscribe( 'topic=ftrack.action.discover and source.user.username={0}'.format( getpass.getuser() ), self.discover ) ftrack.EVENT_HUB.subscribe( 'topic=ftrack.action.launch and source.user.username={0} ' 'and data.actionIdentifier={1}'.format( getpass.getuser(), self.identifier ), self.launch ) def discover(self, event): '''Return discovered applications.''' if not self.is_valid_selection( event['data'].get('selection', []) ): return items = [] applications = self.application_store.applications applications = sorted( applications, key=lambda application: application['label'] ) for application in applications: application_identifier = application['identifier'] label = application['label'] items.append({ 'actionIdentifier': self.identifier, 'label': label, 'icon': application.get('icon', 'default'), 'applicationIdentifier': application_identifier }) return { 'items': items } def launch(self, event): '''Handle *event*. event['data'] should contain: *applicationIdentifier* to identify which application to start. ''' # Prevent further processing by other listeners. event.stop() if not self.is_valid_selection( event['data'].get('selection', []) ): return applicationIdentifier = event['data']['applicationIdentifier'] context = event['data'].copy() context['source'] = event['source'] task = ftrack.Task(event['data']['selection'][0]['entityId']) type_name = task.getType().getName() # getting path to file path = '' try: asset = None component = None # search for asset with same name as task for a in task.getAssets(assetTypes=['scene']): if a.getName().lower() == task.getName().lower(): asset = a component_name = 'nuke_work' if 'hiero' in applicationIdentifier: component_name = 'hiero_work' for v in reversed(asset.getVersions()): if not v.get('ispublished'): v.publish() for c in v.getComponents(): if c.getName() == component_name: component = c if component: break current_path = component.getFilesystemPath() self.logger.info('Component path: %s' % current_path) # get current file data current_dir = os.path.dirname(current_path) prefix = os.path.basename(current_path).split('v')[0] extension = os.path.splitext(current_path)[1] max_version = int(self.version_get(current_path, 'v')[1]) current_version = max_version # comparing against files in the same directory new_version = False new_basename = None for f in os.listdir(current_dir): basename = os.path.basename(f) f_prefix = os.path.basename(basename).split('v')[0] if f_prefix == prefix and basename.endswith(extension): if int(self.version_get(f, 'v')[1]) > max_version: new_version = True max_version = int(self.version_get(f, 'v')[1]) new_basename = f if new_version: path = os.path.join(current_dir, new_basename) else: path = current_path except: msg = "Couldn't find any file to launch:" msg += " %s" % traceback.format_exc() self.logger.info(msg) if not path: try: parent = task.getParent() asset = parent.getAsset(parent.getName(), 'scene') version = asset.getVersions()[-1] path = version.getComponent(name='nuke').getFilesystemPath() except: self.logger.info(traceback.format_exc()) self.logger.info('Found path: %s' % path) # adding application and task environment environment = {} tools_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) pyblish_path = os.path.join(tools_path, 'pyblish') data = os.environ['PYBLISHPLUGINPATH'].split(os.pathsep) app_path = os.path.join(pyblish_path, 'pyblish-bumpybox', 'pyblish_bumpybox', 'plugins', 'nuke') if 'hiero' in applicationIdentifier: app_path = os.path.join(pyblish_path, 'pyblish-bumpybox', 'pyblish_bumpybox', 'plugins', 'hiero') data.append(app_path) data.append(os.path.join(app_path, task.getType().getName().lower())) environment['PYBLISHPLUGINPATH'] = data context['environment'] = environment # launching the app applicationStore = ApplicationStore() applicationStore._modifyApplications(path) path = os.path.join(ftrack_connect_path, 'resource', 'ftrack_connect_nuke') launcher = ApplicationLauncher(applicationStore, plugin_path=os.environ.get( 'FTRACK_CONNECT_NUKE_PLUGINS_PATH', path)) myclass = ApplicationThread(launcher, applicationIdentifier, context, task) myclass.start() ftrack.EVENT_HUB.publishReply(event, data={ 'success': True, 'message': 'Launched %s!' % applicationIdentifier } )class ApplicationStore(ftrack_connect.application.ApplicationStore): def _modifyApplications(self, path=''): self.applications = self._discoverApplications(path=path) def _discoverApplications(self, path=''): '''Return a list of applications that can be launched from this host. An application should be of the form: dict( 'identifier': 'name_version', 'label': 'Name version', 'path': 'Absolute path to the file', 'version': 'Version of the application', 'icon': 'URL or name of predefined icon' ) ''' applications = [] launchArguments = [] nukexLaunchArguments = ['--nukex'] hieroLaunchArguments = ['--hiero'] if path: launchArguments = [path] nukexLaunchArguments.append(path) hieroLaunchArguments.append(path) if sys.platform == 'win32': prefix = ['C:\\', 'Program Files.*'] # Specify custom expression for Nuke to ensure the complete version # number (e.g. 9.0v3) is picked up. nuke_version_expression = re.compile( r'(?P<version>[\d.]+[vabc]+[\dvabc.]*)' ) applications.extend(self._searchFilesystem( expression=prefix + ['Nuke.*', 'Nuke\d.+.exe'], versionExpression=nuke_version_expression, label='Nuke {version}', applicationIdentifier='nuke_{version}', icon='nuke', launchArguments=launchArguments )) # Add NukeX as a separate application applications.extend(self._searchFilesystem( expression=prefix + ['Nuke.*', 'Nuke\d.+.exe'], versionExpression=nuke_version_expression, label='NukeX {version}', applicationIdentifier='nukex_{version}', icon='nukex', launchArguments=nukexLaunchArguments )) # Add Hiero as a separate application applications.extend(self._searchFilesystem( expression=prefix + ['Nuke.*', 'Nuke\d.+.exe'], versionExpression=nuke_version_expression, label='Hiero {version}', applicationIdentifier='hiero_{version}', icon='hiero', launchArguments=hieroLaunchArguments )) self.logger.debug( 'Discovered applications:\n{0}'.format( pprint.pformat(applications) ) ) return applicationsclass ApplicationLauncher(ftrack_connect.application.ApplicationLauncher): '''Custom launcher to modify environment before launch.''' def __init__(self, application_store, plugin_path): '''.''' super(ApplicationLauncher, self).__init__(application_store) self.plugin_path = plugin_path def launch(self, applicationIdentifier, context=None): '''Launch application matching *applicationIdentifier*. *context* should provide information that can guide how to launch the application. Return a dictionary of information containing: success - A boolean value indicating whether application launched successfully or not. message - Any additional information (such as a failure message). ''' # Look up application. applicationIdentifierPattern = applicationIdentifier if applicationIdentifierPattern == 'hieroplayer': applicationIdentifierPattern += '*' application = self.applicationStore.getApplication( applicationIdentifierPattern ) if application is None: return { 'success': False, 'message': ( '{0} application not found.' .format(applicationIdentifier) ) } # Construct command and environment. command = self._getApplicationLaunchCommand(application, context) environment = self._getApplicationEnvironment(application, context) # Environment must contain only strings. self._conformEnvironment(environment) success = True message = '{0} application started.'.format(application['label']) try: options = dict( env=environment, close_fds=True ) # Ensure that current working directory is set to the root of the # application being launched to avoid issues with applications # locating shared libraries etc. applicationRootPath = os.path.dirname(application['path']) options['cwd'] = applicationRootPath # Ensure subprocess is detached so closing connect will not also # close launched applications. if sys.platform == 'win32': options['creationflags'] = subprocess.CREATE_NEW_CONSOLE else: options['preexec_fn'] = os.setsid self.logger.debug( 'Launching {0} with options {1}'.format(command, options) ) process = subprocess.Popen(command, **options) # waiting on the process to terminate to inform time tracking process.wait() except (OSError, TypeError): self.logger.exception( '{0} application could not be started with command "{1}".' .format(applicationIdentifier, command) ) success = False message = '{0} application could not be started.'.format( application['label'] ) else: self.logger.debug( '{0} application started. (pid={1})'.format( applicationIdentifier, process.pid ) ) return { 'success': success, 'message': message } def _getApplicationEnvironment( self, application, context=None ): '''Override to modify environment before launch.''' # Make sure to call super to retrieve original environment # which contains the selection and ftrack API. environment = super( ApplicationLauncher, self )._getApplicationEnvironment(application, context) applicationIdentifier = application['identifier'] for k in context['environment']: path = '' for p in context['environment'][k]: path += os.pathsep + p environment[k] = path[1:] entity = context['selection'][0] task = ftrack.Task(entity['entityId']) taskParent = task.getParent() try: environment['FS'] = str(int(taskParent.getFrameStart())) except Exception: environment['FS'] = '1' try: environment['FE'] = str(int(taskParent.getFrameEnd())) except Exception: environment['FE'] = '1' environment['FTRACK_TASKID'] = task.getId() environment['FTRACK_SHOTID'] = task.get('parent_id') nuke_plugin_path = os.path.abspath( os.path.join( self.plugin_path, 'nuke_path' ) ) environment = ftrack_connect.application.appendPath( nuke_plugin_path, 'NUKE_PATH', environment ) nuke_plugin_path = os.path.abspath( os.path.join( self.plugin_path, 'ftrack_connect_nuke' ) ) environment = ftrack_connect.application.appendPath( self.plugin_path, 'FOUNDRY_ASSET_PLUGIN_PATH', environment ) # Set the FTRACK_EVENT_PLUGIN_PATH to include the notification callback # hooks. environment = ftrack_connect.application.appendPath( os.path.join( self.plugin_path, 'crew_hook' ), 'FTRACK_EVENT_PLUGIN_PATH', environment ) environment = ftrack_connect.application.appendPath( os.path.join( self.plugin_path, '..', 'ftrack_python_api' ), 'FTRACK_PYTHON_API_PLUGIN_PATH', environment ) environment['NUKE_USE_FNASSETAPI'] = '1' return environmentdef register(registry, **kw): '''Register hooks.''' # Create store containing applications. application_store = ApplicationStore() path = os.path.join(ftrack_connect_path, 'resource', 'ftrack_connect_nuke') launcher = ApplicationLauncher(application_store, plugin_path=os.environ.get( 'FTRACK_CONNECT_NUKE_PLUGINS_PATH', path)) # Create action and register to respond to discover and launch actions. action = LaunchApplicationAction(application_store, launcher) action.register()def main(arguments=None): '''Set up logging and register action.''' if arguments is None: arguments = [] parser = argparse.ArgumentParser() # Allow setting of logging level from arguments. loggingLevels = {} for level in ( logging.NOTSET, logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL ): loggingLevels[logging.getLevelName(level).lower()] = level parser.add_argument( '-v', '--verbosity', help='Set the logging output verbosity.', choices=loggingLevels.keys(), default='info' ) namespace = parser.parse_args(arguments) '''Register action and listen for events.''' logging.basicConfig(level=loggingLevels[namespace.verbosity]) log = logging.getLogger() ftrack.setup() # Create store containing applications. application_store = ApplicationStore() path = os.path.join(ftrack_connect_path, 'resource', 'ftrack_connect_nuke') launcher = ApplicationLauncher(application_store, plugin_path=os.environ.get( 'FTRACK_CONNECT_NUKE_PLUGINS_PATH', path)) # Create action and register to respond to discover and launch actions. action = LaunchApplicationAction(application_store, launcher) action.register() ftrack.EVENT_HUB.wait()if __name__ == '__main__': raise SystemExit(main(sys.argv[1:]))There is a lot of other stuff going on here, like threading off the launch to record time, but the main area you should focus on is overriding the ApplicationStore class so you can add the path to the nuke file. Then before launching we make a new instance of the ApplicationStore where we inject the path;# launching the appapplicationStore = ApplicationStore()applicationStore._modifyApplications(path)path = os.path.join(ftrack_connect_path, 'resource', 'ftrack_connect_nuke')launcher = ApplicationLauncher(applicationStore, plugin_path=os.environ.get( 'FTRACK_CONNECT_NUKE_PLUGINS_PATH', path))launcher.launch(applicationIdentifier, context)This is definitely not straight forward, and you have to dig around the default actions in Ftrack Connect to make it work. I have a request for extending the default actions with Carl, but don't know how far they are with that. You can find some more documentation here; http://ftrack-connect.rtd.ftrack.com/en/latest/developing/index.html Link to comment Share on other sites More sharing options...
Tobi Posted December 2, 2015 Author Report Share Posted December 2, 2015 Thank you very much for that code which definately helps a lot. My other idea was to code everything on the Nuke side, like checking if the ftrack environment variable FTRACK_TASKID is set when Nuke is starting and run some ftrack api scripts from inside Nuke. But that also seemed like a dirty workaround, so I guess your solution is the better way to go. Maybe some developer can give us an update on how far development is with extending the default actions. Link to comment Share on other sites More sharing options...
Martin Pengelly-Phillips Posted December 4, 2015 Report Share Posted December 4, 2015 Hello! As you can see from Toke's example and the documentation we have the framework in place, but it is not super easy to use or well documented at present. What we are working on currently is improving the documentation to make it more obvious on how to manage plugins / actions both per user and centrally using either Connect or your own event server. Then we plan to tackle making it much easier to alter the default plugins, notably managing them on custom paths without having to extract them from the connect package and also simplify some of the code so there is less you have to override to make small changes. Martin Link to comment Share on other sites More sharing options...
Milan Kolar Posted December 21, 2015 Report Share Posted December 21, 2015 For a quick start it would help if any plugins on custom paths, that have the same name as the default ones, would override the defaults. Right now I have to delete the ones I'm tweaking from the connect's resource/hook, so it doesn't appear twice in the actions. I don't want to be tweaking them there directly purely because I want to keep any custom code separate. Simplifying this workflow is absolutely essential at this point. Having to extract all of the application launchers from connect and tweaking each of them just to add a few environment variable across the board is a bit of an overkill. Link to comment Share on other sites More sharing options...
Mattias Lagergren Posted December 22, 2015 Report Share Posted December 22, 2015 Hi Milan, For a quick start it would help if any plugins on custom paths, that have the same name as the default ones, would override the defaults. Right now I have to delete the ones I'm tweaking from the connect's resource/hook, so it doesn't appear twice in the actions. I don't want to be tweaking them there directly purely because I want to keep any custom code separate. I wonder if you could achieve this with the following modifications to your overrides: def register(self): '''Override register to filter discover actions on logged in user.''' ftrack.EVENT_HUB.subscribe( 'topic=ftrack.action.discover and source.user.username={0}'.format( getpass.getuser() ), self.discover, priority=10 # Set priority to run before the builtin hook. ) ftrack.EVENT_HUB.subscribe( 'topic=ftrack.action.launch and source.user.username={0} ' 'and data.actionIdentifier={1}'.format( getpass.getuser(), self.identifier ), self.launch, priority=10 # Set priority to run before the builtin hook. ) def discover(self, event): '''Return discovered applications.''' # Stop event propagation. event.stop() ... Would this work for you? Link to comment Share on other sites More sharing options...
Milan Kolar Posted February 5, 2016 Report Share Posted February 5, 2016 On 22/12/2015 at 8:50 AM, Mattias Lagergren said: Would this work for you? It looked promising, but I'm afraid it doesn't work. The customised action runs first, however, stopping the event propagation kills off all the other actions, so you end up with only this one in the list. Not stopping the event, of course doubles up the action in the UI and runs it twice. Link to comment Share on other sites More sharing options...
Mattias Lagergren Posted February 8, 2016 Report Share Posted February 8, 2016 On 2/5/2016 at 0:55 AM, Milan Kolar said: It looked promising, but I'm afraid it doesn't work. The customised action runs first, however, stopping the event propagation kills off all the other actions, so you end up with only this one in the list. Not stopping the event, of course doubles up the action in the UI and runs it twice. Ah, right.. As you know we're working on the simplifying plugins in Connect (http://forum.ftrack.com/index.php?/topic/461-simplify-plugins-in-connect/) feature. Having the ability to listen to a pre-launch event and modify the environment variables willI that solve the issue for you? Link to comment Share on other sites More sharing options...
Milan Kolar Posted February 8, 2016 Report Share Posted February 8, 2016 Hey Mattias. Yes that should absolutely do the trick. Link to comment Share on other sites More sharing options...
Mike Posted July 7, 2016 Report Share Posted July 7, 2016 I'm interested in this as well. I'd like to append locations to the MAYA_SCRIPT_PATH to search for some custom userSetup files (rather than edit the local Maya.env file on everyone's computer). I've successfully modified the environment variables on my Houdini hook following some tips in the docs, but I'd like the ability to modify and override the built-in applications hooks as well. Is there support for this yet? Thanks. Link to comment Share on other sites More sharing options...
Mattias Lagergren Posted July 8, 2016 Report Share Posted July 8, 2016 Quote I'm interested in this as well. I'd like to append locations to the MAYA_SCRIPT_PATH to search for some custom userSetup files (rather than edit the local Maya.env file on everyone's computer). I've successfully modified the environment variables on my Houdini hook following some tips in the docs, but I'd like the ability to modify and override the built-in applications hooks as well. Is there support for this yet? Thanks. Yes, have a look at this link: http://ftrack-connect.rtd.ftrack.com/en/latest/developing/tutorial/adding_a_location.html#developing-tutorial-adding-a-location-modifying-application-launch Using the hook you can modify the environment of the launching application. Link to comment Share on other sites More sharing options...
Mike Posted July 8, 2016 Report Share Posted July 8, 2016 6 hours ago, Mattias Lagergren said: Yes, have a look at this link: http://ftrack-connect.rtd.ftrack.com/en/latest/developing/tutorial/adding_a_location.html#developing-tutorial-adding-a-location-modifying-application-launch Using the hook you can modify the environment of the launching application. I figured out that in order to add multiple paths, I needed to format a string like so: maya_connect_scripts = os.path.join(os.getenv('FTRACK_CONNECT_MAYA_PATH'), 'scripts') my_scripts_path = os.getenv('MY_MAYA_SCRIPT_PATH') other_scripts_path = os.getenv('OTHER_MAYA_SCRIPT_PATH') script_paths = '{0};{1};{2}'.format(maya_connect_scripts, my_scripts_path, other_scripts_path) environment = ftrack_connect.application.appendPath( script_paths, 'PYTHONPATH', environment ) So that works, but I have 2 launchers for Maya now. I tried out your suggestion to modify the register and discover methods, but like Milan said, it didn't work and it prevents any hooks from displaying in connect. The log doesn't show any error. Am I doing it correctly? def register(self): '''Override register to filter discover actions on logged in user.''' ftrack.EVENT_HUB.subscribe( 'topic=ftrack.action.discover and source.user.username={0}'.format( getpass.getuser() ), self.discover, priority=10 # Set priority to run before the builtin hook. ) ftrack.EVENT_HUB.subscribe( 'topic=ftrack.action.launch and source.user.username={0} ' 'and data.actionIdentifier={1}'.format( getpass.getuser(), self.identifier ), self.launch, priority=10 # Set priority to run before the builtin hook. ) def discover(self, event): '''return discovered applications.''' # stop event propagation. event.stop() Link to comment Share on other sites More sharing options...
Mattias Lagergren Posted July 11, 2016 Report Share Posted July 11, 2016 What does your module level register function look like? Link to comment Share on other sites More sharing options...
Mike Posted July 11, 2016 Report Share Posted July 11, 2016 def register(session, **kw): '''Register hooks.''' # Validate that registry is the correct ftrack.Registry. If not, # assume that register is being called with another purpose or from a # new or incompatible API and return without doing anything. if not isinstance(session, ftrack_api.Session): # Exit to avoid registering this plugin again. return session.event_hub.subscribe( 'topic=ftrack.connect.application.launch', modify_application_launch ) # Create store containing applications. applicationStore = ApplicationStore() # Create a launcher with the store containing applications. launcher = ApplicationLauncher( applicationStore ) # Create action and register to respond to discover and launch actions. action = MayaAction(applicationStore, launcher, session) action.register() if __name__ == '__main__': session = ftrack_api.Session() register(session) # Wait for events. session.event_hub.wait() Link to comment Share on other sites More sharing options...
Mattias Lagergren Posted July 12, 2016 Report Share Posted July 12, 2016 Quote I've successfully modified the environment variables on my Houdini hook following some tips in the docs, but I'd like the ability to modify and override the built-in applications hooks as well. Is there support for this yet? Thanks. Just to go back to this original question. What aspects of the built-in hooks do you need to modify? If you're only after modifying environment variables and launch arguments, etc. you can use the : http://ftrack-connect.rtd.ftrack.com/en/latest/developing/tutorial/adding_a_location.html#developing-tutorial-adding-a-location-modifying-application-launch method without overriding or adding any extra discover/launch hooks. If you want to replace the Maya launcher entirely the best option is to separate the hooks out of Connect and remove the Maya hook. And then set the FTRACK_EVENT_PLUGIN_PATH to point to this new directory without the built-in Maya hook. Link to comment Share on other sites More sharing options...
Mike Posted July 12, 2016 Report Share Posted July 12, 2016 I'd just like to be able to override the built-in hooks without directly interacting with connect's built-in plugin path files. From my limited experience, I'm guessing that if I were to edit the built-in files directly, if myself or another person were to update connect in the future, I could potentially lose my customizations if we were careless. Ideally, I'd like to be able to set up a location like, BUILTINS_OVERRIDE_PATH where any hooks that I place inside in there will override aspects of the built-in hooks. Your solution to create a separate directory that I can point the FTRACK_EVENT_PLUGIN_PATH to will work, but I'll have to manually update those built-ins in the future, assuming future versions of connect change those built-in plugins. I just like to remove the chance of human error when possible :D. Thanks for the solution, I'll give it a shot. Link to comment Share on other sites More sharing options...
Mattias Lagergren Posted July 13, 2016 Report Share Posted July 13, 2016 8 hours ago, Mike said: Your solution to create a separate directory that I can point the FTRACK_EVENT_PLUGIN_PATH to will work, but I'll have to manually update those built-ins in the future, assuming future versions of connect change those built-in plugins. I just like to remove the chance of human error when possible :D. Thanks for the solution, I'll give it a shot. Yeah, this makes sense and something to think about. We recently did changes in order to make it easier to extend Connect with plugins, and also modify the launch arguments and environment - but it sounds like even more control over the built-ins are necessary. Moving forward we're planning to separate out the built-in integrations into separate installations. The idea being that you could more easily pick-and-choose from a list of available integration/plugins and then have them automatically downloaded and installed (all from an easy UI). This would also allow us to release new integration plugins without having to release a new version of Connect package. Again, thanks for the feedback. The most viable option right now is probably separating them to a new directory and using FTRACK_EVENT_PLUGIN_PATH. Downside being that you will need to manually copy changes from new versions of Connect. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.