"""
Provides a UI to export multiple flight sim object type quickly

run() will create the window and connect it to max. 
"""

import os
import re
import sys
import uuid

from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from maxsdk.globals import *
import BabylonPYMXS

from MultiExporter import optionsMenu, presetUtils,treeView,constants,exporter
import MultiExporter.ui.mainwindow_ui as mainWindowUI

from maxsdk import dialog as sdkdialog
from maxsdk import layer
from maxsdk import perforce as sdkperforce
from maxsdk import qtUtils, sceneUtils, userprop, utility
from pymxs import runtime as rt


class MainWindow(QWidget, mainWindowUI.Ui_MultiExporter):
    def __init__(self):
        QWidget.__init__(self)
        self.setupUi(self)
        self.optionsMenuWindow = None
        # buttons
        self.btnAddExport.pressed.connect(lambda: self._clickedAddExport())
        self.btnRemoveExport.pressed.connect(
            lambda: self._clickedRemoveExport())
        self.btnRefresh.pressed.connect(lambda: self.refreshTool())
        font = QFont()
        font.setPointSize(32)
        font.setWeight(75)
        font.setUnderline(False)
        font.setBold(False)
        self.btnRefresh.setFont(font)
        self.btnRefresh.setText(u"\U0001F5D8")
        self.tabWidget.currentChanged.connect(lambda: self._changedTab())
        self.btnConformLayers.pressed.connect(
            lambda: self._clickedConformLayers())
        self.btnAddPreset.pressed.connect(lambda: self._clickedAddPreset())
        self.btnRemovePreset.pressed.connect(lambda: self._clickedRemovePreset())
        self.btnDuplicatePreset.pressed.connect(self._clickedDuplicatePreset)
        self.btnApplyPresetLayer.pressed.connect(lambda: self._clickedApplyLayerSelection())
        self.btnEditPresetPath.pressed.connect(lambda: self._clickedEditPresetPath())
        self.btnAddGroup.pressed.connect(lambda: self._clickedAddPresetGroup())
        self.btnApplyPresetEdit.pressed.connect(lambda: self._clickedApplyPresetEdit())
        
        self.presetParamName.returnPressed.connect(lambda: self._clickedApplyPresetEdit())
        # export
        self.btnExportSelected.pressed.connect(
            lambda: self._clickedExportSelected())
        self.btnExportAll.pressed.connect(lambda: self._clickedExportAll())
        self.btnExportTicked.pressed.connect(
            lambda: self._clickedExportTicked())
        self.btnOpenExportFolder.pressed.connect(
            lambda: self._clickedOpenExportFolder())
        # lod view
        self.btnSetLODValues.pressed.connect(
            lambda: self._clickedSetLODValues())
        self.btnGenerateXML.pressed.connect(lambda: self._clickedGenerateXML())
        self.btnOptions.pressed.connect(lambda: self._openOptionsMenu())
        

        # LOD VIEW TREE CREATION
        self.verticalLayout_4.removeWidget(self.treeLODs)
        self.treeLODs.setHidden(True)
        self.treeLODs = treeView.TreeViewCategory(self.tab_3)
        self.treeLODs.setAlternatingRowColors(True)
        self.treeLODs.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.treeLODs.setIndentation(20)
        self.treeLODs.setObjectName("treeLODs")
        self.treeLODs.setColumnWidth(0, 450)
        self.treeLODs.setColumnWidth(1, 40)        
        self.treeLODs.setColumnWidth(2, 40)
        self.treeLODs.setColumnWidth(3, 40)
        self.treeLODs.setSortingEnabled(True)
        self.treeLODs.sortItems(0, Qt.SortOrder.AscendingOrder)
        self.treeLODs.header().setDefaultSectionSize(80)
        self.treeLODs.headerItem().setText(0, QApplication.translate("MultiExporter", "         Hierarchy", None, -1))
        self.treeLODs.headerItem().setText(1, QApplication.translate("MultiExporter", "LOD value", None, -1))
        self.treeLODs.headerItem().setText(2, QApplication.translate("MultiExporter", "Flatten", None, -1))
        self.treeLODs.headerItem().setText(3, QApplication.translate("MultiExporter", "Keep Instances", None, -1))
        self.treeLODs.headerItem().setText(4, QApplication.translate("MultiExporter", "Path", None, -1))
        self.verticalLayout_4.insertWidget(1, self.treeLODs)
        self.checkBoxLODModifier = qtUtils.createCheckBox(qtWidget=self.treeLODs)
        self.treeLODs.setGlobalCheckBox(self.checkBoxLODModifier)
        self.treeLODs.itemSelectionChanged.connect(lambda: self._selectionChangedLOD())
        self.cbObjectOptionPreset.setHidden(True)
        self.cbObjectOptionPreset = optionsMenu.ComboBoxOptionPreset(None, self.tab_3)
        self.cbObjectOptionPreset.setObjectName("cbObjectOptionPreset")
        self.cbObjectOptionPreset.setEditable(False)
        self.cbObjectOptionPreset.setMaximumWidth(130)
        self.cbObjectOptionPreset.setMinimumWidth(130)
        
        self.horizontalLayout_6.insertWidget(12,self.cbObjectOptionPreset)

        # PRESET VIEW TREE CREATION
        self.verticalLayout_3.removeWidget(self.treePresets)
        self.treePresets.setHidden(True)
        self.treePresets = treeView.TreeViewPreset(self.verticalLayoutWidget)
        self.treePresets.setEnabled(True)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.treePresets.sizePolicy().hasHeightForWidth())
        self.treePresets.setSizePolicy(sizePolicy)
        self.treePresets.setDragEnabled(True)
        self.treePresets.setDragDropMode(QAbstractItemView.DragDrop)
        self.treePresets.setDefaultDropAction(Qt.MoveAction)
        self.treePresets.setAlternatingRowColors(True)
        self.treePresets.setSortingEnabled(True)
        self.treePresets.sortItems(0, Qt.SortOrder.AscendingOrder)
        self.treePresets.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.treePresets.setObjectName("treePresets")
        self.treePresets.header().setDefaultSectionSize(40)
        self.treePresets.headerItem().setText(0, QApplication.translate("MultiExporter", "         Preset", None, -1))
        self.treePresets.headerItem().setText(1, QApplication.translate("MultiExporter", "Path", None, -1))
        self.verticalLayout_3.insertWidget(0, self.treePresets)
        self.treePresets.itemSelectionChanged.connect(lambda: self._selectionChangedPreset())
        self.cbOptionPreset.setHidden(True)
        self.cbOptionPreset = optionsMenu.ComboBoxOptionPreset(None,self.verticalLayoutWidget)
        self.cbOptionPreset.setObjectName("cbOptionPreset")
        self.cbOptionPreset.setEditable(False)
        self.cbOptionPreset.setMaximumWidth(130)
        self.cbOptionPreset.setMinimumWidth(130)
        self.horizontalLayout_8.insertWidget(4,self.cbOptionPreset)
        self.cbOptionPreset.activated.connect(self._clickedApplyPresetEdit)

        # LAYER VIEW TREE CREATION
        self.treeLayer.setHidden(True)
        self.verticalLayout_7.removeWidget(self.treeLayer)
        self.treeLayer = treeView.TreeViewLayer(self.verticalLayoutWidget_2)
        self.treeLayer.setAlternatingRowColors(True)
        self.treeLayer.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.treeLayer.setSortingEnabled(True)
        self.treeLayer.sortItems(0, Qt.SortOrder.AscendingOrder)
        self.treeLayer.setObjectName("treeLayer")
        self.treeLayer.headerItem().setText(0, QApplication.translate("MultiExporter", "         Layers", None, -1))
        self.verticalLayout_7.insertWidget(0, self.treeLayer)
        self.checkBoxLayerModifier = qtUtils.createCheckBox(qtWidget=self.treeLayer)
        self.treeLayer.setGlobalCheckBox(self.checkBoxLayerModifier)
        self.checkBoxPresetModifier = qtUtils.createCheckBox(qtWidget=self.treePresets)
        self.treePresets.setGlobalCheckBox(self.checkBoxPresetModifier)
        self.treeLayer.itemChanged.connect(lambda: self._changedLayerItem())
        self.treePresets.hasChanged.connect(lambda: self._droppedPresetWidget())

        self.btnLayerExpandAll.pressed.connect(self.treeLayer.expandAll)
        self.btnLayerCollapseAll.pressed.connect(self.treeLayer.collapseAll)
        
        # FILTER
        self.cbVisibleOnly.stateChanged.connect(lambda: self._changeCheckboxVisibility())
        self.cbIncludeLods.stateChanged.connect(lambda: self._changeCheckboxLODs())
        self.cbExportableOnly.stateChanged.connect(lambda: self._changeCheckboxExportable())

        # CREATE TREES AND INITIALIZE DATA
        self._changeCheckboxExportable()
        self._changeCheckboxLODs()
        self._changeCheckboxVisibility()
        self.lastEditedPreset = None
        self.treePresets.createTree()
        self.treeLODs.createTree()
        self.treeLayer.createTree()
        self._selectionChangedPreset()
        self._changedTab()
        self._refreshOptionPreset()

    def contextMenuEvent(self, event):
        r = self.tabWidget.geometry()
        if(r.contains(event.pos())):
            menu = QMenu(self)
            isLodView = self.getCurrentTree() == self.treeLODs
            isPresetView = self.getCurrentTree() == self.treePresets
            exportAction = menu.addAction("Export Selected")
            if(isLodView):
                generateXML = menu.addAction("Generate XML")
            if (isPresetView):
                rename = menu.addAction("Rename")
                addPreset = menu.addAction("Add Preset")
                addGroup = menu.addAction("Add Group")
                remove = menu.addAction("Remove Selected")
            openFolder = menu.addAction("Open in Explorer")
            action = menu.exec_(self.mapToGlobal(event.pos()))
            if(isLodView):
                if action == generateXML:
                    self._clickedGenerateXML()
            if (isPresetView):
                if action == rename:
                    self.treePresets.startEditingSelectedItem()
                if action == addPreset:
                    self._clickedAddPreset()
                if action == addGroup:
                    self._clickedAddPresetGroup()
                if action == remove:
                    self._clickedRemovePreset()
            if action == exportAction:
                self._clickedExportSelected()
            if action == openFolder:
                self._clickedOpenExportFolder()

    def _refreshOptionPreset(self):
        self.cbOptionPreset.refresh()
        self.cbObjectOptionPreset.refresh()


    def _openOptionsMenu(self):
        if (self.optionsMenuWindow == None):
            self.optionsMenuWindow = optionsMenu.run()
            self.optionsMenuWindow.onClosed.connect(
                lambda: self._closeOptionsMenu())
            self.optionsMenuWindow.onModifiedData.connect(lambda : self._refreshOptionPreset())
        else:
            self.optionsMenuWindow.activateWindow()

    def _closeOptionsMenu(self):
        self.optionsMenuWindow = None

    @Slot()
    def _droppedPresetWidget(self):
        self.refreshTool()

    def _clickedConformLayers(self):
        self.conformSceneLayersToLODView()

    def _clickedGenerateXML(self):
        categories = self.treeLODs.getSelectedCategory()
        log = ""
        count = len(categories)
        i = 0
        if count > 0:
            self.progressBar.setRange(0, count)
            self.progressBar.setValue(0)
            for category in categories:
                objects = self.treeLODs._baseNameDict[category]
                objects = sceneUtils.sortObjectsByLODLevels(objects)
                metadataPath = exporter.getMetadataPath(objects[0])
                if (metadataPath is None or metadataPath == ".xml"):
                    log += "\nERROR : No path on {0}. Skipping this XML file.".format(
                        objects[0].name)
                else:
                    log += exporter.createLODMetadata(metadataPath, objects)
                i += 1
                self.progressBar.setValue(i)
            if (log != ""):
                print(log)
                qtUtils.popup_scroll(title="XML Generation Ouput", text=log)

    def _clickedAddPresetGroup(self):
        newGroup = presetUtils.createNewGroup()
        presets = self.treePresets.getSelectedPresets()
        if len(presets) > 0:
            for preset in presets:
                preset.edit(group=newGroup.identifier)
        self.refreshTool()
        self.treePresets.startEditingItemWithGroupID(newGroup.identifier)

    def _clickedAddPreset(self):
        groups = self.treePresets.getSelectedGroups()
        groupID = None
        if (len(groups) > 0):
            groupID = groups[0].identifier
        filePath = presetUtils.askForNewPath("Create New Preset")
        if(filePath != None):
            presetName = os.path.split(filePath)[1]
            presetName = os.path.splitext(presetName)[0]
            presetUtils.createNewPreset(
                presetName, group=groupID, filePath=filePath)
            self.refreshTool()

    def _clickedRemovePreset(self):
        groups = self.treePresets.getSelectedGroups()
        presets = self.treePresets.getSelectedPresets()
        presetUtils.confirmAndRemove(presets=presets, groups=groups)
        self.refreshTool()
        
    def _clickedDuplicatePreset(self):
        groups = self.treePresets.getSelectedGroups()
        presets = self.treePresets.getSelectedPresets()
        groupTransfer = dict()
        for group in groups:
            oldId = group.identifier
            newGroup = presetUtils.createNewGroup(groupName=group.name, optionPreset=group.optionPreset)
            newId = newGroup.identifier
            groupTransfer[oldId] = newId
        for preset in presets:            
            targetGroup = preset.group
            if groupTransfer.has_key(targetGroup):
                targetGroup = groupTransfer[targetGroup] 
            presetUtils.createNewPreset(labelName=preset.name, group=targetGroup, filePath=preset.path, layerNames=preset.layerNames)
            
        self.refreshTool()



    def _changedTab(self):
        currentTab = self.tabWidget.currentIndex()
        isLODView = currentTab == 0
        isPresetView = currentTab == 1
        self.btnGenerateXML.setEnabled(isLODView)
        self.btnAddExport.setEnabled(isLODView)
        self.btnRemoveExport.setEnabled(isLODView)
        self.refreshTool()

    def _clickedOpenExportFolder(self):
        currentTree = self.getCurrentTree()
        exportPath = None
        if(currentTree == self.treeLODs):
            selected = self.getCurrentlySelectedRootList()
            if(len(selected) > 0):
                exportPath = exporter.getAbsoluteExportPath(selected[0])
        elif (currentTree == self.treePresets):
            selected = self.treePresets.getSelectedPresets()
            if (len(selected) > 0):
                exportPath = presetUtils.getAbsoluteExportPath(selected[0])
        if exportPath is not None:
            try:
                exportPath = os.path.split(exportPath)[0]
                os.startfile(exportPath)
            except WindowsError as err:
                qtUtils.popup(title="WindowsError", text=err.strerror)

    def _changeCheckboxExportable(self):
        state = self.cbExportableOnly.checkState() == Qt.Checked
        self.treeLODs._showOnlyExportable = state
        self.treeLayer._showOnlyExportable = state
        self.refreshTool()

    def _changeCheckboxLODs(self):
        state = self.cbIncludeLods.checkState() == Qt.Checked
        self.treeLODs._showOnlyLODs = state
        self.treeLayer._showOnlyLODs = state
        self.refreshTool()

    def _changeCheckboxVisibility(self):
        state = self.cbVisibleOnly.checkState() == Qt.Checked
        self.treeLODs._showOnlyVisible = state
        self.treeLayer._showOnlyVisible = state
        self.refreshTool()

    def _clickedEditPresetPath(self):
        selected = self.treePresets.getSelectedPresets()
        presetUtils.addExportPathToPresets(selected)
        self.refreshTool()

    def _changedLayerItem(self):
        selected = self.treePresets.getSelectedPresets()
        if (len(selected) == 1):
            self.lastEditedPreset = selected[0]
            self.treeLayer.isEdited = True
            self.btnApplyPresetLayer.setText("Apply*")

    def _selectionChangedPreset(self):
        groups = self.treePresets.getSelectedGroups()
        if (self.treeLayer.isEdited):
            if(self.lastEditedPreset):
                if (qtUtils.popup_Yes_No(
                        title="Apply Unsaved Changes ?",
                        text="You have unsaved changes on a preset, do you want to apply them now ?")
                    ):
                    layerSelection = self.treeLayer.getCheckedLayerNames()
                    self.applyLayerSelectionToPreset(
                        self.lastEditedPreset, layerSelection)
        if (len(groups) == 1):
            self.treeLayer.setEnabled(False)
            self.presetParamName.setText(groups[0].name)
            optionPresetId = self.cbOptionPreset.getOptionPresetIndexByIdentifier(groups[0].optionPreset)
            if optionPresetId is not None:                
                self.cbOptionPreset.setCurrentIndex(optionPresetId)
            else:
                self.cbOptionPreset.setCurrentIndex(0)
            self.treeLayer.uncheckAllLayers()
            return
        presets = self.treePresets.getSelectedPresets()
        if (len(presets) == 1):
            self.treeLayer.setEnabled(True)
            preset = presets[0]
            layerNames = preset.layerNames
            self.treeLayer.intializeCheckLayers(layerNames)
            self.btnApplyPresetLayer.setText("Apply")
            self.presetParamName.setText(unicode(preset.name))
        else:
            self.treeLayer.uncheckAllLayers()
            self.treeLayer.setEnabled(False)
            self.presetParamName.setText("-")

    def _clickedApplyPresetEdit(self):
        groups = self.treePresets.getSelectedGroups()
        txt = self.presetParamName.text()
        optionIndex = self.cbOptionPreset.currentIndex()
        if(len(groups) == 1):
            self.treeLayer.setEnabled(False)
            optionPreset = self.cbOptionPreset.itemData(optionIndex)
            groups[0].edit(name=txt,optionPreset=optionPreset.identifier)            
        else:
            selectedPresets = self.treePresets.getSelectedPresets()
            for preset in selectedPresets:
                preset.edit(name=txt)
        self.refreshTool()

    def _clickedApplyLayerSelection(self):
        presets = self.treePresets.getSelectedPresets()
        if (len(presets) == 1):
            checkedLayers = self.treeLayer.getCheckedLayerNames()
            self.applyLayerSelectionToPreset(presets[0], checkedLayers)

    def applyLayerSelectionToPreset(self, preset, layerNames):
        preset.edit(layerNames=layerNames)
        self.btnApplyPresetLayer.setText("Apply")
        self.treeLayer.isEdited = False

    def _selectionChangedLOD(self):
        selected = self.treeLODs.getSelectedRootList()
        lodValue = None
        flattenValue = None
        if(len(selected) == 1):
            lodValue = rt.getUserProp(selected[0], constants.PROP_LOD_VALUE)
            if(lodValue is not None):
                self.lodValue.setText(str(lodValue))
            else:
                self.lodValue.setText("-")
            flattenValue = rt.getUserProp(selected[0], constants.PROP_FLATTEN)
            if(flattenValue is not None):
                self.flattenComboBox.setCurrentIndex(0 if flattenValue else 1)
            else:
                self.flattenComboBox.setCurrentIndex(2)
            keepInstances = rt.getUserProp(selected[0], constants.PROP_KEEP_INSTANCES)
            if (keepInstances is not None):
                self.cbKeepInstances.setCheckState(Qt.Checked if keepInstances else Qt.Unchecked)
            else:
                self.cbKeepInstances.setCheckState(Qt.Unchecked)
        else:
            self.flattenComboBox.setCurrentIndex(2)
            self.lodValue.setText("-")
            self.cbKeepInstances.setCheckState(Qt.PartiallyChecked)


    def _clickedSetLODValues(self):
        lods = self.treeLODs.getSelectedRootList()
        for lod in lods:
            lodValueChoice = self.lodValue.text()
            if(lodValueChoice != "-"):
                validValue = qtUtils.validateFloatLineEdit(lodValueChoice)
                if(validValue):
                    userprop.setUserProp(
                        lod, constants.PROP_LOD_VALUE, validValue)
            flattenChoice = self.flattenComboBox.currentIndex()
            if(flattenChoice != 2):
                flatten = True if flattenChoice == 0 else False
                userprop.setUserProp(lod, constants.PROP_FLATTEN, flatten)
                
            keepInstances = self.cbKeepInstances.checkState()
            if (keepInstances != Qt.PartiallyChecked):
                keepInst = True if keepInstances == Qt.Checked else False
                userprop.setUserProp(lod, constants.PROP_KEEP_INSTANCES, keepInst)
                
        self.refreshTool()

    def _clickedExportTicked(self):
        currentTree = self.getCurrentTree()
        if(currentTree == self.treeLODs):
            selected = self.getCurrentlyCheckedRootList()
            self.sendToExporter(selected)
        if (currentTree == self.treePresets):
            selected = self.treePresets.getCheckedPresetsWithOption()
            self.sendPresetsWithOptionsToExporter(selected)

    def _clickedExportSelected(self):
        currentTree = self.getCurrentTree()
        if(currentTree == self.treeLODs):
            selected = self.getCurrentlySelectedRootList()
            self.sendToExporter(selected)
        elif (currentTree == self.treePresets):
            #presets = self.treePresets.getSelectedPresetsAndGroupsContent()
            presetsAndOptions = self.treePresets.getSelectedPresetsAndGroupsContentWithOption()
            self.sendPresetsWithOptionsToExporter(presetsAndOptions)
            #self.sendPresetsToExporter(presets)

    def _clickedAddExport(self):
        selected = sceneUtils.getSelectedObjects()
        exporter.addExportPathToObjects(selected)
        self.refreshTool()

    def _clickedRemoveExport(self):
        selected = sceneUtils.getSelectedObjects()
        exporter.removeExportPathToObjects(selected)
        self.refreshTool()

    def _clickedExportAll(self):
        currentTree = self.getCurrentTree()
        if(currentTree == self.treeLODs):
            fullList = self.getCurrentFullList()
            self.sendToExporter(fullList)
        elif (currentTree == self.treePresets):
            fullList = self.treePresets.getAllPresetsListWithOption()
            self.sendPresetsWithOptionsToExporter(fullList)

    def refreshTool(self):
        tree = self.getCurrentTree()
        if(tree == self.treePresets):
            self.treeLayer.refreshTree()
        tree.refreshTree()
        self._refreshOptionPreset()

    def getCurrentTree(self):
        currentTab = self.tabWidget.currentIndex()
        if (currentTab == 0):
            return self.treeLODs
        if (currentTab == 1):
            return self.treePresets
        if (currentTab == 2):
            return self.treeAnimation

    def getCurrentFullList(self):
        fullList = []
        tree = self.getCurrentTree()
        if(tree):
            fullList = tree.getAllRootsList()
        return fullList

    def getCurrentlySelectedRootList(self):
        selected = []
        tree = self.getCurrentTree()
        if(tree):
            selected = tree.getSelectedRootList()
        return selected

    def getCurrentlyCheckedRootList(self):
        selected = []
        tree = self.getCurrentTree()
        if(tree):
            selected = tree.getCheckedRootList()
        return selected

    def conformSceneLayersToLODView(self):
        if(self.getCurrentTree() != self.treeLODs):
            return
        if(not qtUtils.popup_Yes_No(
            title="Conform",
            text="""Conforming the scene layers to the LOD View will destroy all your layers and create a hierarchy of layers reflecting the LOD View object list. It will put all the other objects in the default layer. This is optional.\n
            Are you really sure you want to do this ?""")):
            return
        sceneUtils.conformSceneLayersToTemplate(self.treeLODs._baseNameDict)


    def sendToExporter(self, objects):
        count = len(objects)
        log = ""
        optionPreset = self.cbObjectOptionPreset.itemData(self.cbObjectOptionPreset.currentIndex())
        if(count > 0):
            exporter.exportObjects(objects, optionPreset)

    def sendPresetsWithOptionsToExporter(self, presetsAndOptions):
        '''
        in : presetsAndOptions = list(tuple(PresetObject,OptionPresetObject))
        '''
        count = len(presetsAndOptions)
        if(count > 0):
            exporter.exportPresetsAndOptions(presetsAndOptions)

