Boolean value failing to update on button press


#1

Me again! I’m a little worried I’m overstaying my welcome with this script, but se la vie. I have a set of DirectSliders, the second of which copies the first slider’s value, which is edited by pressing the w and s keys. I want to be able to press q and set a boolean that causes the second slider to start being edited independently.

            # w - both wings flare open & glide
	self.w = self.accept('w-repeat', self.glide)

	# s - both wings close & drop
	self.s = self.accept('s-repeat', self.drop)

	self.leftWingUpdate = False
	self.rightWingUpdate = False

	# q - press to change only left wing
	self.q = self.accept('q', self.updateWing, [self.leftWingUpdate])

def setCheckValue(self, button, value):

	button['indicatorValue'] = value

def turnLeft(self):

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

def turnRight(self):

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

def glide(self):

	if self.leftWingUpdate:

		self.rightWingUpdate = False
		self.leftWing['value'] = self.leftWing['value'] + 1

	elif self.rightWingUpdate:

		self.leftWingUpdate = False
		self.rightWing['value'] = self.rightWing['value'] + 1

	else:

		self.wings['value'] = self.wings['value'] + 1
		self.wingInherit()

def drop(self):

	if self.leftWingUpdate:

		self.leftWing['value'] = self.leftWing['value'] - 1

	elif self.rightWingUpdate:

		self.rightWing['value'] = self.rightWing['value'] - 1

	else:

		self.wings['value'] = self.wings['value'] - 1
		self.wingInherit()

def wingInherit(self):

	self.leftWing['value'] = self.wings['value']
	self.rightWing['value'] = self.wings['value']

def updateWing(self, wing):

	pdb.set_trace()

	wing = not wing
	print('Wing updated')

When running the program nothing happens, but when I use pdb I get this when I enter “q”:

h:\dw\control_tests\flightcontrols.py(114)updateWing()
-> wing = not wing
(Pdb) q
Traceback (most recent call last):
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\EventManager.py”, line 47, in eventLoopTask
self.doEvents()
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\EventManager.py”, line 41, in doEvents
processFunc(self.eventQueue.dequeueEvent())
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\EventManager.py”, line 100, in processEvent
messenger.send(eventName)
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\Messenger.py”, line 333, in send
self.__dispatch(acceptorDict, event, sentArgs, foundWatch)
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\Messenger.py”, line 418, in __dispatch
result = method ((extraArgs + sentArgs))
File “flightcontrols.py”, line 114, in updateWing
wing = not wing
File “flightcontrols.py”, line 114, in updateWing
wing = not wing
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\bdb.py”, line 88, in trace_dispatch
return self.dispatch_line(frame)
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\bdb.py”, line 113, in dispatch_line
if self.quitting: raise BdbQuit
bdb.BdbQuit
:task(error): Exception occurred in PythonTask eventManager
Traceback (most recent call last):
File “flightcontrols.py”, line 118, in
ref.run()
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\ShowBase.py”, line 3109, in run
self.taskMgr.run()
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\task\Task.py”, line 531, in run
self.step()
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\task\Task.py”, line 485, in step
self.mgr.poll()
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\EventManager.py”, line 47, in eventLoopTask
self.doEvents()
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\EventManager.py”, line 41, in doEvents
processFunc(self.eventQueue.dequeueEvent())
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\EventManager.py”, line 100, in processEvent
messenger.send(eventName)
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\Messenger.py”, line 333, in send
self.__dispatch(acceptorDict, event, sentArgs, foundWatch)
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\site-packages\direct\showbase\Messenger.py”, line 418, in __dispatch
result = method (
(extraArgs + sentArgs))
File “flightcontrols.py”, line 114, in updateWing
wing = not wing
File “flightcontrols.py”, line 114, in updateWing
wing = not wing
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\bdb.py”, line 88, in trace_dispatch
return self.dispatch_line(frame)
File “C:\Users_\AppData\Local\Programs\Python\Python37-32\lib\bdb.py”, line 113, in dispatch_line
if self.quitting: raise BdbQuit
bdb.BdbQuit

I know it’s not a problem with the code itself because if I set one of the “update wing” variables to true manually the program works. I’ve noticed that in the debug updatewing() runs twice, which might be my problem; how do I solve that?


#2

What does it mean? not a wing, what is that type? You are trying to do the following

self.leftWingUpdate = not wing


#3

Yes:

self.leftWingUpdate = not self.leftWingUpdate

i.e, if self.leftWingUpdate = True:

True = not True

True = False

self.leftWingUpdate = False

here’s a working example I have in another script:

def togglespeed(self):

	self.running = not self.running

	if self.running:

		self.sprinting = not self.sprinting

which has this effect:

Walking <= key pressed => Running <= key pressed => Sprinting


#4

serega-kkz has it correct, I think–although I don’t think that their solution will quite work.

The problem is that you’re passing in “self.leftWingUpdate”, which is a boolean variable, and that, since it’s a simple data-type (not an object, list, etc.) the value is being passed in, not a reference to the variable itself.

Furthermore, I think that you’ll find that your code will always pass in the value “True”, because the value being stored by the object associated with the event is evaluated when you call “self.accept”–that is, right after you set the variable’s value to “True”.

Instead, what I suggest is this: instead of passing in the variable, just access it in the method, like this:

def updateWing(self, wing):
    self.leftWingUpdate = not self.leftWingUpdate

If you want the method to operate on more than one object (such as the “rightWingUpdate” variable"), I suggest passing in a value that indicates which variable it should modify, and checking that value in “updateWing”.


#5

I actually did not give an answer, I asked a question.


#6

Ah, my apologies–I read the following (after your two questions) as an answer:

Sorry about that! ^^;


#7

I do not use inversion. And apply the design of the checks.

from direct.showbase.ShowBase import ShowBase

class Controls(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        self.leftWingUpdate = False
        
        self.key_q = self.accept('q', self.setValue)

    def setValue(self):
        if self.leftWingUpdate:
            self.leftWingUpdate = False
        else:
            self.leftWingUpdate = True
        print (self.leftWingUpdate)

app = Controls()
app.run()

And when I saw “not” I did not immediately understand what it was for. Apparently I’m noob.


#8

@WatcherMagic To clarify further, there are two fundamental issues: firstly, that your updateWing method is being called with a snapshot of the value of self.leftWingUpdate that it was at the time you called self.accept, and secondly, that this code:

…only updates the “wing” variable in the local scope of the function. The new value doesn’t actually persist beyond the end of the function.

What you could do if you don’t want to create separate updateWing functions for left/right wings is instead to use a dictionary or list to store which wings to update:

        self.wingsUpdate = [False, False]
        self.accept('q', self.updateWing, [0])
        self.accept('e', self.updateWing, [1])

    def updateWing(self, wingIndex):
        self.wingsUpdate[wingIndex] = not self.wingsUpdate[wingIndex]

I do recommend that you try and follow some Python courses on variable scoping and object-oriented programming before diving right into using OOP in Panda, though. I see numerous issues with your code that seem to indicate that you would benefit from a better understanding of Python concepts in general.

As one final note, the best way to post code in the forum is using this syntax:

```python
code here  
```

This ensures that the code is highlighted properly and that the indentation is preserved.


#9

Alright, thanks to all of you! I’m going to go back and rework this with the advice you’ve given (and go learn more about OOP with Python. XD) Wish me luck!

Also @rdb Thanks for the tip, I’ve been manually indenting all my code until now