def execute(self, context): unlinked_ids = set() # First remove the Attract properties from the strips. for strip in context.selected_sequences: atc_object_id = getattr(strip, 'atc_object_id') remove_atc_props(strip) if atc_object_id: unlinked_ids.add(atc_object_id) # For all Object IDs that are no longer in use in the edit, let Attract know. # This should be done with care, as the shot could have been attached to multiple # strips. id_to_shots = compute_strip_conflicts(context.scene) for oid in unlinked_ids: if len(id_to_shots[oid]): # Still in use continue node = Node({'_id': oid}) pillar.sync_call(node.patch, {'op': 'unlink'}) if len(unlinked_ids) == 1: shot_id = unlinked_ids.pop() context.window_manager.clipboard = shot_id self.report({'INFO'}, 'Copied unlinked shot ID %s to clipboard' % shot_id) else: self.report({'INFO'}, '%i shots have been marked as Unused.' % len(unlinked_ids)) draw.tag_redraw_all_sequencer_editors() return {'FINISHED'}
def relink(self, strip, atc_object_id, *, refresh=False): from .. import pillar # The node may have been deleted, so we need to send a 'relink' before we try # to fetch the node itself. node = Node({'_id': atc_object_id}) pillar.sync_call(node.patch, {'op': 'relink'}) try: node = pillar.sync_call(Node.find, atc_object_id, caching=False) except (sdk_exceptions.ResourceNotFound, sdk_exceptions.MethodNotAllowed): verb = 'refresh' if refresh else 'relink' self.report({'ERROR'}, 'Shot %r not found on the Attract server, unable to %s.' % (atc_object_id, verb)) strip.atc_is_synced = False return {'CANCELLED'} strip.atc_is_synced = True if not refresh: strip.atc_name = node.name strip.atc_object_id = node['_id'] # We do NOT set the position/cuts of the shot, that always has to come from Blender. strip.atc_status = node.properties.status strip.atc_notes = node.properties.notes or '' strip.atc_description = node.description or '' draw.tag_redraw_all_sequencer_editors()
def tasks(): """User-assigned tasks""" # Pagination index page = request.args.get('page', 1) max_results = 50 api = system_util.pillar_api() node_type_list = NodeType.all({'where': "name=='task'"}, api=api) if len(node_type_list['_items']) == 0: return "Empty NodeType list", 200 node_type = node_type_list._items[0] tasks = Node.all({ 'where': '{"node_type" : "%s", "properties.owners.users": {"$in": ["%s"]}}'\ % (node_type['_id'], current_user.objectid), 'max_results': max_results, 'page': page, 'embedded': '{"parent":1, "picture":1}', 'sort' : "order"}, api=api) # Build the pagination object # pagination = Pagination(int(page), max_results, tasks._meta.total) tasks_datatable = [] for task in tasks._items: cut_in = 0 cut_out = 0 if task.parent.properties.cut_in: cut_in = task.parent.properties.cut_in if task.parent.properties.cut_out: cut_out = task.parent.properties.cut_out data = { 'DT_RowId': "row_{0}".format(task._id), '_id': task._id, 'order': task.order, 'picture': None, 'name': task.name, 'timing': { 'cut_in': task.parent.properties.cut_in, 'cut_out': task.parent.properties.cut_out, }, 'parent': task.parent.to_dict(), 'description': task.description, 'url_view': url_for('nodes.view', node_id=task._id), 'url_edit': url_for('nodes.edit', node_id=task._id, embed=1), 'status': task.properties.status, } tasks_datatable.append(data) return render_template( 'users/tasks.html', title="task", tasks_data=json.dumps(tasks_datatable), node_type=node_type)
def tasks(): """User-assigned tasks""" # Pagination index page = request.args.get("page", 1) max_results = 50 api = SystemUtility.attract_api() node_type_list = NodeType.all({"where": "name=='task'"}, api=api) if len(node_type_list["_items"]) == 0: return "Empty NodeType list", 200 node_type = node_type_list._items[0] tasks = Node.all( { "where": '{"node_type" : "%s", "properties.owners.users": {"$in": ["%s"]}}' % (node_type["_id"], current_user.objectid), "max_results": max_results, "page": page, "embedded": '{"parent":1, "picture":1}', "sort": "order", }, api=api, ) # Build the pagination object # pagination = Pagination(int(page), max_results, tasks._meta.total) tasks_datatable = [] for task in tasks._items: cut_in = 0 cut_out = 0 if task.parent.properties.cut_in: cut_in = task.parent.properties.cut_in if task.parent.properties.cut_out: cut_out = task.parent.properties.cut_out data = { "DT_RowId": "row_{0}".format(task._id), "_id": task._id, "order": task.order, "picture": None, "name": task.name, "timing": {"cut_in": task.parent.properties.cut_in, "cut_out": task.parent.properties.cut_out}, "parent": task.parent.to_dict(), "description": task.description, "url_view": url_for("nodes.view", node_id=task._id), "url_edit": url_for("nodes.edit", node_id=task._id, embed=1), "status": task.properties.status, } tasks_datatable.append(data) return render_template( "users/tasks.html", title="task", tasks_data=json.dumps(tasks_datatable), node_type=node_type )
def submit_new_strip(self, strip): from .. import pillar, blender # Define the shot properties user_uuid = pillar.pillar_user_uuid() if not user_uuid: self.report({'ERROR'}, 'Your Blender Cloud user ID is not known, ' 'update your credentials.') return {'CANCELLED'} prop = { 'name': strip.name, 'description': '', 'properties': { 'status': 'todo', 'notes': '', 'used_in_edit': True, 'trim_start_in_frames': strip.frame_offset_start, 'trim_end_in_frames': strip.frame_offset_end, 'duration_in_edit_in_frames': strip.frame_final_duration, 'cut_in_timeline_in_frames': strip.frame_final_start }, 'order': 0, 'node_type': 'attract_shot', 'project': blender.preferences().attract_project.project, 'user': user_uuid } # Create a Node item with the attract API node = Node(prop) post = pillar.sync_call(node.create) # Populate the strip with the freshly generated ObjectID and info if not post: self.report({'ERROR'}, 'Error creating node! Check the console for now.') return {'CANCELLED'} strip.atc_object_id = node['_id'] strip.atc_is_synced = True strip.atc_name = node['name'] strip.atc_description = node['description'] strip.atc_notes = node['properties']['notes'] strip.atc_status = node['properties']['status'] draw.tag_redraw_all_sequencer_editors()