################################
##### ROOT DEBUG FUNCTION ######
################################


def _printRootNodeProperties():
    rootNode = sceneUtils.getSceneRootNode()
    print(userprop.getUserPropBuffer(rootNode))


def _cleanupProp(prop):
    rootNode = sceneUtils.getSceneRootNode()
    userprop.removeUserProp(rootNode, prop)


def _cleanupRootNodeProperties():
    rootNode = sceneUtils.getSceneRootNode()
    userprop.setUserPropBuffer(rootNode, "")  # CLEANUP ROOT NODE PROPERTIES
    print("Root node user properties wiped")
################################
###### OPENING PROCEDURES ######
################################


def updateObsoleteExportPath():
    log = ""
    roots = sceneUtils.getAllRoots(sceneUtils.getAllObjects())
    for r in roots:
        oldPath = userprop.getUserProp(r, constants.PROP_OLD_EXPORT_PATH)
        newPath = userprop.getUserProp(r, constants.PROP_EXPORT_PATH)
        if oldPath is not None and newPath is None:
            newPath = utility.convertRelativePathToAbsolute(
                oldPath, rt.maxFilePath)
            newPath = utility.convertAbsolutePathToRelative(
                newPath, rt.pathConfig.getCurrentProjectFolder())
            userprop.setUserProp(r, constants.PROP_EXPORT_PATH, newPath)
            log += "{0}\n".format(r.name)
    return log


