Example #1
0
    def __init__(self, parent=None):
        super(ShaderManager, self).__init__(parent)

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        self.setupUi(self)

        self.shadersFromFile = []
        self.displaceFromFile = []

        self.curLayer = None
        # self.listTagsWidget = tagTree(self)
        # self.tagGroup.layout().addWidget(self.listTagsWidget)
        #self.tagGroup.setVisible(0)

        self.shaderToAssign = None
        self.ABCViewerNode = {}

        self.getNode()
        self.getCache()

        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False

        self.propertyEditorWindow = QtGui.QDockWidget(self)
        self.propertyEditorWindow.setAllowedAreas(
            QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.propertyEditorWindow.setWindowTitle("Properties")
        self.propertyEditorWindow.setMinimumWidth(300)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
                           self.propertyEditorWindow)
        self.propertyType = "polymesh"
        self.propertyEditor = PropertyEditor(self, self.propertyType,
                                             self.propertyEditorWindow)
        self.propertyEditorWindow.setWidget(self.propertyEditor)

        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

        self.hierarchyWidget.setColumnWidth(0, 600)
        self.hierarchyWidget.setIconSize(QSize(22, 22))

        self.hierarchyWidget.dragEnterEvent = self.newhierarchyWidgetdragEnterEvent
        self.hierarchyWidget.dragMoveEvent = self.newhierarchyWidgetdragMoveEvent
        self.hierarchyWidget.dropEvent = self.newhierarchyWidgetDropEvent

        self.hierarchyWidget.setColumnWidth(0, 200)
        self.hierarchyWidget.setColumnWidth(1, 300)
        self.hierarchyWidget.setColumnWidth(2, 300)

        self.hierarchyWidget.setItemDelegate(treeDelegate.treeDelegate(self))

        self.updateTags()
        self.populate()

        self.curPath = ""
        self.ABCcurPath = ""

        self.hierarchyWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
        self.hierarchyWidget.itemExpanded.connect(self.requireItemExpanded)
        self.hierarchyWidget.itemCollapsed.connect(self.requireItemCollapse)
        self.hierarchyWidget.itemClicked.connect(self.itemCLicked)
        self.hierarchyWidget.itemSelectionChanged.connect(
            self.itemSelectionChanged)
        self.hierarchyWidget.itemPressed.connect(self.itemPressed)
        self.hierarchyWidget.setExpandsOnDoubleClick(False)

        self.filterShaderLineEdit.textChanged.connect(self.filterShader)

        #self.shadersList.startDrag = self.newshadersListStartDrag
        self.shadersList.itemDoubleClicked.connect(self.shaderCLicked)
        self.shadersList.mouseMoveEvent = self.newshadersListmouseMoveEvent

        self.displacementList.itemPressed.connect(self.shaderCLicked)
        self.displacementList.mouseMoveEvent = self.newdisplaceListmouseMoveEvent

        self.refreshManagerBtn.pressed.connect(self.reset)

        self.refreshShaders()

        self.getLayers()
        self.setCurrentLayer()

        self.addCBs()

        self.afterNewSceneCBId = MSceneMessage.addCallback(
            MSceneMessage.kAfterNew, self.reset)
        self.afterOpenSceneCBId = MSceneMessage.addCallback(
            MSceneMessage.kAfterOpen, self.reset)

        self.disableLayerOverrides()

        self.overrideDisps.stateChanged.connect(self.overrideDispsChanged)
        self.overrideShaders.stateChanged.connect(self.overrideShadersChanged)
        self.overrideProps.stateChanged.connect(self.overridePropsChanged)

        self.isolateCheckbox.stateChanged.connect(self.isolateCheckboxChanged)

        #Widcard management
        self.wildCardButton.pressed.connect(self.addWildCard)
        self.autoAssignButton.pressed.connect(self.autoAssign)
