Esempio n. 1
0
    def renderBuffers(self):
        self.buffersParent.node().removeAllChildren()

        posX = 0
        posY = 0

        for name in self.bufferOrder:
            target = self.buffers[name]
            for targetType in RenderTargetType.All:
                if not target.hasTarget(targetType):
                    continue
                tex = target.getTexture(targetType)
                sizeStr = str(tex.getXSize()) + " x " + str(tex.getYSize())

                if tex.getZSize() != 1:
                    sizeStr += " x " + str(tex.getZSize())

                sizeStr += " - " + str(self.calculateTexSize(tex)) + " MB"

                node = DirectFrame(parent=self.buffersParent, frameColor=(
                    1, 1, 1, 0.2), frameSize=(-self.innerPadding, self.texWidth + self.innerPadding, -self.texHeight - 30 - self.innerPadding, self.innerPadding + 15),
                    state=DGG.NORMAL)
                node.setPos(
                    20 + posX * (self.texWidth + self.texPadding), 0, -self.paddingTop - 22 - posY * (self.texHeight + self.texPadding + 44))
                node.bind(DGG.ENTER, partial(self.onMouseOver, node))
                node.bind(DGG.EXIT, partial(self.onMouseOut, node))
                node.bind(DGG.B1RELEASE, partial(self.showDetail, tex))

                aspect = tex.getYSize() / float(tex.getXSize())
                computedWidth = self.texWidth
                computedHeight = self.texWidth * aspect

                if computedHeight > self.texHeight:
                    # have to scale tex width instead
                    computedHeight = self.texHeight
                    computedWidth = tex.getXSize() / float(tex.getYSize()) * \
                        self.texHeight

                img = BetterOnscreenImage(
                    image=tex, parent=node, x=0, y=30, w=computedWidth,
                    h=computedHeight, transparent=False, nearFilter=False,
                    anyFilter=False)
                txtName = BetterOnscreenText(
                    text=name, x=0, y=0, size=13, parent=node)
                txtSizeFormat = BetterOnscreenText(
                    text=sizeStr, x=0, y=20, size=13, parent=node,
                    color=Vec3(0.2))
                txtTarget = BetterOnscreenText(
                    text=str(targetType), align="right", x=self.texWidth,
                    y=20, size=13, parent=node, color=Vec3(0.2))

                posX += 1
                if posX > self.pageSize:
                    posY += 1
                    posX = 0
Esempio n. 2
0
    def __init__(self, image, carPos, trackDir):
        ShowBase.__init__(self)
        self.image = image
        # add show image function
        #OnscreenImage(image=image, pos=(0, 0, 0))
        bg = DirectFrame(image=image, sortOrder=(-1))
        bg.setPos(0, 20, 0)
        bg.reparentTo(render2d)

        nrDisplayRegions = self.camera.getNumDisplayRegions()
        print(nrDisplayRegions)
        self.carPos = carPos
        self.carModel = None
        self.loadModels(carPos)
        self.trackDir = trackDir
Esempio n. 3
0
def load(args):
    """Sets up the GUI for the main menu.
    Arguments:
        This takes no arguments.
    """

    global backFrame
    global menuFrame
    global pauseText
    global backButton

    font_digital = loader.loadFont('digital.egg')

    backFrame = DirectFrame()
    backFrame['frameColor'] = (0, 0, 0, .5)
    backFrame['frameSize'] = (2, -2, 2, -2)
    backFrame.setPos(0, 0, 0)

    menuFrame = DirectFrame()
    menuFrame.reparentTo(backFrame)
    menuFrame['frameColor'] = (1, 1, 1, .5)
    menuFrame['frameSize'] = (.5, -.5, .5, -.5)
    menuFrame.setPos(0, 0, 0)

    pauseText = OnscreenText()
    pauseText['text'] = ('PAUSED')
    pauseText['scale'] = (.1)
    pauseText['font'] = (font_digital)
    pauseText['fg'] = (1, 1, 1, 1)
    pauseText.setPos(0, .9)

    backButton = DirectButton()
    backButton.reparentTo(menuFrame)
    backButton['text'] = ('Back')
    backButton['text_scale'] = (.1)
    backButton['text_pos'] = (0, -0.03)
    backButton['frameVisibleScale'] = (2, 0.5, 0)
    backButton['frameColor'] = (1, 1, 1, 0)
    backButton['command'] = (messenger.send)
    backButton['extraArgs'] = ("switch_gui", [gui.menu.pause_options, gui.menu.pause])
    backButton.setPos(0, 0, 0)