def writeDefaultBabylonParametersInRootNode():
    sceneRoot = sceneUtils.getSceneRootNode()
    for prop in BabylonPYMXS.propertyToDefault.keys():
        value = userprop.getUserProp(
            sceneRoot, prop, BabylonPYMXS.propertyToDefault[prop])
        userprop.setUserProp(sceneRoot, prop, value)


def checkSavedMaxFilePath():  # UNUSED
    sceneRoot = sceneUtils.getSceneRootNode()
    if rt.maxFilePath == "" or rt.maxFilePath is None:
        qtUtils.popup(title="Scene File is not saved.",
                      text="You need to save your Max scene to use the exporter.")
        return False
    savedFilePath = userprop.getUserProp(
        sceneRoot, constants.PROP_SAVED_MAXFILE_PATH)
    if (savedFilePath is None):
        userprop.setUserProp(
            sceneRoot, constants.PROP_SAVED_MAXFILE_PATH, rt.maxFilePath)
        return True
    else:
        if (savedFilePath != rt.maxFilePath):
            qtUtils.popup(
                title="Max File path changed",
                text="The scene .max file path changed since last time you used the Multi-Exporter.\n\n"
                "If you changed the path of your Max file please make sure all the export path in the Multi-Exporter are still correct.\n\n"
                "NOTE : This can be caused by having different workspaces working on the same file, "
                "it will not be a problem if the .max file didn't change relative to the project.\n\n"
                "If you didn't change the Max file path please ignore this message."
            )
            userprop.setUserProp(
                sceneRoot, constants.PROP_SAVED_MAXFILE_PATH, rt.maxFilePath)
            return True
        else:
            return True