Example #2
0
class ShaderManager(QMainWindow, UI_ABCHierarchy.Ui_NAM):
    def __init__(self, parent=None):
        super(ShaderManager, self).__init__(parent)

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        self.setupUi(self)

        self.shadersFromFile = []
        self.displaceFromFile = []

        self.curLayer = None
        # self.listTagsWidget = tagTree(self)
        # self.tagGroup.layout().addWidget(self.listTagsWidget)
        #self.tagGroup.setVisible(0)

        self.shaderToAssign = None
        self.ABCViewerNode = {}

        self.getNode()
        self.getCache()

        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False

        self.propertyEditorWindow = QtGui.QDockWidget(self)
        self.propertyEditorWindow.setAllowedAreas(
            QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.propertyEditorWindow.setWindowTitle("Properties")
        self.propertyEditorWindow.setMinimumWidth(300)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
                           self.propertyEditorWindow)
        self.propertyType = "polymesh"
        self.propertyEditor = PropertyEditor(self, self.propertyType,
                                             self.propertyEditorWindow)
        self.propertyEditorWindow.setWidget(self.propertyEditor)

        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

        self.hierarchyWidget.setColumnWidth(0, 600)
        self.hierarchyWidget.setIconSize(QSize(22, 22))

        self.hierarchyWidget.dragEnterEvent = self.newhierarchyWidgetdragEnterEvent
        self.hierarchyWidget.dragMoveEvent = self.newhierarchyWidgetdragMoveEvent
        self.hierarchyWidget.dropEvent = self.newhierarchyWidgetDropEvent

        self.hierarchyWidget.setColumnWidth(0, 200)
        self.hierarchyWidget.setColumnWidth(1, 300)
        self.hierarchyWidget.setColumnWidth(2, 300)

        self.hierarchyWidget.setItemDelegate(treeDelegate.treeDelegate(self))

        self.updateTags()
        self.populate()

        self.curPath = ""
        self.ABCcurPath = ""

        self.hierarchyWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
        self.hierarchyWidget.itemExpanded.connect(self.requireItemExpanded)
        self.hierarchyWidget.itemCollapsed.connect(self.requireItemCollapse)
        self.hierarchyWidget.itemClicked.connect(self.itemCLicked)
        self.hierarchyWidget.itemSelectionChanged.connect(
            self.itemSelectionChanged)
        self.hierarchyWidget.itemPressed.connect(self.itemPressed)
        self.hierarchyWidget.setExpandsOnDoubleClick(False)

        self.filterShaderLineEdit.textChanged.connect(self.filterShader)

        #self.shadersList.startDrag = self.newshadersListStartDrag
        self.shadersList.itemDoubleClicked.connect(self.shaderCLicked)
        self.shadersList.mouseMoveEvent = self.newshadersListmouseMoveEvent

        self.displacementList.itemPressed.connect(self.shaderCLicked)
        self.displacementList.mouseMoveEvent = self.newdisplaceListmouseMoveEvent

        self.refreshManagerBtn.pressed.connect(self.reset)

        self.refreshShaders()

        self.getLayers()
        self.setCurrentLayer()

        self.addCBs()

        self.afterNewSceneCBId = MSceneMessage.addCallback(
            MSceneMessage.kAfterNew, self.reset)
        self.afterOpenSceneCBId = MSceneMessage.addCallback(
            MSceneMessage.kAfterOpen, self.reset)

        self.disableLayerOverrides()

        self.overrideDisps.stateChanged.connect(self.overrideDispsChanged)
        self.overrideShaders.stateChanged.connect(self.overrideShadersChanged)
        self.overrideProps.stateChanged.connect(self.overridePropsChanged)

        self.isolateCheckbox.stateChanged.connect(self.isolateCheckboxChanged)

        #Widcard management
        self.wildCardButton.pressed.connect(self.addWildCard)
        self.autoAssignButton.pressed.connect(self.autoAssign)

    def showEvent(self, event):
        self.reset()
        self.isolateCheckbox.setChecked(0)
        return QtGui.QMainWindow.showEvent(self, event)

    def hideEvent(self, event):
        self.reset()
        self.isolateCheckbox.setChecked(0)
        return QtGui.QMainWindow.hideEvent(self, event)

    def reset(self, *args, **kwargs):
        try:
            self.renderLayer.currentIndexChanged.disconnect()
        except:
            pass

        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        self.hierarchyWidget.clear()
        self.shadersList.clear()
        self.displacementList.clear()
        self.propertyEditor.resetToDefault()

        self.curPath = ""
        self.ABCcurPath = ""

        self.shadersFromFile = []
        self.displaceFromFile = []
        self.ABCViewerNode = {}
        self.curLayer = None

        self.getLayers()
        self.setCurrentLayer()

        self.shaderToAssign = None

        self.tags = {}
        self.getNode()
        self.getCache()
        self.updateTags()
        self.populate()
        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False
        self.refreshShaders()

        self.renderLayer.currentIndexChanged.connect(self.layerChanged)
        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

    def filterShader(self, text):
        '''
        Only show shaders matching this string.
        '''

        for i in range(self.shadersList.count()):
            item = self.shadersList.item(i)
            item.setHidden(0)
            if text != "" and not text.lower() in item.text().lower():
                item.setHidden(1)

        for i in range(self.displacementList.count()):
            item = self.displacementList.item(i)
            item.setHidden(0)
            if text != "" and not text.lower() in item.text().lower():
                item.setHidden(1)

    def isolateCheckboxChanged(self, state):
        ''' activate/desactive isolation'''
        if state == 0:
            for cache in self.ABCViewerNode.values():
                cache.setToPath("")

        else:
            for cache in self.ABCViewerNode.values():
                cache.setToPath(cache.getSelection())

    def overrideDispsChanged(self, state):
        result = True
        if state == 0:
            result = False

        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedDisplace(self.getLayer(), result)

        self.updateTree()

    def overrideShadersChanged(self, state):

        result = True
        if state == 0:
            result = False

        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedShader(self.getLayer(), result)

        self.updateTree()

    def overridePropsChanged(self, state):
        result = True
        if state == 0:
            result = False

        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedProperties(self.getLayer(), result)

        self.updateTree()

    def createSG(self, node):
        sg = None

        SGs = cmds.listConnections(node, d=True, s=False, type="shadingEngine")
        if not SGs:
            try:
                sg = cmds.shadingNode("shadingEngine",
                                      n="%sSG" % node,
                                      asRendering=True)
                cmds.connectAttr("%s.outColor" % node,
                                 "%s.surfaceShader" % sg,
                                 force=True)
                return sg
            except:
                print "Error creating shading group for node", node
        else:
            return SGs[0]

    def nameChangedCB(self, node, prevName, client):
        ''' Callback when a node is renamed '''

        if prevName == "" or not prevName or prevName.startswith("_"):
            return
        handle = MObjectHandle(node)
        if not handle.isValid():
            return
        mobject = handle.object()

        nodeFn = MFnDependencyNode(mobject)
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()
            if not cmds.objExists(nodeName):
                return
            if cmds.getClassification(cmds.nodeType(nodeName),
                                      satisfies="shader"):

                if cmds.nodeType(nodeName) == "displacementShader":
                    items = self.displacementList.findItems(
                        prevName, QtCore.Qt.MatchExactly)
                    for item in items:
                        item.setText(nodeName)

                    # renaming shaders in caches
                    for cache in self.ABCViewerNode.values():
                        cache.renameDisplacement(prevName, nodeName)
                    self.checkShaders()
                else:
                    items = self.shadersList.findItems(prevName,
                                                       QtCore.Qt.MatchExactly)
                    for item in items:
                        item.setText(nodeName)

            if cmds.nodeType(nodeName) == "shadingEngine":
                # renaming shaders in caches
                for cache in self.ABCViewerNode.values():
                    cache.renameShader(prevName, nodeName)

                self.checkShaders()

    def newNodeCB(self, newNode, data):
        ''' Callback when creating a new node '''
        mobject = MObjectHandle(newNode).object()
        nodeFn = MFnDependencyNode(mobject)
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()
            if cmds.getClassification(cmds.nodeType(nodeName),
                                      satisfies="shader"):
                if cmds.nodeType(nodeName) == "displacementShader":
                    icon = QtGui.QIcon()
                    icon.addFile(os.path.join(d, "../../icons/sg.xpm"),
                                 QtCore.QSize(25, 25))
                    item = QtGui.QListWidgetItem(nodeName)
                    item.setIcon(icon)
                    self.displacementList.addItem(item)
                else:
                    icon = QtGui.QIcon()
                    icon.addFile(os.path.join(d, "../../icons/sg.xpm"),
                                 QtCore.QSize(25, 25))
                    item = QtGui.QListWidgetItem(nodeName)
                    item.setIcon(icon)
                    self.shadersList.addItem(item)

    def delNodeCB(self, node, data):
        ''' Callback when a node has been deleted '''
        mobject = MObjectHandle(node).object()
        nodeFn = MFnDependencyNode(mobject)
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()

            didSomething = False

            if cmds.nodeType(nodeName) == "displacementShader":
                items = self.displacementList.findItems(
                    nodeName, QtCore.Qt.MatchExactly)
                for item in items:
                    self.displacementList.takeItem(
                        self.displacementList.row(item))

                # remove shaders from caches
                for cache in self.ABCViewerNode.values():
                    didSomething = True
                    cache.removeDisplacement(nodeName)

            else:
                items = self.shadersList.findItems(nodeName,
                                                   QtCore.Qt.MatchExactly)
                for item in items:
                    self.shadersList.takeItem(self.shadersList.row(item))

                # remove shaders from caches
                for cache in self.ABCViewerNode.values():
                    didSomething = True
                    cache.removeShader(nodeName)

            if didSomething:
                self.checkShaders()

    def shaderCLicked(self, item):
        shader = item.text()
        if shader:
            if cmds.objExists(shader):
                try:
                    conn = cmds.connectionInfo(shader + ".surfaceShader",
                                               sourceFromDestination=True)
                    if conn:
                        cmds.select(conn, r=1, ne=1)
                    else:
                        cmds.select(shader, r=1, ne=1)
                except:
                    cmds.select(shader, r=1, ne=1)

    def newshadersListmouseMoveEvent(self, event):
        self.newshadersListStartDrag(event)

    def newdisplaceListmouseMoveEvent(self, event):
        self.newdisplaceListStartDrag(event)

    def newshadersListStartDrag(self, event):
        index = self.shadersList.indexAt(event.pos())
        if not index.isValid():
            return
        selected = self.shadersList.itemFromIndex(index)

        self.shaderCLicked(selected)

        itemData = QtCore.QByteArray()
        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.WriteOnly)
        dataStream << QtCore.QByteArray(str(selected.text()))

        mimeData = QtCore.QMimeData()
        mimeData.setData("application/x-shader", itemData)
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)

        drag.setPixmap(
            self.shadersList.itemAt(event.pos()).icon().pixmap(50, 50))
        drag.setHotSpot(QtCore.QPoint(0, 0))
        drag.start(QtCore.Qt.MoveAction)

    def newdisplaceListStartDrag(self, event):
        index = self.displacementList.indexAt(event.pos())
        if not index.isValid():
            return
        selected = self.displacementList.itemFromIndex(index)

        self.shaderCLicked(selected)

        itemData = QtCore.QByteArray()
        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.WriteOnly)
        dataStream << QtCore.QByteArray(str(selected.text()))

        mimeData = QtCore.QMimeData()
        mimeData.setData("application/x-displacement", itemData)
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)

        drag.setPixmap(
            self.displacementList.itemAt(event.pos()).icon().pixmap(50, 50))
        drag.setHotSpot(QtCore.QPoint(0, 0))
        drag.start(QtCore.Qt.MoveAction)

    def newhierarchyWidgetdragEnterEvent(self, event):
        if event.mimeData().hasFormat(
                "application/x-shader") or event.mimeData().hasFormat(
                    "application/x-displacement"):
            event.accept()
        else:
            event.ignore()

    def newhierarchyWidgetdragMoveEvent(self, event):
        if event.mimeData().hasFormat(
                "application/x-shader") or event.mimeData().hasFormat(
                    "application/x-displacement"):
            event.accept()
        else:
            event.ignore()

    def newhierarchyWidgetDropEvent(self, event):
        mime = event.mimeData()
        itemData = None
        mode = 0

        if mime.hasFormat("application/x-shader"):
            mode = 0
            itemData = mime.data("application/x-shader")
        elif mime.hasFormat("application/x-displacement"):
            mode = 1
            itemData = mime.data("application/x-displacement")

        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.ReadOnly)

        shader = QtCore.QByteArray()
        dataStream >> shader

        shader = str(shader)
        items = []

        selectedItems = self.hierarchyWidget.selectedItems()

        item = self.hierarchyWidget.itemFromIndex(
            self.hierarchyWidget.indexAt(event.pos()))
        if item:
            items.append(item)

        if len(selectedItems) > 1:
            items = items + selectedItems

        for item in items:
            item.shaderToAssign = shader
            if mode == 0:
                item.assignShader()
            elif mode == 1:
                item.assignDisplacement()

        event.accept()

    def addCBs(self, event=None):
        try:
            print "adding callbacks"
            self.renderLayer.currentIndexChanged.connect(self.layerChanged)
            self.NodeNameMsgId = MNodeMessage.addNameChangedCallback(
                MObject(), self.nameChangedCB)
            self.newNodeCBMsgId = MDGMessage.addNodeAddedCallback(
                self.newNodeCB)
            self.delNodeCBMsgId = MDGMessage.addNodeRemovedCallback(
                self.delNodeCB)
            print "adding scriptjob"
            self.layerChangedJob = cmds.scriptJob(
                e=["renderLayerManagerChange", self.setCurrentLayer])
        except:
            pass

    def clearCBs(self, event=None):
        try:
            print "removing scriptjob"
            cmds.scriptJob(kill=self.layerChangedJob, force=True)
            for cache in self.ABCViewerNode.values():
                cache.setSelection("")
            print "removing callbacks"
            MMessage.removeCallback(self.newNodeCBMsgId)
            MMessage.removeCallback(self.delNodeCBMsgId)
            MNodeMessage.removeCallback(self.NodeNameMsgId)
        except:
            pass

    def closeEvent(self, event):
        event.ignore()
        self.hide()
        return

    def clearing(self):
        self.clearCBs()
        try:
            MMessage.removeCallback(self.afterNewSceneCBId)
            MMessage.removeCallback(self.afterOpenSceneCBId)
        except:
            pass

    def setCurrentLayer(self):
        try:
            curLayer = cmds.editRenderLayerGlobals(query=1,
                                                   currentRenderLayer=1)
        except:
            return
        curLayeridx = self.renderLayer.findText(curLayer)
        if curLayeridx != -1:
            self.renderLayer.setCurrentIndex(curLayeridx)
        self.curLayer = curLayer

    def layerChanged(self, index):

        self.curLayer = self.renderLayer.itemText(index)
        if self.curLayer == "defaultRenderLayer":
            self.disableLayerOverrides()
        else:
            self.enableLayerOverrides()
            for cache in self.ABCViewerNode:
                c = self.ABCViewerNode[cache]
                over = c.getLayerOverrides(self.getLayer())

                if over:
                    self.overrideProps.setChecked(over["removeProperties"])
                    self.overrideShaders.setChecked(over["removeShaders"])
                    self.overrideDisps.setChecked(over["removeDisplacements"])

        self.updateTree()
        if self.hierarchyWidget.currentItem():
            self.itemCLicked(self.hierarchyWidget.currentItem(), 0, force=True)

        # change it in maya too
        curLayer = cmds.editRenderLayerGlobals(query=1, currentRenderLayer=1)
        if curLayer != self.curLayer:
            cmds.editRenderLayerGlobals(currentRenderLayer=self.curLayer)

    def updateTree(self):
        items = []
        for i in range(self.hierarchyWidget.topLevelItemCount()):
            self.visitTree(items, self.hierarchyWidget.topLevelItem(i))

        for item in items:
            item.removeAssigns()
            item.checkShaders(self.getLayer())
            item.checkProperties(self.getLayer())

    def visitTree(self, items, treeitem):
        items.append(treeitem)
        for i in range(treeitem.childCount()):
            self.visitTree(items, treeitem.child(i))

    def enableLayerOverrides(self):
        self.overrideDisps.setEnabled(1)
        self.overrideShaders.setEnabled(1)
        self.overrideProps.setEnabled(1)

        self.overrideDisps.setChecked(0)
        self.overrideShaders.setChecked(0)
        self.overrideProps.setChecked(0)

    def disableLayerOverrides(self):
        self.overrideDisps.setEnabled(0)
        self.overrideShaders.setEnabled(0)
        self.overrideProps.setEnabled(0)

        self.overrideDisps.setChecked(0)
        self.overrideShaders.setChecked(0)
        self.overrideProps.setChecked(0)

    def getLayers(self):
        self.renderLayer.clear()
        renderLayers = []
        for layer in cmds.ls(type="renderLayer"):
            con = cmds.connectionInfo(layer + ".identification",
                                      sourceFromDestination=True)
            if con:
                if con.split(".")[0] == "renderLayerManager":
                    renderLayers.append(layer)

        self.renderLayer.addItems(renderLayers)
        idx = self.renderLayer.findText("defaultRenderLayer")
        if idx == -1:
            self.curLayer = self.renderLayer.itemText(0)
        else:
            self.curLayer = self.renderLayer.itemText(idx)
            self.renderLayer.setCurrentIndex(idx)

    def propertyChanged(self, prop):
        if self.propertyEditing:
            return
        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        propName = prop["propname"]
        default = prop["default"]
        value = prop["value"]

        if self.lastClick == 1:

            item = self.hierarchyWidget.currentItem()
            if item:
                curPath = item.getPath()
                if curPath is None:
                    return
            else:
                return

            cache = item.cache
            layer = self.getLayer()
            cache.updateOverride(propName, default, value, curPath, layer)
            self.updatePropertyColor(cache, layer, propName, curPath)

            self.checkProperties(self.getLayer(), item=item)

        elif self.lastClick == 2:
            item = self.listTagsWidget.currentItem()
            item.assignProperty(propName, default, value)

        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

    def updatePropertyColor(self, cache, layer, propName, curPath):
        cacheState = cache.getPropertyState(layer, propName, curPath)
        if cacheState == 3:
            self.propertyEditor.propertyWidgets[propName].title.setText(
                "<font color='darkRed'>%s</font>" % propName)
        if cacheState == 2:
            self.propertyEditor.propertyWidgets[propName].title.setText(
                "<font color='red'>%s</font>" % propName)
        if cacheState == 1:
            self.propertyEditor.propertyWidgets[propName].title.setText(
                "<font color='white'><i>%s</i></font>" % propName)

    def fillShaderList(self):
        self.shadersList.clear()
        shaders = cmds.ls(materials=True)
        icon = QtGui.QIcon()
        icon.addFile(os.path.join(d, "../../icons/sg.xpm"),
                     QtCore.QSize(25, 25))
        for shader in shaders:
            item = QtGui.QListWidgetItem(shader)
            item.setIcon(icon)
            self.shadersList.addItem(item)

    def fillDisplacementList(self):
        self.displacementList.clear()
        displaces = cmds.ls(type="displacementShader")
        icon = QtGui.QIcon()
        icon.addFile(os.path.join(d, "../../icons/displacement.xpm"),
                     QtCore.QSize(25, 25))
        for sg in displaces:
            item = QtGui.QListWidgetItem(sg)
            item.setIcon(icon)
            self.displacementList.addItem(item)

    def refreshShaders(self):
        self.fillShaderList()
        self.fillDisplacementList()

    def getLayer(self):
        if self.curLayer != "defaultRenderLayer":
            return self.curLayer
        return None

    def itemCLicked(self, item, col, force=False):
        self.propertyEditing = True
        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        if item.icon == 7 and self.propertyType != "points":
            self.propertyType = "points"
            self.propertyEditor.resetTo(item.itemType.lower())

        if item.icon == 9 and self.propertyType != "curves":
            self.propertyType = "curves"
            self.propertyEditor.resetTo(item.itemType.lower())

        elif item.icon == 8 and self.propertyType != item.itemType:
            self.propertyType = item.itemType
            if item.itemType == "PointLight":
                self.propertyEditor.resetTo("point_light")

            elif item.itemType == "DistantLight":
                self.propertyEditor.resetTo("distant_light")

            elif item.itemType == "SpotLight":
                self.propertyEditor.resetTo("spot_light")

            elif item.itemType == "QuadLight":
                self.propertyEditor.resetTo("quad_light")

            elif item.itemType == "PhotometricLight":
                self.propertyEditor.resetTo("photometric_light")

            elif item.itemType == "DiskLight":
                self.propertyEditor.resetTo("disk_light")

            elif item.itemType == "CylinderLight":
                self.propertyEditor.resetTo("cylinder_light")

        elif (item.icon == 1
              or item.icon == 2) and self.propertyType != "polymesh":
            self.propertyType = "polymesh"
            self.propertyEditor.resetTo("polymesh")

        self.lastClick = 1

        if self.thisTreeItem is item and force == False:
            self.propertyEditing = False
            return
        self.thisTreeItem = item

        curPath = item.getPath()
        cache = item.cache

        allSelected = []
        for item in self.hierarchyWidget.selectedItems():
            if item.isTag == False and item.isWildCard == False:
                allSelected.append(item.getPath())

        if "/" in allSelected:
            allSelected = []

        cache.setSelection(allSelected)

        if self.isolateCheckbox.checkState() == Qt.Checked:
            cache.setToPath(curPath)

        self.propertyEditor.resetToDefault()

        self.updateAttributeEditor()

        self.propertyEditing = False

    def updateAttributeEditor(self):
        ''' this will update what is inside the attribute editor (red text,....)'''

        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        for item in self.hierarchyWidget.selectedItems():
            curPath = item.getPath()
            cache = item.cache
            layer = self.getLayer()
            attributes = {}

            if layer:
                layerOverrides = cache.getAssignations().getLayerOverrides(
                    layer)
                if not layerOverrides:
                    layerOverrides = dict(removeDisplacements=False,
                                          removeProperties=False,
                                          removeShaders=False)

                if layerOverrides["removeProperties"] == False:
                    attributes = cache.getAssignations().getOverrides(
                        curPath, layer)
                else:
                    attributes = cache.getAssignations().getOverrides(
                        curPath, None)

            else:
                attributes = cache.getAssignations().getOverrides(
                    curPath, None)

            if len(attributes) > 0:
                for propname in attributes:
                    value = attributes[propname].get("override")
                    self.propertyEditor.propertyValue(
                        dict(paramname=propname, value=value))

                    if propname in self.propertyEditor.propertyWidgets:
                        self.updatePropertyColor(cache, layer, propname,
                                                 curPath)

        try:
            self.propertyEditor.propertyChanged.connect(self.propertyChanged)
        except:
            pass

    def itemPressed(self, item, col):
        self.lastClick = 1
        if QtGui.QApplication.mouseButtons() == QtCore.Qt.RightButton:
            item.pressed()

    def itemSelectionChanged(self):
        if len(self.hierarchyWidget.selectedItems()) == 0:
            for cache in self.ABCViewerNode.values():
                cache.setSelection("")

    def requireItemCollapse(self, item):
        pass

    def requireItemExpanded(self, item):
        self.expandItem(item)

    def itemDoubleClicked(self, item, column):
        '''  An item on the hierarchy is double clicked'''
        if column == 0:
            if item.isWildCard:
                if not item.protected:
                    text, ok = QtGui.QInputDialog.getText(
                        self, 'WildCard expression', 'Enter the expression:',
                        QtGui.QLineEdit.Normal, item.getPath())
                    if ok:
                        #first change the path
                        item.setExpression(text)

            else:
                self.expandItem(item)
                item.setExpanded(True)

        elif column == 1:
            shader = item.getShader(self.getLayer())
            if shader:
                if shader["fromfile"] == False:
                    cmds.select(shader["shader"], r=1, ne=1)

        elif column == 2:
            shader = item.getDisplacement(self.getLayer())
            if shader:
                if shader["fromfile"] == False:
                    cmds.select(shader["shader"], r=1, ne=1)

    def expandItem(self, item):
        expandAll = False
        modifiers = QtGui.QApplication.keyboardModifiers()
        if modifiers == QtCore.Qt.ShiftModifier:
            expandAll = True

        if item.hasChidren():
            items = item.cache.getHierarchy(item.getPath())
            if len(items) != 0:
                createdItems = self.createBranch(item, items)
                if expandAll:
                    for i in createdItems:
                        self.hierarchyWidget.expandItem(i)
                        self.expandItem(i)

            return

        item.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.DontShowIndicator)

    def createBranch(self, parentItem, abcchild, hierarchy=False, p="/"):
        ''' 
        createBranch
        This function will create a branch inside the cache hierarchy
        '''
        createdItems = []
        for item in abcchild:
            itemType = item["type"]
            itemName = item["name"]

            itemExists = False
            for i in xrange(0, parentItem.childCount()):
                text = parentItem.child(i).getDisplayPath()
                if str(text) == str(itemName):
                    itemExists = True

            if itemExists == False:
                newItem = treeitem.abcTreeItem(parentItem.cache,
                                               parentItem.path + [itemName],
                                               itemType, self)
                parentItem.cache.itemsTree.append(newItem)

                newItem.checkShaders(self.getLayer())
                newItem.checkProperties(self.getLayer())

                # check if the item has chidren, but go no further...
                childsItems = newItem.cache.getHierarchy(newItem.getPath())
                if childsItems:
                    newItem.setChildIndicatorPolicy(
                        QtGui.QTreeWidgetItem.ShowIndicator)
                    newItem.setHasChildren(True)
                else:
                    newItem.setHasChildren(False)

                parentItem.addChild(newItem)

                if hierarchy == True:
                    parentItem = newItem

                self.hierarchyWidget.resizeColumnToContents(0)
                createdItems.append(newItem)

        return createdItems

    def populate(self):
        for cache in self.ABCViewerNode.values():
            if cache.cache != "":
                firstLevel = cache.getHierarchy()

                root = treeitem.abcTreeItem(cache, [], "Transform", self)
                #root.setCheckState(0, QtCore.Qt.Unchecked)
                root.checkShaders(self.getLayer())
                root.checkProperties(self.getLayer())
                root.setHasChildren(True)
                cache.itemsTree.append(root)

                if cache.ABCcurPath != None:
                    if cache.ABCcurPath != "/":
                        paths = cache.ABCcurPath.split("/")
                        if len(paths) > 0:
                            self.createBranch(root, paths[1:], True)

                self.hierarchyWidget.addTopLevelItem(root)
                self.createBranch(root, firstLevel)
                root.setExpanded(1)

            ### CHECK WILDCARD ASSIGNATIONS
            tags = cache.assignations.getAllTags()
            wildsAdded = []
            tagsAdded = []
            for wild in cache.assignations.getAllWidcards():
                name = wild["name"]
                fromTag = False
                if tags:
                    if name in tags:
                        if not name in tagsAdded:
                            tagsAdded.append(name)
                            self.createTag(root, name, wild["fromfile"])
                            fromTag = True

                if not fromTag:
                    if not name in wildsAdded:
                        wildsAdded.append(name)
                        self.createWildCard(root, name, wild["fromfile"])

            if tags:
                for tag in tags:
                    if not tag in tagsAdded:
                        tagsAdded.append(tag)
                        self.createTag(root, tag, False)

    def getShader(self):
        x = cmds.ls(mat=1, sl=1)
        if len(x) == 0:
            return None

        if cmds.nodeType(x[0]) == "displacementShader":
            return x[0]

        else:
            return self.createSG(x[0])

    def checkShaders(self, layer=None, item=None):

        if item is None or item.isWildCard == True:
            # we check every single item.
            for cache in self.ABCViewerNode.values():
                if cache.cache != "":
                    for item in cache.itemsTree:
                        item.checkShaders(layer)
        else:
            # we only check this item and his childrens
            item.checkShaders(layer)

            numChildren = item.childCount()
            for i in range(numChildren):
                self.checkShaders(layer, item.child(i))

    def checkProperties(self, layer=None, item=None):

        if item is None or item.isWildCard == True:
            # we check every single item.
            for cache in self.ABCViewerNode.values():
                if cache.cache != "":
                    for item in cache.itemsTree:
                        item.checkProperties(layer)
        else:
            # we only check this item and his childrens
            item.checkProperties(layer)
            numChildren = item.childCount()
            for i in range(numChildren):
                self.checkProperties(layer, item.child(i))

    def cleanAssignations(self):
        ''' This function will remove any assignation that no longer exists in the cache'''
        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            shaders = assignations.getAllShaderPaths()

            toRemove = []
            for shader in shaders:
                for path in shader:
                    if path.startswith("/"):
                        if self.ABCViewerNode[shape].getHierarchy(
                                path) == None:
                            toRemove.append(path)

            for remove in toRemove:

                print "Cleaning non existing path", remove
                assignations.assignShader(None, remove, None)

    def getNode(self):
        tr = cmds.ls(type='transform', sl=1, l=1) + cmds.ls(
            type='alembicHolder', sl=1, l=1)
        if len(tr) == 0:
            return
        for x in tr:
            if cmds.nodeType(x) == "alembicHolder":
                shape = x
            else:
                shapes = cmds.listRelatives(x, shapes=True, f=1)
                if not shapes:
                    continue
                shape = shapes[0]
            if cmds.nodeType(shape) == "gpuCache" or cmds.nodeType(
                    shape) == "alembicHolder":

                self.ABCViewerNode[shape] = gpucache.gpucache(shape, self)
                cacheAssignations = self.ABCViewerNode[shape].getAssignations()

                if cmds.objExists(str(shape) + ".jsonFile"):
                    cur = cmds.getAttr("%s.jsonFile" % shape)
                    if cur is not None:
                        for p in os.path.expandvars(cur).split(";"):
                            try:
                                f = open(p, "r")
                                allLines = json.load(f)
                                if "shaders" in allLines:
                                    cacheAssignations.addShaders(
                                        allLines["shaders"], fromFile=True)
                                if "attributes" in allLines:
                                    cacheAssignations.addOverrides(
                                        allLines["attributes"], fromFile=True)
                                if "displacement" in allLines:
                                    cacheAssignations.addDisplacements(
                                        allLines["displacement"],
                                        fromFile=True)
                                if "layers" in allLines:
                                    cacheAssignations.addLayers(
                                        allLines["layers"], fromFile=True)
                                f.close()
                            except:
                                pass

                if not cmds.objExists(str(shape) + ".shadersAssignation"):
                    cmds.addAttr(shape, ln='shadersAssignation', dt='string')
                else:
                    cur = cmds.getAttr("%s.shadersAssignation" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addShaders(json.loads(cur))
                        except:
                            pass

                if not cmds.objExists(str(shape) + ".attributes"):
                    cmds.addAttr(shape, ln='attributes', dt='string')

                else:
                    cur = cmds.getAttr("%s.attributes" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addOverrides(json.loads(cur))
                        except:
                            pass

                if not cmds.objExists(
                        str(shape) + ".displacementsAssignation"):
                    cmds.addAttr(shape,
                                 ln='displacementsAssignation',
                                 dt='string')
                else:
                    cur = cmds.getAttr("%s.displacementsAssignation" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addDisplacements(json.loads(cur))
                        except:
                            pass

                if not cmds.objExists(str(shape) + ".layersOverride"):
                    cmds.addAttr(shape, ln='layersOverride', dt='string')
                else:
                    cur = cmds.getAttr("%s.layersOverride" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addLayers(json.loads(cur))
                        except:
                            pass

                attrs = ["Json", "Shaders", "Attributes", "Displacements"]
                for attr in attrs:
                    if not cmds.objExists(str(shape) + ".skip%s" % attr):
                        cmds.addAttr(shape, ln='skip%s' % attr, at='bool')

    def getCache(self):
        for shape in self.ABCViewerNode:
            self.ABCViewerNode[shape].updateCache()

        self.cleanAssignations()

    def createWildCard(self, parentItem, wildcard="*", protected=False):
        ''' Create a wilcard assignation item '''

        newItem = treeitemWildcard.wildCardItem(parentItem.cache, wildcard,
                                                self)
        parentItem.cache.itemsTree.append(newItem)
        newItem.setChildIndicatorPolicy(
            QtGui.QTreeWidgetItem.DontShowIndicator)
        parentItem.addChild(newItem)

        newItem.checkShaders(self.getLayer())
        newItem.checkProperties(self.getLayer())

        newItem.protected = protected

    def createTag(self, parentItem, tag, protected=False):
        ''' Create a wilcard assignation item '''

        newItem = treeitemTag.tagItem(parentItem.cache, tag, self)
        parentItem.cache.itemsTree.append(newItem)
        newItem.setChildIndicatorPolicy(
            QtGui.QTreeWidgetItem.DontShowIndicator)
        parentItem.addChild(newItem)

        newItem.checkShaders(self.getLayer())
        newItem.checkProperties(self.getLayer())

        newItem.protected = protected

    def updateTags(self):
        for shape in self.ABCViewerNode:
            self.ABCViewerNode[shape].updateTags()

    def addWildCard(self):
        ''' Add a widldcard expression to the current cache'''

        # first get the current cache
        item = self.hierarchyWidget.currentItem()
        if item is None:
            return

        # and the top level ancestor..
        if item is not None:
            while 1:
                pitem = item.parent()
                if pitem is None:
                    break
                item = pitem

        self.createWildCard(item)

    def autoAssign(self):
        ''' Assign shaders to selected tags, using their name.'''
        for item in self.hierarchyWidget.selectedItems():
            if item.isTag:
                item.autoAssignShader()
Example #3
0
    def __init__(self, parent=None):
        super(ShaderManager, self).__init__(parent)
        
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)        

        self.setupUi(self)

        self.shadersFromFile = []
        self.displaceFromFile = []

        self.curLayer = None
        # self.listTagsWidget = tagTree(self)
        # self.tagGroup.layout().addWidget(self.listTagsWidget)
        #self.tagGroup.setVisible(0)

        self.shaderToAssign = None
        self.ABCViewerNode = {}
        self.tags = {}
        self.getNode()
        self.getCache()
        

        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False

        self.propertyEditorWindow = QtGui.QDockWidget(self)
        self.propertyEditorWindow.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.propertyEditorWindow.setWindowTitle("Properties")
        self.propertyEditorWindow.setMinimumWidth(300)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.propertyEditorWindow)
        self.propertyType = "polymesh"
        self.propertyEditor = PropertyEditor(self, self.propertyType, self.propertyEditorWindow)
        self.propertyEditorWindow.setWidget(self.propertyEditor)


        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

        self.hierarchyWidget.setColumnWidth(0,600)
        self.hierarchyWidget.setIconSize(QSize(22,22))

        self.hierarchyWidget.dragEnterEvent = self.newhierarchyWidgetdragEnterEvent
        self.hierarchyWidget.dragMoveEvent = self.newhierarchyWidgetdragMoveEvent
        self.hierarchyWidget.dropEvent = self.newhierarchyWidgetDropEvent

        self.hierarchyWidget.setColumnWidth(0,200)
        self.hierarchyWidget.setColumnWidth(1,300)
        self.hierarchyWidget.setColumnWidth(2,300)

        self.hierarchyWidget.setItemDelegate(treeDelegate.treeDelegate(self))

        self.updateTags()
        self.populate()
        

        self.curPath = ""
        self.ABCcurPath = ""

        self.hierarchyWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
        self.hierarchyWidget.itemExpanded.connect(self.requireItemExpanded)
        self.hierarchyWidget.itemCollapsed.connect(self.requireItemCollapse)
        self.hierarchyWidget.itemClicked.connect(self.itemCLicked)
        self.hierarchyWidget.itemSelectionChanged.connect(self.itemSelectionChanged)
        self.hierarchyWidget.itemPressed.connect(self.itemPressed)
        self.hierarchyWidget.setExpandsOnDoubleClick(False)



        self.filterShaderLineEdit.textChanged.connect(self.filterShader)

        #self.shadersList.startDrag = self.newshadersListStartDrag
        self.shadersList.itemDoubleClicked.connect(self.shaderCLicked)
        self.shadersList.mouseMoveEvent = self.newshadersListmouseMoveEvent


        self.displacementList.itemPressed.connect(self.shaderCLicked)
        self.displacementList.mouseMoveEvent = self.newdisplaceListmouseMoveEvent

        self.refreshManagerBtn.pressed.connect(self.reset)

        self.refreshShaders()

        self.getLayers()
        self.setCurrentLayer()
        
        self.addCBs()

        self.afterNewSceneCBId = MSceneMessage.addCallback(MSceneMessage.kAfterNew, self.reset)
        self.afterOpenSceneCBId = MSceneMessage.addCallback(MSceneMessage.kAfterOpen, self.reset)

        self.disableLayerOverrides()

        self.overrideDisps.stateChanged.connect(self.overrideDispsChanged)
        self.overrideShaders.stateChanged.connect(self.overrideShadersChanged)
        self.overrideProps.stateChanged.connect(self.overridePropsChanged)

        self.isolateCheckbox.stateChanged.connect(self.isolateCheckboxChanged)

        #Widcard management
        self.wildCardButton.pressed.connect(self.addWildCard)
Example #4
0
class ShaderManager(QMainWindow, UI_ABCHierarchy.Ui_NAM):
    def __init__(self, parent=None):
        super(ShaderManager, self).__init__(parent)
        
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)        

        self.setupUi(self)

        self.shadersFromFile = []
        self.displaceFromFile = []

        self.curLayer = None
        # self.listTagsWidget = tagTree(self)
        # self.tagGroup.layout().addWidget(self.listTagsWidget)
        #self.tagGroup.setVisible(0)

        self.shaderToAssign = None
        self.ABCViewerNode = {}
        self.tags = {}
        self.getNode()
        self.getCache()
        

        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False

        self.propertyEditorWindow = QtGui.QDockWidget(self)
        self.propertyEditorWindow.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.propertyEditorWindow.setWindowTitle("Properties")
        self.propertyEditorWindow.setMinimumWidth(300)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.propertyEditorWindow)
        self.propertyType = "polymesh"
        self.propertyEditor = PropertyEditor(self, self.propertyType, self.propertyEditorWindow)
        self.propertyEditorWindow.setWidget(self.propertyEditor)


        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

        self.hierarchyWidget.setColumnWidth(0,600)
        self.hierarchyWidget.setIconSize(QSize(22,22))

        self.hierarchyWidget.dragEnterEvent = self.newhierarchyWidgetdragEnterEvent
        self.hierarchyWidget.dragMoveEvent = self.newhierarchyWidgetdragMoveEvent
        self.hierarchyWidget.dropEvent = self.newhierarchyWidgetDropEvent

        self.hierarchyWidget.setColumnWidth(0,200)
        self.hierarchyWidget.setColumnWidth(1,300)
        self.hierarchyWidget.setColumnWidth(2,300)

        self.hierarchyWidget.setItemDelegate(treeDelegate.treeDelegate(self))

        self.updateTags()
        self.populate()
        

        self.curPath = ""
        self.ABCcurPath = ""

        self.hierarchyWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
        self.hierarchyWidget.itemExpanded.connect(self.requireItemExpanded)
        self.hierarchyWidget.itemCollapsed.connect(self.requireItemCollapse)
        self.hierarchyWidget.itemClicked.connect(self.itemCLicked)
        self.hierarchyWidget.itemSelectionChanged.connect(self.itemSelectionChanged)
        self.hierarchyWidget.itemPressed.connect(self.itemPressed)
        self.hierarchyWidget.setExpandsOnDoubleClick(False)



        self.filterShaderLineEdit.textChanged.connect(self.filterShader)

        #self.shadersList.startDrag = self.newshadersListStartDrag
        self.shadersList.itemDoubleClicked.connect(self.shaderCLicked)
        self.shadersList.mouseMoveEvent = self.newshadersListmouseMoveEvent


        self.displacementList.itemPressed.connect(self.shaderCLicked)
        self.displacementList.mouseMoveEvent = self.newdisplaceListmouseMoveEvent

        self.refreshManagerBtn.pressed.connect(self.reset)

        self.refreshShaders()

        self.getLayers()
        self.setCurrentLayer()
        
        self.addCBs()

        self.afterNewSceneCBId = MSceneMessage.addCallback(MSceneMessage.kAfterNew, self.reset)
        self.afterOpenSceneCBId = MSceneMessage.addCallback(MSceneMessage.kAfterOpen, self.reset)

        self.disableLayerOverrides()

        self.overrideDisps.stateChanged.connect(self.overrideDispsChanged)
        self.overrideShaders.stateChanged.connect(self.overrideShadersChanged)
        self.overrideProps.stateChanged.connect(self.overridePropsChanged)

        self.isolateCheckbox.stateChanged.connect(self.isolateCheckboxChanged)

        #Widcard management
        self.wildCardButton.pressed.connect(self.addWildCard)


    def showEvent(self, event):
        self.reset()
        self.isolateCheckbox.setChecked(0)
        return QtGui.QMainWindow.showEvent(self, event)

    def hideEvent(self, event):
        self.reset()
        self.isolateCheckbox.setChecked(0)
        return QtGui.QMainWindow.hideEvent(self, event)

    def reset(self, *args, **kwargs):
        try:
            self.renderLayer.currentIndexChanged.disconnect()
        except:
            pass

        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        self.hierarchyWidget.clear()
        self.shadersList.clear()
        self.displacementList.clear()
        self.propertyEditor.resetToDefault()

        self.curPath = ""
        self.ABCcurPath = ""        
        
        self.shadersFromFile = []
        self.displaceFromFile = []
        self.ABCViewerNode = {}
        self.curLayer = None

        self.getLayers()
        self.setCurrentLayer()

        self.shaderToAssign = None

        self.tags = {}
        self.getNode()
        self.getCache()   
        self.updateTags()
        self.populate()
        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False    
        self.refreshShaders()

        self.renderLayer.currentIndexChanged.connect(self.layerChanged)
        self.propertyEditor.propertyChanged.connect(self.propertyChanged)
        

        
    def filterShader(self, text):
        '''
        Only show shaders matching this string.
        '''

        for i in range(self.shadersList.count()):
            item = self.shadersList.item(i)
            item.setHidden(0)
            if text != "" and not text.lower() in item.text().lower():
                item.setHidden(1)

        for i in range(self.displacementList.count()):
            item = self.displacementList.item(i)
            item.setHidden(0)
            if text != "" and not text.lower() in item.text().lower():
                item.setHidden(1)


    def isolateCheckboxChanged(self, state):
        ''' activate/desactive isolation'''
        if state == 0:
            for cache in self.ABCViewerNode.values():
                cache.setToPath("")

        else:
            for cache in self.ABCViewerNode.values():
                cache.setToPath(cache.getSelection())            

    def overrideDispsChanged(self, state):
        result = True
        if state == 0:
            result = False


        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedDisplace(self.getLayer(), result)

        self.updateTree()

    def overrideShadersChanged(self, state):

        result = True
        if state == 0:
            result = False

        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedShader(self.getLayer(), result)

        self.updateTree()


    def overridePropsChanged(self, state):
        result = True
        if state == 0:
            result = False

        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedProperties(self.getLayer(), result)

        self.updateTree()

    def createSG(self, node):
        sg = None

        SGs = cmds.listConnections( node, d=True, s=False, type="shadingEngine")        
        if not SGs:
            try:
                sg = cmds.shadingNode("shadingEngine", n="%sSG" % node, asRendering=True)
                cmds.connectAttr("%s.outColor" % node, "%s.surfaceShader" % sg, force=True)
                return sg
            except:
                print "Error creating shading group for node", node
        else:
            return SGs[0]
        


    def nameChangedCB(self, node, prevName, client):
        ''' Callback when a node is renamed '''

        if prevName == "" or not prevName or prevName.startswith("_"):
            return
        handle = MObjectHandle( node )
        if not handle.isValid():
            return
        mobject = handle.object()

        nodeFn = MFnDependencyNode ( mobject )
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()
            if cmds.getClassification(cmds.nodeType(nodeName), satisfies="shader"):

                if cmds.nodeType(nodeName) == "displacementShader":
                    items = self.displacementList.findItems(prevName, QtCore.Qt.MatchExactly)
                    for item in items:
                        item.setText(nodeName)

                    # renaming shaders in caches
                    for cache in self.ABCViewerNode.values():
                        cache.renameDisplacement(prevName, nodeName)
                    self.checkShaders()
                else:
                    items = self.shadersList.findItems(prevName, QtCore.Qt.MatchExactly)
                    for item in items:
                        item.setText(nodeName)

            if cmds.nodeType(nodeName) == "shadingEngine":
                    # renaming shaders in caches
                    for cache in self.ABCViewerNode.values():
                        cache.renameShader(prevName, nodeName)

                    self.checkShaders()


    def newNodeCB(self, newNode, data ):
        ''' Callback when creating a new node '''
        mobject = MObjectHandle( newNode ).object()
        nodeFn = MFnDependencyNode ( mobject )
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()
            if cmds.getClassification(cmds.nodeType(nodeName), satisfies="shader"):
                if cmds.nodeType(nodeName) == "displacementShader":
                    icon = QtGui.QIcon()
                    icon.addFile(os.path.join(d, "../../icons/sg.xpm"), QtCore.QSize(25,25))
                    item = QtGui.QListWidgetItem(nodeName)
                    item.setIcon(icon)
                    self.displacementList.addItem(item)
                else:
                    icon = QtGui.QIcon()
                    icon.addFile(os.path.join(d, "../../icons/sg.xpm"), QtCore.QSize(25,25))
                    item = QtGui.QListWidgetItem(nodeName)
                    item.setIcon(icon)
                    self.shadersList.addItem(item)


    def delNodeCB(self, node, data ):
        ''' Callback when a node has been deleted '''
        mobject = MObjectHandle( node ).object()
        nodeFn = MFnDependencyNode ( mobject )
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()

            didSomething = False

            if cmds.nodeType(nodeName) == "displacementShader":
                items = self.displacementList.findItems(nodeName, QtCore.Qt.MatchExactly)
                for item in items:
                    self.displacementList.takeItem(self.displacementList.row(item))   

                # remove shaders from caches
                for cache in self.ABCViewerNode.values():
                    didSomething = True
                    cache.removeDisplacement(nodeName)

            else:
                items = self.shadersList.findItems(nodeName, QtCore.Qt.MatchExactly)
                for item in items:
                    self.shadersList.takeItem(self.shadersList.row(item))

                # remove shaders from caches
                for cache in self.ABCViewerNode.values():
                    didSomething = True
                    cache.removeShader(nodeName)                
            
            if didSomething:
                self.checkShaders()

    def shaderCLicked(self, item):
        shader = item.text()
        if shader:
            if cmds.objExists(shader):
                try:
                    conn = cmds.connectionInfo(shader +".surfaceShader", sourceFromDestination=True)
                    if conn:
                        cmds.select(conn, r=1, ne=1)
                    else:
                        cmds.select(shader, r=1, ne=1)
                except:
                    cmds.select(shader, r=1, ne=1)

    def newshadersListmouseMoveEvent(self, event):
        self.newshadersListStartDrag(event)

    def newdisplaceListmouseMoveEvent(self, event):
        self.newdisplaceListStartDrag(event)

    def newshadersListStartDrag(self, event):
        index = self.shadersList.indexAt(event.pos())
        if not index.isValid():
            return
        selected = self.shadersList.itemFromIndex(index)

        self.shaderCLicked(selected)

        itemData = QtCore.QByteArray()
        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.WriteOnly)
        dataStream << QtCore.QByteArray(str(selected.text()))

        mimeData = QtCore.QMimeData()
        mimeData.setData("application/x-shader", itemData)
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)

        drag.setPixmap(self.shadersList.itemAt(event.pos()).icon().pixmap(50,50))
        drag.setHotSpot(QtCore.QPoint(0,0))
        drag.start(QtCore.Qt.MoveAction)

    def newdisplaceListStartDrag(self, event):
        index = self.displacementList.indexAt(event.pos())
        if not index.isValid():
            return
        selected = self.displacementList.itemFromIndex(index)

        self.shaderCLicked(selected)

        itemData = QtCore.QByteArray()
        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.WriteOnly)
        dataStream << QtCore.QByteArray(str(selected.text()))

        mimeData = QtCore.QMimeData()
        mimeData.setData("application/x-displacement", itemData)
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)

        drag.setPixmap(self.displacementList.itemAt(event.pos()).icon().pixmap(50,50))
        drag.setHotSpot(QtCore.QPoint(0,0))
        drag.start(QtCore.Qt.MoveAction)

    def newhierarchyWidgetdragEnterEvent(self, event):
        if event.mimeData().hasFormat("application/x-shader") or event.mimeData().hasFormat("application/x-displacement"):
            event.accept()
        else:
            event.ignore()

    def newhierarchyWidgetdragMoveEvent(self, event):
        if event.mimeData().hasFormat("application/x-shader") or event.mimeData().hasFormat("application/x-displacement"):
            event.accept()
        else:
            event.ignore()

    def newhierarchyWidgetDropEvent(self, event):
        mime = event.mimeData()
        itemData = None
        mode = 0
        
        if mime.hasFormat("application/x-shader"):
            mode = 0
            itemData = mime.data("application/x-shader")
        elif mime.hasFormat("application/x-displacement"):
            mode = 1
            itemData = mime.data("application/x-displacement")

        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.ReadOnly)

        shader = QtCore.QByteArray()
        dataStream >> shader

        shader = str(shader)
        items = []
        
        selectedItems = self.hierarchyWidget.selectedItems()

        item = self.hierarchyWidget.itemFromIndex(self.hierarchyWidget.indexAt(event.pos()))
        if item:
            items.append(item)

        if len(selectedItems) > 1:
            items = items + selectedItems

        for item in items:
            item.shaderToAssign = shader
            if mode == 0:
                item.assignShader()
            elif mode == 1:
                item.assignDisplacement()
               
        event.accept()

    def addCBs(self, event=None):
        try:
            print "adding callbacks"
            self.renderLayer.currentIndexChanged.connect(self.layerChanged)
            self.NodeNameMsgId  = MNodeMessage.addNameChangedCallback( MObject(), self.nameChangedCB )
            self.newNodeCBMsgId = MDGMessage.addNodeAddedCallback( self.newNodeCB )
            self.delNodeCBMsgId = MDGMessage.addNodeRemovedCallback( self.delNodeCB )
            print "adding scriptjob"
            self.layerChangedJob = cmds.scriptJob( e= ["renderLayerManagerChange",self.setCurrentLayer])
        except:
            pass

    def clearCBs(self, event=None):
        try:
            print "removing scriptjob"
            cmds.scriptJob( kill=self.layerChangedJob, force=True)
            for cache in self.ABCViewerNode.values():
                cache.setSelection("")
            print "removing callbacks"
            MMessage.removeCallback( self.newNodeCBMsgId )
            MMessage.removeCallback( self.delNodeCBMsgId )
            MNodeMessage.removeCallback( self.NodeNameMsgId )
        except:
            pass


    def closeEvent(self, event):
        event.ignore()
        self.hide()
        return

    def clearing(self):
        self.clearCBs()

        MMessage.removeCallback( self.afterNewSceneCBId )
        MMessage.removeCallback( self.afterOpenSceneCBId )


    def setCurrentLayer(self):
        curLayer = cmds.editRenderLayerGlobals(query=1, currentRenderLayer=1)
        curLayeridx = self.renderLayer.findText(curLayer)
        if curLayeridx != -1:
            self.renderLayer.setCurrentIndex(curLayeridx)
        self.curLayer = curLayer


    def layerChanged(self, index):


        self.curLayer = self.renderLayer.itemText(index)
        if self.curLayer == "defaultRenderLayer":
            self.disableLayerOverrides()
        else:
            self.enableLayerOverrides()
            for cache in self.ABCViewerNode:
                c = self.ABCViewerNode[cache]
                over = c.getLayerOverrides(self.getLayer())

                if over:
                    self.overrideProps.setChecked(over["removeProperties"])
                    self.overrideShaders.setChecked(over["removeShaders"])
                    self.overrideDisps.setChecked(over["removeDisplacements"])


        self.updateTree()
        if self.hierarchyWidget.currentItem():
            self.itemCLicked(self.hierarchyWidget.currentItem(), 0, force=True)

        # change it in maya too
        curLayer = cmds.editRenderLayerGlobals(query=1, currentRenderLayer=1)
        if curLayer != self.curLayer:
            cmds.editRenderLayerGlobals( currentRenderLayer=self.curLayer)



    def updateTree(self):
        items = []
        for i in range(self.hierarchyWidget.topLevelItemCount()):
            self.visitTree(items, self.hierarchyWidget.topLevelItem(i))

        for item in items:
            item.removeAssigns()
            item.checkShaders(self.getLayer())
            item.checkProperties(self.getLayer())


    def visitTree(self, items, treeitem):
        items.append(treeitem)
        for i in range(treeitem.childCount()):
            self.visitTree(items, treeitem.child(i))


    def enableLayerOverrides(self):
        self.overrideDisps.setEnabled(1)
        self.overrideShaders.setEnabled(1)
        self.overrideProps.setEnabled(1)


        self.overrideDisps.setChecked(0)
        self.overrideShaders.setChecked(0)
        self.overrideProps.setChecked(0)


    def disableLayerOverrides(self):
        self.overrideDisps.setEnabled(0)
        self.overrideShaders.setEnabled(0)
        self.overrideProps.setEnabled(0)

        self.overrideDisps.setChecked(0)
        self.overrideShaders.setChecked(0)
        self.overrideProps.setChecked(0)


    def getLayers(self):
        self.renderLayer.clear()
        renderLayers = []
        for layer in cmds.ls(type="renderLayer"):
            con = cmds.connectionInfo(layer + ".identification", sourceFromDestination=True)
            if con:
                if con.split(".")[0] == "renderLayerManager":
                    renderLayers.append(layer)

        self.renderLayer.addItems(renderLayers)
        idx = self.renderLayer.findText("defaultRenderLayer")
        if idx == -1:
            self.curLayer = self.renderLayer.itemText(0)
        else:
            self.curLayer = self.renderLayer.itemText(idx)
            self.renderLayer.setCurrentIndex(idx)

    def propertyChanged(self, prop):
        if self.propertyEditing:
            return
        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        propName = prop["propname"]
        default = prop["default"]
        value = prop["value"]

        if self.lastClick == 1:

            item = self.hierarchyWidget.currentItem()
            if item:
                curPath = item.getPath()
                if curPath is None:
                    return
            else:
                return

            cache = item.cache
            layer = self.getLayer()
            cache.updateOverride(propName, default, value, curPath, layer)
            self.updatePropertyColor(cache, layer, propName, curPath)

            self.checkProperties(self.getLayer(), item=item)

        elif self.lastClick == 2:
            item = self.listTagsWidget.currentItem()
            item.assignProperty(propName, default, value)


        self.propertyEditor.propertyChanged.connect(self.propertyChanged)


    def updatePropertyColor(self, cache, layer, propName, curPath):
        cacheState = cache.getPropertyState(layer, propName, curPath)
        if cacheState == 3:
            self.propertyEditor.propertyWidgets[propName].title.setText("<font color='darkRed'>%s</font>" % propName)
        if cacheState == 2:
            self.propertyEditor.propertyWidgets[propName].title.setText("<font color='red'>%s</font>" % propName)
        if cacheState == 1:
            self.propertyEditor.propertyWidgets[propName].title.setText("<font color='white'><i>%s</i></font>" % propName)


    def fillShaderList(self):
        self.shadersList.clear()
        shaders = cmds.ls(materials=True)
        icon = QtGui.QIcon()
        icon.addFile(os.path.join(d, "../../icons/sg.xpm"), QtCore.QSize(25,25))
        for shader in shaders:
            item = QtGui.QListWidgetItem(shader)
            item.setIcon(icon)
            self.shadersList.addItem(item)

    def fillDisplacementList(self):
        self.displacementList.clear()
        displaces = cmds.ls(type="displacementShader")
        icon = QtGui.QIcon()
        icon.addFile(os.path.join(d, "../../icons/displacement.xpm"), QtCore.QSize(25,25))
        for sg in displaces:
            item = QtGui.QListWidgetItem(sg)
            item.setIcon(icon)
            self.displacementList.addItem(item)

    def refreshShaders(self):
        self.fillShaderList()
        self.fillDisplacementList()

    def getLayer(self):
        if self.curLayer != "defaultRenderLayer":
            return self.curLayer
        return None

    def itemCLicked(self, item, col, force=False) :
        self.propertyEditing = True
        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        if item.icon == 7 and self.propertyType != "points":
            self.propertyType = "points"
            self.propertyEditor.resetTo(item.itemType.lower())

        elif item.icon == 8 and self.propertyType != item.itemType:
            self.propertyType = item.itemType
            if item.itemType == "PointLight":
                self.propertyEditor.resetTo("point_light")

            elif item.itemType == "DistantLight":
                self.propertyEditor.resetTo("distant_light")

            elif item.itemType == "SpotLight":
                self.propertyEditor.resetTo("spot_light")

            elif item.itemType == "QuadLight":
                self.propertyEditor.resetTo("quad_light")                
            
            elif item.itemType == "PhotometricLight":
                self.propertyEditor.resetTo("photometric_light")                                

            elif item.itemType == "DiskLight":
                self.propertyEditor.resetTo("disk_light")

            elif item.itemType == "CylinderLight":
                self.propertyEditor.resetTo("cylinder_light")

        elif (item.icon == 1 or item.icon == 2) and self.propertyType != "polymesh":
            self.propertyType = "polymesh"
            self.propertyEditor.resetTo("polymesh")


        self.lastClick = 1

        if self.thisTreeItem is item and force==False:
            self.propertyEditing = False
            return
        self.thisTreeItem = item

        curPath = item.getPath()
        cache = item.cache

        allSelected = []
        for item in self.hierarchyWidget.selectedItems():
            allSelected.append(item.getPath())

        if "/" in allSelected:
            allSelected = []

        cache.setSelection(allSelected)

        if self.isolateCheckbox.checkState() == Qt.Checked:
            cache.setToPath(curPath)


        self.propertyEditor.resetToDefault()

        self.updateAttributeEditor()

        self.propertyEditing = False

        

    def updateAttributeEditor(self):
        ''' this will update what is inside the attribute editor (red text,....)'''

        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        for item in self.hierarchyWidget.selectedItems():
            curPath = item.getPath()
            cache = item.cache
            layer = self.getLayer()
            attributes = {}

            if layer:
                layerOverrides = cache.getAssignations().getLayerOverrides(layer)
                if not layerOverrides:
                    layerOverrides = dict(removeDisplacements=False, removeProperties=False, removeShaders=False)

                if layerOverrides["removeProperties"] == False:
                    attributes = cache.getAssignations().getOverrides(curPath, layer)
                else:
                    attributes = cache.getAssignations().getOverrides(curPath, None)

            else:
                attributes = cache.getAssignations().getOverrides(curPath, None)


            if len(attributes) > 0 :
                for propname in attributes:
                    value = attributes[propname].get("override") 
                    self.propertyEditor.propertyValue(dict(paramname=propname, value=value))

                    if propname in self.propertyEditor.propertyWidgets :
                        self.updatePropertyColor(cache, layer, propname, curPath)

        try:            
            self.propertyEditor.propertyChanged.connect(self.propertyChanged)
        except:
            pass

    def itemPressed(self, item, col) :
        self.lastClick = 1
        if QtGui.QApplication.mouseButtons()  == QtCore.Qt.RightButton:
            item.pressed()


    def itemSelectionChanged(self):
        if len(self.hierarchyWidget.selectedItems()) == 0:
            for cache in self.ABCViewerNode.values():
                cache.setSelection("")


    def requireItemCollapse(self, item):
        pass

    def requireItemExpanded(self, item) :
        self.expandItem(item)

    def itemDoubleClicked(self, item, column) :
        '''  An item on the hierarchy is double clicked'''
        if column == 0:
            if item.isWildCard:
                if not item.protected:
                    text, ok = QtGui.QInputDialog.getText(self, 'WildCard expression',  'Enter the expression:', QtGui.QLineEdit.Normal, item.getPath())
                    if ok:
                        #first change the path
                        item.setExpression(text)

            else:
                self.expandItem(item)
                item.setExpanded(True)

        elif column == 1:
            shader = item.getShader(self.getLayer())
            if shader:
                if shader["fromfile"] == False:
                    cmds.select(shader["shader"], r=1, ne=1)

        elif column == 2:
            shader = item.getDisplacement(self.getLayer())
            if shader:
                if shader["fromfile"] == False:
                    cmds.select(shader["shader"], r=1, ne=1)


    def expandItem(self, item) :
        expandAll = False
        modifiers = QtGui.QApplication.keyboardModifiers()
        if modifiers == QtCore.Qt.ShiftModifier:
            expandAll = True

        if item.hasChidren():
            items = cmds.ABCHierarchy(item.cache.ABCcache, item.getPath().replace("/", "|"))
            if items != None :
                createdItems = self.createBranch(item, items)
                if expandAll :
                    for i in createdItems:
                        self.hierarchyWidget.expandItem(i)
                        self.expandItem(i)
            
            return


        item.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.DontShowIndicator)

    def createBranch(self, parentItem, abcchild, hierarchy = False, p = "/") :
        ''' 
        createBranch
        This function will create a branch inside the cache hierarchy
        '''
        createdItems = []
        for item in abcchild :
            itemType = item.partition(":")[0]
            itemName = item.partition(":")[-1]

            itemExists = False
            for i in xrange(0, parentItem.childCount()) :
                text = parentItem.child(i).getDisplayPath()
                if str(text) == str(itemName) :
                    itemExists = True

            if itemExists == False :
                newItem = treeitem.abcTreeItem(parentItem.cache, parentItem.path + [itemName], itemType, self)
                parentItem.cache.itemsTree.append(newItem)

                newItem.checkShaders(self.getLayer())
                newItem.checkProperties(self.getLayer())
               
                # check if the item has chidren, but go no further...
                childsItems = cmds.ABCHierarchy(newItem.cache.ABCcache, newItem.getPath().replace("/", "|"))
                if childsItems:
                    newItem.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.ShowIndicator)
                    newItem.setHasChildren(True)
                else:
                    newItem.setHasChildren(False)

                parentItem.addChild(newItem)

                if hierarchy == True :
                    parentItem = newItem

                self.hierarchyWidget.resizeColumnToContents(0)
                createdItems.append(newItem)

        return createdItems

    def populate(self) :
        for cache in self.ABCViewerNode.values():
            if cache.cache != "":
                firstLevel = cmds.ABCHierarchy(cache.ABCcache)

                root = treeitem.abcTreeItem(cache, [], "Transform", self)
                #root.setCheckState(0, QtCore.Qt.Unchecked)
                root.checkShaders(self.getLayer())
                root.checkProperties(self.getLayer())
                root.setHasChildren(True)
                cache.itemsTree.append(root)

                if cache.ABCcurPath != None :
                    if cache.ABCcurPath != "/" :
                        paths = cache.ABCcurPath.split("/")
                        if len(paths) > 0 :
                            self.createBranch(root, paths[1:], True)

                self.hierarchyWidget.addTopLevelItem(root)
                self.createBranch(root,firstLevel)
                root.setExpanded(1)

            ### CHECK WILDCARD ASSIGNATIONS
            tags = cache.assignations.getAllTags()
            wildsAdded = []
            tagsAdded = []
            for wild in cache.assignations.getAllWidcards():
                name = wild["name"]
                fromTag = False
                if tags:
                    if name in tags:
                        if not name in tagsAdded :
                            tagsAdded.append(name)
                            self.createTag(root, name, wild["fromfile"])
                            fromTag = True

                if not fromTag:
                    if not name in wildsAdded :
                        wildsAdded.append(name)
                        self.createWildCard(root, name, wild["fromfile"])
                        

            if tags:
                for tag in tags:
                    if not tag in tagsAdded:
                            tagsAdded.append(tag)
                            self.createTag(root, tag, False)

    def getShader(self):
        x = cmds.ls(mat=1, sl=1)
        if len(x) == 0:
            return None

        if cmds.nodeType(x[0]) == "displacementShader":
            return x[0]

        else:
            return self.createSG(x[0])


    def checkShaders(self, layer=None, item=None):

        if item is None or item.isWildCard == True:
            # we check every single item.
            for cache in self.ABCViewerNode.values():
                if cache.cache != "":
                    for item in cache.itemsTree:
                        item.checkShaders(layer)
        else:
            # we only check this item and his childrens
            item.checkShaders(layer)

            numChildren = item.childCount()
            for i in range(numChildren):
                self.checkShaders(layer, item.child(i))

    def checkProperties(self, layer=None, item=None):

        if item is None or item.isWildCard == True:
            # we check every single item.
            for cache in self.ABCViewerNode.values():
                if cache.cache != "":
                    for item in cache.itemsTree:
                        item.checkProperties(layer)
        else:
            # we only check this item and his childrens
            item.checkProperties(layer)
            numChildren = item.childCount()
            for i in range(numChildren):
                self.checkProperties(layer, item.child(i))
                    

    def cleanAssignations(self):
        ''' This function will remove any assignation that no longer exists in the cache'''
        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            shaders = assignations.getAllShaderPaths()

            toRemove = []
            for shader in shaders:
                for path in shader:
                    if path.startswith("/"):
                        try:
                            cmds.ABCHierarchy(self.ABCViewerNode[shape].getAbcPath(), path.replace("/", "|"))
                        except:
                            toRemove.append(path)
            
            for remove in toRemove:

                print "Cleaning non existing path", remove
                assignations.assignShader(None, remove, None)


    def getNode(self):
        tr = cmds.ls( type= 'transform', sl=1, l=1) + cmds.ls(type= 'alembicHolder', sl=1, l=1)
        if len(tr) == 0:
            return
        for x in tr:
            if cmds.nodeType(x) == "alembicHolder":
                shape = x
            else:
                shapes = cmds.listRelatives(x, shapes=True, f=1)
                if shapes:
                    shape = shapes[0]
            if cmds.nodeType(shape) == "gpuCache" or cmds.nodeType(shape) == "alembicHolder":



                self.ABCViewerNode[shape] = gpucache.gpucache(shape, self)
                cacheAssignations = self.ABCViewerNode[shape].getAssignations()

                if cmds.objExists(str(shape) + ".jsonFile"):
                    cur = cmds.getAttr("%s.jsonFile" % shape)
                    for p in os.path.expandvars(cur).split(";"):
                        try:
                            f = open(p, "r")
                            allLines = json.load(f)
                            if "shaders" in allLines:
                                cacheAssignations.addShaders(allLines["shaders"], fromFile=True)
                            if "attributes" in allLines:
                                cacheAssignations.addOverrides(allLines["attributes"], fromFile=True)
                            if "displacement" in allLines:
                                cacheAssignations.addDisplacements(allLines["displacement"], fromFile=True)
                            if "layers" in allLines:
                                cacheAssignations.addLayers(allLines["layers"], fromFile=True)
                            f.close()
                        except:
                            pass


                if not cmds.objExists(str(shape) + ".shadersAssignation"):
                    cmds.addAttr(shape, ln='shadersAssignation', dt='string')
                else:
                    cur = cmds.getAttr("%s.shadersAssignation"  % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addShaders(json.loads(cur))
                        except:
                            pass


                if not cmds.objExists(str( shape )+ ".attributes"):
                    cmds.addAttr(shape, ln='attributes', dt='string')

                else:
                    cur = cmds.getAttr("%s.attributes"  % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addOverrides(json.loads(cur))
                        except:
                            pass


                if not cmds.objExists(str(shape) + ".displacementsAssignation"):
                    cmds.addAttr(shape, ln='displacementsAssignation', dt='string')
                else:
                    cur = cmds.getAttr("%s.displacementsAssignation" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addDisplacements(json.loads(cur))
                        except:
                            pass


                if not cmds.objExists(str(shape) + ".layersOverride"):
                    cmds.addAttr(shape, ln='layersOverride', dt='string')
                else:
                    cur = cmds.getAttr("%s.layersOverride"  % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addLayers(json.loads(cur))
                        except:
                            pass

                attrs=["Json","Shaders","Overrides","Displacements"]
                for attr in attrs:
                    if not cmds.objExists(str(shape) + ".skip%s" % attr):
                        cmds.addAttr(shape, ln='skip%s' % attr, at='bool')

        

    def getCache(self):
        for shape in self.ABCViewerNode:
            self.ABCViewerNode[shape].updateCache()

        self.cleanAssignations()


    def createWildCard(self, parentItem, wildcard="*", protected=False) :
        ''' Create a wilcard assignation item '''

        newItem = treeitemWildcard.wildCardItem(parentItem.cache, wildcard, self)
        parentItem.cache.itemsTree.append(newItem)
        newItem.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.DontShowIndicator)
        parentItem.addChild(newItem)
        
        newItem.checkShaders(self.getLayer())
        newItem.checkProperties(self.getLayer())

        newItem.protected = protected

    def createTag(self, parentItem, tag, protected=False) :
        ''' Create a wilcard assignation item '''

        newItem = treeitemTag.tagItem(parentItem.cache, tag, self)
        parentItem.cache.itemsTree.append(newItem)
        newItem.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.DontShowIndicator)
        parentItem.addChild(newItem)
        
        newItem.checkShaders(self.getLayer())
        newItem.checkProperties(self.getLayer())

        newItem.protected = protected



    def updateTags(self):
        for shape in self.ABCViewerNode:
            self.ABCViewerNode[shape].updateTags() 

    def addWildCard(self):
        ''' Add a widldcard expression to the current cache'''
        
        # first get the current cache
        item = self.hierarchyWidget.currentItem()
        if item is None:
            return

        # and the top level ancestor..
        if item is not None:
            while 1:
                pitem = item.parent()
                if pitem is None:
                    break
                item = pitem

        self.createWildCard(item)
Example #5
0
    def __init__(self, parent=None):
        """Shader Manager class"""
        super(ShaderManager, self).__init__(parent)

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        # initialise the inherited ui class
        self.setupUi(self)

        # set up some vars
        self.shadersFromFile = []
        self.displaceFromFile = []

        self.curLayer = None
        self.shaderToAssign = None
        self.ABCViewerNode = {}

        self.getNode()
        self.getCache()

        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False

        # properties widget
        self.propertyEditorWindow = QtWidgets.QDockWidget(self)
        self.propertyEditorWindow.setAllowedAreas(
            QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.propertyEditorWindow.setWindowTitle("Properties")
        self.propertyEditorWindow.setMinimumWidth(300)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
                           self.propertyEditorWindow)
        self.propertyType = "polymesh"
        self.propertyEditor = PropertyEditor(self, self.propertyType,
                                             self.propertyEditorWindow)
        self.propertyEditorWindow.setWidget(self.propertyEditor)
        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

        # shaders scroll widget
        self.shaderWindow = QtWidgets.QDockWidget(self)
        self.shaderWindow.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea
                                          | QtCore.Qt.RightDockWidgetArea)
        self.shaderWindow.setWindowTitle("Shaders")
        self.shaderWindow.setMinimumWidth(300)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.shaderWindow)
        self.shaderEditor = shader_widget.ShadersDockWidget(self)
        self.shaderWindow.setWidget(self.shaderEditor)

        # hierarchy widget
        self.hierarchyWidget.setColumnWidth(0, 600)
        self.hierarchyWidget.setIconSize(QtCore.QSize(22, 22))
        self.hierarchyWidget.dragEnterEvent = self.newhierarchyWidgetdragEnterEvent
        self.hierarchyWidget.dragMoveEvent = self.newhierarchyWidgetdragMoveEvent
        self.hierarchyWidget.dropEvent = self.newhierarchyWidgetDropEvent
        self.hierarchyWidget.setColumnWidth(0, 200)
        self.hierarchyWidget.setColumnWidth(1, 300)
        self.hierarchyWidget.setColumnWidth(2, 300)
        self.hierarchyWidget.setItemDelegate(treeDelegate.treeDelegate(self))

        self.updateTags()
        self.populate()

        self.curPath = ""
        self.ABCcurPath = ""

        self.layers_pixmap = QtGui.QPixmap(
            os.path.join(d, "../../icons/layerEditor.png"))
        self.layers_btn.setIconSize(QtCore.QSize(18, 18))
        self.layers_btn.setIcon(self.layers_pixmap)

        # signals, slots and callbacks
        self.hierarchyWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
        self.hierarchyWidget.itemExpanded.connect(self.requireItemExpanded)
        self.hierarchyWidget.itemCollapsed.connect(self.requireItemCollapse)
        self.hierarchyWidget.itemClicked.connect(self.itemCLicked)
        self.hierarchyWidget.itemSelectionChanged.connect(
            self.itemSelectionChanged)
        self.hierarchyWidget.itemPressed.connect(self.itemPressed)
        self.hierarchyWidget.setExpandsOnDoubleClick(False)

        self.getLayers()
        self.setCurrentLayer()

        self.addCBs()

        self.afterNewSceneCBId = MSceneMessage.addCallback(
            MSceneMessage.kAfterNew, self.reset)
        self.afterOpenSceneCBId = MSceneMessage.addCallback(
            MSceneMessage.kAfterOpen, self.reset)

        self.disableLayerOverrides()

        self.overrideShaders.stateChanged.connect(self.overrideShadersChanged)
        self.overrideDisps.stateChanged.connect(self.overrideDispsChanged)
        self.overrideProps.stateChanged.connect(self.overridePropsChanged)
        self.soloSelected.stateChanged.connect(self.soloSelectedChanged)
        self.wildCardButton.pressed.connect(self.addWildCard)
        self.updateXformsButton.pressed.connect(self.updateXforms)
        self.layers_btn.clicked.connect(self.layers_clicked)
Example #6
0
class ShaderManager(QtWidgets.QMainWindow, UI_ABCHierarchy.Ui_NAM):
    def __init__(self, parent=None):
        """Shader Manager class"""
        super(ShaderManager, self).__init__(parent)

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        # initialise the inherited ui class
        self.setupUi(self)

        # set up some vars
        self.shadersFromFile = []
        self.displaceFromFile = []

        self.curLayer = None
        self.shaderToAssign = None
        self.ABCViewerNode = {}

        self.getNode()
        self.getCache()

        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False

        # properties widget
        self.propertyEditorWindow = QtWidgets.QDockWidget(self)
        self.propertyEditorWindow.setAllowedAreas(
            QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
        self.propertyEditorWindow.setWindowTitle("Properties")
        self.propertyEditorWindow.setMinimumWidth(300)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
                           self.propertyEditorWindow)
        self.propertyType = "polymesh"
        self.propertyEditor = PropertyEditor(self, self.propertyType,
                                             self.propertyEditorWindow)
        self.propertyEditorWindow.setWidget(self.propertyEditor)
        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

        # shaders scroll widget
        self.shaderWindow = QtWidgets.QDockWidget(self)
        self.shaderWindow.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea
                                          | QtCore.Qt.RightDockWidgetArea)
        self.shaderWindow.setWindowTitle("Shaders")
        self.shaderWindow.setMinimumWidth(300)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.shaderWindow)
        self.shaderEditor = shader_widget.ShadersDockWidget(self)
        self.shaderWindow.setWidget(self.shaderEditor)

        # hierarchy widget
        self.hierarchyWidget.setColumnWidth(0, 600)
        self.hierarchyWidget.setIconSize(QtCore.QSize(22, 22))
        self.hierarchyWidget.dragEnterEvent = self.newhierarchyWidgetdragEnterEvent
        self.hierarchyWidget.dragMoveEvent = self.newhierarchyWidgetdragMoveEvent
        self.hierarchyWidget.dropEvent = self.newhierarchyWidgetDropEvent
        self.hierarchyWidget.setColumnWidth(0, 200)
        self.hierarchyWidget.setColumnWidth(1, 300)
        self.hierarchyWidget.setColumnWidth(2, 300)
        self.hierarchyWidget.setItemDelegate(treeDelegate.treeDelegate(self))

        self.updateTags()
        self.populate()

        self.curPath = ""
        self.ABCcurPath = ""

        self.layers_pixmap = QtGui.QPixmap(
            os.path.join(d, "../../icons/layerEditor.png"))
        self.layers_btn.setIconSize(QtCore.QSize(18, 18))
        self.layers_btn.setIcon(self.layers_pixmap)

        # signals, slots and callbacks
        self.hierarchyWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
        self.hierarchyWidget.itemExpanded.connect(self.requireItemExpanded)
        self.hierarchyWidget.itemCollapsed.connect(self.requireItemCollapse)
        self.hierarchyWidget.itemClicked.connect(self.itemCLicked)
        self.hierarchyWidget.itemSelectionChanged.connect(
            self.itemSelectionChanged)
        self.hierarchyWidget.itemPressed.connect(self.itemPressed)
        self.hierarchyWidget.setExpandsOnDoubleClick(False)

        self.getLayers()
        self.setCurrentLayer()

        self.addCBs()

        self.afterNewSceneCBId = MSceneMessage.addCallback(
            MSceneMessage.kAfterNew, self.reset)
        self.afterOpenSceneCBId = MSceneMessage.addCallback(
            MSceneMessage.kAfterOpen, self.reset)

        self.disableLayerOverrides()

        self.overrideShaders.stateChanged.connect(self.overrideShadersChanged)
        self.overrideDisps.stateChanged.connect(self.overrideDispsChanged)
        self.overrideProps.stateChanged.connect(self.overridePropsChanged)
        self.soloSelected.stateChanged.connect(self.soloSelectedChanged)
        self.wildCardButton.pressed.connect(self.addWildCard)
        self.updateXformsButton.pressed.connect(self.updateXforms)
        self.layers_btn.clicked.connect(self.layers_clicked)

    def updateXforms(self):
        """"""

        # ensure that the abcfile is the current one
        self.reset()

        for parent in self.ABCViewerNode.keys():

            abcfile = str(self.ABCViewerNode[parent].ABCcache)
            parent_under = '|'.join(
                self.ABCViewerNode[parent].shape.split('|')[:-1])
            abcToApi.update_xforms(abcfile, parent_under)

    def layers_clicked(self):
        """"""
        layers_copy = CopyLayers(self)
        layers_copy.show()

    def geoFilterChanged(self):
        """Geo filter callback, selects matching items"""

        # get the filter string
        filter_string = self.geoFilter.text()
        types = []
        if self.transform_check.isChecked():
            types.append('Transform')
        if self.shape_check.isChecked():
            types.append('Shape')

        # expand the hierarchy so it is iterable
        self.hierarchyWidget.expandAll()
        _iter = QtWidgets.QTreeWidgetItemIterator(self.hierarchyWidget)

        index = 0
        while (_iter.value()):
            item = _iter.value()

            if filter_string != "" and len(filter_string) > 1:

                if filter_string in str(item.text(0)):
                    if item.itemType in types:
                        item.setSelected(True)
                    else:
                        item.setSelected(False)
                else:
                    item.setSelected(False)
            else:
                item.setSelected(False)

            index += 1
            _iter += 1

    def showEvent(self, event):
        """Show the main window"""

        windowname = "hyperShadePanel1Window"
        if cmds.window(windowname, exists=True):
            pass
        else:
            print 'Opening Hypershade'
            mel.eval("HypershadeWindow;")

        current_selection = cmds.ls(sl=True)
        if self.ABCViewerNode != {}:
            self.reset(self.ABCViewerNode.values()[0].shape)
        else:
            self.reset()
        cmds.select(current_selection)

        return QtWidgets.QMainWindow.showEvent(self, event)

    def hideEvent(self, event):
        """Hide the main window"""

        current_selection = cmds.ls(sl=True)
        if self.ABCViewerNode != {}:
            self.reset(self.ABCViewerNode.values()[0].shape)
        else:
            self.reset()
        cmds.select(current_selection)

        return QtWidgets.QMainWindow.hideEvent(self, event)

    def reset(self, shape=None, *args, **kwargs):
        """Reset the main window to initial state"""
        if shape:
            if cmds.objExists(shape):
                cmds.select(shape)

        try:
            self.renderLayer.currentIndexChanged.disconnect()
        except:
            pass

        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        self.hierarchyWidget.clear()
        self.propertyEditor.resetToDefault()

        self.curPath = ""
        self.ABCcurPath = ""

        self.shadersFromFile = []
        self.displaceFromFile = []
        self.ABCViewerNode = {}
        self.curLayer = None

        self.getLayers()
        self.setCurrentLayer()

        self.shaderToAssign = None

        self.tags = {}
        self.getNode()
        self.getCache()
        self.updateTags()
        self.populate()
        self.thisTagItem = None
        self.thisTreeItem = None

        self.lastClick = -1

        self.propertyEditing = False

        self.renderLayer.currentIndexChanged.connect(self.layerChanged)
        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

    def overrideShadersChanged(self, state):
        """Override shaders toggle"""

        result = True
        if state == 0:
            result = False

        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedShader(self.getLayer(), result)

        self.updateTree()

    def overrideDispsChanged(self, state):
        result = True
        if state == 0:
            result = False

        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedDisplace(self.getLayer(), result)

        self.updateTree()

    def overridePropsChanged(self, state):
        """Override properties toggle"""

        result = True
        if state == 0:
            result = False

        if self.getLayer() == None:
            return

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            assignations.setRemovedProperties(self.getLayer(), result)

        self.updateTree()

    def soloSelectedChanged(self, state):
        """Solo selected toggle"""

        if state == 0:
            for cache in self.ABCViewerNode.values():
                cache.setSelection([])
        else:
            for cache in self.ABCViewerNode.values():

                allSelected = []
                for item in self.hierarchyWidget.selectedItems():
                    if item.isTag == False and item.isWildCard == False:
                        allSelected.append(item.getPath())

                if "/" in allSelected:
                    allSelected = []
                cache.setSelection(allSelected)

    def createSG(self, node):
        """Create a shading group if node doesn't have one"""

        sg = None

        SGs = cmds.listConnections(node, d=True, s=False, type="shadingEngine")
        if not SGs:
            try:
                sg = cmds.shadingNode("shadingEngine",
                                      n="%sSG" % node,
                                      asRendering=True)
                cmds.connectAttr("%s.outColor" % node,
                                 "%s.surfaceShader" % sg,
                                 force=True)
                return sg
            except:
                print "Error creating shading group for node", node
        else:
            return SGs[0]

    def nameChangedCB(self, node, prevName, client):
        """Callback when a node is renamed"""

        if prevName == "" or not prevName or prevName.startswith("_"):
            return
        handle = MObjectHandle(node)
        if not handle.isValid():
            return
        mobject = handle.object()

        nodeFn = MFnDependencyNode(mobject)
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()
            if not cmds.objExists(nodeName):
                return

            # we need to ensure that we are updating all the caches, not just the one selected
            current_selection = cmds.ls(sl=True)
            cmds.select(cmds.ls(type='alembicHolder'))
            self.getNode()

            if self.ABCViewerNode != {}:

                if cmds.getClassification(cmds.nodeType(nodeName),
                                          satisfies="shader"):

                    if cmds.nodeType(nodeName) == "displacementShader":
                        # renaming displacements in caches
                        for cache in self.ABCViewerNode.values():
                            cache.renameDisplacement(prevName, nodeName)
                            self.reset(shape=cache.shape)
                        self.shaderEditor.renameShader(prevName, nodeName)

                    else:
                        # renaming shaders in caches
                        for cache in self.ABCViewerNode.values():
                            cache.renameShader(prevName, nodeName)
                            self.reset(shape=cache.shape)
                        self.shaderEditor.renameShader(prevName, nodeName)

                elif cmds.nodeType(nodeName) == "shadingEngine":
                    # renaming shaders in caches
                    for cache in self.ABCViewerNode.values():
                        cache.renameShader(prevName, nodeName)
                        self.reset(shape=cache.shape)

                    self.shaderEditor.renameShader(prevName, nodeName)
                    self.checkShaders()

                elif cmds.nodeType(nodeName) == "renderLayer":

                    for cache in self.ABCViewerNode.values():
                        cache.assignations.layers.renameLayer(
                            prevName, nodeName)
                        cache.assignations.writeLayer()
                        self.reset(shape=cache.shape)

                    # update the layers combo
                    self.getLayers()
                    self.setLayer(nodeName)

            cmds.select(current_selection)

    def newNodeCB(self, newNode, data):
        """Callback when creating a new node"""

        mobject = MObjectHandle(newNode).object()
        nodeFn = MFnDependencyNode(mobject)
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()
            if cmds.getClassification(cmds.nodeType(nodeName),
                                      satisfies="shader"):
                # add shader to scroller
                self.shaderEditor.addShader(nodeName)
            elif nodeFn.typeName() == 'renderLayer':
                self.renderLayer.addItems([nodeName])

    def delNodeCB(self, node, data):
        """Callback when a node has been deleted"""

        mobject = MObjectHandle(node).object()
        nodeFn = MFnDependencyNode(mobject)
        if nodeFn.hasUniqueName():
            nodeName = nodeFn.name()

            didSomething = False
            for cache in self.ABCViewerNode.values():
                didSomething = True
                cache.removeShader(nodeName)

            self.shaderEditor.removeShader(nodeName)

            if didSomething:
                self.checkShaders()

    def newhierarchyWidgetdragEnterEvent(self, event):
        """Enter event"""

        if event.mimeData().hasFormat(
                "application/x-shader") or event.mimeData().hasFormat(
                    "application/x-displacement"):
            event.accept()
        else:
            event.ignore()

    def newhierarchyWidgetdragMoveEvent(self, event):
        """Move event"""

        if event.mimeData().hasFormat(
                "application/x-shader") or event.mimeData().hasFormat(
                    "application/x-displacement"):
            event.accept()
        else:
            event.ignore()

    def newhierarchyWidgetDropEvent(self, event):
        """Drop event"""

        mime = event.mimeData()
        itemData = None
        mode = 0

        if mime.hasFormat("application/x-shader"):
            mode = 0
            itemData = mime.data("application/x-shader")
        elif mime.hasFormat("application/x-displacement"):
            mode = 1
            itemData = mime.data("application/x-displacement")

        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.ReadOnly)

        shader = QtCore.QByteArray()
        dataStream >> shader

        shader = str(shader)
        items = []

        selectedItems = self.hierarchyWidget.selectedItems()

        item = self.hierarchyWidget.itemFromIndex(
            self.hierarchyWidget.indexAt(event.pos()))
        if item:
            items.append(item)

        if len(selectedItems) > 1:
            items = items + selectedItems

        for item in items:
            item.shaderToAssign = shader
            if mode == 0:
                item.assignShader()
            elif mode == 1:
                item.assignDisplacement()

        event.accept()

    def addCBs(self, event=None):
        """Add the callbacks"""

        try:
            self.renderLayer.currentIndexChanged.connect(self.layerChanged)
            self.NodeNameMsgId = MNodeMessage.addNameChangedCallback(
                MObject(), self.nameChangedCB)
            self.newNodeCBMsgId = MDGMessage.addNodeAddedCallback(
                self.newNodeCB)
            self.delNodeCBMsgId = MDGMessage.addNodeRemovedCallback(
                self.delNodeCB)

            self.layerChangedJob = cmds.scriptJob(
                event=["renderLayerManagerChange", self.setCurrentLayer])
        except:
            pass

    def clearCBs(self, event=None):
        """Clear the callbacks"""

        try:
            cmds.scriptJob(kill=self.layerChangedJob, force=True)

            for cache in self.ABCViewerNode.values():
                cache.setSelection("")

            MMessage.removeCallback(self.newNodeCBMsgId)
            MMessage.removeCallback(self.delNodeCBMsgId)
            MNodeMessage.removeCallback(self.NodeNameMsgId)
        except:
            pass

    def closeEvent(self, event):
        """Main window close event"""

        event.ignore()
        self.hide()
        return

    def clearing(self):
        """Clearing method called from maya menu"""

        self.clearCBs()
        try:
            MMessage.removeCallback(self.afterNewSceneCBId)
            MMessage.removeCallback(self.afterOpenSceneCBId)
        except:
            pass

    def setLayer(self, layername):
        """"""
        idx = self.renderLayer.findText(layername)
        if idx != -1:
            self.renderLayer.setCurrentIndex(idx)
        self.curLayer = layername

    def setCurrentLayer(self):
        """Set current layer"""

        try:
            curLayer = cmds.editRenderLayerGlobals(query=1,
                                                   currentRenderLayer=1)
        except:
            return
        curLayeridx = self.renderLayer.findText(curLayer)
        if curLayeridx != -1:
            self.renderLayer.setCurrentIndex(curLayeridx)
        self.curLayer = curLayer

    def layerChanged(self, index):
        """Layer changed slot"""

        self.curLayer = self.renderLayer.itemText(index)

        if self.curLayer == "defaultRenderLayer":
            self.disableLayerOverrides()
        else:
            self.enableLayerOverrides()
            for cache in self.ABCViewerNode:
                c = self.ABCViewerNode[cache]
                over = c.getLayerOverrides(self.getLayer())

                if over:
                    self.overrideProps.setChecked(over["removeProperties"])
                    self.overrideShaders.setChecked(over["removeShaders"])
                    self.overrideDisps.setChecked(over["removeDisplacements"])

        self.updateTree()

        if self.hierarchyWidget.currentItem():
            self.itemCLicked(self.hierarchyWidget.currentItem(), 0, force=True)

        # change it in maya too
        try:
            curLayer = cmds.editRenderLayerGlobals(query=1,
                                                   currentRenderLayer=1)
            if self.curLayer:
                if curLayer != self.curLayer:

                    rs = renderSetup.instance()
                    if self.curLayer != 'defaultRenderLayer':

                        # there is a bug whereby, if you have a collection filter set to 'All' and you change the name of the layer
                        # when you toggle active layer to that layer, it crashes, as a work around, you can set the filter type to transform
                        # and then back 'All'.

                        # so, get the layer in question
                        layer = rs.getRenderLayer(
                            self.curLayer.split('rs_')[-1])

                        # and the collections
                        collections = layer.getCollections()
                        col_types = {}

                        # iterate over the collections and get the filter type and store them
                        for col in collections:
                            selector = col.getSelector()
                            current_filter_type = selector.getFilterType()
                            col_types[col] = current_filter_type

                            # if the filter type is 'All', set it to something else, in this case (1) transform
                            if current_filter_type == 0:
                                selector.setFilterType(1)

                        # now we can set the active layer
                        cmds.editRenderLayerGlobals(
                            currentRenderLayer=self.curLayer)

                        # now we can revert the collections filter type back to their original types
                        for col in col_types:
                            selector = col.getSelector()
                            selector.setFilterType(col_types[col])
                    else:
                        cmds.editRenderLayerGlobals(
                            currentRenderLayer=self.curLayer)
        except:
            pass

    def updateTree(self):
        """Update alembic tree"""

        items = []
        for i in range(self.hierarchyWidget.topLevelItemCount()):
            self.visitTree(items, self.hierarchyWidget.topLevelItem(i))

        for item in items:
            item.removeAssigns()
            item.checkShaders(self.getLayer())
            item.checkProperties(self.getLayer())

    def visitTree(self, items, treeitem):
        """Visit alembic tree"""

        items.append(treeitem)
        for i in range(treeitem.childCount()):
            self.visitTree(items, treeitem.child(i))

    def enableLayerOverrides(self):
        """Enable layer override"""

        self.overrideShaders.setEnabled(1)
        self.overrideDisps.setEnabled(1)
        self.overrideProps.setEnabled(1)

        self.overrideShaders.setChecked(0)
        self.overrideDisps.setChecked(0)
        self.overrideProps.setChecked(0)

    def disableLayerOverrides(self):
        """Disable layer override"""

        self.overrideShaders.setEnabled(0)
        self.overrideDisps.setEnabled(0)
        self.overrideProps.setEnabled(0)

        self.overrideShaders.setChecked(0)
        self.overrideDisps.setChecked(0)
        self.overrideProps.setChecked(0)

    def getLayers(self):
        """Get layers"""

        self.renderLayer.clear()
        renderLayers = []
        for layer in cmds.ls(type="renderLayer"):
            con = cmds.connectionInfo(layer + ".identification",
                                      sourceFromDestination=True)
            if con:
                if con.split(".")[0] == "renderLayerManager":
                    renderLayers.append(layer)

        self.renderLayer.addItems(renderLayers)
        idx = self.renderLayer.findText("defaultRenderLayer")
        if idx == -1:
            self.curLayer = self.renderLayer.itemText(0)
        else:
            self.curLayer = self.renderLayer.itemText(idx)
            self.renderLayer.setCurrentIndex(idx)

    def propertyChanged(self, prop):
        """Properry change slot"""

        if self.propertyEditing:
            return
        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        propName = prop["propname"]
        default = prop["default"]
        value = prop["value"]

        if self.lastClick == 1:

            items = []

            selectedItems = self.hierarchyWidget.selectedItems()

            item = self.hierarchyWidget.currentItem()
            if item:
                items.append(item)

            if len(selectedItems) > 1:
                items = items + selectedItems

            for item in items:
                if item:
                    curPath = item.getPath()
                    if curPath is None:
                        return
                else:
                    return

                cache = item.cache
                layer = self.getLayer()
                cache.updateOverride(propName, default, value, curPath, layer)
                self.updatePropertyColor(cache, layer, propName, curPath)

                self.checkProperties(self.getLayer(), item=item)

        elif self.lastClick == 2:
            item = self.listTagsWidget.currentItem()
            item.assignProperty(propName, default, value)

        self.propertyEditor.propertyChanged.connect(self.propertyChanged)

    def updatePropertyColor(self, cache, layer, propName, curPath):
        """Update the color of a property"""

        cacheState = cache.getPropertyState(layer, propName, curPath)
        if cacheState == 3:
            self.propertyEditor.propertyWidgets[propName].title.setText(
                "<font color='darkRed'>%s</font>" % propName)
        if cacheState == 2:
            self.propertyEditor.propertyWidgets[propName].title.setText(
                "<font color='red'>%s</font>" % propName)
        if cacheState == 1:
            self.propertyEditor.propertyWidgets[propName].title.setText(
                "<font color='white'><i>%s</i></font>" % propName)
        if cacheState == 0:
            self.propertyEditor.propertyWidgets[propName].title.setText(
                "%s" % propName)

    def getLayer(self):
        """Get current layer"""

        if self.curLayer != "defaultRenderLayer":
            return self.curLayer
        return None

    def itemCLicked(self, item, col, force=False):
        """Hierarchy item click"""

        self.propertyEditing = True
        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        if item.icon == 7 and self.propertyType != "points":
            self.propertyType = "points"
            self.propertyEditor.resetTo(item.itemType.lower())

        if item.icon == 9 and self.propertyType != "curves":
            self.propertyType = "curves"
            self.propertyEditor.resetTo(item.itemType.lower())

        elif item.icon == 8 and self.propertyType != item.itemType:
            self.propertyType = item.itemType
            if item.itemType == "PointLight":
                self.propertyEditor.resetTo("point_light")

            elif item.itemType == "DistantLight":
                self.propertyEditor.resetTo("distant_light")

            elif item.itemType == "SpotLight":
                self.propertyEditor.resetTo("spot_light")

            elif item.itemType == "QuadLight":
                self.propertyEditor.resetTo("quad_light")

            elif item.itemType == "PhotometricLight":
                self.propertyEditor.resetTo("photometric_light")

            elif item.itemType == "DiskLight":
                self.propertyEditor.resetTo("disk_light")

            elif item.itemType == "CylinderLight":
                self.propertyEditor.resetTo("cylinder_light")

        elif (item.icon == 1
              or item.icon == 2) and self.propertyType != "polymesh":
            self.propertyType = "polymesh"
            self.propertyEditor.resetTo("polymesh")

        self.lastClick = 1

        if self.thisTreeItem is item and force == False:
            self.propertyEditing = False
            return
        self.thisTreeItem = item

        curPath = item.getPath()
        cache = item.cache

        allSelected = []
        for item in self.hierarchyWidget.selectedItems():
            if item.isTag == False and item.isWildCard == False:
                allSelected.append(item.getPath())

        if "/" in allSelected:
            allSelected = []

        if self.soloSelected.isChecked():
            cache.setSelection(allSelected)
        else:
            cache.setSelection([])

        self.propertyEditor.resetToDefault()
        self.updateAttributeEditor()
        self.propertyEditing = False

    def updateAttributeEditor(self):
        """Update what is inside the attribute editor (red text,....)"""

        try:
            self.propertyEditor.propertyChanged.disconnect()
        except:
            pass

        for item in self.hierarchyWidget.selectedItems():
            curPath = item.getPath()
            cache = item.cache
            layer = self.getLayer()
            attributes = {}

            if layer:
                layerOverrides = cache.getAssignations().getLayerOverrides(
                    layer)
                if not layerOverrides:
                    layerOverrides = dict(removeDisplacements=False,
                                          removeProperties=False,
                                          removeShaders=False)

                if layerOverrides["removeProperties"] == False:
                    attributes = cache.getAssignations().getOverrides(
                        curPath, layer)
                else:
                    attributes = cache.getAssignations().getOverrides(
                        curPath, None)

            else:
                attributes = cache.getAssignations().getOverrides(
                    curPath, None)

            if len(attributes) > 0:
                for propname in attributes:
                    value = attributes[propname].get("override")
                    self.propertyEditor.propertyValue(
                        dict(paramname=propname, value=value))

                    if propname in self.propertyEditor.propertyWidgets:
                        self.updatePropertyColor(cache, layer, propname,
                                                 curPath)

        try:
            self.propertyEditor.propertyChanged.connect(self.propertyChanged)
        except:
            pass

    def itemPressed(self, item, col):
        """Item clicked event"""

        self.lastClick = 1
        if QtWidgets.QApplication.mouseButtons() == QtCore.Qt.RightButton:
            item.pressed()

    def itemSelectionChanged(self):
        """Item selection"""

        if len(self.hierarchyWidget.selectedItems()) == 0:
            for cache in self.ABCViewerNode.values():
                cache.setSelection("")

    def requireItemCollapse(self, item):
        pass

    def requireItemExpanded(self, item):
        """"""

        self.expandItem(item)

    def itemDoubleClicked(self, item, column):
        """Hierarchy item double click slot"""

        if column == 0:
            if item.isWildCard:
                if not item.protected:
                    text, ok = QtWidgets.QInputDialog.getText(
                        self, 'WildCard expression', 'Enter the expression:',
                        QtWidgets.QLineEdit.Normal, item.getPath())
                    if ok:
                        #first change the path
                        item.setExpression(text)

            else:
                self.expandItem(item)
                item.setExpanded(True)

        elif column == 1:
            shader = item.getShader(self.getLayer())
            if shader:
                if shader["fromfile"] == False:
                    cmds.select(shader["shader"], r=1, ne=1)

        elif column == 2:
            shader = item.getDisplacement(self.getLayer())
            if shader:
                if shader["fromfile"] == False:
                    cmds.select(shader["shader"], r=1, ne=1)

    def expandItem(self, item):
        """Expand hierarchy tree"""

        expandAll = False
        modifiers = QtWidgets.QApplication.keyboardModifiers()
        if modifiers == QtCore.Qt.ShiftModifier:
            expandAll = True

        if item.hasChidren():
            items = item.cache.getHierarchy(item.getPath())
            if len(items) != 0:
                createdItems = self.createBranch(item, items)
                if expandAll:
                    for i in createdItems:
                        self.hierarchyWidget.expandItem(i)
                        self.expandItem(i)

            return

        item.setChildIndicatorPolicy(
            QtWidgets.QTreeWidgetItem.DontShowIndicator)

    def createBranch(self, parentItem, abcchild, hierarchy=False, p="/"):
        """Create a branch inside the cache hierarchy"""

        createdItems = []
        for item in abcchild:
            itemType = item["type"]
            itemName = item["name"]

            itemExists = False
            for i in xrange(0, parentItem.childCount()):
                text = parentItem.child(i).getDisplayPath()
                if str(text) == str(itemName):
                    itemExists = True

            if itemExists == False:
                newItem = treeitem.abcTreeItem(parentItem.cache,
                                               parentItem.path + [itemName],
                                               itemType, self)
                parentItem.cache.itemsTree.append(newItem)

                newItem.checkShaders(self.getLayer())
                newItem.checkProperties(self.getLayer())

                # check if the item has chidren, but go no further...
                childsItems = newItem.cache.getHierarchy(newItem.getPath())
                if childsItems:
                    newItem.setChildIndicatorPolicy(
                        QtWidgets.QTreeWidgetItem.ShowIndicator)
                    newItem.setHasChildren(True)
                else:
                    newItem.setHasChildren(False)

                parentItem.addChild(newItem)

                if hierarchy == True:
                    parentItem = newItem

                self.hierarchyWidget.resizeColumnToContents(0)
                createdItems.append(newItem)

        return createdItems

    def populate(self):
        """Populate the hierarchy tree"""

        for cache in self.ABCViewerNode.values():
            if cache.cache != "":
                firstLevel = cache.getHierarchy(cache.ABCcurPath or "/")

                pathList = [
                    elem for elem in cache.ABCcurPath.split("/") if elem
                ]
                root = treeitem.abcTreeItem(cache, pathList, "Transform", self)

                root.checkShaders(self.getLayer())
                root.checkProperties(self.getLayer())
                root.setHasChildren(True)
                cache.itemsTree.append(root)

                self.hierarchyWidget.addTopLevelItem(root)
                self.createBranch(root, firstLevel)
                root.setExpanded(1)

            ### CHECK WILDCARD ASSIGNATIONS
            tags = cache.assignations.getAllTags()
            wildsAdded = []
            tagsAdded = []
            for wild in cache.assignations.getAllWidcards():
                name = wild["name"]
                fromTag = False
                if tags:
                    if name in tags:
                        if not name in tagsAdded:
                            tagsAdded.append(name)
                            self.createTag(root, name, wild["fromfile"])
                            fromTag = True

                if not fromTag:
                    if not name in wildsAdded:
                        wildsAdded.append(name)
                        self.createWildCard(root, name, wild["fromfile"])

            if tags:
                for tag in tags:
                    if not tag in tagsAdded:
                        tagsAdded.append(tag)
                        self.createTag(root, tag, False)

    def getShader(self):
        """Get selected shader"""

        x = cmds.ls(mat=1, sl=1)
        if len(x) == 0:
            return None

        if cmds.nodeType(x[0]) == "displacementShader":
            return x[0]

        else:
            return self.createSG(x[0])

    def checkShaders(self, layer=None, item=None):
        """Check shaders"""

        if item is None or item.isWildCard == True:
            # we check every single item.
            for cache in self.ABCViewerNode.values():
                if cache.cache != "":
                    for item in cache.itemsTree:
                        item.checkShaders(layer)
        else:
            # we only check this item and his childrens
            item.checkShaders(layer)

            numChildren = item.childCount()
            for i in range(numChildren):
                self.checkShaders(layer, item.child(i))

    def checkProperties(self, layer=None, item=None):
        """Check properties"""

        if item is None or item.isWildCard == True:
            # we check every single item.
            for cache in self.ABCViewerNode.values():
                if cache.cache != "":
                    for item in cache.itemsTree:
                        item.checkProperties(layer)
        else:
            # we only check this item and his childrens
            item.checkProperties(layer)
            numChildren = item.childCount()
            for i in range(numChildren):
                self.checkProperties(layer, item.child(i))

    def cleanAssignations(self):
        """Clear any assignation that no longer exists in the cache"""

        for shape in self.ABCViewerNode:
            assignations = self.ABCViewerNode[shape].getAssignations()
            shaders = assignations.getAllShaderPaths()

            toRemove = []
            for shader in shaders:
                for path in shader:
                    if path.startswith("/"):
                        if self.ABCViewerNode[shape].getHierarchy(
                                path) == None:
                            toRemove.append(path)

            for remove in toRemove:

                print "Cleaning non existing path", remove
                assignations.assignShader(None, remove, None)

    def getNode(self):
        """Load selected alembicHolder node into cache manager"""

        tr = cmds.ls(type='transform', sl=1, l=1) + cmds.ls(
            type='alembicHolder', sl=1, l=1)
        if len(tr) == 0:
            return
        for x in tr:
            if cmds.nodeType(x) == "alembicHolder":
                shape = x
            else:
                shapes = cmds.listRelatives(x, shapes=True, f=1)
                if not shapes:
                    continue
                shape = shapes[0]
            if cmds.nodeType(shape) == "gpuCache" or cmds.nodeType(
                    shape) == "alembicHolder":

                self.ABCViewerNode[shape] = gpucache.gpucache(shape, self)
                cacheAssignations = self.ABCViewerNode[shape].getAssignations()

                if cmds.objExists(str(shape) + ".jsonFile"):
                    cur = cmds.getAttr("%s.jsonFile" % shape)
                    if cur is not None:
                        for p in os.path.expandvars(cur).split(";"):
                            try:
                                f = open(p, "r")
                                allLines = json.load(f)
                                if "shaders" in allLines:
                                    cacheAssignations.addShaders(
                                        allLines["shaders"], fromFile=True)
                                if "attributes" in allLines:
                                    cacheAssignations.addOverrides(
                                        allLines["attributes"], fromFile=True)
                                if "displacement" in allLines:
                                    cacheAssignations.addDisplacements(
                                        allLines["displacement"],
                                        fromFile=True)
                                if "layers" in allLines:
                                    cacheAssignations.addLayers(
                                        allLines["layers"], fromFile=True)
                                f.close()
                            except:
                                pass

                if not cmds.objExists(str(shape) + ".shadersAssignation"):
                    cmds.addAttr(shape, ln='shadersAssignation', dt='string')
                else:
                    cur = cmds.getAttr("%s.shadersAssignation" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addShaders(json.loads(cur))
                        except:
                            pass

                if not cmds.objExists(str(shape) + ".attributes"):
                    cmds.addAttr(shape, ln='attributes', dt='string')

                else:
                    cur = cmds.getAttr("%s.attributes" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addOverrides(json.loads(cur))
                        except:
                            pass

                if not cmds.objExists(
                        str(shape) + ".displacementsAssignation"):
                    cmds.addAttr(shape,
                                 ln='displacementsAssignation',
                                 dt='string')
                else:
                    cur = cmds.getAttr("%s.displacementsAssignation" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addDisplacements(json.loads(cur))
                        except:
                            pass

                if not cmds.objExists(str(shape) + ".layersOverride"):
                    cmds.addAttr(shape, ln='layersOverride', dt='string')
                else:
                    cur = cmds.getAttr("%s.layersOverride" % shape)
                    if cur != None and cur != "":
                        try:
                            cacheAssignations.addLayers(json.loads(cur))
                        except:
                            pass

                attrs = ["Json", "Shaders", "Attributes", "Displacements"]
                for attr in attrs:
                    if not cmds.objExists(str(shape) + ".skip%s" % attr):
                        cmds.addAttr(shape, ln='skip%s' % attr, at='bool')

    def getCache(self):
        """Update and clean cache"""

        for shape in self.ABCViewerNode:
            self.ABCViewerNode[shape].updateCache()

        self.cleanAssignations()

    def createWildCard(self, parentItem, wildcard="*", protected=False):
        """Create a wilcard assignation item"""

        newItem = treeitemWildcard.wildCardItem(parentItem.cache, wildcard,
                                                self)
        parentItem.cache.itemsTree.append(newItem)
        newItem.setChildIndicatorPolicy(
            QtWidgets.QTreeWidgetItem.DontShowIndicator)
        parentItem.addChild(newItem)

        newItem.checkShaders(self.getLayer())
        newItem.checkProperties(self.getLayer())

        newItem.protected = protected

    def createTag(self, parentItem, tag, protected=False):
        """Create a tag item"""

        newItem = treeitemTag.tagItem(parentItem.cache, tag, self)
        parentItem.cache.itemsTree.append(newItem)
        newItem.setChildIndicatorPolicy(
            QtWidgets.QTreeWidgetItem.DontShowIndicator)
        parentItem.addChild(newItem)

        newItem.checkShaders(self.getLayer())
        newItem.checkProperties(self.getLayer())

        newItem.protected = protected

    def updateTags(self):
        """Update tags"""

        for shape in self.ABCViewerNode:
            self.ABCViewerNode[shape].updateTags()

    def addWildCard(self):
        """Add a widldcard expression to the current cache"""

        # first get the current cache
        item = self.hierarchyWidget.currentItem()
        if item is None:
            return

        # and the top level ancestor..
        if item is not None:
            while 1:
                pitem = item.parent()
                if pitem is None:
                    break
                item = pitem

        self.createWildCard(item)