def get_root_from_file(self, file_name, flatten_hierarchy=False): """ :param file_name: the kiko file path :param flatten_hierarchy: flattens the hierarchy stored inside the file """ k_file = KikoFile(file_name) k_file.parse() d = deserializers.DeserializerManager.get_deserializer(k_file.version, self._facade) return d.get_root_from_data(k_file.data, flatten_hierarchy=flatten_hierarchy)
def _load_kiko_file(self, path): if path != self._kiko_file_path: self._kiko_file_path = path k_file = KikoFile(self._kiko_file_path) k_file.parse() d = deserializers.DeserializerManager.get_deserializer( k_file.version, self._manager.facade) root = d.get_root_from_data(k_file.data) self._import_button.setEnabled(True) self._tab_widget.setEnabled(True) self._preview.file = k_file self._frame_range.set_range(root.start_frame, root.end_frame) self._mapping.set_root(root)
def file(self, kiko_file): if isinstance(kiko_file, KikoFile): self._static_image_only = kiko_file.num_images == 0 self._kiko_file = kiko_file else: self._static_image_only = (kiko_file is None or not kiko_file.endswith(KIKO_FILE_EXTENSION)) if not self._static_image_only: self._kiko_file = KikoFile(kiko_file) self._kiko_file.parse() self._static_image = QtGui.QImage() if self._static_image_only: self._static_image.load(get_image('kiko.jpg')) else: self._scrubbing_line_position = 5 if self._kiko_file.num_images > 0: self._static_image.loadFromData(self._kiko_file.get_image(0)) self._timer = QtCore.QTimer(self) self._timer.setInterval(1000 / KIKO_PREVIEW_FPS) self._timer.timeout.connect(self._next_frame) else: self._static_image.load(get_image('kiko.jpg')) self._static_image_only = True self.setMouseTracking(not self._static_image_only) self._current_image = self._static_image self.setMaximumWidth(self._static_image.width()) self.setMaximumHeight(self._static_image.height()) if not self._current_image.isNull(): self.setMinimumHeight(self.width() / self.aspect_ratio) if self._play_by_default: self.play() else: self.repaint()
def _export_button_clicked(self): path = self._file_path.text() if not os.path.exists(os.path.dirname(path)): QtWidgets.QMessageBox.critical(self, "Error", "Invalid file path.") return facade = self._manager.facade if not facade.get_selection(): QtWidgets.QMessageBox.critical(self, "Error", "Please selected " "something and retry.") return f_name = self._sanitise_file_name(path) start_frame, end_frame = self._get_start_end_frame() selected_operators = self._get_selected_operators() self._manager.export_to_file(f_name, operators=selected_operators, keep_previous_images=False, hierarchy=self._hierarchy.isChecked(), start_frame=start_frame, end_frame=end_frame, force_op_evaluation=self._force_all.isChecked()) if self._data_export.isChecked(): QtWidgets.QMessageBox.information(self, "Success!", "KB file " "exported " "successfully!") return sample = int(self._image_sampling.text()) start, end = self._image_frame_range.get_range() images = facade.generate_image_sequence( self._image_source.currentText(), start, end, sample) if not images: raise InvalidOperation("Could not generate images") if self._app_preference_widget: self._app_preference_widget.set_preferences() k_file = KikoFile(f_name) k_file.parse() start, end = self._image_frame_range.get_range() k_file.set_images(images) k_file.save() QtWidgets.QMessageBox.information(self, "Success!", "KIKO file exported " "successfully!")
class PreviewWidget(QtWidgets.QWidget): def __init__(self, kiko_file=None, play_by_default=KIKO_PREVIEW_PLAY, parent=None): super(PreviewWidget, self).__init__(parent=parent) self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self._play_by_default = play_by_default self._current_image = QtGui.QImage() self._scrubbing_line_position = 5 self._mouse_over = False self.file = kiko_file @property def file(self): return self._kiko_file @file.setter def file(self, kiko_file): if isinstance(kiko_file, KikoFile): self._static_image_only = kiko_file.num_images == 0 self._kiko_file = kiko_file else: self._static_image_only = (kiko_file is None or not kiko_file.endswith(KIKO_FILE_EXTENSION)) if not self._static_image_only: self._kiko_file = KikoFile(kiko_file) self._kiko_file.parse() self._static_image = QtGui.QImage() if self._static_image_only: self._static_image.load(get_image('kiko.jpg')) else: self._scrubbing_line_position = 5 if self._kiko_file.num_images > 0: self._static_image.loadFromData(self._kiko_file.get_image(0)) self._timer = QtCore.QTimer(self) self._timer.setInterval(1000 / KIKO_PREVIEW_FPS) self._timer.timeout.connect(self._next_frame) else: self._static_image.load(get_image('kiko.jpg')) self._static_image_only = True self.setMouseTracking(not self._static_image_only) self._current_image = self._static_image self.setMaximumWidth(self._static_image.width()) self.setMaximumHeight(self._static_image.height()) if not self._current_image.isNull(): self.setMinimumHeight(self.width() / self.aspect_ratio) if self._play_by_default: self.play() else: self.repaint() def resizeEvent(self, event): if not self._current_image.isNull(): self.setMinimumHeight(self.width() / self.aspect_ratio) if self._scrubbing_line_position: self._scrubbing_line_position *= (float(event.size().width()) / float(event.oldSize().width())) super(PreviewWidget, self).resizeEvent(event) def play(self): if not self._static_image_only and not self._timer.isActive(): self._timer.start() def pause(self): if not self._static_image_only and self._timer.isActive(): self._timer.stop() def _next_frame(self): self._frame_number += 1 if self._frame_number > self._kiko_file.num_images - 1: self._frame_number = 0 self._current_image.loadFromData(self._kiko_file.get_image( self._frame_number)) self.repaint() @property def aspect_ratio(self): if self._current_image.isNull(): return None w = float(self._current_image.width()) h = float(self._current_image.height()) return w / h def mouseMoveEvent(self, event): if not self._static_image_only and not self._play_by_default: w = self.width() ratio = float(event.pos().x()) / float(w) ratio = max(0, min(ratio, 1)) frame_number = int(round((self._kiko_file.num_images - 1) * ratio)) self._current_image.loadFromData(self._kiko_file.get_image( frame_number)) self._scrubbing_line_position = max(5, min(event.pos().x(), w - 5)) self.repaint() super(PreviewWidget, self).mouseMoveEvent(event) def enterEvent(self, event): self._mouse_over = True super(PreviewWidget, self).enterEvent(event) def leaveEvent(self, event): self._mouse_over = False self.repaint() super(PreviewWidget, self).leaveEvent(event) def hideEvent(self, event): if self._play_by_default: self.pause() super(PreviewWidget, self).hideEvent(event) def showEvent(self, event): if self._play_by_default: self.play() super(PreviewWidget, self).showEvent(event) def paintEvent(self, event): if not self._current_image.isNull(): painter = QtGui.QPainter(self) painter.setRenderHint(QtGui.QPainter.Antialiasing) w = min(self._current_image.width(), self.width()) h = w / self.aspect_ratio #image pen = QtGui.QPen() pen.setColor(QtGui.QColor(0, 0, 0, 0)) pen.setJoinStyle(QtCore.Qt.RoundJoin) brush = QtGui.QBrush(self._current_image.scaledToWidth(w, QtCore.Qt.SmoothTransformation)) painter.setBrush(brush) painter.setPen(pen) painter.drawRoundedRect(0, 0, w, h, 10, 10) #border path = QtGui.QPainterPath() path.addRoundedRect(QtCore.QRectF(0, 0, w, h), 10, 10) pen = QtGui.QPen(QtCore.Qt.black, 3) painter.setPen(pen) painter.drawPath(path) if not self._play_by_default and self._scrubbing_line_position: x = self._scrubbing_line_position sh = h - 8 sy = 4 if not self._mouse_over: sh = 4 sy = h - 8 path = QtGui.QPainterPath() path.addRoundedRect(QtCore.QRectF(x - 2, sy, 4, sh), 5, 5) pen = QtGui.QPen(QtGui.QColor(255, 255, 255, 123), 3) painter.setPen(pen) painter.drawPath(path) super(PreviewWidget, self).paintEvent(event)
def export_to_file(self, file_name, objects=None, operators=None, hierarchy=False, keep_previous_images=False, start_frame=None, end_frame=None, force_op_evaluation=False, channel_filter=None): """ :param file_name: the kiko file path, the file extension determines if a preview is going to be exported (kiko) or not (kb). :param objects: The list of objects to processs :param operators: list of operators to use for this export :param hierarchy: enables the hierarchy mode :param keep_previous_images: keeps the images contained by the kiko file if it already exists :param start_frame: the animation start frame :param end_frame: the animation end frame :param force_op_evaluation: force all operators evaluation :param channel_filter: filter the list of channels to export """ if self._facade is None: raise InvalidFacadeException('Cannot export file without a facade. ' 'Please create a new kikoManager with a facade') ops = [] operators = operators or OperatorsFactory().get_all_operator_names( self._facade.get_app_name()) for o in operators: op_c = None if isinstance(o, tuple): if OperatorsFactory.has_operator(o[0], version=o[1]): op_c = OperatorsFactory().get_operator(o[0], o[1]) else: op_ver = OperatorsFactory().get_latest_version(o) if not op_ver is None: op_c = OperatorsFactory().get_operator(o, op_ver) if op_c is None: raise KikoManagerException('Could not find operator %s' % o) if not op_c.is_app_supported(self._facade.get_app_name()): continue ops.append(op_c) if not ops: raise KikoManagerException("No valid operator found.") if objects: objs = [self._facade.get_node_by_name(o) for o in objects] else: objs = self._facade.get_selection() if not objs: raise KikoManagerException("No obj was selected or passed as arg.") k_file = KikoFile(file_name) if keep_previous_images: k_file.parse() s = serializer.Serializer(facade=self._facade) k_file.data = s.serialize(file_name, objs, hierarchy=hierarchy, operators=ops, start_frame=start_frame, end_frame=end_frame, force_op_evaluation=force_op_evaluation, channel_filter=channel_filter) k_file.save()
def import_from_file(self, file_name, objects=None, item_op_priority=None, channel_op_priority=None, import_obj_method=None, import_anim_method=None, str_replacements=None, obj_mapping=None, prefix_to_add=None, suffix_to_add=None, scale_using_fps=False, frame_value=0, ignore_item_chunks=False, start_frame=None, end_frame=None): """ :param file_name: the kiko file path :param objects: The list of objects to processs :param item_op_priority: the priority list for item operators :param channel_op_priority: the priority list for channel operators :param import_obj_method: import object method :param import_anim_method: the import animation method :param str_replacements: a dictionary of string replacements for item mapping :param obj_mapping: object/channel mapping :param prefix_to_add: a prefix to add to the item names for item matching :param suffix_to_add: a suffix to add to the item names for item matching :param scale_using_fps: scales the animation by using the ratio between the frame rate used when exporting the kiko file and the current scene frame rate :param frame_value: a frame offset value :param ignore_item_chunks: if True ignores item chunks/operators :param start_frame: data stored in the kiko file for key frames before this value will be ignored :param end_frame: data stored in the kiko file for key frames after this value will be ignored """ if self._facade is None: raise InvalidFacadeException('Cannot import file without a facade. ' 'Please create a new kikoManager with a facade') k_file = KikoFile(file_name) k_file.parse() if import_obj_method is None: import_obj_method = IMPORT_METHODS.OBJECT.NAME elif not import_obj_method in IMPORT_METHODS.OBJECT.all(): raise KikoManagerException('Invalid object import method given') flatten_hierarchy = import_obj_method != IMPORT_METHODS.OBJECT.HIERARCHY if import_anim_method is None: import_anim_method = IMPORT_METHODS.ANIMATION.APPLY elif not import_anim_method in IMPORT_METHODS.ANIMATION.all(): raise KikoManagerException('Invalid animation import method given') if item_op_priority or channel_op_priority: all_op = (item_op_priority or []) + (channel_op_priority or []) for o in all_op: op_ver = OperatorsFactory().get_latest_version(o) if op_ver is None: raise KikoManagerException("Operators %s not found" % o) op_c = OperatorsFactory().get_operator(o, op_ver) if not op_c.is_app_supported(self._facade.get_app_name()): raise KikoManagerException("Operator %s does not support %s" % (o, self._facade.get_app_name())) if obj_mapping: #building a new map in case there is some channel remapping temp_mapping = {} for key, value in obj_mapping.iteritems(): tokens = key.split('.') if (len(tokens) == 2) != ('.' in value): raise KikoManagerException("Cannot map channel to object " "or viceversa: %s -> %s" % (key, value)) if len(tokens) == 2: if (not tokens[0] in temp_mapping or not isinstance(temp_mapping[tokens[0]], list)): temp_mapping[tokens[0]] = [] vts = value.split('.') temp_mapping[tokens[0]].append((tokens[1], vts[0], vts[1])) else: temp_mapping[key] = value obj_mapping = temp_mapping if objects: objs = [self._facade.get_node_by_name(o) for o in objects] else: objs = self._facade.get_selection() if not objs: msg = "No obj was selected or passed as arg." if import_obj_method == IMPORT_METHODS.OBJECT.NAME: warnings.warn(msg + " Trying to match items by name.") else: raise KikoManagerException(msg) d = deserializers.DeserializerManager.get_deserializer(k_file.version, self._facade) root = d.get_root_from_data(k_file.data, flatten_hierarchy=flatten_hierarchy, ignore_item_chunks=ignore_item_chunks) t_mult = ((float(self._facade.get_fps()) / root.fps) if scale_using_fps else 1) self._facade.pre_import() d.load_data(root, objs, item_op_priority=item_op_priority, channel_op_priority=channel_op_priority, import_obj_method=import_obj_method, import_anim_method=import_anim_method, str_replacements=str_replacements, obj_mapping=obj_mapping, prefix_to_add=prefix_to_add, suffix_to_add=suffix_to_add, frame_value=frame_value, time_multiplier=t_mult, start_frame=start_frame, end_frame=end_frame) self._facade.post_import()