multiExporter = None
def run():
    global multiExporter
    # Some babylon export parameters are needed
    writeDefaultBabylonParametersInRootNode()
    log = updateObsoleteExportPath()
    if log != "":
        qtUtils.popup_scroll(
            title="Updated Export Path",
            text="Update export path property keyword of following objects : {0}".format(
                log)
        )

    BabylonPYMXS.initializeBabylonExport()
    multiExporter = MainWindow()
    multiExporter.show()


# _cleanupProp("fs_export_preset_a8e403c3-aac2-4bc9-b99b-8faac5cd90b5")
# _cleanupProp("fs_export_preset_32756c41-2f78-4a7c-ae6e-4326f8e75045")
# _cleanupProp("flightsim_export_preset")
# _cleanupProp("flightsim_export_preset_group")
#_cleanupRootNodeProperties()
_printRootNodeProperties()
"""
Provides a UI to export multiple flight sim object type quickly

run() will create the window and connect it to max. 
"""

import os
import re
import sys
import uuid

from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from maxsdk.globals import *
import BabylonPYMXS

from MultiExporter import optionsMenu, presetUtils,treeView,constants,exporter
import MultiExporter.ui.mainwindow_ui as mainWindowUI

from maxsdk import dialog as sdkdialog
from maxsdk import layer
from maxsdk import perforce as sdkperforce
from maxsdk import qtUtils, sceneUtils, userprop, utility
from pymxs import runtime as rt