Esempio n. 4
0
class NodeBase(DirectObject):
    def __init__(self, name, parent):
        self.right = 0.5
        self.left = -0.5
        self.name = name
        self.nodeID = uuid4()
        self.inputList = []
        self.outputList = []
        self.selected = False

        self.frame = DirectFrame(state=DGG.NORMAL,
                                 text=name,
                                 text_align=TextNode.A_left,
                                 text_scale=0.1,
                                 text_pos=(self.left, 0.12),
                                 text_fg=(1, 1, 1, 1),
                                 frameColor=(0.25, 0.25, 0.25, 1),
                                 frameSize=(-0.5, 0.5, -.6, 0.2),
                                 parent=parent)

        self.setupBind()
        self.hide()

        self.setPos = self.frame.setPos
        self.getPos = self.frame.getPos

    def addIn(self, name, socketType):
        """Add a new input socket of the given socket type"""
        inSocket = socketType(self, name)
        self.inputList.append(inSocket)

    def addOut(self, name):
        """Add a new output socket"""
        outSocket = OutSocket(self, name)
        self.outputList.append(outSocket)

    def isLeaveNode(self):
        """Returns true if this is a leave node.
        Leave nodes do not have any input connections. Either if no
        input sockets are defined at all or none of the sockets is
        connected."""

        # check if we have any input sockets and if so if any of them is connected
        for inSocket in self.inputList:
            if inSocket.connected: return False
        return True

    def logic(self):
        """Run the logic of this node, process all in and output data.
        This is a stub and should be overwritten by the derived classes"""
        pass

    def update(self):
        """Show all sockets and resize the frame to fit all sockets in"""
        z = 0

        for outSocket in self.outputList:
            outSocket.show(z, self.right)
            z -= outSocket.height

        for inSocket in self.inputList:
            inSocket.show(z, self.left)
            z -= inSocket.height

        fs = self.frame["frameSize"]
        self.frame["frameSize"] = (fs[0], fs[1], z, fs[3])

    def create(self):
        """Place and show the node under the mouse and start draging it."""
        mwn = base.mouseWatcherNode
        if mwn.hasMouse():
            newPos = Point3(mwn.getMouse()[0], 0, mwn.getMouse()[1])
            self.frame.setPos(render2d, newPos)
        self._dragStart(self.frame, None)
        self.show()

    def show(self):
        """Shows the Node frame and updates its sockets"""
        self.update()
        self.frame.show()

    def hide(self):
        """Hide the Node frame"""
        self.frame.hide()

    def destroy(self):
        self.frame.destroy()

    def setupBind(self):
        """Setup the mousebutton actions for drag and drop feature"""
        self.frame.bind(DGG.B1PRESS, self._dragStart, [self.frame])
        self.frame.bind(DGG.B1RELEASE, self._dragStop)

    def select(self, select):
        """Set this node as selected or deselected"""
        if self.selected == select: return
        self.selected = select
        if self.selected:
            self.frame["frameColor"] = (0.45, 0.45, 0.45, 1)
        else:
            self.frame["frameColor"] = (0.25, 0.25, 0.25, 1)

    def _dragStart(self, nodeFrame, event):
        # Mark this node as selected
        base.messenger.send("selectNode", [
            self, True,
            base.mouseWatcherNode.isButtonDown(KeyboardButton.shift()), True
        ])
        # tell everyone we started to drag this node
        base.messenger.send("dragNodeStart", [self])

        # Remove any previous started drag tasks
        taskMgr.remove("dragNodeDropTask")

        # get some positions
        vWidget2render2d = nodeFrame.getPos(render2d)
        vMouse2render2d = Point3(0)
        if event is not None:
            # we get the mouse position from the event
            vMouse2render2d = Point3(event.getMouse()[0], 0,
                                     event.getMouse()[1])
        else:
            # we try to get the current mouse position from the mouse watcher
            mwn = base.mouseWatcherNode
            if mwn.hasMouse():
                vMouse2render2d = Point3(mwn.getMouse()[0], 0,
                                         mwn.getMouse()[1])
        editVec = Vec3(vWidget2render2d - vMouse2render2d)
        self.hasMoved = False

        # Initiate the task to move the node and pass it some initial values
        t = taskMgr.add(self.dragTask, "dragNodeDropTask")
        t.nodeFrame = nodeFrame
        t.editVec = editVec
        t.mouseVec = vMouse2render2d

    def dragTask(self, t):
        mwn = base.mouseWatcherNode
        if mwn.hasMouse():
            # get the current mouse position fitting for a render2d position
            vMouse2render2d = Point3(mwn.getMouse()[0], 0, mwn.getMouse()[1])

            # check if the cursor has moved enough to drag this node
            # this gives us some puffer zone for clicking
            if not self.hasMoved and (t.mouseVec -
                                      vMouse2render2d).length() < 0.01:
                return t.cont

            # We actually have moved now
            self.hasMoved = True

            # calculate the new position
            newPos = vMouse2render2d + t.editVec

            # move the node to the new position
            t.nodeFrame.setPos(render2d, newPos)

            # tell everyone we moved the node
            base.messenger.send("dragNodeMove", [t.mouseVec, vMouse2render2d])

        return t.cont

    def _dragStop(self, event=None):
        self.ignore("mouse1-up")
        # remove the node dragging task
        taskMgr.remove("dragNodeDropTask")

        # check if the node has moved
        if not self.hasMoved:
            # we want to select this node as it has not been moved
            base.messenger.send("selectNode", [
                self, True,
                base.mouseWatcherNode.isButtonDown(KeyboardButton.shift())
            ])
        # tell everyone we stopped moving the node
        base.messenger.send("dragNodeStop", [self])

    def getLeftEdge(self):
        """Get the left edge of the frame as seen from the frame"""
        return self.frame["frameSize"][0]

    def getRightEdge(self):
        """Get the right edge of the frame as seen from the frame"""
        return self.frame["frameSize"][1]

    def getBottomEdge(self):
        """Get the bottom edge of the frame as seen from the frame"""
        return self.frame["frameSize"][2]

    def getTopEdge(self):
        """Get the top edge of the frame as seen from the frame"""
        return self.frame["frameSize"][3]

    def getLeft(self, np=None):
        """Get left edge of the frame with respect to it's position as seen from the given np"""
        if np is None:
            np = render2d
        return self.getPos(render2d).getX() + self.frame["frameSize"][0]

    def getRight(self, np=None):
        """Get right edge of the frame with respect to it's position as seen from the given np"""
        if np is None:
            np = render2d
        return self.getPos(render2d).getX() + self.frame["frameSize"][1]

    def getBottom(self, np=None):
        """Get bottom edge of the frame with respect to it's position as seen from the given np"""
        if np is None:
            np = render2d
        return self.getPos(render2d).getZ() + self.frame["frameSize"][2]

    def getTop(self, np=None):
        """Get top edge of the frame with respect to it's position as seen from the given np"""
        if np is None:
            np = render2d
        return self.getPos(render2d).getZ() + self.frame["frameSize"][3]
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 QuestRewardFrame(DirectFrame):
    notify = directNotify.newCategory('QuestRewardFrame')

    def __init__(self, poster, reward, **kw):
        optiondefs = (('relief', None, None), ('image',
                                               QuestGlobals.getJBIcon(), None),
                      ('image_scale', QuestGlobals.JB_JAR_SCALE,
                       None), ('state', DGG.NORMAL, None))
        self.defineoptions(kw, optiondefs)

        # Finally, initialize the DirectFrame.
        DirectFrame.__init__(self, parent=poster, relief=None)
        self.initialiseoptions(QuestRewardFrame)
        self.reward = reward

        gagShopGeom = loader.loadModel(
            'phase_4/models/gui/gag_shop_purchase_gui.bam')
        self.info = DirectFrame(parent=self,
                                relief=None,
                                geom=gagShopGeom.find('**/Char_Pnl'),
                                geom_scale=(0.15, 0, 0.1275),
                                text='0',
                                text_font=CIGlobals.getToonFont(),
                                text_scale=0.04,
                                text_fg=(0, 0, 0, 1),
                                text_align=TextNode.ACenter,
                                text_pos=(0, -0.01),
                                pos=(0, 0, -0.06))
        self.info.setBin('gui-popup', 40)

        gagShopGeom.removeNode()
        self.hide()

    def setup(self):
        if self.reward.rewardType == 1:
            # This is a jellybeans reward.
            self.setPos(QuestGlobals.LEFT_JB_JAR_POS)
            self.info['text'] = str(self.reward.rewardValue)
        elif self.reward.rewardType == 2:
            # This is a teleport access reward.
            self['image'] = QuestGlobals.getTPAccessIcon()
            self['image_scale'] = QuestGlobals.TP_ACCESS_SCALE
            self.setPos(QuestGlobals.LEFT_TP_ACCESS_POS)
            self.info['text'] = ZoneUtil.ZoneId2HoodAbbr[
                self.reward.rewardValue]
            self.info.setPos(-0.0025, 0, -0.04)
        elif self.reward.rewardType == 3:
            # This is a laff boost reward.
            r, g, b, _ = base.localAvatar.getHeadColor()
            hp = base.localAvatar.getMaxHealth() + self.reward.rewardValue
            laffMeter = LaffOMeter()
            laffMeter.generate(r,
                               g,
                               b,
                               base.localAvatar.getAnimal(),
                               maxHP=hp,
                               initialHP=hp)
            self['image'] = laffMeter
            self['image_scale'] = QuestGlobals.LAFF_METER_SCALE
            self.setPos(QuestGlobals.LEFT_LAFF_METER_POS)
            self.info['text'] = '+%d' % self.reward.rewardValue
            self.info.setPos(0, 0, -0.05)
            laffMeter.destroy()
        elif self.reward.rewardType == 5:
            # This is a gag slot reward.
            icon = QuestGlobals.getGagSlotIcon(self.reward.rewardValue)
            self['image'] = icon
            self['image_scale'] = QuestGlobals.GAG_SLOT_ICON_SCALE
            self.setTransparency(TransparencyAttrib.MAlpha)
            self.setPos(QuestGlobals.LEFT_GAG_SLOT_POS)
            self.info.hide()

        self.show()

    def destroy(self):
        if hasattr(self, 'reward'):
            self.info.destroy()
            del self.info
            del self.reward
            DirectFrame.destroy(self)
