TypeError: function/task missing 1 required positional argument: 'task'


#1

I decided to try an experiment without all the hassle of getting assets together, so I’ve created a script where I’m trying to use keyboard input to change the values of buttons, sliders, labels, etc.

I still don’t have a grasp on accepting input and tasks, and I can’t decipher Roaming Ralph. Too much going on in there. XD So the question remains: how to I accept input by holding a certain key to temporarily change the state of an object?

class FlightControls(ShowBase):

def __init__(self):

	ShowBase.__init__(self)

	self.disableMouse()

	self.createGUI()

	self.a = self.accept('a-repeat', self.controls)
	self.d = self.accept('d-repeat', self.controls)
	self.space = self.accept('space-repeat', self.controls)
	self.q = self.accept('q-repeat', self.controls)
	self.e = self.accept('e-repeat', self.controls)

	taskMgr.add(self.controls, "controls")

def createGUI(self):

	self.leftB = DirectCheckButton(scale=0.25)
	self.leftB.setPos(-0.25, 0, 0.5)

	self.rightB = DirectCheckButton(scale=0.25)
	self.rightB.setPos(0.5, 0, 0.5)

	self.wings = DirectSlider(range=(0,100), pageSize=1, value = 50)
	self.wings.setPos(0, 0, 0)

	self.leftWing = DirectSlider(range = (0,100), pageSize=1, value = 50, scale = 0.5)
	self.leftWing.setPos(-0.7, 0, -0.5)

	self.rightWing = DirectSlider(range=(0,100), pageSize=1, value = 50, scale = 0.5)
	self.rightWing.setPos(0.75, 0, -0.5)

def controls(self, task):

	if self.a:

		self.leftB.indicatorValue = 1

	else:

		self.leftB.indicatorValue = 0

ref = FlightControls()
ref.run()

P.S Does anyone know how to disable the ability to change slider values with the mouse?


#2

Events are not tasks, so there will not be a task object passed into the function when a key is pressed. Removing the task argument from your controls method should fix the issue. You can also remove your taskMgr.add() call as well, since a task probably isn’t even what you want here. You would want a task if you wanted this method to be called automatically after a time delay, for example.

As for disabling the slider, have you tried something like self.wings.disableEdit()? I haven’t actually tested this, but reading through the API reference it seems closest to what you want.


#3

Regarding disabling mouse-input, DirectGUI has a constructor parameter called “suppressMouse”, which should, I think, prevent mouse-interaction with the control. However, I gather that that’s not quite what you want. So, digging into the related code a little, I see that DirectGuiWidget uses the “suppressMouse” parameter to inform a call to to PGItem’s “setSuppressFlags” method. Perhaps you can use that?


#4

@treamous Thank you! The error’s gone; disableEdit just means I can’t use Panda3D’s realtime GUI position and scale editing.

@Thaumaturge That sounds promising, I’m looking in the GitHub source; where did you find PGItem?

Also, the error’s gone but the GUI and the console doesn’t respond to my input; I’m pretty sure I’m missing loading the events in here somewhere, where should I reference the controls() method so I can start to see some reaction?

class FlightControls(ShowBase):

def __init__(self):

	ShowBase.__init__(self)

	self.disableMouse()

	self.createGUI()

	self.a = self.accept('a-repeat', self.controls)
	self.d = self.accept('d-repeat', self.controls)
	self.space = self.accept('space-repeat', self.controls)
	self.q = self.accept('q-repeat', self.controls)
	self.e = self.accept('e-repeat', self.controls)

	self.controls()

def createGUI(self):

	self.leftB = DirectCheckButton(scale=0.25)
	self.leftB.setPos(-0.25, 0, 0.5)

	self.rightB = DirectCheckButton(scale=0.25)
	self.rightB.setPos(0.5, 0, 0.5)

	self.wings = DirectSlider(range=(0,100), pageSize=1, value = 50)
	self.wings.setPos(0, 0, 0)

	self.leftWing = DirectSlider(range = (0,100), pageSize=1, value = 50, scale = 0.5)
	self.leftWing.setPos(-0.7, 0, -0.5)

	self.rightWing = DirectSlider(range=(0,100), pageSize=1, value = 50, scale = 0.5)
	self.rightWing.setPos(0.75, 0, -0.5)

def controls(self):

	if self.a:

		self.leftB.setIndicatorValue(True)
		self.rightB.setIndicatorValue(False)
		print('A')

	elif self.d:

		self.rightB.setIndicatorValue(True)
		self.leftB.setIndicatorValue(False)
		print('D')

#5

The working version for the software state change checkbox.

from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectGui import DirectCheckButton