class MainWindow(QWidget, mainWindowUI.Ui_MultiExporter):
    def __init__(self):
        QWidget.__init__(self)
        self.setupUi(self)
        self.optionsMenuWindow = None
        # buttons
        self.btnAddExport.pressed.connect(lambda: self._clickedAddExport())
        self.btnRemoveExport.pressed.connect(
            lambda: self._clickedRemoveExport())
        self.btnRefresh.pressed.connect(lambda: self.refreshTool())
        font = QFont()
        font.setPointSize(32)
        font.setWeight(75)
        font.setUnderline(False)
        font.setBold(False)
        self.btnRefresh.setFont(font)
        self.btnRefresh.setText(u"\U0001F5D8")
        self.tabWidget.currentChanged.connect(lambda: self._changedTab())
        self.btnConformLayers.pressed.connect(
            lambda: self._clickedConformLayers())
        self.btnAddPreset.pressed.connect(lambda: self._clickedAddPreset())
        self.btnRemovePreset.pressed.connect(lambda: self._clickedRemovePreset())
        self.btnDuplicatePreset.pressed.connect(self._clickedDuplicatePreset)
        self.btnApplyPresetLayer.pressed.connect(lambda: self._clickedApplyLayerSelection())
        self.btnEditPresetPath.pressed.connect(lambda: self._clickedEditPresetPath())
        self.btnAddGroup.pressed.connect(lambda: self._clickedAddPresetGroup())
        self.btnApplyPresetEdit.pressed.connect(lambda: self._clickedApplyPresetEdit())
        
        self.presetParamName.returnPressed.connect(lambda: self._clickedApplyPresetEdit())
        # export
        self.btnExportSelected.pressed.connect(
            lambda: self._clickedExportSelected())
        self.btnExportAll.pressed.connect(lambda: self._clickedExportAll())
        self.btnExportTicked.pressed.connect(
            lambda: self._clickedExportTicked())
        self.btnOpenExportFolder.pressed.connect(
            lambda: self._clickedOpenExportFolder())
        # lod view
        self.btnSetLODValues.pressed.connect(
            lambda: self._clickedSetLODValues())
        self.btnGenerateXML.pressed.connect(lambda: self._clickedGenerateXML())
        self.btnOptions.pressed.connect(lambda: self._openOptionsMenu())
        

        # LOD VIEW TREE CREATION
        self.verticalLayout_4.removeWidget(self.treeLODs)
        self.treeLODs.setHidden(True)
        self.treeLODs = treeView.TreeViewCategory(self.tab_3)
        self.treeLODs.setAlternatingRowColors(True)
        self.treeLODs.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.treeLODs.setIndentation(20)
        self.treeLODs.setObjectName("treeLODs")
        self.treeLODs.setColumnWidth(0, 450)
        self.treeLODs.setColumnWidth(1, 40)        
        self.treeLODs.setColumnWidth(2, 40)
        self.treeLODs.setColumnWidth(3, 40)
        self.treeLODs.setSortingEnabled(True)
        self.treeLODs.sortItems(0, Qt.SortOrder.AscendingOrder)
        self.treeLODs.header().setDefaultSectionSize(80)
        self.treeLODs.headerItem().setText(0, QApplication.translate("MultiExporter", "         Hierarchy", None, -1))
        self.treeLODs.headerItem().setText(1, QApplication.translate("MultiExporter", "LOD value", None, -1))
        self.treeLODs.headerItem().setText(2, QApplication.translate("MultiExporter", "Flatten", None, -1))
        self.treeLODs.headerItem().setText(3, QApplication.translate("MultiExporter", "Keep Instances", None, -1))
        self.treeLODs.headerItem().setText(4, QApplication.translate("MultiExporter", "Path", None, -1))
        self.verticalLayout_4.insertWidget(1, self.treeLODs)
        self.checkBoxLODModifier = qtUtils.createCheckBox(qtWidget=self.treeLODs)
        self.treeLODs.setGlobalCheckBox(self.checkBoxLODModifier)
        self.treeLODs.itemSelectionChanged.connect(lambda: self._selectionChangedLOD())
        self.cbObjectOptionPreset.setHidden(True)
        self.cbObjectOptionPreset = optionsMenu.ComboBoxOptionPreset(None, self.tab_3)
        self.cbObjectOptionPreset.setObjectName("cbObjectOptionPreset")
        self.cbObjectOptionPreset.setEditable(False)
        self.cbObjectOptionPreset.setMaximumWidth(130)
        self.cbObjectOptionPreset.setMinimumWidth(130)
        
        self.horizontalLayout_6.insertWidget(12,self.cbObjectOptionPreset)

        # PRESET VIEW TREE CREATION
        self.verticalLayout_3.removeWidget(self.treePresets)
        self.treePresets.setHidden(True)
        self.treePresets = treeView.TreeViewPreset(self.verticalLayoutWidget)
        self.treePresets.setEnabled(True)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.treePresets.sizePolicy().hasHeightForWidth())
        self.treePresets.setSizePolicy(sizePolicy)
        self.treePresets.setDragEnabled(True)
        self.treePresets.setDragDropMode(QAbstractItemView.DragDrop)
        self.treePresets.setDefaultDropAction(Qt.MoveAction)
        self.treePresets.setAlternatingRowColors(True)
        self.treePresets.setSortingEnabled(True)
        self.treePresets.sortItems(0, Qt.SortOrder.AscendingOrder)
        self.treePresets.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.treePresets.setObjectName("treePresets")
        self.treePresets.header().setDefaultSectionSize(40)
        self.treePresets.headerItem().setText(0, QApplication.translate("MultiExporter", "         Preset", None, -1))
        self.treePresets.headerItem().setText(1, QApplication.translate("MultiExporter", "Path", None, -1))
        self.verticalLayout_3.insertWidget(0, self.treePresets)
        self.treePresets.itemSelectionChanged.connect(lambda: self._selectionChangedPreset())
        self.cbOptionPreset.setHidden(True)
        self.cbOptionPreset = optionsMenu.ComboBoxOptionPreset(None,self.verticalLayoutWidget)
        self.cbOptionPreset.setObjectName("cbOptionPreset")
        self.cbOptionPreset.setEditable(False)
        self.cbOptionPreset.setMaximumWidth(130)
        self.cbOptionPreset.setMinimumWidth(130)
        self.horizontalLayout_8.insertWidget(4,self.cbOptionPreset)
        self.cbOptionPreset.activated.connect(self._clickedApplyPresetEdit)

        # LAYER VIEW TREE CREATION
        self.treeLayer.setHidden(True)
        self.verticalLayout_7.removeWidget(self.treeLayer)
        self.treeLayer = treeView.TreeViewLayer(self.verticalLayoutWidget_2)
        self.treeLayer.setAlternatingRowColors(True)
        self.treeLayer.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.treeLayer.setSortingEnabled(True)
        self.treeLayer.sortItems(0, Qt.SortOrder.AscendingOrder)
        self.treeLayer.setObjectName("treeLayer")
        self.treeLayer.headerItem().setText(0, QApplication.translate("MultiExporter", "         Layers", None, -1))
        self.verticalLayout_7.insertWidget(0, self.treeLayer)
        self.checkBoxLayerModifier = qtUtils.createCheckBox(qtWidget=self.treeLayer)
        self.treeLayer.setGlobalCheckBox(self.checkBoxLayerModifier)
        self.checkBoxPresetModifier = qtUtils.createCheckBox(qtWidget=self.treePresets)
        self.treePresets.setGlobalCheckBox(self.checkBoxPresetModifier)
        self.treeLayer.itemChanged.connect(lambda: self._changedLayerItem())
        self.treePresets.hasChanged.connect(lambda: self._droppedPresetWidget())

        self.btnLayerExpandAll.pressed.connect(self.treeLayer.expandAll)
        self.btnLayerCollapseAll.pressed.connect(self.treeLayer.collapseAll)
        
        # FILTER
        self.cbVisibleOnly.stateChanged.connect(lambda: self._changeCheckboxVisibility())
        self.cbIncludeLods.stateChanged.connect(lambda: self._changeCheckboxLODs())
        self.cbExportableOnly.stateChanged.connect(lambda: self._changeCheckboxExportable())

        # CREATE TREES AND INITIALIZE DATA
        self._changeCheckboxExportable()
        self._changeCheckboxLODs()
        self._changeCheckboxVisibility()
        self.lastEditedPreset = None
        self.treePresets.createTree()
        self.treeLODs.createTree()
        self.treeLayer.createTree()
        self._selectionChangedPreset()
        self._changedTab()
        self._refreshOptionPreset()

    def contextMenuEvent(self, event):
        r = self.tabWidget.geometry()
        if(r.contains(event.pos())):
            menu = QMenu(self)
            isLodView = self.getCurrentTree() == self.treeLODs
            isPresetView = self.getCurrentTree() == self.treePresets
            exportAction = menu.addAction("Export Selected")
            if(isLodView):
                generateXML = menu.addAction("Generate XML")
            if (isPresetView):
                rename = menu.addAction("Rename")
                addPreset = menu.addAction("Add Preset")
                addGroup = menu.addAction("Add Group")
                remove = menu.addAction("Remove Selected")
            openFolder = menu.addAction("Open in Explorer")
            action = menu.exec_(self.mapToGlobal(event.pos()))
            if(isLodView):
                if action == generateXML:
                    self._clickedGenerateXML()
            if (isPresetView):
                if action == rename:
                    self.treePresets.startEditingSelectedItem()
                if action == addPreset:
                    self._clickedAddPreset()
                if action == addGroup:
                    self._clickedAddPresetGroup()
                if action == remove:
                    self._clickedRemovePreset()
            if action == exportAction:
                self._clickedExportSelected()
            if action == openFolder:
                self._clickedOpenExportFolder()

    def _refreshOptionPreset(self):
        self.cbOptionPreset.refresh()
        self.cbObjectOptionPreset.refresh()


    def _openOptionsMenu(self):
        if (self.optionsMenuWindow == None):
            self.optionsMenuWindow = optionsMenu.run()
            self.optionsMenuWindow.onClosed.connect(
                lambda: self._closeOptionsMenu())
            self.optionsMenuWindow.onModifiedData.connect(lambda : self._refreshOptionPreset())
        else:
            self.optionsMenuWindow.activateWindow()

    def _closeOptionsMenu(self):
        self.optionsMenuWindow = None

    @Slot()
    def _droppedPresetWidget(self):
        self.refreshTool()

    def _clickedConformLayers(self):
        self.conformSceneLayersToLODView()

    def _clickedGenerateXML(self):
        categories = self.treeLODs.getSelectedCategory()
        log = ""
        count = len(categories)
        i = 0
        if count > 0:
            self.progressBar.setRange(0, count)
            self.progressBar.setValue(0)
            for category in categories:
                objects = self.treeLODs._baseNameDict[category]
                objects = sceneUtils.sortObjectsByLODLevels(objects)
                metadataPath = exporter.getMetadataPath(objects[0])
                if (metadataPath is None or metadataPath == ".xml"):
                    log += "\nERROR : No path on {0}. Skipping this XML file.".format(
                        objects[0].name)
                else:
                    log += exporter.createLODMetadata(metadataPath, objects)
                i += 1
                self.progressBar.setValue(i)
            if (log != ""):
                print(log)
                qtUtils.popup_scroll(title="XML Generation Ouput", text=log)

    def _clickedAddPresetGroup(self):
        newGroup = presetUtils.createNewGroup()
        presets = self.treePresets.getSelectedPresets()
        if len(presets) > 0:
            for preset in presets:
                preset.edit(group=newGroup.identifier)
        self.refreshTool()
        self.treePresets.startEditingItemWithGroupID(newGroup.identifier)

    def _clickedAddPreset(self):
        groups = self.treePresets.getSelectedGroups()
        groupID = None
        if (len(groups) > 0):
            groupID = groups[0].identifier
        filePath = presetUtils.askForNewPath("Create New Preset")
        if(filePath != None):
            presetName = os.path.split(filePath)[1]
            presetName = os.path.splitext(presetName)[0]
            presetUtils.createNewPreset(
                presetName, group=groupID, filePath=filePath)
            self.refreshTool()

    def _clickedRemovePreset(self):
        groups = self.treePresets.getSelectedGroups()
        presets = self.treePresets.getSelectedPresets()
        presetUtils.confirmAndRemove(presets=presets, groups=groups)
        self.refreshTool()
        
    def _clickedDuplicatePreset(self):
        groups = self.treePresets.getSelectedGroups()
        presets = self.treePresets.getSelectedPresets()
        groupTransfer = dict()
        for group in groups:
            oldId = group.identifier
            newGroup = presetUtils.createNewGroup(groupName=group.name, optionPreset=group.optionPreset)
            newId = newGroup.identifier
            groupTransfer[oldId] = newId
        for preset in presets:            
            targetGroup = preset.group
            if groupTransfer.has_key(targetGroup):
                targetGroup = groupTransfer[targetGroup] 
            presetUtils.createNewPreset(labelName=preset.name, group=targetGroup, filePath=preset.path, layerNames=preset.layerNames)
            
        self.refreshTool()



    def _changedTab(self):
        currentTab = self.tabWidget.currentIndex()
        isLODView = currentTab == 0
        isPresetView = currentTab == 1
        self.btnGenerateXML.setEnabled(isLODView)
        self.btnAddExport.setEnabled(isLODView)
        self.btnRemoveExport.setEnabled(isLODView)
        self.refreshTool()

    def _clickedOpenExportFolder(self):
        currentTree = self.getCurrentTree()
        exportPath = None
        if(currentTree == self.treeLODs):
            selected = self.getCurrentlySelectedRootList()
            if(len(selected) > 0):
                exportPath = exporter.getAbsoluteExportPath(selected[0])
        elif (currentTree == self.treePresets):
            selected = self.treePresets.getSelectedPresets()
            if (len(selected) > 0):
                exportPath = presetUtils.getAbsoluteExportPath(selected[0])
        if exportPath is not None:
            try:
                exportPath = os.path.split(exportPath)[0]
                os.startfile(exportPath)
            except WindowsError as err:
                qtUtils.popup(title="WindowsError", text=err.strerror)

    def _changeCheckboxExportable(self):
        state = self.cbExportableOnly.checkState() == Qt.Checked
        self.treeLODs._showOnlyExportable = state
        self.treeLayer._showOnlyExportable = state
        self.refreshTool()

    def _changeCheckboxLODs(self):
        state = self.cbIncludeLods.checkState() == Qt.Checked
        self.treeLODs._showOnlyLODs = state
        self.treeLayer._showOnlyLODs = state
        self.refreshTool()

    def _changeCheckboxVisibility(self):
        state = self.cbVisibleOnly.checkState() == Qt.Checked
        self.treeLODs._showOnlyVisible = state
        self.treeLayer._showOnlyVisible = state
        self.refreshTool()

    def _clickedEditPresetPath(self):
        selected = self.treePresets.getSelectedPresets()
        presetUtils.addExportPathToPresets(selected)
        self.refreshTool()

    def _changedLayerItem(self):
        selected = self.treePresets.getSelectedPresets()
        if (len(selected) == 1):
            self.lastEditedPreset = selected[0]
            self.treeLayer.isEdited = True
            self.btnApplyPresetLayer.setText("Apply*")

    def _selectionChangedPreset(self):
        groups = self.treePresets.getSelectedGroups()
        if (self.treeLayer.isEdited):
            if(self.lastEditedPreset):
                if (qtUtils.popup_Yes_No(
                        title="Apply Unsaved Changes ?",
                        text="You have unsaved changes on a preset, do you want to apply them now ?")
                    ):
                    layerSelection = self.treeLayer.getCheckedLayerNames()
                    self.applyLayerSelectionToPreset(
                        self.lastEditedPreset, layerSelection)
        if (len(groups) == 1):
            self.treeLayer.setEnabled(False)
            self.presetParamName.setText(groups[0].name)
            optionPresetId = self.cbOptionPreset.getOptionPresetIndexByIdentifier(groups[0].optionPreset)
            if optionPresetId is not None:                
                self.cbOptionPreset.setCurrentIndex(optionPresetId)
            else:
                self.cbOptionPreset.setCurrentIndex(0)
            self.treeLayer.uncheckAllLayers()
            return
        presets = self.treePresets.getSelectedPresets()
        if (len(presets) == 1):
            self.treeLayer.setEnabled(True)
            preset = presets[0]
            layerNames = preset.layerNames
            self.treeLayer.intializeCheckLayers(layerNames)
            self.btnApplyPresetLayer.setText("Apply")
            self.presetParamName.setText(unicode(preset.name))
        else:
            self.treeLayer.uncheckAllLayers()
            self.treeLayer.setEnabled(False)
            self.presetParamName.setText("-")

    def _clickedApplyPresetEdit(self):
        groups = self.treePresets.getSelectedGroups()
        txt = self.presetParamName.text()
        optionIndex = self.cbOptionPreset.currentIndex()
        if(len(groups) == 1):
            self.treeLayer.setEnabled(False)
            optionPreset = self.cbOptionPreset.itemData(optionIndex)
            groups[0].edit(name=txt,optionPreset=optionPreset.identifier)            
        else:
            selectedPresets = self.treePresets.getSelectedPresets()
            for preset in selectedPresets:
                preset.edit(name=txt)
        self.refreshTool()

    def _clickedApplyLayerSelection(self):
        presets = self.treePresets.getSelectedPresets()
        if (len(presets) == 1):
            checkedLayers = self.treeLayer.getCheckedLayerNames()
            self.applyLayerSelectionToPreset(presets[0], checkedLayers)

    def applyLayerSelectionToPreset(self, preset, layerNames):
        preset.edit(layerNames=layerNames)
        self.btnApplyPresetLayer.setText("Apply")
        self.treeLayer.isEdited = False

    def _selectionChangedLOD(self):
        selected = self.treeLODs.getSelectedRootList()
        lodValue = None
        flattenValue = None
        if(len(selected) == 1):
            lodValue = rt.getUserProp(selected[0], constants.PROP_LOD_VALUE)
            if(lodValue is not None):
                self.lodValue.setText(str(lodValue))
            else:
                self.lodValue.setText("-")
            flattenValue = rt.getUserProp(selected[0], constants.PROP_FLATTEN)
            if(flattenValue is not None):
                self.flattenComboBox.setCurrentIndex(0 if flattenValue else 1)
            else:
                self.flattenComboBox.setCurrentIndex(2)
            keepInstances = rt.getUserProp(selected[0], constants.PROP_KEEP_INSTANCES)
            if (keepInstances is not None):
                self.cbKeepInstances.setCheckState(Qt.Checked if keepInstances else Qt.Unchecked)
            else:
                self.cbKeepInstances.setCheckState(Qt.Unchecked)
        else:
            self.flattenComboBox.setCurrentIndex(2)
            self.lodValue.setText("-")
            self.cbKeepInstances.setCheckState(Qt.PartiallyChecked)


    def _clickedSetLODValues(self):
        lods = self.treeLODs.getSelectedRootList()
        for lod in lods:
            lodValueChoice = self.lodValue.text()
            if(lodValueChoice != "-"):
                validValue = qtUtils.validateFloatLineEdit(lodValueChoice)
                if(validValue):
                    userprop.setUserProp(
                        lod, constants.PROP_LOD_VALUE, validValue)
            flattenChoice = self.flattenComboBox.currentIndex()
            if(flattenChoice != 2):
                flatten = True if flattenChoice == 0 else False
                userprop.setUserProp(lod, constants.PROP_FLATTEN, flatten)
                
            keepInstances = self.cbKeepInstances.checkState()
            if (keepInstances != Qt.PartiallyChecked):
                keepInst = True if keepInstances == Qt.Checked else False
                userprop.setUserProp(lod, constants.PROP_KEEP_INSTANCES, keepInst)
                
        self.refreshTool()

    def _clickedExportTicked(self):
        currentTree = self.getCurrentTree()
        if(currentTree == self.treeLODs):
            selected = self.getCurrentlyCheckedRootList()
            self.sendToExporter(selected)
        if (currentTree == self.treePresets):
            selected = self.treePresets.getCheckedPresetsWithOption()
            self.sendPresetsWithOptionsToExporter(selected)

    def _clickedExportSelected(self):
        currentTree = self.getCurrentTree()
        if(currentTree == self.treeLODs):
            selected = self.getCurrentlySelectedRootList()
            self.sendToExporter(selected)
        elif (currentTree == self.treePresets):
            #presets = self.treePresets.getSelectedPresetsAndGroupsContent()
            presetsAndOptions = self.treePresets.getSelectedPresetsAndGroupsContentWithOption()
            self.sendPresetsWithOptionsToExporter(presetsAndOptions)
            #self.sendPresetsToExporter(presets)

    def _clickedAddExport(self):
        selected = sceneUtils.getSelectedObjects()
        exporter.addExportPathToObjects(selected)
        self.refreshTool()

    def _clickedRemoveExport(self):
        selected = sceneUtils.getSelectedObjects()
        exporter.removeExportPathToObjects(selected)
        self.refreshTool()

    def _clickedExportAll(self):
        currentTree = self.getCurrentTree()
        if(currentTree == self.treeLODs):
            fullList = self.getCurrentFullList()
            self.sendToExporter(fullList)
        elif (currentTree == self.treePresets):
            fullList = self.treePresets.getAllPresetsListWithOption()
            self.sendPresetsWithOptionsToExporter(fullList)

    def refreshTool(self):
        tree = self.getCurrentTree()
        if(tree == self.treePresets):
            self.treeLayer.refreshTree()
        tree.refreshTree()
        self._refreshOptionPreset()

    def getCurrentTree(self):
        currentTab = self.tabWidget.currentIndex()
        if (currentTab == 0):
            return self.treeLODs
        if (currentTab == 1):
            return self.treePresets
        if (currentTab == 2):
            return self.treeAnimation

    def getCurrentFullList(self):
        fullList = []
        tree = self.getCurrentTree()
        if(tree):
            fullList = tree.getAllRootsList()
        return fullList

    def getCurrentlySelectedRootList(self):
        selected = []
        tree = self.getCurrentTree()
        if(tree):
            selected = tree.getSelectedRootList()
        return selected

    def getCurrentlyCheckedRootList(self):
        selected = []
        tree = self.getCurrentTree()
        if(tree):
            selected = tree.getCheckedRootList()
        return selected

    def conformSceneLayersToLODView(self):
        if(self.getCurrentTree() != self.treeLODs):
            return
        if(not qtUtils.popup_Yes_No(
            title="Conform",
            text="""Conforming the scene layers to the LOD View will destroy all your layers and create a hierarchy of layers reflecting the LOD View object list. It will put all the other objects in the default layer. This is optional.\n
            Are you really sure you want to do this ?""")):
            return
        sceneUtils.conformSceneLayersToTemplate(self.treeLODs._baseNameDict)


    def sendToExporter(self, objects):
        count = len(objects)
        log = ""
        optionPreset = self.cbObjectOptionPreset.itemData(self.cbObjectOptionPreset.currentIndex())
        if(count > 0):
            exporter.exportObjects(objects, optionPreset)

    def sendPresetsWithOptionsToExporter(self, presetsAndOptions):
        '''
        in : presetsAndOptions = list(tuple(PresetObject,OptionPresetObject))
        '''
        count = len(presetsAndOptions)
        if(count > 0):
            exporter.exportPresetsAndOptions(presetsAndOptions)

################################
##### ROOT DEBUG FUNCTION ######
################################


def _printRootNodeProperties():
    rootNode = sceneUtils.getSceneRootNode()
    print(userprop.getUserPropBuffer(rootNode))


def _cleanupProp(prop):
    rootNode = sceneUtils.getSceneRootNode()
    userprop.removeUserProp(rootNode, prop)


def _cleanupRootNodeProperties():
    rootNode = sceneUtils.getSceneRootNode()
    userprop.setUserPropBuffer(rootNode, "")  # CLEANUP ROOT NODE PROPERTIES
    print("Root node user properties wiped")
################################
###### OPENING PROCEDURES ######
################################


def updateObsoleteExportPath():
    log = ""
    roots = sceneUtils.getAllRoots(sceneUtils.getAllObjects())
    for r in roots:
        oldPath = userprop.getUserProp(r, constants.PROP_OLD_EXPORT_PATH)
        newPath = userprop.getUserProp(r, constants.PROP_EXPORT_PATH)
        if oldPath is not None and newPath is None:
            newPath = utility.convertRelativePathToAbsolute(
                oldPath, rt.maxFilePath)
            newPath = utility.convertAbsolutePathToRelative(
                newPath, rt.pathConfig.getCurrentProjectFolder())
            userprop.setUserProp(r, constants.PROP_EXPORT_PATH, newPath)
            log += "{0}\n".format(r.name)
    return log