Esempio n. 7
0
def load(args):
    """Sets up the GUI for the in game pause menu.
    Arguments:
        args[0] -- The function for the 'resume' button.
        args[1] -- The function for the 'settings' button.
        args[2] -- The function for the 'exit' button.
    """
    # GUI should do what they are told, they should get data sent to them, not request it.

    global pauseText
    global backFrame
    global menuFrame
    global resumeButton

    font_digital = loader.loadFont("digital.egg")

    backFrame = DirectFrame()
    backFrame["frameSize"] = (2, -2, 2, -2)
    backFrame.setPos(0, 0, 0)

    backFrame["frameColor"] = (0, 0, 0, 0.5)
    menuFrame = DirectFrame()
    menuFrame.reparentTo(backFrame)
    menuFrame["frameColor"] = (1, 1, 1, 0.5)
    menuFrame["frameSize"] = (0.5, -0.5, 0.5, -0.5)
    menuFrame.setPos(0, 0, 0)

    buttonClickSound = loader.loadSfx("sound/buttonClick.wav")
    buttonRollSound = loader.loadSfx("sound/buttonRoll.wav")

    resumeButton = DirectButton()
    resumeButton.reparentTo(menuFrame)
    resumeButton["text"] = "Resume"
    resumeButton["text_scale"] = 0.1
    resumeButton["text_pos"] = (0, -0.03)
    resumeButton["frameVisibleScale"] = (2, 0.5, 0)
    resumeButton["frameColor"] = (1, 1, 1, 0)
    resumeButton["command"] = resume
    resumeButton["rolloverSound"] = buttonRollSound
    resumeButton["clickSound"] = buttonClickSound
    resumeButton.setPos(0, 0, 0.4)

    settingsButton = DirectButton()
    settingsButton.reparentTo(menuFrame)
    settingsButton["text"] = "Settings"
    settingsButton["text_scale"] = 0.1
    settingsButton["text_pos"] = (0, -0.03)
    settingsButton["frameVisibleScale"] = (2, 0.5, 0)
    settingsButton["frameColor"] = (1, 1, 1, 0)
    settingsButton["rolloverSound"] = buttonRollSound
    settingsButton["clickSound"] = buttonClickSound
    settingsButton["command"] = messenger.send  # Command to run
    settingsButton["extraArgs"] = ("switch_gui", [gui.menu.pause, gui.menu.pause_options])  # Args to send
    settingsButton.setPos(0, 0, 0.2)

    exitButton = DirectButton()
    exitButton.reparentTo(menuFrame)
    exitButton["text"] = "Exit"
    exitButton["text_scale"] = 0.1
    exitButton["text_pos"] = (0, -0.03)
    exitButton["frameVisibleScale"] = (2, 0.5, 0)
    exitButton["frameColor"] = (1, 1, 1, 0)
    exitButton["rolloverSound"] = buttonRollSound
    exitButton["clickSound"] = buttonClickSound
    exitButton["command"] = exit
    exitButton.setPos(0, 0, 0)

    pauseText = OnscreenText()
    pauseText["text"] = "PAUSED"
    pauseText["scale"] = 0.1
    pauseText["font"] = font_digital
    pauseText["fg"] = (1, 1, 1, 1)
    pauseText.setPos(0, 0.9)
