mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
*** empty log message ***
This commit is contained in:
parent
705edc62dc
commit
f7f44a3e18
@ -2,6 +2,7 @@ lib
|
||||
lib/py
|
||||
src/actor
|
||||
src/directtools
|
||||
src/directdevices
|
||||
src/directnotify
|
||||
src/distributed
|
||||
src/ffi
|
||||
|
193
direct/src/directdevices/DirectDeviceManager.py
Normal file
193
direct/src/directdevices/DirectDeviceManager.py
Normal file
@ -0,0 +1,193 @@
|
||||
""" Class used to create and control vrpn devices """
|
||||
from PandaObject import *
|
||||
|
||||
class DirectDeviceManager(VrpnClient, PandaObject):
|
||||
def __init__(self, server = None):
|
||||
# Determine which server to use
|
||||
if server != None:
|
||||
# One give as constructor argument
|
||||
self.server = server
|
||||
else:
|
||||
# Check config file, if that fails, use default
|
||||
self.server = base.config.GetString('vrpn-server', 'spacedyne')
|
||||
|
||||
# Create a vrpn client
|
||||
VrpnClient.__init__(self, self.server)
|
||||
|
||||
def createButtons(self, device):
|
||||
return DirectButtons(self, device)
|
||||
|
||||
def createAnalogs(self, device):
|
||||
return DirectAnalogs(self, device)
|
||||
|
||||
def createDials(self, device):
|
||||
return DirectDials(self, device)
|
||||
|
||||
def createTimecodeReader(self, device):
|
||||
return DirectTimecodeReader(self, device)
|
||||
|
||||
class DirectButtons(ButtonNode, PandaObject):
|
||||
buttonCount = 0
|
||||
def __init__(self, vrpnClient, device):
|
||||
# Keep track of number of buttons created
|
||||
DirectButtons.buttonCount += 1
|
||||
# Create a unique name for this button object
|
||||
self.name = 'DirectButtons-' + `DirectButtons.buttonCount`
|
||||
# Create a new button node for the given device
|
||||
ButtonNode.__init__(self, vrpnClient, device)
|
||||
# Attach node to data graph
|
||||
self.nodePath = base.dataRoot.attachNewNode(self)
|
||||
|
||||
def __getitem__(self, index):
|
||||
if (index < 0) | (index > self.getNumButtons()):
|
||||
raise IndexError
|
||||
return self.getButtonState(index)
|
||||
|
||||
def __len__(self):
|
||||
return self.getNumButtons()
|
||||
|
||||
def enable(self):
|
||||
self.nodePath.reparentTo(base.dataRoot)
|
||||
|
||||
def disable(self):
|
||||
self.nodePath.reparentTo(base.dataUnused)
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def getNodePath(self):
|
||||
return self.nodePath
|
||||
|
||||
def __repr__(self):
|
||||
str = self.name + ': '
|
||||
for val in self:
|
||||
str = str + '%d' % val + ' '
|
||||
return str
|
||||
|
||||
class DirectAnalogs(AnalogNode, PandaObject):
|
||||
analogCount = 0
|
||||
def __init__(self, vrpnClient, device):
|
||||
# Keep track of number of analogs created
|
||||
DirectAnalogs.analogCount += 1
|
||||
# Create a unique name for this analog object
|
||||
self.name = 'DirectAnalogs-' + `DirectAnalogs.analogCount`
|
||||
# Create a new analog node for the given device
|
||||
AnalogNode.__init__(self, vrpnClient, device)
|
||||
# Attach node to data graph
|
||||
self.nodePath = base.dataRoot.attachNewNode(self)
|
||||
|
||||
def __getitem__(self, index):
|
||||
if (index < 0) | index > self.getNumControls():
|
||||
raise IndexError
|
||||
return self.getControlState(index)
|
||||
|
||||
def __len__(self):
|
||||
return self.getNumControls()
|
||||
|
||||
def enable(self):
|
||||
self.nodePath.reparentTo(base.dataRoot)
|
||||
|
||||
def disable(self):
|
||||
self.nodePath.reparentTo(base.dataUnused)
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def getNodePath(self):
|
||||
return self.nodePath
|
||||
|
||||
def __repr__(self):
|
||||
str = self.name + ': '
|
||||
for val in self:
|
||||
str = str + '%.3f' % val + ' '
|
||||
return str
|
||||
|
||||
class DirectDials(DialNode, PandaObject):
|
||||
dialCount = 0
|
||||
def __init__(self, vrpnClient, device):
|
||||
# Keep track of number of dials created
|
||||
DirectDials.dialCount += 1
|
||||
# Create a unique name for this dial object
|
||||
self.name = 'DirectDials-' + `DirectDials.dialCount`
|
||||
# Create a new dial node for the given device
|
||||
DialNode.__init__(self, vrpnClient, device)
|
||||
# Attach node to data graph
|
||||
self.nodePath = base.dataRoot.attachNewNode(self)
|
||||
|
||||
def __getitem__(self, index):
|
||||
if (index < 0) | (index > self.getNumDials()):
|
||||
raise IndexError
|
||||
return self.readDial(index)
|
||||
|
||||
def __len__(self):
|
||||
return self.getNumDials()
|
||||
|
||||
def enable(self):
|
||||
self.nodePath.reparentTo(base.dataRoot)
|
||||
|
||||
def disable(self):
|
||||
self.nodePath.reparentTo(base.dataUnused)
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def getNodePath(self):
|
||||
return self.nodePath
|
||||
|
||||
def __repr__(self):
|
||||
str = self.name + ': '
|
||||
for val in self:
|
||||
str = str + '%.3f' % val + ' '
|
||||
return str
|
||||
|
||||
class DirectTimecodeReader(AnalogNode, PandaObject):
|
||||
timecodeReaderCount = 0
|
||||
def __init__(self, vrpnClient, device):
|
||||
# Keep track of number of timecodeReader created
|
||||
DirectTimecodeReader.timecodeReaderCount += 1
|
||||
# Create a unique name for this dial object
|
||||
self.name = ('DirectTimecodeReader-' +
|
||||
`DirectTimecodeReader.timecodeReaderCount`)
|
||||
# Initialize components of timecode
|
||||
self.frames = 0
|
||||
self.seconds = 0
|
||||
self.minutes = 0
|
||||
self.hours = 0
|
||||
# Create a new dial node for the given device
|
||||
AnalogNode.__init__(self, vrpnClient, device)
|
||||
# Attach node to data graph
|
||||
self.nodePath = base.dataRoot.attachNewNode(self)
|
||||
|
||||
def enable(self):
|
||||
self.nodePath.reparentTo(base.dataRoot)
|
||||
|
||||
def disable(self):
|
||||
self.nodePath.reparentTo(base.dataUnused)
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def getNodePath(self):
|
||||
return self.nodePath
|
||||
|
||||
def getTime(self):
|
||||
# Assume only one card, use channel 0
|
||||
timeBits = int(self.getControlState(0))
|
||||
self.frames = ((timeBits & 0xF) +
|
||||
(((timeBits & 0xF0) >> 4) * 10))
|
||||
self.seconds = (((timeBits & 0x0F00) >> 8) +
|
||||
(((timeBits & 0xF000) >> 12) * 10))
|
||||
self.minutes = ((((timeBits & 0x0F0000) >> 16) * 10) +
|
||||
((timeBits & 0xF00000) >> 20))
|
||||
self.hours = ((((timeBits & 0xF0000000) >> 24) * 10) +
|
||||
((timeBits & 0xF0000000) >> 28))
|
||||
self.totalSeconds = ((self.hours * 3600) +
|
||||
(self.minutes * 60) +
|
||||
self.seconds +
|
||||
(self.frames / 30.0))
|
||||
return (self.hours, self.minutes, self.seconds, self.frames,
|
||||
self.totalSeconds)
|
||||
|
||||
def __repr__(self):
|
||||
str = ('%s: %d:%d:%d:%d' % ((self.name,) + self.getTime()[:-1]))
|
||||
return str
|
209
direct/src/directdevices/DirectJoybox.py
Normal file
209
direct/src/directdevices/DirectJoybox.py
Normal file
@ -0,0 +1,209 @@
|
||||
""" Class used to create and control joybox device """
|
||||
from PandaObject import *
|
||||
from DirectDeviceManager import *
|
||||
from DirectGeometry import CLAMP
|
||||
import OnscreenText
|
||||
|
||||
JOY_MIN = -0.95
|
||||
JOY_MAX = 0.95
|
||||
JOY_RANGE = JOY_MAX - JOY_MIN
|
||||
JOY_DEADBAND = 0.05
|
||||
# BUTTONS
|
||||
L_STICK = 0
|
||||
L_UPPER = 1
|
||||
L_LOWER = 2
|
||||
R_STICK = 3
|
||||
R_UPPER = 4
|
||||
R_LOWER = 5
|
||||
# ANALOGS
|
||||
L_LEFT_RIGHT = 0
|
||||
L_FWD_BACK = 1
|
||||
L_TWIST = 2
|
||||
L_SLIDE = 3
|
||||
R_LEFT_RIGHT = 4
|
||||
R_FWD_BACK = 5
|
||||
R_TWIST = 6
|
||||
R_SLIDE = 7
|
||||
|
||||
class DirectJoybox(PandaObject):
|
||||
joyboxCount = 0
|
||||
xyzScale = 1.0
|
||||
hprScale = 1.0
|
||||
def __init__(self, nodePath = direct.camera):
|
||||
# See if device manager has been initialized
|
||||
if direct.deviceManager == None:
|
||||
direct.deviceManager = DirectDeviceManager()
|
||||
# Set name
|
||||
self.name = 'Joybox-' + `DirectJoybox.joyboxCount`
|
||||
# Get buttons and analogs
|
||||
self.device = base.config.GetString('joybox-device', 'CerealBox')
|
||||
self.analogs = direct.deviceManager.createAnalogs(self.device)
|
||||
self.buttons = direct.deviceManager.createButtons(self.device)
|
||||
self.aList = [0,0,0,0,0,0,0,0]
|
||||
self.bList = [0,0,0,0,0,0,0,0]
|
||||
self.mapping = [0,1,2,4,5,6]
|
||||
self.modifier = [1,1,1,1,1,1]
|
||||
# Button registry
|
||||
self.addButtonEvents()
|
||||
# Initialize time
|
||||
self.lastTime = globalClock.getTime()
|
||||
# Record node path
|
||||
self.nodePath = nodePath
|
||||
# Text object to display current mode
|
||||
self.readout = OnscreenText.OnscreenText( '', -0.9, -0.95 )
|
||||
# Pick initial mode
|
||||
self.updateFunc = self.joeFly
|
||||
# Spawn update task
|
||||
self.enable()
|
||||
|
||||
def enable(self):
|
||||
taskMgr.spawnMethodNamed(self.updateTask, self.name + '-updateTask')
|
||||
|
||||
def disable(self):
|
||||
taskMgr.removeTasksNamed(self.name + '-updateTask')
|
||||
|
||||
def addButtonEvents(self):
|
||||
self.breg = ButtonRegistry.ptr()
|
||||
# MRM: Hard coded!
|
||||
for i in range(8):
|
||||
self.buttons.setButtonMap(
|
||||
i, self.breg.getButton(self.getEventName(i)))
|
||||
self.eventThrower = self.buttons.getNodePath().attachNewNode(
|
||||
ButtonThrower())
|
||||
|
||||
def setNodePath(self, nodePath):
|
||||
self.nodePath = nodePath
|
||||
def getNodePath(self):
|
||||
return self.nodePath
|
||||
def getEventName(self, index):
|
||||
return self.name + '-button-' + `index`
|
||||
|
||||
def updateTask(self, state):
|
||||
self.updateVals()
|
||||
self.updateFunc()
|
||||
return Task.cont
|
||||
|
||||
def updateVals(self):
|
||||
# Update delta time
|
||||
cTime = globalClock.getTime()
|
||||
self.deltaTime = cTime - self.lastTime
|
||||
self.lastTime = cTime
|
||||
# Update analogs
|
||||
for i in range(len(self.analogs)):
|
||||
try:
|
||||
self.aList[i] = self.normalizeAnalogChannel(i)
|
||||
except IndexError:
|
||||
# That channel may not have been updated yet
|
||||
pass
|
||||
# Update buttons
|
||||
for i in range(len(self.buttons)):
|
||||
try:
|
||||
self.bList[i] = self.buttons[i]
|
||||
except IndexError:
|
||||
# That channel may not have been updated yet
|
||||
pass
|
||||
|
||||
def normalizeAnalog(self, val, min = -1, max = -1):
|
||||
val = CLAMP(val, JOY_MIN, JOY_MAX)
|
||||
if abs(val) < JOY_DEADBAND:
|
||||
val = 0.0
|
||||
return ((max - min) * ((val - JOY_MIN) / JOY_RANGE)) + min
|
||||
|
||||
def normalizeAnalogChannel(self, chan, min = -1, max = 1):
|
||||
if (chan == 2) | (chan == 6):
|
||||
return self.normalizeAnalog(self.analogs[chan] * 3.0, min, max)
|
||||
else:
|
||||
return self.normalizeAnalog(self.analogs[chan], min, max)
|
||||
|
||||
def showMode(self, modeText):
|
||||
def hideText(state, s = self):
|
||||
s.readout.setText('')
|
||||
return Task.done
|
||||
taskMgr.removeTasksNamed(self.name + '-showMode')
|
||||
# Update display
|
||||
self.readout.setText(modeText)
|
||||
t = taskMgr.doMethodLater(3.0, hideText, self.name + '-showMode')
|
||||
t.uponDeath = hideText
|
||||
|
||||
def setMode(self, func, name):
|
||||
self.disable()
|
||||
self.updateFunc = func
|
||||
self.showMode(name)
|
||||
self.enable()
|
||||
|
||||
def joeMode(self):
|
||||
self.setMode(self.joeFly, 'Joe Mode')
|
||||
|
||||
def joeFly(self):
|
||||
hprScale = (self.normalizeAnalogChannel(3, 0.1, 200) *
|
||||
DirectJoybox.hprScale)
|
||||
posScale = (self.normalizeAnalogChannel(7, 0.1, 100) *
|
||||
DirectJoybox.xyzScale)
|
||||
# XYZ
|
||||
x = self.aList[4]
|
||||
y = self.aList[5]
|
||||
if self.bList[L_STICK]:
|
||||
z = 0.0
|
||||
else:
|
||||
z = self.aList[L_FWD_BACK]
|
||||
pos = Vec3(x,y,z) * (posScale * self.deltaTime)
|
||||
# HPR
|
||||
h = -1 * self.aList[R_TWIST]
|
||||
if self.bList[L_STICK]:
|
||||
p = -1 * self.aList[L_FWD_BACK]
|
||||
else:
|
||||
p = 0.0
|
||||
r = 0.0
|
||||
hpr = Vec3(h,p,r) * (hprScale * self.deltaTime)
|
||||
# Move node path
|
||||
self.nodePath.setPosHpr(self.nodePath, pos, hpr)
|
||||
|
||||
def joyboxFly(self):
|
||||
hprScale = (self.normalizeAnalogChannel(3, 0.1, 200) *
|
||||
DirectJoybox.hprScale)
|
||||
posScale = (self.normalizeAnalogChannel(7, 0.1, 100) *
|
||||
DirectJoybox.xyzScale)
|
||||
x = self.analogs[self.mapping[0]] * self.modifier[0]
|
||||
y = self.analogs[self.mapping[1]] * self.modifier[1]
|
||||
z = self.analogs[self.mapping[2]] * self.modifier[2]
|
||||
pos = Vec3(x,y,z) * (posScale * self.deltaTime)
|
||||
|
||||
h = self.analogs[self.mapping[3]] * self.modifier[3]
|
||||
p = self.analogs[self.mapping[4]] * self.modifier[4]
|
||||
r = self.analogs[self.mapping[5]] * self.modifier[5]
|
||||
hpr = Vec3(h,p,r) * (hprScale * self.deltaTime)
|
||||
# Move node path
|
||||
self.nodePath.setPosHpr(self.nodePath, pos, hpr)
|
||||
|
||||
def demoMode(self):
|
||||
self.mapping = [4,5,1,6,0,0]
|
||||
self.modifier = [1,1,1,-1,0,0]
|
||||
self.setMode(self.joyboxFly, 'Demo Mode')
|
||||
|
||||
def driveMode(self):
|
||||
self.mapping = [0,5,1,4,1,0]
|
||||
self.modifier = [1,1,1,-1,0,0]
|
||||
self.setMode(self.joyboxFly, 'Drive Mode')
|
||||
|
||||
def hprXyzMode(self):
|
||||
self.mapping = [4,5,6,2,1,0]
|
||||
self.modifier = [1,1,-1,-1,-1,1]
|
||||
self.setMode(self.joyboxFly, 'HprXyz Mode')
|
||||
|
||||
def lookaroundMode(self):
|
||||
self.mapping = [0,0,0,4,5,0]
|
||||
self.modifier = [0,0,0,-1,-1,0]
|
||||
self.setMode(self.joyboxFly, 'Lookaround Mode')
|
||||
|
||||
def walkthruMode(self):
|
||||
self.mapping = [4,5,2,6,1,0]
|
||||
self.modifier = [1,1,-1,-1,-1, 1]
|
||||
self.setMode(self.joyboxFly, 'Walkthru Mode')
|
||||
|
||||
def jbTest():
|
||||
jb = DirectJoybox()
|
||||
jb.joeMode()
|
||||
jb.accept(jb.getEventName(R_UPPER), jb.joeMode)
|
||||
direct.cameraControl.accept(jb.getEventName(L_UPPER),
|
||||
direct.cameraControl.orbitUprightCam)
|
||||
return jb
|
@ -6,6 +6,7 @@ from DirectGrid import *
|
||||
from DirectGeometry import *
|
||||
from DirectLights import *
|
||||
from DirectSessionPanel import *
|
||||
from DirectDeviceManager import *
|
||||
import Placer
|
||||
import OnscreenText
|
||||
import types
|
||||
@ -50,6 +51,12 @@ class DirectSession(PandaObject):
|
||||
# self.readout.textNode.setCardColor(0.5, 0.5, 0.5, 0.5)
|
||||
self.readout.reparentTo( hidden )
|
||||
|
||||
# Create a vrpn client vrpn-server or default
|
||||
if base.config.GetBool('want-vrpn', 0):
|
||||
self.deviceManager = DirectDeviceManager()
|
||||
else:
|
||||
self.deviceManager = None
|
||||
|
||||
self.fControl = 0
|
||||
self.fAlt = 0
|
||||
self.fShift = 0
|
||||
|
@ -71,6 +71,8 @@ class ForceGroup(DirectObject):
|
||||
# Utility functions
|
||||
def __getitem__(self, index):
|
||||
"""__getItem__(self, index)"""
|
||||
if (index < 0) | (index > self.node.getNumForces()):
|
||||
raise IndexError
|
||||
return self.node.getForce(index)
|
||||
|
||||
def __len__(self):
|
||||
|
@ -49,8 +49,7 @@ class ParticleEffect(NodePath):
|
||||
self.forceGroupDict[forceGroup.getName()] = forceGroup
|
||||
|
||||
# Associate the force group with all particles
|
||||
flist = forceGroup.asList()
|
||||
for f in flist:
|
||||
for f in forceGroup:
|
||||
self.addForce(f)
|
||||
|
||||
def addForce(self, force):
|
||||
@ -65,8 +64,7 @@ class ParticleEffect(NodePath):
|
||||
self.forceGroupDict[forceGroup.getName()] = None
|
||||
|
||||
# Remove forces from all particles
|
||||
flist = forceGroup.asList()
|
||||
for f in flist:
|
||||
for f in forceGroup:
|
||||
self.removeForce(f)
|
||||
|
||||
def removeForce(self, force):
|
||||
@ -81,8 +79,7 @@ class ParticleEffect(NodePath):
|
||||
|
||||
# Associate all forces in all force groups with the particles
|
||||
for fg in self.forceGroupDict.values():
|
||||
flist = fg.asList()
|
||||
for f in flist:
|
||||
for f in fg:
|
||||
particles.addForce(f)
|
||||
|
||||
def removeParticles(self, particles):
|
||||
@ -92,8 +89,7 @@ class ParticleEffect(NodePath):
|
||||
|
||||
# Remove all forces from the particles
|
||||
for fg in self.forceGroupDict.values():
|
||||
flist = fg.asList()
|
||||
for f in flist:
|
||||
for f in fg:
|
||||
particles.removeForce(f)
|
||||
|
||||
def getParticlesList(self):
|
||||
|
@ -1627,7 +1627,7 @@ class ParticlePanel(AppShell):
|
||||
forceGroup.getName())
|
||||
self.forcePage = self.forceGroupNotebook.add(self.forcePageName)
|
||||
self.forcePagesDict[self.forcePageName] = self.forcePage
|
||||
for force in forceGroup.asList():
|
||||
for force in forceGroup:
|
||||
self.addForceWidget(forceGroup, force)
|
||||
|
||||
def addForceWidget(self, forceGroup, force):
|
||||
@ -1635,7 +1635,7 @@ class ParticlePanel(AppShell):
|
||||
pageName = self.forcePageName
|
||||
# How many forces of the same type in the force group object
|
||||
count = 0
|
||||
for f in forceGroup.asList():
|
||||
for f in forceGroup:
|
||||
if f.getClassType().eq(force.getClassType()):
|
||||
count += 1
|
||||
if isinstance(force, LinearVectorForce):
|
||||
|
Loading…
x
Reference in New Issue
Block a user