Fixes to make compatible with new panda

This commit is contained in:
Mark Mine 2002-04-06 02:03:37 +00:00
parent ba517a3317
commit ce32c8c748
13 changed files with 197 additions and 162 deletions

View File

@ -1,14 +1,10 @@
"""ClusterClient: Master for mutlipiping or PC clusters. """
from PandaModules import *
from TaskManagerGlobal import *
from ShowBaseGlobal import *
import Task
import DirectNotifyGlobal
import Datagram
import DirectObject
from ClusterMsgs import *
import time
import DirectNotifyGlobal
import DirectObject
import Task
class ClusterConfigItem:
def __init__(self, serverFunction, serverName, port):
@ -79,10 +75,12 @@ class DisplayConnection:
# the following should only be called by a synchronized cluster manger
def getSwapReady(self):
datagram = self.msgHandler.blockingRead(self.qcr)
(type,dgi) = self.msgHandler.readHeader(datagram)
if type != CLUSTER_SWAP_READY:
self.notify.warning( ('was expecting SWAP_READY, got %d' % type) )
while 1:
(datagram, dgi,type) = self.msgHandler.blockingRead(self.qcr)
if type == CLUSTER_SWAP_READY:
break
else:
self.notify.warning('was expecting SWAP_READY, got %d' % type)
# the following should only be called by a synchronized cluster manger
def sendSwapNow(self):
@ -97,6 +95,13 @@ class DisplayConnection:
datagram = self.msgHandler.makeCommandStringDatagram(commandString)
self.cw.send(datagram, self.tcpConn)
def sendExit(self):
ClusterManager.notify.debug(
"display connect send exit, packet %d" %
self.msgHandler.packetNumber)
datagram = self.msgHandler.makeExitDatagram()
self.cw.send(datagram, self.tcpConn)
class ClusterManager(DirectObject.DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory("ClusterClient")
MGR_NUM = 1000000
@ -127,9 +132,7 @@ class ClusterManager(DirectObject.DirectObject):
server.sendMoveCam(xyz,hpr)
def startMoveCamTask(self):
task = Task.Task(self.moveCameraTask,49)
taskMgr.add(task, "moveCamTask")
return None
taskMgr.add(self.moveCameraTask, "moveCamTask", 49)
def moveCameraTask(self,task):
self.moveCamera(
@ -144,6 +147,14 @@ class ClusterManager(DirectObject.DirectObject):
# Execute locally
exec( commandString, globals())
def exit(self):
# Execute remotely
for server in self.serverList:
server.sendExit()
# Execute locally
import sys
sys.exit()
class ClusterManagerSync(ClusterManager):
def __init__(self, configList):
@ -154,8 +165,7 @@ class ClusterManagerSync(ClusterManager):
self.startSwapCoordinatorTask()
def startSwapCoordinatorTask(self):
task = Task.Task(self.swapCoordinator,51)
taskMgr.add(task, "clientSwapCoordinator")
taskMgr.add(self.swapCoordinator, "clientSwapCoordinator", 51)
return None
def swapCoordinator(self,task):

View File

@ -23,7 +23,7 @@ ClientConfigs = {
{'pos' : Vec3(0),
'hpr' : Vec3(60,0,0)}
],
'cavetest' : [{'pos' : Vec3(-0.105, -0.020, 5.000),
'cavetest-old' : [{'pos' : Vec3(-0.105, -0.020, 5.000),
'hpr' : Vec3(51.213, 0.000, 0.000),
'focal length' : 0.809,
'film size' : (1.000, 0.831),
@ -48,7 +48,7 @@ ClientConfigs = {
'film offset' : (0.000, 0.173),
},
],
'cavetest-all' : [{'pos' : Vec3(-0.105, -0.020, 5.000),
'cavetest' : [{'pos' : Vec3(-0.105, -0.020, 5.000),
'hpr' : Vec3(51.213, 0.000, 0.000),
'focal length' : 0.809,
'film size' : (1.000, 0.831),
@ -100,7 +100,7 @@ def createClusterManager():
displayConfigs = []
configList = ClientConfigs[clusterConfig]
numConfigs = len(configList)
for i in range(numConfigs):
for i in range(1,numConfigs):
configData = configList[i]
serverConfigName = 'display%d' % i
serverString = base.config.GetString(serverConfigName, '')

View File

@ -7,26 +7,23 @@
# recieved are handled outside of here, after the header (message type
# and number) are read here.
from PandaModules import *
import Datagram
import time
#these are the types of messages that are currently supported.
CLUSTER_NOTHING = -1
CLUSTER_NONE = 0
CLUSTER_CAM_OFFSET = 1
CLUSTER_CAM_FRUSTUM = 2
CLUSTER_POS_UPDATE = 3
CLUSTER_CAM_MOVEMENT = 3
CLUSTER_SWAP_READY = 4
CLUSTER_SWAP_NOW = 5
CLUSTER_COMMAND_STRING = 6
CLUSTER_EXIT = 100
#Port number for cluster rendering
CLUSTER_PORT = 1970
from ShowBaseGlobal import *
from PandaModules import *
from TaskManagerGlobal import *
import Task
import DirectNotifyGlobal
import Datagram
import time
class MsgHandler:
"""MsgHandler: wrapper for PC clusters/multi-piping networking"""
def __init__(self,packetStart, notify):
@ -36,41 +33,51 @@ class MsgHandler:
self.notify = notify
def nonBlockingRead(self,qcr):
availGetVal = qcr.dataAvailable()
if availGetVal:
"""
Return a datagram iterator and type if data is available on the
queued connection reader
"""
if qcr.dataAvailable():
datagram = NetDatagram()
readRetVal = qcr.getData(datagram)
if readRetVal:
dgi = DatagramIterator(datagram)
number = dgi.getUint32()
type = dgi.getUint8()
self.notify.debug( ("Packet %d type %d recieved" % (number,type)) )
if qcr.getData(datagram):
(dgi, type) = self.readHeader(datagram)
else:
dgi = None
type = CLUSTER_NONE
self.notify.warning("getData returned false")
else:
type = CLUSTER_NOTHING
dgi = None
return (type,dgi)
def readHeader(self,datagram):
dgi = DatagramIterator(datagram)
number = dgi.getUint32()
type = dgi.getUint8()
self.notify.debug( ("Packet %d type %d recieved" % (number,type)) )
return (type,dgi)
type = CLUSTER_NONE
# Note, return datagram to keep a handle on the data
return (datagram, dgi,type)
def blockingRead(self,qcr):
"""
Block until data is available on the queued connection reader.
Returns a datagram iterator and type
"""
while not qcr.dataAvailable():
# The following may not be necessary.
# I just wanted some
# time given to the operating system while
# busy waiting.
time.sleep(0.002)
# Data is available, create a datagram iterator
datagram = NetDatagram()
readRetVal = qcr.getData(datagram)
if not readRetVal:
if qcr.getData(datagram):
(dgi, type) = self.readHeader(datagram)
else:
(dgi, type) = (None, CLUSTER_NONE)
self.notify.warning("getData returned false")
return datagram
# Note, return datagram to keep a handle on the data
return (datagram, dgi, type)
def readHeader(self,datagram):
dgi = DatagramIterator(datagram)
number = dgi.getUint32()
type = dgi.getUint8()
self.notify.debug("Packet %d type %d recieved" % (number,type))
return (dgi,type)
def makeCamOffsetDatagram(self,xyz,hpr):
datagram = Datagram.Datagram()
@ -85,14 +92,6 @@ class MsgHandler:
datagram.addFloat32(hpr[2])
return datagram
def makeCommandStringDatagram(self, commandString):
datagram = Datagram.Datagram()
datagram.addUint32(self.packetNumber)
self.packetNumber = self.packetNumber + 1
datagram.addUint8(CLUSTER_COMMAND_STRING)
datagram.addString(commandString)
return datagram
def makeCamFrustumDatagram(self,focalLength, filmSize, filmOffset):
datagram = Datagram.Datagram()
datagram.addUint32(self.packetNumber)
@ -109,7 +108,7 @@ class MsgHandler:
datagram = Datagram.Datagram()
datagram.addUint32(self.packetNumber)
self.packetNumber = self.packetNumber + 1
datagram.addUint8(CLUSTER_POS_UPDATE)
datagram.addUint8(CLUSTER_CAM_MOVEMENT)
datagram.addFloat32(xyz[0])
datagram.addFloat32(xyz[1])
datagram.addFloat32(xyz[2])
@ -118,6 +117,14 @@ class MsgHandler:
datagram.addFloat32(hpr[2])
return datagram
def makeCommandStringDatagram(self, commandString):
datagram = Datagram.Datagram()
datagram.addUint32(self.packetNumber)
self.packetNumber = self.packetNumber + 1
datagram.addUint8(CLUSTER_COMMAND_STRING)
datagram.addString(commandString)
return datagram
def makeSwapNowDatagram(self):
datagram = Datagram.Datagram()
datagram.addUint32(self.packetNumber)
@ -132,6 +139,13 @@ class MsgHandler:
datagram.addUint8(CLUSTER_SWAP_READY)
return datagram
def makeExitDatagram(self):
datagram = Datagram.Datagram()
datagram.addUint32(self.packetNumber)
self.packetNumber = self.packetNumber + 1
datagram.addUint8(CLUSTER_EXIT)
return datagram

View File

@ -1,18 +1,11 @@
"""ServerRepository module: contains the ServerRepository class"""
from ShowBaseGlobal import *
from ClusterMsgs import *
import DirectObject
import Datagram
#import DatagramIterator
#import NetDatagram
import __builtin__
import time
from PandaModules import *
from TaskManagerGlobal import *
from ClusterMsgs import *
from MsgTypes import *
import Task
import DirectNotifyGlobal
import DirectObject
import Task
# Cam offset handling is a little sloppy. The problem is that there is a
# single arc used for both movement of the camera, and the offset of the
@ -76,32 +69,32 @@ class ClusterServer(DirectObject.DirectObject):
# Run this task just after the listener poll task and dataloop
taskMgr.add(self.readerPollTask, "serverReaderPollTask", -39)
def readerPollTask(self):
while self.qcr.dataAvailable():
datagram = NetDatagram()
readRetVal = self.qcr.getData(datagram)
if readRetVal:
self.handleDatagram(datagram)
def readerPollTask(self, state):
# Process all available datagrams
while 1:
(datagram, dgi,type) = self.msgHandler.nonBlockingRead(self.qcr)
if type is CLUSTER_NONE:
break
else:
self.notify.warning("getData returned false")
handleDatagram(dgi, type)
return Task.cont
def handleDatagram(self, datagram):
(type, dgi) = self.msgHandler.nonBlockingRead(self.qcr)
if type==CLUSTER_CAM_OFFSET:
def handleDatagram(self, dgi, type):
if type == CLUSTER_NONE:
pass
elif type == CLUSTER_EXIT:
import sys
sys.exit()
elif type == CLUSTER_CAM_OFFSET:
self.handleCamOffset(dgi)
elif type == CLUSTER_CAM_FRUSTUM:
self.handleCamFrustum(dgi)
elif type==CLUSTER_POS_UPDATE:
elif type == CLUSTER_CAM_MOVEMENT:
self.handleCamMovement(dgi)
elif type==CLUSTER_SWAP_READY:
pass
elif type==CLUSTER_SWAP_NOW:
pass
elif type == CLUSTER_COMMAND_STRING:
self.handleCommandString(dgi)
else:
self.notify.warning("recieved unknown packet")
self.notify.warning("Recieved unknown packet type:" % type)
return type
def handleCamOffset(self,dgi):
@ -163,11 +156,10 @@ class ClusterServerSync(ClusterServer):
pass
elif self.qcr.isConnectionOk(self.lastConnection):
# Process datagrams till you get a postion update
type = CLUSTER_NOTHING
while type != CLUSTER_POS_UPDATE:
datagram = self.msgHandler.blockingRead(self.qcr)
(type,dgi) = self.msgHandler.readHeader(datagram)
if type == CLUSTER_POS_UPDATE:
type = CLUSTER_NONE
while type != CLUSTER_CAM_MOVEMENT:
(datagram,dgi,type) = self.msgHandler.blockingRead(self.qcr)
if type == CLUSTER_CAM_MOVEMENT:
# Move camera
self.handleCamMovement(dgi)
# Set flag for swap coordinator
@ -194,13 +186,14 @@ class ClusterServerSync(ClusterServer):
if self.posRecieved:
self.posRecieved = 0
self.sendSwapReady()
datagram = self.msgHandler.blockingRead(self.qcr)
(type,dgi) = self.msgHandler.readHeader(datagram)
while 1:
(datagram,dgi,type) = self.msgHandler.blockingRead(self.qcr)
if type == CLUSTER_SWAP_NOW:
self.notify.debug('swapping')
base.win.swap()
break
else:
self.notify.warning("did not get expected swap now")
self.handleDatagram(dgi,type)
return Task.cont

View File

@ -260,11 +260,23 @@ class DirectCameraControl(PandaObject):
angle = getCrankAngle(state.coaCenter)
deltaAngle = angle - state.lastAngle
state.lastAngle = angle
if deltaAngle != 0.0:
print deltaAngle
print 'cam Manip before'
print self.camManipRef.getMat()
if base.config.GetBool('temp-hpr-fix',0):
self.camManipRef.setHpr(self.camManipRef, 0, 0, deltaAngle)
else:
self.camManipRef.setHpr(self.camManipRef, 0, 0, -deltaAngle)
print 'cam Manip after'
print self.camManipRef.getMat()
print 'direct camera before'
print direct.camera.getMat()
direct.camera.setMat(self.camManipRef, wrtMat)
print 'direct camera after'
print direct.camera.getMat()
print
print
return Task.cont
def lockCOA(self):
@ -352,6 +364,8 @@ class DirectCameraControl(PandaObject):
# ref = base.cam
ref = direct.drList.getCurrentDr().cam
self.coaMarker.setPos(ref, self.coa)
pos = self.coaMarker.getPos()
self.coaMarker.setPosHprScale(pos, Vec3(0), Vec3(1))
# Resize it
self.updateCoaMarkerSize(coaDist)
# Record marker pos in render space

View File

@ -98,7 +98,7 @@ class DirectManipulationControl(PandaObject):
self.hitPt.assign(hitPt)
self.hitPtDist = hitPtDist
# Find the node path from the node found above
nodePath = render.findPathDownTo(node)
nodePath = render.findAllPathsTo(node)[0]
# Select it
direct.select(nodePath, direct.fShift)
else:
@ -223,7 +223,7 @@ class DirectManipulationControl(PandaObject):
self.objectHandles.transferObjectHandlesScale()
self.fScaling = 0
# Alt key switches to a scaling mode
if direct.fAlt:
if direct.fControl:
self.fScaling = 1
self.scale3D(state)
# Otherwise, manip mode depends on where you started

View File

@ -22,7 +22,7 @@ class DirectNodePath(NodePath):
# and its center of action (COA)
self.mCoa2Dnp = Mat4()
self.mCoa2Dnp.assign(Mat4.identMat())
# self.mCoa2Dnp.setRow(3, Vec4(center[0], center[1], center[2], 1))
self.mCoa2Dnp.setRow(3, Vec4(center[0], center[1], center[2], 1))
# Transform from nodePath to widget
self.mDnp2Widget = Mat4()
self.mDnp2Widget.assign(Mat4.identMat())
@ -127,18 +127,7 @@ class SelectedNodePaths(PandaObject):
"""
dnp = self.selectedDict.get(id, None)
if dnp:
# Found item in selected Dictionary, is it still valid?
if dnp.verifyConnectivity():
# Yes
return dnp
else:
# Not valid anymore, try to repair
if dnp.repairConnectivity(render):
# Fixed, return node path
return dnp
else:
del(self.selectedDict[id])
return None
else:
# Not in selected dictionary
return None
@ -152,18 +141,8 @@ class SelectedNodePaths(PandaObject):
"""
dnp = self.deselectedDict.get(id, None)
if dnp:
# Found item in deselected Dictionary, is it still valid?
if dnp.verifyConnectivity():
# Yes
return dnp
else:
# Not valid anymore, try to repair
if dnp.repairConnectivity(render):
# Fixed, return node path
return dnp
else:
del(self.deselectedDict[id])
return None
else:
# Not in deselected dictionary
return None
@ -344,9 +323,10 @@ class DirectBoundingBox:
def getBounds(self):
# Get a node path's bounds
nodeBounds = self.nodePath.node().getBound()
nodeBounds = BoundingSphere()
nodeBounds.extendBy(self.nodePath.node().getInternalBound())
for child in self.nodePath.getChildrenAsList():
nodeBounds.extendBy(child.arc().getBound())
nodeBounds.extendBy(child.getBounds())
return nodeBounds.makeCopy()
def show(self):
@ -428,11 +408,11 @@ class SelectionRay:
for i in range(0,self.numEntries):
entry = self.cq.getEntry(i)
node = entry.getIntoNode()
nodePath = render.findPathDownTo(node)
nodePath = render.findAllPathsTo(node)[0]
# Don't pick hidden nodes
if node.isHidden():
pass
elif fIgnoreCamera and (direct.camera in nodePath.getAncestry()):
#if node.isHidden():
#pass
if fIgnoreCamera and (direct.camera in nodePath.getAncestry()):
# This avoids things parented to a camera. Good idea?
pass
# Can pick unpickable, use the first visible node
@ -520,10 +500,11 @@ class SelectionRay:
entry = self.cq.getEntry(i)
node = entry.getIntoNode()
# Don't pick hidden nodes
if node.isHidden():
pass
# MRM: Doesn't work in new panda for GeomNodes
#if node.isHidden():
#pass
# Can pick unpickable, use the first visible node
elif fIntersectUnpickable:
if fIntersectUnpickable:
self.cqIndex = i
break
# Is it a named node?, If so, see if it has a name

View File

@ -96,12 +96,7 @@ class ShowBase:
self.camList = []
self.camNode = None
self.camLens = None
# base.camera is a little different; rather than referring to
# base.cameraList[0], it is instead the parent node of all
# cameras in base.cameraList. That way, multiple cameras can
# easily be dragged around by moving the one node.
self.camera = self.render.attachNewNode('camera')
self.camera = None
self.cameraList = []
self.groupList = []
self.camera2d = self.render2d.attachNewNode('camera2d')
@ -383,8 +378,8 @@ class ShowBase:
def getCameras(self, chanConfig):
"""getCameras(self, chanConfig)
"""
getCameras(self, chanConfig)
Extracts the camera(s) out of the ChanConfig record, parents
them all to base.camera, and adds them to base.cameraList.
"""
@ -393,7 +388,7 @@ class ShowBase:
# be more than one display region/camera node beneath each
# one.
for i in range(chanConfig.getNumGroups()):
camera = self.camera.attachNewNode(chanConfig.getGroupNode(i))
camera = self.render.attachNewNode(chanConfig.getGroupNode(i))
cam = camera.find('**/+Camera')
lens = cam.node().getLens()
@ -409,19 +404,18 @@ class ShowBase:
for i in range(chanConfig.getNumDrs()):
self.groupList.append(chanConfig.getGroupMembership(i))
# Set the default camera
# Set the default camera and cam
if self.camera == None:
self.camera = self.cameraList[0]
if self.cam == None:
self.cam = self.camList[0]
# If you need to get a handle to the camera node itself,
# use self.camNode.
self.camNode = self.cam.node()
# If you need to adjust camera parameters, like fov or
# near/far clipping planes, use self.camLens.
self.camLens = self.camNode.getLens()
def getAlt(self):
return base.mouseWatcherNode.getModifierButtons().isDown(
KeyboardButton.alt())
@ -576,12 +570,13 @@ class ShowBase:
self.backfaceCullingOn()
def backfaceCullingOn(self):
self.render.setTwoSided(self.wireframeEnabled)
if not self.backfaceCullingEnabled:
self.render.setTwoSided(0)
self.backfaceCullingEnabled = 1
def backfaceCullingOff(self):
if not self.wireframeEnabled:
self.render.setTwoSided(0)
if self.backfaceCullingEnabled:
self.render.setTwoSided(1)
self.backfaceCullingEnabled = 0
def toggleTexture(self):

View File

@ -5,6 +5,7 @@ from MessengerGlobal import *
import time
import fnmatch
import string
import signal
# MRM: Need to make internal task variables like time, name, index
# more unique (less likely to have name clashes)
@ -230,6 +231,8 @@ class TaskManager:
TaskManager.notify = directNotify.newCategory("TaskManager")
self.taskTimerVerbose = 0
self.extendedExceptions = 0
self.fKeyboardInterrupt = 0
self.interruptCount = 0
self.pStatsTasks = 0
self.resumeFunc = None
self.fVerbose = 0
@ -241,6 +244,14 @@ class TaskManager:
self.fVerbose = value
messenger.send('TaskManager-setVerbose', sentArgs = [value])
def keyboardInterruptHandler(self, signalNumber, stackFrame):
self.fKeyboardInterrupt = 1
self.interruptCount += 1
if self.interruptCount == 2:
# The user must really want to interrupt this process
# Next time around use the default interrupt handler
signal.signal(signal.SIGINT, signal.default_int_handler)
def add(self, funcOrTask, name, priority = 0):
"""
Add a new task to the taskMgr.
@ -370,6 +381,12 @@ class TaskManager:
if TaskManager.notify.getDebug():
TaskManager.notify.debug('step')
self.currentTime, self.currentFrame = self.__getTimeFrame()
# Replace keyboard interrupt handler during task list processing
# so we catch the keyboard interrupt but don't handle it until
# after task list processing is complete.
self.fKeyboardInterrupt = 0
self.interruptCount = 0
signal.signal(signal.SIGINT, self.keyboardInterruptHandler)
for task in self.taskList:
task.setCurrentTimeFrame(self.currentTime, self.currentFrame)
@ -410,6 +427,10 @@ class TaskManager:
self.__removeTask(task)
else:
raise StandardError, "Task named %s did not return cont, exit, or done" % task.name
# Restore default interrupt handler
signal.signal(signal.SIGINT, signal.default_int_handler)
if self.fKeyboardInterrupt:
raise KeyboardInterrupt
return len(self.taskList)
def run(self):

View File

@ -695,7 +695,7 @@ class DirectSessionPanel(AppShell):
dictName = name
else:
# Generate a unique name for the dict
dictName = name + '-' + `nodePath.id().this`
dictName = name + '-' + `nodePath.id()`
if not dict.has_key(dictName):
# Update combo box to include new item
names.append(dictName)

View File

@ -292,8 +292,7 @@ class MopathRecorder(AppShell, PandaObject):
resolution = 0.01, command = self.playbackGoTo, side = TOP)
widget.component('hull')['relief'] = RIDGE
# Kill playback task if drag slider
widget.component('scale').bind(
'<ButtonPress-1>', lambda e = None, s = self: s.stopPlayback())
widget['preCallback'] = self.stopPlayback
# Jam duration entry into entry scale
self.createLabeledEntry(widget.labelFrame, 'Resample', 'Path Duration',
'Set total curve duration',
@ -371,7 +370,7 @@ class MopathRecorder(AppShell, PandaObject):
'Number of samples in resampled curve',
resolution = 1, min = 2, max = 1000, command = self.setNumSamples)
widget.component('hull')['relief'] = RIDGE
widget['preCallback'] = widget['postCallback'] = self.sampleCurve
widget['postCallback'] = self.sampleCurve
frame = Frame(resampleFrame)
self.createButton(
@ -785,7 +784,9 @@ class MopathRecorder(AppShell, PandaObject):
def extractPointSetFromCurveCollection(self):
# Use curve to compute new point set
# Record maxT
print 'before', self.maxT
self.maxT = self.curveCollection.getMaxT()
print 'after', self.maxT
# Determine num samples
# Limit point set to 1000 points and samples per second to 30
samplesPerSegment = min(30.0, 1000.0/self.curveCollection.getMaxT())
@ -1232,7 +1233,7 @@ class MopathRecorder(AppShell, PandaObject):
dictName = name
else:
# Generate a unique name for the dict
dictName = name + '-' + `nodePath.id().this`
dictName = name + '-' + `nodePath.id()`
if not dict.has_key(dictName):
# Update combo box to include new item
names.append(dictName)
@ -1248,7 +1249,6 @@ class MopathRecorder(AppShell, PandaObject):
def playbackGoTo(self, time):
if self.curveCollection == None:
return
print time
self.playbackTime = CLAMP(time, 0.0, self.maxT)
if self.curveCollection != None:
pos = Point3(0)

View File

@ -493,7 +493,7 @@ class Placer(AppShell):
dictName = name
else:
# Generate a unique name for the dict
dictName = name + '-' + `nodePath.id().this`
dictName = name + '-' + `nodePath.id()`
if not dict.has_key(dictName):
# Update combo box to include new item
names.append(dictName)

View File

@ -374,6 +374,8 @@ class SliderWidget(Pmw.MegaWidget):
if fInside:
self._fPressInside = 1
self._fUpdate = 1
if self['preCallback']:
apply(self['preCallback'], self['callbackData'])
self._updateValue(event)
else:
self._fPressInside = 0
@ -385,11 +387,16 @@ class SliderWidget(Pmw.MegaWidget):
event.y_root - self._widget.winfo_rooty())
if canvasY > 0:
self._fUpdate = 1
if self['preCallback']:
apply(self['preCallback'], self['callbackData'])
self._unpostOnNextRelease()
elif self._fUpdate:
self._updateValue(event)
def _widgetBtnRelease(self, event):
# Do post callback if any
if self._fUpdate and self['postCallback']:
apply(self['postCallback'], self['callbackData'])
if (self._fUnpost or
(not (self._firstPress or self._fPressInside))):
self._unpostSlider()