class PathSelect(DirectObject):
    def __init__(self, command, headerText, actionText, affirmText, filePath,
                 tooltip):
        self.command = command
        self.darkenFrame = DirectFrame(
            relief=1,
            frameSize=(0, base.getSize()[0], -base.getSize()[1], 0),
            frameColor=(0, 0, 0, 0.45),
            state=DGG.NORMAL,
            parent=base.pixel2d,
        )
        self.mainFrame = DirectFrame(
            relief=1,
            frameSize=(-300, 300, -150, 150),
            frameColor=(1, 1, 1, 1),
            pos=LPoint3f(base.getSize()[0] / 2, 0, -base.getSize()[1] / 2),
            parent=base.pixel2d,
        )

        # Header
        headerFrame = DirectFrame(
            parent=self.mainFrame,
            relief=1,
            frameSize=(-300, 300, -20, 20),
            frameColor=(0.25, 0.25, 0.25, 1.0),
            pos=LPoint3f(0, 0, 130),
            scale=LVecBase3f(1, 0.1, 1),
        )
        DirectLabel(
            parent=headerFrame,
            frameColor=(0.8, 0.8, 0.8, 0.0),
            pos=LPoint3f(-295, 0, -5),
            text=headerText,
            text_align=0,
            text_fg=(1, 1, 1, 1),
            scale=16,
        )

        # Entry
        DirectLabel(
            parent=self.mainFrame,
            frameColor=(0.8, 0.8, 0.8, 0.0),
            pos=LPoint3f(-250, 0, 0),
            scale=12,
            text=actionText,
            text_align=0,
        )
        self.pathEntry = DirectEntry(parent=self.mainFrame,
                                     relief=DGG.SUNKEN,
                                     frameColor=(1, 1, 1, 1),
                                     pad=(0.2, 0.2),
                                     pos=LPoint3f(-250, 0, -20),
                                     scale=12,
                                     width=(500 - 90) / 12,
                                     overflow=True,
                                     command=self.entryCommandHandler,
                                     initialText=filePath)
        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(235, 0, -20),
            text="Browse",
            text_scale=12,
            command=self.browse,
        )
        self.browser = DirectFolderBrowser(self.selectPath,
                                           True,
                                           os.path.dirname(filePath),
                                           os.path.split(filePath)[1],
                                           tooltip=tooltip)
        self.browser.hide()

        # Command Buttons
        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(140, 0, -135),
            text=affirmText,
            text_scale=12,
            command=command,
            extraArgs=[1],
        )
        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(245, 0, -135),
            text="Cancel",
            text_scale=12,
            command=command,
            extraArgs=[0])

        # handle window resizing
        self.prevScreenSize = base.getSize()
        self.accept("window-event", self.windowEventHandler)
        self.accept("escape", command, extraArgs=[0])

    def browse(self):
        self.browser.show()

    def selectPath(self, confirm):
        if confirm:
            self.pathEntry.set(self.browser.get())
        self.browser.hide()

    def entryCommandHandler(self, text):
        self.command(1)

    def destroy(self):
        self.ignoreAll()
        self.browser.destroy()
        self.darkenFrame.destroy()
        self.mainFrame.destroy()

    def getPath(self):
        return self.pathEntry.get()

    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()
            screenWidthPx = base.getSize()[0]
            screenHeightPx = base.getSize()[1]

            self.mainFrame.setPos(screenWidthPx / 2, 0, -screenHeightPx / 2)
            self.darkenFrame["frameSize"] = (0, screenWidthPx, -screenHeightPx,
                                             0)
