Metahuman_DNA_Calibration/dna_viewer/ui/dna_viewer_window.py
2022-11-29 14:25:24 +01:00

247 lines
7.6 KiB
Python

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()