class FlightControls(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        self.key_a = self.accept('a', self.setValue)

        self.leftB = DirectCheckButton(scale=0.25)
        
    def setValue(self):
            self.leftB["indicatorValue"] = True 
            self.leftB.setIndicatorValue()
            print ("key_a")

app = FlightControls()
app.run()

The textbook made a mistake in the key, must be indicatorValue in the textbook IndicatorValue


#6

I think that I just clicked through the source in my IDE to get there. ^^;

However, looking around the GitHub repo, it seems to be in this directory: https://github.com/panda3d/panda3d/tree/master/panda/src/pgui

Regarding your issue, I don’t think that the “accept” function returns anything, so the values of “self.a”, “self.d”, etc. would presumably be “None”–although I stand to be corrected on that!

If you want to determine which key was pressed, you could just pass in an extra parameter, like this:

self.accept("a", self.keyPressed, ["a"])

def keyPressed(self, key):
    print key

(Note that if you want additional parameters, you just add them to the list given as the third parameter to “accept”, above. They are then passed to the function as separate parameters. Something like this:

self.accept("a", self.keyPressed, ["a", "b", "c"])

def keyPressed(self, key, param2, param3):
    print key
    # When "a" is pressed, "key" will have the value "a",
    # "param2" will have the value "b",
    # and "param3" will have the value "c", I believe.

#7

Sample code for your task, which is described in the first post.


from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectGui import DirectCheckButton, DirectSlider

class FlightControls(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        self.key_a = self.accept('a', self.setValueTrueL)
        self.key_a = self.accept('a-up', self.setValueFalseL)
        
        self.key_d = self.accept('d', self.setValueTrueR)
        self.key_d = self.accept('d-up', self.setValueFalseR)
        
        self.leftB = DirectCheckButton(scale=0.25)
        self.leftB.setPos(-0.25, 0, 0.5)

        self.rightB = DirectCheckButton(scale=0.25, indicatorValue=1)
        self.rightB.setPos(0.5, 0, 0.5)


    def setValueTrueL(self):
            self.leftB["indicatorValue"] = True 
            self.leftB.setIndicatorValue()
            
    def setValueFalseL(self):
            self.leftB["indicatorValue"] = False
            self.leftB.setIndicatorValue()
            
    def setValueTrueR(self):
            self.rightB["indicatorValue"] = False
            self.rightB.setIndicatorValue()
            
    def setValueFalseR(self):
            self.rightB["indicatorValue"] = True
            self.rightB.setIndicatorValue()

app = FlightControls()
app.run()


#8

Thank you all a bunch! The first part’s working now. :slight_smile: Here’s the working code (without all the extra stuff I haven’t gotten to yet) for future passerby, and @Thaumaturge thank you for the link!

class FlightControls(ShowBase):

def __init__(self):

	ShowBase.__init__(self)

	self.createGUI()
	
	self.a = self.accept('a', self.turnLeft)
	self.a = self.accept('a-up', self.setIndicatorValue, [self.leftB, False])

	self.d = self.accept('d', self.turnRight)
	self.d = self.accept('d-up', self.setIndicatorValue,[self.rightB, False])

def createGUI(self):

	self.leftB = DirectCheckButton(scale=0.25)
	self.leftB.setPos(-0.25, 0, 0.5)

	self.rightB = DirectCheckButton(scale=0.25)
	self.rightB.setPos(0.5, 0, 0.5)

def setIndicatorValue(self, button, value):

	button['indicatorValue'] = value

def turnLeft(self):

	self.setIndicatorValue(self.leftB, True)
	self.setIndicatorValue(self.rightB, False)

def turnRight(self):

	self.setIndicatorValue(self.rightB, True)
	self.setIndicatorValue(self.leftB, False)

ref = FlightControls()
ref.run()

#9

If you are trying to write the most convoluted code for a simple task. That you have succeeded. :slightly_smiling_face:

class FlightControls(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)
        
        self.leftB = DirectCheckButton(scale=0.25)
        self.leftB.setPos(-0.25, 0, 0.5)

        self.rightB = DirectCheckButton(scale=0.25)
        self.rightB.setPos(0.5, 0, 0.5)
        
        self.key_a = self.accept('a', self.setValue, [self.leftB, True])
        self.key_a = self.accept('a-up', self.setValue, [self.leftB, False])
        
        self.key_d = self.accept('d', self.setValue, [self.rightB, True])
        self.key_d = self.accept('d-up', self.setValue, [self.rightB, False])

    def setValue(self, key, status):
            if status:
                key["indicatorValue"] = True
            else:
                key["indicatorValue"] = False

app = FlightControls()
app.run()

#10

Lol whoops, thanks! XD That is simpler. My only problem there is I’m able to go both left and right at once-something I don’t want fighting when I adapt this for 3d movement.


#11

You can add a vector parameter.

class FlightControls(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)
        
        self.leftB = DirectCheckButton(scale=0.25)
        self.leftB.setPos(-0.25, 0, 0.5)

        self.rightB = DirectCheckButton(scale=0.25)
        self.rightB.setPos(0.5, 0, 0.5)
        
        self.key_a = self.accept('a', self.setValue, [self.leftB, True, 1])
        self.key_a = self.accept('a-up', self.setValue, [self.leftB, False, None])
        
        self.key_d = self.accept('d', self.setValue, [self.rightB, True, -1])
        self.key_d = self.accept('d-up', self.setValue, [self.rightB, False, None])

    def setValue(self, key, status, vec):
            if status:
                key["indicatorValue"] = True
                print ("Move X "+str(vec))
            else:
                key["indicatorValue"] = False
                print ("X "+str(vec))

app = FlightControls()
app.run()

#12

Genius! You’ve blown my mind. I’m still amateur at python and panda, so thanks :slight_smile: