class StructurePanel(): def __init__(self, parent, getEditorRootCanvas, elementDict, selectedElement): height = DGH.getRealHeight(parent) self.collapsedElements = [] self.parent = parent self.box = DirectBoxSizer(frameColor=(0.25, 0.25, 0.25, 1), autoUpdateFrameSize=False, orientation=DGG.VERTICAL) self.sizer = DirectAutoSizer(parent=parent, child=self.box, childUpdateSizeFunc=self.box.refresh) self.lblHeader = DirectLabel( text="Structure", text_scale=16, text_align=TextNode.ALeft, text_fg=(1, 1, 1, 1), frameColor=VBase4(0, 0, 0, 0), ) self.box.addItem(self.lblHeader) color = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)) # Disabled self.structureFrame = DirectScrolledFrame( # make the frame fit into our background frame frameSize=VBase4( self.parent["frameSize"][0], self.parent["frameSize"][1], self.parent["frameSize"][2] + DGH.getRealHeight(self.lblHeader), self.parent["frameSize"][3]), #canvasSize=VBase4(parent["frameSize"][0], parent["frameSize"][1]-20, height+30, 0), # set the frames color to transparent frameColor=VBase4(1, 1, 1, 1), scrollBarWidth=20, verticalScroll_scrollSize=20, verticalScroll_thumb_relief=DGG.FLAT, verticalScroll_incButton_relief=DGG.FLAT, verticalScroll_decButton_relief=DGG.FLAT, verticalScroll_thumb_frameColor=color, verticalScroll_incButton_frameColor=color, verticalScroll_decButton_frameColor=color, horizontalScroll_thumb_relief=DGG.FLAT, horizontalScroll_incButton_relief=DGG.FLAT, horizontalScroll_decButton_relief=DGG.FLAT, horizontalScroll_thumb_frameColor=color, horizontalScroll_incButton_frameColor=color, horizontalScroll_decButton_frameColor=color, state=DGG.NORMAL) self.box.addItem(self.structureFrame) self.structureFrame.bind(DGG.MWDOWN, self.scroll, [0.01]) self.structureFrame.bind(DGG.MWUP, self.scroll, [-0.01]) self.maxWidth = parent["frameSize"][1] - 20 self.getEditorRootCanvas = getEditorRootCanvas self.refreshStructureTree(elementDict, selectedElement) def scroll(self, scrollStep, event): self.structureFrame.verticalScroll.scrollStep(scrollStep) def resizeFrame(self): self.sizer.refresh() self.structureFrame["frameSize"] = (self.parent["frameSize"][0], self.parent["frameSize"][1], self.parent["frameSize"][2] + DGH.getRealHeight(self.lblHeader), self.parent["frameSize"][3]) #posZ = 0 #height = DGH.getRealHeight(parent) #self.lblHeader["frameSize"] = (self.parent["frameSize"][0], self.parent["frameSize"][1], -10, 20) #self.lblHeader["text_pos"] = (self.parent["frameSize"][0], 0) #self.lblHeader.setPos(0,0,posZ-20) #posZ -= 30 #self.structureFrame["frameSize"] = (self.parent["frameSize"][0], self.parent["frameSize"][1], height+30, 0) #self.structureFrame.setPos(0,0,posZ) def refreshStructureTree(self, elementDict, selectedElement): self.elementDict = elementDict self.selectedElement = selectedElement for element in self.structureFrame.getCanvas().getChildren(): element.removeNode() self.maxWidth = self.parent["frameSize"][1] - 20 self.itemCounter = 0 self.__fillStructureTree(self.getEditorRootCanvas(), 0, 0) self.structureFrame["canvasSize"] = ( self.structureFrame["frameSize"][0], self.maxWidth, self.itemCounter * -16, 0) self.structureFrame.setCanvasSize() def __fillStructureTree(self, root, level, z): if "DirectGrid" in root.getName(): return self.itemCounter += 1 elementInfo = None if root.getName() in self.elementDict.keys(): elementInfo = self.elementDict[root.getName()] elif len(root.getName().split("-")) > 1 and root.getName().split( "-")[1] in self.elementDict.keys(): elementInfo = self.elementDict[root.getName().split("-")[1]] if level > 0: self.__makeStructureFrameTreeItem(root, elementInfo, level, z) if hasattr(root, "getChildren") \ and elementInfo not in self.collapsedElements: for child in root.getChildren(): z = -16 * self.itemCounter self.__fillStructureTree(child, level + 1, z) def __makeStructureFrameTreeItem(self, elementNP, elementInfo, parentsLevel, z): if elementInfo is None: lbl = DirectLabel(text=elementNP.getName(), text_align=TextNode.ALeft, frameColor=(0, 0, 0, 0), relief=DGG.FLAT, pos=(self.structureFrame["frameSize"][0] + 20 * parentsLevel, 0, z), scale=16, parent=self.structureFrame.getCanvas()) self.maxWidth = max( self.maxWidth, lbl.getX() + lbl.getWidth() * lbl.getScale()[0]) else: margin = 5 shift = 6 if hasattr(elementNP, "getChildren"): if len(elementNP.getChildren()) > 0: # Collapse Button btnC = DirectCheckBox( relief=DGG.FLAT, pos=(self.structureFrame["frameSize"][0] + 20 * parentsLevel - 16 + margin, 0, z + shift), frameSize=(-8, 8, -8, 8), frameColor=(0, 0, 0, 0), command=self.__collapseElement, extraArgs=[elementInfo], image="icons/Collapsed.png" if elementInfo in self.collapsedElements else "icons/Collapse.png", uncheckedImage="icons/Collapse.png", checkedImage="icons/Collapsed.png", image_scale=8, isChecked=elementInfo in self.collapsedElements, parent=self.structureFrame.getCanvas()) btnC.setTransparency(TransparencyAttrib.M_alpha) btnC.bind(DGG.MWDOWN, self.scroll, [0.01]) btnC.bind(DGG.MWUP, self.scroll, [-0.01]) # Element Name btn = DirectButton( frameColor=( VBase4(1, 1, 1, 1), #normal VBase4(0.9, 0.9, 0.9, 1), #click VBase4(0.8, 0.8, 0.8, 1), #hover VBase4(0.5, 0.5, 0.5, 1)), #disabled text=elementInfo.name, text_align=TextNode.ALeft, relief=DGG.FLAT, pos=(self.structureFrame["frameSize"][0] + 20 * parentsLevel, 0, z), scale=16, command=self.__selectElement, extraArgs=[elementInfo], parent=self.structureFrame.getCanvas()) btn.bind(DGG.MWDOWN, self.scroll, [0.01]) btn.bind(DGG.MWUP, self.scroll, [-0.01]) if self.selectedElement is not None and self.selectedElement == elementInfo: btn.setColorScale(1, 1, 0, 1) # Delete Button btnX = DirectButton( relief=DGG.FLAT, pos=(self.structureFrame["frameSize"][0] + 8 + margin + 20 * parentsLevel + btn.getWidth() * btn.getScale()[0], 0, z + shift), frameSize=(-8, 8, -8, 8), frameColor=(0, 0, 0, 0), command=self.__removeElement, extraArgs=[elementInfo], image="icons/DeleteSmall.png", image_scale=8, parent=self.structureFrame.getCanvas()) btnX.setTransparency(TransparencyAttrib.M_multisample) btnX.bind(DGG.MWDOWN, self.scroll, [0.01]) btnX.bind(DGG.MWUP, self.scroll, [-0.01]) # Visibility Button btnV = DirectCheckBox( relief=DGG.FLAT, pos=(self.structureFrame["frameSize"][0] + 8 + margin * 2 + 20 * parentsLevel + btn.getWidth() * btn.getScale()[0] + btnX.getWidth(), 0, z + shift), frameSize=(-8, 8, -8, 8), frameColor=(0, 0, 0, 0), command=self.__toggleElementVisibility, extraArgs=[elementInfo], image="icons/VisibilityOffSmall.png" if elementInfo.element.isHidden() else "icons/VisibilityOnSmall.png", uncheckedImage="icons/VisibilityOffSmall.png", checkedImage="icons/VisibilityOnSmall.png", image_scale=8, isChecked=not elementInfo.element.isHidden(), parent=self.structureFrame.getCanvas()) btnV.setTransparency(TransparencyAttrib.M_multisample) btnV.bind(DGG.MWDOWN, self.scroll, [0.01]) btnV.bind(DGG.MWUP, self.scroll, [-0.01]) self.maxWidth = max(self.maxWidth, btnV.getX() + 8) def __selectElement(self, elementInfo, args=None): if elementInfo is not None: base.messenger.send("selectElement", [elementInfo, args]) def __removeElement(self, elementInfo): if elementInfo is not None: base.messenger.send("removeElement", [elementInfo.element]) def __toggleElementVisibility(self, toggle, elementInfo): if elementInfo is not None: base.messenger.send("toggleElementVisibility", [elementInfo.element]) def __collapseElement(self, collapse, elementInfo): if elementInfo is not None: if collapse: self.collapsedElements.append(elementInfo) else: self.collapsedElements.remove(elementInfo) base.messenger.send("refreshStructureTree")
class DirectFolderBrowser(DirectObject): def __init__(self, command, fileBrowser=False, defaultPath="~", defaultFilename="unnamed.txt", fileExtensions=[], tooltip=None): """ A simple file and folder browser command: The command that will be called on closing the browser fileBrowser: If set to True the browser will show files, otherwise it will only show folders defaultPath: The initial path the browser will be set to show defaultFilename: The filename that will be set by default, only usefull if fileBrowser is True fileExtensions: A list of extensions. Only files with those extensions will be shown. Only usefull if fileBrowser is True tooltip: An instance of the Tooltip class to display tooltips for certain parts of the editor """ self.tt = tooltip self.command = command self.showFiles = fileBrowser self.fileExtensions = fileExtensions self.showHidden = False self.currentPath = os.path.expanduser(defaultPath) if not os.path.exists(self.currentPath): self.currentPath = os.path.expanduser("~") self.previousPath = self.currentPath self.screenWidthPx = base.getSize()[0] self.screenWidthPxHalf = self.screenWidthPx * 0.5 self.screenHeightPx = base.getSize()[1] self.screenHeightPxHalf = self.screenHeightPx * 0.5 self.mainFrame = DirectFrame( relief=1, frameSize=(-self.screenWidthPxHalf,self.screenWidthPxHalf,-self.screenHeightPxHalf,self.screenHeightPxHalf), frameColor=(1, 1, 1, 1), pos=LPoint3f(base.getSize()[0]/2, 0, -base.getSize()[1]/2), parent=base.pixel2d, state=DGG.NORMAL, ) self.pathRightMargin = 153 self.pathEntryWidth = self.screenWidthPx - self.pathRightMargin self.pathEntry = DirectEntry( parent=self.mainFrame, relief=DGG.SUNKEN, frameColor=(1, 1, 1, 1), pad=(0.2, 0.2), pos=LPoint3f(-self.screenWidthPxHalf + 15, 0, self.screenHeightPxHalf - 25), scale=12, width=self.pathEntryWidth/12, overflow=True, command=self.entryAccept, initialText=self.currentPath, focusInCommand=base.messenger.send, focusInExtraArgs=["unregisterKeyboardEvents"], focusOutCommand=base.messenger.send, focusOutExtraArgs=["reregisterKeyboardEvents"], ) x = self.pathEntryWidth/2-28 self.btnReload = DirectButton( parent=self.mainFrame, relief=1, frameColor = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-14, 14, -10, 18), pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25), command=self.folderReload, image="icons/Reload.png", image_scale=14, image_pos=(0,0,4), ) self.btnReload.setTransparency(TransparencyAttrib.M_multisample) if self.tt is not None: self.btnReload.bind(DGG.ENTER, self.tt.show, ["Reload Folder"]) self.btnReload.bind(DGG.EXIT, self.tt.hide) x += 28 self.btnFolderUp = DirectButton( parent=self.mainFrame, relief=1, frameColor = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-14, 14, -10, 18), pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25), command=self.folderUp, image="icons/FolderUp.png", image_scale=14, image_pos=(0,0,4), ) self.btnFolderUp.setTransparency(TransparencyAttrib.M_multisample) if self.tt is not None: self.btnFolderUp.bind(DGG.ENTER, self.tt.show, ["Move up one level"]) self.btnFolderUp.bind(DGG.EXIT, self.tt.hide) x += 28 self.btnFolderNew = DirectButton( parent=self.mainFrame, relief=1, frameColor = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-14, 14, -10, 18), pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25), command=self.folderNew, image="icons/FolderNew.png", image_scale=14, image_pos=(0,0,4), ) self.btnFolderNew.setTransparency(TransparencyAttrib.M_multisample) if self.tt is not None: self.btnFolderNew.bind(DGG.ENTER, self.tt.show, ["Create new folder"]) self.btnFolderNew.bind(DGG.EXIT, self.tt.hide) x += 28 self.btnFolderShowHidden = DirectButton( parent=self.mainFrame, relief=1, frameColor = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-14, 14, -10, 18), pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25), command=self.folderShowHidden, image="icons/FolderShowHidden.png", image_scale=14, image_pos=(0,0,4), ) self.btnFolderShowHidden.setTransparency(TransparencyAttrib.M_multisample) if self.tt is not None: self.btnFolderShowHidden.bind(DGG.ENTER, self.tt.show, ["Show/Hide hidden files and folders"]) self.btnFolderShowHidden.bind(DGG.EXIT, self.tt.hide) color = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)) # Disabled self.container = DirectScrolledFrame( relief=DGG.RIDGE, borderWidth=(2, 2), frameColor=(1, 1, 1, 1), frameSize=(-self.screenWidthPxHalf+10, self.screenWidthPxHalf-10, -self.screenHeightPxHalf+50, self.screenHeightPxHalf-50), canvasSize=(-self.screenWidthPxHalf+31, self.screenWidthPxHalf-10, -self.screenHeightPxHalf+50, self.screenHeightPxHalf-50), pos=LPoint3f(0, 0, 0), parent=self.mainFrame, scrollBarWidth=20, verticalScroll_scrollSize=20, verticalScroll_thumb_relief=DGG.FLAT, verticalScroll_incButton_relief=DGG.FLAT, verticalScroll_decButton_relief=DGG.FLAT, verticalScroll_thumb_frameColor=color, verticalScroll_incButton_frameColor=color, verticalScroll_decButton_frameColor=color, horizontalScroll_thumb_relief=DGG.FLAT, horizontalScroll_incButton_relief=DGG.FLAT, horizontalScroll_decButton_relief=DGG.FLAT, horizontalScroll_thumb_frameColor=color, horizontalScroll_incButton_frameColor=color, horizontalScroll_decButton_frameColor=color, state=DGG.NORMAL, ) self.container.bind(DGG.MWDOWN, self.scroll, [0.01]) self.container.bind(DGG.MWUP, self.scroll, [-0.01]) self.btnOk = DirectButton( parent=self.mainFrame, relief=1, frameColor = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-45, 45, -6, 14), pos=LPoint3f(self.screenWidthPxHalf-160, 0, -self.screenHeightPxHalf+25), text = "ok", text_scale=12, command=command, extraArgs=[1], ) self.btnCancel = DirectButton( parent=self.mainFrame, relief=1, frameColor = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-45, 45, -6, 14), pos=LPoint3f(self.screenWidthPxHalf-55, 0, -self.screenHeightPxHalf+25), text = "Cancel", text_scale=12, command=command, extraArgs=[0] ) if self.showFiles: self.txtFileName = DirectEntry( parent=self.mainFrame, relief=DGG.SUNKEN, frameColor=(1, 1, 1, 1), pad=(0.2, 0.2), pos=LPoint3f(-self.screenWidthPxHalf+25, 0, -self.screenHeightPxHalf+25), scale=12, width=200/12, overflow=True, command=self.filenameAccept, initialText=defaultFilename, focusInCommand=base.messenger.send, focusInExtraArgs=["unregisterKeyboardEvents"], focusOutCommand=base.messenger.send, focusOutExtraArgs=["reregisterKeyboardEvents"], ) self.newFolderFrame = DirectFrame( parent=self.mainFrame, relief=1, frameSize=(-self.screenWidthPxHalf+10,self.screenWidthPxHalf-10,-20,20), pos=LPoint3f(0, 0, self.screenHeightPxHalf-55), frameColor=(0.5,0.5,0.5,1), ) self.txtNewFolderName = DirectLabel( parent=self.newFolderFrame, text="New Folder Name", text_scale=12, frameColor=(0,0,0,0), text_align=TextNode.ALeft, pos=(-self.screenWidthPxHalf+15, 0, -3), ) self.folderName = DirectEntry( parent=self.newFolderFrame, relief=DGG.SUNKEN, frameColor=(1, 1, 1, 1), pad=(0.2, 0.2), pos=LPoint3f(-self.screenWidthPxHalf+25 + self.txtNewFolderName.getWidth(), 0, -4), scale=12, width=((self.screenWidthPxHalf-25)*2-self.txtNewFolderName.getWidth() - 100)/12, overflow=True, command=self.entryAccept, initialText="New Folder", focusInCommand=base.messenger.send, focusInExtraArgs=["unregisterKeyboardEvents"], focusOutCommand=base.messenger.send, focusOutExtraArgs=["reregisterKeyboardEvents"], ) self.btnCreate = DirectButton( parent=self.newFolderFrame, relief=1, frameColor = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-45, 45, -6, 14), pos=LPoint3f(self.screenWidthPxHalf-65, 0, -4), text = "Create", text_scale=12, command=self.folderCreate, extraArgs=[0] ) self.newFolderFrame.hide() self.folderReload() # handle window resizing self.prevScreenSize = base.getSize() self.accept("window-event", self.windowEventHandler) def show(self): self.mainFrame.show() self.accept("window-event", self.windowEventHandler) def hide(self): self.ignore("window-event") self.mainFrame.hide() def destroy(self): self.ignore("window-event") self.mainFrame.destroy() def scroll(self, scrollStep, event): self.container.verticalScroll.scrollStep(scrollStep) def get(self): if self.showFiles: return os.path.join(self.currentPath, self.txtFileName.get(True)) return self.currentPath def filenameAccept(self, filename): self.command(1) def entryAccept(self, path): self.folderReload() def folderReload(self): for element in self.container.getCanvas().getChildren(): element.removeNode() path = self.pathEntry.get(True) path = os.path.expanduser(path) path = os.path.expandvars(path) if not os.path.exists(path): return self.currentPath = path try: content = os.scandir(path) except PermissionError: base.messenger.send("showWarning", ["Access denied!"]) self.pathEntry.set(self.previousPath) self.currentPath = self.previousPath self.folderReload() return # start position for the folders and files xPos = -self.screenWidthPxHalf + 20 + 50 - 110 zPos = self.screenHeightPxHalf-60-40 dirList = [] fileList = [] unkList = [] for entry in content: if entry.name.startswith(".") and not self.showHidden: continue if entry.is_dir(): dirList.append(entry) elif entry.is_file() and self.showFiles: if len(self.fileExtensions) > 0: if os.path.splitext(entry.name)[1] in self.fileExtensions: fileList.append(entry) else: fileList.append(entry) elif self.showFiles: unkList.append(entry) def moveNext(entry): nonlocal xPos nonlocal zPos if entry.is_dir() or self.showFiles: if xPos + 110 > self.screenWidthPxHalf - 45: # move to the next line if we hit the right border (incl. scrollbar size) xPos = -self.screenWidthPxHalf + 20 + 50 zPos -= 110 else: # move right the next position xPos += 110 def getKey(item): return item.name.lower() for entry in sorted(dirList, key=getKey): moveNext(entry) self.__createFolder(entry, xPos, zPos) for entry in sorted(fileList, key=getKey): moveNext(entry) self.__createFile(entry.name, xPos, zPos) for entry in sorted(unkList, key=getKey): moveNext(entry) self.__createUnknown(entry.name, xPos, zPos) # recalculate the canvas size self.container["canvasSize"] = (-self.screenWidthPxHalf+31, self.screenWidthPxHalf-15, zPos-90, self.screenHeightPxHalf-50) self.container.setCanvasSize() def folderUp(self): self.previousPath = self.currentPath self.currentPath = os.path.normpath(os.path.join(self.currentPath, "..")) self.pathEntry.set(self.currentPath) self.folderReload() def folderMoveIn(self, path): path = os.path.expanduser(path) path = os.path.expandvars(path) self.previousPath = self.currentPath self.currentPath = path self.pathEntry.set(path) self.folderReload() self.container.verticalScroll["value"] = 0 def folderNew(self): if self.newFolderFrame.isHidden(): self.newFolderFrame.show() else: self.newFolderFrame.hide() def folderShowHidden(self): self.showHidden = not self.showHidden self.folderReload() def folderCreate(self, path=""): try: os.makedirs(os.path.join(self.currentPath, self.folderName.get(True))) except: base.messenger.send("showWarning", ["Can't create folder"]) self.newFolderFrame.hide() self.folderReload() def __createFolder(self, entry, xPos, zPos): name = entry.name if len(entry.name) > 10: name = "" for i in range(max(math.ceil(len(entry.name)/10), 4)): name += entry.name[i*10:i*10+10]+"\n" name = name[:-1] if math.ceil(len(entry.name)/10) > 4: name += "..." btn = DirectButton( parent=self.container.getCanvas(), image="icons/Folder.png", image_scale=35, relief=1, frameColor = ( (0.9, 0.9, 0.9, 0), # Normal (0.95, 0.95, 1, 1), # Click (0.9, 0.9, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-40, 40, -40, 40), pos=LPoint3f(xPos, 0, zPos), text = name, text_scale=12, text_pos=(0,-40), command=self.folderMoveIn, extraArgs=[entry.path] ) btn.bind(DGG.MWDOWN, self.scroll, [0.01]) btn.bind(DGG.MWUP, self.scroll, [-0.01]) btn.setTransparency(TransparencyAttrib.M_multisample) def __createFile(self, filename, xPos, zPos): name = filename if len(filename) > 10: name = "" for i in range(min(math.ceil(len(filename)/10), 4)): name += filename[i*10:i*10+10]+"\n" name = name[:-1] if math.ceil(len(filename)/10) > 4: name += "..." btn = DirectButton( parent=self.container.getCanvas(), image="icons/File.png", image_scale=35, relief=1, frameColor = ( (0.9, 0.9, 0.9, 0), # Normal (0.95, 0.95, 1, 1), # Click (0.9, 0.9, 1, 1), # Hover (0.5, 0.5, 0.5, 1)), # Disabled frameSize=(-40, 40, -40, 40), pos=LPoint3f(xPos, 0, zPos), text = name, text_scale=12, text_pos=(0,-40), command=self.txtFileName.set, extraArgs=[filename] ) btn.bind(DGG.MWDOWN, self.scroll, [0.01]) btn.bind(DGG.MWUP, self.scroll, [-0.01]) btn.setTransparency(TransparencyAttrib.M_multisample) def __createUnknown(self, filename, xPos, zPos): name = filename if len(filename) > 10: name = "" for i in range(math.ceil(len(filename)/10)): name += filename[i*10:i*10+10]+"\n" name = name[:-1] lbl = DirectLabel( parent=self.container.getCanvas(), image="icons/File.png", image_scale=35, image_color=(0.9,0.5,0.5,1), relief=1, frameColor = (0.7, 0.7, 0.7, 0), frameSize=(-40, 40, -40, 40), pos=LPoint3f(xPos, 0, zPos), text = name, text_scale=12, text_pos=(0,-40), ) lbl.bind(DGG.MWDOWN, self.scroll, [0.01]) lbl.bind(DGG.MWUP, self.scroll, [-0.01]) lbl.setTransparency(TransparencyAttrib.M_multisample) def windowEventHandler(self, window=None): if window != base.win: # This event isn't about our window. return if window is not None: # window is none if panda3d is not started if self.prevScreenSize == base.getSize(): return self.prevScreenSize = base.getSize() self.screenWidthPx = base.getSize()[0] self.screenWidthPxHalf = self.screenWidthPx * 0.5 self.screenHeightPx = base.getSize()[1] self.screenHeightPxHalf = self.screenHeightPx * 0.5 # reposition and resize all gui elements self.mainFrame.setPos(self.screenWidthPx/2, 0, -self.screenHeightPx/2) self.mainFrame["frameSize"] = (-self.screenWidthPxHalf,self.screenWidthPxHalf,-self.screenHeightPxHalf,self.screenHeightPxHalf) self.pathEntryWidth = self.screenWidthPx - self.pathRightMargin self.pathEntry.setPos(LPoint3f(-self.screenWidthPxHalf + 15, 0, self.screenHeightPxHalf - 25)) self.pathEntry["width"] = self.pathEntryWidth/12 self.pathEntry.resetFrameSize() # reposition top right icons x = self.pathEntryWidth/2-28 self.btnReload.setPos(LPoint3f(x, 0, self.screenHeightPxHalf - 25)) x += 28 self.btnFolderUp.setPos(pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25)) x += 28 self.btnFolderNew.setPos(pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25)) x += 28 self.btnFolderShowHidden.setPos(pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25)) # resize the browsing area self.container["frameSize"] = (-self.screenWidthPxHalf+10, self.screenWidthPxHalf-10, -self.screenHeightPxHalf+50, self.screenHeightPxHalf-50) # Note: canvas size of the container will be reset in the # folder Reload call at the end of this function self.btnOk.setPos(LPoint3f(self.screenWidthPxHalf-160, 0, -self.screenHeightPxHalf+25)) self.btnCancel.setPos(LPoint3f(self.screenWidthPxHalf-55, 0, -self.screenHeightPxHalf+25)) if self.showFiles: self.txtFileName.setPos(LPoint3f(-self.screenWidthPxHalf+25, 0, -self.screenHeightPxHalf+25)) self.newFolderFrame.setPos(LPoint3f(0, 0, self.screenHeightPxHalf-55)) self.newFolderFrame["frameSize"] = (-self.screenWidthPxHalf+10,self.screenWidthPxHalf-10,-20,20) self.txtNewFolderName.setPos(-self.screenWidthPxHalf+15, 0, -3) self.folderName.setPos(LPoint3f(-self.screenWidthPxHalf+25 + self.txtNewFolderName.getWidth(), 0, -4)) self.folderName["width"]=((self.screenWidthPxHalf-25)*2-self.txtNewFolderName.getWidth() - 100)/12 self.btnCreate.setPos(LPoint3f(self.screenWidthPxHalf-65, 0, -4)) self.folderReload()
class ToolboxPanel: def __init__(self, parent): height = DGH.getRealHeight(parent) self.parent = parent self.box = DirectBoxSizer(frameColor=(0.25, 0.25, 0.25, 1), autoUpdateFrameSize=False, orientation=DGG.VERTICAL) self.sizer = DirectAutoSizer(parent=parent, child=self.box, childUpdateSizeFunc=self.box.refresh) self.lblHeader = DirectLabel( text="Toolbox", text_scale=16, text_align=TextNode.ALeft, text_fg=(1, 1, 1, 1), frameColor=VBase4(0, 0, 0, 0), ) self.box.addItem(self.lblHeader) color = ( (0.8, 0.8, 0.8, 1), # Normal (0.9, 0.9, 1, 1), # Click (0.8, 0.8, 1, 1), # Hover (0.5, 0.5, 0.5, 1)) # Disabled self.toolboxFrame = DirectScrolledFrame( # make the frame fit into our background frame frameSize=VBase4( self.parent["frameSize"][0], self.parent["frameSize"][1], self.parent["frameSize"][2] + DGH.getRealHeight(self.lblHeader), self.parent["frameSize"][3]), scrollBarWidth=20, verticalScroll_scrollSize=20, verticalScroll_thumb_relief=DGG.FLAT, verticalScroll_incButton_relief=DGG.FLAT, verticalScroll_decButton_relief=DGG.FLAT, verticalScroll_thumb_frameColor=color, verticalScroll_incButton_frameColor=color, verticalScroll_decButton_frameColor=color, horizontalScroll_thumb_relief=DGG.FLAT, horizontalScroll_incButton_relief=DGG.FLAT, horizontalScroll_decButton_relief=DGG.FLAT, horizontalScroll_thumb_frameColor=color, horizontalScroll_incButton_frameColor=color, horizontalScroll_decButton_frameColor=color, state=DGG.NORMAL) self.box.addItem(self.toolboxFrame) self.toolboxFrame.bind(DGG.MWDOWN, self.scroll, [0.01]) self.toolboxFrame.bind(DGG.MWUP, self.scroll, [-0.01]) self.toolboxEntries = [ ["~Interactive Elements~"], ["Button", "DirectButton"], ["Entry", "DirectEntry"], ["Scrolled Entry", "DirectEntryScroll"], ["Check Box", "DirectCheckBox"], ["Check Button", "DirectCheckButton"], ["Option Menu", "DirectOptionMenu"], ["Radio Button", "DirectRadioButton"], ["Slider", "DirectSlider"], ["Scroll Bar", "DirectScrollBar"], ["Scrolled List Item", "DirectScrolledListItem"], ["~Display Elements~"], ["Label", "DirectLabel"], ["Wait Bar", "DirectWaitBar"], ["~Container~"], ["Frame", "DirectFrame"], ["Scrolled Frame", "DirectScrolledFrame"], ["Scrolled List", "DirectScrolledList"], ["~Dialogs~"], ["OK Dialog", "OkDialog"], ["OK Cancel Dialog", "OkCancelDialog"], ["Yes No Dialog", "YesNoDialog"], ["Yes No Cancel Dialog", "YesNoCancelDialog"], ["Retry Cancel Dialog", "RetryCancelDialog"], ] self.createEntries() def scroll(self, scrollStep, event): self.toolboxFrame.verticalScroll.scrollStep(scrollStep) def createEntries(self): # Empty the toolbox if there were any elements for child in self.toolboxFrame.getCanvas().getChildren(): child.removeNode() idx = 1 for entry in self.toolboxEntries: if len(entry) == 2: item = self.__makeToolboxListItem(entry[0], entry[1], idx) item.reparentTo(self.toolboxFrame.getCanvas()) else: item = self.__makeToolboxCenteredListItem(entry[0], idx) item.reparentTo(self.toolboxFrame.getCanvas()) item.bind(DGG.MWDOWN, self.scroll, [0.01]) item.bind(DGG.MWUP, self.scroll, [-0.01]) idx += 1 self.toolboxFrame["canvasSize"] = (self.parent["frameSize"][0], self.parent["frameSize"][1] - 20, -(len(self.toolboxEntries) * 30), 0) self.toolboxFrame.setCanvasSize() def resizeFrame(self): self.sizer.refresh() self.toolboxFrame["frameSize"] = (self.parent["frameSize"][0], self.parent["frameSize"][1], self.parent["frameSize"][2] + DGH.getRealHeight(self.lblHeader), self.parent["frameSize"][3]) self.createEntries() def __createControl(self, name): base.messenger.send("createControl", [name]) def __makeToolboxListItem(self, displayName, name, index): item = DirectButton( text=displayName, frameSize=VBase4(self.parent["frameSize"][0], self.parent["frameSize"][1] - 20, -10, 20), frameColor=( VBase4(1, 1, 1, 1), #normal VBase4(0.9, 0.9, 0.9, 1), #click VBase4(0.8, 0.8, 0.8, 1), #hover VBase4(0.5, 0.5, 0.5, 1)), #disabled text_align=TextNode.ALeft, text_scale=12, text_pos=(self.parent["frameSize"][0], 0), pos=(0, 0, -30 * index + 10), relief=DGG.FLAT, command=self.__createControl, extraArgs=[name], #suppressMouse=0 ) return item def __makeToolboxCenteredListItem(self, displayName, index): item = DirectFrame( text=displayName, frameSize=VBase4(-self.parent["frameSize"][1], self.parent["frameSize"][1], -10, 20), frameColor=VBase4(0.85, 0.85, 0.85, 1), text_align=TextNode.ACenter, text_scale=16, text_pos=(-10, 0), pos=(0, 0, -30 * index + 10), #self.parent["frameSize"][1]/2-10 state=DGG.NORMAL, #suppressMouse=0 ) return item