Esempio n. 9
0
class Chapter2(ChapterBase):
    def __init__(self, rootParent):
        ChapterBase.__init__(self, "chapter2/warehouse.png", rootParent)

        self.startPos = (-0.7, 0, -0.5)

        self.overlay = Overlay(rootParent)

        self.flashlightLight = DirectFrame(
            frameColor=(0.0, 0.0, 0.0, 1.0),
            frameSize=(-3.5, 3.5, -3.5, 3.5),
            image='chapter2/flashlightLight.png',
            image_scale=(3.5, 1, 3.5),
            parent=rootParent,
        )
        self.flashlightLight.setTransparency(1)
        self.flashLightActive = False

        self.accept("inventory_flashlight", self.activateFlashlight)

        self.accept("box1", self.box1)
        self.accept("box2", self.box2)
        self.accept("box3", self.box3)

        self.accept("mike", self.talkMike)

        base.messenger.send("animateChar", ["idle", "r", 3, True])
        base.messenger.send("showNote", ["I should turn on my flashlight"])

        base.taskMgr.add(self.flashlightTask, "flaslightLightTask")

    def destroy(self):
        base.taskMgr.remove("flaslightLightTask")
        ChapterBase.destroy(self)

    def talkMike(self):
        if self.flashLightActive:
            base.messenger.send("showNote", ["Wow! Such light. Much bright! ... Now I can check all the boxes!"])
        else:
            base.messenger.send("showNote", ["Yeah, who needs a lamp, I can just feel my way around here... Ouch my toe! Guess I should power up that lamp."])

    def activateFlashlight(self):
        if self.flashLightActive:
            self.flashlightLight["frameColor"] = (0,0,0,1)
            base.messenger.send("showNote", ["Without light, I won't see much in here..."])
        else:
            self.flashlightLight["frameColor"] = (0,0,0,0)
            base.messenger.send("showNote", ["That's better, now let's use that lightspot to search around this warehouse. (Light follows cursor)"])
        self.flashLightActive = not self.flashLightActive

    def flashlightTask(self, task):
        mwn = base.mouseWatcherNode
        if mwn.hasMouse():
            vMouse2render2d = Point3(mwn.getMouse()[0], 0, mwn.getMouse()[1])
            self.flashlightLight.setPos(render2d, vMouse2render2d)

        return task.cont

    def box1(self):
        base.messenger.send("addInventory", ["fakeID", "chapter2/fakeID.png"])
        base.messenger.send("showNote", ["O. Mike: Hey, look at that, fake ID cards of secret agents. This may be bigger than I thought..."])
        base.messenger.send("moveChar", [(-0.25, 0, -0.3)])

    def box2(self):
        base.messenger.send("showNote", ["O. Mike: A box full of weapons. Interesting, I'll better call the reinforcement to pick them up."])

    def box3(self):
        self.accept("continue", base.messenger.send, extraArgs=["switchToChapter", ["chapter3"]])
        base.messenger.send("moveChar", [(0.15, 0, -0.35)])
        base.messenger.send("showText", [STORY_BOX.copy()])
