All Activity

This stream auto-updates     

  1. Yesterday
  2. Lorenzo Angeli

    Action on Shot

    hi @Rory here a simple example to translate the entities using the action handler as base class: from ftrack_action_handler.action import BaseAction import ftrack_api class TestAction(BaseAction): label = 'Test Action' identifier = 'com.ftrack.test.action' description = 'Simple test action' def validate_selection(self, entities, event): if not entities: return False results = self._translate_event( self.session, event ) if not results : return False for (entity_type, entity_id) in results[0]: resolved_entity= self.session.get(entity_type, entity_id) print resolved_entity, resolved_entity.entity_type return True def discover(self, session, entities, event): return self.validate_selection(entities, event) def launch(self, session, entities, event): return { 'success': True, 'message': u'Done.' } def register(api_object, **kw): '''Register hook with provided *api_object*.''' if not isinstance(api_object, ftrack_api.session.Session): return action = TestAction(api_object) action.register() hope it helps. L.
  3. Hallo Marc, There is relatively little in the Connect log as this issue is strictly related to the Adobe plugin installation. A workaround has been to have an older version of the Adobe software installed so that the plugin will be detected. Adobe should allow you to download a previous version easily. Please let us know how we can be of more help via your existing Support ticket. Cheers from Madrid, Dan
  4. Last week
  5. Hi @Aaron Powell using the discovery to populate the available applications does not work as it will look into the application store to decide which one to start. The best option at the time seems to be to override the _getApplicationLauncher as by this example to inject the launchArguments you are after. long story short this is what you can simply do: class ApplicationLauncher(ftrack_connect.application.ApplicationLauncher): '''Custom launcher to modify environment before launch.''' def _getApplicationLaunchCommand(self, application, context=None): command = super(ApplicationLauncher, self)._getApplicationLaunchCommand(application, context) command.extend(context.get('launchArguments')) return command The issue is in the original _getApplicationLauncher, which extracts the extra launchArguments from the applications but does not take in account the current context. good news is that we are in the process of reviewing how applications are launched, hence this will be fixed soon. Cheers. L.
  6. Rory

    Action on Shot

    def discover(self, session, entities, event): '''Return True if we can handle the discovery.''' # TODO: Modify to fit your needs. # Example, only allow a single asset version as selection. if len(entities) != 1: return #entity_type, entity_id = entities[0] entityt = self._get_entity_type(entities[0]) if entityt != 'Shot': return return True So from the Handler example - this seems correct ?- using the incoming entities ? But that still doesn't work ?
  7. Lorenzo Angeli

    Action on Shot

    Hi @Rory, if you look a the action handler, the entity needed to be passed in is the original one coming from the event, there's no need to try to build the entity from the session. hope it helps. L.
  8. Rory

    Action on Shot

    entity_type, entity_id = entities[0] entity = session.get('TypedContext', entity_id) entitytype = self._get_entity_type(entity) Hi Lorenzo, I get NoneType returned to entitytype here ? What am I missing ? Thanks
  9. Hi, I'm attempting to send notes from an API user to use as a custom notification. It shows up in the sent items area of the inbox, but doesn't appear to the recipient. What am I missing here? The below method worked very well for my other tool of mass writing notes on an episode, the only difference being it's not being appended to task['notes'] this time. Create Note with content and author Create NoteLabelLink with note_id and label_id (set to "Notification" note label) Create Recipient with note_id and resource_id (the user) Commit session To provide a bit of background, I'm trying to make something where artists can subscribe to certain status changes on items (eg. animators want to know when a rig is updated). An event listener will detect that and send them a notification, I'm just a bit stuck on the notification part.
  10. Rory

    Action on Shot

    Thanks so much Lorenzo - Will take a look asap.
  11. Hi Dan, here is the connect-log file. regards, Marc ftrack_connect.log.zip
  12. Lorenzo Angeli

    Action on Shot

    Hi @Rory, if you want to write new actions I'd suggest having a look at our action handler. Regarding your question is because many of the Context entities comes from a common Task base entity (server side), if you want to properly identify have a look at the _get_entity_type method of the action handler. Hope it helps. L.
  13. Rory

    Action on Shot

    Hi All, I am writing an action to create folder structures on disk based on some Ftrack details. I am trying to attach the action to a Shot. Below is a snippet of the 'discover' method. Why would the entity have to return true for 'task' to get Shot ? This works for Sequence and Shot but I am confused as to why the entityType to test is task and not shot ? def discover(self, event): '''Return action config if triggered on a single asset version.''' data = event['data'] '''If selection contains more than one item return early since this action can only handle a single version.''' # self.logger.info(event[]) selection = data.get('selection', []) self.logger.info('Got selection: {0}'.format(selection)) for item in selection: if item.get('entityType') == 'task': return { 'items': [{ 'label': self.label, 'description': self.description, 'actionIdentifier': self.identifier }] }
  14. Earlier
  15. import logging import ftrack_api import sys import pprint import ftrack_connect.application class ApplicationStore(ftrack_connect.application.ApplicationStore): '''Store used to find and keep track of available applications.''' def _discoverApplications(self): '''Return a list of applications that can be launched from this host.''' applications = [] if sys.platform == 'darwin': prefix = ['/', 'Applications'] applications.extend(self._searchFilesystem( expression=prefix + [ 'Blender*', 'Blender.app' ], label='Blender {version}', applicationIdentifier='blender_{version}' )) elif sys.platform == 'win32': prefix = ['C:\\', 'Program Files.*'] applications.extend(self._searchFilesystem( expression=( prefix + ['Blender Foundation', 'Blender*', 'blender.exe'] ), label='Blender {version}', applicationIdentifier='blender_{version}' )) self.logger.debug( 'Discovered applications:\n{0}'.format( pprint.pformat(applications) ) ) return applications class BlenderAction(object): '''Launch Blender action.''' # Unique action identifier. identifier = 'blender-launch-action' def __debug(self, message): f = open("C:\\Users\\aaron\\Desktop\\output.txt", "a") f.write(pprint.pformat(message)) f.close() def __init__(self, applicationStore, launcher): '''Initialise action with *applicationStore*.''' super(BlenderAction, self).__init__() self.logger = logging.getLogger( __name__ + '.' + self.__class__.__name__ ) self.applicationStore = applicationStore self.launcher = launcher if self.identifier is None: raise ValueError('The action must be given an identifier.') def register(self, session): '''Register action.''' session.event_hub.subscribe( 'topic=ftrack.action.discover', self.discover ) session.event_hub.subscribe( 'topic=ftrack.action.launch and data.actionIdentifier={0}'.format( self.identifier ), self.launch ) self.session = session def is_component(self, selection): if ( len(selection) != 1 or selection[0]['entityType'] != 'Component' ): return False return True def discover(self, event): '''Return action based on *event*.''' launchArguments = [] selection = event['data'].get('selection', []) if self.is_component(selection): component = self.session.get('Component', selection[0]['entityId']) if component is not None: location = self.session.pick_location() url = location.get_filesystem_path(component) launchArguments.append(url) items = [] applications = self.applicationStore.applications applications = sorted( applications, key=lambda application: application['label'] ) for application in applications: applicationIdentifier = application['identifier'] label = application['label'] items.append({ 'actionIdentifier': self.identifier, 'label': label, 'icon': 'http://icons.iconarchive.com/icons/dakirby309/simply-styled/256/Blender-icon.png', 'applicationIdentifier': applicationIdentifier, 'launchArguments': ['c:\\Users\\aaron\\Desktop\\lookdev_addon.blend'] #launchArguments }) return { 'items': items } def launch(self, event): '''Callback method for Blender action.''' applicationIdentifier = ( event['data']['applicationIdentifier'] ) context = event['data'].copy() return self.launcher.launch( applicationIdentifier, context ) class ApplicationLauncher(ftrack_connect.application.ApplicationLauncher): '''Custom launcher to modify environment before launch.''' def __debug(self, message): f = open("C:\\Users\\aaron\\Desktop\\output.txt", "a") f.write(pprint.pformat(message)) f.close() def _getApplicationLaunchCommand(self, application, context=None): command = ftrack_connect.application.ApplicationLauncher._getApplicationLaunchCommand(self, application, context) self.__debug(command) return command def register(session, **kw): '''Register action in Connect.''' # Validate that session is an instance of ftrack_api.Session. If not, assume # that register is being called from an old or incompatible API and return # without doing anything. if not isinstance(session, ftrack_api.Session): return applicationStore = ApplicationStore() launcher = ApplicationLauncher( applicationStore ) action = BlenderAction(applicationStore, launcher) action.register(session) Here's the full hook. To be honest, it's not too much different from the Houdini example in the docs at the moment, which is why I'm not sure what's going on. Let me know if something sticks out.
  16. Hi @Dave Goodbourn the list of available ones can be found here , if you need more complex ui you can think of using custom html widget . Hope it helps. L.
  17. @Aaron Powell would you mind either paste here the full launcher or send it over support so I can have a closer look ? Thanks. L.
  18. @Lorenzo Angeli _getApplicationLaunchCommand seems to only be returning the base command - ['C:\\Program Files\\Blender Foundation\\Blender 2.82\\blender.exe']. No attached launchArguments.
  19. Is it possible to have checkboxes/radioboxes in the interface? I've read something somewhere that you can but I might be getting confused with something else. Cheers, Dave.
  20. Hallo Marc, We are sorry you are having issues. Please could you send us the log files to our Support team via your existing Support ticket? The log files can be found in a separate directory from the ftrack Connect installation. You can open the directory from the About dialog by selecting About in the context menu that will be displayed when you click the ftrack icon in the menu bar/taskbar, and then clicking Open log directory. Cheers, Dan
  21. Cool! Take a look at this if you don't want to hand out that highly-provisioned API key to everyone https://bitbucket.org/ftrack/ftrack-connect/src/57ece813d21bff72621c1a6a58feb958cd0557cd/source/ftrack_connect/ui/login_tools.py?at=master#login_tools.py-12:13,75:76,84,87,92,95,100,103
  22. The user is just running the tool with a custom launcher written in python (so it's like running a command line) . I have a program called explorer which query ftrack to get all the projects/shot/task information for the user. Once he have choose a task the explorer launch the correct software with the correct context. I don't use ftrack connect. I have my own database for our projects, the goal is to work with the local DB and replicate the data in the ftrack one to use the Web UI to manage projects easily
  23. How's the user running this tool? Is there one persistent process running in a central location or is it more like a short-lived command invoked on the command line? Are you using ftrack Connect? Just the web UI? Depending on your use-case, either running your tool as a plugin in Connect, pulling the API key from the config file written by Connect, or using the method demonstrated by Connect to use an authenticated browser session to generate a new API key all sound like good options. If you're exposing this tool as a web page or widget itself, you could embed that in a dashboard and pull API credentials there too. Also, and I don't necessarily suggest this, a global API key can have the permissions to manage User's API keys, so you could generate a new one for each of your users, store them, then create sessions as needed. Be careful not to revoke their existing keys as that will log them out of Connect.
  24. I want the user to query the ftrack database using my python tool (listing projects, pick a shot, task, etc...) but i need this user to be bounded to his permissions. The global API keys aren't limited to the user's role so i need to use the user's key but i don't know how to get it to set the environment variable. The best way in my opinion is to ask the user for his ftrack login/pass to request his API key. But maybe i'm wrong...
  25. Hi Tony, What's your use case exactly? As you've found, the global API keys are not limited by the role(s) assigned to the user's whose username you use to instantiate your session.
  26. Hello, i've tried again but still stuck. If someone can help me with this problem My previous message explains everything. I can't find in the help file the way to use the user api key, so in the session creation i use a global one that I've created. But when i use it the queries aren't bounded to the user's permission
  27. @marc mantei _getApplicationLaunchCommand is a method of the ftrack connect ApplicationLauncher class. Using this as baseclass for your launcher will provide you access to the underlying method. You can see an example in the maya hook hope it helps. L.
  1. Load more activity