def writeDefaultBabylonParametersInRootNode():
    sceneRoot = sceneUtils.getSceneRootNode()
    for prop in BabylonPYMXS.propertyToDefault.keys():
        value = userprop.getUserProp(
            sceneRoot, prop, BabylonPYMXS.propertyToDefault[prop])
        userprop.setUserProp(sceneRoot, prop, value)


def checkSavedMaxFilePath():  # UNUSED
    sceneRoot = sceneUtils.getSceneRootNode()
    if rt.maxFilePath == "" or rt.maxFilePath is None:
        qtUtils.popup(title="Scene File is not saved.",
                      text="You need to save your Max scene to use the exporter.")
        return False
    savedFilePath = userprop.getUserProp(
        sceneRoot, constants.PROP_SAVED_MAXFILE_PATH)
    if (savedFilePath is None):
        userprop.setUserProp(
            sceneRoot, constants.PROP_SAVED_MAXFILE_PATH, rt.maxFilePath)
        return True
    else:
        if (savedFilePath != rt.maxFilePath):
            qtUtils.popup(
                title="Max File path changed",
                text="The scene .max file path changed since last time you used the Multi-Exporter.\n\n"
                "If you changed the path of your Max file please make sure all the export path in the Multi-Exporter are still correct.\n\n"
                "NOTE : This can be caused by having different workspaces working on the same file, "
                "it will not be a problem if the .max file didn't change relative to the project.\n\n"
                "If you didn't change the Max file path please ignore this message."
            )
            userprop.setUserProp(
                sceneRoot, constants.PROP_SAVED_MAXFILE_PATH, rt.maxFilePath)
            return True
        else:
            return True