Esempio n. 10
0
class MenuBar():
    def __init__(self):
        screenWidthPx = base.getSize()[0]

        color = (
            (0.25, 0.25, 0.25, 1),  # Normal
            (0.35, 0.35, 1, 1),  # Click
            (0.25, 0.25, 1, 1),  # Hover
            (0.1, 0.1, 0.1, 1))  # Disabled

        #
        # Menubar
        #
        self.menuBar = DirectFrame(frameColor=(0.25, 0.25, 0.25, 1),
                                   frameSize=(0, screenWidthPx, -12, 12),
                                   pos=(0, 0, -12),
                                   parent=base.pixel2d)

        x = 0

        self.file = DirectOptionMenu(text_fg=(1, 1, 1, 1),
                                     text_scale=0.8,
                                     items=["New", "Save", "Load", "Quit"],
                                     pos=(x, 0, -5),
                                     frameSize=(0, 65 / 21, -7 / 21, 17 / 21),
                                     frameColor=color,
                                     scale=21,
                                     relief=DGG.FLAT,
                                     item_text_fg=(1, 1, 1, 1),
                                     item_text_scale=0.8,
                                     highlightScale=(0.8, 0.8),
                                     item_relief=DGG.FLAT,
                                     item_frameColor=color,
                                     item_pad=(0.2, 0.2),
                                     highlightColor=color[2],
                                     popupMenuLocation=DGG.BELOW,
                                     command=self.toolbarFileCommand,
                                     parent=self.menuBar)
        self.file["text"] = "File"

        x += 65

        self.view = DirectOptionMenu(
            text_fg=(1, 1, 1, 1),
            text_scale=0.8,
            items=["Zoom In", "Zoom Out", "Zoom 100%"],
            pos=(x, 0, -5),
            frameSize=(0, 65 / 21, -7 / 21, 17 / 21),
            frameColor=color,
            scale=21,
            relief=DGG.FLAT,
            item_text_fg=(1, 1, 1, 1),
            item_text_scale=0.8,
            highlightScale=(0.8, 0.8),
            item_relief=DGG.FLAT,
            item_frameColor=color,
            item_pad=(0.2, 0.2),
            highlightColor=color[2],
            popupMenuLocation=DGG.BELOW,
            command=self.toolbarViewCommand,
            parent=self.menuBar)
        self.view["text"] = "View"

        x += 65

        self.tools = DirectOptionMenu(
            text_fg=(1, 1, 1, 1),
            text_scale=0.8,
            items=["Delete Nodes", "Copy Nodes", "Refresh"],
            pos=(x, 0, -5),
            frameSize=(0, 65 / 21, -7 / 21, 17 / 21),
            frameColor=color,
            scale=21,
            relief=DGG.FLAT,
            item_text_fg=(1, 1, 1, 1),
            item_text_scale=0.8,
            highlightScale=(0.8, 0.8),
            item_relief=DGG.FLAT,
            item_frameColor=color,
            item_pad=(0.2, 0.2),
            highlightColor=color[2],
            popupMenuLocation=DGG.BELOW,
            command=self.toolbarToolsCommand,
            parent=self.menuBar)
        self.tools["text"] = "Tools"

        x += 65

        self.nodeMap = {
            "Numeric Input": "NumericNode",
            "Addition": "AddNode",
            "Divide": "DivideNode",
            "Multiply": "MultiplyNode",
            "Boolean Value": "BoolNode",
            "Boolean And": "BoolAnd",
            "Boolean Or": "BoolOr",
            "Simple Output": "TestOutNode"
        }

        self.nodes = DirectOptionMenu(text_fg=(1, 1, 1, 1),
                                      text_scale=0.8,
                                      items=list(self.nodeMap.keys()),
                                      pos=(x, 0, -5),
                                      frameSize=(0, 65 / 21, -7 / 21, 17 / 21),
                                      frameColor=color,
                                      scale=21,
                                      relief=DGG.FLAT,
                                      item_text_fg=(1, 1, 1, 1),
                                      item_text_scale=0.8,
                                      highlightScale=(0.8, 0.8),
                                      item_relief=DGG.FLAT,
                                      item_frameColor=color,
                                      item_pad=(0.2, 0.2),
                                      highlightColor=color[2],
                                      popupMenuLocation=DGG.BELOW,
                                      command=self.toolbarNodesCommand,
                                      parent=self.menuBar)
        self.nodes["text"] = "Nodes"

    def toolbarFileCommand(self, selection):
        if selection == "New":
            base.messenger.send("new")
        elif selection == "Save":
            base.messenger.send("save")
        elif selection == "Load":
            base.messenger.send("load")
        elif selection == "Quit":
            base.messenger.send("quit")

        self.file["text"] = "File"

    def toolbarToolsCommand(self, selection):
        if selection == "Delete Nodes":
            base.messenger.send("removeNode")
        elif selection == "Copy Nodes":
            taskMgr.doMethodLater(0.2,
                                  base.messenger.send,
                                  "delayedCopyFromMenu",
                                  extraArgs=["copyNodes"])
            #base.messenger.send("copyNodes")
        elif selection == "Refresh":
            base.messenger.send("refreshNodes")
        #elif selection == "Options":
        #    base.messenger.send("showSettings")
        #elif selection == "Help":
        #    base.messenger.send("showHelp")

        self.tools["text"] = "Tools"

    def toolbarViewCommand(self, selection):
        if selection == "Zoom In":
            base.messenger.send("zoom", [True])
        elif selection == "Zoom Out":
            base.messenger.send("zoom", [False])
        elif selection == "Zoom 100%":
            base.messenger.send("zoom_reset")

        self.view["text"] = "View"

    def toolbarNodesCommand(self, selection):
        base.messenger.send("addNode", [self.nodeMap[selection]])

        self.nodes["text"] = "Nodes"

    def resizeFrame(self):
        screenWidthPx = base.getSize()[0]
        self.menuBar["frameSize"] = (0, screenWidthPx, -12, 12)
        self.menuBar.setPos(0, 0, -12)
