mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-09 21:33:58 -04:00
*** empty log message ***
This commit is contained in:
parent
59d17bc208
commit
0ba45e5eda
0
direct/src/level/AndLoEntity.py
Executable file
0
direct/src/level/AndLoEntity.py
Executable file
58
direct/src/level/AndLoEntityAI.py
Executable file
58
direct/src/level/AndLoEntityAI.py
Executable file
@ -0,0 +1,58 @@
|
||||
"""AndLoEntityAI.py: contains the AndLoEntity class"""
|
||||
|
||||
|
||||
import PandaObject
|
||||
import DirectNotifyGlobal
|
||||
import Entity
|
||||
|
||||
|
||||
class AndLoEntityAI(Entity.Entity, PandaObject.PandaObject):
|
||||
if __debug__:
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory(
|
||||
'AndLoEntityAI')
|
||||
|
||||
def __init__(self, air, levelDoId, entId, zoneId=None):
|
||||
"""entId: """
|
||||
assert(self.debugPrint(
|
||||
"AndLoEntityAI(air=%s, levelDoId=%s, entId=%s, zoneId=%s)"
|
||||
%("the air", levelDoId, entId, zoneId)))
|
||||
self.input1 = None
|
||||
self.input2 = None
|
||||
self.levelDoId = levelDoId
|
||||
level = air.doId2do[self.levelDoId]
|
||||
Entity.Entity.__init__(self, level, entId)
|
||||
self.initializeEntity()
|
||||
self.setInput_input1_bool(self.input_input1_bool)
|
||||
self.setInput_input2_bool(self.input_input2_bool)
|
||||
|
||||
def setIsInput1(self, isTrue):
|
||||
assert(self.debugPrint("setIsInput1(isTrue=%s)"%(isTrue,)))
|
||||
self.isInput1=isTrue
|
||||
if self.isInput2:
|
||||
messenger.send(self.getName(), [isTrue])
|
||||
|
||||
def setIsInput2(self, isTrue):
|
||||
assert(self.debugPrint("setIsInput1(isTrue=%s)"%(isTrue,)))
|
||||
self.isInput2=isTrue
|
||||
if self.isInput1:
|
||||
messenger.send(self.getName(), [isTrue])
|
||||
|
||||
def setInput_input1_bool(self, event):
|
||||
assert(self.debugPrint("setInput_input1_bool(event=%s)"%(event,)))
|
||||
if self.input1:
|
||||
self.ignore(self.input1)
|
||||
self.input1 = "switch-%s"%(event,)
|
||||
if self.input1:
|
||||
self.accept(self.input1, self.setIsInput1)
|
||||
|
||||
def setInput_input2_bool(self, event):
|
||||
assert(self.debugPrint("setInput_input2_bool(event=%s)"%(event,)))
|
||||
if self.input2:
|
||||
self.ignore(self.input2)
|
||||
self.input2 = "switch-%s"%(event,)
|
||||
if self.input2:
|
||||
self.accept(self.input2, self.setIsInput2)
|
||||
|
||||
def getName(self):
|
||||
#return "andLoEntity-%s"%(self.entId,)
|
||||
return "switch-%s"%(self.entId,)
|
56
direct/src/level/BasicEntities.py
Executable file
56
direct/src/level/BasicEntities.py
Executable file
@ -0,0 +1,56 @@
|
||||
"""BasicEntities module: contains the BasicEntities class"""
|
||||
|
||||
import Entity
|
||||
import DistributedEntity
|
||||
import NodePath
|
||||
|
||||
# this is an internal class, do not instantiate.
|
||||
class privNodePathImpl(NodePath.NodePath):
|
||||
def __init__(self, name):
|
||||
node = hidden.attachNewNode(name)
|
||||
NodePath.NodePath.__init__(self, node)
|
||||
|
||||
def initializeEntity(self):
|
||||
self.callSetters(('pos','x','y','z',
|
||||
'hpr','h','p','r',
|
||||
'scale','sx','sx','sz'))
|
||||
|
||||
if hasattr(self, 'parent'):
|
||||
self.level.requestReparent(self, self.parent)
|
||||
|
||||
def destroy(self):
|
||||
self.removeNode()
|
||||
|
||||
class NodePathEntity(Entity.Entity, privNodePathImpl):
|
||||
"""This is an entity that represents a NodePath on the client.
|
||||
It may be instantiated directly or used as a base class for other
|
||||
entity types."""
|
||||
def __init__(self, level, entId):
|
||||
Entity.Entity.__init__(self, level, entId)
|
||||
privNodePathImpl.__init__(self, str(self))
|
||||
self.initializeEntity()
|
||||
|
||||
def initializeEntity(self):
|
||||
Entity.Entity.initializeEntity(self)
|
||||
privNodePathImpl.initializeEntity(self)
|
||||
|
||||
def destroy(self):
|
||||
Entity.Entity.destroy(self)
|
||||
privNodePathImpl.initializeEntity(self)
|
||||
|
||||
class DistributedNodePathEntity(DistributedEntity.DistributedEntity,
|
||||
privNodePathImpl):
|
||||
"""This is a distributed version of NodePathEntity. It should not
|
||||
be instantiated directly; derive your client-side distEntity from
|
||||
this class instead of DistributedEntity."""
|
||||
def __init__(self, cr):
|
||||
DistributedEntity.DistributedEntity.__init__(self, cr)
|
||||
privNodePathImpl.__init__(self, 'DistributedNodePathEntity')
|
||||
|
||||
def initializeEntity(self):
|
||||
DistributedEntity.DistributedEntity.initializeEntity(self)
|
||||
privNodePathImpl.initializeEntity(self)
|
||||
|
||||
def destroy(self):
|
||||
DistributedEntity.DistributedEntity.destroy(self)
|
||||
privNodePathImpl.destroy(self)
|
46
direct/src/level/DistributedEntity.py
Executable file
46
direct/src/level/DistributedEntity.py
Executable file
@ -0,0 +1,46 @@
|
||||
import DistributedObject
|
||||
import Entity
|
||||
import DirectNotifyGlobal
|
||||
|
||||
class DistributedEntity(DistributedObject.DistributedObject, Entity.Entity):
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory(
|
||||
'DistributedEntity')
|
||||
|
||||
def __init__(self, cr):
|
||||
DistributedObject.DistributedObject.__init__(self, cr)
|
||||
|
||||
def generateInit(self):
|
||||
DistributedEntity.notify.debug('generateInit')
|
||||
DistributedObject.DistributedObject.generateInit(self)
|
||||
# load stuff
|
||||
|
||||
def generate(self):
|
||||
DistributedEntity.notify.debug('generate')
|
||||
DistributedObject.DistributedObject.generate(self)
|
||||
|
||||
def setLevelDoId(self, levelDoId):
|
||||
DistributedEntity.notify.debug('setLevelDoId: %s' % levelDoId)
|
||||
self.levelDoId = levelDoId
|
||||
|
||||
def setEntId(self, entId):
|
||||
DistributedEntity.notify.debug('setEntId: %s' % entId)
|
||||
self.entId = entId
|
||||
|
||||
def announceGenerate(self):
|
||||
DistributedEntity.notify.debug('announceGenerate')
|
||||
|
||||
# ask our level obj for our spec data
|
||||
level = toonbase.tcr.doId2do[self.levelDoId]
|
||||
Entity.Entity.__init__(self, level, self.entId)
|
||||
# this sets all of our initial spec parameters on ourselves
|
||||
self.initializeEntity()
|
||||
|
||||
DistributedObject.DistributedObject.announceGenerate(self)
|
||||
|
||||
def disable(self):
|
||||
DistributedEntity.notify.debug('disable')
|
||||
# stop things
|
||||
|
||||
def delete(self):
|
||||
DistributedEntity.notify.debug('delete')
|
||||
# unload things
|
35
direct/src/level/DistributedEntityAI.py
Executable file
35
direct/src/level/DistributedEntityAI.py
Executable file
@ -0,0 +1,35 @@
|
||||
import DistributedObjectAI
|
||||
import Entity
|
||||
import DirectNotifyGlobal
|
||||
|
||||
class DistributedEntityAI(DistributedObjectAI.DistributedObjectAI,
|
||||
Entity.Entity):
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory(
|
||||
'DistributedEntityAI')
|
||||
|
||||
def __init__(self, air, levelDoId, entId):
|
||||
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
|
||||
self.levelDoId = levelDoId
|
||||
level = self.air.doId2do[self.levelDoId]
|
||||
Entity.Entity.__init__(self, level, entId)
|
||||
# get our spec data
|
||||
self.initializeEntity()
|
||||
|
||||
def generate(self):
|
||||
self.notify.debug('generate')
|
||||
DistributedObjectAI.DistributedObjectAI.generate(self)
|
||||
|
||||
def destroy(self):
|
||||
self.notify.debug('destroy')
|
||||
Entity.Entity.destroy(self)
|
||||
self.requestDelete()
|
||||
|
||||
def delete(self):
|
||||
self.notify.debug('delete')
|
||||
DistributedObjectAI.DistributedObjectAI.delete(self)
|
||||
|
||||
def getLevelDoId(self):
|
||||
return self.levelDoId
|
||||
|
||||
def getEntId(self):
|
||||
return self.entId
|
151
direct/src/level/DistributedInteractiveEntity.py
Normal file
151
direct/src/level/DistributedInteractiveEntity.py
Normal file
@ -0,0 +1,151 @@
|
||||
""" DistributedInteractiveEntity module: contains the DistributedInteractiveEntity
|
||||
class, the client side representation of a 'landmark door'."""
|
||||
|
||||
from ShowBaseGlobal import *
|
||||
from ClockDelta import *
|
||||
|
||||
import DirectNotifyGlobal
|
||||
import FSM
|
||||
import DistributedEntity
|
||||
|
||||
class DistributedInteractiveEntity(DistributedEntity.DistributedEntity):
|
||||
"""
|
||||
DistributedInteractiveEntity class: The client side representation of any
|
||||
simple animated prop.
|
||||
"""
|
||||
|
||||
if __debug__:
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedInteractiveEntity')
|
||||
|
||||
def __init__(self, cr):
|
||||
"""constructor for the DistributedInteractiveEntity"""
|
||||
DistributedEntity.DistributedEntity.__init__(self, cr)
|
||||
assert(self.debugPrint("__init()"))
|
||||
|
||||
self.fsm = FSM.FSM('Distribu, levelDoId, entIdtedInteractiveEntity',
|
||||
[State.State('off',
|
||||
self.enterOff,
|
||||
self.exitOff,
|
||||
['playing',
|
||||
'attract']),
|
||||
State.State('attract',
|
||||
self.enterAttract,
|
||||
self.exitAttract,
|
||||
['playing']),
|
||||
State.State('playing',
|
||||
self.enterPlaying,
|
||||
self.exitPlaying,
|
||||
['attract'])],
|
||||
# Initial State
|
||||
'off',
|
||||
# Final State
|
||||
'off',
|
||||
)
|
||||
self.fsm.enterInitialState()
|
||||
# self.generate will be called automatically.
|
||||
|
||||
def generate(self):
|
||||
"""generate(self)
|
||||
This method is called when the DistributedEntity is reintroduced
|
||||
to the world, either for the first time or from the cache.
|
||||
"""
|
||||
assert(self.debugPrint("generate()"))
|
||||
DistributedEntity.DistributedEntity.generate(self)
|
||||
|
||||
def disable(self):
|
||||
assert(self.debugPrint("disable()"))
|
||||
# Go to the off state when the object is put in the cache
|
||||
self.fsm.request("off")
|
||||
DistributedEntity.DistributedEntity.disable(self)
|
||||
# self.delete() will automatically be called.
|
||||
|
||||
def delete(self):
|
||||
assert(self.debugPrint("delete()"))
|
||||
del self.fsm
|
||||
DistributedEntity.DistributedEntity.delete(self)
|
||||
|
||||
def setAvatarInteract(self, avatarId):
|
||||
"""
|
||||
required dc field.
|
||||
"""
|
||||
assert(self.debugPrint("setAvatarInteract(%s)"%(avatarId,)))
|
||||
assert(not self.__dict__.has_key(avatarId))
|
||||
self.avatarId=avatarId
|
||||
|
||||
def setOwnerDoId(self, ownerDoId):
|
||||
"""
|
||||
required dc field.
|
||||
"""
|
||||
assert(self.debugPrint("setOwnerDoId(%s)"%(ownerDoId,)))
|
||||
assert(not self.__dict__.has_key("ownerDoId"))
|
||||
self.ownerDoId=ownerDoId
|
||||
|
||||
def setInitialState(self, state, timestamp):
|
||||
"""
|
||||
required dc field.
|
||||
"""
|
||||
assert(self.debugPrint("setInitialState(%s, %d)" % (state, timestamp)))
|
||||
assert(not self.__dict__.has_key("initialState"))
|
||||
self.initialState = state
|
||||
self.initialStateTimestamp = timestamp
|
||||
|
||||
def setState(self, state, timestamp):
|
||||
assert(self.debugPrint("setState(%s, %d)" % (state, timestamp)))
|
||||
self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)])
|
||||
|
||||
#def __getPropNodePath(self):
|
||||
# assert(self.debugPrint("__getPropNodePath()"))
|
||||
# if (not self.__dict__.has_key('propNodePath')):
|
||||
# self.propNodePath=self.cr.playGame.hood.loader.geom.find(
|
||||
# "**/prop"+self.entID+":*_DNARoot")
|
||||
# return self.propNodePath
|
||||
|
||||
def enterTrigger(self, args=None):
|
||||
assert(self.debugPrint("enterTrigger(args="+str(args)+")"))
|
||||
messenger.send("DistributedInteractiveEntity_enterTrigger")
|
||||
self.sendUpdate("requestInteract")
|
||||
# the AI server will reply with toonInteract or rejectInteract.
|
||||
|
||||
def exitTrigger(self, args=None):
|
||||
assert(self.debugPrint("exitTrigger(args="+str(args)+")"))
|
||||
messenger.send("DistributedInteractiveEntity_exitTrigger")
|
||||
self.sendUpdate("requestExit")
|
||||
# the AI server will reply with avatarExit.
|
||||
|
||||
def rejectInteract(self):
|
||||
"""Server doesn't let the avatar interact with prop"""
|
||||
assert(self.debugPrint("rejectInteract()"))
|
||||
self.cr.playGame.getPlace().setState('walk')
|
||||
|
||||
def avatarExit(self, avatarId):
|
||||
assert(self.debugPrint("avatarExit(avatarId=%s)"%(avatarId,)))
|
||||
|
||||
##### off state #####
|
||||
|
||||
def enterOff(self):
|
||||
assert(self.debugPrint("enterOff()"))
|
||||
|
||||
def exitOff(self):
|
||||
assert(self.debugPrint("exitOff()"))
|
||||
|
||||
##### attract state #####
|
||||
|
||||
def enterAttract(self, ts):
|
||||
assert(self.debugPrint("enterAttract()"))
|
||||
|
||||
def exitAttract(self):
|
||||
assert(self.debugPrint("exitAttract()"))
|
||||
|
||||
##### playing state #####
|
||||
|
||||
def enterPlaying(self, ts):
|
||||
assert(self.debugPrint("enterPlaying()"))
|
||||
|
||||
def exitPlaying(self):
|
||||
assert(self.debugPrint("exitPlaying()"))
|
||||
|
||||
if __debug__:
|
||||
def debugPrint(self, message):
|
||||
"""for debugging"""
|
||||
return self.notify.debug(
|
||||
str(self.__dict__.get('entId', '?'))+' '+message)
|
144
direct/src/level/DistributedInteractiveEntityAI.py
Normal file
144
direct/src/level/DistributedInteractiveEntityAI.py
Normal file
@ -0,0 +1,144 @@
|
||||
""" DistributedInteractiveEntityAI module: contains the DistributedInteractiveEntityAI
|
||||
class, the server side representation of a simple, animated, interactive
|
||||
prop."""
|
||||
|
||||
|
||||
from AIBaseGlobal import *
|
||||
from ClockDelta import *
|
||||
|
||||
import DirectNotifyGlobal
|
||||
import FSM
|
||||
import DistributedEntityAI
|
||||
import State
|
||||
|
||||
|
||||
class DistributedInteractiveEntityAI(DistributedEntityAI.DistributedEntityAI):
|
||||
"""
|
||||
DistributedInteractiveEntityAI class: The server side representation of
|
||||
an animated prop. This is the object that remembers what the
|
||||
prop is doing. The child of this object, the DistributedAnimatedProp
|
||||
object, is the client side version and updates the display that
|
||||
client's display based on the state of the prop.
|
||||
"""
|
||||
|
||||
if __debug__:
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedInteractiveEntityAI')
|
||||
|
||||
def __init__(self, air, levelDoId, entId):
|
||||
"""entId: a unique identifier for this prop."""
|
||||
DistributedEntityAI.DistributedEntityAI.__init__(self, air,
|
||||
levelDoId, entId)
|
||||
assert(self.debugPrint(
|
||||
"DistributedInteractiveEntityAI(air=%s, entId=%s)"
|
||||
%("the air", entId)))
|
||||
self.fsm = FSM.FSM('DistributedInteractiveEntityAI',
|
||||
[State.State('off',
|
||||
self.enterOff,
|
||||
self.exitOff,
|
||||
['playing']),
|
||||
# Attract is an idle mode. It is named attract
|
||||
# because the prop is not interacting with an
|
||||
# avatar, and is therefore trying to attract an
|
||||
# avatar.
|
||||
State.State('attract',
|
||||
self.enterAttract,
|
||||
self.exitAttract,
|
||||
['playing']),
|
||||
# Playing is for when an avatar is interacting
|
||||
# with the prop.
|
||||
State.State('playing',
|
||||
self.enterPlaying,
|
||||
self.exitPlaying,
|
||||
['attract'])],
|
||||
# Initial State
|
||||
'off',
|
||||
# Final State
|
||||
'off',
|
||||
)
|
||||
self.fsm.enterInitialState()
|
||||
self.avatarId=0
|
||||
|
||||
|
||||
def delete(self):
|
||||
del self.fsm
|
||||
DistributedEntityAI.DistributedEntityAI.delete(self)
|
||||
|
||||
def getAvatarInteract(self):
|
||||
assert(self.debugPrint("getAvatarInteract() returning: %s"%(self.avatarId,)))
|
||||
return self.avatarId
|
||||
|
||||
def getInitialState(self):
|
||||
assert(self.debugPrint("getInitialState()"))
|
||||
return [self.fsm.getCurrentState().getName(),
|
||||
globalClockDelta.getRealNetworkTime()]
|
||||
|
||||
def getOwnerDoId(self):
|
||||
assert(self.debugPrint("getOwnerDoId() returning: %s"%(self.ownerDoId,)))
|
||||
return self.ownerDoId
|
||||
|
||||
def requestInteract(self):
|
||||
assert(self.debugPrint("requestInteract()"))
|
||||
avatarId = self.air.msgSender
|
||||
assert(self.notify.debug(" avatarId:%s"%(avatarId,)))
|
||||
stateName = self.fsm.getCurrentState().getName()
|
||||
if stateName != 'playing':
|
||||
self.sendUpdate("setAvatarInteract", [avatarId])
|
||||
self.avatarId=avatarId
|
||||
self.fsm.request('playing')
|
||||
else:
|
||||
self.sendUpdateToAvatarId(avatarId, "rejectInteract", [])
|
||||
|
||||
def requestExit(self):
|
||||
assert(self.debugPrint("requestExit()"))
|
||||
avatarId = self.air.msgSender
|
||||
assert(self.notify.debug(" avatarId:%s"%(avatarId,)))
|
||||
if avatarId==self.avatarId:
|
||||
stateName = self.fsm.getCurrentState().getName()
|
||||
if stateName == 'playing':
|
||||
self.sendUpdate("avatarExit", [avatarId])
|
||||
self.fsm.request('attract')
|
||||
else:
|
||||
assert(self.notify.debug(" requestExit: invalid avatarId"))
|
||||
|
||||
def getState(self):
|
||||
assert(self.debugPrint("getState()"))
|
||||
return [self.fsm.getCurrentState().getName(),
|
||||
globalClockDelta.getRealNetworkTime()]
|
||||
|
||||
def d_setState(self, state):
|
||||
assert(self.debugPrint("d_setState(state=%s)"%(state,)))
|
||||
self.sendUpdate('setState', [state, globalClockDelta.getRealNetworkTime()])
|
||||
|
||||
##### off state #####
|
||||
|
||||
def enterOff(self):
|
||||
assert(self.debugPrint("enterOff()"))
|
||||
#self.d_setState('off')
|
||||
|
||||
def exitOff(self):
|
||||
assert(self.debugPrint("exitOff()"))
|
||||
|
||||
##### attract state #####
|
||||
|
||||
def enterAttract(self):
|
||||
assert(self.debugPrint("enterAttract()"))
|
||||
self.d_setState('attract')
|
||||
|
||||
def exitAttract(self):
|
||||
assert(self.debugPrint("exitAttract()"))
|
||||
|
||||
##### open state #####
|
||||
|
||||
def enterPlaying(self):
|
||||
assert(self.debugPrint("enterPlaying()"))
|
||||
self.d_setState('playing')
|
||||
|
||||
def exitPlaying(self):
|
||||
assert(self.debugPrint("exitPlaying()"))
|
||||
|
||||
if __debug__:
|
||||
def debugPrint(self, message):
|
||||
"""for debugging"""
|
||||
return self.notify.debug(
|
||||
str(self.__dict__.get('entId', '?'))+' '+message)
|
||||
|
254
direct/src/level/DistributedLevel.py
Executable file
254
direct/src/level/DistributedLevel.py
Executable file
@ -0,0 +1,254 @@
|
||||
"""DistributedLevel.py: contains the DistributedLevel class"""
|
||||
|
||||
from ClockDelta import *
|
||||
from PythonUtil import Functor, sameElements, list2dict, uniqueElements
|
||||
import ToontownGlobals
|
||||
import DistributedObject
|
||||
import LevelBase
|
||||
import DirectNotifyGlobal
|
||||
import EntityCreator
|
||||
|
||||
class DistributedLevel(DistributedObject.DistributedObject,
|
||||
LevelBase.LevelBase):
|
||||
"""DistributedLevel"""
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLevel')
|
||||
|
||||
WantVisibility = config.GetBool('level-visibility', 0)
|
||||
HideZones = config.GetBool('level-hidezones', 1)
|
||||
|
||||
def __init__(self, cr):
|
||||
DistributedObject.DistributedObject.__init__(self, cr)
|
||||
LevelBase.LevelBase.__init__(self)
|
||||
|
||||
def generate(self):
|
||||
self.notify.debug('generate')
|
||||
DistributedObject.DistributedObject.generate(self)
|
||||
|
||||
self.setLevelId(self.doId)
|
||||
|
||||
# this dict stores entity reparents if the parent hasn't been
|
||||
# created yet
|
||||
self.pendingEntId2ParentId = {}
|
||||
|
||||
# Most (if not all) of the timed entities of levels
|
||||
# run on looping intervals that are started once based on
|
||||
# the level's start time.
|
||||
# This sync request is *NOT* guaranteed to finish by the time
|
||||
# the entities get created.
|
||||
# We should listen for any and all time-sync events and re-sync
|
||||
# all our entities at that time.
|
||||
toonbase.tcr.timeManager.synchronize('DistributedLevel.generate')
|
||||
|
||||
# required fields
|
||||
def setZoneIds(self, zoneIds):
|
||||
self.notify.debug('setZoneIds: %s' % zoneIds)
|
||||
self.zoneIds = zoneIds
|
||||
|
||||
def setStartTimestamp(self, timestamp):
|
||||
self.notify.debug('setStartTimestamp: %s' % timestamp)
|
||||
self.startTime = globalClockDelta.networkToLocalTime(timestamp,bits=32)
|
||||
|
||||
def setScenarioIndex(self, scenarioIndex):
|
||||
self.scenarioIndex = scenarioIndex
|
||||
|
||||
def initializeLevel(self, spec):
|
||||
""" subclass should call this as soon as it's located its spec data """
|
||||
LevelBase.LevelBase.initializeLevel(self, spec, self.scenarioIndex)
|
||||
# load stuff
|
||||
self.geom = loader.loadModel(self.spec['modelFilename'])
|
||||
|
||||
def findNumberedNodes(baseString, model=self.geom, self=self):
|
||||
# finds nodes whose name follows the pattern 'baseString#'
|
||||
# where there are no characters after #
|
||||
# returns dictionary that maps # to node
|
||||
potentialNodes = model.findAllMatches(
|
||||
'**/%s*' % baseString).asList()
|
||||
num2node = {}
|
||||
for potentialNode in potentialNodes:
|
||||
name = potentialNode.getName()
|
||||
self.notify.debug('potential match for %s: %s' %
|
||||
(baseString, name))
|
||||
try:
|
||||
num = int(name[len(baseString):])
|
||||
except:
|
||||
continue
|
||||
|
||||
num2node[num] = potentialNode
|
||||
|
||||
return num2node
|
||||
|
||||
# find the zones in the model and fix them up
|
||||
self.zoneNum2Node = findNumberedNodes('Zone')
|
||||
# add the UberZone
|
||||
self.zoneNum2Node[0] = self.geom
|
||||
|
||||
# fix up the floor collisions for walkable zones
|
||||
for zoneNum, zoneNode in self.zoneNum2Node.items():
|
||||
# if this is a walkable zone, fix up the model
|
||||
floorColl = zoneNode.find('**/*FloorCollision*')
|
||||
if not floorColl.isEmpty():
|
||||
# rename the floor collision node, and make sure no other
|
||||
# nodes under the ZoneNode have that name
|
||||
floorCollName = 'Zone%sFloor' % zoneNum
|
||||
others = zoneNode.findAllMatches(
|
||||
'**/%s' % floorCollName).asList()
|
||||
for other in others:
|
||||
other.setName('%s_renamed' % floorCollName)
|
||||
floorColl.setName(floorCollName)
|
||||
|
||||
# listen for zone enter events from floor collisions
|
||||
def handleZoneEnter(collisionEntry,
|
||||
self=self, zoneNum=zoneNum):
|
||||
# eat the collisionEntry
|
||||
self.enterZone(zoneNum)
|
||||
self.accept('enter%s' % floorCollName, handleZoneEnter)
|
||||
|
||||
self.zoneNums = self.zoneNum2Node.keys()
|
||||
self.zoneNums.sort()
|
||||
self.notify.debug('zones: %s' % self.zoneNums)
|
||||
assert sameElements(self.zoneNums, self.spec['zones'].keys() + [0])
|
||||
|
||||
# find the doorway nodes
|
||||
self.doorwayNum2Node = findNumberedNodes('Doorway')
|
||||
|
||||
self.initVisibility()
|
||||
|
||||
# create client-side Entities
|
||||
# TODO: only create client-side Entities for the
|
||||
# currently-visible zones?
|
||||
self.localEntities = {}
|
||||
for entId, spec in self.entId2Spec.iteritems():
|
||||
entity = EntityCreator.createEntity(spec['type'], self, entId)
|
||||
if entity is not None:
|
||||
self.localEntities[entId] = entity
|
||||
|
||||
# there should not be any pending reparents left
|
||||
assert len(self.pendingEntId2ParentId) == 0
|
||||
|
||||
def announceGenerate(self):
|
||||
self.notify.debug('announceGenerate')
|
||||
DistributedObject.DistributedObject.announceGenerate(self)
|
||||
|
||||
def disable(self):
|
||||
self.notify.debug('disable')
|
||||
DistributedObject.DistributedObject.disable(self)
|
||||
self.ignoreAll()
|
||||
|
||||
# destroy all of the local entities
|
||||
for entId, entity in self.localEntities.items():
|
||||
entity.destroy()
|
||||
del self.localEntities
|
||||
|
||||
self.destroyLevel()
|
||||
|
||||
def delete(self):
|
||||
self.notify.debug('delete')
|
||||
DistributedObject.DistributedObject.delete(self)
|
||||
|
||||
def getDoorwayNode(self, doorwayNum):
|
||||
# returns node that doors should parent themselves to
|
||||
return self.doorwayNum2Node[doorwayNum]
|
||||
|
||||
def requestReparent(self, entity, parent):
|
||||
if parent is 'zone':
|
||||
entity.reparentTo(self.zoneNum2Node[entity.zone])
|
||||
else:
|
||||
parentId = parent
|
||||
assert(entity.entId != parentId)
|
||||
|
||||
if self.entities.has_key(parentId):
|
||||
# parent has already been created
|
||||
entity.reparentTo(self.entities[parentId])
|
||||
else:
|
||||
# parent hasn't been created yet; schedule the reparent
|
||||
self.notify.debug(
|
||||
'entity %s requesting reparent to %s, not yet created' %
|
||||
(entity, parent))
|
||||
entId = entity.entId
|
||||
self.pendingEntId2ParentId[entId] = parentId
|
||||
entity.reparentTo(hidden)
|
||||
# do the reparent once the parent is initialized
|
||||
def doReparent(entId=entId, parentId=parentId, self=self):
|
||||
entity=self.getEntity(entId)
|
||||
parent=self.getEntity(parentId)
|
||||
self.notify.debug(
|
||||
'performing pending reparent of %s to %s' %
|
||||
(entity, parent))
|
||||
entity.reparentTo(parent)
|
||||
del self.pendingEntId2ParentId[entId]
|
||||
self.accept(self.getEntityCreateEvent(parentId), doReparent)
|
||||
|
||||
def showZone(self, zoneNum):
|
||||
self.zoneNum2Node[zoneNum].show()
|
||||
|
||||
def hideZone(self, zoneNum):
|
||||
self.zoneNum2Node[zoneNum].hide()
|
||||
|
||||
def setTransparency(self, alpha, zone=None):
|
||||
self.geom.setTransparency(1)
|
||||
if zone is None:
|
||||
node = self.geom
|
||||
else:
|
||||
node = self.zoneNum2Node[zone]
|
||||
node.setAlphaScale(alpha)
|
||||
|
||||
def initVisibility(self):
|
||||
# start out with every zone visible, since none of the zones have
|
||||
# been hidden
|
||||
self.curVisibleZoneNums = list2dict(self.zoneNums)
|
||||
# we have not entered any zone yet
|
||||
self.curZoneNum = None
|
||||
|
||||
# TODO: make this data-driven
|
||||
firstZone = 16
|
||||
self.enterZone(firstZone)
|
||||
|
||||
def enterZone(self, zoneNum):
|
||||
if not DistributedLevel.WantVisibility:
|
||||
return
|
||||
|
||||
if zoneNum == self.curZoneNum:
|
||||
return
|
||||
|
||||
print "enterZone %s" % zoneNum
|
||||
zoneSpec = self.spec['zones'][zoneNum]
|
||||
# use dicts to efficiently ensure that there are no duplicates
|
||||
visibleZoneNums = list2dict([zoneNum])
|
||||
visibleZoneNums.update(list2dict(zoneSpec['visibility']))
|
||||
|
||||
if DistributedLevel.HideZones:
|
||||
# figure out which zones are new and which are going invisible
|
||||
# use dicts because it's faster to use dict.has_key(x)
|
||||
# than 'x in list'
|
||||
addedZoneNums = []
|
||||
removedZoneNums = []
|
||||
allVZ = dict(visibleZoneNums)
|
||||
allVZ.update(self.curVisibleZoneNums)
|
||||
for vz,None in allVZ.items():
|
||||
new = vz in visibleZoneNums
|
||||
old = vz in self.curVisibleZoneNums
|
||||
if new and old:
|
||||
continue
|
||||
if new:
|
||||
addedZoneNums.append(vz)
|
||||
else:
|
||||
removedZoneNums.append(vz)
|
||||
# show the new, hide the old
|
||||
self.notify.debug('showing zones %s' % addedZoneNums)
|
||||
for az in addedZoneNums:
|
||||
self.showZone(az)
|
||||
self.notify.debug('hiding zones %s' % removedZoneNums)
|
||||
for rz in removedZoneNums:
|
||||
self.hideZone(rz)
|
||||
|
||||
# convert the zone numbers into their actual zoneIds
|
||||
# always include Toontown and factory uberZones
|
||||
visibleZoneIds = [ToontownGlobals.UberZone, self.getZoneId(0)]
|
||||
for vz in visibleZoneNums.keys():
|
||||
visibleZoneIds.append(self.getZoneId(vz))
|
||||
assert(uniqueElements(visibleZoneIds))
|
||||
self.notify.debug('new viz list: %s' % visibleZoneIds)
|
||||
|
||||
toonbase.tcr.sendSetZoneMsg(self.getZoneId(zoneNum), visibleZoneIds)
|
||||
self.curZoneNum = zoneNum
|
||||
self.curVisibleZoneNums = visibleZoneNums
|
80
direct/src/level/DistributedLevelAI.py
Executable file
80
direct/src/level/DistributedLevelAI.py
Executable file
@ -0,0 +1,80 @@
|
||||
"""DistributedLevelAI.py: contains the DistributedLevelAI class"""
|
||||
|
||||
from ClockDelta import *
|
||||
import DistributedObjectAI
|
||||
import LevelBase
|
||||
import DirectNotifyGlobal
|
||||
import EntityCreatorAI
|
||||
import WeightedChoice
|
||||
|
||||
class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
||||
LevelBase.LevelBase):
|
||||
"""DistributedLevelAI"""
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLevelAI')
|
||||
|
||||
def __init__(self, air):
|
||||
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
|
||||
LevelBase.LevelBase.__init__(self)
|
||||
|
||||
def initializeLevel(self, spec, uberZoneId):
|
||||
self.uberZoneId = uberZoneId
|
||||
|
||||
# choose a scenario
|
||||
wc = WeightedChoice.WeightedChoice(spec['scenarios'], 1)
|
||||
scenario = wc.choose()
|
||||
scenarioIndex = spec['scenarios'].index(scenario)
|
||||
|
||||
LevelBase.LevelBase.initializeLevel(self, spec, scenarioIndex)
|
||||
|
||||
# allocate the rest of the zones; add one for the uber-zone
|
||||
self.numZones = len(self.spec['zones']) + 1
|
||||
self.zoneIds = [self.uberZoneId]
|
||||
for i in range(1,self.numZones):
|
||||
# there is error checking in air.allocateZone
|
||||
self.zoneIds.append(self.air.allocateZone())
|
||||
|
||||
# record the level's start time so that we can sync the clients
|
||||
self.startTime = globalClock.getRealTime()
|
||||
self.startTimestamp = globalClockDelta.localToNetworkTime(
|
||||
self.startTime, bits=32)
|
||||
|
||||
# required-field getters
|
||||
def getZoneIds(self):
|
||||
return self.zoneIds
|
||||
|
||||
def getStartTimestamp(self):
|
||||
return self.startTimestamp
|
||||
|
||||
def getScenarioIndex(self):
|
||||
return self.scenarioIndex
|
||||
|
||||
def generate(self):
|
||||
self.notify.debug('generate')
|
||||
DistributedObjectAI.DistributedObjectAI.generate(self)
|
||||
|
||||
self.setLevelId(self.doId)
|
||||
|
||||
# create the Entities
|
||||
self.aiEntities = {}
|
||||
for entId, spec in self.entId2Spec.iteritems():
|
||||
self.notify.debug('creating %s %s' % (spec['type'], entId))
|
||||
entity = EntityCreatorAI.createEntity(
|
||||
spec['type'], self.air, self.doId, entId,
|
||||
self.getZoneId(spec['zone']))
|
||||
if entity is not None:
|
||||
self.aiEntities[entId] = entity
|
||||
|
||||
def delete(self):
|
||||
self.notify.debug('delete')
|
||||
|
||||
for entId in self.aiEntities.keys():
|
||||
self.aiEntities[entId].destroy()
|
||||
del self.aiEntities
|
||||
|
||||
# we do not allocate the uberZone for now, so don't deallocate it
|
||||
for zoneId in self.zoneIds[1:]:
|
||||
self.air.deallocateZone(zoneId)
|
||||
|
||||
self.destroyLevel()
|
||||
|
||||
DistributedObjectAI.DistributedObjectAI.delete(self)
|
74
direct/src/level/Entity.py
Executable file
74
direct/src/level/Entity.py
Executable file
@ -0,0 +1,74 @@
|
||||
"""Entity.py: contains the Entity class"""
|
||||
|
||||
import string
|
||||
|
||||
class Entity:
|
||||
"""Entity is the base class for all objects that exist in a Level
|
||||
and can be edited with the LevelEditor."""
|
||||
|
||||
# these are values that can be changed in the level editor
|
||||
# TODO: pick a good name for these values;
|
||||
# parameters, tweakables, attributes, attribs, traits,
|
||||
Tweakables = (
|
||||
# Name, PythonType, CallSetterOnInitialization
|
||||
('name', str, 0),
|
||||
('comment', str, 0),
|
||||
)
|
||||
|
||||
def __init__(self, level, entId, tweakables=None):
|
||||
self.level = level
|
||||
self.entId = entId
|
||||
|
||||
self.tweakables = Entity.Tweakables
|
||||
# add any additional tweakable values
|
||||
if tweakables is not None:
|
||||
self.tweakables.update(tweakables)
|
||||
|
||||
# TODO: funcs to populate the entity with its spec data, and system
|
||||
# to call back when data changes
|
||||
def initializeEntity(self):
|
||||
"""Call this once on initialization to set this entity's
|
||||
spec data"""
|
||||
self.level.initializeEntity(self)
|
||||
|
||||
def destroy(self):
|
||||
del self.level
|
||||
|
||||
def privGetSetter(self, attrib):
|
||||
setFuncName = 'set%s%s' % (string.upper(attrib[0]), attrib[1:])
|
||||
if hasattr(self, setFuncName):
|
||||
return getattr(self, setFuncName)
|
||||
return None
|
||||
|
||||
def callSetters(self, attribList):
|
||||
"""call this with a list of attribs, and any that exist on the
|
||||
entity and have setters will be passed to their setter"""
|
||||
for attrib in attribList:
|
||||
if hasattr(self, attrib):
|
||||
setter = self.privGetSetter(attrib)
|
||||
if setter is not None:
|
||||
setter(getattr(self, attrib))
|
||||
|
||||
def paramChanged(self):
|
||||
"""This is called when a parameter is tweaked and no setter
|
||||
is called; i.e. the value is set directly on the object.
|
||||
Some Entities might want to completely reset every time anything
|
||||
is tweaked; this is the place to do it; override this func in your
|
||||
derived class
|
||||
"""
|
||||
pass
|
||||
|
||||
def getTweakables(self):
|
||||
return self.tweakables
|
||||
|
||||
def privTweak(self, name, value):
|
||||
self.__dict__[name] = value
|
||||
|
||||
def __str__(self):
|
||||
return 'ent%s(%s)' % (self.entId, self.level.getEntityType(self.entId))
|
||||
|
||||
if __debug__:
|
||||
def debugPrint(self, message):
|
||||
"""for debugging"""
|
||||
return self.notify.debug(
|
||||
str(self.__dict__.get('entId', '?'))+' '+message)
|
35
direct/src/level/EntityCreator.py
Executable file
35
direct/src/level/EntityCreator.py
Executable file
@ -0,0 +1,35 @@
|
||||
"""EntityCreator.py: contains methods for creation of Entities"""
|
||||
|
||||
from PythonUtil import Functor
|
||||
import PlatformEntity
|
||||
import BasicEntities
|
||||
|
||||
def nothing(level, entId):
|
||||
"""For entities that don't need to be created by the client"""
|
||||
return None
|
||||
|
||||
# Client-side entity ctors:
|
||||
EntityType2Ctor = {
|
||||
# Map entity type name to constructor function that takes
|
||||
# (level, entId)
|
||||
'beanBarrel': nothing,
|
||||
'door': nothing,
|
||||
'gagBarrel': nothing,
|
||||
'lift': nothing,
|
||||
'nodepath': BasicEntities.NodePathEntity,
|
||||
#'platform': PlatformEntity.PlatformEntity,
|
||||
'stomper': nothing,
|
||||
'switch': nothing,
|
||||
|
||||
'andLogicObject': nothing,
|
||||
'orLogicObject': nothing,
|
||||
'xorLogicObject': nothing, #XorLoEntity.XorLoEntity,
|
||||
}
|
||||
|
||||
# TODO: what other args will be required?
|
||||
def createEntity(entType, level, entId):
|
||||
if not EntityType2Ctor.has_key(entType):
|
||||
print "createEntity(entType=%s, entId=%s) not found"%(
|
||||
entType, entId)
|
||||
return None
|
||||
return EntityType2Ctor[entType](level, entId)
|
49
direct/src/level/EntityCreatorAI.py
Executable file
49
direct/src/level/EntityCreatorAI.py
Executable file
@ -0,0 +1,49 @@
|
||||
"""EntityCreatorAI.py: contains methods for creation of Entities"""
|
||||
|
||||
from PythonUtil import Functor
|
||||
import DistributedBeanBarrelAI
|
||||
import DistributedLiftAI
|
||||
import DistributedDoorEntityAI
|
||||
import DistributedGagBarrelAI
|
||||
#import DistributedStomperPairAI
|
||||
import DistributedSwitchAI
|
||||
import DistributedStomperAI
|
||||
import AndLoEntityAI
|
||||
import OrLoEntityAI
|
||||
#import XorLoEntity
|
||||
|
||||
|
||||
def cDE(AIclass, air, levelDoId, entId, zoneId):
|
||||
"""create a distributed entity"""
|
||||
ent = AIclass(air, levelDoId, entId)
|
||||
ent.generateWithRequired(zoneId)
|
||||
return ent
|
||||
|
||||
def nothing(air, levelDoId, entId, zoneId):
|
||||
"""Create entity that doesn't have a server side representation."""
|
||||
return None
|
||||
|
||||
# Server (AI) side factory functions:
|
||||
EntityType2Ctor = {
|
||||
# Map entity type name to constructor function that takes
|
||||
# (air, level doId, entId, zoneId)
|
||||
'beanBarrel': Functor(cDE, DistributedBeanBarrelAI.DistributedBeanBarrelAI),
|
||||
'door': DistributedDoorEntityAI.DistributedDoorEntityAI,
|
||||
'gagBarrel': Functor(cDE, DistributedGagBarrelAI.DistributedGagBarrelAI),
|
||||
'lift': Functor(cDE, DistributedLiftAI.DistributedLiftAI),
|
||||
'nodepath': nothing,
|
||||
'platform': nothing,
|
||||
'stomper': Functor(cDE, DistributedStomperAI.DistributedStomperAI),
|
||||
'switch': DistributedSwitchAI.DistributedSwitchAI,
|
||||
|
||||
'andLogicObject': AndLoEntityAI.AndLoEntityAI,
|
||||
'orLogicObject': OrLoEntityAI.OrLoEntityAI,
|
||||
'xorLogicObject': nothing, #XorLoEntity.XorLoEntity,
|
||||
}
|
||||
|
||||
def createEntity(entType, air, levelDoId, entId, zoneId):
|
||||
if not EntityType2Ctor.has_key(entType):
|
||||
print "createEntity(entType=%s, air=%s, levelDoId=%s, entId=%s, zoneId=%s) not found"%(
|
||||
entType, "the air", levelDoId, entId, zoneId)
|
||||
return None
|
||||
return EntityType2Ctor[entType](air, levelDoId, entId, zoneId)
|
91
direct/src/level/LevelBase.py
Executable file
91
direct/src/level/LevelBase.py
Executable file
@ -0,0 +1,91 @@
|
||||
"""LevelBase.py: contains the LevelBase class"""
|
||||
|
||||
import DirectNotifyGlobal
|
||||
import string
|
||||
|
||||
class LevelBase:
|
||||
"""LevelBase: shared client and AI code
|
||||
representation of a game level, keeps track of all of the
|
||||
Level Entities and their interrelations"""
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory('LevelBase')
|
||||
|
||||
def __init__(self, levelId=None):
|
||||
if levelId is not None:
|
||||
self.setLevelId(levelId)
|
||||
|
||||
def setLevelId(self, levelId):
|
||||
self.levelId = levelId
|
||||
|
||||
def initializeLevel(self, spec, scenarioIndex):
|
||||
""" subclass should call this as soon as it has located
|
||||
its spec data """
|
||||
self.spec = spec
|
||||
self.scenarioIndex = scenarioIndex
|
||||
|
||||
# create a complete set of global and scenario-specific entity specs
|
||||
globalEntities = self.spec['globalEntities']
|
||||
scenarioEntities = self.spec['scenarios'][self.scenarioIndex][0]
|
||||
entId2Spec = {}
|
||||
entId2Spec.update(globalEntities)
|
||||
entId2Spec.update(scenarioEntities)
|
||||
self.entId2Spec = entId2Spec
|
||||
|
||||
# this will be filled in as the entities are created and report in
|
||||
self.entities = {}
|
||||
|
||||
def destroyLevel(self):
|
||||
del self.entities
|
||||
del self.entId2Spec
|
||||
del self.spec
|
||||
|
||||
def initializeEntity(self, entity):
|
||||
"""populate an entity with its spec data"""
|
||||
entId = entity.entId
|
||||
spec = self.entId2Spec[entId]
|
||||
# on initialization, set items directly on entity
|
||||
for key,value in spec.items():
|
||||
if key in ('type', 'name', 'comment',):
|
||||
continue
|
||||
if hasattr(entity, key):
|
||||
self.notify.warning('entity %s (%s) already has member %s' %
|
||||
(entId, spec['type'], key))
|
||||
entity.__dict__[key] = value
|
||||
|
||||
# entity is initialized, add it to the list of entities
|
||||
self.entities[entity.entId] = entity
|
||||
# send the create event
|
||||
messenger.send(self.getEntityCreateEvent(entity.entId))
|
||||
|
||||
"""
|
||||
# set items directly on entity, or call callback functions...
|
||||
for key,value in spec.items():
|
||||
# filter out some entries; we might want to restructure the
|
||||
# spec data into different categories of properties instead
|
||||
# of filtering them here
|
||||
if key in ('type', 'name', 'comment', 'zone',):
|
||||
continue
|
||||
setFuncName = 'set%s%s' % (string.upper(key[0]), key[1:])
|
||||
if hasattr(entity, setFuncName):
|
||||
# call the setter
|
||||
func = getattr(entity, setFuncName)
|
||||
func(value)
|
||||
else:
|
||||
# set the param directly on the object
|
||||
entity.__dict__[key] = value
|
||||
"""
|
||||
|
||||
def getEntityCreateEvent(self, entId):
|
||||
"""This is the event that is thrown immediately after an entity
|
||||
is initialized"""
|
||||
return 'entityCreate-%s-%s' % (self.levelId, entId)
|
||||
|
||||
def getEntity(self, entId):
|
||||
return self.entities[entId]
|
||||
|
||||
def getEntityType(self, entId):
|
||||
return self.entId2Spec[entId]['type']
|
||||
|
||||
def getZoneId(self, index):
|
||||
# get the actual zoneId for this index
|
||||
# TODO: perhaps the zones should be fixed up in the specs
|
||||
return self.zoneIds[index]
|
56
direct/src/level/NandLoEntityAI.py
Executable file
56
direct/src/level/NandLoEntityAI.py
Executable file
@ -0,0 +1,56 @@
|
||||
"""NandLoEntityAI.py: contains the NandLoEntity class"""
|
||||
|
||||
|
||||
import PandaObject
|
||||
import DirectNotifyGlobal
|
||||
import Entity
|
||||
|
||||
|
||||
class NandLoEntityAI(Entity.Entity, PandaObject.PandaObject):
|
||||
if __debug__:
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory(
|
||||
'NandLoEntityAI')
|
||||
|
||||
def __init__(self, air, levelDoId, entId, zoneId=None):
|
||||
"""entId: """
|
||||
assert(self.debugPrint(
|
||||
"NandLoEntityAI(air=%s, levelDoId=%s, entId=%s, zoneId=%s)"
|
||||
%("the air", levelDoId, entId, zoneId)))
|
||||
self.input1 = None
|
||||
self.input2 = None
|
||||
self.levelDoId = levelDoId
|
||||
level = air.doId2do[self.levelDoId]
|
||||
Entity.Entity.__init__(self, level, entId)
|
||||
self.initializeEntity()
|
||||
self.setInput_input1_bool(self.input_input1_bool)
|
||||
self.setInput_input2_bool(self.input_input2_bool)
|
||||
|
||||
def setIsInput1(self, isTrue):
|
||||
assert(self.debugPrint("setIsInput1(isTrue=%s)"%(isTrue,)))
|
||||
self.isInput1=isTrue
|
||||
messenger.send(self.getName(), [not (isTrue or self.isInput2)])
|
||||
|
||||
def setIsInput2(self, isTrue):
|
||||
assert(self.debugPrint("setIsInput1(isTrue=%s)"%(isTrue,)))
|
||||
self.isInput2=isTrue
|
||||
messenger.send(self.getName(), [not (isTrue or self.isInput1)])
|
||||
|
||||
def setInput_input1_bool(self, event):
|
||||
assert(self.debugPrint("setInput_input1_bool(event=%s)"%(event,)))
|
||||
if self.input1:
|
||||
self.ignore(self.input1)
|
||||
self.input1 = "switch-%s"%(event,)
|
||||
if self.input1:
|
||||
self.accept(self.input1, self.setIsInput1)
|
||||
|
||||
def setInput_input2_bool(self, event):
|
||||
assert(self.debugPrint("setInput_input2_bool(event=%s)"%(event,)))
|
||||
if self.input2:
|
||||
self.ignore(self.input2)
|
||||
self.input2 = "switch-%s"%(event,)
|
||||
if self.input2:
|
||||
self.accept(self.input2, self.setIsInput2)
|
||||
|
||||
def getName(self):
|
||||
#return "NandLoEntity-%s"%(self.entId,)
|
||||
return "switch-%s"%(self.entId,)
|
19
direct/src/level/OrLoEntity.py
Executable file
19
direct/src/level/OrLoEntity.py
Executable file
@ -0,0 +1,19 @@
|
||||
"""OrLoEntity.py: contains the OrLoEntity class"""
|
||||
|
||||
class OrLoEntity(Entity.Entity):
|
||||
if __debug__:
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory(
|
||||
'OrLoEntity')
|
||||
|
||||
def __init__(self, air, levelDoId, entId, zoneId=None):
|
||||
"""entId: """
|
||||
assert(self.debugPrint(
|
||||
"DistributedDoorEntityAI(air=%s, levelDoId=%s, entId=%s, zoneId=%s)"
|
||||
%("the air", levelDoId, entId, zoneId)))
|
||||
self.doLaterTask=None
|
||||
self.isOpenInput = None
|
||||
DistributedInteractiveEntityAI.DistributedInteractiveEntityAI.__init__(
|
||||
self, air, levelDoId, entId)
|
||||
self.fsm.setName('DistributedDoorEntity')
|
||||
if zoneId is not None:
|
||||
self.generateWithRequired(zoneId)
|
60
direct/src/level/OrLoEntityAI.py
Executable file
60
direct/src/level/OrLoEntityAI.py
Executable file
@ -0,0 +1,60 @@
|
||||
"""OrLoEntityAI.py: contains the OrLoEntity class"""
|
||||
|
||||
|
||||
import PandaObject
|
||||
import DirectNotifyGlobal
|
||||
import Entity
|
||||
|
||||
|
||||
class OrLoEntityAI(Entity.Entity, PandaObject.PandaObject):
|
||||
if __debug__:
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory(
|
||||
'OrLoEntityAI')
|
||||
|
||||
def __init__(self, air, levelDoId, entId, zoneId=None):
|
||||
"""entId: """
|
||||
assert(self.debugPrint(
|
||||
"OrLoEntityAI(air=%s, levelDoId=%s, entId=%s, zoneId=%s)"
|
||||
%("the air", levelDoId, entId, zoneId)))
|
||||
self.input1 = None
|
||||
self.input2 = None
|
||||
self.levelDoId = levelDoId
|
||||
level = air.doId2do[self.levelDoId]
|
||||
Entity.Entity.__init__(self, level, entId)
|
||||
self.initializeEntity()
|
||||
self.setInput_input1_bool(self.input_input1_bool)
|
||||
self.setInput_input2_bool(self.input_input2_bool)
|
||||
|
||||
def setIsInput1(self, isTrue):
|
||||
assert(self.debugPrint("setIsInput1(isTrue=%s)"%(isTrue,)))
|
||||
self.isInput1=isTrue
|
||||
if not self.isInput2:
|
||||
# ...we already sent the messege when input2 was set.
|
||||
messenger.send(self.getName(), [isTrue])
|
||||
|
||||
def setIsInput2(self, isTrue):
|
||||
assert(self.debugPrint("setIsInput1(isTrue=%s)"%(isTrue,)))
|
||||
self.isInput2=isTrue
|
||||
if not self.isInput1:
|
||||
# ...we already sent the messege when input1 was set.
|
||||
messenger.send(self.getName(), [isTrue])
|
||||
|
||||
def setInput_input1_bool(self, event):
|
||||
assert(self.debugPrint("setInput_input1_bool(event=%s)"%(event,)))
|
||||
if self.input1:
|
||||
self.ignore(self.input1)
|
||||
self.input1 = "switch-%s"%(event,)
|
||||
if self.input1:
|
||||
self.accept(self.input1, self.setIsInput1)
|
||||
|
||||
def setInput_input2_bool(self, event):
|
||||
assert(self.debugPrint("setInput_input2_bool(event=%s)"%(event,)))
|
||||
if self.input2:
|
||||
self.ignore(self.input2)
|
||||
self.input2 = "switch-%s"%(event,)
|
||||
if self.input2:
|
||||
self.accept(self.input2, self.setIsInput2)
|
||||
|
||||
def getName(self):
|
||||
#return "orLoEntity-%s"%(self.entId,)
|
||||
return "switch-%s"%(self.entId,)
|
3
direct/src/level/Sources.pp
Normal file
3
direct/src/level/Sources.pp
Normal file
@ -0,0 +1,3 @@
|
||||
// For now, since we are not installing Python files, this file can
|
||||
// remain empty.
|
||||
|
0
direct/src/level/XorLoEntity.py
Executable file
0
direct/src/level/XorLoEntity.py
Executable file
56
direct/src/level/XorLoEntityAI.py
Executable file
56
direct/src/level/XorLoEntityAI.py
Executable file
@ -0,0 +1,56 @@
|
||||
"""XorLoEntityAI.py: contains the XorLoEntity class"""
|
||||
|
||||
|
||||
import PandaObject
|
||||
import DirectNotifyGlobal
|
||||
import Entity
|
||||
|
||||
|
||||
class XorLoEntityAI(Entity.Entity, PandaObject.PandaObject):
|
||||
if __debug__:
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory(
|
||||
'XorLoEntityAI')
|
||||
|
||||
def __init__(self, air, levelDoId, entId, zoneId=None):
|
||||
"""entId: """
|
||||
assert(self.debugPrint(
|
||||
"XorLoEntityAI(air=%s, levelDoId=%s, entId=%s, zoneId=%s)"
|
||||
%("the air", levelDoId, entId, zoneId)))
|
||||
self.input1 = None
|
||||
self.input2 = None
|
||||
self.levelDoId = levelDoId
|
||||
level = air.doId2do[self.levelDoId]
|
||||
Entity.Entity.__init__(self, level, entId)
|
||||
self.initializeEntity()
|
||||
self.setInput_input1_bool(self.input_input1_bool)
|
||||
self.setInput_input2_bool(self.input_input2_bool)
|
||||
|
||||
def setIsInput1(self, isTrue):
|
||||
assert(self.debugPrint("setIsInput1(isTrue=%s)"%(isTrue,)))
|
||||
self.isInput1=isTrue
|
||||
messenger.send(self.getName(), [(not (isTrue and self.isInput2)) and (isTrue or self.isInput2)])
|
||||
|
||||
def setIsInput2(self, isTrue):
|
||||
assert(self.debugPrint("setIsInput1(isTrue=%s)"%(isTrue,)))
|
||||
self.isInput2=isTrue
|
||||
messenger.send(self.getName(), [(not (isTrue and self.isInput2)) and (isTrue or self.isInput2)])
|
||||
|
||||
def setInput_input1_bool(self, event):
|
||||
assert(self.debugPrint("setInput_input1_bool(event=%s)"%(event,)))
|
||||
if self.input1:
|
||||
self.ignore(self.input1)
|
||||
self.input1 = "switch-%s"%(event,)
|
||||
if self.input1:
|
||||
self.accept(self.input1, self.setIsInput1)
|
||||
|
||||
def setInput_input2_bool(self, event):
|
||||
assert(self.debugPrint("setInput_input2_bool(event=%s)"%(event,)))
|
||||
if self.input2:
|
||||
self.ignore(self.input2)
|
||||
self.input2 = "switch-%s"%(event,)
|
||||
if self.input2:
|
||||
self.accept(self.input2, self.setIsInput2)
|
||||
|
||||
def getName(self):
|
||||
#return "xorLoEntity-%s"%(self.entId,)
|
||||
return "switch-%s"%(self.entId,)
|
Loading…
x
Reference in New Issue
Block a user