multiExporter = None
def run():
    global multiExporter
    # Some babylon export parameters are needed
    writeDefaultBabylonParametersInRootNode()
    log = updateObsoleteExportPath()
    if log != "":
        qtUtils.popup_scroll(
            title="Updated Export Path",
            text="Update export path property keyword of following objects : {0}".format(
                log)
        )

    BabylonPYMXS.initializeBabylonExport()
    multiExporter = MainWindow()
    multiExporter.show()


# _cleanupProp("fs_export_preset_a8e403c3-aac2-4bc9-b99b-8faac5cd90b5")
# _cleanupProp("fs_export_preset_32756c41-2f78-4a7c-ae6e-4326f8e75045")
# _cleanupProp("flightsim_export_preset")
# _cleanupProp("flightsim_export_preset_group")
#_cleanupRootNodeProperties()
_printRootNodeProperties()
Provides a UI to export multiple flight sim object type quickly
 
 run() will create the window and connect it to max. # buttons # export # lod view # LOD VIEW TREE CREATION # PRESET VIEW TREE CREATION # LAYER VIEW TREE CREATION # FILTER # CREATE TREES AND INITIALIZE DATA #presets = self.treePresets.getSelectedPresetsAndGroupsContent() #self.sendPresetsToExporter(presets) Conforming the scene layers to the LOD View will destroy all your layers and create a hierarchy of layers reflecting the LOD View object list. It will put all the other objects in the default layer. This is optional.\n
             Are you really sure you want to do this ? in : presetsAndOptions = list(tuple(PresetObject,OptionPresetObject)) ################################ ##### ROOT DEBUG FUNCTION ###### ################################ # CLEANUP ROOT NODE PROPERTIES ################################ ###### OPENING PROCEDURES ###### ################################ # UNUSED # Some babylon export parameters are needed # _cleanupProp("fs_export_preset_a8e403c3-aac2-4bc9-b99b-8faac5cd90b5") # _cleanupProp("fs_export_preset_32756c41-2f78-4a7c-ae6e-4326f8e75045") # _cleanupProp("flightsim_export_preset") # _cleanupProp("flightsim_export_preset_group") #_cleanupRootNodeProperties()