import logging from pathlib import Path from typing import Optional from maya.cmds import confirmDialog from PySide2 import QtCore, QtWidgets from ..builder.scene import Scene from ..config.aas import AdditionalAssemblyScript from ..config.analog_gui import AnalogGui from ..config.character import Character from ..config.gui import Gui from ..config.rig_logic import RigLogic from ..config.units import AngleUnit, LinearUnit from ..const.ui import ( MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, SPACING, WINDOW_OBJECT, WINDOW_SIZE_HEIGHT_MAX, WINDOW_SIZE_HEIGHT_MIN, WINDOW_SIZE_WIDTH_MAX, WINDOW_SIZE_WIDTH_MIN, WINDOW_TITLE, ) from ..reader.dna import DNA from ..ui.elements import Elements from ..ui.elements_creator import ElementsCreator from .widgets import QHLine def show_dna_viewer_window() -> None: DnaViewerWindow.show_window() class DnaViewerWindow(QtWidgets.QMainWindow): """ UI Window Attributes ---------- @type elements: Elements @param elements: The object containing references to the UI elements @type elements_creator: ElementsCreator @param elements_creator: The class used for creating UI elements @type build_scene_successful: bool @param build_scene_successful: A flag representing if building of the scene was a success @type character_config: Character @param character_config: The character configuration that will be processed """ window: QtWidgets.QMainWindow = None def __init__(self, parent: QtWidgets.QWidget = None) -> None: super().__init__(parent) self.elements = Elements() self.elements_creator = ElementsCreator(self, self.elements) self.setup_window() self.create_ui() self.build_scene_successful = False self.character_config: Optional[Character] = None def setup_window(self) -> None: """A method for setting up the window""" self.setWindowFlags( self.windowFlags() | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMaximizeButtonHint | QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowCloseButtonHint ) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setObjectName(WINDOW_OBJECT) self.setWindowTitle(WINDOW_TITLE) self.setWindowFlags(QtCore.Qt.Window) self.setFocusPolicy(QtCore.Qt.StrongFocus) def create_ui(self) -> None: """Fills the window with UI elements""" self.elements.main_widget = self.create_main_widget() self.setCentralWidget(self.elements.main_widget) self.set_size() def create_main_widget(self) -> QtWidgets.QWidget: """ Creates the widget containing the UI elements @rtype: QtWidgets.QWidget @returns: the main widget """ header = self.elements_creator.create_header() body = self.elements_creator.create_body() widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout(widget) layout.addLayout(header) layout.addWidget(QHLine()) layout.addLayout(body) layout.setContentsMargins(MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM) layout.setSpacing(SPACING) return widget def set_size(self) -> None: """Sets the window size""" self.setMaximumSize(WINDOW_SIZE_WIDTH_MAX, WINDOW_SIZE_HEIGHT_MAX) self.setMinimumSize(WINDOW_SIZE_WIDTH_MIN, WINDOW_SIZE_HEIGHT_MIN) self.resize(WINDOW_SIZE_WIDTH_MIN, WINDOW_SIZE_HEIGHT_MIN) def process(self) -> None: """Start the build process of creation of scene from provided configuration from the UI""" self.character_config = self.get_character_config() self.elements.main_widget.setEnabled(False) self.build_scene() self.elements.main_widget.setEnabled(True) def get_character_config(self) -> Character: """ Gets the character config from the UI elements @rtype: Character @returns: character configuration object """ gui_path = self.elements.get_gui_path() gui_options = Gui(gui_path=gui_path) if gui_path else None analog_gui_path = self.elements.get_analog_gui_path() analog_gui_options = ( AnalogGui(gui_path=analog_gui_path) if analog_gui_path else None ) aas_path = self.elements.get_aas_path() aas = ( AdditionalAssemblyScript( path=aas_path, module_name=Path(aas_path).stem, ) if aas_path else None ) riglogic = ( RigLogic() if Elements.is_checked(self.elements.rig_logic_cb) else None ) config = Character( dna=self.elements.dna, create_character_node=False, create_display_layers=False, meshes=self.elements.mesh_tree_list.get_selected_meshes(), gui_options=gui_options, analog_gui_options=analog_gui_options, aas=aas, rig_logic_config=riglogic, ) config.options = self.elements.get_build_options() return config def set_progress(self, text: str = None, value: int = None) -> None: """Setting text and/or value to progress bar""" if text is not None: self.elements.progress_bar.setFormat(text) if value is not None: self.elements.progress_bar.setValue(value) def build_scene(self) -> None: """Start building the scene""" try: self.set_progress(text="Processing in progress...", value=0) dna_file_path = Elements.get_file_path(self.elements.select_dna_path) if dna_file_path: DNA.load_dna(dna_file_path) self.set_progress(value=33) builder = Scene() builder.config.with_character(self.character_config) builder.config.with_linear_unit(unit=LinearUnit.cm).with_angle_unit( unit=AngleUnit.degree ) self.set_progress(value=66) builder.build() self.set_progress(text="Processing completed", value=100) except Exception as e: self.set_progress(text="Processing failed", value=100) logging.error(e) confirmDialog(message=e, button=["ok"], icon="critical") @staticmethod def show_window() -> None: if DnaViewerWindow.window is None: DnaViewerWindow.window = DnaViewerWindow( parent=DnaViewerWindow.maya_main_window() ) DnaViewerWindow.activate_window() @staticmethod def maya_main_window() -> QtWidgets.QWidget: """ Gets the MayaWindow instance @throws RuntimeError @rtype: QtWidgets.QWidget @returns: main window instance """ for obj in QtWidgets.QApplication.topLevelWidgets(): if obj.objectName() == "MayaWindow": return obj raise RuntimeError("Could not find MayaWindow instance") @staticmethod def activate_window() -> None: """Shows window if minimized""" try: DnaViewerWindow.window.show() if DnaViewerWindow.window.windowState() & QtCore.Qt.WindowMinimized: DnaViewerWindow.window.setWindowState(QtCore.Qt.WindowActive) DnaViewerWindow.window.raise_() DnaViewerWindow.window.activateWindow() except RuntimeError as e: print(e) if str(e).rstrip().endswith("already deleted."): DnaViewerWindow.window = None DnaViewerWindow.show_window()