DirectButton in a new window

'ello everyone,

I’m trying to create a GUI in a seperate window, so that I can control the main window without cluttering it. In a previous script I created three buttons for loading different scripts in a queue. There are two animations that it loads, and the third button cancels the current animation. I basically took the directbutton example from the manual and worked from there.

What I have tried to do is create another window and put the buttons there. I followed the steps drwr layed out in this thread:
. Here is how I tried to implement it:

import direct.directbase.DirectStart
from direct.gui.OnscreenText import OnscreenText
from direct.gui.DirectGui import *
from posetest import *
from animationtest2 import *
from direct.showbase.DirectObject import DirectObject
import sys, os

class GUI(DirectObject):
    def __init__(self):
        #create new window for the gui
        wp = WindowProperties()
        wp.setSize(400, 300)
        wp.setOrigin(879, 200)
        controlwin = base.openWindow(props = wp, aspectRatio = 1.33)
        render2d = NodePath('render2d')
        camera2d = base.makeCamera2d(controlwin)
        #add some text
        bk_text = "This is my Demo"
        self.textObject = OnscreenText(text = bk_text, pos = (0.95,-0.95), 
                                       scale = 0.07,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=1)
        bk_text = "Current Animation: None"
        self.runtextObject = OnscreenText(text = bk_text, pos = (0.95, -0.90),
                                           scale = .07, fg = (1, 0.5, 0.5, 1),
                                            align = TextNode.ACenter, mayChange = 1)
        #add buttons
        b = DirectButton(text = ("Ready", "Run", "Click to run posetest", "disabled"), scale = .10, command = self.addPoseq, pos = (.8, 0, .8))
        a = DirectButton(text = ("Ready", "Run", "Click to run animationtest2", "disabled"), scale = .10, command = self.addAnimq, pos = (-.8, 0, .8))
        b1 = DirectButton(text = ("Ready", "Stop", "Click to stop animations", "disabled"), scale = .10, command = self.stopAnim, pos = (-.8, 0, -.8))
        self.q = []
        taskMgr.add(self.runQ, 'run')
    #task for running the queue                  
    def runQ(self, task):
        if len(self.q) == 0:
            bk_text = "No objects in queue"
            if self.q[-1].running == 0:
                bk_text = "Current: " + self.q[-1].name
            if self.q[-1].done == 1:
        return Task.cont

    #function for adding "posetest"
    def addPoseq(self):
        self.q.insert(0, World())
        bk_text = "posetest added to queue"

    #function for adding "animation2"
    def addAnimq(self):
        self.q.insert(0, Anim())
        bk_text = "animationtest2 added to queue"
    #function for cancel button
    def stopAnim(self):
        if len(self.q) != 0:
            bk_text = "Animation canceled"
w = GUI()
#run the tutorial

Unsure of what drwr meant by “passing the parent parameter”, I just reparented the buttons to the render2d object. The window is created fine, and the images(default) for the buttons appear in the designated positions, but none of the text for the buttons appears, in addition to the buttons not clicking properly. I’m almost certain that reparent the buttons iis my problem, but I do not know how else to get them over to the window, as the manual does not speak of any “parent” keyword for directobjects. Any advice in this manner would be WONderful. Thanks.

EDIT: Almost forgot an important thing: When I click in the main window, a thick red dot appears in the middle of both windows. Weird…

I don’t know what I must have been thinking when I made that earlier post. In addition to creating a render2d and setting up a camera for it, if you want to use DirectGui, you also need two additional things: (1) an aspect2d node, which is a node of type PGTop, critical for DirectGui objects; and (2) a MouseWatcher, to monitor the mouse motion in your second window, and active your DirectGui objects when the mouse rolls over them.

Here are the relevant lines from your example, extended to create the new structures:

        #create new window for the gui
        wp = WindowProperties()
        wp.setSize(400, 300)
        wp.setOrigin(879, 200)
        aspectRatio = 1.33
        controlwin = base.openWindow(props = wp, aspectRatio = aspectRatio)

        # Setup a render2d and aspect2d for the new window.
        render2d = NodePath('render2d')
        camera2d = base.makeCamera2d(controlwin)

        aspect2d = render2d.attachNewNode(PGTop("aspect2d"))
        aspect2d.setScale(1.0 / aspectRatio, 1.0, 1.0)

        # Set up a MouseWatcher to monitor the DirectGui.
        name = controlwin.getInputDeviceName(0)
        mk = base.dataRoot.attachNewNode(MouseAndKeyboard(controlwin, 0, name))
        mw = mk.attachNewNode(MouseWatcher(name))

Now you can parent your DirectGui objects to aspect2d, rather than render2d, and they should work. Note that there is a keyword parameter named parent, available to every DirectGui object; in lieu of reparenting it afterwards, you could simply say “DirectButton(parent = aspect2d, …)”. But reparenting it does the same thing. I don’t know why this convenience parameter isn’t documented.

The red dot you are referring to is the selection dot you get when you have the DirectTools loaded. You must have “want-directtools 1” in your Config.prc file.


Awesome. The buttons are working properly now. All I need to do now is keep the animations from rendering in the second window. Is there an easy way to do that? Thanks so much!

You are seeing the animations in the second window, because the default behavior of base.openWindow() is to create a camera for the window that looks out onto render. To stop this from happening, just put makeCamera = 0 on the parameter list to your openWindow() call.


Hurrah, it’s running well now. Thanks again.