Esempio n. 11
0
class DirectFolderBrowser(DirectObject):
    def __init__(self,
                 command,
                 fileBrowser=False,
                 defaultPath="~",
                 defaultFilename="unnamed.txt",
                 fileExtensions=[],
                 tooltip=None,
                 iconDir=None,
                 parent=None,
                 theme=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
        iconDir: A directory path that contains replacement images. It must contain all required images which are:
            File.png
            Folder.png
            FolderNew.png
            FolderShowHidden.png
            FolderUp.png
            Reload.png
        parent: Another DirectGUI element which has pixel2d as root parent.
            The browser frame is placed centered so a frame for example should have equal sizes in horizontal and vertical directions
            e.g. frameSize=(-250,250,-200,200)
        """
        self.theme = theme if theme is not None else LightTheme()
        self.tt = tooltip
        self.command = command
        self.showFiles = fileBrowser
        self.fileExtensions = fileExtensions
        self.showHidden = False
        self.parent = parent

        self.imageOpts = LoaderOptions()
        self.imageOpts.set_auto_texture_scale(ATS_none)

        if self.theme.icon_dir is not None:
            self.iconDir = self.theme.icon_dir
        elif iconDir is None:
            fn = Filename.fromOsSpecific(os.path.dirname(__file__))
            fn.makeTrueCase()
            self.iconDir = str(fn) + "/icons"
        else:
            self.iconDir = iconDir
        self.selectedViewType = "Symbol"

        self.currentPath = os.path.expanduser(defaultPath)
        if not os.path.exists(self.currentPath):
            self.currentPath = os.path.expanduser("~")
        self.previousPath = self.currentPath

        if self.parent is None:
            self.parent = base.pixel2d
            self.screenWidthPx = base.getSize()[0]
            self.screenHeightPx = base.getSize()[1]
            self.position = LPoint3f(base.getSize()[0] / 2, 0,
                                     -base.getSize()[1] / 2)
        else:
            self.screenWidthPx = self.parent.getWidth()
            self.screenHeightPx = self.parent.getHeight()
            self.position = LPoint3f(0)
        self.screenWidthPxHalf = self.screenWidthPx * 0.5
        self.screenHeightPxHalf = self.screenHeightPx * 0.5

        self.mainFrame = DirectFrame(
            relief=1,
            frameSize=(-self.screenWidthPxHalf, self.screenWidthPxHalf,
                       -self.screenHeightPxHalf, self.screenHeightPxHalf),
            frameColor=self.theme.main_background,
            pos=self.position,
            parent=self.parent,
            state=DGG.NORMAL,
        )

        self.pathRightMargin = 155  # NOTE: Add 28 for each button to the right + 15px margin
        self.pathEntryWidth = self.screenWidthPx - self.pathRightMargin - 28

        # The path entry on top of the window
        self.pathEntry = DirectEntry(
            text_fg=self.theme.default_text_color,
            parent=self.mainFrame,
            relief=DGG.SUNKEN,
            frameColor=self.theme.entry_background,
            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"],
        )

        # ----------------
        # CONTROL BUTTONS
        # ----------------
        x = self.screenWidthPxHalf - self.pathRightMargin + 18

        # RELOAD
        self.btnReload = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderReload,
            image=loader.load_texture(f"{self.iconDir}/Reload.png",
                                      loaderOptions=self.imageOpts),
            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)

        # MOVE UP ONE FOLDER
        x += 28
        self.btnFolderUp = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderUp,
            image=loader.load_texture(f"{self.iconDir}/FolderUp.png",
                                      loaderOptions=self.imageOpts),
            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)

        # CREATE NEW FOLDER
        x += 28
        self.btnFolderNew = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderNew,
            image=loader.load_texture(f"{self.iconDir}/FolderNew.png",
                                      loaderOptions=self.imageOpts),
            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)

        # SHOW HIDDEN FOLDERS
        x += 28
        self.btnFolderShowHidden = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.folderShowHidden,
            image=loader.load_texture(f"{self.iconDir}/FolderShowHidden.png",
                                      loaderOptions=self.imageOpts),
            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)

        # TOGGLE VIEW TYPE
        x += 28
        self.btnViewType = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.icon_button_background,
            frameSize=(-14, 14, -10, 18),
            pos=LPoint3f(x, 0, self.screenHeightPxHalf - 25),
            command=self.toggleViewType,
            image=loader.load_texture(f"{self.iconDir}/ViewTypeSymbol.png",
                                      loaderOptions=self.imageOpts),
            image_scale=14,
            image_pos=(0, 0, 4),
        )
        self.btnViewType.setTransparency(TransparencyAttrib.M_multisample)
        if self.tt is not None:
            self.btnViewType.bind(
                DGG.ENTER, self.tt.show,
                ["Toggle view between Symbols and Detail list"])
            self.btnViewType.bind(DGG.EXIT, self.tt.hide)

        # --------------
        # CONTENT FRAME
        # --------------
        color = self.theme.scrollbar_controlls_color
        self.container = DirectScrolledFrame(
            relief=DGG.RIDGE,
            borderWidth=(2, 2),
            frameColor=self.theme.main_background,
            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,
            verticalScroll_frameColor=self.theme.scroll_background,
            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,
            horizontalScroll_frameColor=self.theme.scroll_background,
            state=DGG.NORMAL,
        )
        self.container.bind(DGG.MWDOWN, self.scroll, [0.01])
        self.container.bind(DGG.MWUP, self.scroll, [-0.01])

        # ACCEPT BUTTON
        self.btnOk = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.text_button_background,
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf - 160, 0,
                         -self.screenHeightPxHalf + 25),
            text="ok",
            text_scale=12,
            text_fg=self.theme.default_text_color,
            command=command,
            extraArgs=[1],
        )

        # CANCEL BUTTON
        self.btnCancel = DirectButton(
            parent=self.mainFrame,
            relief=1,
            frameColor=self.theme.text_button_background,
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf - 55, 0,
                         -self.screenHeightPxHalf + 25),
            text="Cancel",
            text_scale=12,
            text_fg=self.theme.default_text_color,
            command=command,
            extraArgs=[0])

        # SELECTED FILE ENTRY FIELD
        if self.showFiles:
            self.txtFileName = DirectEntry(
                text_fg=self.theme.default_text_color,
                parent=self.mainFrame,
                relief=DGG.SUNKEN,
                frameColor=self.theme.entry_background,
                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"],
            )

        # ------------------
        # CREATE NEW FOLDER
        # ------------------
        # FRAME FOR CREATING NEW FOLDER
        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=self.theme.popup_frame_background,
        )

        # LABEL FOR NEW FOLDER NAME ENTRY
        self.txtNewFolderName = DirectLabel(
            parent=self.newFolderFrame,
            text="New Folder Name",
            text_scale=12,
            text_fg=self.theme.default_text_color,
            frameColor=(0, 0, 0, 0),
            text_align=TextNode.ALeft,
            pos=(-self.screenWidthPxHalf + 15, 0, -3),
        )

        # ENTRY FOR THE NEW FOLDER NAME
        self.folderName = DirectEntry(
            text_fg=self.theme.default_text_color,
            parent=self.newFolderFrame,
            relief=DGG.SUNKEN,
            frameColor=self.theme.entry_background,
            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"],
        )

        # ACCEPT BUTTON FOR THE CREATE NEW FOLDER
        self.btnCreate = DirectButton(
            parent=self.newFolderFrame,
            relief=1,
            frameColor=self.theme.text_button_background,
            frameSize=(-45, 45, -6, 14),
            pos=LPoint3f(self.screenWidthPxHalf - 65, 0, -4),
            text="Create",
            text_scale=12,
            text_fg=self.theme.default_text_color,
            command=self.folderCreate,
            extraArgs=[0])
        # Hide the create new folder frame by default
        self.newFolderFrame.hide()

        # ---------------
        # UPDATE CONTENT
        # ---------------
        # Initial loading of the files and folders of the current path
        self.folderReload()

        # handle window resizing
        self.prevScreenSize = base.getSize()
        if self.parent is base.pixel2d:
            self.accept("window-event", self.windowEventHandler)

    def show(self):
        self.mainFrame.show()
        if self.parent is None:
            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
        VIEWTYPE[self.selectedViewType](self, content)

    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 toggleViewType(self):
        if self.selectedViewType == "Symbol":
            self.selectedViewType = "Detail"
            self.btnViewType["image"] = loader.load_texture(
                f"{self.iconDir}/ViewTypeDetail.png",
                loaderOptions=self.imageOpts)
        else:
            self.selectedViewType = "Symbol"
            self.btnViewType["image"] = loader.load_texture(
                f"{self.iconDir}/ViewTypeSymbol.png",
                loaderOptions=self.imageOpts)

        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 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 - 28
            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.screenWidthPxHalf - self.pathRightMargin + 14
            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))
            x += 28
            self.btnViewType.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()
Esempio n. 12
0
    def renderBuffers(self):
        self.buffersParent.node().removeAllChildren()

        posX = 0
        posY = 0

        for name in self.bufferOrder:
            target = self.buffers[name]
            for targetType in RenderTargetType.All:
                if not target.hasTarget(targetType):
                    continue
                tex = target.getTexture(targetType)
                sizeStr = str(tex.getXSize()) + " x " + str(tex.getYSize())

                if tex.getZSize() != 1:
                    sizeStr += " x " + str(tex.getZSize())

                node = DirectFrame(
                    parent=self.buffersParent,
                    frameColor=(1, 1, 1, 0.2),
                    frameSize=(-self.innerPadding,
                               self.texWidth + self.innerPadding,
                               -self.texHeight - 30 - self.innerPadding,
                               self.innerPadding + 15),
                    state=DGG.NORMAL)
                node.setPos(
                    20 + posX * (self.texWidth + self.texPadding), 0,
                    -self.paddingTop - 22 - posY *
                    (self.texHeight + self.texPadding + 44))
                node.bind(DGG.ENTER, partial(self.onMouseOver, node))
                node.bind(DGG.EXIT, partial(self.onMouseOut, node))
                node.bind(DGG.B1RELEASE, partial(self.showDetail, tex))

                aspect = tex.getYSize() / float(tex.getXSize())
                computedWidth = self.texWidth
                computedHeight = self.texWidth * aspect

                if computedHeight > self.texHeight:
                    # have to scale tex width instead
                    computedHeight = self.texHeight
                    computedWidth = tex.getXSize() / float(tex.getYSize()) * \
                        self.texHeight

                img = BetterOnscreenImage(image=tex,
                                          parent=node,
                                          x=0,
                                          y=30,
                                          w=computedWidth,
                                          h=computedHeight,
                                          transparent=False,
                                          nearFilter=False,
                                          anyFilter=False)
                txtName = BetterOnscreenText(text=name,
                                             x=0,
                                             y=0,
                                             size=15,
                                             parent=node)
                txtSizeFormat = BetterOnscreenText(text=sizeStr,
                                                   x=0,
                                                   y=20,
                                                   size=15,
                                                   parent=node,
                                                   color=Vec3(0.2))
                txtTarget = BetterOnscreenText(text=str(targetType),
                                               align="right",
                                               x=self.texWidth,
                                               y=20,
                                               size=15,
                                               parent=node,
                                               color=Vec3(0.2))

                posX += 1
                if posX > self.pageSize:
                    posY += 1
                    posX = 0